/** Render the area left of the iframe */ public function renderSidebar() { $idSite = Common::getRequestVar('idSite'); $period = Common::getRequestVar('period'); $date = Common::getRequestVar('date'); $currentUrl = Common::getRequestVar('currentUrl'); $currentUrl = Common::unsanitizeInputValue($currentUrl); $normalizedCurrentUrl = PageUrl::excludeQueryParametersFromUrl($currentUrl, $idSite); $normalizedCurrentUrl = Common::unsanitizeInputValue($normalizedCurrentUrl); // load the appropriate row of the page urls report using the label filter ArchivingHelper::reloadConfig(); $path = ArchivingHelper::getActionExplodedNames($normalizedCurrentUrl, Action::TYPE_PAGE_URL); $path = array_map('urlencode', $path); $label = implode('>', $path); $request = new Request('method=Actions.getPageUrls' . '&idSite=' . urlencode($idSite) . '&date=' . urlencode($date) . '&period=' . urlencode($period) . '&label=' . urlencode($label) . '&format=original'); $dataTable = $request->process(); $data = array(); if ($dataTable->getRowsCount() > 0) { $row = $dataTable->getFirstRow(); $translations = Metrics::getDefaultMetricTranslations(); $showMetrics = array('nb_hits', 'nb_visits', 'nb_users', 'nb_uniq_visitors', 'bounce_rate', 'exit_rate', 'avg_time_on_page'); foreach ($showMetrics as $metric) { $value = $row->getColumn($metric); if ($value === false) { // skip unique visitors for period != day continue; } if ($metric == 'avg_time_on_page') { $value = MetricsFormatter::getPrettyTimeFromSeconds($value); } $data[] = array('name' => $translations[$metric], 'value' => $value); } } // generate page url string foreach ($path as &$part) { $part = preg_replace(';^/;', '', urldecode($part)); } $page = '/' . implode('/', $path); $page = preg_replace(';/index$;', '/', $page); if ($page == '/') { $page = '/index'; } // render template $view = new View('@Overlay/renderSidebar'); $view->data = $data; $view->location = $page; $view->normalizedUrl = $normalizedCurrentUrl; $view->label = $label; $view->idSite = $idSite; $view->period = $period; $view->date = $date; $this->outputCORSHeaders(); return $view->render(); }
public function getSimpleLastVisitCount() { $lastMinutes = Config::getInstance()->General[self::SIMPLE_VISIT_COUNT_WIDGET_LAST_MINUTES_CONFIG_KEY]; $lastNData = Request::processRequest('Live.getCounters', array('lastMinutes' => $lastMinutes)); $view = new View('@Live/getSimpleLastVisitCount'); $view->lastMinutes = $lastMinutes; $view->visitors = MetricsFormatter::getPrettyNumber($lastNData[0]['visitors']); $view->visits = MetricsFormatter::getPrettyNumber($lastNData[0]['visits']); $view->actions = MetricsFormatter::getPrettyNumber($lastNData[0]['actions']); $view->refreshAfterXSecs = Config::getInstance()->General['live_widget_refresh_after_seconds']; $view->translations = array('one_visitor' => Piwik::translate('Live_NbVisitor'), 'visitors' => Piwik::translate('Live_NbVisitors'), 'one_visit' => Piwik::translate('General_OneVisit'), 'visits' => Piwik::translate('General_NVisits'), 'one_action' => Piwik::translate('General_OneAction'), 'actions' => Piwik::translate('VisitsSummary_NbActionsDescription'), 'one_minute' => Piwik::translate('General_OneMinute'), 'minutes' => Piwik::translate('General_NMinutes')); return $this->render($view); }
/** * Returns the index for this plugin. Shows every other report defined by this plugin, * except the '...ByYear' reports. These can be loaded as related reports. * * Also, the 'getIndividual...Summary' reports are loaded by AJAX, as they can take * a significant amount of time to load on setups w/ lots of websites. */ public function index() { Piwik::checkUserIsSuperUser(); $view = new View('@DBStats/index'); $this->setBasicVariablesView($view); $view->databaseUsageSummary = $this->getDatabaseUsageSummary(true); $view->trackerDataSummary = $this->getTrackerDataSummary(true); $view->metricDataSummary = $this->getMetricDataSummary(true); $view->reportDataSummary = $this->getReportDataSummary(true); $view->adminDataSummary = $this->getAdminDataSummary(true); list($siteCount, $userCount, $totalSpaceUsed) = API::getInstance()->getGeneralInformation(); $view->siteCount = MetricsFormatter::getPrettyNumber($siteCount); $view->userCount = MetricsFormatter::getPrettyNumber($userCount); $view->totalSpaceUsed = MetricsFormatter::getPrettySizeFromBytes($totalSpaceUsed); return $view->render(); }
private function setShowGoalsColumnsProperties() { // set view properties based on goal requested $idSite = Common::getRequestVar('idSite', null, 'int'); $idGoal = Common::getRequestVar('idGoal', AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW, 'string'); if (Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER == $idGoal) { $this->setPropertiesForEcommerceView(); } else { if (AddColumnsProcessedMetricsGoal::GOALS_FULL_TABLE == $idGoal) { $this->setPropertiesForGoals($idSite, 'all'); } else { if (AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW == $idGoal) { $this->setPropertiesForGoalsOverview($idSite); } else { $this->setPropertiesForGoals($idSite, array($idGoal)); } } } // add goals columns $this->config->filters[] = array('AddColumnsProcessedMetricsGoal', array($ignore = true, $idGoal), $priority = true); // prettify columns $setRatePercent = function ($rate, $thang = false) { return $rate == 0 ? "0%" : $rate; }; foreach ($this->config->columns_to_display as $columnName) { if (false !== strpos($columnName, 'conversion_rate')) { $this->config->filters[] = array('ColumnCallbackReplace', array($columnName, $setRatePercent)); } } $formatPercent = function ($value) use($idSite) { return MetricsFormatter::getPrettyMoney(sprintf("%.1f", $value), $idSite); }; foreach ($this->config->columns_to_display as $columnName) { if ($this->isRevenueColumn($columnName)) { $this->config->filters[] = array('ColumnCallbackReplace', array($columnName, $formatPercent)); } } // this ensures that the value is set to zero for all rows where the value was not set (no conversion) $identityFunction = function ($value) { return $value; }; foreach ($this->config->columns_to_display as $columnName) { if (!$this->isRevenueColumn($columnName)) { $this->config->filters[] = array('ColumnCallbackReplace', array($columnName, $identityFunction)); } } }
protected function addPageDisplayProperties(ViewDataTable $view) { $view->config->addTranslations(array('nb_hits' => Piwik::translate('General_ColumnPageviews'), 'nb_visits' => Piwik::translate('General_ColumnUniquePageviews'), 'avg_time_on_page' => Piwik::translate('General_ColumnAverageTimeOnPage'), 'bounce_rate' => Piwik::translate('General_ColumnBounceRate'), 'exit_rate' => Piwik::translate('General_ColumnExitRate'), 'avg_time_generation' => Piwik::translate('General_ColumnAverageGenerationTime'))); // prettify avg_time_on_page column $getPrettyTimeFromSeconds = '\\Piwik\\MetricsFormatter::getPrettyTimeFromSeconds'; $view->config->filters[] = array('ColumnCallbackReplace', array('avg_time_on_page', $getPrettyTimeFromSeconds)); // prettify avg_time_generation column $avgTimeCallback = function ($time) { return $time ? MetricsFormatter::getPrettyTimeFromSeconds($time, true, true, false) : "-"; }; $view->config->filters[] = array('ColumnCallbackReplace', array('avg_time_generation', $avgTimeCallback)); // add avg_generation_time tooltip $tooltipCallback = function ($hits, $min, $max) { if (!$hits) { return false; } return Piwik::translate("Actions_AvgGenerationTimeTooltip", array($hits, "<br />", MetricsFormatter::getPrettyTimeFromSeconds($min), MetricsFormatter::getPrettyTimeFromSeconds($max))); }; $view->config->filters[] = array('ColumnCallbackAddMetadata', array(array('nb_hits_with_time_generation', 'min_time_generation', 'max_time_generation'), 'avg_time_generation_tooltip', $tooltipCallback)); $this->addExcludeLowPopDisplayProperties($view); }
/** * @param $visitorDetailsArray * @param $actionsLimit * @param $timezone * @return array */ public static function enrichVisitorArrayWithActions($visitorDetailsArray, $actionsLimit, $timezone) { $idVisit = $visitorDetailsArray['idVisit']; $maxCustomVariables = CustomVariables::getMaxCustomVariables(); $sqlCustomVariables = ''; for ($i = 1; $i <= $maxCustomVariables; $i++) { $sqlCustomVariables .= ', custom_var_k' . $i . ', custom_var_v' . $i; } // The second join is a LEFT join to allow returning records that don't have a matching page title // eg. Downloads, Outlinks. For these, idaction_name is set to 0 $sql = "\n\t\t\t\tSELECT\n\t\t\t\t\tCOALESCE(log_action_event_category.type, log_action.type, log_action_title.type) AS type,\n\t\t\t\t\tlog_action.name AS url,\n\t\t\t\t\tlog_action.url_prefix,\n\t\t\t\t\tlog_action_title.name AS pageTitle,\n\t\t\t\t\tlog_action.idaction AS pageIdAction,\n\t\t\t\t\tlog_link_visit_action.server_time as serverTimePretty,\n\t\t\t\t\tlog_link_visit_action.time_spent_ref_action as timeSpentRef,\n\t\t\t\t\tlog_link_visit_action.idlink_va AS pageId,\n\t\t\t\t\tlog_link_visit_action.custom_float\n\t\t\t\t\t" . $sqlCustomVariables . ",\n\t\t\t\t\tlog_action_event_category.name AS eventCategory,\n\t\t\t\t\tlog_action_event_action.name as eventAction\n\t\t\t\tFROM " . Common::prefixTable('log_link_visit_action') . " AS log_link_visit_action\n\t\t\t\t\tLEFT JOIN " . Common::prefixTable('log_action') . " AS log_action\n\t\t\t\t\tON log_link_visit_action.idaction_url = log_action.idaction\n\t\t\t\t\tLEFT JOIN " . Common::prefixTable('log_action') . " AS log_action_title\n\t\t\t\t\tON log_link_visit_action.idaction_name = log_action_title.idaction\n\t\t\t\t\tLEFT JOIN " . Common::prefixTable('log_action') . " AS log_action_event_category\n\t\t\t\t\tON log_link_visit_action.idaction_event_category = log_action_event_category.idaction\n\t\t\t\t\tLEFT JOIN " . Common::prefixTable('log_action') . " AS log_action_event_action\n\t\t\t\t\tON log_link_visit_action.idaction_event_action = log_action_event_action.idaction\n\t\t\t\tWHERE log_link_visit_action.idvisit = ?\n\t\t\t\tORDER BY server_time ASC\n\t\t\t\tLIMIT 0, {$actionsLimit}\n\t\t\t\t "; $actionDetails = Db::fetchAll($sql, array($idVisit)); foreach ($actionDetails as $actionIdx => &$actionDetail) { $actionDetail =& $actionDetails[$actionIdx]; $customVariablesPage = array(); for ($i = 1; $i <= $maxCustomVariables; $i++) { if (!empty($actionDetail['custom_var_k' . $i])) { $cvarKey = $actionDetail['custom_var_k' . $i]; $cvarKey = static::getCustomVariablePrettyKey($cvarKey); $customVariablesPage[$i] = array('customVariablePageName' . $i => $cvarKey, 'customVariablePageValue' . $i => $actionDetail['custom_var_v' . $i]); } unset($actionDetail['custom_var_k' . $i]); unset($actionDetail['custom_var_v' . $i]); } if (!empty($customVariablesPage)) { $actionDetail['customVariables'] = $customVariablesPage; } if ($actionDetail['type'] == Action::TYPE_CONTENT) { unset($actionDetails[$actionIdx]); continue; } elseif ($actionDetail['type'] == Action::TYPE_EVENT_CATEGORY) { // Handle Event if (strlen($actionDetail['pageTitle']) > 0) { $actionDetail['eventName'] = $actionDetail['pageTitle']; } unset($actionDetail['pageTitle']); } else { if ($actionDetail['type'] == Action::TYPE_SITE_SEARCH) { // Handle Site Search $actionDetail['siteSearchKeyword'] = $actionDetail['pageTitle']; unset($actionDetail['pageTitle']); } } // Event value / Generation time if ($actionDetail['type'] == Action::TYPE_EVENT_CATEGORY) { if (strlen($actionDetail['custom_float']) > 0) { $actionDetail['eventValue'] = round($actionDetail['custom_float'], self::EVENT_VALUE_PRECISION); } } elseif ($actionDetail['custom_float'] > 0) { $actionDetail['generationTime'] = \Piwik\MetricsFormatter::getPrettyTimeFromSeconds($actionDetail['custom_float'] / 1000); } unset($actionDetail['custom_float']); if ($actionDetail['type'] != Action::TYPE_EVENT_CATEGORY) { unset($actionDetail['eventCategory']); unset($actionDetail['eventAction']); } // Reconstruct url from prefix $actionDetail['url'] = Tracker\PageUrl::reconstructNormalizedUrl($actionDetail['url'], $actionDetail['url_prefix']); unset($actionDetail['url_prefix']); // Set the time spent for this action (which is the timeSpentRef of the next action) if (isset($actionDetails[$actionIdx + 1])) { $actionDetail['timeSpent'] = $actionDetails[$actionIdx + 1]['timeSpentRef']; $actionDetail['timeSpentPretty'] = \Piwik\MetricsFormatter::getPrettyTimeFromSeconds($actionDetail['timeSpent']); } unset($actionDetails[$actionIdx]['timeSpentRef']); // not needed after timeSpent is added } // If the visitor converted a goal, we shall select all Goals $sql = "\n\t\t\t\tSELECT\n\t\t\t\t\t\t'goal' as type,\n\t\t\t\t\t\tgoal.name as goalName,\n\t\t\t\t\t\tgoal.idgoal as goalId,\n\t\t\t\t\t\tgoal.revenue as revenue,\n\t\t\t\t\t\tlog_conversion.idlink_va as goalPageId,\n\t\t\t\t\t\tlog_conversion.server_time as serverTimePretty,\n\t\t\t\t\t\tlog_conversion.url as url\n\t\t\t\tFROM " . Common::prefixTable('log_conversion') . " AS log_conversion\n\t\t\t\tLEFT JOIN " . Common::prefixTable('goal') . " AS goal\n\t\t\t\t\tON (goal.idsite = log_conversion.idsite\n\t\t\t\t\t\tAND\n\t\t\t\t\t\tgoal.idgoal = log_conversion.idgoal)\n\t\t\t\t\tAND goal.deleted = 0\n\t\t\t\tWHERE log_conversion.idvisit = ?\n\t\t\t\t\tAND log_conversion.idgoal > 0\n ORDER BY server_time ASC\n\t\t\t\tLIMIT 0, {$actionsLimit}\n\t\t\t"; $goalDetails = Db::fetchAll($sql, array($idVisit)); $sql = "SELECT\n\t\t\t\t\t\tcase idgoal when " . GoalManager::IDGOAL_CART . " then '" . Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART . "' else '" . Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER . "' end as type,\n\t\t\t\t\t\tidorder as orderId,\n\t\t\t\t\t\t" . LogAggregator::getSqlRevenue('revenue') . " as revenue,\n\t\t\t\t\t\t" . LogAggregator::getSqlRevenue('revenue_subtotal') . " as revenueSubTotal,\n\t\t\t\t\t\t" . LogAggregator::getSqlRevenue('revenue_tax') . " as revenueTax,\n\t\t\t\t\t\t" . LogAggregator::getSqlRevenue('revenue_shipping') . " as revenueShipping,\n\t\t\t\t\t\t" . LogAggregator::getSqlRevenue('revenue_discount') . " as revenueDiscount,\n\t\t\t\t\t\titems as items,\n\n\t\t\t\t\t\tlog_conversion.server_time as serverTimePretty\n\t\t\t\t\tFROM " . Common::prefixTable('log_conversion') . " AS log_conversion\n\t\t\t\t\tWHERE idvisit = ?\n\t\t\t\t\t\tAND idgoal <= " . GoalManager::IDGOAL_ORDER . "\n\t\t\t\t\tORDER BY server_time ASC\n\t\t\t\t\tLIMIT 0, {$actionsLimit}"; $ecommerceDetails = Db::fetchAll($sql, array($idVisit)); foreach ($ecommerceDetails as &$ecommerceDetail) { if ($ecommerceDetail['type'] == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART) { unset($ecommerceDetail['orderId']); unset($ecommerceDetail['revenueSubTotal']); unset($ecommerceDetail['revenueTax']); unset($ecommerceDetail['revenueShipping']); unset($ecommerceDetail['revenueDiscount']); } // 25.00 => 25 foreach ($ecommerceDetail as $column => $value) { if (strpos($column, 'revenue') !== false) { if ($value == round($value)) { $ecommerceDetail[$column] = round($value); } } } } // Enrich ecommerce carts/orders with the list of products usort($ecommerceDetails, array('static', 'sortByServerTime')); foreach ($ecommerceDetails as &$ecommerceConversion) { $sql = "SELECT\n\t\t\t\t\t\t\tlog_action_sku.name as itemSKU,\n\t\t\t\t\t\t\tlog_action_name.name as itemName,\n\t\t\t\t\t\t\tlog_action_category.name as itemCategory,\n\t\t\t\t\t\t\t" . LogAggregator::getSqlRevenue('price') . " as price,\n\t\t\t\t\t\t\tquantity as quantity\n\t\t\t\t\t\tFROM " . Common::prefixTable('log_conversion_item') . "\n\t\t\t\t\t\t\tINNER JOIN " . Common::prefixTable('log_action') . " AS log_action_sku\n\t\t\t\t\t\t\tON idaction_sku = log_action_sku.idaction\n\t\t\t\t\t\t\tLEFT JOIN " . Common::prefixTable('log_action') . " AS log_action_name\n\t\t\t\t\t\t\tON idaction_name = log_action_name.idaction\n\t\t\t\t\t\t\tLEFT JOIN " . Common::prefixTable('log_action') . " AS log_action_category\n\t\t\t\t\t\t\tON idaction_category = log_action_category.idaction\n\t\t\t\t\t\tWHERE idvisit = ?\n\t\t\t\t\t\t\tAND idorder = ?\n\t\t\t\t\t\t\tAND deleted = 0\n\t\t\t\t\t\tLIMIT 0, {$actionsLimit}\n\t\t\t\t"; $bind = array($idVisit, isset($ecommerceConversion['orderId']) ? $ecommerceConversion['orderId'] : GoalManager::ITEM_IDORDER_ABANDONED_CART); $itemsDetails = Db::fetchAll($sql, $bind); foreach ($itemsDetails as &$detail) { if ($detail['price'] == round($detail['price'])) { $detail['price'] = round($detail['price']); } } $ecommerceConversion['itemDetails'] = $itemsDetails; } $actions = array_merge($actionDetails, $goalDetails, $ecommerceDetails); usort($actions, array('static', 'sortByServerTime')); $visitorDetailsArray['actionDetails'] = $actions; foreach ($visitorDetailsArray['actionDetails'] as &$details) { switch ($details['type']) { case 'goal': $details['icon'] = 'plugins/Morpheus/images/goal.png'; break; case Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER: case Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART: $details['icon'] = 'plugins/Morpheus/images/' . $details['type'] . '.gif'; break; case Action::TYPE_DOWNLOAD: $details['type'] = 'download'; $details['icon'] = 'plugins/Morpheus/images/download.png'; break; case Action::TYPE_OUTLINK: $details['type'] = 'outlink'; $details['icon'] = 'plugins/Morpheus/images/link.gif'; break; case Action::TYPE_SITE_SEARCH: $details['type'] = 'search'; $details['icon'] = 'plugins/Morpheus/images/search_ico.png'; break; case Action::TYPE_EVENT_CATEGORY: $details['type'] = 'event'; $details['icon'] = 'plugins/Morpheus/images/event.png'; break; default: $details['type'] = 'action'; $details['icon'] = null; break; } // Convert datetimes to the site timezone $dateTimeVisit = Date::factory($details['serverTimePretty'], $timezone); $details['serverTimePretty'] = $dateTimeVisit->getLocalized(Piwik::translate('CoreHome_ShortDateFormat') . ' %time%'); } $visitorDetailsArray['goalConversions'] = count($goalDetails); return $visitorDetailsArray; }
protected function getDeleteDataInfo() { Piwik::checkUserHasSuperUserAccess(); $deleteDataInfos = array(); $taskScheduler = new TaskScheduler(); $deleteDataInfos["config"] = PrivacyManager::getPurgeDataSettings(); $deleteDataInfos["deleteTables"] = "<br/>" . implode(", ", LogDataPurger::getDeleteTableLogTables()); $scheduleTimetable = $taskScheduler->getScheduledTimeForMethod("PrivacyManager", "deleteLogTables"); $optionTable = Option::get(self::OPTION_LAST_DELETE_PIWIK_LOGS); //If task was already rescheduled, read time from taskTimetable. Else, calculate next possible runtime. if (!empty($scheduleTimetable) && $scheduleTimetable - time() > 0) { $nextPossibleSchedule = (int) $scheduleTimetable; } else { $date = Date::factory("today"); $nextPossibleSchedule = $date->addDay(1)->getTimestamp(); } //deletion schedule did not run before if (empty($optionTable)) { $deleteDataInfos["lastRun"] = false; //next run ASAP (with next schedule run) $date = Date::factory("today"); $deleteDataInfos["nextScheduleTime"] = $nextPossibleSchedule; } else { $deleteDataInfos["lastRun"] = $optionTable; $deleteDataInfos["lastRunPretty"] = Date::factory((int) $optionTable)->getLocalized('%day% %shortMonth% %longYear%'); //Calculate next run based on last run + interval $nextScheduleRun = (int) ($deleteDataInfos["lastRun"] + $deleteDataInfos["config"]["delete_logs_schedule_lowest_interval"] * 24 * 60 * 60); //is the calculated next run in the past? (e.g. plugin was disabled in the meantime or something) -> run ASAP if ($nextScheduleRun - time() <= 0) { $deleteDataInfos["nextScheduleTime"] = $nextPossibleSchedule; } else { $deleteDataInfos["nextScheduleTime"] = $nextScheduleRun; } } $deleteDataInfos["nextRunPretty"] = MetricsFormatter::getPrettyTimeFromSeconds($deleteDataInfos["nextScheduleTime"] - time()); return $deleteDataInfos; }
function getVisitLengthPretty() { return \Piwik\MetricsFormatter::getPrettyTimeFromSeconds($this->details['visit_total_time']); }
private function logArchiveTimeoutInfo() { $this->logSection("NOTES"); // Recommend to disable browser archiving when using this script if (Rules::isBrowserTriggerEnabled()) { $this->log("- If you execute this script at least once per hour (or more often) in a crontab, you may disable 'Browser trigger archiving' in Piwik UI > Settings > General Settings. "); $this->log(" See the doc at: http://piwik.org/docs/setup-auto-archiving/"); } $this->log("- Reports for today will be processed at most every " . $this->todayArchiveTimeToLive . " seconds. You can change this value in Piwik UI > Settings > General Settings."); $this->log("- Reports for the current week/month/year will be refreshed at most every " . $this->processPeriodsMaximumEverySeconds . " seconds."); // Try and not request older data we know is already archived if ($this->lastSuccessRunTimestamp !== false) { $dateLast = time() - $this->lastSuccessRunTimestamp; $this->log("- Archiving was last executed without error " . \Piwik\MetricsFormatter::getPrettyTimeFromSeconds($dateLast, true, $isHtml = false) . " ago"); } }
/** * Returns prettified and translated text that describes when a report was last updated. * * @return string */ private function makePrettyArchivedOnText() { $dateText = $this->metadata[DataTable::ARCHIVED_DATE_METADATA_NAME]; $date = Date::factory($dateText); $today = mktime(0, 0, 0); if ($date->getTimestamp() > $today) { $elapsedSeconds = time() - $date->getTimestamp(); $timeAgo = MetricsFormatter::getPrettyTimeFromSeconds($elapsedSeconds); return Piwik::translate('CoreHome_ReportGeneratedXAgo', $timeAgo); } $prettyDate = $date->getLocalized("%longYear%, %longMonth% %day%") . $date->toString('S'); return Piwik::translate('CoreHome_ReportGeneratedOn', $prettyDate); }
public function getSumVisitsLengthPretty($idSite, $period, $date, $segment = false) { $table = $this->getSumVisitsLength($idSite, $period, $date, $segment); if (is_object($table)) { $table->filter('ColumnCallbackReplace', array('sum_visit_length', '\\Piwik\\MetricsFormatter::getPrettyTimeFromSeconds')); } else { $table = MetricsFormatter::getPrettyTimeFromSeconds($table); } return $table; }
/** * Renders and echo's an admin page that lets users generate custom JavaScript * tracking code and custom image tracker links. */ public function trackingCodeGenerator() { $view = new View('@CoreAdminHome/trackingCodeGenerator'); $this->setBasicVariablesView($view); $view->topMenu = MenuTop::getInstance()->getMenu(); $view->userMenu = MenuUser::getInstance()->getMenu(); $viewableIdSites = APISitesManager::getInstance()->getSitesIdWithAtLeastViewAccess(); $defaultIdSite = reset($viewableIdSites); $view->idSite = Common::getRequestVar('idSite', $defaultIdSite, 'int'); $view->defaultReportSiteName = Site::getNameFor($view->idSite); $view->defaultSiteRevenue = \Piwik\MetricsFormatter::getCurrencySymbol($view->idSite); $view->maxCustomVariables = CustomVariables::getMaxCustomVariables(); $allUrls = APISitesManager::getInstance()->getSiteUrlsFromId($view->idSite); if (isset($allUrls[1])) { $aliasUrl = $allUrls[1]; } else { $aliasUrl = 'x.domain.com'; } $view->defaultReportSiteAlias = $aliasUrl; $mainUrl = Site::getMainUrlFor($view->idSite); $view->defaultReportSiteDomain = @parse_url($mainUrl, PHP_URL_HOST); // get currencies for each viewable site $view->currencySymbols = APISitesManager::getInstance()->getCurrencySymbols(); $view->serverSideDoNotTrackEnabled = \Piwik\Plugins\PrivacyManager\DoNotTrackHeaderChecker::isActive(); return $view->render(); }
/** * Derive the unit name from a column name * @param $column * @param $idSite * @return string * @ignore */ public static function getUnit($column, $idSite) { $nameToUnit = array('_rate' => '%', 'revenue' => MetricsFormatter::getCurrencySymbol($idSite), '_time_' => 's'); foreach ($nameToUnit as $pattern => $type) { if (strpos($column, $pattern) !== false) { return $type; } } return ''; }
/** * Enhance $simpleDataTable using metadata : * * - remove metrics based on $reportMetadata['metrics'] * - add 0 valued metrics if $simpleDataTable doesn't provide all $reportMetadata['metrics'] * - format metric values to a 'human readable' format * - extract row metadata to a separate Simple $rowsMetadata * * @param int $idSite enables monetary value formatting based on site currency * @param Simple $simpleDataTable * @param array $metadataColumns * @param boolean $hasDimension * @param bool $returnRawMetrics If set to true, the original metrics will be returned * * @return array DataTable $enhancedDataTable filtered metrics with human readable format & Simple $rowsMetadata */ private function handleSimpleDataTable($idSite, $simpleDataTable, $metadataColumns, $hasDimension, $returnRawMetrics = false) { // new DataTable to store metadata $rowsMetadata = new DataTable(); // new DataTable to store 'human readable' values if ($hasDimension) { $enhancedDataTable = new DataTable(); } else { $enhancedDataTable = new Simple(); } foreach ($simpleDataTable->getRows() as $row) { $rowMetrics = $row->getColumns(); // add missing metrics foreach ($metadataColumns as $id => $name) { if (!isset($rowMetrics[$id])) { $row->setColumn($id, 0); $rowMetrics[$id] = 0; } } $enhancedRow = new Row(); $enhancedDataTable->addRow($enhancedRow); foreach ($rowMetrics as $columnName => $columnValue) { // filter metrics according to metadata definition if (isset($metadataColumns[$columnName])) { // generate 'human readable' metric values // if we handle MultiSites.getAll we do not always have the same idSite but different ones for // each site, see https://github.com/piwik/piwik/issues/5006 $idSiteForRow = $idSite; if ($row->getMetadata('idsite') && is_numeric($row->getMetadata('idsite'))) { $idSiteForRow = (int) $row->getMetadata('idsite'); } $prettyValue = MetricsFormatter::getPrettyValue($idSiteForRow, $columnName, $columnValue, $htmlAllowed = false); $enhancedRow->addColumn($columnName, $prettyValue); } elseif ($returnRawMetrics) { if (!isset($columnValue)) { $columnValue = 0; } $enhancedRow->addColumn($columnName, $columnValue); } } // If report has a dimension, extract metadata into a distinct DataTable if ($hasDimension) { $rowMetadata = $row->getMetadata(); $idSubDataTable = $row->getIdSubDataTable(); // Create a row metadata only if there are metadata to insert if (count($rowMetadata) > 0 || !is_null($idSubDataTable)) { $metadataRow = new Row(); $rowsMetadata->addRow($metadataRow); foreach ($rowMetadata as $metadataKey => $metadataValue) { $metadataRow->addColumn($metadataKey, $metadataValue); } if (!is_null($idSubDataTable)) { $metadataRow->addColumn('idsubdatatable', $idSubDataTable); } } } } return array($enhancedDataTable, $rowsMetadata); }
/** * Returns an array describing a visitor using her last visits (uses a maximum of 100). * * @param int $idSite Site ID * @param bool|false|string $visitorId The ID of the visitor whose profile to retrieve. * @param bool|false|string $segment * @param bool $checkForLatLong If true, hasLatLong will appear in the output and be true if * one of the first 100 visits has a latitude/longitude. * @return array */ public function getVisitorProfile($idSite, $visitorId = false, $segment = false, $checkForLatLong = false) { Piwik::checkUserHasViewAccess($idSite); if ($visitorId === false) { $visitorId = $this->getMostRecentVisitorId($idSite, $segment); } $newSegment = ($segment === false ? '' : $segment . ';') . 'visitorId==' . $visitorId; $visits = $this->loadLastVisitorDetailsFromDatabase($idSite, $period = false, $date = false, $newSegment, $numVisitorsToFetch = self::VISITOR_PROFILE_MAX_VISITS_TO_AGGREGATE, $overrideVisitorId = false, $minTimestamp = false); $this->addFilterToCleanVisitors($visits, $idSite, $flat = false, $doNotFetchActions = false, $filterNow = true); if ($visits->getRowsCount() == 0) { return array(); } $isEcommerceEnabled = Site::isEcommerceEnabledFor($idSite); $result = array(); $result['totalVisits'] = 0; $result['totalVisitDuration'] = 0; $result['totalActions'] = 0; $result['totalSearches'] = 0; $result['totalPageViews'] = 0; $result['totalGoalConversions'] = 0; $result['totalConversionsByGoal'] = array(); if ($isEcommerceEnabled) { $result['totalEcommerceConversions'] = 0; $result['totalEcommerceRevenue'] = 0; $result['totalEcommerceItems'] = 0; $result['totalAbandonedCarts'] = 0; $result['totalAbandonedCartsRevenue'] = 0; $result['totalAbandonedCartsItems'] = 0; } $countries = array(); $continents = array(); $cities = array(); $siteSearchKeywords = array(); $pageGenerationTimeTotal = 0; // aggregate all requested visits info for total_* info foreach ($visits->getRows() as $visit) { ++$result['totalVisits']; $result['totalVisitDuration'] += $visit->getColumn('visitDuration'); $result['totalActions'] += $visit->getColumn('actions'); $result['totalGoalConversions'] += $visit->getColumn('goalConversions'); // individual goal conversions are stored in action details foreach ($visit->getColumn('actionDetails') as $action) { if ($action['type'] == 'goal') { // handle goal conversion $idGoal = $action['goalId']; $idGoalKey = 'idgoal=' . $idGoal; if (!isset($result['totalConversionsByGoal'][$idGoalKey])) { $result['totalConversionsByGoal'][$idGoalKey] = 0; } ++$result['totalConversionsByGoal'][$idGoalKey]; if (!empty($action['revenue'])) { if (!isset($result['totalRevenueByGoal'][$idGoalKey])) { $result['totalRevenueByGoal'][$idGoalKey] = 0; } $result['totalRevenueByGoal'][$idGoalKey] += $action['revenue']; } } else { if ($action['type'] == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER && $isEcommerceEnabled) { ++$result['totalEcommerceConversions']; $result['totalEcommerceRevenue'] += $action['revenue']; $result['totalEcommerceItems'] += $action['items']; } else { if ($action['type'] == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART && $isEcommerceEnabled) { ++$result['totalAbandonedCarts']; $result['totalAbandonedCartsRevenue'] += $action['revenue']; $result['totalAbandonedCartsItems'] += $action['items']; } } } if (isset($action['siteSearchKeyword'])) { $keyword = $action['siteSearchKeyword']; if (!isset($siteSearchKeywords[$keyword])) { $siteSearchKeywords[$keyword] = 0; ++$result['totalSearches']; } ++$siteSearchKeywords[$keyword]; } if (isset($action['generationTime'])) { $pageGenerationTimeTotal += $action['generationTime']; ++$result['totalPageViews']; } } $countryCode = $visit->getColumn('countryCode'); if (!isset($countries[$countryCode])) { $countries[$countryCode] = 0; } ++$countries[$countryCode]; $continentCode = $visit->getColumn('continentCode'); if (!isset($continents[$continentCode])) { $continents[$continentCode] = 0; } ++$continents[$continentCode]; if ($countryCode && !array_key_exists($countryCode, $cities)) { $cities[$countryCode] = array(); } $city = $visit->getColumn('city'); if (!empty($city)) { $cities[$countryCode][] = $city; } } // sort countries/continents/search keywords by visit/action asort($countries); asort($continents); arsort($siteSearchKeywords); // transform country/continents/search keywords into something that will look good in XML $result['countries'] = $result['continents'] = $result['searches'] = array(); foreach ($countries as $countryCode => $nbVisits) { $countryInfo = array('country' => $countryCode, 'nb_visits' => $nbVisits, 'flag' => \Piwik\Plugins\UserCountry\getFlagFromCode($countryCode), 'prettyName' => \Piwik\Plugins\UserCountry\countryTranslate($countryCode)); if (!empty($cities[$countryCode])) { $countryInfo['cities'] = array_unique($cities[$countryCode]); } $result['countries'][] = $countryInfo; } foreach ($continents as $continentCode => $nbVisits) { $result['continents'][] = array('continent' => $continentCode, 'nb_visits' => $nbVisits, 'prettyName' => \Piwik\Plugins\UserCountry\continentTranslate($continentCode)); } foreach ($siteSearchKeywords as $keyword => $searchCount) { $result['searches'][] = array('keyword' => $keyword, 'searches' => $searchCount); } if ($result['totalPageViews']) { $result['averagePageGenerationTime'] = round($pageGenerationTimeTotal / $result['totalPageViews'], $precision = 2); } $result['totalVisitDurationPretty'] = MetricsFormatter::getPrettyTimeFromSeconds($result['totalVisitDuration']); // use requested visits for first/last visit info $rows = $visits->getRows(); $result['firstVisit'] = $this->getVisitorProfileVisitSummary(end($rows)); $result['lastVisit'] = $this->getVisitorProfileVisitSummary(reset($rows)); // check if requested visits have lat/long if ($checkForLatLong) { $result['hasLatLong'] = false; foreach ($rows as $visit) { if ($visit->getColumn('latitude') !== false) { // realtime map only checks for latitude $result['hasLatLong'] = true; break; } } } // save count of visits we queries $result['visitsAggregated'] = count($rows); // use N most recent visits for last_visits $visits->deleteRowsOffset(self::VISITOR_PROFILE_MAX_VISITS_TO_SHOW); $result['lastVisits'] = $visits; // use the right date format for the pretty server date $timezone = Site::getTimezoneFor($idSite); foreach ($result['lastVisits']->getRows() as $visit) { $dateTimeVisitFirstAction = Date::factory($visit->getColumn('firstActionTimestamp'), $timezone); $datePretty = $dateTimeVisitFirstAction->getLocalized(self::VISITOR_PROFILE_DATE_FORMAT); $visit->setColumn('serverDatePrettyFirstAction', $datePretty); $dateTimePretty = $datePretty . ' ' . $visit->getColumn('serverTimePrettyFirstAction'); $visit->setColumn('serverDateTimePrettyFirstAction', $dateTimePretty); } $result['userId'] = $visit->getColumn('userId'); // get visitor IDs that are adjacent to this one in log_visit // TODO: make sure order of visitor ids is not changed if a returning visitor visits while the user is // looking at the popup. $latestVisitTime = reset($rows)->getColumn('lastActionDateTime'); $result['nextVisitorId'] = $this->getAdjacentVisitorId($idSite, $visitorId, $latestVisitTime, $segment, $getNext = true); $result['previousVisitorId'] = $this->getAdjacentVisitorId($idSite, $visitorId, $latestVisitTime, $segment, $getNext = false); /** * Triggered in the Live.getVisitorProfile API method. Plugins can use this event * to discover and add extra data to visitor profiles. * * For example, if an email address is found in a custom variable, a plugin could load the * gravatar for the email and add it to the visitor profile, causing it to display in the * visitor profile popup. * * The following visitor profile elements can be set to augment the visitor profile popup: * * - **visitorAvatar**: A URL to an image to display in the top left corner of the popup. * - **visitorDescription**: Text to be used as the tooltip of the avatar image. * * @param array &$visitorProfile The unaugmented visitor profile info. */ Piwik::postEvent('Live.getExtraVisitorDetails', array(&$result)); return $result; }
/** * Returns the currency symbol for a site. * * @param int $idSite The ID of the site to return the currency symbol for. * @return string eg, `'$'`. */ public static function getCurrencySymbol($idSite) { $symbols = MetricsFormatter::getCurrencyList(); $site = new Site($idSite); $currency = $site->getCurrency(); if (isset($symbols[$currency])) { return $symbols[$currency][0]; } return ''; }
protected function applyPrettyMoney(&$sites) { foreach ($sites as $idsite => &$site) { $revenue = "-"; if (!empty($site['revenue'])) { $revenue = MetricsFormatter::getPrettyMoney($site['revenue'], $site['idsite'], $htmlAllowed = false); } $site['revenue'] = '"' . $revenue . '"'; } }
/** * Returns the list of currency symbols * @see getCurrencyList() * @return array( currencyId => currencySymbol ) */ public function getCurrencySymbols() { $currencies = MetricsFormatter::getCurrencyList(); return array_map(function ($a) { return $a[0]; }, $currencies); }
/** * The "Manage Users and Permissions" Admin UI screen */ function index() { Piwik::checkUserIsNotAnonymous(); $view = new View('@UsersManager/index'); $IdSitesAdmin = APISitesManager::getInstance()->getSitesIdWithAdminAccess(); $idSiteSelected = 1; if (count($IdSitesAdmin) > 0) { $defaultWebsiteId = $IdSitesAdmin[0]; $idSiteSelected = Common::getRequestVar('idSite', $defaultWebsiteId); } if ($idSiteSelected === 'all') { $usersAccessByWebsite = array(); $defaultReportSiteName = Piwik::translate('UsersManager_ApplyToAllWebsites'); } else { $usersAccessByWebsite = APIUsersManager::getInstance()->getUsersAccessFromSite($idSiteSelected); $defaultReportSiteName = Site::getNameFor($idSiteSelected); } // we dont want to display the user currently logged so that the user can't change his settings from admin to view... $currentlyLogged = Piwik::getCurrentUserLogin(); $usersLogin = APIUsersManager::getInstance()->getUsersLogin(); foreach ($usersLogin as $login) { if (!isset($usersAccessByWebsite[$login])) { $usersAccessByWebsite[$login] = 'noaccess'; } } unset($usersAccessByWebsite[$currentlyLogged]); // $usersAccessByWebsite is not supposed to contain unexistant logins, but it does when upgrading from some old Piwik version foreach ($usersAccessByWebsite as $login => $access) { if (!in_array($login, $usersLogin)) { unset($usersAccessByWebsite[$login]); continue; } } ksort($usersAccessByWebsite); $users = array(); $superUsers = array(); $usersAliasByLogin = array(); if (Piwik::isUserHasSomeAdminAccess()) { $view->showLastSeen = true; $users = APIUsersManager::getInstance()->getUsers(); foreach ($users as $index => $user) { $usersAliasByLogin[$user['login']] = $user['alias']; $lastSeen = LastSeenTimeLogger::getLastSeenTimeForUser($user['login']); $users[$index]['last_seen'] = $lastSeen == 0 ? false : MetricsFormatter::getPrettyTimeFromSeconds(time() - $lastSeen); } if (Piwik::hasUserSuperUserAccess()) { foreach ($users as $user) { if ($user['superuser_access']) { $superUsers[] = $user['login']; } } } } $view->anonymousHasViewAccess = $this->hasAnonymousUserViewAccess($usersAccessByWebsite); $view->idSiteSelected = $idSiteSelected; $view->defaultReportSiteName = $defaultReportSiteName; $view->users = $users; $view->superUserLogins = $superUsers; $view->usersAliasByLogin = $usersAliasByLogin; $view->usersCount = count($users) - 1; $view->usersAccessByWebsite = $usersAccessByWebsite; $websites = APISitesManager::getInstance()->getSitesWithAdminAccess(); uasort($websites, array('Piwik\\Plugins\\UsersManager\\Controller', 'orderByName')); $view->websites = $websites; $this->setBasicVariablesView($view); return $view->render(); }
protected function addFilter_sumTime() { $sumtimeFilter = new Twig_SimpleFilter('sumtime', function ($numberOfSeconds) { return MetricsFormatter::getPrettyTimeFromSeconds($numberOfSeconds); }); $this->twig->addFilter($sumtimeFilter); }
/** * @dataProvider getGetPrettyValueTestCases */ public function testGetPrettyValue($columnName, $value, $expected) { Translate::loadEnglishTranslation(); $access = Access::getInstance(); $access->setSuperUserAccess(true); $idsite = API::getInstance()->addSite("test", "http://test"); $this->assertEquals($expected, MetricsFormatter::getPrettyValue($idsite, $columnName, $value, false, false)); Translate::unloadEnglishTranslation(); }
/** * Returns the domain age for the current url * * @return int */ public function getAge() { $ageArchiveOrg = $this->_getAgeArchiveOrg(); $ageWhoIs = $this->_getAgeWhoIs(); $ageWhoisCom = $this->_getAgeWhoisCom(); $ages = array(); if ($ageArchiveOrg > 0) { $ages[] = $ageArchiveOrg; } if ($ageWhoIs > 0) { $ages[] = $ageWhoIs; } if ($ageWhoisCom > 0) { $ages[] = $ageWhoisCom; } if (count($ages) > 1) { $maxAge = min($ages); } else { $maxAge = array_shift($ages); } if ($maxAge) { return MetricsFormatter::getPrettyTimeFromSeconds(time() - $maxAge); } return false; }
/** * Enhance $simpleDataTable using metadata : * * - remove metrics based on $reportMetadata['metrics'] * - add 0 valued metrics if $simpleDataTable doesn't provide all $reportMetadata['metrics'] * - format metric values to a 'human readable' format * - extract row metadata to a separate Simple $rowsMetadata * * @param int $idSite enables monetary value formatting based on site currency * @param Simple $simpleDataTable * @param array $metadataColumns * @param boolean $hasDimension * @param bool $returnRawMetrics If set to true, the original metrics will be returned * * @return array DataTable $enhancedDataTable filtered metrics with human readable format & Simple $rowsMetadata */ private function handleSimpleDataTable($idSite, $simpleDataTable, $metadataColumns, $hasDimension, $returnRawMetrics = false) { // new DataTable to store metadata $rowsMetadata = new DataTable(); // new DataTable to store 'human readable' values if ($hasDimension) { $enhancedDataTable = new DataTable(); } else { $enhancedDataTable = new Simple(); } // add missing metrics foreach ($simpleDataTable->getRows() as $row) { $rowMetrics = $row->getColumns(); foreach ($metadataColumns as $id => $name) { if (!isset($rowMetrics[$id])) { $row->addColumn($id, 0); } } } foreach ($simpleDataTable->getRows() as $row) { $enhancedRow = new Row(); $enhancedDataTable->addRow($enhancedRow); $rowMetrics = $row->getColumns(); foreach ($rowMetrics as $columnName => $columnValue) { // filter metrics according to metadata definition if (isset($metadataColumns[$columnName])) { // generate 'human readable' metric values $prettyValue = MetricsFormatter::getPrettyValue($idSite, $columnName, $columnValue, $htmlAllowed = false); $enhancedRow->addColumn($columnName, $prettyValue); } elseif ($returnRawMetrics) { $enhancedRow->addColumn($columnName, $columnValue); } } // If report has a dimension, extract metadata into a distinct DataTable if ($hasDimension) { $rowMetadata = $row->getMetadata(); $idSubDataTable = $row->getIdSubDataTable(); // Create a row metadata only if there are metadata to insert if (count($rowMetadata) > 0 || !is_null($idSubDataTable)) { $metadataRow = new Row(); $rowsMetadata->addRow($metadataRow); foreach ($rowMetadata as $metadataKey => $metadataValue) { $metadataRow->addColumn($metadataKey, $metadataValue); } if (!is_null($idSubDataTable)) { $metadataRow->addColumn('idsubdatatable', $idSubDataTable); } } } } return array($enhancedDataTable, $rowsMetadata); }