From a2e8083bebbce47e07a9613ee71132c1b1eb0308 Mon Sep 17 00:00:00 2001
From: Carsten Brandt <mail@cebe.cc>
Date: Mon, 11 Aug 2014 23:48:04 +0200
Subject: [PATCH] Created ArrayCache class

- can be used to enable caching in a request without the need for any storage
- useful for example in complex console tasks that should still be independed
---
 framework/CHANGELOG.md                          |  1 +
 framework/caching/ArrayCache.php                | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/unit/framework/caching/ArrayCacheTest.php | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 tests/unit/framework/caching/CacheTestCase.php  | 18 ++++++++++++++++++
 4 files changed, 154 insertions(+)
 create mode 100644 framework/caching/ArrayCache.php
 create mode 100644 tests/unit/framework/caching/ArrayCacheTest.php

diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md
index 163fd91..53ad035 100644
--- a/framework/CHANGELOG.md
+++ b/framework/CHANGELOG.md
@@ -233,6 +233,7 @@ Yii Framework 2 Change Log
 - New #3911: Added `yii\behaviors\SluggableBehavior` that fills the specified model attribute with the transliterated and adjusted version to use in URLs (creocoder)
 - New #4193: Added `yii\filters\Cors` CORS filter to allow Cross Origin Resource Sharing (pgaultier)
 - New: Added `yii\base\InvalidValueException` (qiangxue)
+- New: Added `yii\caching\ArrayCache` (cebe)
 
 
 2.0.0-beta April 13, 2014
diff --git a/framework/caching/ArrayCache.php b/framework/caching/ArrayCache.php
new file mode 100644
index 0000000..7295fc0
--- /dev/null
+++ b/framework/caching/ArrayCache.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright (c) 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ */
+
+namespace yii\caching;
+
+/**
+ * ArrayCache provides caching for the current request only by storing the values in an array.
+ *
+ * See [[Cache]] for common cache operations that ArrayCache supports.
+ *
+ * Unlike the [[Cache]], ArrayCache allows the expire parameter of [[set]], [[add]], [[mset]] and [[madd]] to
+ * be a floating point number, so you may specify the time in milliseconds (e.g. 0.1 will be 100 milliseconds).
+ *
+ * @author Carsten Brandt <mail@cebe.cc>
+ * @since 2.0
+ */
+class ArrayCache extends Cache
+{
+    private $_cache;
+
+
+    /**
+     * @inheritdoc
+     */
+    public function exists($key)
+    {
+        $key = $this->buildKey($key);
+        return isset($this->_cache[$key]) && ($this->_cache[$key][1] === 0 || $this->_cache[$key][1] > microtime(true));
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function getValue($key)
+    {
+        if (isset($this->_cache[$key]) && ($this->_cache[$key][1] === 0 || $this->_cache[$key][1] > microtime(true))) {
+            return $this->_cache[$key][0];
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function setValue($key, $value, $duration)
+    {
+        $this->_cache[$key] = [$value, $duration === 0 ? 0 : microtime(true) + $duration];
+        return true;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function addValue($key, $value, $duration)
+    {
+        if (isset($this->_cache[$key]) && ($this->_cache[$key][1] === 0 || $this->_cache[$key][1] > microtime(true))) {
+            return false;
+        } else {
+            $this->_cache[$key] = [$value, $duration === 0 ? 0 : microtime(true) + $duration];
+            return true;
+        }
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function deleteValue($key)
+    {
+        unset($this->_cache[$key]);
+        return true;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    protected function flushValues()
+    {
+        $this->_cache = [];
+        return true;
+    }
+}
diff --git a/tests/unit/framework/caching/ArrayCacheTest.php b/tests/unit/framework/caching/ArrayCacheTest.php
new file mode 100644
index 0000000..5ec7d73
--- /dev/null
+++ b/tests/unit/framework/caching/ArrayCacheTest.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace yiiunit\framework\caching;
+
+use yii\caching\ArrayCache;
+
+/**
+ * Class for testing file cache backend
+ * @group caching
+ */
+class ArrayCacheTest extends CacheTestCase
+{
+    private $_cacheInstance = null;
+
+    /**
+     * @return ArrayCache
+     */
+    protected function getCacheInstance()
+    {
+        if ($this->_cacheInstance === null) {
+            $this->_cacheInstance = new ArrayCache();
+        }
+        return $this->_cacheInstance;
+    }
+
+    public function testExpire()
+    {
+        $cache = $this->getCacheInstance();
+
+        static::$microtime = \microtime(true);
+        $this->assertTrue($cache->set('expire_test', 'expire_test', 2));
+        static::$microtime++;
+        $this->assertEquals('expire_test', $cache->get('expire_test'));
+        static::$microtime++;
+        $this->assertFalse($cache->get('expire_test'));
+    }
+
+    public function testExpireAdd()
+    {
+        $cache = $this->getCacheInstance();
+
+        static::$microtime = \microtime(true);
+        $this->assertTrue($cache->add('expire_testa', 'expire_testa', 2));
+        static::$microtime++;
+        $this->assertEquals('expire_testa', $cache->get('expire_testa'));
+        static::$microtime++;
+        $this->assertFalse($cache->get('expire_testa'));
+    }
+}
diff --git a/tests/unit/framework/caching/CacheTestCase.php b/tests/unit/framework/caching/CacheTestCase.php
index 40c7705..f31d600 100644
--- a/tests/unit/framework/caching/CacheTestCase.php
+++ b/tests/unit/framework/caching/CacheTestCase.php
@@ -11,8 +11,19 @@ function time()
     return \yiiunit\framework\caching\CacheTestCase::$time ?: \time();
 }
 
+/**
+ * Mock for the microtime() function for caching classes
+ * @param bool $float
+ * @return float
+ */
+function microtime($float = false)
+{
+    return \yiiunit\framework\caching\CacheTestCase::$microtime ?: \microtime($float);
+}
+
 namespace yiiunit\framework\caching;
 
+use yii\caching\Cache;
 use yiiunit\TestCase;
 
 /**
@@ -25,6 +36,12 @@ abstract class CacheTestCase extends TestCase
      * Null means normal time() behavior.
      */
     public static $time;
+    /**
+     * @var float virtual time to be returned by mocked microtime() function.
+     * Null means normal microtime() behavior.
+     */
+    public static $microtime;
+
 
     /**
      * @return Cache
@@ -40,6 +57,7 @@ abstract class CacheTestCase extends TestCase
     protected function tearDown()
     {
         static::$time = null;
+        static::$microtime = null;
     }
 
     /**
--
libgit2 0.27.1