public static function getAllDashboards($login) { $dashboards = Piwik_FetchAll('SELECT iddashboard, name FROM ' . Piwik_Common::prefixTable('user_dashboard') . ' WHERE login = ? ORDER BY iddashboard', array($login)); $pos = 0; $nameless = 1; foreach ($dashboards as &$dashboard) { if (!empty($dashboard['name'])) { $dashboard['name'] = $dashboard['name']; } else { $dashboard['name'] = Piwik_Translate('Dashboard_DashboardOf', $login); if ($nameless > 1) { $dashboard['name'] .= " ({$nameless})"; } if (empty($dashboard['layout'])) { $layout = '[]'; } else { $layout = html_entity_decode($dashboard['layout']); $layout = str_replace("\\\"", "\"", $layout); } $dashboard['layout'] = Piwik_Common::json_decode($layout); $nameless++; } $dashboard['name'] = Piwik_Common::unsanitizeInputValue($dashboard['name']); $pos++; } return $dashboards; }
private function initBulkTrackingRequests($rawData) { // POST data can be array of string URLs or array of arrays w/ visit info $jsonData = Piwik_Common::json_decode($rawData, $assoc = true); if (isset($jsonData['requests'])) { $this->requests = $jsonData['requests']; } $this->tokenAuth = Piwik_Common::getRequestVar('token_auth', false, null, $jsonData); if (empty($this->tokenAuth)) { throw new Exception(" token_auth must be specified when using Bulk Tracking Import. See <a href='http://piwik.org/docs/tracking-api/reference/'>Tracking Doc</a>"); } if (!empty($this->requests)) { $idSiteForAuthentication = 0; foreach ($this->requests as &$request) { // if a string is sent, we assume its a URL and try to parse it if (is_string($request)) { $params = array(); $url = @parse_url($request); if (!empty($url)) { @parse_str($url['query'], $params); $request = $params; if (isset($request['idsite']) && !$idSiteForAuthentication) { $idSiteForAuthentication = $request['idsite']; } } } } if (!$this->authenticateSuperUserOrAdmin(array('idsite' => $idSiteForAuthentication))) { throw new Exception(" token_auth specified is not valid for site " . intval($idSiteForAuthentication)); } } }
/** * Generates a report file. * * @param int $idReport ID of the report to generate. * @param string $date YYYY-MM-DD * @param bool|false|string $language If not passed, will use default language. * @param bool|false|int $outputType 1 = download report, 2 = save report to disk, 3 = output report in browser, 4 = return report content to caller, defaults to download * @param bool|false|string $period Defaults to 'day'. If not specified, will default to the report's period set when creating the report * @param bool|false|string $reportFormat 'pdf', 'html' or any other format provided via the PDFReports.getReportFormats hook * @param bool|false|array $parameters array of parameters * @return array|void */ public function generateReport($idReport, $date, $language = false, $outputType = false, $period = false, $reportFormat = false, $parameters = false) { Piwik::checkUserIsNotAnonymous(); // load specified language if (empty($language)) { $language = Piwik_Translate::getInstance()->getLanguageDefault(); } Piwik_Translate::getInstance()->reloadLanguage($language); $reports = $this->getReports($idSite = false, $_period = false, $idReport); $report = reset($reports); $idSite = $report['idsite']; $reportType = $report['type']; // override report period if (empty($period)) { $period = $report['period']; } // override report format if (!empty($reportFormat)) { self::validateReportFormat($reportType, $reportFormat); $report['format'] = $reportFormat; } else { $reportFormat = $report['format']; } // override report parameters if (!empty($parameters)) { $report['parameters'] = Piwik_Common::json_decode(self::validateReportParameters($reportType, $parameters), true); } else { $parameters = $report['parameters']; } // decode report list $reportUniqueIds = $report['reports']; // available reports $availableReportMetadata = Piwik_API_API::getInstance()->getReportMetadata($idSite); // we need to lookup which reports metadata are registered in this report $reportMetadata = array(); foreach ($availableReportMetadata as $metadata) { if (in_array($metadata['uniqueId'], $reportUniqueIds)) { $reportMetadata[] = $metadata; } } // the report will be rendered with the first 23 rows and will aggregate other rows in a summary row // 23 rows table fits in one portrait page $initialFilterTruncate = Piwik_Common::getRequestVar('filter_truncate', false); $_GET['filter_truncate'] = self::REPORT_TRUNCATE; $prettyDate = null; $processedReports = array(); foreach ($reportMetadata as $action) { $apiModule = $action['module']; $apiAction = $action['action']; $apiParameters = array(); if (isset($action['parameters'])) { $apiParameters = $action['parameters']; } $mustRestoreGET = false; // all Websites dashboard should not be truncated in the report if ($apiModule == 'MultiSites') { $mustRestoreGET = $_GET; $_GET['enhanced'] = true; if ($apiAction == 'getAll') { $_GET['filter_truncate'] = false; // when a view/admin user created a report, workaround the fact that "Super User" // is enforced in Scheduled tasks, and ensure Multisites.getAll only return the websites that this user can access if (!empty($userLogin) && $userLogin != Piwik_Config::getInstance()->superuser['login']) { $_GET['_restrictSitesToLogin'] = $userLogin; } } } $processedReport = Piwik_API_API::getInstance()->getProcessedReport($idSite, $period, $date, $apiModule, $apiAction, $segment = false, $apiParameters, $idGoal = false, $language); // TODO add static method getPrettyDate($period, $date) in Piwik_Period $prettyDate = $processedReport['prettyDate']; if ($mustRestoreGET) { $_GET = $mustRestoreGET; } $processedReports[] = $processedReport; } // restore filter truncate parameter value if ($initialFilterTruncate !== false) { $_GET['filter_truncate'] = $initialFilterTruncate; } $notificationInfo = array(self::REPORT_TYPE_INFO_KEY => $reportType, self::REPORT_KEY => $report); // allow plugins to alter processed reports Piwik_PostEvent(self::PROCESS_REPORTS_EVENT, $processedReports, $notificationInfo); // retrieve report renderer instance $reportRenderer = null; Piwik_PostEvent(self::GET_RENDERER_INSTANCE_EVENT, $reportRenderer, $notificationInfo); // init report renderer $reportRenderer->setLocale($language); $reportRenderer->setRenderImageInline($outputType != self::OUTPUT_SAVE_ON_DISK); // render report $websiteName = Piwik_Site::getNameFor($idSite); $description = str_replace(array("\r", "\n"), ' ', $report['description']); $reportRenderer->renderFrontPage($websiteName, $prettyDate, $description, $reportMetadata); array_walk($processedReports, array($reportRenderer, 'renderReport')); switch ($outputType) { case self::OUTPUT_SAVE_ON_DISK: $outputFilename = strtoupper($reportFormat) . ' ' . ucfirst($reportType) . ' Report - ' . $idReport . '.' . $date . '.' . $idSite . '.' . $language; $outputFilename = $reportRenderer->sendToDisk($outputFilename); $additionalFiles = array(); if ($reportRenderer instanceof Piwik_ReportRenderer_Html) { foreach ($processedReports as &$report) { if ($report['displayGraph']) { $additionalFile = array(); $additionalFile['filename'] = $report['metadata']['name'] . '.png'; $additionalFile['cid'] = $report['metadata']['uniqueId']; $additionalFile['content'] = Piwik_ReportRenderer::getStaticGraph($report['metadata']['imageGraphUrl'], Piwik_ReportRenderer_Html::IMAGE_GRAPH_WIDTH, Piwik_ReportRenderer_Html::IMAGE_GRAPH_HEIGHT); $additionalFile['mimeType'] = 'image/png'; $additionalFile['encoding'] = Zend_Mime::ENCODING_BASE64; $additionalFiles[] = $additionalFile; } } } return array($outputFilename, $prettyDate, $websiteName, $additionalFiles); break; case self::OUTPUT_INLINE: $reportRenderer->sendToBrowserInline("{$websiteName} - {$prettyDate} - {$description}"); break; case self::OUTPUT_RETURN: return $reportRenderer->getRenderedReport(); break; default: case self::OUTPUT_DOWNLOAD: $reportRenderer->sendToBrowserDownload("{$websiteName} - {$prettyDate} - {$description}"); break; } }
/** * Returns Items read from the request string * @return array|false */ protected function getEcommerceItemsFromRequest() { $items = Piwik_Common::unsanitizeInputValue(Piwik_Common::getRequestVar('ec_items', '', 'string', $this->request)); if (empty($items)) { printDebug("There are no Ecommerce items in the request"); // we still record an Ecommerce order without any item in it return array(); } $items = Piwik_Common::json_decode($items, $assoc = true); if (!is_array($items)) { printDebug("Error while json_decode the Ecommerce items = " . var_export($items, true)); return false; } $cleanedItems = $this->getCleanedEcommerceItems($items); return $cleanedItems; }
/** * Returns a sanitized variable value from the $_GET and $_POST superglobal. * If the variable doesn't have a value or an empty value, returns the defaultValue if specified. * If the variable doesn't have neither a value nor a default value provided, an exception is raised. * * @see sanitizeInputValues() for the applied sanitization * * @param string $varName name of the variable * @param string $varDefault default value. If '', and if the type doesn't match, exit() ! * @param string $varType Expected type, the value must be one of the following: array, int, integer, string, json * @param array $requestArrayToUse * * @throws Exception if the variable type is not known * or if the variable we want to read doesn't have neither a value nor a default value specified * * @return mixed The variable after cleaning */ public static function getRequestVar($varName, $varDefault = null, $varType = null, $requestArrayToUse = null) { if (is_null($requestArrayToUse)) { $requestArrayToUse = $_GET + $_POST; } $varDefault = self::sanitizeInputValues($varDefault); if ($varType === 'int') { // settype accepts only integer // 'int' is simply a shortcut for 'integer' $varType = 'integer'; } // there is no value $varName in the REQUEST so we try to use the default value if (empty($varName) || !isset($requestArrayToUse[$varName]) || !is_array($requestArrayToUse[$varName]) && strlen($requestArrayToUse[$varName]) === 0) { if (is_null($varDefault)) { throw new Exception("The parameter '{$varName}' isn't set in the Request, and a default value wasn't provided."); } else { if (!is_null($varType) && in_array($varType, array('string', 'integer', 'array'))) { settype($varDefault, $varType); } return $varDefault; } } // Normal case, there is a value available in REQUEST for the requested varName: // we deal w/ json differently if ($varType == 'json') { $value = self::undoMagicQuotes($requestArrayToUse[$varName]); $value = Piwik_Common::json_decode($value, $assoc = true); return self::sanitizeInputValues($value, $alreadyStripslashed = true); } $value = self::sanitizeInputValues($requestArrayToUse[$varName]); if (!is_null($varType)) { $ok = false; if ($varType === 'string') { if (is_string($value)) { $ok = true; } } elseif ($varType === 'integer') { if ($value == (string) (int) $value) { $ok = true; } } elseif ($varType === 'float') { if ($value == (string) (double) $value) { $ok = true; } } elseif ($varType === 'array') { if (is_array($value)) { $ok = true; } } else { throw new Exception("\$varType specified is not known. It should be one of the following: array, int, integer, float, string"); } // The type is not correct if ($ok === false) { if ($varDefault === null) { throw new Exception("The parameter '{$varName}' doesn't have a correct type, and a default value wasn't provided."); } else { settype($varDefault, $varType); return $varDefault; } } settype($value, $varType); } return $value; }
protected function removeDisabledPluginFromLayout($layout) { $layout = str_replace("\n", "", $layout); // if the json decoding works (ie. new Json format) // we will only return the widgets that are from enabled plugins $layoutObject = Piwik_Common::json_decode($layout, $assoc = false); if (is_array($layoutObject)) { $layoutObject = (object) array('config' => array('layout' => '33-33-33'), 'columns' => $layoutObject); } if (empty($layoutObject) || empty($layoutObject->columns)) { $layoutObject = (object) array('config' => array('layout' => '33-33-33'), 'columns' => array()); } foreach ($layoutObject->columns as &$row) { if (!is_array($row)) { $row = array(); continue; } foreach ($row as $widgetId => $widget) { if (isset($widget->parameters->module)) { $controllerName = $widget->parameters->module; $controllerAction = $widget->parameters->action; if (!Piwik_IsWidgetDefined($controllerName, $controllerAction)) { unset($row[$widgetId]); } } else { unset($row[$widgetId]); } } } $layout = Piwik_Common::json_encode($layoutObject); return $layout; }
/** * @param Piwik_ArchiveProcessing_Day $archiveProcessing * @return void */ protected function archiveDayAggregate(Piwik_ArchiveProcessing_Day $archiveProcessing) { for ($i = 1; $i <= Piwik_Tracker::MAX_CUSTOM_VARIABLES; $i++) { $keyField = "custom_var_k" . $i; $valueField = "custom_var_v" . $i; $dimensions = array($keyField, $valueField); $where = "%s.{$keyField} != ''"; // Custom Vars names and values metrics for visits $query = $archiveProcessing->queryVisitsByDimension($dimensions, $where); while ($row = $query->fetch()) { // Handle case custom var value is empty $row[$valueField] = $this->cleanCustomVarValue($row[$valueField]); // Aggregate if (!isset($this->interestByCustomVariables[$row[$keyField]])) { $this->interestByCustomVariables[$row[$keyField]] = $archiveProcessing->getNewInterestRow(); } if (!isset($this->interestByCustomVariablesAndValue[$row[$keyField]][$row[$valueField]])) { $this->interestByCustomVariablesAndValue[$row[$keyField]][$row[$valueField]] = $archiveProcessing->getNewInterestRow(); } $archiveProcessing->updateInterestStats($row, $this->interestByCustomVariables[$row[$keyField]]); $archiveProcessing->updateInterestStats($row, $this->interestByCustomVariablesAndValue[$row[$keyField]][$row[$valueField]]); } // Custom Vars names and values metrics for page views $query = $archiveProcessing->queryActionsByDimension($dimensions, $where); $onlyMetricsAvailableInActionsTable = true; while ($row = $query->fetch()) { // Handle case custom var value is empty $row[$valueField] = $this->cleanCustomVarValue($row[$valueField]); $label = $row[$valueField]; // Remove price tracked if it's zero or we if we are not currently tracking an ecommerce var if (!in_array($row[$keyField], array('_pks', '_pkn', '_pkc'))) { unset($row[Piwik_Archive::INDEX_ECOMMERCE_ITEM_PRICE_VIEWED]); } // when custom variable value is a JSON array of categories // possibly JSON value $mustInsertCustomVariableValue = true; if ($row[$keyField] == '_pkc' && $label[0] == '[' && $label[1] == '"') { // In case categories were truncated, try closing the array if (substr($label, -2) != '"]') { $label .= '"]'; } $decoded = @Piwik_Common::json_decode($label); if (is_array($decoded)) { $count = 0; foreach ($decoded as $category) { if (empty($category) || $count >= Piwik_Tracker_GoalManager::MAXIMUM_PRODUCT_CATEGORIES) { continue; } if (!isset($this->interestByCustomVariablesAndValue[$row[$keyField]][$category])) { $this->interestByCustomVariablesAndValue[$row[$keyField]][$category] = $archiveProcessing->getNewInterestRow($onlyMetricsAvailableInActionsTable); } $archiveProcessing->updateInterestStats($row, $this->interestByCustomVariablesAndValue[$row[$keyField]][$category], $onlyMetricsAvailableInActionsTable); $mustInsertCustomVariableValue = false; $count++; } } } // end multi categories hack if ($mustInsertCustomVariableValue) { if (!isset($this->interestByCustomVariablesAndValue[$row[$keyField]][$row[$valueField]])) { $this->interestByCustomVariablesAndValue[$row[$keyField]][$row[$valueField]] = $archiveProcessing->getNewInterestRow($onlyMetricsAvailableInActionsTable); } $archiveProcessing->updateInterestStats($row, $this->interestByCustomVariablesAndValue[$row[$keyField]][$row[$valueField]], $onlyMetricsAvailableInActionsTable); } // Do not report on Price viewed for the Custom Variable names unset($row[Piwik_Archive::INDEX_ECOMMERCE_ITEM_PRICE_VIEWED]); // When tracking Custom Variables with scope=page we do not add up visits numbers // as it is incorrect to sum visits this way // for scope=visit this is allowed, since there is supposed to be one custom var value per custom variable name for a given visit $doNotSumVisits = true; if (!isset($this->interestByCustomVariables[$row[$keyField]])) { $this->interestByCustomVariables[$row[$keyField]] = $archiveProcessing->getNewInterestRow($onlyMetricsAvailableInActionsTable, $doNotSumVisits); } $archiveProcessing->updateInterestStats($row, $this->interestByCustomVariables[$row[$keyField]], $onlyMetricsAvailableInActionsTable, $doNotSumVisits); } // Custom Vars names and values metrics for Goals $query = $archiveProcessing->queryConversionsByDimension($dimensions, $where); if ($query !== false) { while ($row = $query->fetch()) { // Handle case custom var value is empty $row[$valueField] = $this->cleanCustomVarValue($row[$valueField]); if (!isset($this->interestByCustomVariables[$row[$keyField]][Piwik_Archive::INDEX_GOALS][$row['idgoal']])) { $this->interestByCustomVariables[$row[$keyField]][Piwik_Archive::INDEX_GOALS][$row['idgoal']] = $archiveProcessing->getNewGoalRow($row['idgoal']); } if (!isset($this->interestByCustomVariablesAndValue[$row[$keyField]][$row[$valueField]][Piwik_Archive::INDEX_GOALS][$row['idgoal']])) { $this->interestByCustomVariablesAndValue[$row[$keyField]][$row[$valueField]][Piwik_Archive::INDEX_GOALS][$row['idgoal']] = $archiveProcessing->getNewGoalRow($row['idgoal']); } $archiveProcessing->updateGoalStats($row, $this->interestByCustomVariables[$row[$keyField]][Piwik_Archive::INDEX_GOALS][$row['idgoal']]); $archiveProcessing->updateGoalStats($row, $this->interestByCustomVariablesAndValue[$row[$keyField]][$row[$valueField]][Piwik_Archive::INDEX_GOALS][$row['idgoal']]); } } } $archiveProcessing->enrichConversionsByLabelArray($this->interestByCustomVariables); $archiveProcessing->enrichConversionsByLabelArrayHasTwoLevels($this->interestByCustomVariablesAndValue); // var_dump($this->interestByCustomVariables); //var_dump($this->interestByCustomVariablesAndValue); }
private function getUserSettings($user) { $optionIndex = $user . Piwik_MobileMessaging::USER_SETTINGS_POSTFIX_OPTION; $userSettings = Piwik_GetOption($optionIndex); if (empty($userSettings)) { $userSettings = array(); } else { $userSettings = Piwik_Common::json_decode($userSettings, true); } return $userSettings; }
public static function getCustomVariables($scope, $request) { if ($scope == 'visit') { $parameter = '_cvar'; $debug = 'Visit level'; } else { $parameter = 'cvar'; $debug = 'Page level'; } $customVar = Piwik_Common::unsanitizeInputValue(Piwik_Common::getRequestVar($parameter, '', 'string', $request)); $customVar = @Piwik_Common::json_decode($customVar, $assoc = true); if (!is_array($customVar)) { return array(); } $customVariables = array(); foreach ($customVar as $id => $keyValue) { $id = (int) $id; if ($id < 1 || $id > Piwik_Tracker::MAX_CUSTOM_VARIABLES || count($keyValue) != 2 || !is_string($keyValue[0]) && !is_numeric($keyValue[0])) { printDebug("Invalid custom variables detected (id={$id})"); continue; } if (strlen($keyValue[1]) == 0) { $keyValue[1] = ""; } // We keep in the URL when Custom Variable have empty names // and values, as it means they can be deleted server side $key = self::truncateCustomVariable($keyValue[0]); $value = self::truncateCustomVariable($keyValue[1]); $customVariables['custom_var_k' . $id] = $key; $customVariables['custom_var_v' . $id] = $value; } if (!empty($customVariables)) { printDebug("{$debug} Custom Variables: "); printDebug($customVariables); } return $customVariables; }