Security update for Core, with self-updated composer
[yaffs-website] / web / core / lib / Drupal / Core / KeyValueStore / DatabaseStorage.php
1 <?php
2
3 namespace Drupal\Core\KeyValueStore;
4
5 use Drupal\Component\Serialization\SerializationInterface;
6 use Drupal\Core\Database\Query\Merge;
7 use Drupal\Core\Database\Connection;
8 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
9
10 /**
11  * Defines a default key/value store implementation.
12  *
13  * This is Drupal's default key/value store implementation. It uses the database
14  * to store key/value data.
15  */
16 class DatabaseStorage extends StorageBase {
17
18   use DependencySerializationTrait;
19
20   /**
21    * The serialization class to use.
22    *
23    * @var \Drupal\Component\Serialization\SerializationInterface
24    */
25   protected $serializer;
26
27   /**
28    * The database connection.
29    *
30    * @var \Drupal\Core\Database\Connection
31    */
32   protected $connection;
33
34   /**
35    * The name of the SQL table to use.
36    *
37    * @var string
38    */
39   protected $table;
40
41   /**
42    * Overrides Drupal\Core\KeyValueStore\StorageBase::__construct().
43    *
44    * @param string $collection
45    *   The name of the collection holding key and value pairs.
46    * @param \Drupal\Component\Serialization\SerializationInterface $serializer
47    *   The serialization class to use.
48    * @param \Drupal\Core\Database\Connection $connection
49    *   The database connection to use.
50    * @param string $table
51    *   The name of the SQL table to use, defaults to key_value.
52    */
53   public function __construct($collection, SerializationInterface $serializer, Connection $connection, $table = 'key_value') {
54     parent::__construct($collection);
55     $this->serializer = $serializer;
56     $this->connection = $connection;
57     $this->table = $table;
58   }
59
60   /**
61    * {@inheritdoc}
62    */
63   public function has($key) {
64     return (bool) $this->connection->query('SELECT 1 FROM {' . $this->connection->escapeTable($this->table) . '} WHERE collection = :collection AND name = :key', [
65       ':collection' => $this->collection,
66       ':key' => $key,
67     ])->fetchField();
68   }
69
70   /**
71    * {@inheritdoc}
72    */
73   public function getMultiple(array $keys) {
74     $values = [];
75     try {
76       $result = $this->connection->query('SELECT name, value FROM {' . $this->connection->escapeTable($this->table) . '} WHERE name IN ( :keys[] ) AND collection = :collection', [':keys[]' => $keys, ':collection' => $this->collection])->fetchAllAssoc('name');
77       foreach ($keys as $key) {
78         if (isset($result[$key])) {
79           $values[$key] = $this->serializer->decode($result[$key]->value);
80         }
81       }
82     }
83     catch (\Exception $e) {
84       // @todo: Perhaps if the database is never going to be available,
85       // key/value requests should return FALSE in order to allow exception
86       // handling to occur but for now, keep it an array, always.
87     }
88     return $values;
89   }
90
91   /**
92    * {@inheritdoc}
93    */
94   public function getAll() {
95     $result = $this->connection->query('SELECT name, value FROM {' . $this->connection->escapeTable($this->table) . '} WHERE collection = :collection', [':collection' => $this->collection]);
96     $values = [];
97
98     foreach ($result as $item) {
99       if ($item) {
100         $values[$item->name] = $this->serializer->decode($item->value);
101       }
102     }
103     return $values;
104   }
105
106   /**
107    * {@inheritdoc}
108    */
109   public function set($key, $value) {
110     $this->connection->merge($this->table)
111       ->keys([
112         'name' => $key,
113         'collection' => $this->collection,
114       ])
115       ->fields(['value' => $this->serializer->encode($value)])
116       ->execute();
117   }
118
119   /**
120    * {@inheritdoc}
121    */
122   public function setIfNotExists($key, $value) {
123     $result = $this->connection->merge($this->table)
124       ->insertFields([
125         'collection' => $this->collection,
126         'name' => $key,
127         'value' => $this->serializer->encode($value),
128       ])
129       ->condition('collection', $this->collection)
130       ->condition('name', $key)
131       ->execute();
132     return $result == Merge::STATUS_INSERT;
133   }
134
135   /**
136    * {@inheritdoc}
137    */
138   public function rename($key, $new_key) {
139     $this->connection->update($this->table)
140       ->fields(['name' => $new_key])
141       ->condition('collection', $this->collection)
142       ->condition('name', $key)
143       ->execute();
144   }
145
146   /**
147    * {@inheritdoc}
148    */
149   public function deleteMultiple(array $keys) {
150     // Delete in chunks when a large array is passed.
151     while ($keys) {
152       $this->connection->delete($this->table)
153         ->condition('name', array_splice($keys, 0, 1000), 'IN')
154         ->condition('collection', $this->collection)
155         ->execute();
156     }
157   }
158
159   /**
160    * {@inheritdoc}
161    */
162   public function deleteAll() {
163     $this->connection->delete($this->table)
164       ->condition('collection', $this->collection)
165       ->execute();
166   }
167
168 }