Returns the timezone of the site with the specified ID.
public static getTimezoneFor ( integer $idsite ) : string | ||
$idsite | integer | The site ID. |
리턴 | string |
/** * This method takes the websites timezone into consideration when scheduling a task. * @param int $idSite * @param string $period Eg 'day', 'week', 'month' * @return Daily|Monthly|Weekly * @throws \Exception * @ignore */ public static function getScheduledTimeForSite($idSite, $period) { $arbitraryDateInUTC = Date::factory('2011-01-01'); $midnightInSiteTimezone = date('H', Date::factory($arbitraryDateInUTC, Site::getTimezoneFor($idSite))->getTimestamp()); $hourInUTC = (24 - $midnightInSiteTimezone) % 24; $schedule = self::getScheduledTimeForPeriod($period); $schedule->setHour($hourInUTC); return $schedule; }
public function schedule() { foreach (API::getInstance()->getReports() as $report) { if (!$report['deleted'] && $report['period'] != ScheduledTime::PERIOD_NEVER) { $timezone = Site::getTimezoneFor($report['idsite']); $schedule = ScheduledTime::getScheduledTimeForPeriod($report['period']); $schedule->setHour($report['hour']); $schedule->setTimezone($timezone); $this->custom(API::getInstance(), 'sendReport', $report['idreport'], $schedule); } } }
public function schedule() { $alerts = new CustomAlerts(); $siteIds = $alerts->getSiteIdsHavingAlerts(); foreach ($siteIds as $idSite) { $timezoneForSite = Site::getTimezoneFor($idSite); $scheduledTime = $this->daily('runAlertsDaily', $idSite); $scheduledTime->setTimezone($timezoneForSite); $scheduledTime = $this->weekly('runAlertsWeekly', $idSite); $scheduledTime->setTimezone($timezoneForSite); $scheduledTime = $this->monthly('runAlertsMonthly', $idSite); $scheduledTime->setTimezone($timezoneForSite); } }
/** * Returns datatable describing the number of visits for each day of the week. * * @param string $idSite The site ID. Cannot refer to multiple sites. * @param string $period The period type: day, week, year, range... * @param string $date The start date of the period. Cannot refer to multiple dates. * @param bool|string $segment The segment. * @throws Exception * @return DataTable */ public function getByDayOfWeek($idSite, $period, $date, $segment = false) { Piwik::checkUserHasViewAccess($idSite); // metrics to query $metrics = Metrics::getVisitsMetricNames(); unset($metrics[Metrics::INDEX_MAX_ACTIONS]); // disabled for multiple dates if (Period::isMultiplePeriod($date, $period)) { throw new Exception("VisitTime.getByDayOfWeek does not support multiple dates."); } // get metric data for every day within the supplied period $oPeriod = Period\Factory::makePeriodFromQueryParams(Site::getTimezoneFor($idSite), $period, $date); $dateRange = $oPeriod->getDateStart()->toString() . ',' . $oPeriod->getDateEnd()->toString(); $archive = Archive::build($idSite, 'day', $dateRange, $segment); // disabled for multiple sites if (count($archive->getParams()->getIdSites()) > 1) { throw new Exception("VisitTime.getByDayOfWeek does not support multiple sites."); } $dataTable = $archive->getDataTableFromNumeric($metrics)->mergeChildren(); // if there's no data for this report, don't bother w/ anything else if ($dataTable->getRowsCount() == 0) { return $dataTable; } // group by the day of the week (see below for dayOfWeekFromDate function) $dataTable->filter('GroupBy', array('label', __NAMESPACE__ . '\\dayOfWeekFromDate')); // create new datatable w/ empty rows, then add calculated datatable $rows = array(); foreach (array(1, 2, 3, 4, 5, 6, 7) as $day) { $rows[] = array('label' => $day, 'nb_visits' => 0); } $result = new DataTable(); $result->addRowsFromSimpleArray($rows); $result->addDataTable($dataTable); // set day of week integer as metadata $result->filter('ColumnCallbackAddMetadata', array('label', 'day_of_week')); // translate labels $result->filter('ColumnCallbackReplace', array('label', __NAMESPACE__ . '\\translateDayOfWeek')); // set datatable metadata for period start & finish $result->setMetadata('date_start', $oPeriod->getDateStart()); $result->setMetadata('date_end', $oPeriod->getDateEnd()); return $result; }
private function getDateRangeForFooterMessage() { // get query params $idSite = Common::getRequestVar('idSite', false); $date = Common::getRequestVar('date', false); $period = Common::getRequestVar('period', false); // create a period instance try { $oPeriod = Period\Factory::makePeriodFromQueryParams(Site::getTimezoneFor($idSite), $period, $date); } catch (\Exception $ex) { return ''; // if query params are incorrect, forget about the footer message } // set the footer message using the period start & end date $start = $oPeriod->getDateStart()->toString(); $end = $oPeriod->getDateEnd()->toString(); if ($start == $end) { $dateRange = $start; } else { $dateRange = $start . " – " . $end; } return $dateRange; }
/** * The Multisites reports displays the first calendar date as the earliest day available for all websites. * Also, today is the later "today" available across all timezones. * @param array $siteIds Array of IDs for each site being displayed. * @return Date[] of two Date instances. First is the min-date & the second * is the max date. * @ignore */ public static function getMinMaxDateAcrossWebsites($siteIds) { $siteIds = self::getIdSitesFromIdSitesString($siteIds); $now = Date::now(); $minDate = null; $maxDate = $now->subDay(1)->getTimestamp(); foreach ($siteIds as $idsite) { // look for 'now' in the website's timezone $timezone = Site::getTimezoneFor($idsite); $date = Date::adjustForTimezone($now->getTimestamp(), $timezone); if ($date > $maxDate) { $maxDate = $date; } // look for the absolute minimum date $creationDate = Site::getCreationDateFor($idsite); $date = Date::adjustForTimezone(strtotime($creationDate), $timezone); if (is_null($minDate) || $date < $minDate) { $minDate = $date; } } return array(Date::factory($minDate), Date::factory($maxDate)); }
private function hasBeenProcessedSinceMidnight($idSite, $lastTimestampWebsiteProcessedDay) { if (false === $lastTimestampWebsiteProcessedDay) { return true; } $timezone = Site::getTimezoneFor($idSite); $dateInTimezone = Date::factory('now', $timezone); $midnightInTimezone = $dateInTimezone->setTime('00:00:00'); $lastProcessedDateInTimezone = Date::factory((int) $lastTimestampWebsiteProcessedDay, $timezone); return $lastProcessedDateInTimezone->getTimestamp() >= $midnightInTimezone->getTimestamp(); }
/** * Returns a new Archive instance that will query archive data for the given set of * sites and periods, using an optional Segment. * * This method uses data that is found in query parameters, so the parameters to this * function can be string values. * * If you want to create an Archive instance with an array of Period instances, use * {@link Archive::factory()}. * * @param string|int|array $idSites A single ID (eg, `'1'`), multiple IDs (eg, `'1,2,3'` or `array(1, 2, 3)`), * or `'all'`. * @param string $period 'day', `'week'`, `'month'`, `'year'` or `'range'` * @param Date|string $strDate 'YYYY-MM-DD', magic keywords (ie, 'today'; {@link Date::factory()} * or date range (ie, 'YYYY-MM-DD,YYYY-MM-DD'). * @param bool|false|string $segment Segment definition or false if no segment should be used. {@link Piwik\Segment} * @param bool|false|string $_restrictSitesToLogin Used only when running as a scheduled task. * @param bool $skipAggregationOfSubTables Whether the archive, when it is processed, should also aggregate all sub-tables * @return Archive */ public static function build($idSites, $period, $strDate, $segment = false, $_restrictSitesToLogin = false, $skipAggregationOfSubTables = false) { $websiteIds = Site::getIdSitesFromIdSitesString($idSites, $_restrictSitesToLogin); if (Period::isMultiplePeriod($strDate, $period)) { $oPeriod = Factory::build($period, $strDate); $allPeriods = $oPeriod->getSubperiods(); } else { $timezone = count($websiteIds) == 1 ? Site::getTimezoneFor($websiteIds[0]) : false; $oPeriod = Factory::makePeriodFromQueryParams($timezone, $period, $strDate); $allPeriods = array($oPeriod); } $segment = new Segment($segment, $websiteIds); $idSiteIsAll = $idSites == self::REQUEST_ALL_WEBSITES_FLAG; $isMultipleDate = Period::isMultiplePeriod($strDate, $period); return Archive::factory($segment, $allPeriods, $websiteIds, $idSiteIsAll, $isMultipleDate, $skipAggregationOfSubTables); }
protected function enrichTriggeredAlerts($triggeredAlerts) { $processedReport = new ProcessedReport(); $cached = array(); foreach ($triggeredAlerts as &$alert) { $idSite = $alert['idsite']; $metric = $alert['metric']; $report = $alert['report']; if (!array_key_exists($idSite, $cached)) { $cached[$idSite] = array('report' => array(), 'metric' => array(), 'siteName' => '', 'siteTimezone' => null); } if (empty($cached[$idSite]['siteName'])) { $cached[$idSite]['siteName'] = $this->findSiteName($alert); } if (empty($cached[$idSite]['siteTimezone']) && !empty($cached[$idSite]['siteName'])) { $cached[$idSite]['siteTimezone'] = Site::getTimezoneFor($idSite); } if (!array_key_exists($report, $cached[$idSite]['report'])) { $cached[$idSite]['report'][$report] = $this->findReportMetadata($alert); $cached[$idSite]['metric'][$report] = array(); } if (is_array($cached[$idSite]['metric'][$report]) && !array_key_exists($metric, $cached[$idSite]['metric'][$report])) { $cached[$idSite]['metric'][$report][$metric] = $processedReport->translateMetric($metric, $idSite, $alert['report']); } } foreach ($triggeredAlerts as &$alert) { $idSite = $alert['idsite']; $metric = $alert['metric']; $report = $alert['report']; $cachedSite = $cached[$idSite]; $alert['value_old'] = (int) $alert['value_old'] == $alert['value_old'] ? (int) $alert['value_old'] : $alert['value_old']; $alert['value_new'] = (int) $alert['value_new'] == $alert['value_new'] ? (int) $alert['value_new'] : $alert['value_new']; $alert['reportName'] = null; $alert['dimension'] = null; $alert['reportMetric'] = !empty($cachedSite['metric'][$report][$metric]) ? $cachedSite['metric'][$report][$metric] : null; $alert['reportConditionName'] = null; $alert['siteName'] = $cached[$idSite]['siteName']; $alert['ts_triggered'] = $this->getPrettyDateForSite($alert['ts_triggered'], $alert['period'], $cachedSite['siteTimezone']); if (!empty($cachedSite['report'][$report])) { $reportMetadata = $cachedSite['report'][$report]; $alert['reportName'] = $reportMetadata['name']; $alert['dimension'] = !empty($reportMetadata['dimension']) ? $reportMetadata['dimension'] : null; $conditionTranslation = array_search($alert['report_condition'], Processor::getGroupConditions(), true); $alert['reportConditionName'] = $conditionTranslation ? Piwik::translate($conditionTranslation) : null; } } return $triggeredAlerts; }
/** * 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; }
protected function adjustTimezoneBySite($hour, $idSite) { $timezone = Site::getTimezoneFor($idSite); $timeZoneDifference = -ceil(Date::getUtcOffset($timezone) / 3600); return (24 + $hour + $timeZoneDifference) % 24; }
public function getScheduledTasks(&$tasks) { $arbitraryDateInUTC = Date::factory('2011-01-01'); foreach (API::getInstance()->getReports() as $report) { if (!$report['deleted'] && $report['period'] != ScheduledTime::PERIOD_NEVER) { $midnightInSiteTimezone = date('H', Date::factory($arbitraryDateInUTC, Site::getTimezoneFor($report['idsite']))->getTimestamp()); $hourInUTC = (24 - $midnightInSiteTimezone + $report['hour']) % 24; $schedule = ScheduledTime::getScheduledTimeForPeriod($report['period']); $schedule->setHour($hourInUTC); $tasks[] = new ScheduledTask(API::getInstance(), 'sendReport', $report['idreport'], $schedule); } } }
private function getDateForAlertInPast($idSite, $period, $subPeriodN) { $timezone = Site::getTimezoneFor($idSite); $date = Date::now(); $date = Date::factory($date->getDatetime(), $timezone); if ($subPeriodN) { $date = $date->subPeriod($subPeriodN, $period); } return $date->toString(); }
protected function getPrettyDateForSite($period, $idSite) { $timezone = Site::getTimezoneFor($idSite); $date = $this->getToday(); $date = Date::factory($date->getDatetime(), $timezone); // we ran the alerts for the period before... $date = $date->subPeriod(1, $period); // also make sure if period is month to display "2014-01" and not "2014-01-31" $period = Period\Factory::build($period, $date); $prettyDate = $period->getLocalizedLongString(); return $prettyDate; }