Download core/API/Proxy.php from Leon4gr45/matomo: direct link, hf CLI and curl.
- Browser
- Download file 29.6 kB
-
https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/core/API/Proxy.php
- Command line
-
hf download hf://spaces/Leon4gr45/matomo/core/API/Proxy.php
-
curl -L -o Proxy.php https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/core/API/Proxy.php
29.6 kB
| /** | |
| * Matomo - free/libre analytics platform | |
| * | |
| * @link https://matomo.org | |
| * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later | |
| */ | |
| namespace Piwik\API; | |
| use Exception; | |
| use Piwik\Http\BadRequestException; | |
| use Piwik\Common; | |
| use Piwik\Container\StaticContainer; | |
| use Piwik\Context; | |
| use Piwik\Piwik; | |
| use Piwik\Plugin\API; | |
| use Piwik\Plugin\Manager; | |
| use ReflectionClass; | |
| use ReflectionMethod; | |
| // prevent upgrade error eg from Matomo 3.x to Matomo 4.x. Refs https://github.com/matomo-org/matomo/pull/16468 | |
| // the `false` is important otherwise it would fail and try to load the proxy.php file again. | |
| if (!class_exists('Piwik\API\NoDefaultValue', false)) { | |
| // phpcs:ignoreFile PSR1.Classes.ClassDeclaration.MultipleClasses | |
| class NoDefaultValue | |
| { | |
| } | |
| } | |
| /** | |
| * Proxy is a singleton that has the knowledge of every method available, their parameters | |
| * and default values. | |
| * Proxy receives all the API calls requests via call() and forwards them to the right | |
| * object, with the parameters in the right order. | |
| */ | |
| class Proxy | |
| { | |
| // array of already registered plugins names | |
| protected $alreadyRegistered = array(); | |
| protected $metadataArray = array(); | |
| private $hideIgnoredFunctions = true; | |
| // when a parameter doesn't have a default value we use this | |
| private $noDefaultValue; | |
| public function __construct() | |
| { | |
| $this->noDefaultValue = new NoDefaultValue(); | |
| } | |
| public static function getInstance() | |
| { | |
| return StaticContainer::get(self::class); | |
| } | |
| /** | |
| * Returns array containing reflection meta data for all the loaded classes | |
| * eg. number of parameters, method names, etc. | |
| * | |
| * @return array | |
| */ | |
| public function getMetadata() | |
| { | |
| ksort($this->metadataArray); | |
| return $this->metadataArray; | |
| } | |
| /** | |
| * Registers the API information of a given module. | |
| * | |
| * The module to be registered must be | |
| * - a singleton (providing a getInstance() method) | |
| * - the API file must be located in plugins/ModuleName/API.php | |
| * for example plugins/Referrers/API.php | |
| * | |
| * The method will introspect the methods, their parameters, etc. | |
| * | |
| * @param string $className Fully qualified API class name, eg. "\Piwik\Plugins\Referrers\API" | |
| */ | |
| public function registerClass($className) | |
| { | |
| if (isset($this->alreadyRegistered[$className])) { | |
| return; | |
| } | |
| $this->includeApiFile($className); | |
| $this->checkClassIsSingleton($className); | |
| $rClass = new ReflectionClass($className); | |
| if (!$this->shouldHideAPIMethod($rClass->getDocComment())) { | |
| foreach ($rClass->getMethods() as $method) { | |
| $this->loadMethodMetadata($className, $method); | |
| } | |
| $this->setDocumentation($rClass, $className); | |
| $this->alreadyRegistered[$className] = true; | |
| } | |
| } | |
| /** | |
| * Will be displayed in the API page | |
| * | |
| * @param ReflectionClass $rClass Instance of ReflectionClass | |
| * @param string $className Name of the class | |
| */ | |
| private function setDocumentation($rClass, $className) | |
| { | |
| // Doc comment | |
| $doc = $rClass->getDocComment(); | |
| $doc = $this->removeDocblockAnnotationBlocks($doc, 'phpstan'); | |
| $doc = str_replace(" * " . PHP_EOL, "<br>", $doc); | |
| // boldify the first line only if there is more than one line, otherwise too much bold | |
| if (substr_count($doc, '<br>') > 1) { | |
| $firstLineBreak = strpos($doc, "<br>"); | |
| $doc = "<div class='apiFirstLine'>" . substr($doc, 0, $firstLineBreak) . "</div>" . substr($doc, $firstLineBreak + strlen("<br>")); | |
| } | |
| $doc = preg_replace("/(@package)[a-z _A-Z]*/", "", $doc); | |
| $doc = preg_replace("/(@method).*/", "", $doc); | |
| $doc = str_replace(array("\t", "\n", "/**", "*/", " * ", " *", " ", "\t*", " * @package"), " ", $doc); | |
| // replace 'foo' and `bar` and "foobar" with code blocks... much magic | |
| $doc = preg_replace('/`(.*?)`/', '<code>$1</code>', $doc); | |
| $this->metadataArray[$className]['__documentation'] = $doc; | |
| } | |
| /** | |
| * Removes docblock annotations and their continuation lines. | |
| * | |
| * For example, this removes `@phpstan-type` and the following multiline shape definition. | |
| * | |
| * @param string|false $doc | |
| * @param string $annotationPrefix | |
| * @return string|false | |
| */ | |
| private function removeDocblockAnnotationBlocks($doc, $annotationPrefix) | |
| { | |
| if (!is_string($doc) || $doc === '') { | |
| return $doc; | |
| } | |
| $lines = preg_split('/\R/', $doc); | |
| $result = []; | |
| $isSkipping = false; | |
| foreach ($lines as $line) { | |
| if (preg_match('/^\s*\*\s*@' . preg_quote($annotationPrefix, '/') . '\S*/', $line)) { | |
| $isSkipping = true; | |
| continue; | |
| } | |
| if ($isSkipping) { | |
| // stop skipping once a new annotation starts | |
| if (preg_match('/^\s*\*\s*@\S+/', $line)) { | |
| $isSkipping = false; | |
| } elseif (preg_match('/^\s*\*\/\s*$/', $line)) { | |
| $isSkipping = false; | |
| } else { | |
| continue; | |
| } | |
| } | |
| $result[] = $line; | |
| } | |
| return implode(PHP_EOL, $result); | |
| } | |
| /** | |
| * Returns number of classes already loaded | |
| * @return int | |
| */ | |
| public function getCountRegisteredClasses() | |
| { | |
| return count($this->alreadyRegistered); | |
| } | |
| /** | |
| * Will execute $className->$methodName($parametersValues) | |
| * If any error is detected (wrong number of parameters, method not found, class not found, etc.) | |
| * it will throw an exception | |
| * | |
| * @param string $className The class name (eg. API) | |
| * @param string $methodName The method name | |
| * @param array $parametersRequest The parameters pairs (name=>value) | |
| * | |
| * @return mixed|null | |
| * @throws Exception|\Piwik\NoAccessException | |
| */ | |
| public function call($className, $methodName, $parametersRequest) | |
| { | |
| // Temporarily sets the Request array to this API call context | |
| return Context::executeWithQueryParameters($parametersRequest, function () use ($className, $methodName, $parametersRequest) { | |
| $this->registerClass($className); | |
| $request = new \Piwik\Request($parametersRequest); | |
| /** | |
| * instantiate the object | |
| * @var API $object | |
| */ | |
| $object = $className::getInstance(); | |
| // check method exists | |
| $this->checkMethodExists($className, $methodName); | |
| // get the list of parameters required by the method | |
| $parameterNamesDefaultValuesAndTypes = $this->getParametersListWithTypes($className, $methodName); | |
| // load parameters in the right order, etc. | |
| if ($object->usesAutoSanitizeInputParams() && !$this->usesUnsanitizedInputParams($className, $methodName)) { | |
| $finalParameters = $this->getSanitizedRequestParametersArray($parameterNamesDefaultValuesAndTypes, $request->getParameters()); | |
| } else { | |
| $finalParameters = $this->getRequestParametersArray($parameterNamesDefaultValuesAndTypes, $request); | |
| } | |
| // allow plugins to manipulate the value | |
| $pluginName = $this->getModuleNameFromClassName($className); | |
| $returnedValue = null; | |
| /** | |
| * Triggered before an API request is dispatched. | |
| * | |
| * This event can be used to modify the arguments passed to one or more API methods. | |
| * | |
| * **Example** | |
| * | |
| * Piwik::addAction('API.Request.dispatch', function (&$parameters, $pluginName, $methodName) { | |
| * if ($pluginName == 'Actions') { | |
| * if ($methodName == 'getPageUrls') { | |
| * // ... do something ... | |
| * } else { | |
| * // ... do something else ... | |
| * } | |
| * } | |
| * }); | |
| * | |
| * @param array &$finalParameters List of parameters that will be passed to the API method. | |
| * @param string $pluginName The name of the plugin the API method belongs to. | |
| * @param string $methodName The name of the API method that will be called. | |
| */ | |
| Piwik::postEvent('API.Request.dispatch', array(&$finalParameters, $pluginName, $methodName)); | |
| /** | |
| * Triggered before an API request is dispatched. | |
| * | |
| * This event exists for convenience and is triggered directly after the {@hook API.Request.dispatch} | |
| * event is triggered. It can be used to modify the arguments passed to a **single** API method. | |
| * | |
| * _Note: This is can be accomplished with the {@hook API.Request.dispatch} event as well, however | |
| * event handlers for that event will have to do more work._ | |
| * | |
| * **Example** | |
| * | |
| * Piwik::addAction('API.Actions.getPageUrls', function (&$parameters) { | |
| * // force use of a single website. for some reason. | |
| * $parameters['idSite'] = 1; | |
| * }); | |
| * | |
| * @param array &$finalParameters List of parameters that will be passed to the API method. | |
| */ | |
| Piwik::postEvent(sprintf('API.%s.%s', $pluginName, $methodName), array(&$finalParameters)); | |
| /** | |
| * Triggered before an API request is dispatched. | |
| * | |
| * Use this event to intercept an API request and execute your own code instead. If you set | |
| * `$returnedValue` in a handler for this event, the original API method will not be executed, | |
| * and the result will be what you set in the event handler. | |
| * | |
| * @param mixed &$returnedValue Set this to set the result and preempt normal API invocation. | |
| * @param array &$finalParameters List of parameters that will be passed to the API method. | |
| * @param string $pluginName The name of the plugin the API method belongs to. | |
| * @param string $methodName The name of the API method that will be called. | |
| * @param array $parametersRequest The query parameters for this request. | |
| */ | |
| Piwik::postEvent('API.Request.intercept', [&$returnedValue, $finalParameters, $pluginName, $methodName, $parametersRequest]); | |
| $apiParametersInCorrectOrder = array(); | |
| foreach ($parameterNamesDefaultValuesAndTypes as $name => $parameter) { | |
| if (isset($finalParameters[$name]) || array_key_exists($name, $finalParameters)) { | |
| $apiParametersInCorrectOrder[] = $finalParameters[$name]; | |
| } | |
| } | |
| // call the method if a hook hasn't already set an output variable | |
| if ($returnedValue === null) { | |
| $returnedValue = call_user_func_array(array($object, $methodName), $apiParametersInCorrectOrder); | |
| } | |
| $endHookParams = array( | |
| &$returnedValue, | |
| array('className' => $className, | |
| 'module' => $pluginName, | |
| 'action' => $methodName, | |
| 'parameters' => $finalParameters) | |
| ); | |
| /** | |
| * Triggered directly after an API request is dispatched. | |
| * | |
| * This event exists for convenience and is triggered immediately before the | |
| * {@hook API.Request.dispatch.end} event. It can be used to modify the output of a **single** | |
| * API method. | |
| * | |
| * _Note: This can be accomplished with the {@hook API.Request.dispatch.end} event as well, | |
| * however event handlers for that event will have to do more work._ | |
| * | |
| * **Example** | |
| * | |
| * // append (0 hits) to the end of row labels whose row has 0 hits | |
| * Piwik::addAction('API.Actions.getPageUrls', function (&$returnValue, $info)) { | |
| * $returnValue->filter('ColumnCallbackReplace', 'label', function ($label, $hits) { | |
| * if ($hits === 0) { | |
| * return $label . " (0 hits)"; | |
| * } else { | |
| * return $label; | |
| * } | |
| * }, null, array('nb_hits')); | |
| * } | |
| * | |
| * @param mixed &$returnedValue The API method's return value. Can be an object, such as a | |
| * {@link Piwik\DataTable DataTable} instance. | |
| * could be a {@link Piwik\DataTable DataTable}. | |
| * @param array $extraInfo An array holding information regarding the API request. Will | |
| * contain the following data: | |
| * | |
| * - **className**: The namespace-d class name of the API instance | |
| * that's being called. | |
| * - **module**: The name of the plugin the API request was | |
| * dispatched to. | |
| * - **action**: The name of the API method that was executed. | |
| * - **parameters**: The array of parameters passed to the API | |
| * method. | |
| */ | |
| Piwik::postEvent(sprintf('API.%s.%s.end', $pluginName, $methodName), $endHookParams); | |
| /** | |
| * Triggered directly after an API request is dispatched. | |
| * | |
| * This event can be used to modify the output of any API method. | |
| * | |
| * **Example** | |
| * | |
| * // append (0 hits) to the end of row labels whose row has 0 hits for any report that has the 'nb_hits' metric | |
| * Piwik::addAction('API.Actions.getPageUrls.end', function (&$returnValue, $info)) { | |
| * // don't process non-DataTable reports and reports that don't have the nb_hits column | |
| * if (!($returnValue instanceof DataTableInterface) | |
| * || in_array('nb_hits', $returnValue->getColumns()) | |
| * ) { | |
| * return; | |
| * } | |
| * | |
| * $returnValue->filter('ColumnCallbackReplace', 'label', function ($label, $hits) { | |
| * if ($hits === 0) { | |
| * return $label . " (0 hits)"; | |
| * } else { | |
| * return $label; | |
| * } | |
| * }, null, array('nb_hits')); | |
| * } | |
| * | |
| * @param mixed &$returnedValue The API method's return value. Can be an object, such as a | |
| * {@link Piwik\DataTable DataTable} instance. | |
| * @param array $extraInfo An array holding information regarding the API request. Will | |
| * contain the following data: | |
| * | |
| * - **className**: The namespace-d class name of the API instance | |
| * that's being called. | |
| * - **module**: The name of the plugin the API request was | |
| * dispatched to. | |
| * - **action**: The name of the API method that was executed. | |
| * - **parameters**: The array of parameters passed to the API | |
| * method. | |
| */ | |
| Piwik::postEvent('API.Request.dispatch.end', $endHookParams); | |
| return $returnedValue; | |
| }); | |
| } | |
| /** | |
| * Returns the parameters names and default values for the method $name | |
| * of the class $class | |
| * | |
| * @param string $class The class name | |
| * @param string $name The method name | |
| * @return array Format array( | |
| * 'testParameter' => null, // no default value | |
| * 'life' => 42, // default value = 42 | |
| * 'date' => 'yesterday', | |
| * ); | |
| */ | |
| public function getParametersList($class, $name) | |
| { | |
| return array_combine( | |
| array_keys($this->metadataArray[$class][$name]['parameters']), | |
| array_column($this->metadataArray[$class][$name]['parameters'], 'default') | |
| ); | |
| } | |
| /** | |
| * Returns the parameters names, default values and types for the method $name | |
| * of the class $class | |
| * | |
| * @param string $class The class name | |
| * @param string $name The method name | |
| * @return array Format array( | |
| * 'testParameter' => ['default' => null, 'type' => null], // no default value | |
| * 'life' => ['default' => 42, 'type' => 'int'], // default value 42, type hint is int | |
| * ); | |
| */ | |
| public function getParametersListWithTypes($class, $name) | |
| { | |
| return $this->metadataArray[$class][$name]['parameters']; | |
| } | |
| /** | |
| * Check if given method name is deprecated or not. | |
| */ | |
| public function isDeprecatedMethod($class, $methodName) | |
| { | |
| return $this->metadataArray[$class][$methodName]['isDeprecated'] ?? false; | |
| } | |
| /** | |
| * Check if given method uses unsanitized input parameters. | |
| */ | |
| public function usesUnsanitizedInputParams($class, $methodName) | |
| { | |
| return $this->metadataArray[$class][$methodName]['unsanitizedInputParams'] ?? false; | |
| } | |
| /** | |
| * Returns the 'moduleName' part of '\\Piwik\\Plugins\\moduleName\\API' | |
| * | |
| * @param string $className "API" | |
| * @return string "Referrers" | |
| */ | |
| public function getModuleNameFromClassName($className) | |
| { | |
| return str_replace(array('\\Piwik\\Plugins\\', '\\API'), '', $className); | |
| } | |
| public function isExistingApiAction($pluginName, $apiAction) | |
| { | |
| $namespacedApiClassName = "\\Piwik\\Plugins\\$pluginName\\API"; | |
| $api = $namespacedApiClassName::getInstance(); | |
| return method_exists($api, $apiAction); | |
| } | |
| public function buildApiActionName($pluginName, $apiAction) | |
| { | |
| return sprintf("%s.%s", $pluginName, $apiAction); | |
| } | |
| /** | |
| * Sets whether to hide '@ignore'd functions from method metadata or not. | |
| * | |
| * @param bool $hideIgnoredFunctions | |
| */ | |
| public function setHideIgnoredFunctions($hideIgnoredFunctions) | |
| { | |
| $this->hideIgnoredFunctions = $hideIgnoredFunctions; | |
| // make sure metadata gets reloaded | |
| $this->alreadyRegistered = array(); | |
| $this->metadataArray = array(); | |
| } | |
| /** | |
| * Returns an array containing the *sanitized* values of the parameters to pass to the method to call | |
| * | |
| * @param array $requiredParameters array mapping parameter name to ['default' => value, 'type' => type] | |
| * @param array $parametersRequest | |
| * @throws Exception | |
| * @return array values to pass to the function call | |
| */ | |
| private function getSanitizedRequestParametersArray($requiredParameters, $parametersRequest) | |
| { | |
| $finalParameters = []; | |
| foreach ($requiredParameters as $name => $parameter) { | |
| try { | |
| $defaultValue = $parameter['default']; | |
| $type = $parameter['type']; | |
| $request = new \Piwik\Request($parametersRequest); | |
| if (in_array($name, ['segment', 'password', 'passwordConfirmation']) && !empty($parametersRequest[$name])) { | |
| // special handling for some parameters: | |
| // segment: we do not want to sanitize user input as it would break the segment encoding | |
| // password / passwordConfirmation: sanitizing this parameters might change special chars in passwords, breaking login and confirmation boxes | |
| $requestValue = ($parametersRequest[$name]); | |
| } elseif ($defaultValue instanceof NoDefaultValue) { | |
| if ($type === 'bool') { | |
| $requestValue = $request->getBoolParameter($name); | |
| } else { | |
| $requestValue = Common::getRequestVar($name, null, $type, $parametersRequest); | |
| } | |
| } else { | |
| try { | |
| if ($type === 'bool') { | |
| $requestValue = $request->getBoolParameter($name, $defaultValue); | |
| } else { | |
| $requestValue = Common::getRequestVar($name, $defaultValue, $type, $parametersRequest); | |
| } | |
| } catch (Exception $e) { | |
| // Special case: empty parameter in the URL, should return the empty string, if no incompatible type is defined | |
| if (isset($parametersRequest[$name]) | |
| && $parametersRequest[$name] === '' | |
| && (empty($type) || $type === 'string') | |
| ) { | |
| $requestValue = ''; | |
| } else { | |
| $requestValue = $defaultValue; | |
| } | |
| } | |
| } | |
| } catch (Exception $e) { | |
| throw new BadRequestException(Piwik::translate('General_PleaseSpecifyValue', [$name])); | |
| } | |
| $finalParameters[$name] = $requestValue; | |
| } | |
| return $finalParameters; | |
| } | |
| /** | |
| * Returns an array containing the values of the parameters to pass to the method to call | |
| * | |
| * @param array $requiredParameters array mapping parameter name to ['default' => value, 'type' => type] | |
| * @param \Piwik\Request $request | |
| * @throws Exception | |
| * @return array values to pass to the function call | |
| */ | |
| private function getRequestParametersArray($requiredParameters, \Piwik\Request $request): array | |
| { | |
| $finalParameters = []; | |
| foreach ($requiredParameters as $name => $parameter) { | |
| try { | |
| $defaultValue = $parameter['default']; | |
| $type = $parameter['type'] ?? ''; | |
| $requestValue = null; | |
| switch (strtolower($type)) { | |
| case 'bool': | |
| $method = 'getBoolParameter'; | |
| break; | |
| case 'int': | |
| $method = 'getIntegerParameter'; | |
| break; | |
| case 'string': | |
| $method = 'getStringParameter'; | |
| break; | |
| case 'float': | |
| $method = 'getFloatParameter'; | |
| break; | |
| case 'array': | |
| $method = 'getArrayParameter'; | |
| break; | |
| default: | |
| $method = 'getParameter'; | |
| } | |
| if ($defaultValue instanceof NoDefaultValue) { | |
| $requestValue = $request->$method($name); | |
| } elseif ($defaultValue === null) { | |
| try { | |
| $requestValue = $request->$method($name); | |
| } catch (\InvalidArgumentException $e) { | |
| $requestValue = null; | |
| } | |
| } else { | |
| $requestValue = $request->$method($name, $defaultValue); | |
| } | |
| } catch (Exception $e) { | |
| throw new BadRequestException(Piwik::translate('General_PleaseSpecifyValue', [$name])); | |
| } | |
| $finalParameters[$name] = $requestValue; | |
| } | |
| return $finalParameters; | |
| } | |
| /** | |
| * Includes the class API by looking up plugins/xxx/API.php | |
| * | |
| * @param string $fileName api class name eg. "API" | |
| * @throws Exception | |
| */ | |
| private function includeApiFile($fileName) | |
| { | |
| $module = self::getModuleNameFromClassName($fileName); | |
| $path = Manager::getPluginDirectory($module) . '/API.php'; | |
| if (is_readable($path)) { | |
| require_once $path; // prefixed by PIWIK_INCLUDE_PATH | |
| } else { | |
| throw new Exception("API module $module not found."); | |
| } | |
| } | |
| /** | |
| * @param string $class name of a class | |
| * @param ReflectionMethod $method instance of ReflectionMethod | |
| */ | |
| private function loadMethodMetadata($class, $method) | |
| { | |
| if (!$this->checkIfMethodIsAvailable($method)) { | |
| return; | |
| } | |
| $name = $method->getName(); | |
| $parameters = $method->getParameters(); | |
| $docComment = $method->getDocComment(); | |
| $aParameters = array(); | |
| foreach ($parameters as $parameter) { | |
| $nameVariable = $parameter->getName(); | |
| $defaultValue = $this->noDefaultValue; | |
| if ($parameter->isDefaultValueAvailable()) { | |
| $defaultValue = $parameter->getDefaultValue(); | |
| } | |
| $type = $parameter->getType(); | |
| // In case no default value is defined in the method, but the type hint allows null, we assume null as default value | |
| if ($type && $type->allowsNull() && $defaultValue === $this->noDefaultValue) { | |
| $defaultValue = null; | |
| } | |
| $aParameters[$nameVariable] = [ | |
| 'default' => $defaultValue, | |
| 'type' => ($type && $type->isBuiltin()) ? $type->getName() : null, | |
| 'allowsNull' => $type ? $type->allowsNull() : $defaultValue === null, | |
| ]; | |
| } | |
| $this->metadataArray[$class][$name]['parameters'] = $aParameters; | |
| $this->metadataArray[$class][$name]['numberOfRequiredParameters'] = $method->getNumberOfRequiredParameters(); | |
| $this->metadataArray[$class][$name]['isDeprecated'] = false !== strstr($docComment, '@deprecated'); | |
| $this->metadataArray[$class][$name]['unsanitizedInputParams'] = false !== strstr($docComment, '@unsanitized'); | |
| } | |
| /** | |
| * Checks that the method exists in the class | |
| * | |
| * @param string $className The class name | |
| * @param string $methodName The method name | |
| * @throws Exception If the method is not found | |
| */ | |
| private function checkMethodExists($className, $methodName) | |
| { | |
| if (!$this->isMethodAvailable($className, $methodName)) { | |
| throw new BadRequestException(Piwik::translate('General_ExceptionMethodNotFound', [$methodName, $className])); | |
| } | |
| } | |
| /** | |
| * @param string|false $docComment | |
| * @return bool | |
| */ | |
| public function shouldHideAPIMethod($docComment) | |
| { | |
| $hideLine = strstr($docComment, '@hide'); | |
| if ($hideLine === false) { | |
| return false; | |
| } | |
| $hideLine = trim($hideLine); | |
| $hideLine .= ' '; | |
| $token = trim(strtok($hideLine, " "), "\n"); | |
| $hide = false; | |
| if (!empty($token)) { | |
| /** | |
| * This event exists for checking whether a Plugin API class or a Plugin API method tagged | |
| * with a `@hideXYZ` should be hidden in the API listing. | |
| * | |
| * @param bool &$hide whether to hide APIs tagged with $token should be displayed. | |
| */ | |
| Piwik::postEvent(sprintf('API.DocumentationGenerator.%s', $token), array(&$hide)); | |
| } | |
| return $hide; | |
| } | |
| /** | |
| * @param ReflectionMethod $method | |
| * @return bool | |
| */ | |
| protected function checkIfMethodIsAvailable(ReflectionMethod $method) | |
| { | |
| if (!$method->isPublic() || $method->isConstructor() || $method->getName() === 'getInstance') { | |
| return false; | |
| } | |
| if ($this->hideIgnoredFunctions && false !== strstr($method->getDocComment(), '@ignore')) { | |
| return false; | |
| } | |
| if ($this->shouldHideAPIMethod($method->getDocComment())) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| /** | |
| * Returns true if the method is found in the API of the given class name. | |
| * | |
| * @param string $className The class name | |
| * @param string $methodName The method name | |
| * @return bool | |
| */ | |
| private function isMethodAvailable($className, $methodName) | |
| { | |
| return isset($this->metadataArray[$className][$methodName]); | |
| } | |
| /** | |
| * Checks that the class is a Singleton (presence of the getInstance() method) | |
| * | |
| * @param string $className The class name | |
| * @throws Exception If the class is not a Singleton | |
| */ | |
| private function checkClassIsSingleton($className) | |
| { | |
| if (!method_exists($className, "getInstance")) { | |
| throw new Exception("$className that provide an API must be Singleton and have a 'public static function getInstance()' method."); | |
| } | |
| } | |
| } | |