Skip to content
Extraits de code Groupes Projets
Valider 98bc277a rédigé par Thomas Steur's avatar Thomas Steur
Parcourir les fichiers

started to work on command to set number of available custom variables

parent 23bf6195
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
......@@ -330,6 +330,19 @@ class Db
return self::query("DROP TABLE " . implode(',', $tables));
}
/**
* Get columns information from table
*
* @param string|array $table The name of the table you want to get the columns definition for.
* @return \Zend_Db_Statement
*/
static public function getColumnNamesFromTable($table)
{
$columns = self::fetchAssoc("SHOW COLUMNS FROM " . $table);
return array_keys($columns);
}
/**
* Locks the supplied table or tables.
*
......
......@@ -192,16 +192,6 @@ class Mysql implements SchemaInterface
location_city varchar(255) DEFAULT NULL,
location_latitude float(10, 6) DEFAULT NULL,
location_longitude float(10, 6) DEFAULT NULL,
custom_var_k1 VARCHAR(200) DEFAULT NULL,
custom_var_v1 VARCHAR(200) DEFAULT NULL,
custom_var_k2 VARCHAR(200) DEFAULT NULL,
custom_var_v2 VARCHAR(200) DEFAULT NULL,
custom_var_k3 VARCHAR(200) DEFAULT NULL,
custom_var_v3 VARCHAR(200) DEFAULT NULL,
custom_var_k4 VARCHAR(200) DEFAULT NULL,
custom_var_v4 VARCHAR(200) DEFAULT NULL,
custom_var_k5 VARCHAR(200) DEFAULT NULL,
custom_var_v5 VARCHAR(200) DEFAULT NULL,
PRIMARY KEY(idvisit),
INDEX index_idsite_config_datetime (idsite, config_id, visit_last_action_time),
INDEX index_idsite_datetime (idsite, visit_last_action_time),
......@@ -264,16 +254,6 @@ class Mysql implements SchemaInterface
revenue_shipping float default NULL,
revenue_discount float default NULL,
custom_var_k1 VARCHAR(200) DEFAULT NULL,
custom_var_v1 VARCHAR(200) DEFAULT NULL,
custom_var_k2 VARCHAR(200) DEFAULT NULL,
custom_var_v2 VARCHAR(200) DEFAULT NULL,
custom_var_k3 VARCHAR(200) DEFAULT NULL,
custom_var_v3 VARCHAR(200) DEFAULT NULL,
custom_var_k4 VARCHAR(200) DEFAULT NULL,
custom_var_v4 VARCHAR(200) DEFAULT NULL,
custom_var_k5 VARCHAR(200) DEFAULT NULL,
custom_var_v5 VARCHAR(200) DEFAULT NULL,
PRIMARY KEY (idvisit, idgoal, buster),
UNIQUE KEY unique_idsite_idorder (idsite, idorder),
INDEX index_idsite_datetime ( idsite, server_time )
......@@ -293,16 +273,7 @@ class Mysql implements SchemaInterface
idaction_event_category INTEGER(10) UNSIGNED DEFAULT NULL,
idaction_event_action INTEGER(10) UNSIGNED DEFAULT NULL,
time_spent_ref_action INTEGER(10) UNSIGNED NOT NULL,
custom_var_k1 VARCHAR(200) DEFAULT NULL,
custom_var_v1 VARCHAR(200) DEFAULT NULL,
custom_var_k2 VARCHAR(200) DEFAULT NULL,
custom_var_v2 VARCHAR(200) DEFAULT NULL,
custom_var_k3 VARCHAR(200) DEFAULT NULL,
custom_var_v3 VARCHAR(200) DEFAULT NULL,
custom_var_k4 VARCHAR(200) DEFAULT NULL,
custom_var_v4 VARCHAR(200) DEFAULT NULL,
custom_var_k5 VARCHAR(200) DEFAULT NULL,
custom_var_v5 VARCHAR(200) DEFAULT NULL,
custom_float FLOAT NULL DEFAULT NULL,
PRIMARY KEY(idlink_va),
INDEX index_idvisit(idvisit),
......
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\CustomVariables\Commands;
use Piwik\Plugin\ConsoleCommand;
use Piwik\Plugins\CustomVariables\Model;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
*/
class SetNumberOfCustomVariables extends ConsoleCommand
{
/**
* @var \Symfony\Component\Console\Helper\ProgressHelper
*/
private $progress;
protected function configure()
{
$this->setName('customvariables:set-number-available-custom-variables');
$this->setDescription('Change the number of available custom variables');
$this->setHelp("Example:
./console customvariables:set-number-available-custom-variables 10
=> 10 custom variables will be available in total
");
$this->addArgument('maxCustomVars', InputArgument::REQUIRED, 'The number of available custom variables');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$numVarsToSet = $this->getNumVariablesToSet($input);
$numChangesToPerform = $this->getNumberOfChangesToPerform($numVarsToSet);
if (0 === $numChangesToPerform) {
$this->writeSuccessMessage($output, array(
'Your Piwik is already configured for ' . $numVarsToSet . ' custom variables.'
));
return;
}
foreach (Model::getScopes() as $scope) {
$this->printChanges($scope, $numVarsToSet, $output);
}
if (!$this->confirmChange($output)) {
return;
}
$output->writeln('');
$output->writeln('Starting to apply changes');
$output->writeln('');
$this->progress = $this->initProgress($numChangesToPerform, $output);
foreach (Model::getScopes() as $scope) {
$this->performChange($scope, $numVarsToSet, $output);
}
$this->progress->finish();
$this->writeSuccessMessage($output, array(
'Your Piwik is now configured for ' . $numVarsToSet . ' custom variables.'
));
}
private function initProgress($numChangesToPerform, OutputInterface $output)
{
/** @var \Symfony\Component\Console\Helper\ProgressHelper $progress */
$progress = $this->getHelperSet()->get('progress');
$progress->start($output, $numChangesToPerform);
return $progress;
}
private function performChange($scope, $numVarsToSet, OutputInterface $output)
{
$model = new Model($scope);
$numCurrentVars = $model->getCurrentNumCustomVars();
$numDifference = $this->getAbsoluteDifference($numCurrentVars, $numVarsToSet);
if ($numVarsToSet > $numCurrentVars) {
$this->addCustomVariables($model, $numDifference, $output);
return;
}
$this->removeCustomVariables($model, $numDifference, $output);
}
private function getNumVariablesToSet(InputInterface $input)
{
$maxCustomVars = $input->getArgument('maxCustomVars');
if (!is_numeric($maxCustomVars)) {
throw new \Exception('The number of available custom variables has to be number');
}
$maxCustomVars = (int) $maxCustomVars;
if ($maxCustomVars <= 0) {
throw new \Exception('There has to be at least 1 custom variable');
}
return $maxCustomVars;
}
private function confirmChange(OutputInterface $output)
{
$output->writeln('');
$dialog = $this->getHelperSet()->get('dialog');
return $dialog->askConfirmation(
$output,
'<question>Are you sure you want to perform these actions? (y/N)</question>',
false
);
}
private function printChanges($scope, $numVarsToSet, OutputInterface $output)
{
$model = new Model($scope);
$scopeName = $model->getScopeName();
$highestIndex = $model->getHighestCustomVarIndex();
$numCurrentCustomVars = $model->getCurrentNumCustomVars();
$numVarsDifference = $this->getAbsoluteDifference($numCurrentCustomVars, $numVarsToSet);
$output->writeln('');
$output->writeln(sprintf('Scope "%s"', $scopeName));
if ($numVarsToSet > $numCurrentCustomVars) {
$indexes = implode(',', range($highestIndex + 1, $highestIndex + $numVarsDifference));
$output->writeln(
sprintf('%s new custom variables having the index(es) %s will be ADDED', $numVarsDifference, $indexes)
);
} elseif ($numVarsToSet < $numCurrentCustomVars) {
$indexes = implode(',', range($highestIndex - $numVarsDifference + 1, $highestIndex));
$output->writeln(
sprintf("%s existing custom variables having the index(es) %s will be REMOVED.", $numVarsDifference, $indexes)
);
$output->writeln('<comment>This is an irreversible change</comment>');
}
}
private function getAbsoluteDifference($currentNumber, $numberToSet)
{
return abs($numberToSet - $currentNumber);
}
private function removeCustomVariables(Model $model, $numberOfVarsToRemove, OutputInterface $output)
{
for ($index = 0; $index < $numberOfVarsToRemove; $index++) {
$indexRemoved = $model->removeCustomVariable();
$this->progress->advance();
$output->writeln(' <info>Removed a variable in scope "' . $model->getScopeName() . '" having the index ' . $indexRemoved . '</info>');
}
}
private function addCustomVariables(Model $model, $numberOfVarsToAdd, OutputInterface $output)
{
for ($index = 0; $index < $numberOfVarsToAdd; $index++) {
$indexAdded = $model->addCustomVariable();
$this->progress->advance();
$output->writeln(' <info>Added a variable in scope "' . $model->getScopeName() . '" having the index ' . $indexAdded . '</info>');
}
}
private function getNumberOfChangesToPerform($numVarsToSet)
{
$numChangesToPerform = 0;
foreach (Model::getScopes() as $scope) {
$model = new Model($scope);
$numCurrentCustomVars = $model->getCurrentNumCustomVars();
$numChangesToPerform += $this->getAbsoluteDifference($numCurrentCustomVars, $numVarsToSet);
}
return $numChangesToPerform;
}
}
......@@ -38,6 +38,7 @@ class CustomVariables extends \Piwik\Plugin
'API.getReportMetadata' => 'getReportMetadata',
'API.getSegmentDimensionMetadata' => 'getSegmentsMetadata',
'ViewDataTable.configure' => 'configureViewDataTable',
'Console.addCommands' => 'addConsoleCommands'
);
return $hooks;
}
......@@ -52,6 +53,16 @@ class CustomVariables extends \Piwik\Plugin
MenuMain::getInstance()->add('General_Visitors', 'CustomVariables_CustomVariables', array('module' => 'CustomVariables', 'action' => 'index'), $display = true, $order = 50);
}
public function install()
{
Model::install();
}
public function addConsoleCommands(&$commands)
{
$commands[] = __NAMESPACE__ . '\\Commands\\SetNumberOfCustomVariables';
}
/**
* Returns metadata for available reports
*/
......
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\CustomVariables;
use Piwik\Common;
use Piwik\DataTable;
use Piwik\Db;
class Model
{
const SCOPE_PAGE = 'log_link_visit_action';
const SCOPE_VISIT = 'log_visit';
const SCOPE_CONVERSION = 'log_conversion';
private $scope = null;
public function __construct($scope)
{
if (empty($scope) || !in_array($scope, $this->getScopes())) {
throw new \Exception('Invalid custom variable scope');
}
$this->scope = $scope;
}
public function getScopeName()
{
// actually we should have a class for each scope but don't want to overengineer it for now
switch ($this->scope) {
case self::SCOPE_PAGE:
return 'Page';
case self::SCOPE_VISIT:
return 'Visit';
case self::SCOPE_CONVERSION:
return 'Conversion';
}
}
public function getCurrentNumCustomVars()
{
$customVarColumns = $this->getCustomVarColumnNames();
$currentNumCustomVars = count($customVarColumns) / 2;
return (int) $currentNumCustomVars;
}
public function getHighestCustomVarIndex()
{
$columns = $this->getCustomVarColumnNames();
if (empty($columns)) {
return 0;
}
$indexes = array_map(function ($column) {
$onlyNumber = str_replace(array('custom_var_k', 'custom_var_v'), '', $column);
return (int) $onlyNumber;
}, $columns);
return max($indexes);
}
private function getCustomVarColumnNames()
{
$dbTable = Common::prefixTable($this->scope);
$columns = Db::getColumnNamesFromTable($dbTable);
$customVarColumns = array_filter($columns, function ($column) {
return false !== strpos($column, 'custom_var_');
});
return $customVarColumns;
}
public function removeCustomVariable()
{
$dbTable = Common::prefixTable($this->scope);
$index = $this->getHighestCustomVarIndex();
if ($index < 1) {
return null;
}
Db::exec(sprintf('ALTER TABLE %s DROP COLUMN custom_var_k%d', $dbTable, $index));
Db::exec(sprintf('ALTER TABLE %s DROP COLUMN custom_var_v%d', $dbTable, $index));
return $index;
}
public function addCustomVariable()
{
$dbTable = Common::prefixTable($this->scope);
$index = $this->getHighestCustomVarIndex() + 1;
Db::exec(sprintf('ALTER TABLE %s ADD COLUMN custom_var_k%d VARCHAR(200) DEFAULT NULL', $dbTable, $index));
Db::exec(sprintf('ALTER TABLE %s ADD COLUMN custom_var_v%d VARCHAR(200) DEFAULT NULL', $dbTable, $index));
return $index;
}
public static function getScopes()
{
return array(self::SCOPE_PAGE, self::SCOPE_VISIT, self::SCOPE_CONVERSION);
}
public static function install()
{
foreach (self::getScopes() as $scope) {
$model = new Model($scope);
for ($index = 0; $index < 5; $index++) {
$model->addCustomVariable();
}
}
}
}
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
namespace Piwik\Plugins\CustomVariables\tests;
use Piwik\Db;
use Piwik\Plugins\CustomVariables\Model;
/**
* @group CustomVariables
* @group ModelTest
* @group Database
*/
class ModelTest extends \DatabaseTestCase
{
public function testGetAllScopes()
{
$this->assertEquals(array('log_link_visit_action', 'log_visit', 'log_conversion'), Model::getScopes());
}
public function testGetScopeName()
{
$this->assertEquals('Page', $this->getPageScope()->getScopeName());
$this->assertEquals('Visit', $this->getVisitScope()->getScopeName());
$this->assertEquals('Conversion', $this->getConversionScope()->getScopeName());
}
public function test_getCurrentNumCustomVars()
{
$this->assertEquals(5, $this->getPageScope()->getCurrentNumCustomVars());
$this->assertEquals(5, $this->getVisitScope()->getCurrentNumCustomVars());
$this->assertEquals(5, $this->getConversionScope()->getCurrentNumCustomVars());
$this->getPageScope()->addCustomVariable();
$this->getConversionScope()->removeCustomVariable();
$this->assertEquals(6, $this->getPageScope()->getCurrentNumCustomVars());
$this->assertEquals(5, $this->getVisitScope()->getCurrentNumCustomVars());
$this->assertEquals(4, $this->getConversionScope()->getCurrentNumCustomVars());
}
public function test_getHighestCustomVarIndex_addCustomVariable_removeCustomVariable()
{
$this->assertEquals(5, $this->getPageScope()->getHighestCustomVarIndex());
$this->assertEquals(5, $this->getVisitScope()->getHighestCustomVarIndex());
$this->assertEquals(5, $this->getConversionScope()->getHighestCustomVarIndex());
$this->getPageScope()->addCustomVariable();
$this->getConversionScope()->removeCustomVariable();
$this->assertEquals(6, $this->getPageScope()->getHighestCustomVarIndex());
$this->assertEquals(5, $this->getVisitScope()->getHighestCustomVarIndex());
$this->assertEquals(4, $this->getConversionScope()->getHighestCustomVarIndex());
$this->getConversionScope()->removeCustomVariable();
$this->getPageScope()->addCustomVariable();
$this->getVisitScope()->addCustomVariable();
$this->getPageScope()->addCustomVariable();
$this->getConversionScope()->removeCustomVariable();
$this->assertEquals(8, $this->getPageScope()->getHighestCustomVarIndex());
$this->assertEquals(6, $this->getVisitScope()->getHighestCustomVarIndex());
$this->assertEquals(2, $this->getConversionScope()->getHighestCustomVarIndex());
}
public function test_removeCustomVariable_shouldNotFailIfRemovesMoreThanExist()
{
$scope = $this->getPageScope();
$this->assertEquals(5, $scope->getHighestCustomVarIndex());
for ($index = 0; $index < 5; $index++) {
$scope->removeCustomVariable();
$this->assertEquals(4 - $index, $scope->getHighestCustomVarIndex());
}
$this->assertNull($scope->removeCustomVariable());
$this->assertEquals(0, $scope->getHighestCustomVarIndex());
$this->assertEquals(0, $scope->getCurrentNumCustomVars());
}
public function test_removeCustomVariable_addCustomVariable_ReturnsIndex()
{
$scopeToAdd = $this->getPageScope();
$scopeToRemove = $this->getVisitScope();
for ($index = 0; $index < 5; $index++) {
$this->assertEquals(5 - $index, $scopeToRemove->removeCustomVariable());
$this->assertEquals(6 + $index, $scopeToAdd->addCustomVariable());
}
}
private function getPageScope()
{
return new Model(Model::SCOPE_PAGE);
}
private function getVisitScope()
{
return new Model(Model::SCOPE_VISIT);
}
private function getConversionScope()
{
return new Model(Model::SCOPE_CONVERSION);
}
}
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
use Piwik\Db;
use Piwik\Common;
/**
* Class Core_DbTest
*
* @group Core
*/
class Core_DbTest extends DatabaseTestCase
{
public function test_getColumnNamesFromTable()
{
$this->assertColumnNames('access', array('login', 'idsite', 'access'));
$this->assertColumnNames('option', array('option_name', 'option_value', 'autoload'));
}
private function assertColumnNames($tableName, $expectedColumnNames)
{
$colmuns = Db::getColumnNamesFromTable(Common::prefixTable($tableName));
$this->assertEquals($expectedColumnNames, $colmuns);
}
}
\ No newline at end of file
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter