public function test_CheckIfMethodComment_DoesNotContainHideAnnotation() { $annotation = '@not found here'; EventDispatcher::getInstance()->addObserver('API.DocumentationGenerator.@hello', function (&$hide) { $hide = true; }); $this->assertEquals(Proxy::getInstance()->shouldHideAPIMethod($annotation), false); }
public function listAllAPI() { $view = new View("@API/listAllAPI"); $this->setGeneralVariablesView($view); $ApiDocumentation = new DocumentationGenerator(); $view->countLoadedAPI = Proxy::getInstance()->getCountRegisteredClasses(); $view->list_api_methods_with_links = $ApiDocumentation->getAllInterfaceString(); return $view->render(); }
/** * Renders a report depending on the configured ViewDataTable see {@link configureView()} and * {@link getDefaultTypeViewDataTable()}. If you want to customize the render process or just render any custom view * you can overwrite this method. * * @return string * @throws \Exception In case the given API action does not exist yet. * @api */ public function render() { $apiProxy = Proxy::getInstance(); if (!$apiProxy->isExistingApiAction($this->module, $this->action)) { throw new Exception("Invalid action name '{$this->action}' for '{$this->module}' plugin."); } $apiAction = $apiProxy->buildApiActionName($this->module, $this->action); $view = ViewDataTableFactory::build(null, $apiAction, $this->module . '.' . $this->action); $rendered = $view->render(); return $rendered; }
private function getAllApiMethods() { $result = array(); foreach (Proxy::getInstance()->getMetadata() as $class => $info) { $moduleName = Proxy::getInstance()->getModuleNameFromClassName($class); foreach ($info as $methodName => $infoMethod) { if ($this->shouldSkipApiMethod($moduleName, $methodName)) { continue; } $result[] = array($class, $moduleName, $methodName); } } return $result; }
/** * Convenience method that creates and renders a ViewDataTable for a API method. * * @param string|\Piwik\Plugin\Report $apiAction The name of the API action (eg, `'getResolution'`) or * an instance of an report. * @param bool $controllerAction The name of the Controller action name that is rendering the report. Defaults * to the `$apiAction`. * @param bool $fetch If `true`, the rendered string is returned, if `false` it is `echo`'d. * @throws \Exception if `$pluginName` is not an existing plugin or if `$apiAction` is not an * existing method of the plugin's API. * @return string|void See `$fetch`. * @api */ protected function renderReport($apiAction, $controllerAction = false) { if (empty($controllerAction) && is_string($apiAction)) { $report = Report::factory($this->pluginName, $apiAction); if (!empty($report)) { $apiAction = $report; } } if ($apiAction instanceof Report) { $this->checkSitePermission(); $apiAction->checkIsEnabled(); return $apiAction->render(); } $pluginName = $this->pluginName; /** @var Proxy $apiProxy */ $apiProxy = Proxy::getInstance(); if (!$apiProxy->isExistingApiAction($pluginName, $apiAction)) { throw new \Exception("Invalid action name '{$apiAction}' for '{$pluginName}' plugin."); } $apiAction = $apiProxy->buildApiActionName($pluginName, $apiAction); if ($controllerAction !== false) { $controllerAction = $pluginName . '.' . $controllerAction; } $view = ViewDataTableFactory::build(null, $apiAction, $controllerAction); $rendered = $view->render(); return $rendered; }
/** * @internal */ protected function loadDataTableFromAPI() { if (!is_null($this->dataTable)) { // data table is already there // this happens when setDataTable has been used return $this->dataTable; } // we build the request (URL) to call the API $request = $this->buildApiRequestArray(); $module = $this->requestConfig->getApiModuleToRequest(); $method = $this->requestConfig->getApiMethodToRequest(); PluginManager::getInstance()->checkIsPluginActivated($module); $class = ApiRequest::getClassNameAPI($module); $dataTable = Proxy::getInstance()->call($class, $method, $request); $response = new ResponseBuilder($format = 'original', $request); $response->disableSendHeader(); $response->disableDataTablePostProcessor(); $this->dataTable = $response->getResponse($dataTable, $module, $method); }
/** * Dispatches the API request to the appropriate API method and returns the result * after post-processing. * * Post-processing includes: * * - flattening if **flat** is 0 * - running generic filters unless **disable_generic_filters** is set to 1 * - URL decoding label column values * - running queued filters unless **disable_queued_filters** is set to 1 * - removing columns based on the values of the **hideColumns** and **showColumns** query parameters * - filtering rows if the **label** query parameter is set * - converting the result to the appropriate format (ie, XML, JSON, etc.) * * If `'original'` is supplied for the output format, the result is returned as a PHP * object. * * @throws PluginDeactivatedException if the module plugin is not activated. * @throws Exception if the requested API method cannot be called, if required parameters for the * API method are missing or if the API method throws an exception and the **format** * query parameter is **original**. * @return DataTable|Map|string The data resulting from the API call. */ public function process() { // read the format requested for the output data $outputFormat = strtolower(Common::getRequestVar('format', 'xml', 'string', $this->request)); // create the response $response = new ResponseBuilder($outputFormat, $this->request); $corsHandler = new CORSHandler(); $corsHandler->handle(); try { // read parameters $moduleMethod = Common::getRequestVar('method', null, 'string', $this->request); list($module, $method) = $this->extractModuleAndMethod($moduleMethod); $module = $this->renameModule($module); if (!\Piwik\Plugin\Manager::getInstance()->isPluginActivated($module)) { throw new PluginDeactivatedException($module); } $apiClassName = $this->getClassNameAPI($module); self::reloadAuthUsingTokenAuth($this->request); // call the method $returnedValue = Proxy::getInstance()->call($apiClassName, $method, $this->request); $toReturn = $response->getResponse($returnedValue, $module, $method); } catch (Exception $e) { Log::debug($e); $toReturn = $response->getResponseException($e); } return $toReturn; }
/** * Renders a report depending on the configured ViewDataTable see {@link configureView()} and * {@link getDefaultTypeViewDataTable()}. If you want to customize the render process or just render any custom view * you can overwrite this method. * * @return string * @throws \Exception In case the given API action does not exist yet. * @api */ public function render() { $viewDataTable = Common::getRequestVar('viewDataTable', false, 'string'); $fixed = Common::getRequestVar('forceView', 0, 'int'); $module = $this->getModule(); $action = $this->getAction(); $apiProxy = Proxy::getInstance(); if (!$apiProxy->isExistingApiAction($module, $action)) { throw new Exception("Invalid action name '{$module}' for '{$action}' plugin."); } $apiAction = $apiProxy->buildApiActionName($module, $action); $view = ViewDataTableFactory::build($viewDataTable, $apiAction, $module . '.' . $action, $fixed); return $view->render(); }
public function tearDown() { Proxy::getInstance()->setHideIgnoredFunctions(true); }
/** * Get a combined report of the *.get API methods. */ public function get($idSite, $period, $date, $segment = false, $columns = false) { Piwik::checkUserHasViewAccess($idSite); $columns = Piwik::getArrayFromApiParameter($columns); // build columns map for faster checks later on $columnsMap = array(); foreach ($columns as $column) { $columnsMap[$column] = true; } // find out which columns belong to which plugin $columnsByPlugin = array(); $meta = \Piwik\Plugins\API\API::getInstance()->getReportMetadata($idSite, $period, $date); foreach ($meta as $reportMeta) { // scan all *.get reports if ($reportMeta['action'] == 'get' && !isset($reportMeta['parameters']) && $reportMeta['module'] != 'API' && !empty($reportMeta['metrics'])) { $plugin = $reportMeta['module']; $allMetrics = array_merge($reportMeta['metrics'], @$reportMeta['processedMetrics'] ?: array()); foreach ($allMetrics as $column => $columnTranslation) { // a metric from this report has been requested if (isset($columnsMap[$column]) || empty($columnsMap)) { $columnsByPlugin[$plugin][] = $column; } } } } krsort($columnsByPlugin); $mergedDataTable = false; $params = compact('idSite', 'period', 'date', 'segment', 'idGoal'); foreach ($columnsByPlugin as $plugin => $columns) { // load the data $className = Request::getClassNameAPI($plugin); $params['columns'] = implode(',', $columns); $dataTable = Proxy::getInstance()->call($className, 'get', $params); $dataTable->filter(function (DataTable $table) { $table->clearQueuedFilters(); }); // merge reports if ($mergedDataTable === false) { $mergedDataTable = $dataTable; } else { $merger = new MergeDataTables(); $merger->mergeDataTables($mergedDataTable, $dataTable); } } if (!empty($columnsMap) && !empty($mergedDataTable)) { $mergedDataTable->queueFilter('ColumnDelete', array(false, array_keys($columnsMap))); } return $mergedDataTable; }
/** * Get a combined report of the *.get API methods. */ public function get($idSite, $period, $date, $segment = false, $columns = false) { $columns = Piwik::getArrayFromApiParameter($columns); // build columns map for faster checks later on $columnsMap = array(); foreach ($columns as $column) { $columnsMap[$column] = true; } // find out which columns belong to which plugin $columnsByPlugin = array(); $meta = \Piwik\Plugins\API\API::getInstance()->getReportMetadata($idSite, $period, $date); foreach ($meta as $reportMeta) { // scan all *.get reports if ($reportMeta['action'] == 'get' && !isset($reportMeta['parameters']) && $reportMeta['module'] != 'API' && !empty($reportMeta['metrics'])) { $plugin = $reportMeta['module']; foreach ($reportMeta['metrics'] as $column => $columnTranslation) { // a metric from this report has been requested if (isset($columnsMap[$column]) || empty($columnsMap)) { $columnsByPlugin[$plugin][] = $column; } } } } krsort($columnsByPlugin); $mergedDataTable = false; $params = compact('idSite', 'period', 'date', 'segment', 'idGoal'); foreach ($columnsByPlugin as $plugin => $columns) { // load the data $className = Request::getClassNameAPI($plugin); $params['columns'] = implode(',', $columns); $dataTable = Proxy::getInstance()->call($className, 'get', $params); // make sure the table has all columns $array = $dataTable instanceof DataTable\Map ? $dataTable->getDataTables() : array($dataTable); foreach ($array as $table) { // we don't support idSites=all&date=DATE1,DATE2 if ($table instanceof DataTable) { $firstRow = $table->getFirstRow(); if (!$firstRow) { $firstRow = new Row(); $table->addRow($firstRow); } foreach ($columns as $column) { if ($firstRow->getColumn($column) === false) { $firstRow->setColumn($column, 0); } } } } // merge reports if ($mergedDataTable === false) { $mergedDataTable = $dataTable; } else { $this->mergeDataTables($mergedDataTable, $dataTable); } } return $mergedDataTable; }
public function tearDown() { parent::tearDown(); // reset that value after the test Proxy::getInstance()->setHideIgnoredFunctions(true); }
/** * Dispatches the API request to the appropriate API method and returns the result * after post-processing. * * Post-processing includes: * * - flattening if **flat** is 0 * - running generic filters unless **disable_generic_filters** is set to 1 * - URL decoding label column values * - running queued filters unless **disable_queued_filters** is set to 1 * - removing columns based on the values of the **hideColumns** and **showColumns** query parameters * - filtering rows if the **label** query parameter is set * - converting the result to the appropriate format (ie, XML, JSON, etc.) * * If `'original'` is supplied for the output format, the result is returned as a PHP * object. * * @throws PluginDeactivatedException if the module plugin is not activated. * @throws Exception if the requested API method cannot be called, if required parameters for the * API method are missing or if the API method throws an exception and the **format** * query parameter is **original**. * @return DataTable|Map|string The data resulting from the API call. */ public function process() { // read the format requested for the output data $outputFormat = strtolower(Common::getRequestVar('format', 'xml', 'string', $this->request)); // create the response $response = new ResponseBuilder($outputFormat, $this->request); $corsHandler = new CORSHandler(); $corsHandler->handle(); $tokenAuth = Common::getRequestVar('token_auth', '', 'string', $this->request); $shouldReloadAuth = false; try { // read parameters $moduleMethod = Common::getRequestVar('method', null, 'string', $this->request); list($module, $method) = $this->extractModuleAndMethod($moduleMethod); list($module, $method) = self::getRenamedModuleAndAction($module, $method); PluginManager::getInstance()->checkIsPluginActivated($module); $apiClassName = self::getClassNameAPI($module); if ($shouldReloadAuth = self::shouldReloadAuthUsingTokenAuth($this->request)) { $access = Access::getInstance(); $tokenAuthToRestore = $access->getTokenAuth(); $hadSuperUserAccess = $access->hasSuperUserAccess(); self::forceReloadAuthUsingTokenAuth($tokenAuth); } // call the method $returnedValue = Proxy::getInstance()->call($apiClassName, $method, $this->request); $toReturn = $response->getResponse($returnedValue, $module, $method); } catch (Exception $e) { Log::debug($e); $toReturn = $response->getResponseException($e); } if ($shouldReloadAuth) { $this->restoreAuthUsingTokenAuth($tokenAuthToRestore, $hadSuperUserAccess); } return $toReturn; }
/** * Given a list of default parameters to set, returns the URLs of APIs to call * If any API was specified in $this->apiNotToCall we ensure only these are tested. * If any API is set as excluded (see list below) then it will be ignored. * * @param array $parametersToSet Parameters to set in api call * @param array $formats Array of 'format' to fetch from API * @param array $periods Array of 'period' to query API * @param bool $supertableApi * @param bool $setDateLastN If set to true, the 'date' parameter will be rewritten to query instead a range of dates, rather than one period only. * @param bool|string $language 2 letter language code, defaults to default piwik language * @param bool|string $fileExtension * * @throws Exception * * @return array of API URLs query strings */ protected function generateUrlsApi($parametersToSet, $formats, $periods, $supertableApi = false, $setDateLastN = false, $language = false, $fileExtension = false) { // Get the URLs to query against the API for all functions starting with get* $skipped = $requestUrls = array(); $apiMetadata = new DocumentationGenerator(); foreach (Proxy::getInstance()->getMetadata() as $class => $info) { $moduleName = Proxy::getInstance()->getModuleNameFromClassName($class); foreach ($info as $methodName => $infoMethod) { $apiId = $moduleName . '.' . $methodName; // If Api to test were set, we only test these if (!empty($this->apiToCall) && in_array($moduleName, $this->apiToCall) === false && in_array($apiId, $this->apiToCall) === false) { $skipped[] = $apiId; continue; } elseif (strpos($methodName, 'get') !== 0 && $methodName != 'generateReport' || in_array($moduleName, $this->apiNotToCall) === true || in_array($apiId, $this->apiNotToCall) === true || $methodName == 'getLogoUrl' || $methodName == 'getSVGLogoUrl' || $methodName == 'hasSVGLogo' || $methodName == 'getHeaderLogoUrl') { // Excluded modules from test $skipped[] = $apiId; continue; } foreach ($periods as $period) { $parametersToSet['period'] = $period; // If date must be a date range, we process this date range by adding 6 periods to it if ($setDateLastN) { if (!isset($parametersToSet['dateRewriteBackup'])) { $parametersToSet['dateRewriteBackup'] = $parametersToSet['date']; } $lastCount = (int) $setDateLastN; if ($setDateLastN === true) { $lastCount = 6; } $firstDate = $parametersToSet['dateRewriteBackup']; $secondDate = date('Y-m-d', strtotime("+{$lastCount} " . $period . "s", strtotime($firstDate))); $parametersToSet['date'] = $firstDate . ',' . $secondDate; } // Set response language if ($language !== false) { $parametersToSet['language'] = $language; } // set idSubtable if subtable API is set if ($supertableApi !== false) { $request = new Request(array('module' => 'API', 'method' => $supertableApi, 'idSite' => $parametersToSet['idSite'], 'period' => $parametersToSet['period'], 'date' => $parametersToSet['date'], 'format' => 'php', 'serialize' => 0)); // find first row w/ subtable $content = $request->process(); $this->checkRequestResponse($content); foreach ($content as $row) { if (isset($row['idsubdatatable'])) { $parametersToSet['idSubtable'] = $row['idsubdatatable']; break; } } // if no subtable found, throw if (!isset($parametersToSet['idSubtable'])) { throw new Exception("Cannot find subtable to load for {$apiId} in {$supertableApi}."); } } // Generate for each specified format foreach ($formats as $format) { $parametersToSet['format'] = $format; $parametersToSet['hideIdSubDatable'] = 1; $parametersToSet['serialize'] = 1; $exampleUrl = $apiMetadata->getExampleUrl($class, $methodName, $parametersToSet); if ($exampleUrl === false) { $skipped[] = $apiId; continue; } // Remove the first ? in the query string $exampleUrl = substr($exampleUrl, 1); $apiRequestId = $apiId; if (strpos($exampleUrl, 'period=') !== false) { $apiRequestId .= '_' . $period; } $apiRequestId .= '.' . $format; if ($fileExtension) { $apiRequestId .= '.' . $fileExtension; } $requestUrls[$apiRequestId] = $exampleUrl; } } } } return $requestUrls; }
/** * Convenience method that creates and renders a ViewDataTable for a API method. * * @param string $apiAction The name of the API action (eg, `'getResolution'`). * @param bool $controllerAction The name of the Controller action name that is rendering the report. Defaults * to the `$apiAction`. * @param bool $fetch If `true`, the rendered string is returned, if `false` it is `echo`'d. * @throws \Exception if `$pluginName` is not an existing plugin or if `$apiAction` is not an * existing method of the plugin's API. * @return string|void See `$fetch`. * @api */ protected function renderReport($apiAction, $controllerAction = false) { $pluginName = $this->pluginName; /** @var Proxy $apiProxy */ $apiProxy = Proxy::getInstance(); if (!$apiProxy->isExistingApiAction($pluginName, $apiAction)) { throw new \Exception("Invalid action name '{$apiAction}' for '{$pluginName}' plugin."); } $apiAction = $apiProxy->buildApiActionName($pluginName, $apiAction); if ($controllerAction !== false) { $controllerAction = $pluginName . '.' . $controllerAction; } $view = ViewDataTableFactory::build(null, $apiAction, $controllerAction); $rendered = $view->render(); return $rendered; }
protected function callApiAndReturnDataTable($apiModule, $method, $request) { $class = Request::getClassNameAPI($apiModule); $request = $this->manipulateSubtableRequest($request); $request['serialize'] = 0; $request['expanded'] = 0; // don't want to run recursive filters on the subtables as they are loaded, // otherwise the result will be empty in places (or everywhere). instead we // run it on the flattened table. unset($request['filter_pattern_recursive']); $dataTable = Proxy::getInstance()->call($class, $method, $request); $response = new ResponseBuilder($format = 'original', $request); $response->disableSendHeader(); $dataTable = $response->getResponse($dataTable); if (Common::getRequestVar('disable_queued_filters', 0, 'int', $request) == 0) { if (method_exists($dataTable, 'applyQueuedFilters')) { $dataTable->applyQueuedFilters(); } } return $dataTable; }
/** * Returns the methods $class.$name parameters (and default value if provided) as a string. * * @param string $class The class name * @param string $name The method name * @return string For example "(idSite, period, date = 'today')" */ public function getParametersString($class, $name) { $aParameters = Proxy::getInstance()->getParametersList($class, $name); $asParameters = array(); foreach ($aParameters as $nameVariable => $defaultValue) { // Do not show API parameters starting with _ // They are supposed to be used only in internal API calls if (strpos($nameVariable, '_') === 0) { continue; } $str = $nameVariable; if (!$defaultValue instanceof NoDefaultValue) { if (is_array($defaultValue)) { $str .= " = 'Array'"; } else { $str .= " = '{$defaultValue}'"; } } $asParameters[] = $str; } $sParameters = implode(", ", $asParameters); return "({$sParameters})"; }