diff --git a/core/Development.php b/core/Development.php index c0d34f11e906a6f146123aaa6ec07b9ebad089e3..60d3dcd81c72745af863d56aa8d19c2485ad9664 100644 --- a/core/Development.php +++ b/core/Development.php @@ -12,17 +12,21 @@ namespace Piwik; use \Exception; /** - * Development related checks and tools + * Development related checks and tools. You can enable/disable development using `./console development:enable` and + * `./console development:disable`. The intention of the development mode and this class is to support the developer + * as much as possible by doing some additional checks if the development mode is enabled. For instance if a developer + * has to register any class/method we can make sure whether they actually exist and if not display a useful error + * message. This helps the user to find for instance simple typos and makes sure it will actually work even if he + * forgets to test it. */ class Development { private static $isEnabled = null; /** - * Returns `true` if segmentation is allowed for this user, `false` if otherwise. + * Returns `true` if development mode is enabled and `false` otherwise. * * @return bool - * @api */ public static function isEnabled() { @@ -33,50 +37,110 @@ class Development return self::$isEnabled; } - public static function methodExists($classOrInstance, $method) + /** + * Verifies whether a className of object implements the given method. It does not check whether the given method + * is actually callable (public). + * + * @param string|object $classOrObject + * @param string $method + * + * @return bool true if the method exists, false otherwise. + */ + public static function methodExists($classOrObject, $method) { - if (is_string($classOrInstance)) { - return class_exists($classOrInstance) && method_exists($classOrInstance, $method); + if (is_string($classOrObject)) { + return class_exists($classOrObject) && method_exists($classOrObject, $method); } - return method_exists($classOrInstance, $method); + return method_exists($classOrObject, $method); } - public static function formatMethodCall($classOrInstance, $method) + /** + * Formats a method call depending on the given class/object and method name. It does not perform any checks whether + * does actually exists. + * + * @param string|object $classOrObject + * @param string $method + * + * @return string Formatted method call. Example: "MyNamespace\MyClassname::methodName()" + */ + public static function formatMethodCall($classOrObject, $method) { - if (is_object($classOrInstance)) { - $classOrInstance = get_class($classOrInstance); + if (is_object($classOrObject)) { + $classOrObject = get_class($classOrObject); } - return $classOrInstance . '::' . $method . '()'; + return $classOrObject . '::' . $method . '()'; } - public static function checkMethodIsCallable($classOrInstance, $method, $prefixMessageIfError) + /** + * Checks whether the given method is actually callable on the given class/object if the development mode is + * enabled. En error will be triggered if the method does not exist or is not callable (public) containing a useful + * error message for the developer. + * + * @param string|object $classOrObject + * @param string $method + * @param string $prefixMessageIfError You can prepend any string to the error message in case the method is not + * callable. + */ + public static function checkMethodIsCallable($classOrObject, $method, $prefixMessageIfError) { if (!self::isEnabled()) { return; } - if (!self::methodExists($classOrInstance, $method)) { - self::error($prefixMessageIfError . ' "' . self::formatMethodCall($classOrInstance, $method) . '" does not exist. Please make sure to define such a method.'); + self::checkMethodExists($classOrObject, $method, $prefixMessageIfError); + + if (!self::isCallableMethod($classOrObject, $method)) { + self::error($prefixMessageIfError . ' "' . self::formatMethodCall($classOrObject, $method) . '" is not callable. Please make sure to method is public'); } + } - if (!self::isCallableMethod($classOrInstance, $method)) { - self::error($prefixMessageIfError . ' "' . self::formatMethodCall($classOrInstance, $method) . '" is not callable. Please make sure to method is public'); + /** + * Checks whether the given method is actually callable on the given class/object if the development mode is + * enabled. En error will be triggered if the method does not exist or is not callable (public) containing a useful + * error message for the developer. + * + * @param string|object $classOrObject + * @param string $method + * @param string $prefixMessageIfError You can prepend any string to the error message in case the method is not + * callable. + */ + public static function checkMethodExists($classOrObject, $method, $prefixMessageIfError) + { + if (!self::isEnabled()) { + return; + } + if (!self::methodExists($classOrObject, $method)) { + self::error($prefixMessageIfError . ' "' . self::formatMethodCall($classOrObject, $method) . '" does not exist. Please make sure to define such a method.'); } } - public static function isCallableMethod($classOrInstance, $method) + /** + * Verify whether the given method actually exists and is callable (public). + * + * @param string|object $classOrObject + * @param string $method + * @return bool + */ + public static function isCallableMethod($classOrObject, $method) { - if (!self::methodExists($classOrInstance, $method)) { + if (!self::methodExists($classOrObject, $method)) { return false; } - $reflection = new \ReflectionMethod($classOrInstance, $method); + $reflection = new \ReflectionMethod($classOrObject, $method); return $reflection->isPublic(); } + /** + * Triggers an error if the development mode is enabled. Depending on the current environment / mode it will either + * log the given message or throw an exception to make sure it will be displayed in the Piwik UI. + * + * @param string $message + * @throws Exception + */ public static function error($message) { if (!self::isEnabled()) { @@ -91,6 +155,42 @@ class Development } else { throw new Exception($message); } + } + + public static function getMethodSourceCode($className, $methodName) + { + $method = new \ReflectionMethod($className, $methodName); + + $file = new \SplFileObject($method->getFileName()); + $offset = $method->getStartLine() - 1; + $count = $method->getEndLine() - $method->getStartLine() + 1; + + $fileIterator = new \LimitIterator($file, $offset, $count); + + $methodCode = "\n " . $method->getDocComment() . "\n"; + foreach($fileIterator as $line) { + $methodCode .= $line; + } + $methodCode .= "\n"; + + return $methodCode; + } + + public static function getUseStatements($className) + { + $class = new \ReflectionClass($className); + + $file = new \SplFileObject($class->getFileName()); + + $fileIterator = new \LimitIterator($file, 0, $class->getStartLine()); + + $uses = array(); + foreach($fileIterator as $line) { + if (preg_match('/(\s*)use (.+)/', $line, $match)) { + $uses[] = trim($match[2]); + } + } + return $uses; } } diff --git a/core/Updater.php b/core/Updater.php index e10c6bf33c5575f13e79bb0b48ffe6d563108609..6cd6bf757f8eb567f4c50d5d25721babbdc2b977 100644 --- a/core/Updater.php +++ b/core/Updater.php @@ -170,7 +170,7 @@ class Updater return $queries; } - private function getUpdateClassName($componentName, $fileVersion) + public function getUpdateClassName($componentName, $fileVersion) { $suffix = strtolower(str_replace(array('-', '.'), '_', $fileVersion)); $className = 'Updates_' . $suffix; diff --git a/plugins/CoreConsole/Commands/GenerateDimension.php b/plugins/CoreConsole/Commands/GenerateDimension.php index ad752b0a78f1ee61b5358e5b4d5200aa271077ef..73c2984d1b87c73efbaf357bfa5f6f1433c1d508 100644 --- a/plugins/CoreConsole/Commands/GenerateDimension.php +++ b/plugins/CoreConsole/Commands/GenerateDimension.php @@ -17,9 +17,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -/** - * TODO automatically create or modify translation file for instance for dimension name - */ class GenerateDimension extends GeneratePluginBase { protected function configure() @@ -33,27 +30,40 @@ class GenerateDimension extends GeneratePluginBase ->addOption('columntype', null, InputOption::VALUE_REQUIRED, 'The MySQL type for your dimension, for instance "VARCHAR(255) NOT NULL".'); } + /** + * @param InputInterface $input + * @param OutputInterface $output + * @throws \InvalidArgumentException + */ protected function execute(InputInterface $input, OutputInterface $output) { $pluginName = $this->getPluginName($input, $output); $type = $this->getDimensionType($input, $output); $dimensionName = $this->getDimensionName($input, $output); - $columnName = $this->getColumnName($input, $output, $type); - $columType = $this->getColumnType($input, $output); - - $dimensionClassName = $this->getDimensionClassName($dimensionName); - - $exampleFolder = PIWIK_INCLUDE_PATH . '/plugins/ExamplePlugin'; - $replace = array('example_action_dimension' => strtolower($columnName), - 'example_visit_dimension' => strtolower($columnName), - 'example_conversion_dimension' => strtolower($columnName), - 'INTEGER(11) DEFAULT 0 NOT NULL' => strtoupper($columType), - 'VARCHAR(255) DEFAULT NULL' => strtoupper($columType), - 'ExampleVisitDimension' => $dimensionClassName, - 'ExampleActionDimension' => $dimensionClassName, - 'ExampleConversionDimension' => $dimensionClassName, - 'ExamplePlugin_DimensionName' => ucfirst($dimensionName), - 'ExamplePlugin' => $pluginName, + + if ('non-tracking-dimension' === $type) { + $columnName = ''; + $columType = ''; + } else { + $columnName = $this->getColumnName($input, $output, $type); + $columType = $this->getColumnType($input, $output); + } + + $dimensionClassName = $this->getDimensionClassName($dimensionName); + $translatedDimensionName = $this->makeTranslationIfPossible($pluginName, ucfirst($dimensionName)); + + $exampleFolder = PIWIK_INCLUDE_PATH . '/plugins/ExamplePlugin'; + $replace = array('example_action_dimension' => strtolower($columnName), + 'example_visit_dimension' => strtolower($columnName), + 'example_conversion_dimension' => strtolower($columnName), + 'INTEGER(11) DEFAULT 0 NOT NULL' => strtoupper($columType), + 'VARCHAR(255) DEFAULT NULL' => strtoupper($columType), + 'ExampleDimension' => $dimensionClassName, + 'ExampleVisitDimension' => $dimensionClassName, + 'ExampleActionDimension' => $dimensionClassName, + 'ExampleConversionDimension' => $dimensionClassName, + 'ExamplePlugin_DimensionName' => $translatedDimensionName, + 'ExamplePlugin' => $pluginName, ); $whitelistFiles = array('/Columns'); @@ -64,6 +74,8 @@ class GenerateDimension extends GeneratePluginBase $whitelistFiles[] = '/Columns/ExampleActionDimension.php'; } elseif ('conversion' == $type) { $whitelistFiles[] = '/Columns/ExampleConversionDimension.php'; + } elseif ('non-tracking-dimension' == $type) { + $whitelistFiles[] = '/Columns/ExampleDimension.php'; } else { throw new \InvalidArgumentException('This dimension type is not available'); } @@ -125,6 +137,7 @@ class GenerateDimension extends GeneratePluginBase /** * @param InputInterface $input * @param OutputInterface $output + * @param string $type * @return array * @throws \RunTimeException */ @@ -206,11 +219,11 @@ class GenerateDimension extends GeneratePluginBase */ protected function getDimensionType(InputInterface $input, OutputInterface $output) { - $acceptedValues = array('visit', 'action', 'conversion'); + $acceptedValues = array('visit', 'action', 'conversion', 'non-tracking-dimension'); $validate = function ($type) use ($acceptedValues) { if (empty($type) || !in_array($type, $acceptedValues)) { - throw new \InvalidArgumentException('Please enter a valid dimension type (' . implode(', ', $acceptedValues) . '): '); + throw new \InvalidArgumentException('Please enter a valid dimension type (' . implode(', ', $acceptedValues) . '). Choose "non-tracking-dimension" if you only need a blank dimension having a name: '); } return $type; @@ -220,7 +233,7 @@ class GenerateDimension extends GeneratePluginBase if (empty($type)) { $dialog = $this->getHelperSet()->get('dialog'); - $type = $dialog->askAndValidate($output, 'Please choose the type of dimension you want to create (' . implode(', ', $acceptedValues) . '): ', $validate, false, null, $acceptedValues); + $type = $dialog->askAndValidate($output, 'Please choose the type of dimension you want to create (' . implode(', ', $acceptedValues) . '). Choose "non-tracking-dimension" if you only need a blank dimension having a name: ', $validate, false, null, $acceptedValues); } else { $validate($type); } diff --git a/plugins/CoreConsole/Commands/GeneratePluginBase.php b/plugins/CoreConsole/Commands/GeneratePluginBase.php index 8c17304aaa0f63f24f6ef1069a4b338454ed2c00..cd90321fec00852ae9a8bfa58ce66ec573bb40d0 100644 --- a/plugins/CoreConsole/Commands/GeneratePluginBase.php +++ b/plugins/CoreConsole/Commands/GeneratePluginBase.php @@ -10,13 +10,12 @@ namespace Piwik\Plugins\CoreConsole\Commands; +use Piwik\Development; use Piwik\Filesystem; use Piwik\Plugin\ConsoleCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -/** - */ abstract class GeneratePluginBase extends ConsoleCommand { public function getPluginPath($pluginName) @@ -24,24 +23,157 @@ abstract class GeneratePluginBase extends ConsoleCommand return PIWIK_INCLUDE_PATH . '/plugins/' . ucfirst($pluginName); } - private function createFolderWithinPluginIfNotExists($pluginName, $folder) + private function createFolderWithinPluginIfNotExists($pluginNameOrCore, $folder) { - $pluginPath = $this->getPluginPath($pluginName); + if ($pluginNameOrCore === 'core') { + $pluginPath = $this->getPathToCore(); + } else { + $pluginPath = $this->getPluginPath($pluginNameOrCore); + } - if (!file_exists($pluginName . $folder)) { + if (!file_exists($pluginPath . $folder)) { Filesystem::mkdir($pluginPath . $folder); } } - protected function createFileWithinPluginIfNotExists($pluginName, $fileName, $content) + protected function createFileWithinPluginIfNotExists($pluginNameOrCore, $fileName, $content) { - $pluginPath = $this->getPluginPath($pluginName); + if ($pluginNameOrCore === 'core') { + $pluginPath = $this->getPathToCore(); + } else { + $pluginPath = $this->getPluginPath($pluginNameOrCore); + } if (!file_exists($pluginPath . $fileName)) { file_put_contents($pluginPath . $fileName, $content); } } + /** + * Creates a lang/en.json within the plugin in case it does not exist yet and adds a translation for the given + * text. + * + * @param $pluginName + * @param $translatedText + * @return string Either the generated translation key or the original text if a different translation for this + * generated translation key already exists. + */ + protected function makeTranslationIfPossible($pluginName, $translatedText) + { + $defaultLang = array($pluginName => array()); + + $this->createFolderWithinPluginIfNotExists($pluginName, '/lang'); + $this->createFileWithinPluginIfNotExists($pluginName, '/lang/en.json', $this->toJson($defaultLang)); + + $langJsonPath = $this->getPluginPath($pluginName) . '/lang/en.json'; + $translations = file_get_contents($langJsonPath); + $translations = json_decode($translations, true); + + if (empty($translations[$pluginName])) { + $translations[$pluginName] = array(); + } + + $key = $this->buildTranslationKey($translatedText); + + if (array_key_exists($key, $translations[$pluginName])) { + // we do not want to overwrite any existing translations + if ($translations[$pluginName][$key] === $translatedText) { + return $pluginName . '_' . $key; + } + + return $translatedText; + } + + $translations[$pluginName][$key] = $this->removeNonJsonCompatibleCharacters($translatedText); + + file_put_contents($langJsonPath, $this->toJson($translations)); + + return $pluginName . '_' . $key; + } + + private function toJson($value) + { + if (defined('JSON_PRETTY_PRINT')) { + + return json_encode($value, JSON_PRETTY_PRINT); + } + + return json_encode($value); + } + + private function buildTranslationKey($translatedText) + { + $translatedText = preg_replace('/(\s+)/', '', $translatedText); + $translatedText = preg_replace("/[^A-Za-z0-9]/", '', $translatedText); + $translatedText = trim($translatedText); + + return $this->removeNonJsonCompatibleCharacters($translatedText); + } + + private function removeNonJsonCompatibleCharacters($text) + { + return preg_replace('/[^(\x00-\x7F)]*/', '', $text); + } + + /** + * Copies the given method and all needed use statements into an existing class. The target class name will be + * built based on the given $replace argument. + * @param string $sourceClassName + * @param string $methodName + * @param array $replace + */ + protected function copyTemplateMethodToExisitingClass($sourceClassName, $methodName, $replace) + { + $targetClassName = $this->replaceContent($replace, $sourceClassName); + + if (Development::methodExists($targetClassName, $methodName)) { + // we do not want to add the same method twice + return; + } + + Development::checkMethodExists($sourceClassName, $methodName, 'Cannot copy template method: '); + + $targetClass = new \ReflectionClass($targetClassName); + $file = new \SplFileObject($targetClass->getFileName()); + + $methodCode = Development::getMethodSourceCode($sourceClassName, $methodName); + $methodCode = $this->replaceContent($replace, $methodCode); + $methodLine = $targetClass->getEndLine() - 1; + + $sourceUses = Development::getUseStatements($sourceClassName); + $targetUses = Development::getUseStatements($targetClassName); + $usesToAdd = array_diff($sourceUses, $targetUses); + if (empty($usesToAdd)) { + $useCode = ''; + } else { + $useCode = "\nuse " . implode("\nuse ", $usesToAdd) . "\n"; + } + + // search for namespace line before the class starts + $useLine = 0; + foreach (new \LimitIterator($file, 0, $targetClass->getStartLine()) as $index => $line) { + if (0 === strpos(trim($line), 'namespace ')) { + $useLine = $index + 1; + break; + } + } + + $newClassCode = ''; + foreach(new \LimitIterator($file) as $index => $line) { + if ($index == $methodLine) { + $newClassCode .= $methodCode; + } + + if (0 !== $useLine && $index == $useLine) { + $newClassCode .= $useCode; + } + + $newClassCode .= $line; + } + + file_put_contents($targetClass->getFileName(), $newClassCode); + } + /** * @param string $templateFolder full path like /home/... * @param string $pluginName @@ -70,13 +202,9 @@ abstract class GeneratePluginBase extends ConsoleCommand $this->createFolderWithinPluginIfNotExists($pluginName, $fileNamePlugin); } else { $template = file_get_contents($file); - foreach ($replace as $key => $value) { - $template = str_replace($key, $value, $template); - } + $template = $this->replaceContent($replace, $template); - foreach ($replace as $key => $value) { - $fileNamePlugin = str_replace($key, $value, $fileNamePlugin); - } + $fileNamePlugin = $this->replaceContent($replace, $fileNamePlugin); $this->createFileWithinPluginIfNotExists($pluginName, $fileNamePlugin, $template); } @@ -140,4 +268,19 @@ abstract class GeneratePluginBase extends ConsoleCommand return $pluginName; } + private function getPathToCore() + { + $path = PIWIK_INCLUDE_PATH . '/core'; + return $path; + } + + private function replaceContent($replace, $contentToReplace) + { + foreach ((array) $replace as $key => $value) { + $contentToReplace = str_replace($key, $value, $contentToReplace); + } + + return $contentToReplace; + } + } diff --git a/plugins/CoreConsole/Commands/GenerateReport.php b/plugins/CoreConsole/Commands/GenerateReport.php index 7288fb6a16b0f6fd8c39594a100966e44c81ad53..d1e5cbbcf9c019d0cbfcb109f998adecaa4b3b2a 100644 --- a/plugins/CoreConsole/Commands/GenerateReport.php +++ b/plugins/CoreConsole/Commands/GenerateReport.php @@ -15,10 +15,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -/** - * TODO we should automatically create a method in the API (works currently only if there is no API.php yet) - * TODO automatically create or modify translation file for instance for report name - */ class GenerateReport extends GeneratePluginBase { protected function configure() @@ -49,13 +45,20 @@ class GenerateReport extends GeneratePluginBase 'getExampleReport' => lcfirst($apiName), 'getApiReport' => lcfirst($apiName), 'ExampleCategory' => $category, - 'ExampleReportName' => $reportName, + 'ExampleReportName' => $this->makeTranslationIfPossible($pluginName, $reportName), 'ExampleReportDocumentation' => $documentation, '999' => $order, 'new ExitPageUrl()' => $dimension, 'use Piwik\Plugins\Actions\Columns\ExitPageUrl;' => $dimensionClass ); - $whitelistFiles = array('/Reports', '/Reports/Base.php', '/Reports/GetExampleReport.php', '/API.php'); + + $whitelistFiles = array('/Reports', '/Reports/Base.php', '/Reports/GetExampleReport.php'); + + if (file_exists($this->getPluginPath($pluginName) . '/API.php')) { + $this->copyTemplateMethodToExisitingClass('Piwik\Plugins\ExamplePlugin\API', 'getExampleReport', $replace); + } else { + $whitelistFiles[] = '/API.php'; + } $this->copyTemplateToPlugin($exampleFolder, $pluginName, $replace, $whitelistFiles); @@ -224,7 +227,7 @@ class GenerateReport extends GeneratePluginBase $name = $dimension->getName(); if (!empty($name)) { $dimensions[$name] = get_class($dimension); - $dimensionNames[] = $name; + $dimensionNames[] = $name; } } } diff --git a/plugins/CoreConsole/Commands/GenerateUpdate.php b/plugins/CoreConsole/Commands/GenerateUpdate.php new file mode 100644 index 0000000000000000000000000000000000000000..745918666aaf9e112b73c159395c755a525754b6 --- /dev/null +++ b/plugins/CoreConsole/Commands/GenerateUpdate.php @@ -0,0 +1,118 @@ +<?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\Plugins\CoreConsole\Commands; + +use Piwik\Plugin; +use Piwik\Updater; +use Piwik\Version; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class GenerateUpdate extends GeneratePluginBase +{ + protected function configure() + { + $this->setName('generate:update') + ->setDescription('Adds a new update to an existing plugin or "core"') + ->addOption('component', null, InputOption::VALUE_REQUIRED, 'The name of an existing plugin or "core"'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $component = $this->getComponent($input, $output); + + $version = $this->getVersion($component); + $namespace = $this->getNamespace($component); + $className = $this->getUpdateClassName($component, $version); + + $exampleFolder = PIWIK_INCLUDE_PATH . '/plugins/ExamplePlugin'; + $replace = array('Piwik\Plugins\ExamplePlugin' => $namespace, + 'ExamplePlugin' => $component, + 'Updates_0_0_2' => $className, + '0.0.2' => $version); + $whitelistFiles = array('/Updates', '/Updates/0.0.2.php'); + + $this->copyTemplateToPlugin($exampleFolder, $component, $replace, $whitelistFiles); + + $this->writeSuccessMessage($output, array( + sprintf('Updates/%s.php for %s generated.', $version, $component), + 'You should have a look at the method update() or getSql() now.', + 'Enjoy!' + )); + } + + private function getUpdateClassName($component, $version) + { + $updater = new Updater(); + $className = $updater->getUpdateClassName($component, $version); + $parts = explode('\\', $className); + + return end($parts); + } + + private function getVersion($component) + { + if ($component === 'core') { + return Version::VERSION; + } + + $pluginManager = Plugin\Manager::getInstance(); + + if ($pluginManager->isPluginLoaded($component)) { + $plugin = $pluginManager->getLoadedPlugin($component); + } else { + $plugin = new Plugin($component); + } + + return $plugin->getVersion(); + } + + private function getNamespace($component) + { + $updater = new Updater(); + $className = $updater->getUpdateClassName($component, 'xx'); + $className = str_replace('Updates_xx', '', $className); + $className = trim($className, '\\'); + + return $className; + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @return array + * @throws \RunTimeException + */ + private function getComponent(InputInterface $input, OutputInterface $output) + { + $components = $this->getPluginNames(); + $components[] = 'core'; + + $validate = function ($component) use ($components) { + if (!in_array($component, $components)) { + throw new \InvalidArgumentException('You have to enter a name of an existing plugin or "core".'); + } + + return $component; + }; + + $component = $input->getOption('component'); + + if (empty($component)) { + $dialog = $this->getHelperSet()->get('dialog'); + $component = $dialog->askAndValidate($output, 'Enter the name of your plugin or "core": ', $validate, false, null, $components); + } else { + $validate($component); + } + + return $component; + } +} diff --git a/plugins/CoreConsole/Commands/GenerateVisualizationPlugin.php b/plugins/CoreConsole/Commands/GenerateVisualizationPlugin.php index abb9d29cb58689267b0d20d498baad082fc72e1f..b2f3d9ea11ab4849b3a7bd0d6bbbe271ddd1726c 100644 --- a/plugins/CoreConsole/Commands/GenerateVisualizationPlugin.php +++ b/plugins/CoreConsole/Commands/GenerateVisualizationPlugin.php @@ -43,7 +43,7 @@ class GenerateVisualizationPlugin extends GeneratePlugin $replace = array( 'SimpleTable' => $visualizationName, 'simpleTable' => lcfirst($visualizationName), - 'Simple Table' => $visualizationName, + 'Simple Table' => $this->makeTranslationIfPossible($pluginName, $visualizationName), 'ExampleVisualization' => $pluginName, 'ExampleVisualizationDescription' => $description ); @@ -72,7 +72,7 @@ class GenerateVisualizationPlugin extends GeneratePlugin } if (!ctype_alnum($visualizationName)) { - throw new \RunTimeException(sprintf('The visualization name %s is not valid', $visualizationName)); + throw new \RunTimeException(sprintf('The visualization name %s is not valid (only AlNum allowed)', $visualizationName)); } return $visualizationName; @@ -82,7 +82,7 @@ class GenerateVisualizationPlugin extends GeneratePlugin if (empty($visualizationName)) { $dialog = $this->getHelperSet()->get('dialog'); - $visualizationName = $dialog->askAndValidate($output, 'Enter a visualization name: ', $validate); + $visualizationName = $dialog->askAndValidate($output, 'Enter a visualization name (only AlNum allowed): ', $validate); } else { $validate($visualizationName); } diff --git a/plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php b/plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php index 9f9e9170f3a71b9d9b7c0ead4211ba9f0fefdd3a..ea8e1b9f7ef46e47595e4c2f2a97a72f2e15c100 100644 --- a/plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php +++ b/plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php @@ -34,7 +34,6 @@ class GetVisitInformationPerServerTime extends Base $view->requestConfig->filter_limit = 24; $view->requestConfig->request_parameters_to_modify['hideFutureHoursWhenToday'] = 1; - $view->config->show_goals = true; $view->config->addTranslation('label', $this->dimension->getName()); if ($view->isViewDataTableId(Graph::ID)) {