Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
drupal
Commits
e9f18147
Commit
e9f18147
authored
Dec 20, 2009
by
Dries Buytaert
Browse files
- Patch
#612894
by yched: display field improvements.
parent
8874a4e2
Changes
5
Hide whitespace changes
Inline
Side-by-side
modules/field/field.attach.inc
View file @
e9f18147
...
...
@@ -338,7 +338,7 @@ function _field_invoke_multiple($op, $obj_type, $objects, &$a = NULL, &$b = NULL
if
(
function_exists
(
$function
))
{
// Iterate over all the field translations.
foreach
(
$grouped_items
[
$field_id
]
as
$langcode
=>
$items
)
{
$results
=
$function
(
$obj_type
,
$grouped_objects
[
$field_id
],
$field
,
$grouped_instances
[
$field_id
],
$langcode
,
$grouped_items
[
$field_id
][
$langcode
],
$options
,
$a
,
$b
);
$results
=
$function
(
$obj_type
,
$grouped_objects
[
$field_id
],
$field
,
$grouped_instances
[
$field_id
],
$langcode
,
$grouped_items
[
$field_id
][
$langcode
],
$a
,
$b
);
if
(
isset
(
$results
))
{
// Collect results by object.
// For hooks with array results, we merge results together.
...
...
@@ -1177,7 +1177,7 @@ function field_attach_view($obj_type, $object, $build_mode = 'full', $langcode =
$output
[
'#pre_render'
][]
=
'_field_extra_weights_pre_render'
;
$output
[
'#extra_fields'
]
=
field_extra_fields
(
$bundle
);
// Let other modules
make changes after rendering the view
.
// Let other modules
alter the renderable array
.
$context
=
array
(
'obj_type'
=>
$obj_type
,
'object'
=>
$object
,
...
...
modules/field/field.default.inc
View file @
e9f18147
...
...
@@ -97,13 +97,32 @@ function field_default_insert($obj_type, $object, $field, $instance, $langcode,
}
/**
* Invoke hook_field_formatter_prepare_view() on the relavant formatters.
*/
function
field_default_prepare_view
(
$obj_type
,
$objects
,
$field
,
$instances
,
$langcode
,
&
$items
,
$options
,
$build_mode
)
{
* Invokes hook_field_formatter_prepare_view() on the relevant formatters.
*
* @param $obj_type
* The type of $object; e.g. 'node' or 'user'.
* @param $objects
* An array of objects being displayed, keyed by object id.
* @param $field
* The field structure for the operation.
* @param $instances
* Array of instance structures for $field for each object, keyed by object
* id.
* @param $langcode
* The language associated to $items.
* @param $items
* Array of field values already loaded for the objects, keyed by object id.
* @param $display
* Can be either:
* - the name of a build mode
* - or an array of display settings to use for display, as found in the
* 'display' entry of $instance definitions.
*/
function
field_default_prepare_view
(
$obj_type
,
$objects
,
$field
,
$instances
,
$langcode
,
&
$items
,
$display
)
{
// Group objects, instances and items by formatter module.
$modules
=
array
();
foreach
(
$instances
as
$id
=>
$instance
)
{
$display
=
$instance
[
'display'
][
$
build_mode
]
;
$display
=
is_string
(
$display
)
?
$instance
[
'display'
][
$
display
]
:
$display
;
if
(
$display
[
'type'
]
!==
'hidden'
)
{
$module
=
$display
[
'module'
];
$modules
[
$module
]
=
$module
;
...
...
@@ -125,16 +144,41 @@ function field_default_prepare_view($obj_type, $objects, $field, $instances, $la
}
/**
*
Default field 'view' operation
.
*
Builds a renderable array for field values
.
*
* @see field_attach_view()
* @param $obj_type
* The type of $object; e.g. 'node' or 'user'.
* @param $objects
* An array of objects being displayed, keyed by object id.
* @param $field
* The field structure for the operation.
* @param $instances
* Array of instance structures for $field for each object, keyed by object
* id.
* @param $langcode
* The language associated to $items.
* @param $items
* Array of field values already loaded for the objects, keyed by object id.
* @param $display
* Can be either:
* - the name of a build mode;
* - or an array of custom display settings, as found in the 'display' entry
* of $instance definitions.
*/
function
field_default_view
(
$obj_type
,
$object
,
$field
,
$instance
,
$langcode
,
$items
,
$
build_mode
)
{
function
field_default_view
(
$obj_type
,
$object
,
$field
,
$instance
,
$langcode
,
$items
,
$
display
)
{
list
(
$id
,
$vid
,
$bundle
)
=
entity_extract_ids
(
$obj_type
,
$object
);
$addition
=
array
();
$display
=
$instance
[
'display'
][
$build_mode
];
// Prepare incoming display specifications.
if
(
is_string
(
$display
))
{
$build_mode
=
$display
;
$display
=
$instance
[
'display'
][
$build_mode
];
}
else
{
$build_mode
=
'_custom_display'
;
}
if
(
$display
[
'type'
]
!==
'hidden'
)
{
// We never want to index fields labels.
if
(
$build_mode
==
'search_index'
)
{
...
...
modules/field/field.info.inc
View file @
e9f18147
...
...
@@ -278,22 +278,10 @@ function _field_info_prepare_instance($instance, $field) {
$instance
[
'default_value'
]
=
NULL
;
}
// Fallback to default widget if widget type is not available.
if
(
!
field_info_widget_types
(
$instance
[
'widget'
][
'type'
]))
{
$instance
[
'widget'
][
'type'
]
=
$field_type
[
'default_widget'
];
}
// Make sure all expected widget settings are present.
$instance
[
'widget'
][
'settings'
]
+=
field_info_widget_settings
(
$instance
[
'widget'
][
'type'
]);
$instance
[
'widget'
]
=
_field_info_prepare_instance_widget
(
$field
,
$instance
[
'widget'
]);
foreach
(
$instance
[
'display'
]
as
$build_mode
=>
$display
)
{
if
(
$display
[
'type'
]
!=
'hidden'
)
{
// Fallback to default formatter if formatter type is not available.
if
(
!
field_info_formatter_types
(
$instance
[
'display'
][
$build_mode
][
'type'
]))
{
$instance
[
'display'
][
$build_mode
][
'type'
]
=
$field_type
[
'default_formatter'
];
}
// Make sure all expected formatter settings are present.
$instance
[
'display'
][
$build_mode
][
'settings'
]
+=
field_info_formatter_settings
(
$instance
[
'display'
][
$build_mode
][
'type'
]);
}
$instance
[
'display'
][
$build_mode
]
=
_field_info_prepare_instance_display
(
$field
,
$display
);
}
// Fallback to 'full' display settings for unspecified build modes.
...
...
@@ -307,6 +295,70 @@ function _field_info_prepare_instance($instance, $field) {
}
/**
* Adapts display specifications to the current run-time context.
*
* @param $field
* The field structure for the instance.
* @param $display
* Display specifications as found in
* $instance['display']['some_build_mode'].
*/
function
_field_info_prepare_instance_display
(
$field
,
$display
)
{
$field_type
=
field_info_field_types
(
$field
[
'type'
]);
// Fill in default values.
$display
+=
array
(
'label'
=>
'above'
,
'type'
=>
$field_type
[
'default_formatter'
],
'settings'
=>
array
(),
'weight'
=>
0
,
);
if
(
$display
[
'type'
]
!=
'hidden'
)
{
$formatter_type
=
field_info_formatter_types
(
$display
[
'type'
]);
// Fallback to default formatter if formatter type is not available.
if
(
!
$formatter_type
)
{
$display
[
'type'
]
=
$field_type
[
'default_formatter'
];
$formatter_type
=
field_info_formatter_types
(
$display
[
'type'
]);
}
$display
[
'module'
]
=
$formatter_type
[
'module'
];
// Fill in default settings for the formatter.
$display
[
'settings'
]
+=
field_info_formatter_settings
(
$display
[
'type'
]);
}
return
$display
;
}
/**
* Prepares widget specifications for the current run-time context.
*
* @param $field
* The field structure for the instance.
* @param $widget
* Widget specifications as found in $instance['widget'].
*/
function
_field_info_prepare_instance_widget
(
$field
,
$widget
)
{
$field_type
=
field_info_field_types
(
$field
[
'type'
]);
// Fill in default values.
$widget
+=
array
(
'type'
=>
$field_type
[
'default_widget'
],
'settings'
=>
array
(),
'weight'
=>
0
,
);
$widget_type
=
field_info_widget_types
(
$widget
[
'type'
]);
// Fallback to default formatter if formatter type is not available.
if
(
!
$widget_type
)
{
$widget
[
'type'
]
=
$field_type
[
'default_widget'
];
$widget_type
=
field_info_widget_types
(
$widget
[
'type'
]);
}
$widget
[
'module'
]
=
$widget_type
[
'module'
];
// Fill in default settings for the widget.
$widget
[
'settings'
]
+=
field_info_widget_settings
(
$widget
[
'type'
]);
return
$widget
;
}
*
Determines
the
behavior
of
a
widget
with
respect
to
an
operation
.
*
*
@
param
$op
...
...
modules/field/field.module
View file @
e9f18147
...
...
@@ -565,45 +565,103 @@ function field_format($obj_type, $object, $field, $item, $formatter_type = NULL,
}
/**
* Return a
single field, fully themed with label and multiple values
.
* Return
s
a
renderable array for the value of a single field in an object
.
*
* To be used by third-party code (Views, Panels...) that needs to output
* an isolated field. Do *not* use inside node templates, use
* render($content[FIELD_NAME]) instead.
* The resulting output is a fully themed field with label and multiple values.
*
* The field will be displayed using the display options (label display,
* formatter settings...) specified in the $instance structure for the given
* build mode: $instance['display'][$build_mode].
* This function can be used by third-party modules that need to output an
* isolated field.
* - Do not use inside node (or other entities) templates, use
* render($content[FIELD_NAME]) instead.
* - Do not use to display all fields in an object, use
* field_attach_prepare_view() and field_attach_view() instead.
*
* The function takes care of invoking the prepare_view steps. It also respects
* field access permissions.
*
* @param $obj_type
* The type of $object; e.g. 'node' or 'user'.
* @param $object
* The object containing the field to display. Must at least contain the id key,
* revision key (if applicable), bundle key, and the field data.
* @param $field
* The field structure.
* @param $instance
* The instance structure for $field on $object's bundle.
* @param $build_mode
* Build mode, e.g. 'full', 'teaser'...
* The object containing the field to display. Must at least contain the id
* key and the field data to display.
* @param $field_name
* The name of the field to display.
* @param $display
* Can be either:
* - The name of a build mode. The field will be displayed according to the
* display settings specified for this build mode in the $instance
* definition for the field in the object's bundle.
* If no display settings are found for the build mode, the settings for
* the 'full' build mode will be used.
* - An array of display settings, as found in the 'display' entry of
* $instance definitions. The following kay/value pairs are allowed:
* - label: (string) Position of the label. The default 'field' theme
* implementation supports the values 'inline', 'above' and 'hidden'.
* Defaults to 'above'.
* - type: (string) The formatter to use. Defaults to the
* 'default_formatter' for the field type, specified in
* hook_field_info(). The default formatter will also be used if the
* requested formatter is not available.
* - settings: (array) Settings specific to the formatter. Defaults to the
* formatter's default settings, specified in
* hook_field_formatter_info().
* - weight: (float) The weight to assign to the renderable element.
* Defaults to 0.
* @param $langcode
* (Optional) The language the field values are to be shown in. The site's
* current language fallback logic will be applied no values are available
* for the language. If no language is provided the current language will be
* used.
* @return
*
The themed output
for the field.
*
A renderable array
for the field
value
.
*/
function
field_view_field
(
$obj_type
,
$object
,
$field
,
$instance
,
$build_mode
=
'full'
)
{
$output
=
''
;
if
(
isset
(
$object
->
$field
[
'field_name'
]))
{
$items
=
$object
->
$field
[
'field_name'
];
function
field_view_field
(
$obj_type
,
$object
,
$field_name
,
$display
=
array
(),
$langcode
=
NULL
)
{
$output
=
array
();
// One-field equivalent to _field_invoke('sanitize').
$function
=
$field
[
'module'
]
.
'_field_sanitize'
;
if
(
function_exists
(
$function
))
{
$function
(
$obj_type
,
$object
,
$field
,
$instance
,
$items
);
$object
->
$field
[
'field_name'
]
=
$items
;
if
(
$field
=
field_info_field
(
$field_name
))
{
if
(
is_array
(
$display
))
{
// When using custom display settings, fill in default values.
$display
=
_field_info_prepare_instance_display
(
$field
,
$display
);
}
else
{
// When using a build mode, make sure we have settings for it, or fall
// back to the 'full' build mode.
list
(,
,
$bundle
)
=
entity_extract_ids
(
$obj_type
,
$object
);
$instance
=
field_info_instance
(
$obj_type
,
$field_name
,
$bundle
);
if
(
!
isset
(
$instance
[
'display'
][
$display
]))
{
$display
=
'full'
;
}
}
$view
=
field_default_view
(
$obj_type
,
$object
,
$field
,
$instance
,
$items
,
$build_mode
);
// TODO : what about hook_field_attach_view ?
// Hook invocations are done through the _field_invoke() functions in
// 'single field' mode, to reuse the language fallback logic.
$options
=
array
(
'field_name'
=>
$field_name
,
'language'
=>
field_multilingual_valid_language
(
$langcode
,
FALSE
));
$null
=
NULL
;
list
(
$id
)
=
entity_extract_ids
(
$obj_type
,
$object
);
// First let the field types do their preparation.
_field_invoke_multiple
(
'prepare_view'
,
$obj_type
,
array
(
$id
=>
$object
),
$display
,
$null
,
$options
);
// Then let the formatters do their own specific massaging.
_field_invoke_multiple_default
(
'prepare_view'
,
$obj_type
,
array
(
$id
=>
$object
),
$display
,
$null
,
$options
);
// Build the renderable array.
$result
=
_field_invoke_default
(
'view'
,
$obj_type
,
$object
,
$display
,
$null
,
$options
);
// Invoke hook_field_attach_view_alter() to tet other modules alter the
// renderable array, as in a full field_attach_view() execution.
$context
=
array
(
'obj_type'
=>
$obj_type
,
'object'
=>
$object
,
'build_mode'
=>
'_custom'
,
'langcode'
=>
$langcode
,
);
drupal_alter
(
'field_attach_view'
,
$result
,
$context
);
$output
=
$view
[
$field
[
'field_name'
]];
if
(
isset
(
$result
[
$field_name
]))
{
$output
=
$result
[
$field_name
];
$output
[
'#attached'
][
'css'
][]
=
drupal_get_path
(
'module'
,
'field'
)
.
'/theme/field.css'
;
}
}
return
$output
;
}
...
...
modules/field/tests/field.test
View file @
e9f18147
...
...
@@ -1728,6 +1728,107 @@ class FieldFormTestCase extends FieldTestCase {
}
}
class
FieldDisplayAPITestCase
extends
FieldTestCase
{
public
static
function
getInfo
()
{
return
array
(
'name'
=>
'Field Display API tests'
,
'description'
=>
'Test the display API.'
,
'group'
=>
'Field API'
,
);
}
function
setUp
()
{
parent
::
setUp
(
'field_test'
);
// Create a field and instance.
$this
->
field_name
=
'test_field'
;
$this
->
label
=
$this
->
randomName
();
$this
->
cardinality
=
4
;
$this
->
field
=
array
(
'field_name'
=>
$this
->
field_name
,
'type'
=>
'test_field'
,
'cardinality'
=>
$this
->
cardinality
,
);
$this
->
instance
=
array
(
'field_name'
=>
$this
->
field_name
,
'object_type'
=>
'test_entity'
,
'bundle'
=>
'test_bundle'
,
'label'
=>
$this
->
label
,
'display'
=>
array
(
'full'
=>
array
(
'type'
=>
'field_test_default'
,
'settings'
=>
array
(
'test_formatter_setting'
=>
$this
->
randomName
(),
),
),
),
);
field_create_field
(
$this
->
field
);
field_create_instance
(
$this
->
instance
);
// Create an entity with values.
$this
->
values
=
$this
->
_generateTestFieldValues
(
$this
->
cardinality
);
$this
->
entity
=
field_test_create_stub_entity
();
$this
->
is_new
=
TRUE
;
$this
->
entity
->
{
$this
->
field_name
}[
LANGUAGE_NONE
]
=
$this
->
values
;
field_test_entity_save
(
$this
->
entity
);
}
/**
* Test the field_view_field() function.
*/
function
testFieldBuildField
()
{
// No display settings: check that default display settings are used.
$output
=
field_view_field
(
'test_entity'
,
$this
->
entity
,
$this
->
field_name
);
$this
->
drupalSetContent
(
drupal_render
(
$output
));
$settings
=
field_info_formatter_settings
(
'field_test_default'
);
$setting
=
$settings
[
'test_formatter_setting'
];
$this
->
assertText
(
$this
->
label
,
t
(
'Label was displayed.'
));
foreach
(
$this
->
values
as
$delta
=>
$value
)
{
$this
->
assertText
(
$setting
.
'|'
.
$value
[
'value'
],
t
(
'Value @delta was displayed with expected setting.'
,
array
(
'@delta'
=>
$delta
)));
}
// Check that explicit display settings are used.
$display
=
array
(
'label'
=>
'hidden'
,
'type'
=>
'field_test_multiple'
,
'settings'
=>
array
(
'test_formatter_setting_multiple'
=>
$this
->
randomName
(),
),
);
$output
=
field_view_field
(
'test_entity'
,
$this
->
entity
,
$this
->
field_name
,
$display
);
$this
->
drupalSetContent
(
drupal_render
(
$output
));
$setting
=
$display
[
'settings'
][
'test_formatter_setting_multiple'
];
$this
->
assertNoText
(
$this
->
label
,
t
(
'Label was not displayed.'
));
$array
=
array
();
foreach
(
$this
->
values
as
$delta
=>
$value
)
{
$array
[]
=
$delta
.
':'
.
$value
[
'value'
];
}
$this
->
assertText
(
$setting
.
'|'
.
implode
(
'|'
,
$array
),
t
(
'Values were displayed with expected setting.'
));
// Build mode: check that display settings specified in the instance are
// used.
$output
=
field_view_field
(
'test_entity'
,
$this
->
entity
,
$this
->
field_name
,
'full'
);
$this
->
drupalSetContent
(
drupal_render
(
$output
));
$setting
=
$this
->
instance
[
'display'
][
'full'
][
'settings'
][
'test_formatter_setting'
];
$this
->
assertText
(
$this
->
label
,
t
(
'Label was displayed.'
));
foreach
(
$this
->
values
as
$delta
=>
$value
)
{
$this
->
assertText
(
$setting
.
'|'
.
$value
[
'value'
],
t
(
'Value @delta was displayed with expected setting.'
,
array
(
'@delta'
=>
$delta
)));
}
// Unknown build mode: check that display settings for 'full' build mode
// are used.
$output
=
field_view_field
(
'test_entity'
,
$this
->
entity
,
$this
->
field_name
,
'unknown_build_mode'
);
$this
->
drupalSetContent
(
drupal_render
(
$output
));
$setting
=
$this
->
instance
[
'display'
][
'full'
][
'settings'
][
'test_formatter_setting'
];
$this
->
assertText
(
$this
->
label
,
t
(
'Label was displayed.'
));
foreach
(
$this
->
values
as
$delta
=>
$value
)
{
$this
->
assertText
(
$setting
.
'|'
.
$value
[
'value'
],
t
(
'Value @delta was displayed with expected setting.'
,
array
(
'@delta'
=>
$delta
)));
}
}
}
class
FieldCrudTestCase
extends
FieldTestCase
{
public
static
function
getInfo
()
{
return
array
(
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment