Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrobocoder <anthon.pang@gmail.com>2011-03-05 21:28:08 +0300
committerrobocoder <anthon.pang@gmail.com>2011-03-05 21:28:08 +0300
commit6f7dccc9c68e18c834246ce472e0f70b3844e000 (patch)
treecbb7496f777f40e4e4fb8f5a7dff5f28f9db53a2
parent410da5dae2ca94a97faeb924414360e381bf277d (diff)
fixes #2150
git-svn-id: http://dev.piwik.org/svn/trunk@4030 59fd770c-687e-43c8-a1e3-f5a4ff64c105
-rw-r--r--core/Option.php81
-rw-r--r--tests/core/Option.test.php165
2 files changed, 240 insertions, 6 deletions
diff --git a/core/Option.php b/core/Option.php
index c8147a23ce..39e12c98d3 100644
--- a/core/Option.php
+++ b/core/Option.php
@@ -21,9 +21,13 @@
class Piwik_Option
{
private $all = array();
+ private $loaded = false;
static private $instance = null;
+
/**
+ * Singleton
+ *
* @return Piwik_Option
*/
static public function getInstance()
@@ -37,6 +41,12 @@ class Piwik_Option
private function __construct() {}
+ /**
+ * Returns the option value for the requested option $name, fetching from database, if not in cache.
+ *
+ * @param string $name Key
+ * @return string|false Value or false, if not found
+ */
public function get($name)
{
$this->autoload();
@@ -55,6 +65,13 @@ class Piwik_Option
return $value;
}
+ /**
+ * Sets the option value in the database and cache
+ *
+ * @param string $name
+ * @param string $value
+ * @param int $autoload if set to 1, this option value will be automatically loaded; should be set to 1 for options that will always be used in the Piwik request.
+ */
public function set($name, $value, $autoload = 0)
{
$autoload = (int)$autoload;
@@ -64,14 +81,64 @@ class Piwik_Option
array($name, $value, $autoload, $value));
$this->all[$name] = $value;
}
-
+
+ /**
+ * Delete key-value pair from database and reload cache.
+ *
+ * @param string $name Key to match exactly
+ * @param string $value Optional value
+ */
+ public function delete($name, $value = null)
+ {
+ $sql = 'DELETE FROM '. Piwik_Common::prefixTable('option') . ' WHERE option_name = ?';
+ $bind[] = $name;
+
+ if(isset($value))
+ {
+ $sql .= ' AND option_value = ?';
+ $bind[] = $value;
+ }
+
+ Piwik_Query($sql, $bind);
+
+ $this->clearCache();
+ }
+
+ /**
+ * Delete key-value pair(s) from database and reload cache.
+ * The supplied pattern should use '%' as wildcards, and literal '_' should be escaped.
+ *
+ * @param string $name Pattern of key to match.
+ * @param string $value Optional value
+ */
+ public function deleteLike($name, $value = null)
+ {
+ $sql = 'DELETE FROM `'. Piwik_Common::prefixTable('option') . '` WHERE option_name LIKE ?';
+ $bind[] = $name;
+
+ if(isset($value))
+ {
+ $sql .= ' AND option_value = ?';
+ $bind[] = $value;
+ }
+
+ Piwik_Query($sql, $bind);
+
+ $this->clearCache();
+ }
+
+ /**
+ * Initialize cache with autoload settings.
+ *
+ * @param bool $forceReload Forces a reload if true; default is false
+ */
private function autoload()
{
- static $loaded = false;
- if($loaded)
+ if($this->loaded)
{
return;
}
+
$all = Piwik_FetchAll('SELECT option_value, option_name
FROM `'. Piwik_Common::prefixTable('option') . '`
WHERE autoload = 1');
@@ -79,7 +146,8 @@ class Piwik_Option
{
$this->all[$option['option_name']] = $option['option_value'];
}
- $loaded = true;
+
+ $this->loaded = true;
}
/**
@@ -90,6 +158,7 @@ class Piwik_Option
*/
public function clearCache()
{
+ $this->loaded = false;
$this->all = array();
}
}
@@ -97,8 +166,8 @@ class Piwik_Option
/**
* Returns the option value for the requested option $name
*
- * @param string $name
- * @return string|false if not found
+ * @param string $name Key
+ * @return string|false Value or false, if not found
*/
function Piwik_GetOption($name)
{
diff --git a/tests/core/Option.test.php b/tests/core/Option.test.php
new file mode 100644
index 0000000000..8a9cf45e4c
--- /dev/null
+++ b/tests/core/Option.test.php
@@ -0,0 +1,165 @@
+<?php
+if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
+{
+ require_once dirname(__FILE__)."/../../tests/config_test.php";
+}
+
+require_once 'Database.test.php';
+require_once "Option.php";
+
+class Test_Piwik_Option extends Test_Database
+{
+ public function test_get()
+ {
+ // empty table, expect false (i.e., not found)
+ $this->assertTrue( Piwik_Option::getInstance()->get('anonymous_defaultReport') === false );
+
+ // populate table, expect '1' (i.e., found)
+ Piwik_Query("INSERT INTO ".Piwik_Common::prefixTable('option')." VALUES ('anonymous_defaultReport', '1', false)");
+ $this->assertTrue( Piwik_Option::getInstance()->get('anonymous_defaultReport') === '1' );
+
+ // delete row (bypassing API), expect '1' (i.e., from cache)
+ Piwik_Query("DELETE FROM ".Piwik_Common::prefixTable('option')." WHERE option_name = ?", array('anonymous_defaultReport'));
+ $this->assertTrue( Piwik_Option::getInstance()->get('anonymous_defaultReport') === '1' );
+
+ // force cache reload, expect false (i.e., not found)
+ Piwik_Option::getInstance()->clearCache();
+ $this->assertTrue( Piwik_Option::getInstance()->get('anonymous_defaultReport') === false );
+ }
+
+ public function test_getOption()
+ {
+ // empty table, expect false (i.e., not found)
+ $this->assertTrue( Piwik_GetOption('anonymous_defaultReport') === false );
+
+ // populate table, expect '1' (i.e., found)
+ Piwik_Query("INSERT INTO ".Piwik_Common::prefixTable('option')." VALUES ('anonymous_defaultReport', '1',true)");
+ $this->assertTrue( Piwik_GetOption('anonymous_defaultReport') === '1' );
+
+ // delete row (bypassing API), expect '1' (i.e., from cache)
+ Piwik_Query("DELETE FROM ".Piwik_Common::prefixTable('option')." WHERE option_name = ?", array('anonymous_defaultReport'));
+ $this->assertTrue( Piwik_GetOption('anonymous_defaultReport') === '1' );
+
+ // force cache reload, expect false (i.e., not found)
+ Piwik_Option::getInstance()->clearCache();
+ $this->assertTrue( Piwik_GetOption('anonymous_defaultReport') === false );
+ }
+
+ public function test_set()
+ {
+ // empty table, expect false (i.e., not found)
+ $this->assertTrue( Piwik_GetOption('anonymous_defaultReport') === false );
+
+ // populate table, expect '1'
+ Piwik_Option::getInstance()->set('anonymous_defaultReport', '1', true);
+ $this->assertTrue( Piwik_Option::getInstance()->get('anonymous_defaultReport') === '1' );
+ }
+
+ public function test_setOption()
+ {
+ // empty table, expect false (i.e., not found)
+ $this->assertTrue( Piwik_GetOption('anonymous_defaultReport') === false );
+
+ // populate table, expect '1'
+ Piwik_SetOption('anonymous_defaultReport', '1', false);
+ $this->assertTrue( Piwik_Option::getInstance()->get('anonymous_defaultReport') === '1' );
+ }
+
+ public function test_delete()
+ {
+ // empty table, expect false (i.e., not found)
+ $this->assertTrue( Piwik_GetOption('anonymous_defaultReport') === false );
+ $this->assertTrue( Piwik_GetOption('admin_defaultReport') === false );
+
+ // populate table, expect '1'
+ Piwik_SetOption('anonymous_defaultReport', '1', true);
+ Piwik_Option::getInstance()->delete('_defaultReport');
+ $this->assertTrue( Piwik_Option::getInstance()->get('anonymous_defaultReport') === '1' );
+
+ // populate table, expect '2'
+ Piwik_SetOption('admin_defaultReport', '2', false);
+ Piwik_Option::getInstance()->delete('_defaultReport');
+ $this->assertTrue( Piwik_Option::getInstance()->get('admin_defaultReport') === '2' );
+
+ // delete with non-matching value, expect '1'
+ Piwik_Option::getInstance()->delete('anonymous_defaultReport', '2');
+ $this->assertTrue( Piwik_Option::getInstance()->get('anonymous_defaultReport') === '1' );
+
+ // delete with matching value, expect false
+ Piwik_Option::getInstance()->delete('anonymous_defaultReport', '1');
+ $this->assertTrue( Piwik_Option::getInstance()->get('anonymous_defaultReport') === false );
+
+ // this shouldn't have been deleted, expect '2'
+ $this->assertTrue( Piwik_Option::getInstance()->get('admin_defaultReport') === '2' );
+
+ // deleted, expect false
+ Piwik_Option::getInstance()->delete('admin_defaultReport');
+ $this->assertTrue( Piwik_Option::getInstance()->get('admin_defaultReport') === false );
+ }
+
+ public function test_deleteLike()
+ {
+ // empty table, expect false (i.e., not found)
+ $this->assertTrue( Piwik_GetOption('anonymous_defaultReport') === false );
+ $this->assertTrue( Piwik_GetOption('admin_defaultReport') === false );
+ $this->assertTrue( Piwik_GetOption('visitor_defaultReport') === false );
+
+ // insert guard - to test unescaped underscore
+ Piwik_SetOption('adefaultReport', '0', true);
+ $this->assertTrue( Piwik_GetOption('adefaultReport') === '0' );
+
+ // populate table, expect '1'
+ Piwik_SetOption('anonymous_defaultReport', '1', true);
+ Piwik_Option::getInstance()->deleteLike('\_defaultReport');
+ $this->assertTrue( Piwik_Option::getInstance()->get('anonymous_defaultReport') === '1' );
+ $this->assertTrue( Piwik_GetOption('adefaultReport') === '0' );
+
+ // populate table, expect '2'
+ Piwik_SetOption('admin_defaultReport', '2', false);
+ Piwik_Option::getInstance()->deleteLike('\_defaultReport');
+ $this->assertTrue( Piwik_Option::getInstance()->get('admin_defaultReport') === '2' );
+ $this->assertTrue( Piwik_GetOption('adefaultReport') === '0' );
+
+ // populate table, expect '3'
+ Piwik_SetOption('visitor_defaultReport', '3', false);
+ Piwik_Option::getInstance()->deleteLike('\_defaultReport');
+ $this->assertTrue( Piwik_Option::getInstance()->get('visitor_defaultReport') === '3' );
+ $this->assertTrue( Piwik_GetOption('adefaultReport') === '0' );
+
+ // delete with non-matching value, expect '1'
+ Piwik_Option::getInstance()->deleteLike('%\_defaultReport', '4');
+ $this->assertTrue( Piwik_Option::getInstance()->get('anonymous_defaultReport') === '1' );
+ $this->assertTrue( Piwik_GetOption('adefaultReport') === '0' );
+
+ // delete with matching pattern, expect false
+ Piwik_Option::getInstance()->deleteLike('%\_defaultReport', '1');
+ $this->assertTrue( Piwik_Option::getInstance()->get('anonymous_defaultReport') === false );
+ $this->assertTrue( Piwik_GetOption('adefaultReport') === '0' );
+
+ // this shouldn't have been deleted, expect '2' and '3'
+ $this->assertTrue( Piwik_Option::getInstance()->get('admin_defaultReport') === '2' );
+ $this->assertTrue( Piwik_Option::getInstance()->get('visitor_defaultReport') === '3' );
+ $this->assertTrue( Piwik_GetOption('adefaultReport') === '0' );
+
+ // deleted, expect false (except for the guard)
+ Piwik_Option::getInstance()->deleteLike('%\_defaultReport');
+ $this->assertTrue( Piwik_Option::getInstance()->get('admin_defaultReport') === false );
+ $this->assertTrue( Piwik_Option::getInstance()->get('visitor_defaultReport') === false );
+
+ // unescaped backslash (single quotes)
+ Piwik_Option::getInstance()->deleteLike('%\_defaultReport');
+ $this->assertTrue( Piwik_GetOption('adefaultReport') === '0' );
+
+ // escaped backslash (single quotes)
+ Piwik_Option::getInstance()->deleteLike('%\\_defaultReport');
+ $this->assertTrue( Piwik_GetOption('adefaultReport') === '0' );
+
+ // unescaped backslash (double quotes)
+ Piwik_Option::getInstance()->deleteLike("%\_defaultReport");
+ $this->assertTrue( Piwik_GetOption('adefaultReport') === '0' );
+
+ // escaped backslash (double quotes)
+ Piwik_Option::getInstance()->deleteLike("%\\_defaultReport");
+ $this->assertTrue( Piwik_GetOption('adefaultReport') === '0' );
+ }
+}