Pathologic was missing because of a .git folder inside.
[yaffs-website] / web / modules / contrib / diff / src / DiffBuilderManager.php
1 <?php
2
3 namespace Drupal\diff;
4
5 use Drupal\Core\Cache\CacheBackendInterface;
6 use Drupal\Core\Config\ConfigFactoryInterface;
7 use Drupal\Core\Entity\EntityTypeManagerInterface;
8 use Drupal\Core\Extension\ModuleHandlerInterface;
9 use Drupal\Core\Field\BaseFieldDefinition;
10 use Drupal\Core\Field\FieldDefinitionInterface;
11 use Drupal\Core\Field\FieldStorageDefinitionInterface;
12 use Drupal\Core\Plugin\DefaultPluginManager;
13 use Drupal\field\Entity\FieldStorageConfig;
14
15 /**
16  * Plugin type manager for field diff builders.
17  *
18  * @ingroup field_diff_builder
19  *
20  * Plugin directory Plugin/diff/Field.
21  *
22  * @see \Drupal\diff\Annotation\FieldDiffBuilder
23  * @see \Drupal\diff\FieldDiffBuilderInterface
24  * @see plugin_api
25  */
26 class DiffBuilderManager extends DefaultPluginManager {
27
28   /**
29    * The entity type manager.
30    *
31    * @var \Drupal\Core\Entity\EntityTypeManagerInterface
32    */
33   protected $entityTypeManager;
34
35   /**
36    * Wrapper object for simple configuration from diff.settings.yml.
37    *
38    * @var \Drupal\Core\Config\ImmutableConfig
39    */
40   protected $config;
41
42   /**
43    * Wrapper object for simple configuration from diff.plugins.yml.
44    *
45    * @var \Drupal\Core\Config\ImmutableConfig
46    */
47   protected $pluginsConfig;
48
49   /**
50    * Static cache of field definitions per bundle and entity type.
51    *
52    * @var array
53    */
54   protected $pluginDefinitions;
55
56   /**
57    * Constructs a DiffBuilderManager object.
58    *
59    * @param \Traversable $namespaces
60    *   An object that implements \Traversable which contains the root paths
61    *   keyed by the corresponding namespace to look for plugin implementations.
62    * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
63    *   Cache backend instance to use.
64    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
65    *   The module handler.
66    * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
67    *   The entity type manager.
68    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
69    *   The config factory.
70    */
71   public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory) {
72     parent::__construct('Plugin/diff/Field', $namespaces, $module_handler, '\Drupal\diff\FieldDiffBuilderInterface', 'Drupal\diff\Annotation\FieldDiffBuilder');
73
74     $this->setCacheBackend($cache_backend, 'field_diff_builder_plugins');
75     $this->alterInfo('field_diff_builder_info');
76     $this->entityTypeManager = $entity_type_manager;
77     $this->config = $config_factory->get('diff.settings');
78     $this->pluginsConfig = $config_factory->get('diff.plugins');
79
80   }
81
82   /**
83    * Define whether a field should be displayed or not as a diff change.
84    *
85    * To define if a field should be displayed in the diff comparison, check if
86    * it is revisionable and is not the bundle or revision field of the entity.
87    *
88    * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $field_storage_definition
89    *   The field storage definition.
90    *
91    * @return bool
92    *   TRUE if the field will be displayed.
93    */
94   public function showDiff(FieldStorageDefinitionInterface $field_storage_definition) {
95     $show_diff = FALSE;
96     // Check if the field is revisionable.
97     if ($field_storage_definition->isRevisionable()) {
98       $show_diff = TRUE;
99       // Do not display the field, if it is the bundle or revision field of the
100       // entity.
101       $entity_type = $this->entityTypeManager->getDefinition($field_storage_definition->getTargetEntityTypeId());
102       // @todo Don't hard code fields after: https://www.drupal.org/node/2248983
103       if (in_array($field_storage_definition->getName(), [
104         'revision_log',
105         'revision_uid',
106         $entity_type->getKey('bundle'),
107         $entity_type->getKey('revision'),
108       ])) {
109         $show_diff = FALSE;
110       }
111     }
112     return $show_diff;
113   }
114
115   /**
116    * Creates a plugin instance for a field definition.
117    *
118    * Creates the instance based on the selected plugin for the field.
119    *
120    * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
121    *   The field definition.
122    *
123    * @return \Drupal\diff\FieldDiffBuilderInterface|null
124    *   The plugin instance, NULL if none.
125    */
126   public function createInstanceForFieldDefinition(FieldDefinitionInterface $field_definition) {
127     $selected_plugin = $this->getSelectedPluginForFieldStorageDefinition($field_definition->getFieldStorageDefinition());
128     if ($selected_plugin['type'] != 'hidden') {
129       return $this->createInstance($selected_plugin['type'], $selected_plugin['settings']);
130     }
131     return NULL;
132   }
133
134   /**
135    * Selects a default plugin for a field storage definition.
136    *
137    * Checks if a plugin has been already selected for the field, otherwise
138    * chooses one between the plugins that can be applied to the field.
139    *
140    * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $field_definition
141    *   The field storage definition.
142    *
143    * @return array
144    *   An array with the key type (which contains the plugin ID) and settings.
145    *   The special type hidden indicates that the field should not be shown.
146    */
147   public function getSelectedPluginForFieldStorageDefinition(FieldStorageDefinitionInterface $field_definition) {
148     $plugin_options = $this->getApplicablePluginOptions($field_definition);
149     $field_key = $field_definition->getTargetEntityTypeId() . '.' . $field_definition->getName();
150
151     // Start with the stored configuration, this returns NULL if there is none.
152     $selected_plugin = $this->pluginsConfig->get('fields.' . $field_key);
153
154     // If there is configuration and it is a valid type or exlplicitly set to
155     // hidden, then use that, otherwise try to find a suitable default plugin.
156     if ($selected_plugin && (in_array($selected_plugin['type'], array_keys($plugin_options)) || $selected_plugin['type'] == 'hidden')) {
157       return $selected_plugin + ['settings' => []];
158     }
159     elseif (!empty($plugin_options) && $this->isFieldStorageDefinitionDisplayed($field_definition)) {
160       return ['type' => key($plugin_options), 'settings' => []];
161     }
162     else {
163       return ['type' => 'hidden', 'settings' => []];
164     }
165   }
166
167   /**
168    * Determines if the field is displayed.
169    *
170    * Determines if a field should be displayed when comparing revisions based on
171    * the entity view display if there is no plugin selected for the field.
172    *
173    * @param FieldStorageDefinitionInterface $field_storage_definition
174    *   The field name.
175    *
176    * @return bool
177    *   Whether the field is displayed.
178    */
179   public function isFieldStorageDefinitionDisplayed(FieldStorageDefinitionInterface $field_storage_definition) {
180     if (($field_storage_definition instanceof BaseFieldDefinition && $field_storage_definition->isDisplayConfigurable('view')) || $field_storage_definition instanceof FieldStorageConfig) {
181       $field_key = 'content.' . $field_storage_definition->getName() . '.type';
182       $storage = $this->entityTypeManager->getStorage('entity_view_display');
183       $query = $storage->getQuery()->condition('targetEntityType', $field_storage_definition->getTargetEntityTypeId());
184       if ($field_storage_definition instanceof FieldStorageConfig) {
185         $bundles = $field_storage_definition->getBundles();
186         $query->condition('bundle', (array) $bundles, 'IN');
187       }
188       $result = $query->exists($field_key)->range(0, 1)->execute();
189       return !empty($result) ? TRUE : FALSE;
190     }
191     else {
192       $view_options = (bool) $field_storage_definition->getDisplayOptions('view');
193       return $view_options;
194     }
195   }
196
197   /**
198    * Gets the applicable plugin options for a given field.
199    *
200    * Loop over the plugins that can be applied to the field and builds an array
201    * of possible plugins based on each plugin weight.
202    *
203    * @param FieldStorageDefinitionInterface $field_definition
204    *   The field storage definition.
205    *
206    * @return array
207    *   The plugin option for the given field based on plugin weight.
208    */
209   public function getApplicablePluginOptions(FieldStorageDefinitionInterface $field_definition) {
210     $plugins = $this->getPluginDefinitions();
211     // Build a list of all diff plugins supporting the field type of the field.
212     $plugin_options = [];
213     if (isset($plugins[$field_definition->getType()])) {
214       // Sort the plugins based on their weight.
215       uasort($plugins[$field_definition->getType()], 'Drupal\Component\Utility\SortArray::sortByWeightElement');
216
217       foreach ($plugins[$field_definition->getType()] as $id => $weight) {
218         $definition = $this->getDefinition($id, FALSE);
219         // Check if the plugin is applicable.
220         if (isset($definition['class']) && in_array($field_definition->getType(), $definition['field_types'])) {
221           /** @var FieldDiffBuilderInterface $class */
222           $class = $definition['class'];
223           if ($class::isApplicable($field_definition)) {
224             $plugin_options[$id] = $this->getDefinitions()[$id]['label'];
225           }
226         }
227       }
228     }
229     return $plugin_options;
230   }
231
232   /**
233    * Initializes the local pluginDefinitions property.
234    *
235    * Loop over the plugin definitions and build an array keyed by the field type
236    * that plugins can be applied to.
237    *
238    * @return array
239    *   The initialized plugins array sort by field type.
240    */
241   public function getPluginDefinitions() {
242     if (!isset($this->pluginDefinitions)) {
243       // Get the definition of all the FieldDiffBuilder plugins.
244       foreach ($this->getDefinitions() as $plugin_definition) {
245         if (isset($plugin_definition['field_types'])) {
246           // Iterate through all the field types this plugin supports
247           // and for every such field type add the id of the plugin.
248           if (!isset($plugin_definition['weight'])) {
249             $plugin_definition['weight'] = 0;
250           }
251
252           foreach ($plugin_definition['field_types'] as $id) {
253             $this->pluginDefinitions[$id][$plugin_definition['id']]['weight'] = $plugin_definition['weight'];
254           }
255         }
256       }
257     }
258     return $this->pluginDefinitions;
259   }
260
261   /**
262    * Clear the pluginDefinitions local property array.
263    */
264   public function clearCachedDefinitions() {
265     unset($this->pluginDefinitions);
266   }
267
268 }