3 namespace Drupal\pathauto;
5 use Drupal\Component\Utility\Crypt;
6 use Drupal\Core\TypedData\TypedData;
9 * A property that stores in keyvalue whether an entity should receive an alias.
11 class PathautoState extends TypedData {
14 * An automatic alias should not be created.
19 * An automatic alias should be created.
31 * @var \Drupal\Core\Field\FieldItemInterface
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;
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);
67 * Returns TRUE if a value was set.
69 public function hasValue() {
70 return $this->value !== NULL;
76 public function persist() {
77 \Drupal::keyValue($this->getCollection())
78 ->set(static::getPathautoStateKey($this->parent->getEntity()->id()), $this->getValue());
82 * Deletes the stored state.
84 public function purge() {
85 \Drupal::keyValue($this->getCollection())
86 ->delete(static::getPathautoStateKey($this->parent->getEntity()->id()));
90 * Returns the key value collection that should be used for the given entity.
93 protected function getCollection() {
94 return 'pathauto_state.' . $this->parent->getEntity()->getEntityTypeId();
98 * Deletes the URL aliases for multiple entities of the same type.
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.
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);
110 $pids_by_id[$key] = $pid;
111 unset($pids_by_id[$id]);
114 $states = \Drupal::keyValue("pathauto_state.$entity_type_id")
115 ->getMultiple(array_keys($pids_by_id));
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) {
124 \Drupal::service('pathauto.alias_storage_helper')->deleteMultiple($pids);
128 * Gets the key-value store entry key for 'pathauto_state.*' collections.
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.
138 * The code is inspired by
139 * \Drupal\Core\Cache\DatabaseBackend::normalizeCid().
141 * @param int|string $entity_id
142 * The entity id for which to compute the key.
145 * The key used to store the value in the key-value store.
147 * @see \Drupal\Core\Cache\DatabaseBackend::normalizeCid()
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.
155 return Crypt::hashBase64($entity_id);