function _webform_render_view in Webform view 7.4
Same name and namespace in other branches
- 7 webform_view.inc \_webform_render_view()
Show the embedded view on the webform.
The returned renderable array representing the element to be themed may include form elements & nesting.
Implements _webform_render_component().
File
- ./
webform_view.inc, line 126 - Additional component for webform that allows views to be used as embeddable elements.
Code
function _webform_render_view($component, $value_serialized = NULL, $filter = TRUE) {
if (!empty($value_serialized) && is_array($value_serialized)) {
$value = unserialize(reset($value_serialized));
}
$node = isset($component['nid']) ? node_load($component['nid']) : NULL;
$view_key = $component['extra']['view'];
$args = explode('/', $component['extra']['contextual_filters']);
$args = array_filter($args);
$placeholder_fields = array();
// Nicely stolen from views_block_view()
// If the delta doesn't contain valid data return nothing.
$explode = explode('-', $view_key);
if (count($explode) != 2) {
return NULL;
}
list($name, $display_id) = $explode;
// Load the view.
if (!($view = views_get_view($name))) {
watchdog('webform_view', 'Invalid view - cannot embed %name %display_id', array(
'%name' => $name,
'%display_id' => $display_id,
));
return NULL;
}
if (!$view
->access($display_id)) {
watchdog('webform_view', 'View access denied - cannot embed %name %display_id', array(
'%name' => $name,
'%display_id' => $display_id,
));
}
// execute_display produces cooked text.
// It can include a placeholder string for our form elements,
// if a field chooses to use the 'webform_placeholder' as a renderer.
$output = $view
->preview($display_id, $args);
if (empty($output)) {
return NULL;
}
// Go through the rows to prepare the webform-like fields.
// Do this by CLONING the children elements already nested in this one.
foreach ($view->result as $index => $row) {
// Key on the real row ID if possible.
$key = isset($row->{$view->base_field}) ? $row->{$view->base_field} : $index;
// If reviewing or editing fields, the $value array may be available.
// It's our job to put it back into the element.
$component_value = isset($value[$key]) ? $value[$key] : array();
// This is now an array representing the data last stored in this row.
// One of these fields should probably be a textfield that can hold the
// item identifier
// Should use tokens to prefill it. Would be good.
// For now, just steal values direct from the row result.
// A token like [node_title] will pull the id from a view -
// as long as the view row has that data.
// I can't expose to the user what those machine names are however...
// https://drupal.org/node/2099751
// They just have to guess.
$tokens = array();
foreach ($row as $token_key => $token_val) {
if (is_string($token_val)) {
$tokens["[{$token_key}]"] = $token_val;
}
elseif (is_array($token_val) && ($sub_val = reset($token_val))) {
if (isset($sub_val) && isset($sub_val['raw']) && isset($sub_val['raw']['value'])) {
$tokens["[{$token_key}]"] = $sub_val['raw']['value'];
}
}
}
// Each component that is defined as a child of this view component
// gets replicated.
if (empty($component['children'])) {
watchdog('webform_view', '
The embedded webform component "!component" in "!webform" has no
"child" elements defined.
If you want the webform to submit data, please create a webform
field element and nest it beneath the embedded view.
...And then configure the view to expose this field in its layout.
', array(
'!component' => l($component['name'], '/node/' . $node->nid . '/webform/components/' . $component['cid']),
'!webform' => l($node->title, '/node/' . $node->nid . '/webform/components/'),
), WATCHDOG_NOTICE);
$component['children'] = array();
}
foreach ((array) $component['children'] as $webform_component) {
// Some webform welements are not native. @see webform_element_info
$type = $webform_component['type'];
$webform_elements = array(
'number' => 'webform_number',
);
if (isset($webform_elements[$type])) {
$type = $webform_elements[$type];
}
// Use replacements to put the item identifier into a field value.
$default_value = NULL;
if (!empty($webform_component['value'])) {
$default_value = str_replace(array_keys($tokens), array_values($tokens), $webform_component['value']);
}
// Copy any previously set value into our element default value.
if (isset($component_value[$webform_component['form_key']])) {
$default_value = $component_value[$webform_component['form_key']];
}
// Webform components are very unlike normal form elements.
// that's a bore. Copy some parameters like size across.
// Can I delegate this to each elements own webform_render_THING
// callback - I feel like doing this by hand could be errorful.?
$render_func = '_webform_render_' . $webform_component['type'];
if (function_exists($render_func)) {
// The value arg is apparently expected to be an array? Whatever.
if (!is_array($default_value)) {
$default_value = array(
$default_value,
);
}
$placeholder_fields[$key][$webform_component['form_key']] = $render_func($webform_component, $default_value);
$placeholder_fields[$key][$webform_component['form_key']]['#webform_component'] = $webform_component;
}
else {
/*
//////SNIP THIS
// This was me doing it by hand - probably redundant if ^ is working.
$placeholder_fields[$key][$webform_component['form_key']] = array(
'#type' => $type,
'#title' => $webform_component['name'],
'#size' => isset($webform_component['extra']['width'])
? $webform_component['extra']['width'] : NULL,
'#default_value' => isset($default_value) ? $default_value : NULL,
'#webform_component' => $webform_component,
// Need to call in the theme wrapper to get field markup
// and title to show.
'#theme_wrappers' => ($type == 'hidden')
? array() : array('webform_element'),
);
/////
*/
}
}
}
// $display = $view->display[$view->current_display];
$element = array(
'#title_display' => $component['extra']['title_display'] ? $component['extra']['title_display'] : 'before',
'#required' => $component['mandatory'],
'#weight' => $component['weight'],
'#description' => $filter ? _webform_filter_descriptions($component['extra']['description'], $node) : $component['extra']['description'],
'#theme_wrappers' => array(
'webform_element',
),
'#theme' => 'webform_view_embedded',
// Needed to disable double-wrapping of radios and checkboxes.
'#pre_render' => array(),
'#translatable' => array(
'title',
'description',
'options',
),
// When webform renders elements, the content is expected to be inside
// element #children. #markup is not respected.
'#type' => 'markup',
);
// Add the made-up placeholder fields as children.
$element += $placeholder_fields;
// Add our embedded view as a renderable.
// Using #markup so that even if rendering starts falling apart later,
// it will still show up. Normally however, this value gets caught and
// preprocessed in theme_webform_view_embedded()
$element['view']['#markup'] = $output;
// Don't do this until we are finished with the data.
// $view->destroy();
return $element;
}