466db1c3877176bba5ccb21dd563782c0b6d5980
[yaffs-website] / web / modules / contrib / pathauto / src / PathautoState.php
1 <?php
2
3 namespace Drupal\pathauto;
4
5 use Drupal\Component\Utility\Crypt;
6 use Drupal\Core\TypedData\TypedData;
7
8 /**
9  * A property that stores in keyvalue whether an entity should receive an alias.
10  */
11 class PathautoState extends TypedData {
12
13   /**
14    * An automatic alias should not be created.
15    */
16   const SKIP = 0;
17
18   /**
19    * An automatic alias should be created.
20    */
21   const CREATE = 1;
22
23   /**
24    * Pathauto state.
25    *
26    * @var int
27    */
28   protected $value;
29
30   /**
31    * @var \Drupal\Core\Field\FieldItemInterface
32    */
33   protected $parent;
34
35   /**
36    * {@inheritdoc}
37    */
38   public function getValue() {
39     if ($this->value === NULL) {
40       // If no value has been set or loaded yet, try to load a value if this
41       // entity has already been saved.
42       $this->value = \Drupal::keyValue($this->getCollection())
43         ->get(static::getPathautoStateKey($this->parent->getEntity()->id()));
44       // If it was not yet saved or no value was found, then set the flag to
45       // create the alias if there is a matching pattern.
46       if ($this->value === NULL) {
47         $entity = $this->parent->getEntity();
48         $pattern = \Drupal::service('pathauto.generator')->getPatternByEntity($entity);
49         $this->value = !empty($pattern) ? static::CREATE : static::SKIP;
50       }
51     }
52     return $this->value;
53   }
54
55   /**
56    * {@inheritdoc}
57    */
58   public function setValue($value, $notify = TRUE) {
59     $this->value = $value;
60     // Notify the parent of any changes.
61     if ($notify && isset($this->parent)) {
62       $this->parent->onChange($this->name);
63     }
64   }
65
66   /**
67    * Returns TRUE if a value was set.
68    */
69   public function hasValue() {
70     return $this->value !== NULL;
71   }
72
73   /**
74    * Persists the state.
75    */
76   public function persist() {
77     \Drupal::keyValue($this->getCollection())
78       ->set(static::getPathautoStateKey($this->parent->getEntity()->id()), $this->getValue());
79   }
80
81   /**
82    * Deletes the stored state.
83    */
84   public function purge() {
85     \Drupal::keyValue($this->getCollection())
86       ->delete(static::getPathautoStateKey($this->parent->getEntity()->id()));
87   }
88
89   /**
90    * Returns the key value collection that should be used for the given entity.
91    * @return string
92    */
93   protected function getCollection() {
94     return 'pathauto_state.' . $this->parent->getEntity()->getEntityTypeId();
95   }
96
97   /**
98    * Deletes the URL aliases for multiple entities of the same type.
99    *
100    * @param string $entity_type_id
101    *   The entity type ID of entities being deleted.
102    * @param int[] $pids_by_id
103    *   A list of path IDs keyed by entity ID.
104    */
105   public static function bulkDelete($entity_type_id, array $pids_by_id) {
106     foreach ($pids_by_id as $id => $pid) {
107       // Some key-values store entries have computed keys.
108       $key = static::getPathautoStateKey($id);
109       if ($key !== $id) {
110         $pids_by_id[$key] = $pid;
111         unset($pids_by_id[$id]);
112       }
113     }
114     $states = \Drupal::keyValue("pathauto_state.$entity_type_id")
115       ->getMultiple(array_keys($pids_by_id));
116
117     $pids = [];
118     foreach ($pids_by_id as $id => $pid) {
119       // Only delete aliases that were created by this module.
120       if (isset($states[$id]) && $states[$id] == PathautoState::CREATE) {
121         $pids[] = $pid;
122       }
123     }
124     \Drupal::service('pathauto.alias_storage_helper')->deleteMultiple($pids);
125   }
126
127   /**
128    * Gets the key-value store entry key for 'pathauto_state.*' collections.
129    *
130    * Normally we want to use the entity ID as key for 'pathauto_state.*'
131    * collection entries. But some entity types may use string IDs. When such IDs
132    * are exceeding 128 characters, which is the limit for the 'name' column in
133    * the {key_value} table, the insertion of the ID in {key_value} will fail.
134    * Thus we test if we can use the plain ID or we need to store a hashed
135    * version of the entity ID. Also, it is not possible to rely on the UUID as
136    * entity types might not have one or might use a non-standard format.
137    *
138    * The code is inspired by
139    * \Drupal\Core\Cache\DatabaseBackend::normalizeCid().
140    *
141    * @param int|string $entity_id
142    *   The entity id for which to compute the key.
143    *
144    * @return int|string
145    *   The key used to store the value in the key-value store.
146    *
147    * @see \Drupal\Core\Cache\DatabaseBackend::normalizeCid()
148    */
149   public static function getPathautoStateKey($entity_id) {
150     $entity_id_is_ascii = mb_check_encoding($entity_id, 'ASCII');
151     if ($entity_id_is_ascii && strlen($entity_id) <= 128) {
152       // The original entity ID, if it's an ASCII of 128 characters or less.
153       return $entity_id;
154     }
155     return Crypt::hashBase64($entity_id);
156   }
157
158 }