Loading src/Plugin/views/field/Combine.php +76 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ use Drupal\views\Views; */ class Combine extends FieldPluginBase { /** * The handler types with map options. */ const MAP_HANDLER_TYPES = ['filter', 'sort']; /** * {@inheritdoc} */ Loading @@ -32,15 +37,52 @@ class Combine extends FieldPluginBase { return $this->options['view_id']; } /** * Get exposed views handlers. * * @param string $handler_type * The views handler type. * * @return array * Returns array of views exposed handlers. */ public function getExposedHandlers(string $handler_type) { return array_filter( $this->view->getHandlers($handler_type), function ($handler) { return isset($handler['exposed']) && $handler['exposed']; } ); } /** * {@inheritdoc} */ protected function defineOptions() { $options = parent::defineOptions(); $options['view_id'] = ['default' => '']; foreach (self::MAP_HANDLER_TYPES as $handler_type) { $key = "{$handler_type}_map"; $options[$key] = []; foreach ($this->getExposedHandlers($handler_type) as $id => $definition) { $options[$key][$id] = ['default' => '']; } } return $options; } /** * {@inheritdoc} */ protected function setOptionDefaults(array &$storage, array $options) { foreach ($options as &$definition) { if (!isset($definition['default'])) { $definition['default'] = ''; } } parent::setOptionDefaults($storage, $options); } /** * {@inheritdoc} */ Loading @@ -54,6 +96,40 @@ class Combine extends FieldPluginBase { '#default_value' => $this->options['view_id'], '#required' => TRUE, ]; foreach (self::MAP_HANDLER_TYPES as $handler_type) { $this->buildMap($handler_type, $form); } } /** * Builds the views handler map elements. * * @param string $handler_type * The views handler type. * @param array $form * The form. */ protected function buildMap(string $handler_type, array &$form) { if ($handlers = $this->getExposedHandlers($handler_type)) { $key = "{$handler_type}_map"; $title = mb_strtolower(ViewExecutable::getHandlerTypes()[$handler_type]['title']); $form[$key] = [ '#type' => 'details', '#title' => $this->t('Map exposed @title', ['@title' => $title]), '#description' => $this->t('Map exposed @title input identifiers from this view to the combined view.', [ '@title' => $title, ]), '#open' => TRUE, '#tree' => TRUE, ]; foreach ($handlers as $id => $definition) { $form[$key][$id] = [ '#type' => 'textfield', '#title' => $id, '#default_value' => $this->options[$key][$id] ?? '', ]; } } } /** Loading src/ViewsCombiner.php +38 −3 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ namespace Drupal\views_combine; use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException; use Drupal\Component\Plugin\Exception\PluginNotFoundException; use Drupal\Core\Database\Query\Select; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\ViewExecutable; /** Loading Loading @@ -205,13 +206,47 @@ class ViewsCombiner { * The display identifier. * @param \Drupal\views\ViewExecutable $base_view * The base view. * @param \Drupal\views\Plugin\views\field\FieldPluginBase|null $field_handler * The views field handler. * * @return \Drupal\views\ViewExecutable|null * Returns the built view executable. */ public function buildView(string $view_id, string $display_id, ViewExecutable $base_view) { public function buildView(string $view_id, string $display_id, ViewExecutable $base_view, FieldPluginBase $field_handler = NULL) { if ($view = $this->getView($view_id, $display_id)) { $view->setExposedInput($base_view->exposed_raw_input); $input = $base_view->exposed_raw_input; if ($field_handler) { foreach ($input as $id => $value) { if (isset($field_handler->options['filter_map'][$id]) && $field_handler->options['filter_map'][$id]) { // Use the mapped filter identifier. $input[$field_handler->options['filter_map'][$id]] = $value; } } } if (isset($input['sort_by']) && !empty($input['sort_by'])) { $id = $input['sort_by']; $sort_handlers = $view->getHandlers('sort'); if (!array_key_exists($id, $sort_handlers)) { $input['sort_order'] = $input['sort_order'] ?? 'ASC'; if (isset($field_handler->options['sort_map'][$id]) && $field_handler->options['sort_map'][$id]) { // Use the mapped sort identifier. $input['sort_by'] = $field_handler->options['sort_map'][$id]; } elseif (!empty($sort_handlers)) { // Use the first sort identifier. $input['sort_by'] = key($sort_handlers); } else { unset($input['sort_by'], $input['sort_order'], $input['sort_bef_combine']); } if (isset($input['sort_bef_combine'])) { $input['sort_bef_combine'] = $input['sort_by'] . '_' . $input['sort_order']; } } } $view->setExposedInput($input); $view->preExecute($base_view->args); $view->build(); return $view; Loading Loading @@ -287,7 +322,7 @@ class ViewsCombiner { foreach ($this->view->field as $field_handler) { if ($field_handler->realField === 'views_combine' && $field_handler->options['view_id']) { [$view_id, $display_id] = explode(':', $field_handler->options['view_id']); if (($_view = $this->buildView($view_id, $display_id, $this->view)) && $this->filter($_view)) { if (($_view = $this->buildView($view_id, $display_id, $this->view, $field_handler)) && $this->filter($_view)) { if ($_view->build_info['query'] instanceof Select) { /** @var \Drupal\Core\Database\Query\Select $query */ $query = $_view->build_info['query']; Loading Loading
src/Plugin/views/field/Combine.php +76 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ use Drupal\views\Views; */ class Combine extends FieldPluginBase { /** * The handler types with map options. */ const MAP_HANDLER_TYPES = ['filter', 'sort']; /** * {@inheritdoc} */ Loading @@ -32,15 +37,52 @@ class Combine extends FieldPluginBase { return $this->options['view_id']; } /** * Get exposed views handlers. * * @param string $handler_type * The views handler type. * * @return array * Returns array of views exposed handlers. */ public function getExposedHandlers(string $handler_type) { return array_filter( $this->view->getHandlers($handler_type), function ($handler) { return isset($handler['exposed']) && $handler['exposed']; } ); } /** * {@inheritdoc} */ protected function defineOptions() { $options = parent::defineOptions(); $options['view_id'] = ['default' => '']; foreach (self::MAP_HANDLER_TYPES as $handler_type) { $key = "{$handler_type}_map"; $options[$key] = []; foreach ($this->getExposedHandlers($handler_type) as $id => $definition) { $options[$key][$id] = ['default' => '']; } } return $options; } /** * {@inheritdoc} */ protected function setOptionDefaults(array &$storage, array $options) { foreach ($options as &$definition) { if (!isset($definition['default'])) { $definition['default'] = ''; } } parent::setOptionDefaults($storage, $options); } /** * {@inheritdoc} */ Loading @@ -54,6 +96,40 @@ class Combine extends FieldPluginBase { '#default_value' => $this->options['view_id'], '#required' => TRUE, ]; foreach (self::MAP_HANDLER_TYPES as $handler_type) { $this->buildMap($handler_type, $form); } } /** * Builds the views handler map elements. * * @param string $handler_type * The views handler type. * @param array $form * The form. */ protected function buildMap(string $handler_type, array &$form) { if ($handlers = $this->getExposedHandlers($handler_type)) { $key = "{$handler_type}_map"; $title = mb_strtolower(ViewExecutable::getHandlerTypes()[$handler_type]['title']); $form[$key] = [ '#type' => 'details', '#title' => $this->t('Map exposed @title', ['@title' => $title]), '#description' => $this->t('Map exposed @title input identifiers from this view to the combined view.', [ '@title' => $title, ]), '#open' => TRUE, '#tree' => TRUE, ]; foreach ($handlers as $id => $definition) { $form[$key][$id] = [ '#type' => 'textfield', '#title' => $id, '#default_value' => $this->options[$key][$id] ?? '', ]; } } } /** Loading
src/ViewsCombiner.php +38 −3 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ namespace Drupal\views_combine; use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException; use Drupal\Component\Plugin\Exception\PluginNotFoundException; use Drupal\Core\Database\Query\Select; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\ViewExecutable; /** Loading Loading @@ -205,13 +206,47 @@ class ViewsCombiner { * The display identifier. * @param \Drupal\views\ViewExecutable $base_view * The base view. * @param \Drupal\views\Plugin\views\field\FieldPluginBase|null $field_handler * The views field handler. * * @return \Drupal\views\ViewExecutable|null * Returns the built view executable. */ public function buildView(string $view_id, string $display_id, ViewExecutable $base_view) { public function buildView(string $view_id, string $display_id, ViewExecutable $base_view, FieldPluginBase $field_handler = NULL) { if ($view = $this->getView($view_id, $display_id)) { $view->setExposedInput($base_view->exposed_raw_input); $input = $base_view->exposed_raw_input; if ($field_handler) { foreach ($input as $id => $value) { if (isset($field_handler->options['filter_map'][$id]) && $field_handler->options['filter_map'][$id]) { // Use the mapped filter identifier. $input[$field_handler->options['filter_map'][$id]] = $value; } } } if (isset($input['sort_by']) && !empty($input['sort_by'])) { $id = $input['sort_by']; $sort_handlers = $view->getHandlers('sort'); if (!array_key_exists($id, $sort_handlers)) { $input['sort_order'] = $input['sort_order'] ?? 'ASC'; if (isset($field_handler->options['sort_map'][$id]) && $field_handler->options['sort_map'][$id]) { // Use the mapped sort identifier. $input['sort_by'] = $field_handler->options['sort_map'][$id]; } elseif (!empty($sort_handlers)) { // Use the first sort identifier. $input['sort_by'] = key($sort_handlers); } else { unset($input['sort_by'], $input['sort_order'], $input['sort_bef_combine']); } if (isset($input['sort_bef_combine'])) { $input['sort_bef_combine'] = $input['sort_by'] . '_' . $input['sort_order']; } } } $view->setExposedInput($input); $view->preExecute($base_view->args); $view->build(); return $view; Loading Loading @@ -287,7 +322,7 @@ class ViewsCombiner { foreach ($this->view->field as $field_handler) { if ($field_handler->realField === 'views_combine' && $field_handler->options['view_id']) { [$view_id, $display_id] = explode(':', $field_handler->options['view_id']); if (($_view = $this->buildView($view_id, $display_id, $this->view)) && $this->filter($_view)) { if (($_view = $this->buildView($view_id, $display_id, $this->view, $field_handler)) && $this->filter($_view)) { if ($_view->build_info['query'] instanceof Select) { /** @var \Drupal\Core\Database\Query\Select $query */ $query = $_view->build_info['query']; Loading