diff options
Diffstat (limited to 'core/Settings/Storage/Backend')
-rw-r--r-- | core/Settings/Storage/Backend/BackendInterface.php | 47 | ||||
-rw-r--r-- | core/Settings/Storage/Backend/Cache.php | 78 | ||||
-rw-r--r-- | core/Settings/Storage/Backend/MeasurableSettingsTable.php | 167 | ||||
-rw-r--r-- | core/Settings/Storage/Backend/Null.php | 44 | ||||
-rw-r--r-- | core/Settings/Storage/Backend/PluginSettingsTable.php | 175 | ||||
-rw-r--r-- | core/Settings/Storage/Backend/SitesTable.php | 122 |
6 files changed, 633 insertions, 0 deletions
diff --git a/core/Settings/Storage/Backend/BackendInterface.php b/core/Settings/Storage/Backend/BackendInterface.php new file mode 100644 index 0000000000..624493460e --- /dev/null +++ b/core/Settings/Storage/Backend/BackendInterface.php @@ -0,0 +1,47 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Settings\Storage\Backend; + +/** + * Interface for a storage backend. Any new storage backend must implement this interface. + */ +interface BackendInterface +{ + + /** + * Get an id that identifies the current storage. Eg `Plugin_$pluginName_Settings` could be a storage id + * for plugin settings. It's kind of like a cache key and the value will be actually used for this by a cache + * decorator. + * + * @return string + */ + public function getStorageId(); + + /** + * Saves (persists) the current setting values in the database. Always all values that belong to a group of + * settings or backend needs to be passed. Usually existing values will be deleted and new values will be saved + * @param array $values An array of key value pairs where $settingName => $settingValue. + * Eg array('settingName1' > 'settingValue1') + */ + public function save($values); + + /** + * Deletes all saved settings. + * @return void + */ + public function delete(); + + /** + * Loads previously saved setting values and returns them (if some were saved) + * + * @return array An array of key value pairs where $settingName => $settingValue. + * Eg array('settingName1' > 'settingValue1') + */ + public function load(); +} diff --git a/core/Settings/Storage/Backend/Cache.php b/core/Settings/Storage/Backend/Cache.php new file mode 100644 index 0000000000..f3150d77ee --- /dev/null +++ b/core/Settings/Storage/Backend/Cache.php @@ -0,0 +1,78 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ + +namespace Piwik\Settings\Storage\Backend; + +use Piwik\Settings\Storage; +use Piwik\Tracker; +use Piwik\Cache as PiwikCache; + +/** + * Loads settings from tracker cache instead of database. If not yet present in tracker cache will cache it. + * + * Can be used as a decorator in combination with any other storage backend. + */ +class Cache implements BackendInterface +{ + /** + * @var BackendInterface + */ + private $backend; + + public function __construct(BackendInterface $backend) + { + $this->backend = $backend; + } + + /** + * Saves (persists) the current setting values in the database. + */ + public function save($values) + { + $this->backend->save($values); + self::clearCache(); + } + + public function getStorageId() + { + return $this->backend->getStorageId(); + } + + public function delete() + { + $this->backend->delete(); + self::clearCache(); + } + + public function load() + { + $cacheId = $this->getStorageId(); + $cache = self::buildCache(); + + if ($cache->contains($cacheId)) { + return $cache->fetch($cacheId); + } + + $settings = $this->backend->load(); + $cache->save($cacheId, $settings); + + return $settings; + } + + public static function clearCache() + { + Tracker\Cache::deleteTrackerCache(); + self::buildCache()->flushAll(); + } + + public static function buildCache() + { + return PiwikCache::getEagerCache(); + } +} diff --git a/core/Settings/Storage/Backend/MeasurableSettingsTable.php b/core/Settings/Storage/Backend/MeasurableSettingsTable.php new file mode 100644 index 0000000000..22452288c8 --- /dev/null +++ b/core/Settings/Storage/Backend/MeasurableSettingsTable.php @@ -0,0 +1,167 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ + +namespace Piwik\Settings\Storage\Backend; + +use Piwik\Common; +use Piwik\Db; +use Exception; + +/** + * Measurable settings backend. Stores all settings in a "site_setting" database table. + * + * If a value that needs to be stored is an array, will insert a new row for each value of this array. + */ +class MeasurableSettingsTable implements BackendInterface +{ + /** + * @var int + */ + private $idSite; + + /** + * @var string + */ + private $pluginName; + + /** + * @var Db\AdapterInterface + */ + private $db; + + public function __construct($idSite, $pluginName) + { + if (empty($pluginName)) { + throw new Exception('No plugin name given for MeasurableSettingsTable backend'); + } + + if (empty($idSite)) { + throw new Exception('No idSite given for MeasurableSettingsTable backend'); + } + + $this->idSite = (int) $idSite; + $this->pluginName = $pluginName; + } + + private function initDbIfNeeded() + { + if (!isset($this->db)) { + // we need to avoid db creation on instance creation, especially important in tracker mode + // the db might be never actually used when values are eg fetched from a cache + $this->db = Db::get(); + } + } + + /** + * @inheritdoc + */ + public function getStorageId() + { + return 'MeasurableSettings_' . $this->idSite . '_' . $this->pluginName; + } + + /** + * Saves (persists) the current setting values in the database. + */ + public function save($values) + { + $this->initDbIfNeeded(); + + $table = $this->getTableName(); + + $this->delete(); + + foreach ($values as $name => $value) { + if (!is_array($value)) { + $value = array($value); + } + + foreach ($value as $val) { + if (!isset($val)) { + continue; + } + + if (is_bool($val)) { + $val = (int) $val; + } + + $sql = "INSERT INTO $table (`idsite`, `plugin_name`, `setting_name`, `setting_value`) VALUES (?, ?, ?, ?)"; + $bind = array($this->idSite, $this->pluginName, $name, $val); + + $this->db->query($sql, $bind); + } + } + } + + public function load() + { + $this->initDbIfNeeded(); + + $table = $this->getTableName(); + + $sql = "SELECT `setting_name`, `setting_value` FROM " . $table . " WHERE idsite = ? and plugin_name = ?"; + $bind = array($this->idSite, $this->pluginName); + + $settings = $this->db->fetchAll($sql, $bind); + + $flat = array(); + foreach ($settings as $setting) { + $name = $setting['setting_name']; + + if (array_key_exists($name, $flat)) { + if (!is_array($flat[$name])) { + $flat[$name] = array($flat[$name]); + } + $flat[$name][] = $setting['setting_value']; + } else { + $flat[$name] = $setting['setting_value']; + } + } + + return $flat; + } + + private function getTableName() + { + return Common::prefixTable('site_setting'); + } + + public function delete() + { + $this->initDbIfNeeded(); + + $table = $this->getTableName(); + $sql = "DELETE FROM $table WHERE `idsite` = ? and plugin_name = ?"; + $bind = array($this->idSite, $this->pluginName); + + $this->db->query($sql, $bind); + } + + /** + * @internal + * @param int $idSite + * @throws \Exception + */ + public static function removeAllSettingsForSite($idSite) + { + $query = sprintf('DELETE FROM %s WHERE idsite = ?', Common::prefixTable('site_setting')); + Db::query($query, array($idSite)); + } + + /** + * @internal + * @param string $pluginName + * @throws \Exception + */ + public static function removeAllSettingsForPlugin($pluginName) + { + $query = sprintf('DELETE FROM %s WHERE plugin_name = ?', Common::prefixTable('site_setting')); + Db::query($query, array($pluginName)); + } +} diff --git a/core/Settings/Storage/Backend/Null.php b/core/Settings/Storage/Backend/Null.php new file mode 100644 index 0000000000..cc64c55654 --- /dev/null +++ b/core/Settings/Storage/Backend/Null.php @@ -0,0 +1,44 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ + +namespace Piwik\Settings\Storage\Backend; + +use Piwik\Settings\Storage; + +/** + * Static / temporary storage where a value shall never be persisted. Meaning it will use the default value + * for each request until configured differently. Useful for tests etc. + */ +class Null implements BackendInterface +{ + private $storageId; + + public function __construct($storageId) + { + $this->storageId = $storageId; + } + + public function load() + { + return array(); + } + + public function getStorageId() + { + return $this->storageId; + } + + public function delete() + { + } + + public function save($values) + { + } +} diff --git a/core/Settings/Storage/Backend/PluginSettingsTable.php b/core/Settings/Storage/Backend/PluginSettingsTable.php new file mode 100644 index 0000000000..87476ff8fb --- /dev/null +++ b/core/Settings/Storage/Backend/PluginSettingsTable.php @@ -0,0 +1,175 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ + +namespace Piwik\Settings\Storage\Backend; + +use Piwik\Common; +use Piwik\Db; +use Exception; + +/** + * Plugin settings backend. Stores all settings in a "plugin_setting" database table. + * + * If a value that needs to be stored is an array, will insert a new row for each value of this array. + */ +class PluginSettingsTable implements BackendInterface +{ + /** + * @var string + */ + private $pluginName; + + /** + * @var string + */ + private $userLogin; + + /** + * @var Db\AdapterInterface + */ + private $db; + + public function __construct($pluginName, $userLogin) + { + if (empty($pluginName)) { + throw new Exception('No plugin name given for PluginSettingsTable backend'); + } + + if ($userLogin === false || $userLogin === null) { + throw new Exception('Invalid user login name given for PluginSettingsTable backend'); + } + + $this->pluginName = $pluginName; + $this->userLogin = $userLogin; + } + + private function initDbIfNeeded() + { + if (!isset($this->db)) { + // we do not want to create a db connection on backend creation + $this->db = Db::get(); + } + } + + /** + * @inheritdoc + */ + public function getStorageId() + { + return 'PluginSettings_' . $this->pluginName . '_User_' . $this->userLogin; + } + + /** + * Saves (persists) the current setting values in the database. + */ + public function save($values) + { + $this->initDbIfNeeded(); + + $table = $this->getTableName(); + + $this->delete(); + + foreach ($values as $name => $value) { + + if (!is_array($value)) { + $value = array($value); + } + + foreach ($value as $val) { + if (!isset($val)) { + continue; + } + + if (is_bool($val)) { + $val = (int) $val; + } + + $sql = "INSERT INTO $table (`plugin_name`, `user_login`, `setting_name`, `setting_value`) VALUES (?, ?, ?, ?)"; + $bind = array($this->pluginName, $this->userLogin, $name, $val); + + $this->db->query($sql, $bind); + } + } + } + + public function load() + { + $this->initDbIfNeeded(); + + $sql = "SELECT `setting_name`, `setting_value` FROM " . $this->getTableName() . " WHERE plugin_name = ? and user_login = ?"; + $bind = array($this->pluginName, $this->userLogin); + + $settings = $this->db->fetchAll($sql, $bind); + + $flat = array(); + foreach ($settings as $setting) { + $name = $setting['setting_name']; + + if (array_key_exists($name, $flat)) { + if (!is_array($flat[$name])) { + $flat[$name] = array($flat[$name]); + } + $flat[$name][] = $setting['setting_value']; + } else { + $flat[$name] = $setting['setting_value']; + } + } + + return $flat; + } + + private function getTableName() + { + return Common::prefixTable('plugin_setting'); + } + + public function delete() + { + $this->initDbIfNeeded(); + + $table = $this->getTableName(); + $sql = "DELETE FROM $table WHERE `plugin_name` = ? and `user_login` = ?"; + $bind = array($this->pluginName, $this->userLogin); + + $this->db->query($sql, $bind); + } + + /** + * Unsets all settings for a user. The settings will be removed from the database. Used when + * a user is deleted. + * + * @internal + * @param string $userLogin + * @throws \Exception If the `$userLogin` is empty. Otherwise we would delete most plugin settings + */ + public static function removeAllUserSettingsForUser($userLogin) + { + if (empty($userLogin)) { + throw new Exception('No userLogin specified. Cannot remove all settings for this user'); + } + + $table = Common::prefixTable('plugin_setting'); + Db::get()->query(sprintf('DELETE FROM %s WHERE user_login = ?', $table), array($userLogin)); + } + + /** + * Unsets all settings for a plugin. The settings will be removed from the database. Used when + * a plugin is uninstalled. + * + * @internal + * @param string $pluginName + * @throws \Exception If the `$userLogin` is empty. + */ + public static function removeAllSettingsForPlugin($pluginName) + { + $table = Common::prefixTable('plugin_setting'); + Db::get()->query(sprintf('DELETE FROM %s WHERE plugin_name = ?', $table), array($pluginName)); + } +} diff --git a/core/Settings/Storage/Backend/SitesTable.php b/core/Settings/Storage/Backend/SitesTable.php new file mode 100644 index 0000000000..81de89b100 --- /dev/null +++ b/core/Settings/Storage/Backend/SitesTable.php @@ -0,0 +1,122 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ + +namespace Piwik\Settings\Storage\Backend; + +use Piwik\Plugins\SitesManager\Model; +use Piwik\Site; +use Exception; + +/** + * Backend for an existing site. Stores all settings in the "site" database table. + */ +class SitesTable implements BackendInterface +{ + /** + * @var int + */ + private $idSite; + + private $commaSeparatedArrayFields = array( + 'sitesearch_keyword_parameters', + 'sitesearch_category_parameters', + 'excluded_user_agents', + 'excluded_parameters', + 'excluded_ips' + ); + + // these fields are standard fields of a site and cannot be adjusted via a setting + private $allowedNames = array( + 'ecommerce', 'sitesearch', 'sitesearch_keyword_parameters', + 'sitesearch_category_parameters', 'exclude_unknown_urls', + 'excluded_ips', 'excluded_parameters', + 'excluded_user_agents', 'keep_url_fragment', 'urls' + ); + + public function __construct($idSite) + { + if (empty($idSite)) { + throw new Exception('No idSite given for Measurable backend'); + } + + $this->idSite = (int) $idSite; + } + + /** + * @inheritdoc + */ + public function getStorageId() + { + return 'SitesTable_' . $this->idSite; + } + + /** + * Saves (persists) the current setting values in the database. + */ + public function save($values) + { + $model = $this->getModel(); + + foreach ($values as $key => $value) { + if (!in_array($key, $this->allowedNames)) { + unset($values[$key]); + continue; + } + + if (is_array($value) && in_array($key, $this->commaSeparatedArrayFields)) { + $values[$key] = implode(',', $value); + } elseif (is_bool($value)) { + $values[$key] = (int) $value; + } + } + + if (!empty($values['urls'])) { + $urls = array_unique($values['urls']); + $values['main_url'] = array_shift($urls); + + $model->deleteSiteAliasUrls($this->idSite); + foreach ($urls as $url) { + $model->insertSiteUrl($this->idSite, $url); + } + } + + unset($values['urls']); + + $model->updateSite($values, $this->idSite); + Site::clearCacheForSite($this->idSite); + } + + public function load() + { + if (!empty($this->idSite)) { + $site = Site::getSite($this->idSite); + + $urls = $this->getModel(); + $site['urls'] = $urls->getSiteUrlsFromId($this->idSite); + + foreach ($this->commaSeparatedArrayFields as $field) { + if (!empty($site[$field]) && is_string($site[$field])) { + $site[$field] = explode(',', $site[$field]); + } + } + + return $site; + } + } + + private function getModel() + { + return new Model(); + } + + public function delete() + { + } + +} |