View source
<?php
function entityreference_view_widget_entity_info_alter(&$info) {
foreach ($info as $entity_type => $data) {
$info[$entity_type]['view modes']['entityreference_view_widget'] = array(
'label' => t('Entity Reference View Widget'),
'custom settings' => TRUE,
);
}
}
function entityreference_view_widget_entity_view($entity, $type, $view_mode, $langcode) {
if ($view_mode == 'entityreference_view_widget') {
$entity_id = entity_id($type, $entity);
$entity->content['entityreference_view_widget_action'] = array(
'#markup' => '<!--entityreference-view-widget-action-' . $entity_id . '-->',
'#weight' => -10,
);
}
}
function entityreference_view_widget_menu() {
$items = array();
$items['entityreference_view_widget/ajax'] = array(
'title' => 'AJAX callback',
'page callback' => 'entityreference_view_widget_ajax',
'delivery callback' => 'ajax_deliver',
'access callback' => TRUE,
'theme callback' => 'ajax_base_page_theme',
'type' => MENU_CALLBACK,
);
return $items;
}
function entityreference_view_widget_theme() {
return array(
'widget' => array(
'render element' => 'form',
'template' => 'entityreference-view-widget',
),
'entityreference_view_widget_selected_items' => array(
'render element' => 'element',
),
);
}
function entityreference_view_widget_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'entityreference_view_widget') . '/views',
);
}
function entityreference_view_widget_ajax() {
if (isset($_POST['ajax_html_ids'])) {
unset($_POST['ajax_html_ids']);
}
form_load_include($form_state, 'inc', 'node', 'node.pages');
list($form, $form_state) = ajax_get_form();
drupal_process_form($form['#form_id'], $form, $form_state);
$form_parents = func_get_args();
$form = drupal_array_get_nested_value($form, $form_parents);
$output = drupal_render($form);
$js = drupal_add_js();
$settings = call_user_func_array('array_merge_recursive', $js['settings']['data']);
$commands = array();
$commands[] = ajax_command_replace(NULL, $output, $settings);
return array(
'#type' => 'ajax',
'#commands' => $commands,
);
}
function entityreference_view_widget_field_widget_info() {
$widgets['entityreference_view_widget'] = array(
'label' => t('View'),
'description' => t('An advanced, view-based widget.'),
'field types' => array(
'entityreference',
),
'settings' => array(
'view' => '',
'pass_argument' => FALSE,
),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_CUSTOM,
'default value' => FIELD_BEHAVIOR_NONE,
),
);
return $widgets;
}
function entityreference_view_widget_preprocess_views_view(&$vars) {
if (is_array($vars['exposed'])) {
$vars['exposed'] = '';
}
}
function entityreference_view_widget_field_widget_settings_form($field, $instance) {
if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED) {
drupal_set_message(t("The selected widget only supports fields with 'Number of values' set to 'Unlimited'. Otherwise it won't get displayed on the entity form."), 'warning');
}
$widget = $instance['widget'];
$settings = $widget['settings'];
$target_type = $field['settings']['target_type'];
$info = entity_get_info($target_type);
$target_base_table = $info['base table'];
if ($widget['type'] == 'entityreference_view_widget') {
$options = array();
$displays = views_get_applicable_views('entityreference view display');
foreach ($displays as $data) {
list($view, $display_id) = $data;
$view_name = !empty($view->human_name) ? $view->human_name : $view->name;
$options[$view->name . '|' . $display_id] = check_plain($view_name . ' | ' . $view->display_handler->display->display_title);
}
$element['view'] = array(
'#type' => 'select',
'#title' => t('View'),
'#description' => t('Specify the View to use for selecting items. Only views that have an "Entityreference View Widget" display are shown.'),
'#options' => $options,
'#default_value' => $settings['view'],
'#required' => TRUE,
);
$element['pass_argument'] = array(
'#type' => 'checkbox',
'#title' => t('Pass selected entity ids to View'),
'#description' => t('If enabled, the View will get all selected entity ids as the first argument. Useful for excluding already selected items.'),
'#default_value' => $settings['pass_argument'],
);
}
return $element;
}
function entityreference_view_widget_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$field_name = $field['field_name'];
$field_language = $element['#language'];
$entity_type = $field['settings']['target_type'];
$widget = $instance['widget'];
if (empty($widget['settings']['view'])) {
return;
}
if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED) {
drupal_set_message(t("The widget for field %field won't be displayed because it only supports fields with unlimited cardinality.", array(
'%field' => $instance['label'],
)), 'error');
return;
}
$field_state = field_form_get_state($element['#field_parents'], $field['field_name'], $langcode, $form_state);
if (isset($field_state['items'])) {
$items = $field_state['items'];
}
$selected_entity_ids = array();
foreach ($items as $item) {
$selected_entity_ids[] = $item['target_id'];
}
$target_view = explode('|', $widget['settings']['view']);
$view = views_get_view($target_view[0]);
$view
->set_display($target_view[1]);
$ajax = isset($form_state['values'][$field_name][$field_language]);
if ($ajax) {
$values = $form_state['values'][$field_name];
if (!empty($values['exposed_filters'])) {
$exposed_input = $values['exposed_filters'];
$view->exposed_raw_input = $exposed_input;
$view->exposed_data = $exposed_input;
unset($exposed_input['submit']);
$view->exposed_input = $exposed_input;
}
if (isset($values['page']) && is_numeric($values['page']) && empty($form_state['triggering_element']['#exposed_filter'])) {
$view
->set_current_page($values['page']);
}
}
if (!empty($selected_entity_ids) && !empty($widget['settings']['pass_argument'])) {
$arguments = array();
$arguments[0] = implode(',', $selected_entity_ids);
$view
->set_arguments($arguments);
}
$output = $ajax ? theme('status_messages') : '';
$output .= $view
->preview($target_view[1]);
$element += array(
'#element_validate' => array(
'entityreference_view_widget_validate',
),
'#theme' => 'widget',
'#theme_wrappers' => array(
'fieldset',
),
'#attributes' => array(
'class' => array(
'entityreference-view-widget',
),
),
);
$element['#attached']['css'][] = drupal_get_path('module', 'entityreference_view_widget') . '/entityreference_view_widget.css';
$element['#attached']['js'][] = drupal_get_path('module', 'entityreference_view_widget') . '/entityreference_view_widget.js';
$element['view'] = array(
'#markup' => $output,
);
if (!empty($view->exposed_widgets)) {
$element['filters'] = entityreference_view_widget_prepare_filters($view->exposed_widgets, $field_name);
}
$element['page'] = array(
'#parents' => array(
$field_name,
'page',
),
'#type' => 'hidden',
'#attributes' => array(
'class' => array(
'entityreference-view-widget-page',
),
),
'#default_value' => 0,
);
$element['pager_submit'] = array(
'#type' => 'button',
'#name' => 'pager_submit',
'#attributes' => array(
'class' => array(
'pager-submit',
),
),
'#ajax' => array(
'path' => 'entityreference_view_widget/ajax/' . $field_name,
'wrapper' => 'edit-' . str_replace('_', '-', $field_name),
'method' => 'replace',
'progress' => array(
'type' => 'throbber',
'message' => '',
),
),
'#limit_validation_errors' => array(
array(
$field_name,
),
),
'#weight' => 100,
'#submit' => array(
'entityreference_view_widget_exposed_filters_pager_submit',
),
);
if (!$view->display_handler->options['hide_left']) {
if (!empty($selected_entity_ids)) {
$selected_entities = entity_load($entity_type, $selected_entity_ids);
$entity_view = entity_view($entity_type, $selected_entities, 'entityreference_view_widget');
$entity_view = reset($entity_view);
$i = 0;
foreach ($selected_entities as $entity_id => $entity) {
unset($entity_view[$entity_id]['entityreference_view_widget_action']);
$entity_view[$entity_id]['_weight'] = array(
'#parents' => array(
$field_name,
$field_language,
'items',
$entity_id,
'_weight',
),
'#type' => 'weight',
'#title' => t('Weight for @title', array(
'@title' => entity_label($entity_type, $entity),
)),
'#title_display' => 'invisible',
'#delta' => count($selected_entities),
'#default_value' => $i,
);
$entity_view[$entity_id]['remove'] = array(
'#parents' => array(
$field_name,
$field_language,
'items',
$entity_id,
'remove',
),
'#type' => 'checkbox',
'#title' => t('Remove'),
'#weight' => -10,
'#refresh_items' => TRUE,
'#ajax' => array(
'path' => 'entityreference_view_widget/ajax/' . $field_name,
'wrapper' => 'edit-' . str_replace('_', '-', $field_name),
'method' => 'replace',
'progress' => array(
'type' => 'throbber',
'message' => '',
),
),
);
$i++;
}
$element['selected_items'] = $entity_view;
$element['selected_items']['#theme'] = 'entityreference_view_widget_selected_items';
}
else {
$element['selected_items'] = array(
'#markup' => t('No items have been selected.'),
);
}
}
$substitutions = array();
$result_entities = $view->query
->get_result_entities($view->result);
foreach ($result_entities[1] as $row_id => $entity) {
$entity_id = entity_id($entity_type, $entity);
if (!$view->display_handler->options['hide_left']) {
$element['add'][$entity_id] = array(
'#type' => 'checkbox',
'#refresh_items' => TRUE,
'#ajax' => array(
'path' => 'entityreference_view_widget/ajax/' . $field_name,
'wrapper' => 'edit-' . str_replace('_', '-', $field_name),
'method' => 'replace',
'progress' => array(
'type' => 'throbber',
'message' => '',
),
),
);
}
else {
$element['add'][$entity_id] = array(
'#type' => 'checkbox',
'#refresh_items' => TRUE,
);
}
$substitutions[] = array(
'placeholder' => '<!--entityreference-view-widget-action-' . $entity_id . '-->',
'entity_id' => $entity_id,
);
}
$element['#substitutions'] = array(
'#type' => 'value',
'#value' => $substitutions,
);
return $element;
}
function entityreference_view_widget_preprocess_widget(&$variables) {
$form = $variables['form'];
$search = array();
$replace = array();
foreach ($form['#substitutions']['#value'] as $substitution) {
$entity_id = $substitution['entity_id'];
$search[] = $substitution['placeholder'];
$replace[] = isset($form['add'][$entity_id]) ? drupal_render($form['add'][$entity_id]) : '';
}
$form['view']['#markup'] = str_replace($search, $replace, $form['view']['#markup']);
$variables['selected_items'] = drupal_render($form['selected_items']);
$variables['filters'] = drupal_render($form['filters']);
$variables['pager_submit'] = drupal_render($form['pager_submit']);
$variables['view'] = drupal_render($form['view']);
unset($form['filters']);
unset($form['selected_items']);
unset($form['view']);
unset($form['pager_submit']);
$variables['extra'] = drupal_render_children($form);
}
function theme_entityreference_view_widget_selected_items($variables) {
$element = $variables['element'];
$weight_class = $element['#id'] . '-weight';
$table_id = $element['#id'] . '-table';
$widgets = array();
foreach (element_children($element) as $key) {
$widgets[] =& $element[$key];
}
usort($widgets, '_field_sort_items_value_helper');
$rows = array();
foreach ($widgets as $key => &$widget) {
$widget['_weight']['#attributes']['class'] = array(
$weight_class,
);
$weight = render($widget['_weight']);
$widget['#theme_wrappers'] = array();
$information = drupal_render($widget);
$rows[] = array(
'data' => array(
$information,
$weight,
),
'class' => isset($widget['#attributes']['class']) ? array_merge($widget['#attributes']['class'], array(
'draggable',
)) : array(
'draggable',
),
'no_striping' => TRUE,
);
}
drupal_add_tabledrag($table_id, 'order', 'sibling', $weight_class);
$output = empty($rows) ? '' : theme('table', array(
'header' => array(),
'rows' => $rows,
'attributes' => array(
'id' => $table_id,
),
));
$output .= drupal_render_children($element);
return $output;
}
function entityreference_view_widget_validate($element, &$form_state) {
$field_name = $element['#field_name'];
$language = $element['#language'];
$target_type = $form_state['field'][$field_name][$language]['field']['settings']['target_type'];
$element_values = $form_state['values'][$field_name][$language];
$value = array();
if (!empty($element_values['items'])) {
uasort($element_values['items'], '_field_sort_items_helper');
foreach ($element_values['items'] as $entity_id => $data) {
if (!$data['remove']) {
$value[] = array(
'target_type' => $target_type,
'target_id' => $entity_id,
);
}
}
}
if (!empty($element_values['add'])) {
$add = array_filter($element_values['add']);
foreach ($add as $entity_id => $status) {
if (!isset($element_values['items'][$entity_id])) {
$value[] = array(
'target_type' => $target_type,
'target_id' => $entity_id,
);
}
}
}
form_set_value($element, $value, $form_state);
$parents = array_slice($element['#parents'], 0, -2);
$field_state = field_form_get_state($parents, $field_name, $language, $form_state);
$field_state['items'] = $value;
field_form_set_state($parents, $field_name, $language, $form_state, $field_state);
}
function entityreference_view_widget_exposed_filters_validate($element, &$form_state) {
}
function entityreference_view_widget_prepare_filters($form, $field_name) {
if (!is_array($form)) {
return;
}
$form['#element_validate'] = array(
'entityreference_view_widget_exposed_filters_validate',
);
$form['submit']['#submit'] = array(
'entityreference_view_widget_exposed_filters_submit',
);
$form['submit']['#limit_validation_errors'] = array(
array(
$field_name,
),
);
$form['submit']['#name'] = 'apply-' . $field_name;
foreach (element_get_visible_children($form) as $key) {
$form[$key]['#parents'] = array(
$field_name,
'exposed_filters',
$key,
);
$form[$key]['#exposed_filter'] = TRUE;
if (!empty($form[$key]['#ajax']) && empty($form[$key]['#ajax']['path']) && empty($form[$key]['#ajax']['callback'])) {
$form[$key]['#ajax']['path'] = 'entityreference_view_widget/ajax/' . $field_name;
$form[$key]['#ajax']['wrapper'] = 'edit-' . str_replace('_', '-', $field_name);
}
}
return $form;
}
function entityreference_view_widget_exposed_filters_submit($form, &$form_state) {
$form_state['rebuild'] = TRUE;
}
function entityreference_view_widget_exposed_filters_pager_submit($form, &$form_state) {
$form_state['rebuild'] = TRUE;
}