/** * General method to get transitions for an action * * @param $actionName * @param $actionType "url"|"title" * @param $idSite * @param $period * @param $date * @param bool $segment * @param bool $limitBeforeGrouping * @param string $parts * @return array * @throws Exception */ public function getTransitionsForAction($actionName, $actionType, $idSite, $period, $date, $segment = false, $limitBeforeGrouping = false, $parts = 'all') { Piwik::checkUserHasViewAccess($idSite); // get idaction of the requested action $idaction = $this->deriveIdAction($actionName, $actionType); if ($idaction < 0) { throw new Exception('NoDataForAction'); } // prepare log aggregator $segment = new Segment($segment, $idSite); $site = new Site($idSite); $period = Period::factory($period, $date); $params = new ArchiveProcessor\Parameters($site, $period, $segment); $logAggregator = new LogAggregator($params); // prepare the report $report = array('date' => Period::factory($period->getLabel(), $date)->getLocalizedShortString()); $partsArray = explode(',', $parts); if ($parts == 'all' || in_array('internalReferrers', $partsArray)) { $this->addInternalReferrers($logAggregator, $report, $idaction, $actionType, $limitBeforeGrouping); } if ($parts == 'all' || in_array('followingActions', $partsArray)) { $includeLoops = $parts != 'all' && !in_array('internalReferrers', $partsArray); $this->addFollowingActions($logAggregator, $report, $idaction, $actionType, $limitBeforeGrouping, $includeLoops); } if ($parts == 'all' || in_array('externalReferrers', $partsArray)) { $this->addExternalReferrers($logAggregator, $report, $idaction, $actionType, $limitBeforeGrouping); } // derive the number of exits from the other metrics if ($parts == 'all') { $report['pageMetrics']['exits'] = $report['pageMetrics']['pageviews'] - $this->getTotalTransitionsToFollowingActions() - $report['pageMetrics']['loops']; } // replace column names in the data tables $reportNames = array('previousPages' => true, 'previousSiteSearches' => false, 'followingPages' => true, 'followingSiteSearches' => false, 'outlinks' => true, 'downloads' => true); foreach ($reportNames as $reportName => $replaceLabel) { if (isset($report[$reportName])) { $columnNames = array(Metrics::INDEX_NB_ACTIONS => 'referrals'); if ($replaceLabel) { $columnNames[Metrics::INDEX_NB_ACTIONS] = 'referrals'; } $report[$reportName]->filter('ReplaceColumnNames', array($columnNames)); } } return $report; }
/** * Creates a Period instance using a period, date and timezone. * * @param string $timezone The timezone of the date. Only used if `$date` is `'now'`, `'today'`, * `'yesterday'` or `'yesterdaySameTime'`. * @param string $period The period string: `"day"`, `"week"`, `"month"`, `"year"`, `"range"`. * @param string $date The date or date range string. Can be a special value including * `'now'`, `'today'`, `'yesterday'`, `'yesterdaySameTime'`. * @return \Piwik\Period */ public static function makePeriodFromQueryParams($timezone, $period, $date) { if (empty($timezone)) { $timezone = 'UTC'; } if ($period == 'range') { $oPeriod = new Period\Range('range', $date, $timezone, Date::factory('today', $timezone)); } else { if (!$date instanceof Date) { if ($date == 'now' || $date == 'today') { $date = date('Y-m-d', Date::factory('now', $timezone)->getTimestamp()); } elseif ($date == 'yesterday' || $date == 'yesterdaySameTime') { $date = date('Y-m-d', Date::factory('now', $timezone)->subDay(1)->getTimestamp()); } $date = Date::factory($date); } $oPeriod = Period::factory($period, $date); } return $oPeriod; }
/** * Adds new subperiods * * @param Date $startDate * @param Date $endDate * @param string $period */ protected function fillArraySubPeriods($startDate, $endDate, $period) { $arrayPeriods = array(); $endSubperiod = Period::factory($period, $endDate); $arrayPeriods[] = $endSubperiod; // set end date to start of end period since we're comparing against start date. $endDate = $endSubperiod->getDateStart(); while ($endDate->isLater($startDate)) { $endDate = $endDate->addPeriod(-1, $period); $subPeriod = Period::factory($period, $endDate); $arrayPeriods[] = $subPeriod; } $arrayPeriods = array_reverse($arrayPeriods); foreach ($arrayPeriods as $period) { $this->addSubperiod($period); } }
public function getSitesInfo($isWidgetized = false) { Piwik::checkUserHasSomeViewAccess(); $displayRevenueColumn = Common::isGoalPluginEnabled(); $date = Common::getRequestVar('date', 'today'); $period = Common::getRequestVar('period', 'day'); $siteIds = APISitesManager::getInstance()->getSitesIdWithAtLeastViewAccess(); list($minDate, $maxDate) = Site::getMinMaxDateAcrossWebsites($siteIds); // overwrites the default Date set in the parent controller // Instead of the default current website's local date, // we set "today" or "yesterday" based on the default Piwik timezone $piwikDefaultTimezone = APISitesManager::getInstance()->getDefaultTimezone(); if ($period != 'range') { $date = $this->getDateParameterInTimezone($date, $piwikDefaultTimezone); $this->setDate($date); $date = $date->toString(); } $dataTable = APIMultiSites::getInstance()->getAll($period, $date, $segment = false); // put data into a form the template will understand better $digestableData = array(); foreach ($siteIds as $idSite) { $isEcommerceEnabled = Site::isEcommerceEnabledFor($idSite); $digestableData[$idSite] = array('idsite' => $idSite, 'main_url' => Site::getMainUrlFor($idSite), 'name' => Site::getNameFor($idSite), 'visits' => 0, 'pageviews' => 0); if ($period != 'range') { $digestableData[$idSite]['visits_evolution'] = 0; $digestableData[$idSite]['pageviews_evolution'] = 0; } if ($displayRevenueColumn) { $revenueDefault = $isEcommerceEnabled ? 0 : "'-'"; if ($period != 'range') { $digestableData[$idSite]['revenue_evolution'] = $revenueDefault; } } } foreach ($dataTable->getRows() as $row) { $idsite = (int) $row->getMetadata('idsite'); $site =& $digestableData[$idsite]; $site['visits'] = (int) $row->getColumn('nb_visits'); $site['pageviews'] = (int) $row->getColumn('nb_pageviews'); if ($displayRevenueColumn) { if ($row->getColumn('revenue') !== false) { $site['revenue'] = $row->getColumn('revenue'); } } if ($period != 'range') { $site['visits_evolution'] = $row->getColumn('visits_evolution'); $site['pageviews_evolution'] = $row->getColumn('pageviews_evolution'); if ($displayRevenueColumn) { $site['revenue_evolution'] = $row->getColumn('revenue_evolution'); } } } $this->applyPrettyMoney($digestableData); $view = new View("@MultiSites/getSitesInfo"); $view->isWidgetized = $isWidgetized; $view->sitesData = array_values($digestableData); $view->evolutionBy = $this->evolutionBy; $view->period = $period; $view->page = $this->page; $view->limit = $this->limit; $view->orderBy = $this->orderBy; $view->order = $this->order; $view->totalVisits = $dataTable->getMetadata('total_nb_visits'); $view->totalRevenue = $dataTable->getMetadata('total_revenue'); $view->displayRevenueColumn = $displayRevenueColumn; $view->totalPageviews = $dataTable->getMetadata('total_nb_pageviews'); $view->pastTotalVisits = $dataTable->getMetadata('last_period_total_nb_visits'); $view->totalVisitsEvolution = $dataTable->getMetadata('total_visits_evolution'); if ($view->totalVisitsEvolution > 0) { $view->totalVisitsEvolution = '+' . $view->totalVisitsEvolution; } if ($period != 'range') { $lastPeriod = Period::factory($period, $dataTable->getMetadata('last_period_date')); $view->pastPeriodPretty = self::getCalendarPrettyDate($lastPeriod); } $params = $this->getGraphParamsModified(); $view->dateSparkline = $period == 'range' ? $date : $params['date']; $view->autoRefreshTodayReport = false; // if the current date is today, or yesterday, // in case the website is set to UTC-12), or today in UTC+14, we refresh the page every 5min if (in_array($date, array('today', date('Y-m-d'), 'yesterday', Date::factory('yesterday')->toString('Y-m-d'), Date::factory('now', 'UTC+14')->toString('Y-m-d')))) { $view->autoRefreshTodayReport = Config::getInstance()->General['multisites_refresh_after_seconds']; } $this->setGeneralVariablesView($view); $this->setMinDateView($minDate, $view); $this->setMaxDateView($maxDate, $view); $view->show_sparklines = Config::getInstance()->General['show_multisites_sparklines']; return $view->render(); }
/** * Sends the http headers for csv file */ protected function renderHeader() { $fileName = 'Piwik ' . Piwik::translate('General_Export'); $period = Common::getRequestVar('period', false); $date = Common::getRequestVar('date', false); if ($period || $date) { if ($period == 'range') { $period = new Range($period, $date); } else { if (strpos($date, ',') !== false) { $period = new Range('range', $date); } else { $period = Period::factory($period, Date::factory($date)); } } $prettyDate = $period->getLocalizedLongString(); $meta = $this->getApiMetaData(); $fileName .= ' _ ' . $meta['name'] . ' _ ' . $prettyDate . '.csv'; } // silent fail otherwise unit tests fail @header('Content-Type: application/vnd.ms-excel'); @header('Content-Disposition: attachment; filename="' . $fileName . '"'); ProxyHttp::overrideCacheControlHeaders(); }
public function getProcessedReport($idSite, $period, $date, $apiModule, $apiAction, $segment = false, $apiParameters = false, $idGoal = false, $language = false, $showTimer = true, $hideMetricsDoc = false, $idSubtable = false, $showRawMetrics = false) { $timer = new Timer(); if (empty($apiParameters)) { $apiParameters = array(); } if (!empty($idGoal) && empty($apiParameters['idGoal'])) { $apiParameters['idGoal'] = $idGoal; } // Is this report found in the Metadata available reports? $reportMetadata = $this->getMetadata($idSite, $apiModule, $apiAction, $apiParameters, $language, $period, $date, $hideMetricsDoc, $showSubtableReports = true); if (empty($reportMetadata)) { throw new Exception("Requested report {$apiModule}.{$apiAction} for Website id={$idSite} not found in the list of available reports. \n"); } $reportMetadata = reset($reportMetadata); // Generate Api call URL passing custom parameters $parameters = array_merge($apiParameters, array('method' => $apiModule . '.' . $apiAction, 'idSite' => $idSite, 'period' => $period, 'date' => $date, 'format' => 'original', 'serialize' => '0', 'language' => $language, 'idSubtable' => $idSubtable)); if (!empty($segment)) { $parameters['segment'] = $segment; } $url = Url::getQueryStringFromParameters($parameters); $request = new Request($url); try { /** @var DataTable */ $dataTable = $request->process(); } catch (Exception $e) { throw new Exception("API returned an error: " . $e->getMessage() . " at " . basename($e->getFile()) . ":" . $e->getLine() . "\n"); } list($newReport, $columns, $rowsMetadata, $totals) = $this->handleTableReport($idSite, $dataTable, $reportMetadata, $showRawMetrics); foreach ($columns as $columnId => &$name) { $name = ucfirst($name); } $website = new Site($idSite); $period = Period::factory($period, $date); $period = $period->getLocalizedLongString(); $return = array('website' => $website->getName(), 'prettyDate' => $period, 'metadata' => $reportMetadata, 'columns' => $columns, 'reportData' => $newReport, 'reportMetadata' => $rowsMetadata, 'reportTotal' => $totals); if ($showTimer) { $return['timerMillis'] = $timer->getTimeMs(0); } return $return; }
/** * Returns start & end dates for the range described by a period and optional lastN * argument. * * @param string|bool $date The start date of the period (or the date range of a range * period). * @param string $period The period type ('day', 'week', 'month', 'year' or 'range'). * @param bool|int $lastN Whether to include the last N periods in the range or not. * Ignored if period == range. * * @return Date[] array of Date objects or array(false, false) * @ignore */ public static function getDateRangeForPeriod($date, $period, $lastN = false) { if ($date === false) { return array(false, false); } // if the range is just a normal period (or the period is a range in which case lastN is ignored) if ($lastN === false || $period == 'range') { if ($period == 'range') { $oPeriod = new Range('day', $date); } else { $oPeriod = Period::factory($period, Date::factory($date)); } $startDate = $oPeriod->getDateStart(); $endDate = $oPeriod->getDateEnd(); } else { list($date, $lastN) = EvolutionViz::getDateRangeAndLastN($period, $date, $lastN); list($startDate, $endDate) = explode(',', $date); $startDate = Date::factory($startDate); $endDate = Date::factory($endDate); } return array($startDate, $endDate); }
private function loadLastVisitorDetailsFromDatabase($idSite, $period, $date, $segment = false, $countVisitorsToFetch = 100, $visitorId = false, $minTimestamp = false) { $where = $whereBind = array(); list($whereClause, $idSites) = $this->getIdSitesWhereClause($idSite); $where[] = $whereClause; $whereBind = $idSites; $orderBy = "idsite, visit_last_action_time DESC"; $orderByParent = "sub.visit_last_action_time DESC"; if (!empty($visitorId)) { $where[] = "log_visit.idvisitor = ? "; $whereBind[] = @Common::hex2bin($visitorId); } if (!empty($minTimestamp)) { $where[] = "log_visit.visit_last_action_time > ? "; $whereBind[] = date("Y-m-d H:i:s", $minTimestamp); } // If no other filter, only look at the last 24 hours of stats if (empty($visitorId) && empty($countVisitorsToFetch) && empty($period) && empty($date)) { $period = 'day'; $date = 'yesterdaySameTime'; } // SQL Filter with provided period if (!empty($period) && !empty($date)) { $currentSite = new Site($idSite); $currentTimezone = $currentSite->getTimezone(); $dateString = $date; if ($period == 'range') { $processedPeriod = new Range('range', $date); if ($parsedDate = Range::parseDateRange($date)) { $dateString = $parsedDate[2]; } } else { $processedDate = Date::factory($date); if ($date == 'today' || $date == 'now' || $processedDate->toString() == Date::factory('now', $currentTimezone)->toString()) { $processedDate = $processedDate->subDay(1); } $processedPeriod = Period::factory($period, $processedDate); } $dateStart = $processedPeriod->getDateStart()->setTimezone($currentTimezone); $where[] = "log_visit.visit_last_action_time >= ?"; $whereBind[] = $dateStart->toString('Y-m-d H:i:s'); if (!in_array($date, array('now', 'today', 'yesterdaySameTime')) && strpos($date, 'last') === false && strpos($date, 'previous') === false && Date::factory($dateString)->toString('Y-m-d') != Date::factory('now', $currentTimezone)->toString()) { $dateEnd = $processedPeriod->getDateEnd()->setTimezone($currentTimezone); $where[] = " log_visit.visit_last_action_time <= ?"; $dateEndString = $dateEnd->addDay(1)->toString('Y-m-d H:i:s'); $whereBind[] = $dateEndString; } } if (count($where) > 0) { $where = join("\n\t\t\t\tAND ", $where); } else { $where = false; } $segment = new Segment($segment, $idSite); // Subquery to use the indexes for ORDER BY $select = "log_visit.*"; $from = "log_visit"; $subQuery = $segment->getSelectQuery($select, $from, $where, $whereBind, $orderBy); $sqlLimit = $countVisitorsToFetch >= 1 ? " LIMIT 0, " . (int) $countVisitorsToFetch : ""; // Group by idvisit so that a visitor converting 2 goals only appears once $sql = "\n\t\t\tSELECT sub.*\n\t\t\tFROM (\n\t\t\t\t" . $subQuery['sql'] . "\n\t\t\t\t{$sqlLimit}\n\t\t\t) AS sub\n\t\t\tGROUP BY sub.idvisit\n\t\t\tORDER BY {$orderByParent}\n\t\t"; try { $data = Db::fetchAll($sql, $subQuery['bind']); } catch (Exception $e) { echo $e->getMessage(); exit; } $dataTable = new DataTable(); $dataTable->addRowsFromSimpleArray($data); return $dataTable; }
/** * Returns the pretty date representation * * @param $date string * @param $period string * @return string Pretty date */ public static function getPrettyDate($date, $period) { return self::getCalendarPrettyDate(Period::factory($period, Date::factory($date))); }