From 79f43572fcec3122c65a90d1f5a34fbd42f0cd5a Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Fri, 9 Mar 2012 00:20:35 +0900
Subject: [PATCH] Issue #1469826 by andremolnar: Convert DrupalCacheArray and
 SchemaCache to PSR-0.

---
 core/includes/bootstrap.inc                  | 226 +------------------
 core/includes/theme.inc                      |   4 +-
 core/lib/Drupal/Core/Utility/CacheArray.php  | 210 +++++++++++++++++
 core/lib/Drupal/Core/Utility/SchemaCache.php |  35 +++
 4 files changed, 248 insertions(+), 227 deletions(-)
 create mode 100644 core/lib/Drupal/Core/Utility/CacheArray.php
 create mode 100644 core/lib/Drupal/Core/Utility/SchemaCache.php

diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 0297a74bdf8d..2664a4274372 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -1,6 +1,7 @@
 <?php
 
 use Drupal\Core\Database\Database;
+use Drupal\Core\Utility\SchemaCache;
 use Symfony\Component\ClassLoader\UniversalClassLoader;
 use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
 
@@ -271,206 +272,6 @@
 
 require_once DRUPAL_ROOT . '/core/includes/config.inc';
 
-/**
- * Provides a caching wrapper to be used in place of large array structures.
- *
- * This class should be extended by systems that need to cache large amounts
- * of data and have it represented as an array to calling functions. These
- * arrays can become very large, so ArrayAccess is used to allow different
- * strategies to be used for caching internally (lazy loading, building caches
- * over time etc.). This can dramatically reduce the amount of data that needs
- * to be loaded from cache backends on each request, and memory usage from
- * static caches of that same data.
- *
- * Note that array_* functions do not work with ArrayAccess. Systems using
- * DrupalCacheArray should use this only internally. If providing API functions
- * that return the full array, this can be cached separately or returned
- * directly. However since DrupalCacheArray holds partial content by design, it
- * should be a normal PHP array or otherwise contain the full structure.
- *
- * Note also that due to limitations in PHP prior to 5.3.4, it is impossible to
- * write directly to the contents of nested arrays contained in this object.
- * Only writes to the top-level array elements are possible. So if you
- * previously had set $object['foo'] = array(1, 2, 'bar' => 'baz'), but later
- * want to change the value of 'bar' from 'baz' to 'foobar', you cannot do so
- * a targeted write like $object['foo']['bar'] = 'foobar'. Instead, you must
- * overwrite the entire top-level 'foo' array with the entire set of new
- * values: $object['foo'] = array(1, 2, 'bar' => 'foobar'). Due to this same
- * limitation, attempts to create references to any contained data, nested or
- * otherwise, will fail silently. So $var = &$object['foo'] will not throw an
- * error, and $var will be populated with the contents of $object['foo'], but
- * that data will be passed by value, not reference. For more information on
- * the PHP limitation, see the note in the official PHP documentation at·
- * http://php.net/manual/en/arrayaccess.offsetget.php on
- * ArrayAccess::offsetGet().
- *
- * By default, the class accounts for caches where calling functions might
- * request keys in the array that won't exist even after a cache rebuild. This
- * prevents situations where a cache rebuild would be triggered over and over
- * due to a 'missing' item. These cases are stored internally as a value of
- * NULL. This means that the offsetGet() and offsetExists() methods
- * must be overridden if caching an array where the top level values can
- * legitimately be NULL, and where $object->offsetExists() needs to correctly
- * return (equivalent to array_key_exists() vs. isset()). This should not
- * be necessary in the majority of cases.
- *
- * Classes extending this class must override at least the
- * resolveCacheMiss() method to have a working implementation.
- *
- * offsetSet() is not overridden by this class by default. In practice this
- * means that assigning an offset via arrayAccess will only apply while the
- * object is in scope and will not be written back to the persistent cache.
- * This follows a similar pattern to static vs. persistent caching in
- * procedural code. Extending classes may wish to alter this behaviour, for
- * example by overriding offsetSet() and adding an automatic call to persist().
- *
- * @see SchemaCache
- */
-abstract class DrupalCacheArray implements ArrayAccess {
-
-  /**
-   * A cid to pass to cache()->set() and cache()->get().
-   */
-  protected $cid;
-
-  /**
-   * A bin to pass to cache()->set() and cache()->get().
-   */
-  protected $bin;
-
-  /**
-   * An array of keys to add to the cache at the end of the request.
-   */
-  protected $keysToPersist = array();
-
-  /**
-   * Storage for the data itself.
-   */
-  protected $storage = array();
-
-  /**
-   * Constructs a DrupalCacheArray object.
-   *
-   * @param $cid
-   *   The cid for the array being cached.
-   * @param $bin
-   *   The bin to cache the array.
-   */
-  public function __construct($cid, $bin) {
-    $this->cid = $cid;
-    $this->bin = $bin;
-
-    if ($cached = cache($bin)->get($this->cid)) {
-     $this->storage = $cached->data;
-    }
-  }
-
-  /**
-   * Implements ArrayAccess::offsetExists().
-   */
-  public function offsetExists($offset) {
-    return $this->offsetGet($offset) !== NULL;
-  }
-
-  /**
-   * Implements ArrayAccess::offsetGet().
-   */
-  public function offsetGet($offset) {
-    if (isset($this->storage[$offset]) || array_key_exists($offset, $this->storage)) {
-      return $this->storage[$offset];
-    }
-    else {
-      return $this->resolveCacheMiss($offset);
-    }
-  }
-
-  /**
-   * Implements ArrayAccess::offsetSet().
-   */
-  public function offsetSet($offset, $value) {
-    $this->storage[$offset] = $value;
-  }
-
-  /**
-   * Implements ArrayAccess::offsetUnset().
-   */
-  public function offsetUnset($offset) {
-    unset($this->storage[$offset]);
-  }
-
-  /**
-   * Flags an offset value to be written to the persistent cache.
-   *
-   * If a value is assigned to a cache object with offsetSet(), by default it
-   * will not be written to the persistent cache unless it is flagged with this
-   * method. This allows items to be cached for the duration of a request,
-   * without necessarily writing back to the persistent cache at the end.
-   *
-   * @param $offset
-   *   The array offset that was request.
-   * @param $persist
-   *   Optional boolean to specify whether the offset should be persisted or
-   *   not, defaults to TRUE. When called with $persist = FALSE the offset will
-   *   be unflagged so that it will not written at the end of the request.
-   */
-  protected function persist($offset, $persist = TRUE) {
-    $this->keysToPersist[$offset] = $persist;
-  }
-
-  /**
-   * Resolves a cache miss.
-   *
-   * When an offset is not found in the object, this is treated as a cache
-   * miss. This method allows classes implementing the interface to look up
-   * the actual value and allow it to be cached.
-   *
-   * @param $offset
-   *   The offset that was requested.
-   *
-   * @return
-   *   The value of the offset, or NULL if no value was found.
-   */
-  abstract protected function resolveCacheMiss($offset);
-
-  /**
-   * Writes a value to the persistent cache immediately.
-   *
-   * @param $data
-   *   The data to write to the persistent cache.
-   * @param $lock
-   *   Whether to acquire a lock before writing to cache.
-   */
-  protected function set($data, $lock = TRUE) {
-    // Lock cache writes to help avoid stampedes.
-    // To implement locking for cache misses, override __construct().
-    $lock_name = $this->cid . ':' . $this->bin;
-    if (!$lock || lock_acquire($lock_name)) {
-      if ($cached = cache($this->bin)->get($this->cid)) {
-        $data = $cached->data + $data;
-      }
-      cache($this->bin)->set($this->cid, $data);
-      if ($lock) {
-        lock_release($lock_name);
-      }
-    }
-  }
-
-  /**
-   * Destructs the DrupalCacheArray object.
-   */
-  public function __destruct() {
-    $data = array();
-    foreach ($this->keysToPersist as $offset => $persist) {
-      if ($persist) {
-        $data[$offset] = $this->storage[$offset];
-      }
-    }
-    if (!empty($data)) {
-      $this->set($data);
-    }
-  }
-}
-
 /**
  * Starts the timer with the specified name.
  *
@@ -2982,31 +2783,6 @@ function drupal_get_schema($table = NULL, $rebuild = FALSE) {
   }
 }
 
-/**
- * Extends DrupalCacheArray to allow for dynamic building of the schema cache.
- */
-class SchemaCache extends DrupalCacheArray {
-
-  /**
-   * Constructs a SchemaCache object.
-   */
-  public function __construct() {
-    // Cache by request method.
-    parent::__construct('schema:runtime:' . ($_SERVER['REQUEST_METHOD'] == 'GET'), 'cache');
-  }
-
-  /**
-   * Overrides DrupalCacheArray::resolveCacheMiss().
-   */
-  protected function resolveCacheMiss($offset) {
-    $complete_schema = drupal_get_complete_schema();
-    $value = isset($complete_schema[$offset]) ? $complete_schema[$offset] :  NULL;
-    $this->storage[$offset] = $value;
-    $this->persist($offset);
-    return $value;
-  }
-}
-
 /**
  * Gets the whole database schema.
  *
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index fbb78045ea0e..d044f06882fc 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1,5 +1,5 @@
 <?php
-
+use Drupal\Core\Utility\CacheArray;
 /**
  * @file
  * The theme system, which controls the output of Drupal.
@@ -346,7 +346,7 @@ function drupal_theme_rebuild() {
  * that are actually in use on the site. On cache misses the complete
  * theme registry is loaded and used to update the run-time cache.
  */
-class ThemeRegistry Extends DrupalCacheArray {
+class ThemeRegistry Extends CacheArray {
 
   /**
    * Whether the partial registry can be persisted to the cache.
diff --git a/core/lib/Drupal/Core/Utility/CacheArray.php b/core/lib/Drupal/Core/Utility/CacheArray.php
new file mode 100644
index 000000000000..8f98b72f0d7a
--- /dev/null
+++ b/core/lib/Drupal/Core/Utility/CacheArray.php
@@ -0,0 +1,210 @@
+<?php
+
+/**
+ * @file
+ * Definition of CacheArray
+ */
+
+namespace Drupal\Core\Utility;
+
+use ArrayAccess;
+
+/**
+ * Provides a caching wrapper to be used in place of large array structures.
+ *
+ * This class should be extended by systems that need to cache large amounts
+ * of data and have it represented as an array to calling functions. These
+ * arrays can become very large, so ArrayAccess is used to allow different
+ * strategies to be used for caching internally (lazy loading, building caches
+ * over time etc.). This can dramatically reduce the amount of data that needs
+ * to be loaded from cache backends on each request, and memory usage from
+ * static caches of that same data.
+ *
+ * Note that array_* functions do not work with ArrayAccess. Systems using
+ * DrupalCacheArray should use this only internally. If providing API functions
+ * that return the full array, this can be cached separately or returned
+ * directly. However since DrupalCacheArray holds partial content by design, it
+ * should be a normal PHP array or otherwise contain the full structure.
+ *
+ * Note also that due to limitations in PHP prior to 5.3.4, it is impossible to
+ * write directly to the contents of nested arrays contained in this object.
+ * Only writes to the top-level array elements are possible. So if you
+ * previously had set $object['foo'] = array(1, 2, 'bar' => 'baz'), but later
+ * want to change the value of 'bar' from 'baz' to 'foobar', you cannot do so
+ * a targeted write like $object['foo']['bar'] = 'foobar'. Instead, you must
+ * overwrite the entire top-level 'foo' array with the entire set of new
+ * values: $object['foo'] = array(1, 2, 'bar' => 'foobar'). Due to this same
+ * limitation, attempts to create references to any contained data, nested or
+ * otherwise, will fail silently. So $var = &$object['foo'] will not throw an
+ * error, and $var will be populated with the contents of $object['foo'], but
+ * that data will be passed by value, not reference. For more information on
+ * the PHP limitation, see the note in the official PHP documentation atá
+ * http://php.net/manual/en/arrayaccess.offsetget.php on
+ * ArrayAccess::offsetGet().
+ *
+ * By default, the class accounts for caches where calling functions might
+ * request keys in the array that won't exist even after a cache rebuild. This
+ * prevents situations where a cache rebuild would be triggered over and over
+ * due to a 'missing' item. These cases are stored internally as a value of
+ * NULL. This means that the offsetGet() and offsetExists() methods
+ * must be overridden if caching an array where the top level values can
+ * legitimately be NULL, and where $object->offsetExists() needs to correctly
+ * return (equivalent to array_key_exists() vs. isset()). This should not
+ * be necessary in the majority of cases.
+ *
+ * Classes extending this class must override at least the
+ * resolveCacheMiss() method to have a working implementation.
+ *
+ * offsetSet() is not overridden by this class by default. In practice this
+ * means that assigning an offset via arrayAccess will only apply while the
+ * object is in scope and will not be written back to the persistent cache.
+ * This follows a similar pattern to static vs. persistent caching in
+ * procedural code. Extending classes may wish to alter this behaviour, for
+ * example by overriding offsetSet() and adding an automatic call to persist().
+ *
+ * @see SchemaCache
+ */
+abstract class CacheArray implements ArrayAccess {
+
+  /**
+   * A cid to pass to cache()->set() and cache()->get().
+   */
+  protected $cid;
+
+  /**
+   * A bin to pass to cache()->set() and cache()->get().
+   */
+  protected $bin;
+
+  /**
+   * An array of keys to add to the cache at the end of the request.
+   */
+  protected $keysToPersist = array();
+
+  /**
+   * Storage for the data itself.
+   */
+  protected $storage = array();
+
+  /**
+   * Constructs a DrupalCacheArray object.
+   *
+   * @param $cid
+   *   The cid for the array being cached.
+   * @param $bin
+   *   The bin to cache the array.
+   */
+  public function __construct($cid, $bin) {
+    $this->cid = $cid;
+    $this->bin = $bin;
+
+    if ($cached = cache($bin)->get($this->cid)) {
+     $this->storage = $cached->data;
+    }
+  }
+
+  /**
+   * Implements ArrayAccess::offsetExists().
+   */
+  public function offsetExists($offset) {
+    return $this->offsetGet($offset) !== NULL;
+  }
+
+  /**
+   * Implements ArrayAccess::offsetGet().
+   */
+  public function offsetGet($offset) {
+    if (isset($this->storage[$offset]) || array_key_exists($offset, $this->storage)) {
+      return $this->storage[$offset];
+    }
+    else {
+      return $this->resolveCacheMiss($offset);
+    }
+  }
+
+  /**
+   * Implements ArrayAccess::offsetSet().
+   */
+  public function offsetSet($offset, $value) {
+    $this->storage[$offset] = $value;
+  }
+
+  /**
+   * Implements ArrayAccess::offsetUnset().
+   */
+  public function offsetUnset($offset) {
+    unset($this->storage[$offset]);
+  }
+
+  /**
+   * Flags an offset value to be written to the persistent cache.
+   *
+   * If a value is assigned to a cache object with offsetSet(), by default it
+   * will not be written to the persistent cache unless it is flagged with this
+   * method. This allows items to be cached for the duration of a request,
+   * without necessarily writing back to the persistent cache at the end.
+   *
+   * @param $offset
+   *   The array offset that was request.
+   * @param $persist
+   *   Optional boolean to specify whether the offset should be persisted or
+   *   not, defaults to TRUE. When called with $persist = FALSE the offset will
+   *   be unflagged so that it will not written at the end of the request.
+   */
+  protected function persist($offset, $persist = TRUE) {
+    $this->keysToPersist[$offset] = $persist;
+  }
+
+  /**
+   * Resolves a cache miss.
+   *
+   * When an offset is not found in the object, this is treated as a cache
+   * miss. This method allows classes implementing the interface to look up
+   * the actual value and allow it to be cached.
+   *
+   * @param $offset
+   *   The offset that was requested.
+   *
+   * @return
+   *   The value of the offset, or NULL if no value was found.
+   */
+  abstract protected function resolveCacheMiss($offset);
+
+  /**
+   * Writes a value to the persistent cache immediately.
+   *
+   * @param $data
+   *   The data to write to the persistent cache.
+   * @param $lock
+   *   Whether to acquire a lock before writing to cache.
+   */
+  protected function set($data, $lock = TRUE) {
+    // Lock cache writes to help avoid stampedes.
+    // To implement locking for cache misses, override __construct().
+    $lock_name = $this->cid . ':' . $this->bin;
+    if (!$lock || lock_acquire($lock_name)) {
+      if ($cached = cache($this->bin)->get($this->cid)) {
+        $data = $cached->data + $data;
+      }
+      cache($this->bin)->set($this->cid, $data);
+      if ($lock) {
+        lock_release($lock_name);
+      }
+    }
+  }
+
+  /**
+   * Destructs the DrupalCacheArray object.
+   */
+  public function __destruct() {
+    $data = array();
+    foreach ($this->keysToPersist as $offset => $persist) {
+      if ($persist) {
+        $data[$offset] = $this->storage[$offset];
+      }
+    }
+    if (!empty($data)) {
+      $this->set($data);
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/Utility/SchemaCache.php b/core/lib/Drupal/Core/Utility/SchemaCache.php
new file mode 100644
index 000000000000..d8c3a5019d77
--- /dev/null
+++ b/core/lib/Drupal/Core/Utility/SchemaCache.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Definition of SchemaCache
+ */
+
+namespace Drupal\Core\Utility;
+
+use Drupal\Core\Utility\CacheArray;
+
+/**
+ * Extends DrupalCacheArray to allow for dynamic building of the schema cache.
+ */
+class SchemaCache extends CacheArray {
+
+  /**
+   * Constructs a SchemaCache object.
+   */
+  public function __construct() {
+    // Cache by request method.
+    parent::__construct('schema:runtime:' . ($_SERVER['REQUEST_METHOD'] == 'GET'), 'cache');
+  }
+
+  /**
+   * Overrides DrupalCacheArray::resolveCacheMiss().
+   */
+  protected function resolveCacheMiss($offset) {
+    $complete_schema = drupal_get_complete_schema();
+    $value = isset($complete_schema[$offset]) ? $complete_schema[$offset] :  NULL;
+    $this->storage[$offset] = $value;
+    $this->persist($offset);
+    return $value;
+  }
+}
-- 
GitLab