diff --git a/cache/lib.php b/cache/lib.php
index 001cd431439..1ee4100e7cf 100644
--- a/cache/lib.php
+++ b/cache/lib.php
@@ -148,4 +148,81 @@ class cache_exception extends moodle_exception {
// This may appear like a useless override but you will notice that we have set a MUCH more useful default for $module.
parent::__construct($errorcode, $module, $link, $a, $debuginfo);
}
+}
+
+/**
+ * An array of cacheable objects.
+ *
+ * This class allows a developer to create an array of cacheable objects and store that.
+ * The cache API doesn't check items within an array to see whether they are cacheable. Such a check would be very costly to both
+ * arrays using cacheable object and those that don't.
+ * Instead the developer must explicitly use a cacheable_object_array instance.
+ *
+ * The following is one example of how this class can be used.
+ *
+ * $data = array();
+ * $data[] = new cacheable_object('one');
+ * $data[] = new cacheable_object('two');
+ * $data[] = new cacheable_object('three');
+ * $cache->set(new cacheable_object_array($data));
+ *
+ * Another example would be
+ *
+ * $data = new cacheable_object_array();
+ * $data[] = new cacheable_object('one');
+ * $data[] = new cacheable_object('two');
+ * $data[] = new cacheable_object('three');
+ * $cache->set($data);
+ *
+ *
+ * @copyright 2012 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class cacheable_object_array extends ArrayObject implements cacheable_object {
+
+ /**
+ * Constructs a new array object instance.
+ * @param array $items
+ */
+ final public function __construct(array $items = array()) {
+ parent::__construct($items, ArrayObject::STD_PROP_LIST);
+ }
+
+ /**
+ * Returns the data to cache for this object.
+ *
+ * @return array An array of cache_cached_object instances.
+ * @throws coding_exception
+ */
+ final public function prepare_to_cache() {
+ $result = array();
+ foreach ($this as $key => $value) {
+ if ($value instanceof cacheable_object) {
+ $value = new cache_cached_object($value);
+ } else {
+ throw new coding_exception('Only cacheable_object instances can be added to a cacheable_array');
+ }
+ $result[$key] = $value;
+ }
+ return $result;
+ }
+
+ /**
+ * Returns the cacheable_object_array that was originally sent to the cache.
+ *
+ * @param array $data
+ * @return cacheable_object_array
+ * @throws coding_exception
+ */
+ final static public function wake_from_cache($data) {
+ if (!is_array($data)) {
+ throw new coding_exception('Invalid data type when reviving cacheable_array data');
+ }
+ $result = array();
+ foreach ($data as $key => $value) {
+ $result[$key] = $value->restore_object();
+ }
+ $class = __CLASS__;
+ return new $class($result);
+ }
}
\ No newline at end of file
diff --git a/cache/tests/cache_test.php b/cache/tests/cache_test.php
index edef90db99d..e7fe8369204 100644
--- a/cache/tests/cache_test.php
+++ b/cache/tests/cache_test.php
@@ -231,6 +231,23 @@ class cache_phpunit_tests extends advanced_testcase {
$this->assertEquals('red_ptc_wfc', $result->property1);
$this->assertEquals('blue_ptc_wfc', $result->property2);
+ // Test array of objects
+ $specobject = new cache_phpunit_dummy_object('red', 'blue');
+ $data = new cacheable_object_array(array(
+ clone($specobject),
+ clone($specobject),
+ clone($specobject))
+ );
+ $this->assertTrue($cache->set($key, $data));
+ $result = $cache->get($key);
+ $this->assertInstanceOf('cacheable_object_array', $result);
+ $this->assertCount(3, $data);
+ foreach ($result as $item) {
+ $this->assertInstanceOf('cache_phpunit_dummy_object', $item);
+ $this->assertEquals('red_ptc_wfc', $item->property1);
+ $this->assertEquals('blue_ptc_wfc', $item->property2);
+ }
+
// Test set many.
$cache->set_many(array('key1' => 'data1', 'key2' => 'data2'));
$this->assertEquals('data1', $cache->get('key1'));