cbcef472f3e26c040b9159c1ff67de6961e5a0e6
[yaffs-website] / web / themes / contrib / bootstrap / src / Utility / Storage.php
1 <?php
2 /**
3  * @file
4  * Contains \Drupal\bootstrap\Utility\Storage.
5  */
6
7 namespace Drupal\bootstrap\Utility;
8
9 use Drupal\bootstrap\Bootstrap;
10 use Drupal\Core\Cache\Cache;
11 use Drupal\Core\KeyValueStore\MemoryStorage;
12
13 /**
14  * Theme Storage.
15  *
16  * A hybrid storage solution that utilizes the cache system for complex and
17  * expensive operations performed by a [base] theme.
18  *
19  * Instead of using multiple cache identifiers, which increases the number of
20  * database calls, this storage only executes a single cache call and stores
21  * individual entries in memory as an associative array.
22  *
23  * It also tracks when the data has been modified so it can be saved back to
24  * cache before the system fully shuts down.
25  *
26  * This storage object can be used in `foreach` loops.
27  *
28  * @ingroup utility
29  *
30  * @see \Drupal\bootstrap\Utility\StorageItem
31  */
32 class Storage extends MemoryStorage implements \Iterator {
33
34   /**
35    * The bin (table) data should be stored in (not prefixed with "cache_").
36    *
37    * @var string
38    */
39   protected $bin;
40
41   /**
42    * Flag determining whether or not the cache should be saved to the database.
43    *
44    * @var bool
45    */
46   protected $changed;
47
48   /**
49    * The cache identifier.
50    *
51    * @var string
52    */
53   protected $cid;
54
55   /**
56    * Indicates when the cache should expire.
57    *
58    * @var string
59    */
60   protected $expire;
61
62   /**
63    * Flag determining whether or not object has been initialized yet.
64    *
65    * @var bool
66    */
67   protected $initialized = FALSE;
68
69   /**
70    * Tags to associate with the cached data so it can be properly invalidated.
71    *
72    * @var string
73    */
74   protected $tags;
75
76   /**
77    * {@inheritdoc}
78    */
79   public function __construct($cid, $bin = 'default', $expire = Cache::PERMANENT, $tags = [Bootstrap::CACHE_TAG]) {
80     $this->cid = "theme_registry:storage:$cid";
81     $this->bin = $bin;
82     $this->changed = FALSE;
83     $this->expire = $expire;
84     $this->tags = $tags;
85
86     // Register the cache object to save, if it's needed, on shutdown.
87     drupal_register_shutdown_function([$this, 'save']);
88
89     // Retrieve the cached data.
90     $data = ($cached = \Drupal::cache($bin)->get($this->cid)) && !empty($cached->data) ? $cached->data : [];
91
92     // Set the data.
93     $this->setMultiple($data);
94
95     // Cache has been initialized.
96     $this->initialized = TRUE;
97   }
98
99   /**
100    * Notifies the object that data has changed.
101    */
102   public function changed() {
103     if ($this->initialized) {
104       $this->changed = TRUE;
105     }
106   }
107
108   /**
109    * {@inheritdoc}
110    */
111   public function current() {
112     return current($this->data);
113   }
114
115   /**
116    * {@inheritdoc}
117    */
118   public function delete($key) {
119     parent::delete($key);
120     $this->changed();
121   }
122
123   /**
124    * {@inheritdoc}
125    */
126   public function deleteAll() {
127     parent::deleteAll();
128     $this->changed();
129   }
130
131   /**
132    * {@inheritdoc}
133    */
134   public function deleteMultiple(array $keys) {
135     parent::deleteMultiple($keys);
136     $this->changed();
137   }
138
139   /**
140    * {@inheritdoc}
141    */
142   public function getAll($arrays = TRUE) {
143     $data = $this->data;
144     if ($arrays) {
145       foreach ($data as $key => $value) {
146         if ($value instanceof StorageItem) {
147           $data[$key] = $value->getAll();
148         }
149       }
150     }
151     return $data;
152   }
153
154   /**
155    * Determines if the cache is empty.
156    *
157    * @return bool
158    *   TRUE or FALSE
159    */
160   public function isEmpty() {
161     return empty($this->data);
162   }
163
164   /**
165    * {@inheritdoc}
166    */
167   public function key() {
168     return key($this->data);
169   }
170
171   /**
172    * {@inheritdoc}
173    */
174   public function next() {
175     return next($this->data);
176   }
177
178   /**
179    * {@inheritdoc}
180    */
181   public function rename($key, $new_key) {
182     parent::rename($key, $new_key);
183     $this->changed();
184   }
185
186   /**
187    * {@inheritdoc}
188    */
189   public function rewind() {
190     return reset($this->data);
191   }
192
193   /**
194    * Saves the data back to the database, if necessary, on shutdown.
195    *
196    * This method is automatically invoked during PHP shutdown.
197    *
198    * @internal
199    *
200    * @see \Drupal\bootstrap\Utility\Storage::__construct
201    */
202   public function save() {
203     if ($this->changed) {
204       \Drupal::cache($this->bin)->set($this->cid, $this->getAll(), $this->expire, $this->tags);
205     }
206   }
207
208   /**
209    * {@inheritdoc}
210    */
211   public function set($key, $value) {
212     if (is_array($value)) {
213       $value = new StorageItem($value, $this);
214     }
215     parent::set($key, $value);
216     $this->changed();
217   }
218
219   /**
220    * {@inheritdoc}
221    */
222   public function setIfNotExists($key, $value) {
223     if (!isset($this->data[$key])) {
224       if (is_array($value)) {
225         $value = new StorageItem($value, $this);
226       }
227       $this->data[$key] = $value;
228       $this->changed();
229       return TRUE;
230     }
231     return FALSE;
232   }
233
234   /**
235    * {@inheritdoc}
236    */
237   public function setMultiple(array $data) {
238     foreach ($data as $key => $value) {
239       if (is_array($value)) {
240         $data[$key] = new StorageItem($value, $this);
241       }
242     }
243     parent::setMultiple($data);
244     $this->changed();
245   }
246
247   /**
248    * {@inheritdoc}
249    */
250   public function valid() {
251     return key($this->data) !== NULL;
252   }
253
254 }