| @@ 25-201 (lines=177) @@ | ||
| 22 | * deriver = "Drupal\graphql_views\Plugin\Deriver\Fields\SubViewDeriver" |
|
| 23 | * ) |
|
| 24 | */ |
|
| 25 | class SubView extends FieldPluginBase implements ContainerFactoryPluginInterface { |
|
| 26 | use DependencySerializationTrait; |
|
| 27 | ||
| 28 | /** |
|
| 29 | * The entity type manager. |
|
| 30 | * |
|
| 31 | * @var \Drupal\Core\Entity\EntityTypeManagerInterface |
|
| 32 | */ |
|
| 33 | protected $entityTypeManager; |
|
| 34 | ||
| 35 | /** |
|
| 36 | * {@inheritdoc} |
|
| 37 | */ |
|
| 38 | public function __construct( |
|
| 39 | array $configuration, |
|
| 40 | $pluginId, |
|
| 41 | $pluginDefinition, |
|
| 42 | EntityTypeManagerInterface $entityTypeManager |
|
| 43 | ) { |
|
| 44 | $this->entityTypeManager = $entityTypeManager; |
|
| 45 | parent::__construct($configuration, $pluginId, $pluginDefinition); |
|
| 46 | } |
|
| 47 | ||
| 48 | /** |
|
| 49 | * {@inheritdoc} |
|
| 50 | */ |
|
| 51 | public static function create(ContainerInterface $container, array $configuration, $pluginId, $pluginDefinition) { |
|
| 52 | return new static( |
|
| 53 | $configuration, |
|
| 54 | $pluginId, |
|
| 55 | $pluginDefinition, |
|
| 56 | $container->get('entity_type.manager') |
|
| 57 | ); |
|
| 58 | } |
|
| 59 | ||
| 60 | /** |
|
| 61 | * {@inheritdoc} |
|
| 62 | */ |
|
| 63 | public function resolveValues($value, array $args, ResolveContext $context, ResolveInfo $info) { |
|
| 64 | $storage = $this->entityTypeManager->getStorage('view'); |
|
| 65 | $definition = $this->getPluginDefinition(); |
|
| 66 | ||
| 67 | /** @var \Drupal\views\Entity\View $view */ |
|
| 68 | if ($view = $storage->load($definition['view'])) { |
|
| 69 | $executable = $view->getExecutable(); |
|
| 70 | $executable->setDisplay($definition['display']); |
|
| 71 | /** @var \Drupal\graphql_views\Plugin\views\display\GraphQL $display */ |
|
| 72 | $display = $executable->getDisplay($definition['display']); |
|
| 73 | ||
| 74 | // a subview can only work on an entity, so return null it it is not. |
|
| 75 | ||
| 76 | if (!$value instanceof EntityInterface) { |
|
| 77 | return; |
|
| 78 | } |
|
| 79 | ||
| 80 | // Set the first argument to the id of the current entity. |
|
| 81 | $executable->setArguments([$value->id()]); |
|
| 82 | ||
| 83 | $filters = $executable->getDisplay()->getOption('filters');; |
|
| 84 | $input = $this->extractExposedInput($value, $args, $filters); |
|
| 85 | $executable->setExposedInput($input); |
|
| 86 | ||
| 87 | // This is a workaround for the Taxonomy Term filter which requires a full |
|
| 88 | // exposed form to be sent OR the display being an attachment to just |
|
| 89 | // accept input values. |
|
| 90 | $executable->is_attachment = TRUE; |
|
| 91 | $executable->exposed_raw_input = $input; |
|
| 92 | ||
| 93 | if (!empty($definition['paged'])) { |
|
| 94 | // Set paging parameters. |
|
| 95 | $executable->setItemsPerPage($args['pageSize']); |
|
| 96 | $executable->setCurrentPage($args['page']); |
|
| 97 | } |
|
| 98 | ||
| 99 | if (isset($args['offset']) && !empty($args['offset'])) { |
|
| 100 | $executable->setOffset($args['offset']); |
|
| 101 | } |
|
| 102 | ||
| 103 | $result = $executable->render($definition['display']); |
|
| 104 | /** @var \Drupal\Core\Cache\CacheableMetadata $cache */ |
|
| 105 | if ($cache = $result['cache']) { |
|
| 106 | $cache->setCacheContexts( |
|
| 107 | array_filter($cache->getCacheContexts(), function ($context) { |
|
| 108 | // Don't emit the url cache contexts. |
|
| 109 | return $context !== 'url' && strpos($context, 'url.') !== 0; |
|
| 110 | }) |
|
| 111 | ); |
|
| 112 | } |
|
| 113 | yield $result; |
|
| 114 | } |
|
| 115 | } |
|
| 116 | ||
| 117 | /** |
|
| 118 | * {@inheritdoc} |
|
| 119 | */ |
|
| 120 | protected function getCacheDependencies(array $result, $value, array $args, ResolveContext $context, ResolveInfo $info) { |
|
| 121 | return array_map(function ($item) { |
|
| 122 | return $item['cache']; |
|
| 123 | }, $result); |
|
| 124 | } |
|
| 125 | ||
| 126 | /** |
|
| 127 | * Retrieves the contextual filter argument from the parent value or args. |
|
| 128 | * |
|
| 129 | * @param $value |
|
| 130 | * The resolved parent value. |
|
| 131 | * @param $args |
|
| 132 | * The arguments provided to the field. |
|
| 133 | * |
|
| 134 | * @return array |
|
| 135 | * An array of arguments containing the contextual filter value from the |
|
| 136 | * parent or provided args if any. |
|
| 137 | */ |
|
| 138 | protected function extractContextualFilters($value, $args) { |
|
| 139 | $definition = $this->getPluginDefinition(); |
|
| 140 | $arguments = []; |
|
| 141 | ||
| 142 | foreach ($definition['arguments_info'] as $argumentId => $argumentInfo) { |
|
| 143 | if (isset($args['contextualFilter'][$argumentId])) { |
|
| 144 | $arguments[$argumentInfo['index']] = $args['contextualFilter'][$argumentId]; |
|
| 145 | } |
|
| 146 | elseif ( |
|
| 147 | $value instanceof EntityInterface && |
|
| 148 | $value->getEntityTypeId() === $argumentInfo['entity_type'] && |
|
| 149 | (empty($argumentInfo['bundles']) || |
|
| 150 | in_array($value->bundle(), $argumentInfo['bundles'], TRUE)) |
|
| 151 | ) { |
|
| 152 | $arguments[$argumentInfo['index']] = $value->id(); |
|
| 153 | } |
|
| 154 | else { |
|
| 155 | $arguments[$argumentInfo['index']] = NULL; |
|
| 156 | } |
|
| 157 | } |
|
| 158 | ||
| 159 | return $arguments; |
|
| 160 | } |
|
| 161 | ||
| 162 | /** |
|
| 163 | * Retrieves sort and filter arguments from the provided field args. |
|
| 164 | * |
|
| 165 | * @param $value |
|
| 166 | * The resolved parent value. |
|
| 167 | * @param $args |
|
| 168 | * The array of arguments provided to the field. |
|
| 169 | * @param $filters |
|
| 170 | * The available filters for the configured view. |
|
| 171 | * |
|
| 172 | * @return array |
|
| 173 | * The array of sort and filter arguments to execute the view with. |
|
| 174 | */ |
|
| 175 | protected function extractExposedInput($value, $args, $filters) { |
|
| 176 | // Prepare arguments for use as exposed form input. |
|
| 177 | $input = array_filter([ |
|
| 178 | // Sorting arguments. |
|
| 179 | 'sort_by' => isset($args['sortBy']) ? $args['sortBy'] : NULL, |
|
| 180 | 'sort_order' => isset($args['sortDirection']) ? $args['sortDirection'] : NULL, |
|
| 181 | ]); |
|
| 182 | ||
| 183 | // If some filters are missing from the input, set them to an empty string |
|
| 184 | // explicitly. Otherwise views module generates "Undefined index" notice. |
|
| 185 | foreach ($filters as $filterKey => $filterRow) { |
|
| 186 | if (!isset($filterRow['expose']['identifier'])) { |
|
| 187 | continue; |
|
| 188 | } |
|
| 189 | ||
| 190 | $inputKey = $filterRow['expose']['identifier']; |
|
| 191 | if (!isset($args['filter'][$inputKey])) { |
|
| 192 | $input[$inputKey] = $filterRow['value']; |
|
| 193 | } else { |
|
| 194 | $input[$inputKey] = $args['filter'][$inputKey]; |
|
| 195 | } |
|
| 196 | } |
|
| 197 | ||
| 198 | return $input; |
|
| 199 | } |
|
| 200 | ||
| 201 | } |
|
| 202 | ||
| @@ 25-197 (lines=173) @@ | ||
| 22 | * deriver = "Drupal\graphql_views\Plugin\Deriver\Fields\ViewDeriver" |
|
| 23 | * ) |
|
| 24 | */ |
|
| 25 | class View extends FieldPluginBase implements ContainerFactoryPluginInterface { |
|
| 26 | use DependencySerializationTrait; |
|
| 27 | ||
| 28 | /** |
|
| 29 | * The entity type manager. |
|
| 30 | * |
|
| 31 | * @var \Drupal\Core\Entity\EntityTypeManagerInterface |
|
| 32 | */ |
|
| 33 | protected $entityTypeManager; |
|
| 34 | ||
| 35 | /** |
|
| 36 | * {@inheritdoc} |
|
| 37 | */ |
|
| 38 | public function __construct( |
|
| 39 | array $configuration, |
|
| 40 | $pluginId, |
|
| 41 | $pluginDefinition, |
|
| 42 | EntityTypeManagerInterface $entityTypeManager |
|
| 43 | ) { |
|
| 44 | $this->entityTypeManager = $entityTypeManager; |
|
| 45 | parent::__construct($configuration, $pluginId, $pluginDefinition); |
|
| 46 | } |
|
| 47 | ||
| 48 | /** |
|
| 49 | * {@inheritdoc} |
|
| 50 | */ |
|
| 51 | public static function create(ContainerInterface $container, array $configuration, $pluginId, $pluginDefinition) { |
|
| 52 | return new static( |
|
| 53 | $configuration, |
|
| 54 | $pluginId, |
|
| 55 | $pluginDefinition, |
|
| 56 | $container->get('entity_type.manager') |
|
| 57 | ); |
|
| 58 | } |
|
| 59 | ||
| 60 | /** |
|
| 61 | * {@inheritdoc} |
|
| 62 | */ |
|
| 63 | public function resolveValues($value, array $args, ResolveContext $context, ResolveInfo $info) { |
|
| 64 | $storage = $this->entityTypeManager->getStorage('view'); |
|
| 65 | $definition = $this->getPluginDefinition(); |
|
| 66 | ||
| 67 | /** @var \Drupal\views\Entity\View $view */ |
|
| 68 | if ($view = $storage->load($definition['view'])) { |
|
| 69 | $executable = $view->getExecutable(); |
|
| 70 | $executable->setDisplay($definition['display']); |
|
| 71 | ||
| 72 | // Set view contextual filters. |
|
| 73 | /* @see \Drupal\graphql_views\ViewDeriverHelperTrait::getArgumentsInfo() */ |
|
| 74 | if (!empty($definition['arguments_info'])) { |
|
| 75 | $arguments = $this->extractContextualFilters($value, $args); |
|
| 76 | $executable->setArguments($arguments); |
|
| 77 | } |
|
| 78 | ||
| 79 | $filters = $executable->getDisplay()->getOption('filters');; |
|
| 80 | $input = $this->extractExposedInput($value, $args, $filters); |
|
| 81 | $executable->setExposedInput($input); |
|
| 82 | ||
| 83 | // This is a workaround for the Taxonomy Term filter which requires a full |
|
| 84 | // exposed form to be sent OR the display being an attachment to just |
|
| 85 | // accept input values. |
|
| 86 | $executable->is_attachment = TRUE; |
|
| 87 | $executable->exposed_raw_input = $input; |
|
| 88 | ||
| 89 | if (!empty($definition['paged'])) { |
|
| 90 | // Set paging parameters. |
|
| 91 | $executable->setItemsPerPage($args['pageSize']); |
|
| 92 | $executable->setCurrentPage($args['page']); |
|
| 93 | } |
|
| 94 | ||
| 95 | if (isset($args['offset']) && !empty($args['offset'])) { |
|
| 96 | $executable->setOffset($args['offset']); |
|
| 97 | } |
|
| 98 | ||
| 99 | $result = $executable->render($definition['display']); |
|
| 100 | /** @var \Drupal\Core\Cache\CacheableMetadata $cache */ |
|
| 101 | if ($cache = $result['cache']) { |
|
| 102 | $cache->setCacheContexts( |
|
| 103 | array_filter($cache->getCacheContexts(), function ($context) { |
|
| 104 | // Don't emit the url cache contexts. |
|
| 105 | return $context !== 'url' && strpos($context, 'url.') !== 0; |
|
| 106 | }) |
|
| 107 | ); |
|
| 108 | } |
|
| 109 | yield $result; |
|
| 110 | } |
|
| 111 | } |
|
| 112 | ||
| 113 | /** |
|
| 114 | * {@inheritdoc} |
|
| 115 | */ |
|
| 116 | protected function getCacheDependencies(array $result, $value, array $args, ResolveContext $context, ResolveInfo $info) { |
|
| 117 | return array_map(function ($item) { |
|
| 118 | return $item['cache']; |
|
| 119 | }, $result); |
|
| 120 | } |
|
| 121 | ||
| 122 | /** |
|
| 123 | * Retrieves the contextual filter argument from the parent value or args. |
|
| 124 | * |
|
| 125 | * @param $value |
|
| 126 | * The resolved parent value. |
|
| 127 | * @param $args |
|
| 128 | * The arguments provided to the field. |
|
| 129 | * |
|
| 130 | * @return array |
|
| 131 | * An array of arguments containing the contextual filter value from the |
|
| 132 | * parent or provided args if any. |
|
| 133 | */ |
|
| 134 | protected function extractContextualFilters($value, $args) { |
|
| 135 | $definition = $this->getPluginDefinition(); |
|
| 136 | $arguments = []; |
|
| 137 | ||
| 138 | foreach ($definition['arguments_info'] as $argumentId => $argumentInfo) { |
|
| 139 | if (isset($args['contextualFilter'][$argumentId])) { |
|
| 140 | $arguments[$argumentInfo['index']] = $args['contextualFilter'][$argumentId]; |
|
| 141 | } |
|
| 142 | elseif ( |
|
| 143 | $value instanceof EntityInterface && |
|
| 144 | $value->getEntityTypeId() === $argumentInfo['entity_type'] && |
|
| 145 | (empty($argumentInfo['bundles']) || |
|
| 146 | in_array($value->bundle(), $argumentInfo['bundles'], TRUE)) |
|
| 147 | ) { |
|
| 148 | $arguments[$argumentInfo['index']] = $value->id(); |
|
| 149 | } |
|
| 150 | else { |
|
| 151 | $arguments[$argumentInfo['index']] = NULL; |
|
| 152 | } |
|
| 153 | } |
|
| 154 | ||
| 155 | return $arguments; |
|
| 156 | } |
|
| 157 | ||
| 158 | /** |
|
| 159 | * Retrieves sort and filter arguments from the provided field args. |
|
| 160 | * |
|
| 161 | * @param $value |
|
| 162 | * The resolved parent value. |
|
| 163 | * @param $args |
|
| 164 | * The array of arguments provided to the field. |
|
| 165 | * @param $filters |
|
| 166 | * The available filters for the configured view. |
|
| 167 | * |
|
| 168 | * @return array |
|
| 169 | * The array of sort and filter arguments to execute the view with. |
|
| 170 | */ |
|
| 171 | protected function extractExposedInput($value, $args, $filters) { |
|
| 172 | // Prepare arguments for use as exposed form input. |
|
| 173 | $input = array_filter([ |
|
| 174 | // Sorting arguments. |
|
| 175 | 'sort_by' => isset($args['sortBy']) ? $args['sortBy'] : NULL, |
|
| 176 | 'sort_order' => isset($args['sortDirection']) ? $args['sortDirection'] : NULL, |
|
| 177 | ]); |
|
| 178 | ||
| 179 | // If some filters are missing from the input, set them to an empty string |
|
| 180 | // explicitly. Otherwise views module generates "Undefined index" notice. |
|
| 181 | foreach ($filters as $filterKey => $filterRow) { |
|
| 182 | if (!isset($filterRow['expose']['identifier'])) { |
|
| 183 | continue; |
|
| 184 | } |
|
| 185 | ||
| 186 | $inputKey = $filterRow['expose']['identifier']; |
|
| 187 | if (!isset($args['filter'][$inputKey])) { |
|
| 188 | $input[$inputKey] = $filterRow['value']; |
|
| 189 | } else { |
|
| 190 | $input[$inputKey] = $args['filter'][$inputKey]; |
|
| 191 | } |
|
| 192 | } |
|
| 193 | ||
| 194 | return $input; |
|
| 195 | } |
|
| 196 | ||
| 197 | } |
|
| 198 | ||