diff --git a/src/Plugin/Field/FieldFormatter/ViewfieldDefaultFormatter.php b/src/Plugin/Field/FieldFormatter/ViewfieldDefaultFormatter.php index c4b2b14..817efd2 100644 --- a/src/Plugin/Field/FieldFormatter/ViewfieldDefaultFormatter.php +++ b/src/Plugin/Field/FieldFormatter/ViewfieldDefaultFormatter.php @@ -11,6 +11,7 @@ use Drupal\Core\Field\FormatterBase; use Drupal\Core\Field\FieldItemListInterface; use Drupal\views\Views; +use Drupal\Component\Serialization\Json; /** * Plugin implementation of the 'viewfield_default' formatter. @@ -35,6 +36,9 @@ public function viewElements(FieldItemListInterface $items, $langcode) { $entity = $item->getEntity(); list($view_name, $view_display) = explode('|', $item->vname, 2); $view = Views::getView($view_name); + if (!empty($item->settings)) { + $settings = Json::decode($item->settings); + } $elements[$delta] = array( '#type' => 'viewfield', '#view' => $view, @@ -45,9 +49,11 @@ public function viewElements(FieldItemListInterface $items, $langcode) { '#entity_type' => $entity->getEntityTypeId(), '#entity_id' => $entity->id(), '#entity' => $entity, + '#exposed_settings' => $settings, '#theme' => 'viewfield_formatter_default', ); } return $elements; } + } diff --git a/src/Plugin/Field/FieldType/ViewfieldItem.php b/src/Plugin/Field/FieldType/ViewfieldItem.php index 5a2977d..361dc2a 100644 --- a/src/Plugin/Field/FieldType/ViewfieldItem.php +++ b/src/Plugin/Field/FieldType/ViewfieldItem.php @@ -13,7 +13,6 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\views\Views; - /** * Plugin implementation of the 'viewfield' field type. * @@ -58,14 +57,16 @@ public static function schema(FieldStorageDefinitionInterface $field_definition) 'vname' => array( 'type' => 'varchar', 'not null' => FALSE, - // Views requires at least 96 chars for the view name and display, plus - // we need 1 for our delimiter. Round up to a common value of 128. 'length' => 128, ), 'vargs' => array( 'type' => 'varchar', 'not null' => FALSE, - 'length' => 255, //viewfield_field_instance_settings_form_validate + 'length' => 255, + ), + 'settings' => array( + 'type' => 'text', + 'size' => 'big', ), ), ); @@ -79,6 +80,8 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel ->setLabel(t('View name')); $properties['vargs'] = DataDefinition::create('string') ->setLabel(t('View args')); + $properties['settings'] = DataDefinition::create('string') + ->setLabel(t('View settings')); return $properties; } @@ -127,4 +130,5 @@ public static function fieldSettingsFormValidate(array $form, FormStateInterface } } } + } diff --git a/src/Plugin/Field/FieldWidget/ViewfieldWidget.php b/src/Plugin/Field/FieldWidget/ViewfieldWidget.php index ddc3d60..abd9415 100644 --- a/src/Plugin/Field/FieldWidget/ViewfieldWidget.php +++ b/src/Plugin/Field/FieldWidget/ViewfieldWidget.php @@ -10,7 +10,11 @@ use Drupal\Core\Field\WidgetBase; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Render\Element; +use Drupal\Core\Form\FormState; +use Drupal\Component\Utility\Html; +use Drupal\Component\Serialization\Json; +use Drupal\Component\Utility\NestedArray; +use Drupal\Component\Utility\SortArray; use Drupal\views\Views; /** @@ -34,31 +38,135 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $field_settings = $this->getFieldSettings(); $options = $this->getPotentialReferences($field_settings); + $id = Html::getUniqueId('state-wrapper-' . $items->getName() . '-' . $delta); + $element['#field_name'] = $items->getName(); $element['vname'] = array( '#type' => 'select', '#title' => t('Views Field'), '#options' => $options, '#empty_value' => 0, + '#ajax' => array( + 'callback' => array($this, 'viewsSettings'), + 'event' => 'change', + 'progress' => array( + 'type' => 'throbber', + 'message' => NULL, + ), + 'wrapper' => $id, + ), '#access' => !$field_settings['force_default'], '#default_value' => isset($items[$delta]->vname) ? $items[$delta]->vname : NULL, ); + + $element['settings_wrapper'] = array( + '#type' => 'fieldset', + ); + + $element['settings_wrapper']['settings_wrapper_form'] = array( + '#type' => 'html_tag', + '#tag' => 'div', + ); + + $element['settings_wrapper']['settings_wrapper_form']['settings'] = array( + '#type' => 'html_tag', + '#tag' => 'div', + '#attributes' => array( + 'id' => $id, + ), + ); + + if (isset($items[$delta]->vname)) { + $view = explode('|', $items[$delta]->vname); + $viewInstance = $this->getView($view[0], $view[1]); + $itemSettings = []; + if (!empty($items[$delta]->settings)) { + $itemSettings = Json::decode($items[$delta]->settings); + } + if ($viewInstance) { + $element['settings_wrapper']['settings_wrapper_form']['settings'] = $this->getViewSettings($viewInstance, $view[1], $itemSettings); + $element['settings_wrapper']['settings_wrapper_form']['settings']['#attributes']['id'] = $id; + } + } + $element['vargs'] = array( '#type' => 'textfield', '#title' => t('Arguments'), '#default_value' => isset($items[$delta]->vargs) ? $items[$delta]->vargs : NULL, '#access' => !$field_settings['force_default'], - '#description' => t('A comma separated list of arguments to pass to the selected view. '), + '#description' => t('A comma separated list of arguments to pass to the selected view.'), ); return $element; } + /** + * Helper function for get exposed filter. + */ + public function getViewSettings($view, $display, $settings) { + $form_state = new FormState(); + if ($settings) { + $form_state->setUserInput($settings); + } + $view->initHandlers(); + $form = []; + // Let form plugins know this is for exposed widgets. + $form_state->set('exposed', TRUE); + $form['settings'] = []; + + // Go through each handler and let it generate its exposed widget. + foreach ($view->display_handler->handlers as $type => $value) { + /** @var \Drupal\views\Plugin\views\ViewsHandlerInterface $handler */ + foreach ($view->$type as $id => $handler) { + if ($handler->canExpose() && $handler->isExposed()) { + if ($handler->isAGroup()) { + $handler->groupForm($form, $form_state); + $id = $handler->options['group_info']['identifier']; + } + else { + $handler->buildExposedForm($form, $form_state); + } + if ($info = $handler->exposedInfo()) { + $form['#info']["$type-$id"] = $info; + } + } + } + } + + foreach ($settings as $name => $set) { + if ($form[$name]) { + $form[$name]['#default_value'] = $set; + } + } + + foreach ($form['#info'] as $info) { + if (isset($form[$info['value']])) { + $form[$info['value']]['#title'] = $info['label']; + } + } + + $exposed_form_plugin = $view->display_handler->getPlugin('exposed_form'); + $exposed_form_plugin->exposedFormAlter($form, $form_state); + + unset($form['actions']); + return $form; + } + + public function viewsSettings(array $form, FormStateInterface $form_state) { + $view = $form_state->getTriggeringElement()['#value']; + $view = explode('|', $view); + $viewInstance = $this->getView($view[0], $view[1]); + if ($viewInstance && is_a($viewInstance->getDisplay(), 'Drupal\viewfield\Plugin\views\display\ViewFieldDisplay')) { + return $this->getViewSettings($viewInstance, $view[1]); + } + return []; + } + /** * Returns a select options list of views displays of enabled and allowed views. * - * @param array @settings - * The field settings + * @param array $settings + * The field settings. * * @return array * An array with the allowed and enabled views and displays. @@ -75,7 +183,7 @@ protected function getPotentialReferences($settings) { } } $options = array(); - foreach ($views as $view_name => $view) { + foreach ($views as $view) { $displays = $view->get('display'); foreach ($displays as $display) { $options[$view->id() . '|' . $display['id']] = $view->id() . ' - ' . $display['display_title']; @@ -84,4 +192,31 @@ protected function getPotentialReferences($settings) { return $options; } + /** + * Helper function for retrieve view. + * + * @param string $viewId + * View machinable name to load. + * @param string $display + * Display plugin to load. + */ + public function getView($viewId, $display) { + $view = Views::getView($viewId); + if ($view) { + $view->setDisplay($display); + return $view; + } + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function massageFormValues(array $values, array $form, FormStateInterface $formState) { + foreach ($values as $key => $value) { + $values[$key]['settings'] = Json::encode($value['settings_wrapper']['settings_wrapper_form']['settings']); + } + return $values; + } + } diff --git a/src/Plugin/views/display/ViewFieldDisplay.php b/src/Plugin/views/display/ViewFieldDisplay.php new file mode 100644 index 0000000..968b638 --- /dev/null +++ b/src/Plugin/views/display/ViewFieldDisplay.php @@ -0,0 +1,29 @@ + !\Drupal::config('views.settings')->get('ui.show.display_embed'), + * + * @ViewsDisplay( + * id = "viewfield", + * title = @Translation("Viewfield"), + * help = @Translation("Provide a display which can be embedded using the views api."), + * theme = "views_view", + * uses_menu_links = FALSE + * ) + */ +class ViewFieldDisplay extends DisplayPluginBase { + + public function displaysExposed() { + return FALSE; + } + +} diff --git a/viewfield.module b/viewfield.module index 56d3c68..6c82ac9 100644 --- a/viewfield.module +++ b/viewfield.module @@ -1,13 +1,12 @@ setExposedInput($element['#exposed_settings']); $view_el = $element['#view']->preview($element['#view_display'], array($element['#view_arguments'])); - $output = render ($view_el); + $output = render($view_el); $variables['output'] = $output; } @@ -42,7 +42,7 @@ function viewfield_element_info() { } /** - * #pre_render callback for a viewfield field. + * pre_render callback for a viewfield field. * * @see viewfield_post_render() */ @@ -75,7 +75,7 @@ function viewfield_pre_render($element) { } /** - * #post_render callback for a viewfield field. + * post_render callback for a viewfield field. * * @see viewfield_pre_render() */ @@ -85,9 +85,8 @@ function viewfield_post_render($content, $element) { return $content; } - /** - * Perform argument replacement + * Perform argument replacement. */ function _viewfield_get_view_args($vargs, $entity_type, $entity) { $args = array();