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:
authorThomas Steur <tsteur@users.noreply.github.com>2018-05-03 22:37:39 +0300
committerBenaka <diosmosis@users.noreply.github.com>2018-05-03 22:37:39 +0300
commit94ba5d292a0bde8a3b2056e698cfcb3e9ea7c1af (patch)
tree0cc5deab197195dd092ddf1c528cc5b438ddd942 /core/Settings
parent19000f9e263e28be2703fedc9d2b77b7d962539b (diff)
Added new setting field to configure multiple values (#12807)
* Added new setting field to configure multiple values * remove not needed comment * better spacing between rows * make fields wider * fix ui test * rename multipair to multituple * rename variable * fix it was not possible to persist nested arrays * only catch error when using old version * catch exception * better implementation * require higher version * trying to fix json_encoded columm missing in db during updater * silence errors * hard code the query * fix user login cannot be null * fail if query fails
Diffstat (limited to 'core/Settings')
-rw-r--r--core/Settings/FieldConfig.php5
-rw-r--r--core/Settings/FieldConfig/MultiPair.php89
-rw-r--r--core/Settings/Setting.php5
-rw-r--r--core/Settings/Storage/Backend/MeasurableSettingsTable.php54
-rw-r--r--core/Settings/Storage/Backend/PluginSettingsTable.php54
5 files changed, 174 insertions, 33 deletions
diff --git a/core/Settings/FieldConfig.php b/core/Settings/FieldConfig.php
index e7b819b34e..3132032dc8 100644
--- a/core/Settings/FieldConfig.php
+++ b/core/Settings/FieldConfig.php
@@ -70,6 +70,11 @@ class FieldConfig
const UI_CONTROL_SINGLE_EXPANDABLE_SELECT = 'expandable-select';
/**
+ * Lets a user configure two form fields next to each other, and add multiple entries of those two pairs.
+ */
+ const UI_CONTROL_MULTI_TUPLE = 'multituple';
+
+ /**
* Generates a hidden form field. To use this field assign it to the `$uiControl` property.
*/
const UI_CONTROL_HIDDEN = 'hidden';
diff --git a/core/Settings/FieldConfig/MultiPair.php b/core/Settings/FieldConfig/MultiPair.php
new file mode 100644
index 0000000000..ede9477e3f
--- /dev/null
+++ b/core/Settings/FieldConfig/MultiPair.php
@@ -0,0 +1,89 @@
+<?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\FieldConfig;
+
+/**
+ * Lets you configure a multi pair field.
+ *
+ * Usage:
+ *
+ * $field->uiControl = FieldConfig::UI_CONTROL_MULTI_PAIR;
+ * $field1 = new FieldConfig\MultiPair('Index', 'index', FieldConfig::UI_CONTROL_TEXT);
+ * $field2 = new FieldConfig\MultiPair('Value', 'value', FieldConfig::UI_CONTROL_TEXT);
+ * $field->uiControlAttributes['field1'] = $field1->toArray();
+ * $field->uiControlAttributes['field2'] = $field2->toArray();
+ *
+ * @api
+ */
+class MultiPair
+{
+ /**
+ * The name of the key the index should have eg "dimension" will make an index array(array('dimension' => '...'))
+ * @var string
+ */
+ public $key = '';
+
+ /**
+ * Describes what HTML element should be used to manipulate the setting through Piwik's UI.
+ *
+ * See {@link Piwik\Plugin\Settings} for a list of supported control types.
+ *
+ * @var string
+ */
+ public $uiControl = null;
+
+ /**
+ * Defines a custom template file for a UI control. This file should render a UI control and expose the value in a
+ * "formField.value" angular model. For an example see "plugins/CorePluginsAdmin/angularjs/form-field/field-text.html"
+ *
+ * @var string
+ */
+ public $customUiControlTemplateFile = '';
+
+ /**
+ * This setting's display name, for example, `'Refresh Interval'`.
+ *
+ * Be sure to escape any user input as HTML can be used here.
+ *
+ * @var string
+ */
+ public $title = '';
+
+ /**
+ * The list of all available values for this setting. If null, the setting can have any value.
+ *
+ * If supplied, this field should be an array mapping available values with their prettified
+ * display value. Eg, if set to `array('nb_visits' => 'Visits', 'nb_actions' => 'Actions')`,
+ * the UI will display **Visits** and **Actions**, and when the user selects one, Piwik will
+ * set the setting to **nb_visits** or **nb_actions** respectively.
+ *
+ * @var null|array
+ */
+ public $availableValues = null;
+
+ public function __construct($title, $key, $uiControl = 'text')
+ {
+ $this->title = $title;
+ $this->key = $key;
+ $this->uiControl = $uiControl;
+ }
+
+ public function toArray()
+ {
+ return array(
+ 'key' => $this->key,
+ 'title' => $this->title,
+ 'uiControl' => $this->uiControl,
+ 'templateFile' => $this->customUiControlTemplateFile,
+ 'availableValues' => $this->availableValues,
+ );
+ }
+
+}
diff --git a/core/Settings/Setting.php b/core/Settings/Setting.php
index 9bcf683e0d..0dc84e3952 100644
--- a/core/Settings/Setting.php
+++ b/core/Settings/Setting.php
@@ -321,6 +321,11 @@ class Setting
throw new Exception('Type must be an array when using a multi select');
}
+ if ($field->uiControl === FieldConfig::UI_CONTROL_MULTI_TUPLE &&
+ $this->type !== FieldConfig::TYPE_ARRAY) {
+ throw new Exception('Type must be an array when using a multi pair');
+ }
+
$types = array(
FieldConfig::TYPE_INT,
FieldConfig::TYPE_FLOAT,
diff --git a/core/Settings/Storage/Backend/MeasurableSettingsTable.php b/core/Settings/Storage/Backend/MeasurableSettingsTable.php
index e91a7ac9cd..181505ff20 100644
--- a/core/Settings/Storage/Backend/MeasurableSettingsTable.php
+++ b/core/Settings/Storage/Backend/MeasurableSettingsTable.php
@@ -12,6 +12,7 @@ namespace Piwik\Settings\Storage\Backend;
use Piwik\Common;
use Piwik\Db;
use Exception;
+use Piwik\Version;
/**
* Measurable settings backend. Stores all settings in a "site_setting" database table.
@@ -78,43 +79,64 @@ class MeasurableSettingsTable implements BackendInterface
$this->delete();
foreach ($values as $name => $value) {
- if (!is_array($value)) {
- $value = array($value);
+ if (!isset($value)) {
+ continue;
}
- foreach ($value as $val) {
- if (!isset($val)) {
- continue;
- }
-
- if (is_bool($val)) {
- $val = (int) $val;
+ if (is_array($value) || is_object($value)) {
+ $jsonEncoded = 1;
+ $value = json_encode($value);
+ } else {
+ $jsonEncoded = 0;
+ if (is_bool($value)) {
+ // we are currently not storing booleans as json as it could result in trouble with the UI and regress
+ // preselecting the correct value
+ $value = (int) $value;
}
+ }
- $sql = "INSERT INTO $table (`idsite`, `plugin_name`, `setting_name`, `setting_value`) VALUES (?, ?, ?, ?)";
- $bind = array($this->idSite, $this->pluginName, $name, $val);
+ $sql = "INSERT INTO $table (`idsite`, `plugin_name`, `setting_name`, `setting_value`, `json_encoded`) VALUES (?, ?, ?, ?, ?)";
+ $bind = array($this->idSite, $this->pluginName, $name, $value, $jsonEncoded);
- $this->db->query($sql, $bind);
- }
+ $this->db->query($sql, $bind);
}
}
+ private function jsonEncodedMissingError(Exception $e)
+ {
+ return strpos($e->getMessage(), 'json_encoded') !== false;
+ }
+
public function load()
{
$this->initDbIfNeeded();
$table = $this->getTableName();
- $sql = "SELECT `setting_name`, `setting_value` FROM " . $table . " WHERE idsite = ? and plugin_name = ?";
+ $sql = "SELECT `setting_name`, `setting_value`, `json_encoded` FROM " . $table . " WHERE idsite = ? and plugin_name = ?";
$bind = array($this->idSite, $this->pluginName);
- $settings = $this->db->fetchAll($sql, $bind);
+ try {
+ $settings = $this->db->fetchAll($sql, $bind);
+ } catch (\Exception $e) {
+ // we catch an exception since json_encoded might not be present before matomo is updated to 3.5.0+ but the updater
+ // may run this query
+ if ($this->jsonEncodedMissingError($e)) {
+ $sql = "SELECT `setting_name`, `setting_value` FROM " . $table . " WHERE idsite = ? and plugin_name = ?";
+ $settings = $this->db->fetchAll($sql, $bind);
+ } else {
+ throw $e;
+ }
+
+ }
$flat = array();
foreach ($settings as $setting) {
$name = $setting['setting_name'];
- if (array_key_exists($name, $flat)) {
+ if (!empty($setting['json_encoded'])) {
+ $flat[$name] = json_decode($setting['setting_value'], true);
+ } elseif (array_key_exists($name, $flat)) {
if (!is_array($flat[$name])) {
$flat[$name] = array($flat[$name]);
}
diff --git a/core/Settings/Storage/Backend/PluginSettingsTable.php b/core/Settings/Storage/Backend/PluginSettingsTable.php
index 0f49d6b68e..126460a8af 100644
--- a/core/Settings/Storage/Backend/PluginSettingsTable.php
+++ b/core/Settings/Storage/Backend/PluginSettingsTable.php
@@ -12,6 +12,7 @@ namespace Piwik\Settings\Storage\Backend;
use Piwik\Common;
use Piwik\Db;
use Exception;
+use Piwik\Version;
/**
* Plugin settings backend. Stores all settings in a "plugin_setting" database table.
@@ -77,42 +78,61 @@ class PluginSettingsTable implements BackendInterface
$this->delete();
foreach ($values as $name => $value) {
-
- if (!is_array($value)) {
- $value = array($value);
+ if (!isset($value)) {
+ continue;
}
- foreach ($value as $val) {
- if (!isset($val)) {
- continue;
- }
-
- if (is_bool($val)) {
- $val = (int) $val;
+ if (is_array($value) || is_object($value)) {
+ $jsonEncoded = 1;
+ $value = json_encode($value);
+ } else {
+ $jsonEncoded = 0;
+ if (is_bool($value)) {
+ // we are currently not storing booleans as json as it could result in trouble with the UI and regress
+ // preselecting the correct value
+ $value = (int) $value;
}
+ }
- $sql = "INSERT INTO $table (`plugin_name`, `user_login`, `setting_name`, `setting_value`) VALUES (?, ?, ?, ?)";
- $bind = array($this->pluginName, $this->userLogin, $name, $val);
+ $sql = "INSERT INTO $table (`plugin_name`, `user_login`, `setting_name`, `setting_value`, `json_encoded`) VALUES (?, ?, ?, ?, ?)";
+ $bind = array($this->pluginName, $this->userLogin, $name, $value, $jsonEncoded);
- $this->db->query($sql, $bind);
- }
+ $this->db->query($sql, $bind);
}
}
+ private function jsonEncodedMissingError(Exception $e)
+ {
+ return strpos($e->getMessage(), 'json_encoded') !== false;
+ }
+
public function load()
{
$this->initDbIfNeeded();
- $sql = "SELECT `setting_name`, `setting_value` FROM " . $this->getTableName() . " WHERE plugin_name = ? and user_login = ?";
+ $sql = "SELECT `setting_name`, `setting_value`, `json_encoded` FROM " . $this->getTableName() . " WHERE plugin_name = ? and user_login = ?";
$bind = array($this->pluginName, $this->userLogin);
- $settings = $this->db->fetchAll($sql, $bind);
+ try {
+ $settings = $this->db->fetchAll($sql, $bind);
+ } catch (\Exception $e) {
+ // we catch an exception since json_encoded might not be present before matomo is updated to 3.5.0+ but the updater
+ // may run this query
+ if ($this->jsonEncodedMissingError($e)) {
+ $sql = "SELECT `setting_name`, `setting_value` FROM " . $this->getTableName() . " WHERE plugin_name = ? and user_login = ?";
+ $settings = $this->db->fetchAll($sql, $bind);
+ } else {
+ throw $e;
+ }
+ }
$flat = array();
foreach ($settings as $setting) {
$name = $setting['setting_name'];
- if (array_key_exists($name, $flat)) {
+ if (!empty($setting['json_encoded'])) {
+ $flat[$name] = json_decode($setting['setting_value'], true);
+ } elseif (array_key_exists($name, $flat)) {
if (!is_array($flat[$name])) {
$flat[$name] = array($flat[$name]);
}