diff options
author | matt <matt@59fd770c-687e-43c8-a1e3-f5a4ff64c105> | 2008-03-28 03:33:02 +0300 |
---|---|---|
committer | matt <matt@59fd770c-687e-43c8-a1e3-f5a4ff64c105> | 2008-03-28 03:33:02 +0300 |
commit | aeadb6f6b5accaa19dee96ed68cc0d3f4ad1fdcc (patch) | |
tree | e75aa5ef2580cce4e711a7730431eb2272e40c19 | |
parent | 5f01e995b241d489167563d4582a205a0e0910f1 (diff) |
- refs #33 work in progress
27 files changed, 1039 insertions, 426 deletions
@@ -59,5 +59,4 @@ Piwik_FrontController::$enableDispatch = ENABLE_DISPATCH; $controller = Piwik_FrontController::getInstance(); $controller->init();
-$controller->dispatch();
-$controller->end(); +$controller->dispatch(); diff --git a/modules/Access.php b/modules/Access.php index f8d268aa2f..bf761b1d1c 100755 --- a/modules/Access.php +++ b/modules/Access.php @@ -13,7 +13,10 @@ require_once 'SitesManager/API.php'; /** - * Class to handle User Access. + * Class to handle User Access: + * - loads user access from the DB + * - make it easy to check that the current user has specific permissions (see check* methods) + * * In Piwik there are mainly 4 access levels * - no access * - VIEW access @@ -36,16 +39,42 @@ require_once 'SitesManager/API.php'; class Piwik_Access { - private $accesssByIdsite = null; - private $idsitesByAccess = null; - private $identity = null; //login - private $isSuperUser = false; - - public function isSuperUser() - { - return $this->isSuperUser; - } + /** + * Array of pairs (idsite => accessLevel) for each site available to this user + * + * @var array + */ + protected $accessByIdsite = null; + + /** + * Array of idsites available to the current user, indexed by permission level + * @see getSitesIdWith*() + * + * @var array + */ + protected $idsitesByAccess = null; + + /** + * Login of the current user + * + * @var string + */ + protected $identity = null; + + /** + * Defines if the current user is the super user + * @see isSuperUser() + * + * @var bool + */ + protected $isSuperUser = false; + + /** + * List of available permissions in Piwik + * + * @var array + */ static private $availableAccess = array('noaccess', 'view', 'admin', 'superuser'); /** @@ -61,18 +90,19 @@ class Piwik_Access /** * @param Piwik_Auth The authentification object */ - public function __construct( $auth ) + public function __construct( Piwik_Auth $auth ) { $this->auth = $auth; } /** - * Load the access levels for the current user. + * Loads the access levels for the current user. * - * First call the authentication method to try to log the user in the system. + * Calls the authentication method to try to log the user in the system. * If the user credentials are not correct we don't load anything. * If the login/password is correct the user is either the SuperUser or a normal user. * We load the access levels for this user for all the websites. + * */ public function loadAccess() { @@ -120,9 +150,19 @@ class Piwik_Access $this->accessByIdsite = $accessByIdsite; $this->idsitesByAccess = $idsitesByAccess; } - + + /** + * Returns true if the current user is logged in as the super user + * + * @return bool + */ + public function isSuperUser() + { + return $this->isSuperUser; + } + /** - * Returns the user login + * Returns the current user login * @return string */ public function getIdentity() @@ -173,7 +213,8 @@ class Piwik_Access } /** - * Throws an exception if the user is not the SuperUser + * Throws an exception if the user is not the SuperUser + * * @throws Exception */ public function checkUserIsSuperUser() @@ -186,6 +227,7 @@ class Piwik_Access /** * If the user doesn't have an ADMIN access for at least one website, throws an exception + * * @throws Exception */ public function checkUserHasSomeAdminAccess() @@ -200,6 +242,7 @@ class Piwik_Access /** * This method checks that the user has ADMIN access for the given list of websites. * If the user doesn't have ADMIN access for at least one website of the list, we throw an exception. + * * @param int|arrayOfIntegers List of ID sites to check * @throws Exception If for any of the websites the user doesn't have an ADMIN access */ @@ -223,6 +266,7 @@ class Piwik_Access /** * This method checks that the user has VIEW or ADMIN access for the given list of websites. * If the user doesn't have VIEW or ADMIN access for at least one website of the list, we throw an exception. + * * @param int|arrayOfIntegers List of ID sites to check * @throws Exception If for any of the websites the user doesn't have an VIEW or ADMIN access */ @@ -246,6 +290,8 @@ class Piwik_Access /** * + * Exception thrown when a user doesn't have sufficient access. + * * @package Piwik */ class Piwik_Access_NoAccessException extends Exception diff --git a/modules/Archive.php b/modules/Archive.php index 7845dfbc0a..a6227640b0 100644 --- a/modules/Archive.php +++ b/modules/Archive.php @@ -16,25 +16,36 @@ require_once 'ArchiveProcessing.php'; require_once 'Archive/Single.php'; /** - * Architecture - * - *ArchiveProcessing* entity : handle all the computation on an archive / create & delete archive - * - *Archive* entity: - * contains the information on an archive, - * uses the ArchiveProcessing if necessary - * small overhead so we can instanciate many objects of this class for example one for each day - * of the month - * - *Website* entity: getId, getUrls, getFirstDay, etc. - * + *Period* entity: composed of *Date* objects - * + *Table* entity: serialize, unserialize, sort elements, limit number of elements - * contains all the logic, data structure, etc. - * receives data directly from the sql query via a known API - * - The *ArchiveProcessing* saves in the DB *numbers* or *Table* objects - * + * The archive object is used to query specific data for a day or a period of statistics for a given website. + * + * Example: + * <pre> + * $archive = Piwik_Archive::build($idSite = 1, $period = 'week', '2008-03-08' ); + * $dataTable = $archive->getDataTable('Provider_hostnameExt'); + * $dataTable->queueFilter('Piwik_DataTable_Filter_ReplaceColumnNames'); + * return $dataTable; + * </pre> + * + * Example bis: + * <pre> + * $archive = Piwik_Archive::build($idSite = 3, $period = 'day', $date = 'today' ); + * $nbVisits = $archive->getNumeric('nb_visits'); + * return $nbVisits; + * </pre> + * + * If the requested statistics are not yet processed, Archive uses ArchiveProcessing to archive the statistics. + * * @package Piwik + * @subpackage Piwik_Archive */ - abstract class Piwik_Archive { + /** + * When saving DataTables in the DB, we sometimes replace the columns name by these IDs so we save up lots of bytes + * Eg. INDEX_NB_UNIQ_VISITORS is an integer: 4 bytes, but 'nb_uniq_visitors' is 16 bytes at least + * (in php it's actually even much more) + * + */ const INDEX_NB_UNIQ_VISITORS = 1; const INDEX_NB_VISITS = 2; const INDEX_NB_ACTIONS = 3; @@ -42,23 +53,35 @@ abstract class Piwik_Archive const INDEX_SUM_VISIT_LENGTH = 5; const INDEX_BOUNCE_COUNT = 6; - protected $alreadyChecked = false; + /** + * Website Piwik_Site + * + * @var Piwik_Site + */ protected $site = null; - + + /** + * Stores the already built archives. + * Act as a big caching array + * + * @var array of Piwik_Archive + */ static protected $alreadyBuilt = array(); /** * Builds an Archive object or returns the same archive if previously built. * * @param int $idSite - * @param string|Piwik_Date $date 'YYYY-MM-DD' or magic keywords 'today' See Piwik_Date::factory + * @param string|Piwik_Date $date 'YYYY-MM-DD' or magic keywords 'today' @see Piwik_Date::factory() * @param string $period 'week' 'day' etc. + * * @return Piwik_Archive */ static public function build($idSite, $period, $strDate ) { $oSite = new Piwik_Site($idSite); - + + // if a period date string is detected: either 'last30', 'previous10' or 'YYYY-MM-DD,YYYY-MM-DD' if(is_string($strDate) && ( ereg('^(last|previous){1}([0-9]*)$', $strDate, $regs) @@ -69,6 +92,7 @@ abstract class Piwik_Archive require_once 'Archive/Array.php'; $archive = new Piwik_Archive_Array($oSite, $period, $strDate); } + // case we request a single archive else { if(is_string($strDate)) @@ -161,7 +185,7 @@ abstract class Piwik_Archive abstract public function getDataTableExpanded($name, $idSubTable = null); /** - * Set the site + * Sets the site * * @param Piwik_Site $site */ @@ -171,7 +195,7 @@ abstract class Piwik_Archive } /** - * Get the site + * Gets the site * * @param Piwik_Site $site */ diff --git a/modules/Archive/Array.php b/modules/Archive/Array.php index e9965c4ad7..a7a34df565 100644 --- a/modules/Archive/Array.php +++ b/modules/Archive/Array.php @@ -19,13 +19,25 @@ require_once "DataTable/Array.php"; */ class Piwik_Archive_Array extends Piwik_Archive { - // this array contains one Piwik_Archive per entry in the period + /** + * This array contains one Piwik_Archive per entry in the period + * + * @var array + */ protected $archives = array(); - // stores the timestamp of each archive, used to sort the archives by date + /** + * Stores the timestamp of each archive, this is used for sorting the archives by date + * + * @var array pairs(id,timestamp) + */ protected $idArchiveToTimestamp = array(); - // array containing the id of the archives stored in this object + /** + * Array containing the id of the archives stored in this object + * + * @var array + */ protected $idArchives = array(); /** diff --git a/modules/Archive/Single.php b/modules/Archive/Single.php index d91704351e..8cccacc6bc 100644 --- a/modules/Archive/Single.php +++ b/modules/Archive/Single.php @@ -11,7 +11,8 @@ */ /** - * This class is used to store the data of a given archive. + * This class is used to store the data of a single archive, + * for example the statistics for the 'day' '2008-02-21' for the website idSite '2' * */ class Piwik_Archive_Single extends Piwik_Archive @@ -51,7 +52,7 @@ class Piwik_Archive_Single extends Piwik_Archive */ protected $numericCached = array(); -/** + /** * Array of cached blob, used to make requests faster when requesting the same blob again and again * * @var array of mixed @@ -66,6 +67,13 @@ class Piwik_Archive_Single extends Piwik_Archive protected $idArchive = null; /** + * Flag set to true once the archive has been checked (when we make sure it is archived) + * + * @var bool + */ + protected $alreadyChecked = false; + + /** * Returns the pretty date of this Archive, eg. 'Thursday 20th March 2008' * * @return string diff --git a/modules/ArchiveProcessing.php b/modules/ArchiveProcessing.php index f131f00554..402b99b43f 100644 --- a/modules/ArchiveProcessing.php +++ b/modules/ArchiveProcessing.php @@ -11,11 +11,14 @@ require_once 'TablePartitioning.php';
require_once 'ArchiveProcessing/Record.php';
-require_once 'DataTable.php';
+require_once 'DataTable.php'; +
/** * The ArchiveProcessing module is a module that reads the Piwik logs from the DB and * compute all the reports, which are then stored in the database. * + * The ArchiveProcessing class is used by the Archive object to make sure the given Archive is processed and available in the DB. + * * A record in the Database for a given report is defined by * - idarchive = unique ID that is associated to all the data of this archive (idsite+period+date) * - idsite = the ID of the website @@ -31,57 +34,148 @@ require_once 'DataTable.php'; abstract class Piwik_ArchiveProcessing { + /** + * Flag stored at the end of the archiving + * + * @var int + */ const DONE_OK = 1; + + /** + * Flag stored at the start of the archiving + * When requesting an Archive, we make sure that non-finished archive are not considered valid + * + * @var int + */ const DONE_ERROR = 2; - + /** + * Idarchive in the DB for the requested archive + * + * @var int + */ protected $idArchive; - protected $periodId;
+ + /** + * Period id @see Piwik_Period::getId() + * + * @var int + */ + protected $periodId; + + /** + * Timestamp for the first date of the period + * + * @var int unix timestamp + */
protected $timestampDateStart = null;
- /**
+ /** + * Starting date of the archive + *
* @var Piwik_Date
*/ protected $dateStart;
- /**
+ /** + * Ending date of the archive + *
* @var Piwik_Date
*/ protected $dateEnd;
- /**
+ /** + * Object used to generate (depending on the $dateStart) the name of the DB table to use to store numeric values + *
* @var Piwik_TablePartitioning
*/ protected $tableArchiveNumeric;
- /**
+ /** + * Object used to generate (depending on the $dateStart) the name of the DB table to use to store numeric values + *
* @var Piwik_TablePartitioning
*/ protected $tableArchiveBlob;
+ /** + * Maximum timestamp above which a given archive is considered out of date + * + * @var int + */ protected $maxTimestampArchive; - // Attributes that can be accessed by plugins (that is why they are public) + /** + * Id of the current site + * Can be accessed by plugins (that is why it's public) + * + * @var int + */ public $idsite = null;
-
- /**
+ + /** + * Period of the current archive + * Can be accessed by plugins (that is why it's public) + * * @var Piwik_Period
*/ public $period = null;
- /**
+ /** + * Site of the current archive + * Can be accessed by plugins (that is why it's public) + *
* @var Piwik_Site
*/ public $site = null; - // strings + /** + * Starting date @see Piwik_Date::toString() + * + * @var string + */ public $strDateStart; + + /** + * Ending date @see Piwik_Date::toString() + * + * @var string + */ public $strDateEnd; + + /** + * Name of the DB table _log_visit + * + * @var string + */ public $logTable; + + /** + * Name of the DB table _log_link_visit_action + * + * @var string + */ public $logVisitActionTable; + + /** + * Name of the DB table _log_action + * + * @var string + */ public $logActionTable; + /** + * When set to true, we always archive, even if the archive is already available. + * You can change this settings automatically in the config/global.ini.php always_archive_data under the [Debug] section + * + * @var bool + */ protected $debugAlwaysArchive = false; + /** + * Builds the archive processing object, + * Reads some configuration value from the config file + * + */ public function __construct() { $this->debugAlwaysArchive = Zend_Registry::get('config')->Debug->always_archive_data; @@ -119,7 +213,7 @@ abstract class Piwik_ArchiveProcessing }
/** - * Assign helper variables // init the object
+ * Inits the object
*
* @return void */ @@ -167,59 +261,17 @@ abstract class Piwik_ArchiveProcessing { $this->maxTimestampArchive = Piwik_Date::today()->getTimestamp(); } - // $timeStampWhere = " AND (UNIX_TIMESTAMP(ts_archived) > UNIX_TIMESTAMP(CONCAT(date2, ' 23:59:59')) "; } } - /**
- * Returns the name of the numeric table where the archive numeric values are stored
- *
- * @return string
- */ - public function getTableArchiveNumericName() - { - return $this->tableArchiveNumeric->getTableName(); - } -
- /**
- * Returns the name of the blob table where the archive blob values are stored
- *
- * @return string
- */ - public function getTableArchiveBlobName() - { - return $this->tableArchiveBlob->getTableName(); - } - - - /**
- * Set the period
- *
- * @param Piwik_Period $period
- */ - public function setPeriod( Piwik_Period $period ) - { - $this->period = $period; - } - - /**
- * Set the site
- *
- * @param Piwik_Site $site
- */ - public function setSite( Piwik_Site $site ) - { - $this->site = $site; - } -
- /**
- * This method returns the idArchive ; if necessary, it triggers the archiving process.
- *
- * If the archive was not processed yet, it will launch the archiving process.
- * If the current archive needs sub-archives (eg. a month archive needs all the days archive)
- * it will recursively launch the archiving (using this loadArchive() on the sub-periods)
- *
- * @return int The idarchive of the archive
+ /** + * This method returns the idArchive ; if necessary, it triggers the archiving process. + * + * If the archive was not processed yet, it will launch the archiving process. + * If the current archive needs sub-archives (eg. a month archive needs all the days archive) + * it will recursively launch the archiving (using this loadArchive() on the sub-periods) + * + * @return int The idarchive of the archive */ public function loadArchive() { @@ -258,11 +310,11 @@ abstract class Piwik_ArchiveProcessing * and computes the archive of the current period. */ abstract protected function compute(); -
- /**
- * Init the object before launching the real archive processing
- *
- * @return void
+ + /** + * Init the object before launching the real archive processing + * + * @return void */ protected function initCompute() { @@ -276,15 +328,14 @@ abstract class Piwik_ArchiveProcessing $this->logVisitActionTable = Piwik::prefixTable('log_link_visit_action'); $this->logActionTable = Piwik::prefixTable('log_action'); } -
- /**
- * Post processing called at the end of the main archive processing.
- * Makes sure the new archive is marked as "successful" in the DB
- *
- * We also try to delete some stuff from memory but really there is still a lot...
- *
- * @return void
- *
+ + /** + * Post processing called at the end of the main archive processing. + * Makes sure the new archive is marked as "successful" in the DB + * + * We also try to delete some stuff from memory but really there is still a lot... + * + * @return void */ protected function postCompute() { @@ -321,6 +372,62 @@ abstract class Piwik_ArchiveProcessing } /**
+ * Returns the name of the numeric table where the archive numeric values are stored
+ *
+ * @return string
+ */ + public function getTableArchiveNumericName() + { + return $this->tableArchiveNumeric->getTableName(); + } +
+ /**
+ * Returns the name of the blob table where the archive blob values are stored
+ *
+ * @return string
+ */ + public function getTableArchiveBlobName() + { + return $this->tableArchiveBlob->getTableName(); + } + + + /**
+ * Set the period
+ *
+ * @param Piwik_Period $period
+ */ + public function setPeriod( Piwik_Period $period ) + { + $this->period = $period; + } + + /**
+ * Set the site
+ *
+ * @param Piwik_Site $site
+ */ + public function setSite( Piwik_Site $site ) + { + $this->site = $site; + } + + /** + * Returns the timestamp of the first date of the period + * + * @return int + */ + public function getTimestampStartDate() + { + // case when archive processing is in the past or the future, the starting date has not been set or processed yet + if(is_null($this->timestampDateStart)) + { + return Piwik_Date::factory($this->strDateStart)->getTimestamp(); + } + return $this->timestampDateStart; + } + + /**
* Returns the idArchive we will use for the current archive
*
* @return int IdArchive to use when saving the current Archive
@@ -470,15 +577,5 @@ abstract class Piwik_ArchiveProcessing } } - public function getTimestampStartDate() - { - // case when archive processing is in the past or the future, the starting date has not been set or processed yet - if(is_null($this->timestampDateStart)) - { - return Piwik_Date::factory($this->strDateStart)->getTimestamp(); -// throw new Exception("Starting date has not been set"); - } - return $this->timestampDateStart; - } } diff --git a/modules/Auth.php b/modules/Auth.php index a6377ecef8..e84ed8b7b4 100644 --- a/modules/Auth.php +++ b/modules/Auth.php @@ -10,7 +10,11 @@ */
/** - * + * Authentication object. + * Should be reviewed and refactor to allow simple plugin overwrite + * See OpenId authentication plugin, using Zend_Auth_OpenId on http://dev.piwik.org/trac/ticket/160 + * See Review the Login plugin to make it really modular http://dev.piwik.org/trac/ticket/144 + * * @package Piwik */ class Piwik_Auth extends Zend_Auth_Adapter_DbTable diff --git a/modules/Common.php b/modules/Common.php index 6f53a7691a..b726671f1f 100644 --- a/modules/Common.php +++ b/modules/Common.php @@ -10,10 +10,9 @@ */
/** - * Static class providing functions used by both the CORE of Piwik and the - * visitor logging engine. + * Static class providing functions used by both the CORE of Piwik and the visitor logging engine. * - * This is the only external class loaded by the Piwik.php file. + * This is the only external class loaded by the /piwik.php file. * This class should contain only the functions that are used in * both the CORE and the piwik.php statistics logging engine. *
@@ -21,6 +20,10 @@ */ class Piwik_Common { + /** + * Const used to map the referer type to an integer in the log_visit table + * + */ const REFERER_TYPE_DIRECT_ENTRY = 1; const REFERER_TYPE_SEARCH_ENGINE = 2; const REFERER_TYPE_WEBSITE = 3; @@ -28,9 +31,21 @@ class Piwik_Common const REFERER_TYPE_NEWSLETTER = 5; const REFERER_TYPE_CAMPAIGN = 6; + /** + * Flag used with htmlspecialchar + * See php.net/htmlspecialchars + * + */ const HTML_ENCODING_QUOTE_STYLE = ENT_COMPAT; + /** + * Returns the path and query part from a URL. + * Eg. http://piwik.org/test/index.php?module=Home will return /test/index.php?module=Home + * + * @param string $url either http://piwik.org/test or / + * @return string + */ static function getPathAndQueryFromUrl($url) { $parsedUrl = parse_url( $url ); @@ -51,8 +66,80 @@ class Piwik_Common } /** + * Returns the value of a GET parameter $parameter in an URL query $urlQuery + * + * @param string $urlQuery result of parse_url()['query'] and htmlentitied (& is &) eg. module=test&action=toto or ?page=test + * @param string $param + * + * @return string|bool Parameter value if found (can be the empty string!), false if not found + */ + static public function getParameterFromQueryString( $urlQuery, $parameter) + { + $nameToValue = self::getArrayFromQueryString($urlQuery); + + if(isset($nameToValue[$parameter])) + { + return $nameToValue[$parameter]; + } + return false; + } + + /** + * Returns an URL query string in an array format + * The input query string should be htmlspecialchar'ed + * + * @param string urlQuery + * @return array array( param1=> value1, param2=>value2) + */ + static public function getArrayFromQueryString( $urlQuery ) + { + if(strlen($urlQuery) == 0) + { + return array(); + } + if($urlQuery[0] == '?') + { + $urlQuery = substr($urlQuery, 1); + } + + $separator = '&'; + + $urlQuery = $separator . $urlQuery; + // $urlQuery = str_replace(array('%20'), ' ', $urlQuery); + $refererQuery = trim($urlQuery); + + $values = explode($separator, $refererQuery); + + $nameToValue = array(); + + foreach($values as $value) + { + if( false !== strpos($value, '=')) + { + $exploded = explode('=',$value); + $nameToValue[$exploded[0]] = $exploded[1]; + } + } + return $nameToValue; + } + + /** + * Returns true if the string is a valid filename + * File names that start with a-Z or 0-9 and contain a-Z, 0-9, underscore(_), dash(-), and dot(.) will be accepted. + * File names beginning with anything but a-Z or 0-9 will be rejected (including .htaccess for example). + * File names containing anything other than above mentioned will also be rejected (file names with spaces won't be accepted). + * + * @param string filename + * @return bool + * + */ + static public function isValidFilename($filename) + { + return (false !== ereg("(^[a-zA-Z0-9]+([a-zA-Z\_0-9\.-]*))$" , $filename)); + } + /** * Returns true if the string passed may be a URL. - * We don't need a precise test here as the value comes from the website + * We don't need a precise test here because the value comes from the website * tracked source code and the URLs may look very strange. * * @param string $url @@ -232,17 +319,23 @@ class Piwik_Common return $value; } - + /** + * Returns a 32 characters long uniq ID + * + * @return string 32 chars + */ static public function generateUniqId() { return md5(uniqid(rand(), true)); } /** - * + * Returns a 3 letters ID for the operating system part, given a user agent string. + * @see modules/DataFiles/OS.php for the list of OS (also available in $GLOBALS['Piwik_Oslist']) + * If the OS cannot be identified in the user agent, returns 'UNK' + * * @param string $userAgent - * @param array $osList - * + * * @return string */ static public function getOs($userAgent) @@ -262,13 +355,16 @@ class Piwik_Common } /** - * + * Returns the browser information from the user agent string. + * + * @see modules/DataFiles/Browsers.php for the list of OS (also available in $GLOBALS['Piwik_BrowserList']) + * * @param string $userAgent - * @return array array( 'name' => '', - 'major_number' => '', - 'minor_number' => '', - 'version' => '' // major_number.minor_number - ); + * @return array array( 'name' => '', // 2 letters ID or 'UNK' for an unknown browser + * 'major_number' => '', // 2 in firefox 2.0.12 + * 'minor_number' => '', // 0 in firefox 2.0.12 + * 'version' => '' // major_number.minor_number + * ); */ static public function getBrowserInfo($userAgent) { @@ -328,7 +424,7 @@ class Piwik_Common /** - * Returns the best possible IP in the format A.B.C.D + * Returns the best possible IP of the current user, in the format A.B.C.D * * @return string ip */ @@ -390,7 +486,7 @@ class Piwik_Common * * @return string Continent (3 letters code : afr, asi, eur, amn, ams, oce) */ - static function getContinent($country) + static public function getContinent($country) { require_once PIWIK_DATAFILES_INCLUDE_PATH . "/Countries.php"; @@ -407,13 +503,13 @@ class Piwik_Common } /** - * Returns the visitor country based only on the Browser Lang information + * Returns the visitor country based only on the Browser 'accepted language' information * * @param string $lang browser lang * - * @return string + * @return string 2 letters ISO code */ - static function getCountry( $lang ) + static public function getCountry( $lang ) { require_once PIWIK_DATAFILES_INCLUDE_PATH . "/Countries.php"; @@ -512,78 +608,6 @@ class Piwik_Common return 'xx'; } - /** - * Returns the value of a GET parameter $parameter in an URL query $urlQuery - * - * @param string $urlQuery result of parse_url()['query'] and htmlentitied (& is &) - * @param string $param - * - * @return string|bool Parameter value if found (can be the empty string!), false if not found - */ - static public function getParameterFromQueryString( $urlQuery, $parameter) - { - $nameToValue = self::getArrayFromQueryString($urlQuery); - - if(isset($nameToValue[$parameter])) - { - return $nameToValue[$parameter]; - } - return false; - } - - /** - * Returns an URL query string in an array format - * The input query string should be htmlspecialchar - * - * @param string urlQuery - * @return array array( param1=> value1, param2=>value2) - */ - static public function getArrayFromQueryString( $urlQuery ) - { - if(strlen($urlQuery) == 0) - { - return array(); - } - if($urlQuery[0] == '?') - { - $urlQuery = substr($urlQuery, 1); - } - - $separator = '&'; - - $urlQuery = $separator . $urlQuery; - // $urlQuery = str_replace(array('%20'), ' ', $urlQuery); - $refererQuery = trim($urlQuery); - - $values = explode($separator, $refererQuery); - - $nameToValue = array(); - - foreach($values as $value) - { - if( false !== strpos($value, '=')) - { - $exploded = explode('=',$value); - $nameToValue[$exploded[0]] = $exploded[1]; - } - } - return $nameToValue; - } -
- /**
- * Returns true if the string is a valid filename
- * File names that start with a-Z or 0-9 and contain a-Z, 0-9, underscore(_), dash(-), and dot(.) will be accepted.
- * File names beginning with anything but a-Z or 0-9 will be rejected (including .htaccess for example).
- * File names containing anything other than above mentioned will also be rejected (file names with spaces won't be accepted).
- *
- * @param string filename
- * @return bool
- *
- */
- static public function isValidFilename($filename)
- {
- return (false !== ereg("(^[a-zA-Z0-9]+([a-zA-Z\_0-9\.-]*))$" , $filename));
- } } diff --git a/modules/Config.php b/modules/Config.php index a125c90691..5686b62fe0 100755 --- a/modules/Config.php +++ b/modules/Config.php @@ -12,20 +12,28 @@ require_once "Zend/Config/Ini.php"; require_once "Zend/Registry.php";
-/**
- * TODO rewrite__set __get __destruct - * tests: install - * test dashboard has been installed (means config file written dashboard in PluginsInstalled - * test activate/deactivate plugins - * rewrite logic behind saving arrays, very bad at the moment - *
+/** + * This class is used to access configuration files values. + * You can also set these values, the updated configuration files will be written at the end of the script execution. + * + * Example reading a value from the configuration file: + * $minValue = Zend_Registry::get('config')->General->minimumMemoryLimit; + * + * will read the value minimumMemoryLimit under the [General] section of the config file
+ * * @package Piwik_Helper
*/ class Piwik_Config { + /** + * When the user modifies the configuration file and there is one value missing, we suggest the default config file + * + * @var string + */ protected $urlToPiwikHelpMissingValueInConfigurationFile = 'http://dev.piwik.org/trac/browser/trunk/config/global.ini.php?format=raw'; + protected $defaultConfig = null; protected $userConfig = null; protected $pathIniFileUserConfig = null; @@ -33,17 +41,32 @@ class Piwik_Config protected $configFileUpdated = false; public $doWriteFileWhenUpdated = true; - // see http://bugs.php.net/bug.php?id=34206 + /** + * Storing the correct cwd() because the value is not correct in the destructor + * "The working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache)." + * + * @see http://bugs.php.net/bug.php?id=34206 + */ protected $correctCwd; + /** + * Returns default relative path for configuration file + * + * @return string + */ static public function getDefaultUserConfigPath() { return PIWIK_INCLUDE_PATH . '/config/config.ini.php'; } + /** + * Builds the Config object, given the optional path for the user INI file + * If not specified, it will use the default path + * + * @param string $pathIniFileUserConfig + */ function __construct($pathIniFileUserConfig = null) { - Zend_Registry::set('config', $this); $this->pathIniFileDefaultConfig = PIWIK_INCLUDE_PATH . '/config/global.ini.php'; @@ -63,11 +86,15 @@ class Piwik_Config throw new Exception("The configuration file {$this->pathIniFileUserConfig} has not been found."); } $this->userConfig = new Zend_Config_Ini($this->pathIniFileUserConfig, null, true); - $this->setPrefixTables(); // see http://bugs.php.net/bug.php?id=34206 $this->correctCwd = getcwd(); } + + /** + * At the script shutdown, we save the new configuration file, if the user has set some values + * + */ function __destruct() { // saves the config file if changed @@ -123,18 +150,28 @@ class Piwik_Config } } + /** + * If called, we use the "testing" environment, which means using the database_tests and log_tests sections + * for DB & Log configuration. + * + * @return void + * + */ public function setTestEnvironment() { $this->database = $this->database_tests; $this->log = $this->log_tests; - $this->setPrefixTables(); - } - - private function setPrefixTables() - { - Zend_Registry::set('tablesPrefix', $this->database->tables_prefix); } + /** + * Called when setting configuration values eg. + * Zend_Registry::get('config')->superuser = $_SESSION['superuser_infos']; + * + * The values will be saved in the configuration file at the end of the script @see __destruct() + * + * @param string $name + * @param mixed $value + */ public function __set($name, $value) { if(!is_null($this->userConfig)) @@ -151,6 +188,14 @@ class Piwik_Config } } + /** + * Called when getting a configuration value, eg. Zend_Registry::get('config')->superuser->login + * + * @param string $name + * @return mixed value + * + * @throws exception if the value was not found in the configuration file + */ public function __get($name) { if( !is_null($this->userConfig) diff --git a/modules/Controller.php b/modules/Controller.php index aa42cde8d9..d2c6f74805 100644 --- a/modules/Controller.php +++ b/modules/Controller.php @@ -10,11 +10,37 @@ */
/**
+ * Parent class of all plugins Controllers (located in /plugins/PluginName/Controller.php + * It defines some helper functions controllers can use. *
- * @package Piwik_
+ * @package Piwik
*/
abstract class Piwik_Controller { + /** + * Plugin name, eg. Referers + * @var string + */ + protected $pluginName; + + /** + * Date string + * + * @var string + */ + protected $strDate; + + /** + * Piwik_Date object or null if the requested date is a range + * + * @var Piwik_Date|null + */ + protected $date; + + /** + * Builds the controller object, reads the date from the request, extracts plugin name from + * + */ function __construct() { $aPluginName = explode('_', get_class($this)); @@ -32,13 +58,27 @@ abstract class Piwik_Controller } } + /** + * Returns the name of the default method that will be called + * when visiting: index.php?module=PluginName without the action parameter + * + * @return string + */ function getDefaultAction() { return 'index'; } - /* FACTORING // COPIED FROM Home_Controller */ - protected function renderView($view, $fetch) + /** + * Given an Object implementing Piwik_iView interface, we either: + * - echo the output of the rendering if fetch = false + * - returns the output of the rendering if fetch = true + * + * @param Piwik_ViewDataTable $view + * @param bool $fetch + * @return string|void + */ + protected function renderView( Piwik_ViewDataTable $view, $fetch) { $view->main(); $rendered = $view->getView()->render(); @@ -49,6 +89,15 @@ abstract class Piwik_Controller echo $rendered; } + /** + * Returns a ViewDataTable object of an Evolution graph + * for the last30 days/weeks/etc. of the current period, relative to the current date. + * + * @param string $currentModuleName + * @param string $currentControllerAction + * @param string $apiMethod + * @return Piwik_ViewDataTable_Graph_ChartEvolution + */ protected function getLastUnitGraph($currentModuleName, $currentControllerAction, $apiMethod) { require_once "ViewDataTable/Graph.php"; @@ -60,33 +109,24 @@ abstract class Piwik_Controller // see constructor if( !is_null($this->date)) { - $view->setParametersToModify( $this->getGraphParamsModified( array('date'=>$this->strDate))); + $view->setParametersToModify( + $this->getGraphParamsModified( array('date'=>$this->strDate)) + ); } return $view; } - protected function getNumericValue( $methodToCall ) - { - $requestString = 'method='.$methodToCall.'&format=original'; - $request = new Piwik_API_Request($requestString); - return $request->process(); - } - - protected function getUrlSparkline( $action ) - { - $params = $this->getGraphParamsModified( - array( 'viewDataTable' => 'sparkline', - 'action' => $action, - 'module' => $this->pluginName) - ); - $url = Piwik_Url::getCurrentQueryStringWithParametersModified($params); - return $url; - } - - /** + * Returns the array of new processed parameters once the parameters are applied. + * For example: if you set range=last30 and date=2008-03-10, + * the date element of the returned array will be "2008-02-10,2008-03-10" + * + * Parameters you can set: + * - range: last30, previous10, etc. + * - date: YYYY-MM-DD, today, yesterday + * - period: day, week, month, year * * @param array paramsToSet = array( 'date' => 'last50', 'viewDataTable' =>'sparkline' ) */ @@ -130,4 +170,39 @@ abstract class Piwik_Controller return $params; } + /** + * Returns a numeric value from the API. + * Works only for API methods that originally returns numeric values (there is no cast here) + * + * @param string $methodToCall, eg. Referers.getNumberOfDistinctSearchEngines + * @return int|float + */ + protected function getNumericValue( $methodToCall ) + { + $requestString = 'method='.$methodToCall.'&format=original'; + $request = new Piwik_API_Request($requestString); + return $request->process(); + } + + /** + * Returns the current URL to use in a <img src=X> to display a sparkline. + * $action must be the name of a Controller method that requests data using the Piwik_ViewDataTable::factory + * It will automatically build a sparkline by setting the viewDataTable=sparkline parameter in the URL. + * It will also computes automatically the 'date' for the 'last30' days/weeks/etc. + * + * @param string $action, eg. method name of the controller to call in the img src + * @return string the generated URL + */ + protected function getUrlSparkline( $action ) + { + $params = $this->getGraphParamsModified( + array( 'viewDataTable' => 'sparkline', + 'action' => $action, + 'module' => $this->pluginName) + ); + $url = Piwik_Url::getCurrentQueryStringWithParametersModified($params); + return $url; + } + + }
\ No newline at end of file diff --git a/modules/Cookie.php b/modules/Cookie.php index b5cdcbed4e..9ba2e46d1b 100644 --- a/modules/Cookie.php +++ b/modules/Cookie.php @@ -11,14 +11,10 @@ /** - * Simple class to handle the cookies. - * Its features are: - * + * Simple class to handle the cookies: * - read a cookie values * - edit an existing cookie and save it * - create a new cookie, set values, expiration date, etc. and save it - * - * The cookie content is saved in an optimized way. *
* @package Piwik_Helper */ @@ -117,6 +113,8 @@ class Piwik_Cookie /** * We set the privacy policy header + * + * @return void */ protected function setP3PHeader() { @@ -125,6 +123,8 @@ class Piwik_Cookie /** * Delete the cookie + * + * @return void */ public function delete() { @@ -148,6 +148,8 @@ class Piwik_Cookie * Parses the cookie string to extract the different variables. * Unserialize the array when necessary. * Decode the non numeric values that were base64 encoded. + * + * @return void */ protected function loadContentFromCookie() { @@ -181,8 +183,8 @@ class Piwik_Cookie /** * Returns the string to save in the cookie from the $this->value array of values. - * It goes through the array and generate the cookie content string. - * @return string Cookie string + * It goes through the array and generates the cookie content string. + * @return string Cookie content */ protected function generateContentString() { diff --git a/modules/DataTable.php b/modules/DataTable.php index fe846dc022..7321bfd3b8 100644 --- a/modules/DataTable.php +++ b/modules/DataTable.php @@ -130,11 +130,47 @@ require_once "DataTable/Manager.php"; class Piwik_DataTable { + /** + * Array of Piwik_DataTable_Row + * + * @var array + */ protected $rows = array(); + + /** + * Id assigned to the DataTable, used to lookup the table using the DataTable_Manager + * + * @var int + */ protected $currentId; + + /** + * Current depth level of this data table + * 0 is the parent data table + * + * @var int + */ protected $depthLevel = 0; + + /** + * This flag is set to false once we modify the table in a way that outdates the index + * + * @var bool + */ protected $indexNotUpToDate = false; + + /** + * List of Piwik_DataTable_Filter queued to this table + * + * @var array + */ protected $queuedFilters = array(); + + /** + * We keep track of the number of rows before applying the LIMIT filter that deletes some rows + * + * @var int + */ protected $rowsCountBeforeLimitFilter = 0; /** @@ -144,13 +180,27 @@ class Piwik_DataTable */ protected $enableRecursiveSort = false; + /** + * Maximum nesting level + * + * @var int + */ const MAXIMUM_DEPTH_LEVEL_ALLOWED = 20; + /** + * Builds the DataTable, registers itself to the manager + * + */ public function __construct() { $this->currentId = Piwik_DataTable_Manager::getInstance()->addTable($this); } + /** + * Sort the dataTable rows using the php callback function + * + * @param string $functionCallback + */ public function sort( $functionCallback ) { $this->indexNotUpToDate = true; @@ -170,11 +220,22 @@ class Piwik_DataTable } } + /** + * Enables the recursive sort. Means that when using $table->sort() + * it will also sort all subtables using the same callback + * + * @return void + */ public function enableRecursiveSort() { $this->enableRecursiveSort = true; } + /** + * Returns the number of rows before we applied the limit filter + * + * @return int + */ public function getRowsCountBeforeLimitFilter() { $toReturn = $this->rowsCountBeforeLimitFilter; @@ -185,6 +246,12 @@ class Piwik_DataTable return $toReturn; } + /** + * Saves the current number of rows + * + * @return void + * + */ function setRowsCountBeforeLimitFilter() { $this->rowsCountBeforeLimitFilter = $this->getRowsCount(); @@ -206,6 +273,11 @@ class Piwik_DataTable $this->queuedFilters[] = array('className' => $className, 'parameters' => $parameters); } + /** + * Apply all filters that were previously queued to this table + * @see queueFilter() + * @return void + */ public function applyQueuedFilters() { foreach($this->queuedFilters as $filter) @@ -225,28 +297,12 @@ class Piwik_DataTable } $this->queuedFilters = array(); } - - public function rebuildIndex() - { - foreach($this->getRows() as $id => $row) - { - $label = $row->getColumn('label'); - - if($label !== false) - { - $this->rowsIndexByLabel[$label] = $id; - } - } - $this->indexNotUpToDate = false; - } - - /** - * Add a new DataTable to this DataTable + * Adds a new DataTable to this DataTable * Go through all the rows of the new DataTable and applies the algorithm: - * - if a row in $table doesnt exist in $this we add the row to $this - * - if a row exists in both $table and $this we add the columns values into $this + * - if a row in $table doesnt exist in $this we add the new row to $this + * - if a row exists in both $table and $this we sum the columns values into $this * * A common row to 2 DataTable is defined by the same label * @@ -262,7 +318,7 @@ class Piwik_DataTable $labelToLookFor = $row->getColumn('label'); $rowFound = $this->getRowFromLabel( $labelToLookFor ); - // the row with this label already exists + // the row with this label not found if($rowFound === false) { $this->addRow( $row ); @@ -286,8 +342,8 @@ class Piwik_DataTable /** * Returns the Piwik_DataTable_Row that has a column 'label' with the value $label * - * @param string $label - * @return Piwik_DataTable_Row|false The row + * @param string $label Value of the column 'label' of the row to return + * @return Piwik_DataTable_Row|false The row if found, false otherwise */ public function getRowFromLabel( $label ) { @@ -304,6 +360,12 @@ class Piwik_DataTable return $this->rows[$this->rowsIndexByLabel[$label]]; } + /** + * Returns the ith row in the array + * + * @param int $id + * @return Piwik_DataTable_Row or false if not found + */ public function getRowFromId($id) { if(!isset($this->rows[$id])) @@ -313,35 +375,43 @@ class Piwik_DataTable return $this->rows[$id]; } - public function __destruct() - { - unset($this->rows); - } - /** * Shortcut function used for performance reasons + * + * @param Piwik_DataTable_Row $row to add at the end of the array */ - public function addRow( $row ) + public function addRow( Piwik_DataTable_Row $row ) { $this->rows[] = $row; $this->indexNotUpToDate = true; } + /** + * Returns the dataTable ID + * + * @return int + */ public function getId() { return $this->currentId; } - /**
- * You should use loadFromArray for performance!
+ /** + * Adds a new row from a PHP array data structure
+ * You should use loadFromArray for performance! + * + * @param array $row, eg. array(Piwik_DataTable_Row::COLUMNS => array( 'visits' => 13, 'test' => 'toto'),)
*/
public function addRowFromArray( $row )
{
$this->loadFromArray(array($row));
}
- /**
- * You should use loadFromSimpleArray for performance!
+ /** + * Adds a new row a PHP array data structure
+ * You should use loadFromSimpleArray for performance! + * + * @param array $row, eg. array('name' => 'google analytics', 'license' => 'commercial')
*/
public function addRowFromSimpleArray( $row )
{
@@ -357,14 +427,22 @@ class Piwik_DataTable { return $this->rows; } + /** - * Returns the number of rows + * Returns the number of rows in the table + * + * @return int */ public function getRowsCount() { return count($this->rows); } + /** + * Returns the first row of the DataTable + * + * @return Piwik_DataTable_Row + */ public function getFirstRow() { if(count($this->rows) == 0) @@ -378,6 +456,8 @@ class Piwik_DataTable /** * Returns the sum of the number of rows of all the subtables * + the number of rows in the parent table + * + * @return int */ public function getRowsCountRecursive() { @@ -386,7 +466,6 @@ class Piwik_DataTable { if(($idSubTable = $row->getIdSubDataTable()) !== null) { - $subTable = Piwik_DataTable_Manager::getInstance()->getTable($idSubTable); $count = $subTable->getRowsCountRecursive(); $totalCount+=$count; @@ -396,6 +475,12 @@ class Piwik_DataTable $totalCount += $this->getRowsCount(); return $totalCount; } + + /** + * Delete a given column $name in all the rows + * + * @param string $name + */ public function deleteColumn( $name ) { foreach($this->getRows() as $row) @@ -403,15 +488,29 @@ class Piwik_DataTable $row->deleteColumn($name); } } - public function deleteRow( $key ) + + /** + * Deletes the ith row + * + * @param int $key + * @throws Exception if the row $id cannot be found + */ + public function deleteRow( $id ) { - if(!isset($this->rows[$key])) + if(!isset($this->rows[$id])) { - throw new Exception("Trying to delete unknown row with idkey = $key"); + throw new Exception("Trying to delete unknown row with idkey = $id"); } - unset($this->rows[$key]); + unset($this->rows[$id]); } + /** + * Deletes all row from offset, offset + limit. + * If limit is null then limit = $table->getRowsCount() + * + * @param int $offset + * @param int $limit + */ public function deleteRowsOffset( $offset, $limit = null ) { if(is_null($limit)) @@ -421,6 +520,12 @@ class Piwik_DataTable array_splice($this->rows, $offset, $limit); } + /** + * Deletes the rows from the list of rows ID + * + * @param array $aKeys ID of the rows to delete + * @throws Exception if any of the row to delete couldn't be found + */ public function deleteRows( array $aKeys ) { foreach($aKeys as $key) @@ -429,14 +534,27 @@ class Piwik_DataTable } } + /** + * Returns a simple output of the DataTable for easy visualization + * Example: echo $datatable; + * + * @return string + */ public function __toString() { $renderer = new Piwik_DataTable_Renderer_Console($this); return (string)$renderer; } - - static public function isEqual($table1, $table2) + /** + * Returns true if both DataTable are exactly the same. + * Used in unit tests. + * + * @param Piwik_DataTable $table1 + * @param Piwik_DataTable $table2 + * @return bool + */ + static public function isEqual(Piwik_DataTable $table1, Piwik_DataTable $table2) { $rows1 = $table1->getRows(); $rows2 = $table2->getRows(); @@ -471,10 +589,10 @@ class Piwik_DataTable /** * The serialization returns a one dimension array containing all the * serialized DataTable contained in this DataTable. + * We save DataTable in serialized format in the Database. + * Each row of this returned PHP array will be a row in the DB table. * * The keys of the array are very important as they are used to define the DataTable - * For the example the key 3 is used in the array corresponding to the key 2 - * because the key 3 is the array which is a child of the array corresponding to the key 2 * * IMPORTANT: The main table (level 0, parent of all tables) will always be indexed by 0 * even it was created after some other tables. @@ -482,6 +600,8 @@ class Piwik_DataTable * serialized arrays. You should never lookup a parent table using the getTable( $id = 0) as it * won't work. * + * @throws Exception if an infinite recursion is found (a table row's has a subtable that is one of its parent table) + * * @return array Serialized arrays * array( // Datatable level0 * 0 => 'eghuighahgaueytae78yaet7yaetae', @@ -537,18 +657,20 @@ class Piwik_DataTable } /** - * Load a serialized string. + * Load a serialized string of a datatable. * * Does not load recursively all the sub DataTable. * They will be loaded only when requesting them specifically. * - * The function creates the DataTable_Row + * The function creates all the necessary DataTable_Row * + * @param string Serialized string of a datatable + * @return void */ public function loadFromSerialized( $stringSerialized ) { $serialized = unserialize($stringSerialized); - if($serialized===false) + if($serialized === false) { throw new Exception("The unserialization has failed!"); } @@ -556,7 +678,7 @@ class Piwik_DataTable } /** - * Load the data from a PHP array + * Loads the DataTable from a PHP array data structure * * @param array Array with the following structure * array(
@@ -571,8 +693,7 @@ class Piwik_DataTable * array( ... ), * * ) - * - * @see DataTable_Row::loadFromArray for the row structures + * @return void */ public function loadFromArray( $array ) { @@ -588,9 +709,9 @@ class Piwik_DataTable }
/**
- * Load the data from a simple php array.
- * Basically maps a simple multidimensional php php array to a DataTable.
- * Not recursive (if a row contains a php array itself, it won't work well...)
+ * Loads the data from a simple php array.
+ * Basically maps a simple multidimensional php array to a DataTable.
+ * Not recursive (if a row contains a php array itself, it won't be loaded)
*
* @param array Array with the simple structure:
* array(
@@ -599,10 +720,7 @@ class Piwik_DataTable * )
*/
public function loadFromSimpleArray( $array )
- {
-// var_dump($array);exit;
-
-
+ {
// we define an exception we may throw if at one point we notice that we cannot handle the data structure
$e = new Exception(" Data structure returned is not convertible in the requested format.".
" Try to call this method with the parameters '&format=original&serialize=1'".
@@ -614,7 +732,8 @@ class Piwik_DataTable // array(col1_name => val1, col2_name => val2, etc.)
// with val* that are never arrays (only strings/numbers/bool/etc.)
// if we detect such a "simple" data structure we convert it to a row with the correct columns' names
- $rowBuilt = array(); $thisIsNotThatSimple = false;
+ $rowBuilt = array(); $thisIsNotThatSimple = false; +
foreach($array as $columnName => $columnValue )
{
if(is_array($columnValue) || is_object($columnValue))
@@ -623,7 +742,8 @@ class Piwik_DataTable break;
}
$rowBuilt += array($columnName => $columnValue );
- }
+ } +
if($thisIsNotThatSimple === false)
{
$this->addRow( new Piwik_DataTable_Row( array( Piwik_DataTable_Row::COLUMNS => $rowBuilt ) ) );
@@ -673,7 +793,7 @@ class Piwik_DataTable } /** - * Rewrite the input $array + * Rewrites the input $array * array ( * LABEL => array(col1 => X, col2 => Y), * LABEL2 => array(col1 => X, col2 => Y), @@ -702,6 +822,10 @@ class Piwik_DataTable * ), * ) * + * @param array $array See method description + * @param array|null $subtablePerLabel see method description + * + * @return void */ public function loadFromArrayLabelIsKey( $array, $subtablePerLabel = null) { @@ -725,12 +849,37 @@ class Piwik_DataTable $this->addRow( new Piwik_DataTable_Row($cleanRow) ); } } -} - + -function Piwik_DataTable_orderRowByLabel($o1,$o2) -{ - return strcmp($o1->getColumn('label'), $o2->getColumn('label')); + /** + * Rebuilds the index used to lookup a row by label + * + * @return void + */ + protected function rebuildIndex() + { + foreach($this->getRows() as $id => $row) + { + $label = $row->getColumn('label'); + + if($label !== false) + { + $this->rowsIndexByLabel[$label] = $id; + } + } + + $this->indexNotUpToDate = false; + } + + /** + * At destruction we try to free memory + * But php doesn't give us much control on this + */ + public function __destruct() + { + unset($this->rows); + } + } /** diff --git a/modules/Date.php b/modules/Date.php index e79f41c746..d455350188 100644 --- a/modules/Date.php +++ b/modules/Date.php @@ -10,6 +10,7 @@ */
/** + * Date object widely used in Piwik. *
* //TODO remove factory OR constructor! cant have both
* @package Piwik_Helper @@ -17,6 +18,25 @@ class Piwik_Date { /** + * Returns a Piwik_Date objects. + * Accepts strings 'today' 'yesterday' or any YYYY-MM-DD or timestamp + * + * @param string $strDate + * @return Piwik_Date + */ + static public function factory($strDate) + { + switch($strDate) + { + case 'today': return self::today(); break; + case 'yesterday': return self::yesterday(); break; + default: return new Piwik_Date($strDate); break; + } + } + + /** + * Builds a Piwik_Date object + * * @param Timestamp date OR string format 2007-01-31 */ public function __construct( $date ) @@ -36,9 +56,11 @@ class Piwik_Date } /** - * - * + * Sets the time part of the date + * Doesn't modify $this + * * @param string $time HH:MM:SS + * @return Piwik_Date The new date with the time part set */ //TODO test this method public function setTime($time) @@ -46,25 +68,55 @@ class Piwik_Date return new Piwik_Date( strtotime( $this->get("j F Y") . " $time")); } + /** + * Returns the unix timestamp of the date + * + * @return int + */ public function getTimestamp() { return $this->timestamp; } + /** + * Returns true if the current date is older than the given $date + * + * @param Piwik_Date $date + * @return bool + */ public function isLater( Piwik_Date $date) { return $this->getTimestamp() > $date->getTimestamp(); } + + /** + * Returns true if the current date is earlier than the given $date + * + * @param Piwik_Date $date + * @return bool + */ public function isEarlier(Piwik_Date $date) { return $this->getTimestamp() < $date->getTimestamp(); } + /** + * Returns the Y-m-d representation of the string. + * You can specify the output, see the list on php.net/date + * + * @param string $part + * @return string + */ public function toString($part = 'Y-m-d') { return date($part, $this->getTimestamp()); } + /** + * @see toString() + * + * @return string + */ public function __toString() { return $this->toString(); @@ -73,7 +125,9 @@ class Piwik_Date /** * Sets a new day * Returned is the new date object + * Doesn't modify $this * + * @param int Day eg. 31 * @return Piwik_Date new date */ public function setDay( $day ) @@ -89,9 +143,11 @@ class Piwik_Date ); return new Piwik_Date( $result ); } + /** * Sets a new year * Returned is the new date object + * Doesn't modify $this * * @param int 2010 * @return Piwik_Date new date @@ -110,33 +166,12 @@ class Piwik_Date return new Piwik_Date( $result ); } - /** - * Compares only the week part, returning the difference - * Returned is the new date object - * Returns if equal, earlier or later - * Example: 09.Jan.2007 13:07:25 -> compareWeek(2); -> 0 - * - * @return integer 0 = equal, 1 = later, -1 = earlier - */ - public function compareWeek(Piwik_Date $date) - { - $currentWeek = date('W', $this->getTimestamp()); - $toCompareWeek = date('W', $date->getTimestamp()); - if( $currentWeek == $toCompareWeek) - { - return 0; - } - if( $currentWeek < $toCompareWeek) - { - return -1; - } - return 1; - } /** - * Subtracts days from the existing date object. - + * Subtracts days from the existing date object and returns a new Piwik_Date object + * Doesn't modify $this + * * Returned is the new date object * @return Piwik_Date new date */ @@ -149,12 +184,12 @@ class Piwik_Date /** * Subtracts a month from the existing date object. * Returned is the new date object + * Doesn't modify $this * * @return Piwik_Date new date */ public function subMonth( $n ) { -// $ts = strtotime("-$n months", $this->getTimestamp()); $ts = $this->getTimestamp(); $result = mktime( date('H', $ts), @@ -170,7 +205,7 @@ class Piwik_Date /** * Returns a representation of a date or datepart * - * @param string $part OPTIONAL Part of the date to return, if null the timestamp is returned + * @param string OPTIONAL Part of the date to return, if null the timestamp is returned * @return integer|string date or datepart */ public function get($part = null) @@ -185,6 +220,9 @@ class Piwik_Date /** * Adds days to the existing date object. * Returned is the new date object + * Doesn't modify $this + * + * @param int Number of days to add * @return Piwik_Date new date */ public function addDay( $n ) @@ -192,11 +230,33 @@ class Piwik_Date $ts = strtotime("+$n day", $this->getTimestamp()); return new Piwik_Date( $ts ); } - + + /** + * Compares the week of the current date against the given $date + * Returns 0 if equal, -1 if current week is earlier or 1 if current week is later + * Example: 09.Jan.2007 13:07:25 -> compareWeek(2); -> 0 + * + * @param Piwik_Date $date + * @return integer 0 = equal, 1 = later, -1 = earlier + */ + public function compareWeek(Piwik_Date $date) + { + $currentWeek = date('W', $this->getTimestamp()); + $toCompareWeek = date('W', $date->getTimestamp()); + if( $currentWeek == $toCompareWeek) + { + return 0; + } + if( $currentWeek < $toCompareWeek) + { + return -1; + } + return 1; + } /** - * Compares the month with the existing date object, ignoring other date parts. - * For example: 10.03.2000 -> 15.03.1950 -> true - * Returns if equal, earlier or later + * Compares the month of the current date against the given $date month + * Returns 0 if equal, -1 if current month is earlier or 1 if current month is later + * For example: 10.03.2000 -> 15.03.1950 -> 0 * * @param Piwik_Date $month Month to compare * @return integer 0 = equal, 1 = later, -1 = earlier @@ -218,6 +278,8 @@ class Piwik_Date /** * Returns a date object set to today midnight + * + * @return Piwik_Date */ static public function today() { @@ -226,6 +288,7 @@ class Piwik_Date } /** * Returns a date object set to yesterday midnight + * @return Piwik_Date */ static public function yesterday() { @@ -233,14 +296,5 @@ class Piwik_Date return $date; } - static public function factory($strDate) - { - switch($strDate) - { - case 'today': return self::today(); break; - case 'yesterday': return self::yesterday(); break; - default: return new Piwik_Date($strDate); break; - } - } } diff --git a/modules/ErrorHandler.php b/modules/ErrorHandler.php index 8643720a18..ce9f68eec3 100755 --- a/modules/ErrorHandler.php +++ b/modules/ErrorHandler.php @@ -8,13 +8,14 @@ *
* @package Piwik_Helper
*/
+ +require_once "Zend/Registry.php"; /** - *
+ * Error handler used to display nicely errors in Piwik
*
* @package Piwik_Helper */ -require_once "Zend/Registry.php"; function Piwik_ErrorHandler($errno, $errstr, $errfile, $errline) { // if the error has been suppressed by the @ we don't handle the error diff --git a/modules/ExceptionHandler.php b/modules/ExceptionHandler.php index 13e1e013cb..edfb684f42 100644 --- a/modules/ExceptionHandler.php +++ b/modules/ExceptionHandler.php @@ -9,9 +9,10 @@ * @package Piwik_Helper
*/
-require_once "modules/Piwik.php";
+require_once "modules/Piwik.php"; +
/** - *
+ * Exception handler used to display nicely exceptions in Piwik
*
* @package Piwik_Helper */ diff --git a/modules/Form.php b/modules/Form.php index 4d5e3ae371..2a82abe7c7 100644 --- a/modules/Form.php +++ b/modules/Form.php @@ -14,12 +14,16 @@ require_once "HTML/QuickForm.php"; require_once "HTML/QuickForm/Renderer/ArraySmarty.php"; /**
+ * Parent class for forms to be included in Smarty + * + * For an example, @see Piwik_Login_Form *
* @package Piwik_Helper
*/ abstract class Piwik_Form extends HTML_QuickForm { - private $a_formElements = array(); + protected $a_formElements = array(); + function __construct( $action = '' ) { if(empty($action)) diff --git a/modules/FrontController.php b/modules/FrontController.php index 0f7fccc115..da10538096 100644 --- a/modules/FrontController.php +++ b/modules/FrontController.php @@ -14,7 +14,6 @@ * Zend classes */ require_once "Zend/Exception.php"; -require_once "Zend/Loader.php"; require_once "Zend/Auth.php"; require_once "Zend/Auth/Adapter/DbTable.php"; @@ -32,20 +31,36 @@ require_once "Translate.php"; require_once "Url.php"; require_once "Controller.php"; -require_once "Menu.php"; -require_once "AdminMenu.php"; -require_once "Widget.php"; +require_once "PluginsFunctions/Menu.php"; +require_once "PluginsFunctions/AdminMenu.php"; +require_once "PluginsFunctions/Widget.php"; +require_once "PluginsFunctions/Sql.php"; /** + * Front controller. + * This is the class hit in the first place. + * It dispatches the request to the right controller. * + * For a detailed explanation, see the documentation on http://dev.piwik.org/trac/wiki/MainSequenceDiagram * * @package Piwik */ class Piwik_FrontController { + /** + * Set to false and the Front Controller will not dispatch the request + * + * @var bool + */ static public $enableDispatch = true; - static private $instance = null; + static private $instance = null; + + /** + * returns singleton + * + * @return Piwik_FrontController + */ static public function getInstance() { if (self::$instance == null) @@ -56,6 +71,17 @@ class Piwik_FrontController return self::$instance; } + /** + * Dispatches the request to the right plugin and executes the requested action on the plugin controller. + * + * @throws Exception in case the plugin doesn't exist, the action doesn't exist, there is not enough permission, etc. + * + * @param string $module + * @param string $action + * @param array $parameters + * @return mixed The returned value of the calls, often nothing as the module print but don't return data + * @see fetchDispatch() + */ function dispatch( $module = null, $action = null, $parameters = null) { if( self::$enableDispatch === false) @@ -125,6 +151,15 @@ class Piwik_FrontController } } + /** + * Often plugins controller display stuff using echo/print. + * Using this function instead of dispath() returns the output form the actions calls. + * + * @param string $controllerName + * @param string $actionName + * @param array $parameters + * @return string + */ function fetchDispatch( $controllerName = null, $actionName = null, $parameters = null) { ob_start(); @@ -138,7 +173,11 @@ class Piwik_FrontController return $output; } - function end() + /** + * Called at the end of the page generation + * + */ + function __destruct() { try { Piwik::printZendProfiler(); @@ -148,9 +187,14 @@ class Piwik_FrontController // Piwik::printMemoryUsage(); // Piwik::printTimer(); // Piwik::uninstall(); - } + /** + * Checks that the directories Piwik needs write access are actually writable + * Displays a nice error page if permissions are missing on some directories + * + * @return void + */ protected function checkDirectoriesWritableOrDie() { $resultCheck = Piwik::checkDirectoriesWritable( ); @@ -231,6 +275,16 @@ class Piwik_FrontController } } + /** + * Must be called before dispatch() + * - checks that directories are writable, + * - loads the configuration file, + * - loads the plugin, + * - inits the DB connection, + * - etc. + * + * @return void + */ function init() { Zend_Registry::set('timer', new Piwik_Timer); @@ -303,7 +357,11 @@ class Piwik_FrontController Zend_Registry::get('access')->loadAccess(); } } - +/** + * Exception thrown when the requested plugin is not activated in the config file + * + * @package Piwik + */ // TODO organize exceptions class Exception_PluginDeactivated extends Exception { diff --git a/modules/LogStats.php b/modules/LogStats.php index ec74f9b505..db124735b3 100644 --- a/modules/LogStats.php +++ b/modules/LogStats.php @@ -10,6 +10,9 @@ */
/** + * Class used by the logging script piwik.php called by the javascript tag. + * Handles the visitor & his/her actions on the website, saves the data in the DB, saves information in the cookie, etc. + * * To maximise the performance of the logging module, we use different techniques. * * On the PHP-only side: @@ -32,9 +35,6 @@ * * - handle the timezone settings?? * - * [ - country detection plugin => ip lookup ] - * [ - precise country detection plugin ] - * * We could also imagine a batch system that would read a log file every 5min, * and which prepares the file containg the rows to insert, then we load DATA INFILE * diff --git a/modules/Period.php b/modules/Period.php index 1e05eb91fb..90d94bb707 100644 --- a/modules/Period.php +++ b/modules/Period.php @@ -10,7 +10,7 @@ */
/** - * Creating a new Piwik_Period + * Creating a new Piwik_Period subclass: * * Every overloaded method must start with the code * if(!$this->subperiodsProcessed) diff --git a/modules/Piwik.php b/modules/Piwik.php index b86ae04342..e128a4281b 100755 --- a/modules/Piwik.php +++ b/modules/Piwik.php @@ -16,6 +16,8 @@ require_once "Log.php"; require_once "PluginsManager.php"; /**
+ * Main piwik helper class. + * Contains static functions you can call from the plugins. *
* @package Piwik
*/ diff --git a/modules/AdminMenu.php b/modules/PluginsFunctions/AdminMenu.php index b450eb04f4..b450eb04f4 100644 --- a/modules/AdminMenu.php +++ b/modules/PluginsFunctions/AdminMenu.php diff --git a/modules/Menu.php b/modules/PluginsFunctions/Menu.php index 84e06b5a70..84e06b5a70 100644 --- a/modules/Menu.php +++ b/modules/PluginsFunctions/Menu.php diff --git a/modules/PluginsFunctions/Sql.php b/modules/PluginsFunctions/Sql.php new file mode 100644 index 0000000000..f169c4cf7e --- /dev/null +++ b/modules/PluginsFunctions/Sql.php @@ -0,0 +1,34 @@ +<?php + +/** + * Executes a SQL query on the DB and returns the Zend_Db_Statement object + * If you want to fetch data from the DB you should use the function Piwik_FetchAll() + * + * See also http://framework.zend.com/manual/en/zend.db.statement.html + * + * @param string $sqlQuery + * @param array Parameters to bind in the query, array( param1 => value1, param2 => value2) + * @return Zend_Db_Statement + */ +function Piwik_Query( $sqlQuery, $parameters = array()) +{ + return Zend_Registry::get('db')->query( $sqlQuery, $parameters); +} + +/** + * Executes the SQL Query and fetches all the rows from the database + * + * @param string $sqlQuery + * @param array Parameters to bind in the query, array( param1 => value1, param2 => value2) + * @return array (one row in the array per row fetched in the DB) + */ +function Piwik_FetchAll( $sqlQuery, $parameters = array()) +{ + return Zend_Registry::get('db')->fetchAll( $sqlQuery, $parameters ); +} + +function Piwik_FetchOne( $sqlQuery, $parameters = array()) +{ + return Zend_Registry::get('db')->fetchOne( $sqlQuery, $parameters ); +} + diff --git a/modules/Widget.php b/modules/PluginsFunctions/Widget.php index 65e90d84fa..65e90d84fa 100644 --- a/modules/Widget.php +++ b/modules/PluginsFunctions/Widget.php diff --git a/modules/PluginsManager.php b/modules/PluginsManager.php index 0f1a69eca7..f7bbc87cf6 100644 --- a/modules/PluginsManager.php +++ b/modules/PluginsManager.php @@ -451,36 +451,4 @@ function Piwik_PostEvent( $eventName, &$object = null, $info = array() ) function Piwik_AddAction( $hookName, $function ) { Piwik_PluginsManager::getInstance()->dispatcher->addObserver( $function, $hookName ); -} - -/** - * Executes a SQL query on the DB and returns the Zend_Db_Statement object - * If you want to fetch data from the DB you should use the function Piwik_FetchAll() - * - * See also http://framework.zend.com/manual/en/zend.db.statement.html - * - * @param string $sqlQuery - * @param array Parameters to bind in the query, array( param1 => value1, param2 => value2) - * @return Zend_Db_Statement - */ -function Piwik_Query( $sqlQuery, $parameters = array()) -{ - return Zend_Registry::get('db')->query( $sqlQuery, $parameters); -} - -/** - * Executes the SQL Query and fetches all the rows from the database - * - * @param string $sqlQuery - * @param array Parameters to bind in the query, array( param1 => value1, param2 => value2) - * @return array (one row in the array per row fetched in the DB) - */ -function Piwik_FetchAll( $sqlQuery, $parameters = array()) -{ - return Zend_Registry::get('db')->fetchAll( $sqlQuery, $parameters ); -} -function Piwik_FetchOne( $sqlQuery, $parameters = array()) -{ - return Zend_Registry::get('db')->fetchOne( $sqlQuery, $parameters ); -} - +}
\ No newline at end of file diff --git a/modules/iView.php b/modules/iView.php index c014a2d90e..42003b4a72 100644 --- a/modules/iView.php +++ b/modules/iView.php @@ -10,10 +10,18 @@ */
/**
+ * Piwik_ViewDataTable must create a $view attribute which implements this interface. *
* @package Piwik_Visualization
*/
interface Piwik_iView
-{
+{ + /** + * Outputs the data. + * Either outputs html, xml, an image, nothing, etc. + * + * @return mixed + * + */
function render();
}
\ No newline at end of file diff --git a/plugins/UsersManager/API.php b/plugins/UsersManager/API.php index 63f36b3eb4..cb230e5f2d 100755 --- a/plugins/UsersManager/API.php +++ b/plugins/UsersManager/API.php @@ -9,8 +9,6 @@ * @package Piwik_UsersManager
*/
-Zend_Loader::loadClass("Piwik_Access"); -
/**
*
* @package Piwik_UsersManager
|