diff options
-rw-r--r-- | core/DataTable.php | 3 | ||||
-rw-r--r-- | core/Metrics.php | 13 | ||||
-rw-r--r-- | core/MetricsFormatter.php | 72 | ||||
-rw-r--r-- | core/Nonce.php | 44 | ||||
-rw-r--r-- | core/Option.php | 69 | ||||
-rw-r--r-- | core/Period.php | 140 |
6 files changed, 214 insertions, 127 deletions
diff --git a/core/DataTable.php b/core/DataTable.php index 211b1837f5..998950bd40 100644 --- a/core/DataTable.php +++ b/core/DataTable.php @@ -44,7 +44,8 @@ require_once PIWIK_INCLUDE_PATH . '/core/Common.php'; * regarding all the data, such as the site or period that the data is for. _Row metadata_ * is information regarding that row, such as a browser logo or website URL. * - * Finally, DataTables all contain a special _summary_ row. + * Finally, DataTables all contain a special _summary_ row. This row, if it exists, is + * always at the end of the DataTable. * * ### Populating DataTables * diff --git a/core/Metrics.php b/core/Metrics.php index d7a6c07cac..3a936f35fc 100644 --- a/core/Metrics.php +++ b/core/Metrics.php @@ -14,13 +14,18 @@ namespace Piwik; require_once PIWIK_INCLUDE_PATH . "/core/Piwik.php"; /** - * This class holds the various mappings we use to internally store and manipulate metrics. + * This class contains metadata regarding core metrics and contains several + * related helper functions. + * + * Of note are the `INDEX_...` constants. In the database, metric column names + * are stored in DataTable rows are stored as integers to save space. The integer + * values used are determined by these constants. * * @api */ class Metrics { - /** + /* * When saving DataTables in the DB, we replace all columns name with these IDs. This saves many bytes, * eg. INDEX_NB_UNIQ_VISITORS is an integer: 4 bytes, but 'nb_uniq_visitors' is 16 bytes at least */ @@ -75,6 +80,7 @@ class Metrics const INDEX_GOAL_ECOMMERCE_REVENUE_SHIPPING = 6; const INDEX_GOAL_ECOMMERCE_REVENUE_DISCOUNT = 7; const INDEX_GOAL_ECOMMERCE_ITEMS = 8; + static public $mappingFromIdToName = array( Metrics::INDEX_NB_UNIQ_VISITORS => 'nb_uniq_visitors', Metrics::INDEX_NB_VISITS => 'nb_visits', @@ -115,6 +121,7 @@ class Metrics Metrics::INDEX_ECOMMERCE_ITEM_PRICE_VIEWED => 'price_viewed', Metrics::INDEX_ECOMMERCE_ORDERS => 'orders', ); + static public $mappingFromIdToNameGoal = array( Metrics::INDEX_GOAL_NB_CONVERSIONS => 'nb_conversions', Metrics::INDEX_GOAL_NB_VISITS_CONVERTED => 'nb_visits_converted', @@ -125,6 +132,7 @@ class Metrics Metrics::INDEX_GOAL_ECOMMERCE_REVENUE_DISCOUNT => 'revenue_discount', Metrics::INDEX_GOAL_ECOMMERCE_ITEMS => 'items', ); + static public $mappingFromNameToId = array( 'nb_uniq_visitors' => Metrics::INDEX_NB_UNIQ_VISITORS, 'nb_visits' => Metrics::INDEX_NB_VISITS, @@ -138,6 +146,7 @@ class Metrics 'goals' => Metrics::INDEX_GOALS, 'sum_daily_nb_uniq_visitors' => Metrics::INDEX_SUM_DAILY_NB_UNIQ_VISITORS, ); + static protected $metricsAggregatedFromLogs = array( Metrics::INDEX_NB_UNIQ_VISITORS, Metrics::INDEX_NB_VISITS, diff --git a/core/MetricsFormatter.php b/core/MetricsFormatter.php index 29c2e71c49..61f1926c06 100644 --- a/core/MetricsFormatter.php +++ b/core/MetricsFormatter.php @@ -13,15 +13,15 @@ namespace Piwik; use Piwik\Tracker\GoalManager; /** - * Class MetricsFormatter + * Contains helper function that format numerical values in different ways. + * * @package Piwik - * * @api */ class MetricsFormatter { /** - * Gets a prettified string representation of a number. The result will have + * Returns a prettified string representation of a number. The result will have * thousands separators and a decimal point specific to the current locale. * * @param number $value @@ -29,21 +29,26 @@ class MetricsFormatter */ public static function getPrettyNumber($value) { - $locale = localeconv(); + static $decimalPoint = null; + static $thousandsSeparator = null; + + if ($decimalPoint === null) { + $locale = localeconv(); - $decimalPoint = $locale['decimal_point']; - $thousandsSeparator = $locale['thousands_sep']; + $decimalPoint = $locale['decimal_point']; + $thousandsSeparator = $locale['thousands_sep']; + } return number_format($value, 0, $decimalPoint, $thousandsSeparator); } /** - * Pretty format a time + * Returns a prettified time value (in seconds). * - * @param int $numberOfSeconds - * @param bool $displayTimeAsSentence If set to true, will output "5min 17s", if false "00:05:17" - * @param bool $isHtml - * @param bool $round to the full seconds + * @param int $numberOfSeconds The number of seconds. + * @param bool $displayTimeAsSentence If set to true, will output `"5min 17s"`, if false `"00:05:17"`. + * @param bool $isHtml If true, replaces all spaces with `' '`. + * @param bool $round Whether to round to the nearest second or not. * @return string */ public static function getPrettyTimeFromSeconds($numberOfSeconds, $displayTimeAsSentence = true, $isHtml = true, $round = false) @@ -95,12 +100,12 @@ class MetricsFormatter } /** - * Pretty format a memory size value + * Returns a prettified memory size value. * - * @param number $size size in bytes + * @param number $size The size in bytes. * @param string $unit The specific unit to use, if any. If null, the unit is determined by $size. * @param int $precision The precision to use when rounding. - * @return string + * @return string eg, `'128 M'` or `'256 K'`. */ public static function getPrettySizeFromBytes($size, $unit = null, $precision = 1) { @@ -120,19 +125,19 @@ class MetricsFormatter } /** - * Pretty format monetary value for a site + * Returns a pretty formated monetary value using the currency associated with a site. * - * @param int|string $value - * @param int $idSite - * @param bool $htmlAllowed + * @param int|string $value The monetary value to format. + * @param int $idSite The ID of the site whose currency will be used. + * @param bool $isHtml If true, replaces all spaces with `' '`. * @return string */ - public static function getPrettyMoney($value, $idSite, $htmlAllowed = true) + public static function getPrettyMoney($value, $idSite, $isHtml = true) { $currencyBefore = MetricsFormatter::getCurrencySymbol($idSite); $space = ' '; - if ($htmlAllowed) { + if ($isHtml) { $space = ' '; } @@ -160,14 +165,15 @@ class MetricsFormatter } /** - * For the given value, based on the column name, will apply: pretty time, pretty money - * @param int $idSite - * @param string $columnName - * @param mixed $value - * @param bool $htmlAllowed + * Prettifies a metric value based on the column name. + * + * @param int $idSite The ID of the site the metric is for (used if the column value is an amount of money). + * @param string $columnName The metric name. + * @param mixed $value The metric value. + * @param bool $isHtml If true, replaces all spaces with `' '`. * @return string */ - public static function getPrettyValue($idSite, $columnName, $value, $htmlAllowed) + public static function getPrettyValue($idSite, $columnName, $value, $isHtml) { // Display time in human readable if (strpos($columnName, 'time') !== false) { @@ -177,7 +183,7 @@ class MetricsFormatter } // Add revenue symbol to revenues if (strpos($columnName, 'revenue') !== false && strpos($columnName, 'evolution') === false) { - return self::getPrettyMoney($value, $idSite, $htmlAllowed); + return self::getPrettyMoney($value, $idSite, $isHtml); } // Add % symbol to rates if (strpos($columnName, '_rate') !== false) { @@ -189,10 +195,10 @@ class MetricsFormatter } /** - * Get currency symbol for a site + * Returns the currency symbol for a site. * - * @param int $idSite - * @return string + * @param int $idSite The ID of the site to return the currency symbol for. + * @return string eg, `'$'`. */ public static function getCurrencySymbol($idSite) { @@ -202,14 +208,14 @@ class MetricsFormatter if (isset($symbols[$currency])) { return $symbols[$currency][0]; } - return ''; } /** - * Returns a list of currency symbols + * Returns the list of all known currency symbols. * - * @return array array( currencyCode => symbol, ... ) + * @return array An array mapping currency codes to their respective currency symbols + * and a description, eg, `array('USD' => array('$', 'US dollar'))`. */ public static function getCurrencyList() { diff --git a/core/Nonce.php b/core/Nonce.php index 0f526fb328..f9a5fe4f5e 100644 --- a/core/Nonce.php +++ b/core/Nonce.php @@ -15,25 +15,26 @@ use Piwik\Session\SessionNamespace; /** * Nonce class. * - * A cryptographic nonce -- "number used only once" -- is often recommended as part of a robust defense against cross-site request forgery (CSRF/XSRF). - * Desrable characteristics: limited lifetime, uniqueness, unpredictability (pseudo-randomness). - * - * We use a session-dependent nonce with a configurable expiration that combines and hashes: - * - a private salt because it's non-public - * - time() because it's unique - * - a mix of PRNGs (pseudo-random number generators) to increase entropy and make it less predictable + * A cryptographic nonce -- "number used only once" -- is often recommended as + * part of a robust defense against cross-site request forgery (CSRF/XSRF). This + * class provides static methods that create and manage nonce values. + * + * Nonces in Piwik are stored as a session variable and have a configurable expiration: * + * Learn more about nonces [here](http://en.wikipedia.org/wiki/Cryptographic_nonce). + * * @package Piwik * @api */ class Nonce { /** - * Generate nonce + * Returns the existing nonce. If none exists, a new nonce will be generated. * - * @param string $id Unique id to avoid namespace conflicts, e.g., ModuleName.ActionName - * @param int $ttl Optional time-to-live in seconds; default is 5 minutes - * @return string Nonce + * @param string $id Unique id to avoid namespace conflicts, e.g., `'ModuleName.ActionName'`. + * @param int $ttl Optional time-to-live in seconds; default is 5 minutes. (ie, in 5 minutes, + * the nonce will no longer be valid). + * @return string */ static public function getNonce($id, $ttl = 300) { @@ -54,7 +55,13 @@ class Nonce } /** - * Verify nonce and check referrer (if present, i.e., it may be suppressed by the browser or a proxy/network). + * Returns if a nonce is valid and comes from a valid request. + * + * A nonce is valid if it matches the current nonce and if the current nonce + * has not expired. + * + * The request is valid if the referrer is a local URL (see [Url::isLocalUrl](#)) + * and if the HTTP origin is valid (see [getAcceptableOrigins](#getAcceptableOrigins)). * * @param string $id Unique id * @param string $cnonce Nonce sent to client @@ -89,9 +96,9 @@ class Nonce } /** - * Discard nonce ("now" as opposed to waiting for garbage collection) + * Force expiration of the current nonce. * - * @param string $id Unique id + * @param string $id The unique nonce ID. */ static public function discardNonce($id) { @@ -100,8 +107,8 @@ class Nonce } /** - * Get ORIGIN header, false if not found - * + * Returns Origin HTTP header or false if not found. + * * @return string|bool */ static public function getOrigin() @@ -113,8 +120,7 @@ class Nonce } /** - * Returns acceptable origins (not simply scheme://host) that - * should handle a variety of proxy and web server (mis)configurations,. + * Returns a list acceptable values for the HTTP Origin header. * * @return array */ @@ -145,4 +151,4 @@ class Nonce return $origins; } -} +}
\ No newline at end of file diff --git a/core/Option.php b/core/Option.php index b86f572c02..8c90022f99 100644 --- a/core/Option.php +++ b/core/Option.php @@ -11,20 +11,38 @@ namespace Piwik; /** - * Option provides a very simple mechanism to save/retrieve key-values pair - * from the database (persistent key-value datastore). - * - * This is useful to save Piwik-wide preferences, configuration values. + * Convenient key-value storage for user specified options and temporary + * data that needs to be persisted beyond one request. + * + * ### Examples + * + * **Setting and getting options** + * + * $optionValue = Option::get('MyPlugin.MyOptionName'); + * if ($optionValue === false) { + * // if not set, set it + * Option::set('MyPlugin.MyOptionName', 'my option value'); + * } + * + * **Storing user specific options** + * + * $userName = // ... + * Option::set('MyPlugin.MyOptionName.' . $userName, 'my option value'); + * + * **Clearing user specific options** + * + * Option::deleteLike('MyPlugin.MyOptionName.%'); * * @package Piwik + * @api */ class Option { /** - * Returns the option value for the requested option $name, fetching from database, if not in cache. - * - * @param string $name Key - * @return string|bool Value or false, if not found + * Returns the option value for the requested option `$name`. + * + * @param string $name The option name. + * @return string|bool The value or false, if not found. */ public static function get($name) { @@ -32,11 +50,12 @@ class Option } /** - * Sets the option value in the database and cache + * Sets an option value by name. * - * @param string $name - * @param string $value - * @param int $autoLoad if set to 1, this option value will be automatically loaded; should be set to 1 for options that will always be used in the Piwik request. + * @param string $name The option name. + * @param string $value The value to set the option to. + * @param int $autoLoad If set to 1, this option value will be automatically loaded when Piwik is initialzed; + * should be set to 1 for options that will be used in every Piwik request. */ public static function set($name, $value, $autoload = 0) { @@ -44,10 +63,10 @@ class Option } /** - * Delete key-value pair from database and reload cache. + * Deletes an option. * - * @param string $name Key to match exactly - * @param string $value Optional value + * @param string $name Option name to match exactly. + * @param string $value If supplied the option will be deleted only if its value matches this value. */ public static function delete($name, $value = null) { @@ -55,22 +74,23 @@ class Option } /** - * Delete key-value pair(s) from database and reload cache. - * The supplied pattern should use '%' as wildcards, and literal '_' should be escaped. + * Deletes all options that match the supplied pattern. * - * @param string $name Pattern of key to match. - * @param string $value Optional value + * @param string $namePattern Pattern of key to match. `'%'` characters should be used as wildcards, and literal + * `'_'` characters should be escaped. + * @param string $value If supplied options will be deleted only if their value matches this value. */ - public static function deleteLike($name, $value = null) + public static function deleteLike($namePattern, $value = null) { - return self::getInstance()->deleteNameLike($name, $value); + return self::getInstance()->deleteNameLike($namePattern, $value); } /** - * Clears the cache - * Used in unit tests to reset the state of the object between tests + * Clears the option value cache and forces a reload from the Database. + * Used in unit tests to reset the state of the object between tests. * * @return void + * @ignore */ public static function clearCache() { @@ -191,5 +211,4 @@ class Option $this->loaded = true; } - -} +}
\ No newline at end of file diff --git a/core/Period.php b/core/Period.php index 4848086a04..f56d7df24e 100644 --- a/core/Period.php +++ b/core/Period.php @@ -11,6 +11,7 @@ namespace Piwik; use Exception; +use Piwik\Date; use Piwik\Period\Day; use Piwik\Period\Month; use Piwik\Period\Range; @@ -18,8 +19,30 @@ use Piwik\Period\Week; use Piwik\Period\Year; /** + * Date range representation. + * + * Piwik allows users to view aggregated statistics for each day and for date + * ranges consisting of several days. When requesting data, a _date_ string and + * a _period_ string must be used to specify the date range to view statistics + * for. This is the class that Piwik uses to represent and manipulate those + * date ranges. + * + * There are five types of periods in Piwik: day, week, month, year and range, + * where **range** is any date range. The reason the other periods exist instead + * of just **range** is that Piwik will archive for days, weeks, months and years + * periodically, while every other date range is archived on-demand. + * + * ### Examples + * + * **Building a period from 'date' and 'period' query parameters** + * + * $date = Common::getRequestVar('date', null, 'string'); + * $period = Common::getRequestVar('period', null, 'string'); + * $periodObject = Period::advancedFactory($period, $date); + * * @package Piwik * @subpackage Period + * @api */ abstract class Period { @@ -39,22 +62,25 @@ abstract class Period * @var Date */ protected $date = null; - static protected $errorAvailablePeriods = 'day, week, month, year, range'; /** - * Constructor + * Constructor. + * * @param Date $date */ - public function __construct($date) + public function __construct(Date $date) { - $this->checkInputDate($date); $this->date = clone $date; } /** - * @param string $strPeriod "day", "week", "month", "year" - * @param Date $date Date object - * @throws Exception + * Creates a new Period instance with a period ID and Date instance. + * + * Note: This method cannot create Range periods. + * + * @param string $strPeriod `"day"`, `"week"`, `"month"`, `"year"` + * @param Date $date A date within the period. + * @throws Exception If `$strPeriod` is invalid. * @return \Piwik\Period */ static public function factory($strPeriod, Date $date) @@ -77,23 +103,24 @@ abstract class Period break; default: - throw new Exception(Piwik::translateException('General_ExceptionInvalidPeriod', array($strPeriod, self::$errorAvailablePeriods))); + $message = Piwik::translateException( + 'General_ExceptionInvalidPeriod', array($strPeriod, 'day, week, month, year, range')); + throw new Exception($message); break; } } /** - * Indicate if $dateString and $period correspond to multiple periods + * Returns true $dateString and $period correspond to multiple periods. * * @static - * @param $dateString - * @param $period + * @param $dateString The `'date'` query parameter value. + * @param $period The `'period'` query parameter value. * @return boolean */ public static function isMultiplePeriod($dateString, $period) { - return - is_string($dateString) + return is_string($dateString) && (preg_match('/^(last|previous){1}([0-9]*)$/D', $dateString, $regs) || Range::parseDateRange($dateString)) && $period != 'range'; @@ -106,11 +133,11 @@ abstract class Period * and range to the API methods can directly be forwarded to this factory * method in order to get a suitable instance of Period. * - * @param string $strPeriod "day", "week", "month", "year", "range" - * @param string $strDate + * @param string $strPeriod `"day"`, `"week"`, `"month"`, `"year"`, `"range"` + * @param string $strDate The `'date'` query parameter value. * @return \Piwik\Period */ - static public function advancedFactory($strPeriod, $strDate) + public static function advancedFactory($strPeriod, $strDate) { if (Period::isMultiplePeriod($strDate, $strPeriod) || $strPeriod == 'range') { return new Range($strPeriod, $strDate); @@ -124,7 +151,8 @@ abstract class Period * * @param string $timezone * @param string $period The period string: day, week, month, year, range - * @param string $date The date or date range string. + * @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) @@ -150,9 +178,9 @@ abstract class Period } /** - * Returns the first day of the period + * Returns the first day of the period. * - * @return Date First day of the period + * @return Date */ public function getDateStart() { @@ -173,9 +201,9 @@ abstract class Period } /** - * Returns the last day of the period ; can be a date in the future + * Returns the last day of the period. * - * @return Date Last day of the period + * @return Date */ public function getDateEnd() { @@ -195,14 +223,20 @@ abstract class Period return $currentPeriod->getDate(); } + /** + * Returns the period ID. + * + * @return int A integer unique to this type of period. + */ public function getId() { return Piwik::$idPeriods[$this->getLabel()]; } /** - * Returns the label for the current period - * @return string + * Returns the label for the current period. + * + * @return string `"day"`, `"week"`, `"month"`, `"year"`, `"range"` */ public function getLabel() { @@ -217,27 +251,14 @@ abstract class Period return $this->date; } - /** - * Checks if the given date is an instance of Date - * - * @param Date $date - * - * @throws Exception - */ - protected function checkInputDate($date) - { - if (!($date instanceof Date)) { - throw new Exception("The date must be a Date object. " . var_export($date, true)); - } - } - protected function generate() { $this->subperiodsProcessed = true; } /** - * Returns the number of available subperiods + * Returns the number of available subperiods. + * * @return int */ public function getNumberOfSubperiods() @@ -249,9 +270,9 @@ abstract class Period } /** - * Returns Period_Day for a period made of days (week, month), - * Period_Month for a period made of months (year) - * + * Returns the set of Period instances that together make up this period. For a year, + * this would be 12 months. For a month this would be 28-31 days. Etc. + * * @return Period[] */ public function getSubperiods() @@ -275,12 +296,10 @@ abstract class Period } /** - * Returns a string representing the current period - * Given param will be used to format the returned value + * Returns a list of strings representing the current period. * - * @param string $format - * - * @return array + * @param string $format The format of each individual day. + * @return array An array of string dates that this period consists of. */ public function toString($format = "Y-m-d") { @@ -294,6 +313,11 @@ abstract class Period return $dateString; } + /** + * See [toString](#toString). + * + * @return string + */ public function __toString() { return implode(",", $this->toString()); @@ -307,14 +331,36 @@ abstract class Period return $this->date->toString($part); } + /** + * Returns a pretty string describing this period. + * + * @return string + */ abstract public function getPrettyString(); + /** + * Returns a short string description of this period that is localized with the currently used + * language. + * + * @return string + */ abstract public function getLocalizedShortString(); + /** + * Returns a long string description of this period that is localized with the currently used + * language. + * + * @return string + */ abstract public function getLocalizedLongString(); + /** + * Returns a succinct string describing this period. + * + * @return string eg, `'2012-01-01,2012-01-31'`. + */ public function getRangeString() { return $this->getDateStart()->toString("Y-m-d") . "," . $this->getDateEnd()->toString("Y-m-d"); } -} +}
\ No newline at end of file |