/** * today is NOT finished * @group Core */ public function testDayIsFinishedToday() { $period = new Day(Date::today()); $this->assertEquals(date("Y-m-d"), $period->toString()); $this->assertEquals(array(), $period->getSubperiods()); $this->assertEquals(0, $period->getNumberOfSubperiods()); }
public function test_filterDataTable_MatchesExactlyIntegration() { $date = Date::today()->addHour(10); $t = Fixture::getTracker($this->idSite, $date->getDatetime(), $defaultInit = true); $t->setUrlReferrer('http://www.google.com.vn/url?sa=t&rct=j&q=%3C%3E%26%5C%22the%20pdo%20extension%20is%20required%20for%20this%20adapter%20but%20the%20extension%20is%20not%20loaded&source=web&cd=4&ved=0FjAD&url=http%3A%2F%2Fforum.piwik.org%2Fread.php%3F2%2C1011&ei=y-HHAQ&usg=AFQjCN2-nt5_GgDeg&cad=rja'); $t->setUrl('http://example.org/%C3%A9%C3%A9%C3%A9%22%27...%20%3Cthis%20is%20cool%3E!'); $t->setGenerationTime(523); $t->doTrackPageView('incredible title! <>,;'); $t->setForceVisitDateTime($date->addHour(0.1)->getDatetime()); $t->setUrl('http://example.org/dir/file.php?foo=bar&foo2=bar'); $t->setGenerationTime(123); $t->doTrackPageView('incredible title! <>,;'); $t->setForceVisitDateTime($date->addHour(0.2)->getDatetime()); $t->setUrl('http://example.org/dir/file/xyz.php?foo=bar&foo2=bar'); $t->setGenerationTime(231); $t->doTrackPageView('incredible title! <>,;'); $t->setForceVisitDateTime($date->addHour(0.2)->getDatetime()); $t->setUrl('http://example.org/what-is-piwik'); $t->setGenerationTime(231); $t->doTrackPageView('incredible title! <>,;'); $t->setForceVisitDateTime($date->addHour(0.3)->getDatetime()); $t->setUrl('http://example.org/dir/file.php?foo=bar&foo2=bar'); $t->setGenerationTime(147); $t->doTrackPageView('incredible title! <>,;'); // for some reasons @dataProvider results in an "Mysql::getProfiler() undefined method" error $assertions = array(array('nb_hits', 'what-is-piwik', 1), array('nb_hits', '/what-is-piwik', null), array('nb_hits', 'foo', 3), array('nb_visits', 'foo', 2), array('nb_hits', 'i', 5), array('nb_hits', 'foo2=bar', 3), array('nb_hits', '/', 3), array('nb_hits', 'foo=bar&foo2=bar', 3), array('nb_hits', 'php?foo=bar&foo2=bar', 3), array('nb_hits', 'file.php?foo=bar&foo2=bar', 2), array('nb_hits', 'dir/file.php?foo=bar&foo2=bar', 2), array('nb_hits', 'dir', 3), array('avg_time_generation', 'dir/file.php?foo=bar&foo2=bar', 0.135), array('bounce_rate', 'php?foo=bar', 0)); foreach ($assertions as $assert) { $alert = array('report' => 'Actions_getPageUrls', 'metric' => $assert[0], 'period' => 'day', 'report_condition' => 'contains', 'report_matched' => Common::sanitizeInputValue($assert[1])); $value = $this->processor->getValueForAlertInPast($alert, $this->idSite, 0); $this->assertEquals($assert[2], $value, $assert[0] . ':' . $assert[1] . ' should return value ' . $assert[2] . ' but returns ' . $value); } }
/** * Controller action that returns HTML displaying annotations for a site and * specific date range. * * Query Param Input: * - idSite: The ID of the site to get annotations for. Only one allowed. * - date: The date to get annotations for. If lastN is not supplied, this is the start date, * otherwise the start date in the last period. * - period: The period type. * - lastN: If supplied, the last N # of periods will be included w/ the range specified * by date + period. * * Output: * - HTML displaying annotations for a specific range. * * @param bool $fetch True if the annotation manager should be returned as a string, * false if it should be echo-ed. * @param bool|string $date Override for 'date' query parameter. * @param bool|string $period Override for 'period' query parameter. * @param bool|string $lastN Override for 'lastN' query parameter. * @return string|void */ public function getAnnotationManager($fetch = false, $date = false, $period = false, $lastN = false) { $idSite = Common::getRequestVar('idSite'); if ($date === false) { $date = Common::getRequestVar('date', false); } if ($period === false) { $period = Common::getRequestVar('period', 'day'); } if ($lastN === false) { $lastN = Common::getRequestVar('lastN', false); } // create & render the view $view = new View('@Annotations/getAnnotationManager'); $allAnnotations = Request::processRequest('Annotations.getAll', array('date' => $date, 'period' => $period, 'lastN' => $lastN)); $view->annotations = empty($allAnnotations[$idSite]) ? array() : $allAnnotations[$idSite]; $view->period = $period; $view->lastN = $lastN; list($startDate, $endDate) = API::getDateRangeForPeriod($date, $period, $lastN); $view->startDate = $startDate->toString(); $view->endDate = $endDate->toString(); if ($startDate->toString() !== $endDate->toString()) { $view->selectedDate = Date::today()->toString(); } else { $view->selectedDate = $endDate->toString(); } $dateFormat = Piwik::translate('CoreHome_ShortDateFormatWithYear'); $view->startDatePretty = $startDate->getLocalized($dateFormat); $view->endDatePretty = $endDate->getLocalized($dateFormat); $view->canUserAddNotes = AnnotationList::canUserAddNotesFor($idSite); return $view->render(); }
public function testFactoryInvalid() { try { Period\Factory::build('inValid', Date::today()); } catch (\Exception $e) { return; } $this->fail('Expected Exception not raised'); }
/** * create today object check that timestamp is correct (midnight) * * @group Core */ public function testToday() { $date = Date::today(); $this->assertEquals(strtotime(date("Y-m-d ") . " 00:00:00"), $date->getTimestamp()); // test getDatetime() $this->assertEquals($date->getDatetime(), $date->getDateStartUTC()); $date = $date->setTime('12:00:00'); $this->assertEquals(date('Y-m-d') . ' 12:00:00', $date->getDatetime()); }
protected function processAlert($alert, $idSite) { if (!$this->shouldBeProcessed($alert, $idSite)) { return; } $valueNew = $this->getValueForAlertInPast($alert, $idSite, 1); if (is_null($valueNew)) { $valueNew = 0; } if (365 == $alert['compared_to'] && Date::today()->isLeapYear()) { $alert['compared_to'] = 366; } $valueOld = $this->getValueForAlertInPast($alert, $idSite, 1 + $alert['compared_to']); if ($this->shouldBeTriggered($alert, $valueNew, $valueOld)) { $this->triggerAlert($alert, $idSite, $valueNew, $valueOld); } }
public function test_markArchivedReportsAsInvalidIfArchiveAlreadyFinished_shouldConsiderWebsitesTimezone() { $timezone1 = 'UTC+4'; $timezone2 = 'UTC+6'; $currentActionTime1 = Date::today()->setTimezone($timezone1)->getDatetime(); $currentActionTime2 = Date::today()->setTimezone($timezone2)->getDatetime(); $idsite = API::getInstance()->addSite('name', 'http://piwik.net/', $ecommerce = null, $siteSearch = null, $searchKeywordParameters = null, $searchCategoryParameters = null, $excludedIps = null, $excludedQueryParameters = null, $timezone = 'UTC+5'); $expectedRemembered = array(substr($currentActionTime1, 0, 10) => array($idsite)); // if website timezone was von considered both would be today (expected = array()) $this->assertRememberedArchivedReportsThatShouldBeInvalidated($idsite, $currentActionTime1, array()); $this->assertRememberedArchivedReportsThatShouldBeInvalidated($idsite, $currentActionTime2, $expectedRemembered); }
/** * Gets the IDs of the archives we're querying for and stores them in $this->archives. * This function will launch the archiving process for each period/site/plugin if * metrics/reports have not been calculated/archived already. * * @param array $archiveGroups @see getArchiveGroupOfReport * @param array $plugins List of plugin names to archive. */ private function cacheArchiveIdsAfterLaunching($archiveGroups, $plugins) { $today = Date::today(); foreach ($this->params->getPeriods() as $period) { $twoDaysBeforePeriod = $period->getDateStart()->subDay(2); $twoDaysAfterPeriod = $period->getDateEnd()->addDay(2); foreach ($this->params->getIdSites() as $idSite) { $site = new Site($idSite); // if the END of the period is BEFORE the website creation date // we already know there are no stats for this period // we add one day to make sure we don't miss the day of the website creation if ($twoDaysAfterPeriod->isEarlier($site->getCreationDate())) { Log::verbose("Archive site %s, %s (%s) skipped, archive is before the website was created.", $idSite, $period->getLabel(), $period->getPrettyString()); continue; } // if the starting date is in the future we know there is no visiidsite = ?t if ($twoDaysBeforePeriod->isLater($today)) { Log::verbose("Archive site %s, %s (%s) skipped, archive is after today.", $idSite, $period->getLabel(), $period->getPrettyString()); continue; } $this->prepareArchive($archiveGroups, $site, $period); } } }
/** * @param $period * @return bool|int */ private function getPeriodId($period) { if (!empty($period)) { $period = Period\Factory::build($period, Date::today()); } $invalidateForPeriod = $period ? $period->getId() : false; return $invalidateForPeriod; }
/** * Returns the date that is X periods before the supplied date. * * @param bool|string $date The date to get the last date of. * @param bool|string $period The period to use (either 'day', 'week', 'month', 'year'); * @param int $subXPeriods How many periods in the past the date should be, for instance 1 or 7. * If sub period is 365 days and the current year is a leap year we assume you want to get the * day one year ago and change the value to 366 days therefore. * * @return array An array with two elements, a string for the date before $date and * a Period instance for the period before $date. * @api */ public static function getDateXPeriodsAgo($subXPeriods, $date = false, $period = false) { if ($date === false) { $date = Common::getRequestVar('date'); } if ($period === false) { $period = Common::getRequestVar('period'); } if (365 == $subXPeriods && 'day' == $period && Date::today()->isLeapYear()) { $subXPeriods = 366; } // can't get the last date for range periods & dates that use lastN/previousN $strLastDate = false; $lastPeriod = false; if ($period != 'range' && !preg_match('/(last|previous)([0-9]*)/', $date, $regs)) { if (strpos($date, ',')) { // date in the form of 2011-01-01,2011-02-02 $rangePeriod = new Range($period, $date); $lastStartDate = $rangePeriod->getDateStart()->subPeriod($subXPeriods, $period); $lastEndDate = $rangePeriod->getDateEnd()->subPeriod($subXPeriods, $period); $strLastDate = "{$lastStartDate},{$lastEndDate}"; } else { $lastPeriod = Date::factory($date)->subPeriod($subXPeriods, $period); $strLastDate = $lastPeriod->toString(); } } return array($strLastDate, $lastPeriod); }
public function testRangeYearLast1() { $range = new Range('year', 'last1'); $currentYear = new Year(Date::today()); $this->assertEquals(1, $range->getNumberOfSubperiods()); $this->assertEquals(array($currentYear->toString()), $range->toString()); }
/** * Returns a summary for an important visit. Used to describe the first & last visits of a visitor. * * @param Row $visit * @return array */ private function getVisitorProfileVisitSummary($visit) { $today = Date::today(); $serverDate = $visit->getColumn('firstActionTimestamp'); return array('date' => $serverDate, 'prettyDate' => Date::factory($serverDate)->getLocalized(self::VISITOR_PROFILE_DATE_FORMAT), 'daysAgo' => (int) Date::secondsToDays($today->getTimestamp() - Date::factory($serverDate)->getTimestamp()), 'referrerType' => $visit->getColumn('referrerType'), 'referralSummary' => self::getReferrerSummaryForVisit($visit)); }
/** * Returns a summary for an important visit. Used to describe the first & last visits of a visitor. * * @param DataTable\Row $visit * @return array */ private function getVisitorProfileVisitSummary($visit) { $today = Date::today(); $serverDate = $visit->getColumn('firstActionTimestamp'); return array('date' => $serverDate, 'prettyDate' => Date::factory($serverDate)->getLocalized(Piwik::translate('CoreHome_DateFormat')), 'daysAgo' => (int) Date::secondsToDays($today->getTimestamp() - Date::factory($serverDate)->getTimestamp()), 'referrerType' => $visit->getColumn('referrerType'), 'referralSummary' => self::getReferrerSummaryForVisit($visit)); }
/** * When tracking data in the past (using Tracking API), this function * can be used to invalidate reports for the idSites and dates where new data * was added. * DEV: If you call this API, the UI should display the data correctly, but will process * in real time, which could be very slow after large data imports. * After calling this function via REST, you can manually force all data * to be reprocessed by visiting the script as the Super User: * http://example.net/piwik/misc/cron/archive.php?token_auth=$SUPER_USER_TOKEN_AUTH_HERE * REQUIREMENTS: On large piwik setups, you will need in PHP configuration: max_execution_time = 0 * We recommend to use an hourly schedule of the script. * More information: http://piwik.org/setup-auto-archiving/ * * @param string $idSites Comma separated list of idSite that have had data imported for the specified dates * @param string $dates Comma separated list of dates to invalidate for all these websites * @param string $period If specified (one of day, week, month, year, range) it will only delete archives for this period. * Note: because week, month, year, range reports aggregate day reports then you need to specifically invalidate day reports to see * other periods reports processed.. * @throws Exception * @return array */ public function invalidateArchivedReports($idSites, $dates, $period = false) { $idSites = Site::getIdSitesFromIdSitesString($idSites); if (empty($idSites)) { throw new Exception("Specify a value for &idSites= as a comma separated list of website IDs, for which your token_auth has 'admin' permission"); } Piwik::checkUserHasAdminAccess($idSites); if (!empty($period)) { $period = Period\Factory::build($period, Date::today()); } // Ensure the specified dates are valid $toInvalidate = $invalidDates = array(); $dates = explode(',', trim($dates)); $dates = array_unique($dates); foreach ($dates as $theDate) { $theDate = trim($theDate); try { $date = Date::factory($theDate); } catch (Exception $e) { $invalidDates[] = $theDate; continue; } if ($date->toString() == $theDate) { $toInvalidate[] = $date; } else { $invalidDates[] = $theDate; } } // If using the feature "Delete logs older than N days"... $purgeDataSettings = PrivacyManager::getPurgeDataSettings(); $logsAreDeletedBeforeThisDate = $purgeDataSettings['delete_logs_schedule_lowest_interval']; $logsDeleteEnabled = $purgeDataSettings['delete_logs_enable']; $minimumDateWithLogs = false; if ($logsDeleteEnabled && $logsAreDeletedBeforeThisDate) { $minimumDateWithLogs = Date::factory('today')->subDay($logsAreDeletedBeforeThisDate); } // Given the list of dates, process which tables they should be deleted from $minDate = false; $warningDates = $processedDates = array(); /* @var $date Date */ foreach ($toInvalidate as $date) { // we should only delete reports for dates that are more recent than N days if ($minimumDateWithLogs && $date->isEarlier($minimumDateWithLogs)) { $warningDates[] = $date->toString(); } else { $processedDates[] = $date->toString(); } $month = $date->toString('Y_m'); // For a given date, we must invalidate in the monthly archive table $datesByMonth[$month][] = $date->toString(); // But also the year stored in January $year = $date->toString('Y_01'); $datesByMonth[$year][] = $date->toString(); // but also weeks overlapping several months stored in the month where the week is starting /* @var $week Week */ $week = Period\Factory::build('week', $date); $weekAsString = $week->getDateStart()->toString('Y_m'); $datesByMonth[$weekAsString][] = $date->toString(); // Keep track of the minimum date for each website if ($minDate === false || $date->isEarlier($minDate)) { $minDate = $date; } } if (empty($minDate)) { throw new Exception("Check the 'dates' parameter is a valid date."); } $invalidateForPeriod = $period ? $period->getId() : false; // In each table, invalidate day/week/month/year containing this date $archiveTables = ArchiveTableCreator::getTablesArchivesInstalled(); foreach ($archiveTables as $table) { // Extract Y_m from table name $suffix = ArchiveTableCreator::getDateFromTableName($table); if (!isset($datesByMonth[$suffix])) { continue; } // Dates which are to be deleted from this table $datesToDeleteInTable = $datesByMonth[$suffix]; // Build one statement to delete all dates from the given table $sql = $bind = array(); $datesToDeleteInTable = array_unique($datesToDeleteInTable); foreach ($datesToDeleteInTable as $dateToDelete) { $sql[] = '(date1 <= ? AND ? <= date2 AND name LIKE \'done%\')'; $bind[] = $dateToDelete; $bind[] = $dateToDelete; } $sql = implode(" OR ", $sql); $sqlPeriod = ""; if ($invalidateForPeriod) { $sqlPeriod = " AND period = ? "; $bind[] = $invalidateForPeriod; } $query = "UPDATE {$table} " . " SET value = " . ArchiveWriter::DONE_INVALIDATED . " WHERE ( {$sql} ) " . " AND idsite IN (" . implode(",", $idSites) . ")" . $sqlPeriod; Db::query($query, $bind); } \Piwik\Plugins\SitesManager\API::getInstance()->updateSiteCreatedTime($idSites, $minDate); // Force to re-process data for these websites in the next cron core:archive command run $invalidatedIdSites = self::getWebsiteIdsToInvalidate(); $invalidatedIdSites = array_merge($invalidatedIdSites, $idSites); $invalidatedIdSites = array_unique($invalidatedIdSites); $invalidatedIdSites = array_values($invalidatedIdSites); Option::set(self::OPTION_INVALIDATED_IDSITES, serialize($invalidatedIdSites)); Site::clearCache(); $output = array(); // output logs if ($warningDates) { $output[] = 'Warning: the following Dates have not been invalidated, because they are earlier than your Log Deletion limit: ' . implode(", ", $warningDates) . "\n The last day with logs is " . $minimumDateWithLogs . ". " . "\n Please disable 'Delete old Logs' or set it to a higher deletion threshold (eg. 180 days or 365 years).'."; } $output[] = "Success. The following dates were invalidated successfully: " . implode(", ", $processedDates); return $output; }
private static function getToday() { return self::$todayOverride ?: Date::today(); }