diff options
author | mattab <matthieu.aubry@gmail.com> | 2013-03-28 03:42:39 +0400 |
---|---|---|
committer | mattab <matthieu.aubry@gmail.com> | 2013-03-28 03:42:40 +0400 |
commit | ae4b03163792f0b6e933933e5d37df87dc3fd566 (patch) | |
tree | d1d7510a9728f587d3d63ebd03e4ecf3d904838b /libs | |
parent | 158c2150f5f2e13ece459b8d131244c11b763997 (diff) |
Mass conversion of all files to the newly agreed coding standard: PSR 1/2
Converting Piwik core source files, PHP, JS, TPL, CSS
More info: http://piwik.org/participate/coding-standards/
Diffstat (limited to 'libs')
-rw-r--r-- | libs/PiwikTracker/PiwikTracker.php | 1618 | ||||
-rw-r--r-- | libs/UserAgentParser/UserAgentParser.php | 1234 | ||||
-rw-r--r-- | libs/UserAgentParser/UserAgentParser.test.php | 70 |
3 files changed, 1428 insertions, 1494 deletions
diff --git a/libs/PiwikTracker/PiwikTracker.php b/libs/PiwikTracker/PiwikTracker.php index 7810fb196f..97e5acbc82 100644 --- a/libs/PiwikTracker/PiwikTracker.php +++ b/libs/PiwikTracker/PiwikTracker.php @@ -24,160 +24,158 @@ */ class PiwikTracker { - /** - * Piwik base URL, for example http://example.org/piwik/ - * Must be set before using the class by calling - * PiwikTracker::$URL = 'http://yourwebsite.org/piwik/'; - * - * @var string - */ - static public $URL = ''; - - /** - * API Version - * - * @ignore - * @var int - */ - const VERSION = 1; - - /** - * @ignore - */ - public $DEBUG_APPEND_URL = ''; - - /** - * Visitor ID length - * - * @ignore - */ - const LENGTH_VISITOR_ID = 16; - - /** - * Charset - * @see setPageCharset - * @ignore - */ - const DEFAULT_CHARSET_PARAMETER_VALUES = 'utf-8'; - - /** - * Builds a PiwikTracker object, used to track visits, pages and Goal conversions - * for a specific website, by using the Piwik Tracking API. - * - * @param int $idSite Id site to be tracked - * @param string $apiUrl "http://example.org/piwik/" or "http://piwik.example.org/" - * If set, will overwrite PiwikTracker::$URL - */ - function __construct( $idSite, $apiUrl = '' ) + /** + * Piwik base URL, for example http://example.org/piwik/ + * Must be set before using the class by calling + * PiwikTracker::$URL = 'http://yourwebsite.org/piwik/'; + * + * @var string + */ + static public $URL = ''; + + /** + * API Version + * + * @ignore + * @var int + */ + const VERSION = 1; + + /** + * @ignore + */ + public $DEBUG_APPEND_URL = ''; + + /** + * Visitor ID length + * + * @ignore + */ + const LENGTH_VISITOR_ID = 16; + + /** + * Charset + * @see setPageCharset + * @ignore + */ + const DEFAULT_CHARSET_PARAMETER_VALUES = 'utf-8'; + + /** + * Builds a PiwikTracker object, used to track visits, pages and Goal conversions + * for a specific website, by using the Piwik Tracking API. + * + * @param int $idSite Id site to be tracked + * @param string $apiUrl "http://example.org/piwik/" or "http://piwik.example.org/" + * If set, will overwrite PiwikTracker::$URL + */ + function __construct($idSite, $apiUrl = '') { - $this->cookieSupport = true; - $this->userAgent = false; - $this->localHour = false; - $this->localMinute = false; - $this->localSecond = false; - $this->hasCookies = false; - $this->plugins = false; - $this->visitorCustomVar = false; - $this->pageCustomVar = false; - $this->customData = false; - $this->forcedDatetime = false; - $this->token_auth = false; - $this->attributionInfo = false; - $this->ecommerceLastOrderTimestamp = false; - $this->ecommerceItems = array(); - $this->generationTime = false; - - $this->requestCookie = ''; - $this->idSite = $idSite; - $this->urlReferrer = @$_SERVER['HTTP_REFERER']; - $this->pageCharset = self::DEFAULT_CHARSET_PARAMETER_VALUES; - $this->pageUrl = self::getCurrentUrl(); - $this->ip = @$_SERVER['REMOTE_ADDR']; - $this->acceptLanguage = @$_SERVER['HTTP_ACCEPT_LANGUAGE']; - $this->userAgent = @$_SERVER['HTTP_USER_AGENT']; - if(!empty($apiUrl)) - { - self::$URL = $apiUrl; - } - $this->setNewVisitorId(); - - // Allow debug while blocking the request - $this->requestTimeout = 600; - $this->doBulkRequests = false; - $this->storedTrackingActions = array(); + $this->cookieSupport = true; + $this->userAgent = false; + $this->localHour = false; + $this->localMinute = false; + $this->localSecond = false; + $this->hasCookies = false; + $this->plugins = false; + $this->visitorCustomVar = false; + $this->pageCustomVar = false; + $this->customData = false; + $this->forcedDatetime = false; + $this->token_auth = false; + $this->attributionInfo = false; + $this->ecommerceLastOrderTimestamp = false; + $this->ecommerceItems = array(); + $this->generationTime = false; + + $this->requestCookie = ''; + $this->idSite = $idSite; + $this->urlReferrer = @$_SERVER['HTTP_REFERER']; + $this->pageCharset = self::DEFAULT_CHARSET_PARAMETER_VALUES; + $this->pageUrl = self::getCurrentUrl(); + $this->ip = @$_SERVER['REMOTE_ADDR']; + $this->acceptLanguage = @$_SERVER['HTTP_ACCEPT_LANGUAGE']; + $this->userAgent = @$_SERVER['HTTP_USER_AGENT']; + if (!empty($apiUrl)) { + self::$URL = $apiUrl; + } + $this->setNewVisitorId(); + + // Allow debug while blocking the request + $this->requestTimeout = 600; + $this->doBulkRequests = false; + $this->storedTrackingActions = array(); } - /** - * By default, Piwik expects utf-8 encoded values, for example - * for the page URL parameter values, Page Title, etc. - * It is recommended to only send UTF-8 data to Piwik. - * If required though, you can also specify another charset using this function. - * - * @param string $charset - */ - public function setPageCharset( $charset = '' ) - { - $this->pageCharset = $charset; - } + /** + * By default, Piwik expects utf-8 encoded values, for example + * for the page URL parameter values, Page Title, etc. + * It is recommended to only send UTF-8 data to Piwik. + * If required though, you can also specify another charset using this function. + * + * @param string $charset + */ + public function setPageCharset($charset = '') + { + $this->pageCharset = $charset; + } /** * Sets the current URL being tracked - * + * * @param string $url Raw URL (not URL encoded) */ - public function setUrl( $url ) + public function setUrl($url) { - $this->pageUrl = $url; + $this->pageUrl = $url; } /** * Sets the URL referrer used to track Referrers details for new visits. - * + * * @param string $url Raw URL (not URL encoded) */ - public function setUrlReferrer( $url ) + public function setUrlReferrer($url) { - $this->urlReferrer = $url; + $this->urlReferrer = $url; } - /** - * Sets the time that generating the document on the server side took. - * - * @param int $timeMs Generation time in ms - */ - public function setGenerationTime( $timeMs ) - { - $this->generationTime = $timeMs; - } - - /** - * @deprecated + /** + * Sets the time that generating the document on the server side took. + * + * @param int $timeMs Generation time in ms + */ + public function setGenerationTime($timeMs) + { + $this->generationTime = $timeMs; + } + + /** + * @deprecated * @ignore */ - public function setUrlReferer( $url ) + public function setUrlReferer($url) { - $this->setUrlReferrer($url); + $this->setUrlReferrer($url); } - + /** - * Sets the attribution information to the visit, so that subsequent Goal conversions are + * Sets the attribution information to the visit, so that subsequent Goal conversions are * properly attributed to the right Referrer URL, timestamp, Campaign Name & Keyword. - * - * This must be a JSON encoded string that would typically be fetched from the JS API: - * piwikTracker.getAttributionInfo() and that you have JSON encoded via JSON2.stringify() + * + * This must be a JSON encoded string that would typically be fetched from the JS API: + * piwikTracker.getAttributionInfo() and that you have JSON encoded via JSON2.stringify() * * @param string $jsonEncoded JSON encoded array containing Attribution info - * @throws Exception + * @throws Exception * @see function getAttributionInfo() in https://github.com/piwik/piwik/blob/master/js/piwik.js */ - public function setAttributionInfo( $jsonEncoded ) + public function setAttributionInfo($jsonEncoded) { - $decoded = json_decode($jsonEncoded, $assoc = true); - if(!is_array($decoded)) - { - throw new Exception("setAttributionInfo() is expecting a JSON encoded string, $jsonEncoded given"); - } - $this->attributionInfo = $decoded; + $decoded = json_decode($jsonEncoded, $assoc = true); + if (!is_array($decoded)) { + throw new Exception("setAttributionInfo() is expecting a JSON encoded string, $jsonEncoded given"); + } + $this->attributionInfo = $decoded; } /** @@ -188,115 +186,103 @@ class PiwikTracker * @param string $name Custom variable name * @param string $value Custom variable value * @param string $scope Custom variable scope. Possible values: visit, page - * @throws Exception + * @throws Exception */ public function setCustomVariable($id, $name, $value, $scope = 'visit') { - if(!is_int($id)) - { - throw new Exception("Parameter id to setCustomVariable should be an integer"); - } - if($scope == 'page') - { - $this->pageCustomVar[$id] = array($name, $value); - } - elseif($scope == 'visit') - { - $this->visitorCustomVar[$id] = array($name, $value); - } - else - { - throw new Exception("Invalid 'scope' parameter value"); - } + if (!is_int($id)) { + throw new Exception("Parameter id to setCustomVariable should be an integer"); + } + if ($scope == 'page') { + $this->pageCustomVar[$id] = array($name, $value); + } elseif ($scope == 'visit') { + $this->visitorCustomVar[$id] = array($name, $value); + } else { + throw new Exception("Invalid 'scope' parameter value"); + } } - + /** * Returns the currently assigned Custom Variable stored in a first party cookie. - * + * * This function will only work if the user is initiating the current request, and his cookies * can be read by PHP from the $_COOKIE array. - * + * * @param int $id Custom Variable integer index to fetch from cookie. Should be a value from 1 to 5 * @param string $scope Custom variable scope. Possible values: visit, page * - * @throws Exception + * @throws Exception * @return mixed An array with this format: array( 0 => CustomVariableName, 1 => CustomVariableValue ) or false * @see Piwik.js getCustomVariable() */ public function getCustomVariable($id, $scope = 'visit') { - if($scope == 'page') - { - return isset($this->pageCustomVar[$id]) ? $this->pageCustomVar[$id] : false; - } - else if($scope != 'visit') - { - throw new Exception("Invalid 'scope' parameter value"); - } - if(!empty($this->visitorCustomVar[$id])) - { - return $this->visitorCustomVar[$id]; - } - $customVariablesCookie = 'cvar.'.$this->idSite.'.'; - $cookie = $this->getCookieMatchingName($customVariablesCookie); - if(!$cookie) - { - return false; - } - if(!is_int($id)) - { - throw new Exception("Parameter to getCustomVariable should be an integer"); - } - $cookieDecoded = json_decode($cookie, $assoc = true); - if(!is_array($cookieDecoded) - || !isset($cookieDecoded[$id]) - || !is_array($cookieDecoded[$id]) - || count($cookieDecoded[$id]) != 2) - { - return false; - } - return $cookieDecoded[$id]; + if ($scope == 'page') { + return isset($this->pageCustomVar[$id]) ? $this->pageCustomVar[$id] : false; + } else if ($scope != 'visit') { + throw new Exception("Invalid 'scope' parameter value"); + } + if (!empty($this->visitorCustomVar[$id])) { + return $this->visitorCustomVar[$id]; + } + $customVariablesCookie = 'cvar.' . $this->idSite . '.'; + $cookie = $this->getCookieMatchingName($customVariablesCookie); + if (!$cookie) { + return false; + } + if (!is_int($id)) { + throw new Exception("Parameter to getCustomVariable should be an integer"); + } + $cookieDecoded = json_decode($cookie, $assoc = true); + if (!is_array($cookieDecoded) + || !isset($cookieDecoded[$id]) + || !is_array($cookieDecoded[$id]) + || count($cookieDecoded[$id]) != 2 + ) { + return false; + } + return $cookieDecoded[$id]; } - + /** * Sets the current visitor ID to a random new one. */ public function setNewVisitorId() { - $this->visitorId = substr(md5(uniqid(rand(), true)), 0, self::LENGTH_VISITOR_ID); + $this->visitorId = substr(md5(uniqid(rand(), true)), 0, self::LENGTH_VISITOR_ID); } - + /** * Sets the current site ID. - * + * * @param int $idSite */ - public function setIdSite( $idSite ) + public function setIdSite($idSite) { - $this->idSite = $idSite; + $this->idSite = $idSite; } - + /** * Sets the Browser language. Used to guess visitor countries when GeoIP is not enabled - * + * * @param string $acceptLanguage For example "fr-fr" */ - public function setBrowserLanguage( $acceptLanguage ) + public function setBrowserLanguage($acceptLanguage) { - $this->acceptLanguage = $acceptLanguage; + $this->acceptLanguage = $acceptLanguage; } /** * Sets the user agent, used to detect OS and browser. * If this function is not called, the User Agent will default to the current user agent. - * + * * @param string $userAgent */ public function setUserAgent($userAgent) { - $this->userAgent = $userAgent; + $this->userAgent = $userAgent; } - + /** * Sets the country of the visitor. If not used, Piwik will try to find the country * using either the visitor's IP address or language. @@ -306,9 +292,9 @@ class PiwikTracker */ public function setCountry($country) { - $this->country = $country; + $this->country = $country; } - + /** * Sets the region of the visitor. If not used, Piwik may try to find the region * using the visitor's IP address (if configured to do so). @@ -318,9 +304,9 @@ class PiwikTracker */ public function setRegion($region) { - $this->region = $region; + $this->region = $region; } - + /** * Sets the city of the visitor. If not used, Piwik may try to find the city * using the visitor's IP address (if configured to do so). @@ -330,9 +316,9 @@ class PiwikTracker */ public function setCity($city) { - $this->city = $city; + $this->city = $city; } - + /** * Sets the latitude of the visitor. If not used, Piwik may try to find the visitor's * latitude using the visitor's IP address (if configured to do so). @@ -342,9 +328,9 @@ class PiwikTracker */ public function setLatitude($lat) { - $this->lat = $lat; + $this->lat = $lat; } - + /** * Sets the longitude of the visitor. If not used, Piwik may try to find the visitor's * longitude using the visitor's IP address (if configured to do so). @@ -354,62 +340,62 @@ class PiwikTracker */ public function setLongitude($long) { - $this->long = $long; + $this->long = $long; } - - /** - * Enables the bulk request feature. When used, each tracking action is stored until the - * doBulkTrack method is called. This method will send all tracking data at once. - */ - public function enableBulkTracking() - { - $this->doBulkRequests = true; - } - + + /** + * Enables the bulk request feature. When used, each tracking action is stored until the + * doBulkTrack method is called. This method will send all tracking data at once. + */ + public function enableBulkTracking() + { + $this->doBulkRequests = true; + } + /** * Tracks a page view - * + * * @param string $documentTitle Page title as it will appear in the Actions > Page titles report * @return mixed Response string or true if using bulk requests. */ - public function doTrackPageView( $documentTitle ) + public function doTrackPageView($documentTitle) { - $url = $this->getUrlTrackPageView($documentTitle); - return $this->sendRequest($url); + $url = $this->getUrlTrackPageView($documentTitle); + return $this->sendRequest($url); } - /** - * Tracks an internal Site Search query, and optionally tracks the Search Category, and Search results Count. - * These are used to populate reports in Actions > Site Search. - * - * @param string $keyword Searched query on the site - * @param string $category Optional, Search engine category if applicable - * @param int $countResults results displayed on the search result page. Used to track "zero result" keywords. - * - * @return mixed Response or true if using bulk requests. - */ - public function doTrackSiteSearch( $keyword, $category = '', $countResults = false ) - { - $url = $this->getUrlTrackSiteSearch($keyword, $category, $countResults); - return $this->sendRequest($url); - } + /** + * Tracks an internal Site Search query, and optionally tracks the Search Category, and Search results Count. + * These are used to populate reports in Actions > Site Search. + * + * @param string $keyword Searched query on the site + * @param string $category Optional, Search engine category if applicable + * @param int $countResults results displayed on the search result page. Used to track "zero result" keywords. + * + * @return mixed Response or true if using bulk requests. + */ + public function doTrackSiteSearch($keyword, $category = '', $countResults = false) + { + $url = $this->getUrlTrackSiteSearch($keyword, $category, $countResults); + return $this->sendRequest($url); + } /** * Records a Goal conversion - * + * * @param int $idGoal Id Goal to record a conversion * @param float $revenue Revenue for this conversion * @return mixed Response or true if using bulk request */ public function doTrackGoal($idGoal, $revenue = 0.0) { - $url = $this->getUrlTrackGoal($idGoal, $revenue); - return $this->sendRequest($url); + $url = $this->getUrlTrackGoal($idGoal, $revenue); + return $this->sendRequest($url); } - + /** * Tracks a download or outlink - * + * * @param string $actionUrl URL of the download or outlink * @param string $actionType Type of the action: 'download' or 'link' * @return mixed Response or true if using bulk request @@ -417,270 +403,257 @@ class PiwikTracker public function doTrackAction($actionUrl, $actionType) { // Referrer could be udpated to be the current URL temporarily (to mimic JS behavior) - $url = $this->getUrlTrackAction($actionUrl, $actionType); - return $this->sendRequest($url); + $url = $this->getUrlTrackAction($actionUrl, $actionType); + return $this->sendRequest($url); } /** * Adds an item in the Ecommerce order. - * + * * This should be called before doTrackEcommerceOrder(), or before doTrackEcommerceCartUpdate(). * This function can be called for all individual products in the cart (or order). * SKU parameter is mandatory. Other parameters are optional (set to false if value not known). * Ecommerce items added via this function are automatically cleared when doTrackEcommerceOrder() or getUrlTrackEcommerceOrder() is called. - * - * @param string $sku (required) SKU, Product identifier + * + * @param string $sku (required) SKU, Product identifier * @param string $name (optional) Product name * @param string|array $category (optional) Product category, or array of product categories (up to 5 categories can be specified for a given product) * @param float|int $price (optional) Individual product price (supports integer and decimal prices) * @param int $quantity (optional) Product quantity. If not specified, will default to 1 in the Reports - * @throws Exception + * @throws Exception */ public function addEcommerceItem($sku, $name = '', $category = '', $price = 0.0, $quantity = 1) { - if(empty($sku)) - { - throw new Exception("You must specify a SKU for the Ecommerce item"); - } - $this->ecommerceItems[$sku] = array( $sku, $name, $category, $price, $quantity ); + if (empty($sku)) { + throw new Exception("You must specify a SKU for the Ecommerce item"); + } + $this->ecommerceItems[$sku] = array($sku, $name, $category, $price, $quantity); } - - /** - * Tracks a Cart Update (add item, remove item, update item). - * - * On every Cart update, you must call addEcommerceItem() for each item (product) in the cart, - * including the items that haven't been updated since the last cart update. - * Items which were in the previous cart and are not sent in later Cart updates will be deleted from the cart (in the database). - * - * @param float $grandTotal Cart grandTotal (typically the sum of all items' prices) - * @return mixed Response or true if using bulk request - */ + + /** + * Tracks a Cart Update (add item, remove item, update item). + * + * On every Cart update, you must call addEcommerceItem() for each item (product) in the cart, + * including the items that haven't been updated since the last cart update. + * Items which were in the previous cart and are not sent in later Cart updates will be deleted from the cart (in the database). + * + * @param float $grandTotal Cart grandTotal (typically the sum of all items' prices) + * @return mixed Response or true if using bulk request + */ public function doTrackEcommerceCartUpdate($grandTotal) { - $url = $this->getUrlTrackEcommerceCartUpdate($grandTotal); - return $this->sendRequest($url); + $url = $this->getUrlTrackEcommerceCartUpdate($grandTotal); + return $this->sendRequest($url); } - + /** * Sends all stored tracking actions at once. Only has an effect if bulk tracking is enabled. - * + * * To enable bulk tracking, call enableBulkTracking(). * - * @throws Exception + * @throws Exception * @return string Response */ public function doBulkTrack() { - if (empty($this->token_auth)) - { - throw new Exception("Token auth is required for bulk tracking."); - } - - if (empty($this->storedTrackingActions)) - { - throw new Exception("Error: you must call the function doTrackPageView or doTrackGoal from this class, before calling this method doBulkTrack()"); - } - - $data = array('requests' => $this->storedTrackingActions, 'token_auth' => $this->token_auth); - - $postData = json_encode($data); - $response = $this->sendRequest($this->getBaseUrl(), 'POST', $postData, $force = true); - - $this->storedTrackingActions = array(); - - return $response; + if (empty($this->token_auth)) { + throw new Exception("Token auth is required for bulk tracking."); + } + + if (empty($this->storedTrackingActions)) { + throw new Exception("Error: you must call the function doTrackPageView or doTrackGoal from this class, before calling this method doBulkTrack()"); + } + + $data = array('requests' => $this->storedTrackingActions, 'token_auth' => $this->token_auth); + + $postData = json_encode($data); + $response = $this->sendRequest($this->getBaseUrl(), 'POST', $postData, $force = true); + + $this->storedTrackingActions = array(); + + return $response; } - - /** - * Tracks an Ecommerce order. - * - * If the Ecommerce order contains items (products), you must call first the addEcommerceItem() for each item in the order. - * All revenues (grandTotal, subTotal, tax, shipping, discount) will be individually summed and reported in Piwik reports. - * Only the parameters $orderId and $grandTotal are required. - * - * @param string|int $orderId (required) Unique Order ID. - * This will be used to count this order only once in the event the order page is reloaded several times. - * orderId must be unique for each transaction, even on different days, or the transaction will not be recorded by Piwik. - * @param float $grandTotal (required) Grand Total revenue of the transaction (including tax, shipping, etc.) - * @param float $subTotal (optional) Sub total amount, typically the sum of items prices for all items in this order (before Tax and Shipping costs are applied) - * @param float $tax (optional) Tax amount for this order - * @param float $shipping (optional) Shipping amount for this order - * @param float $discount (optional) Discounted amount in this order - * @return mixed Response or true if using bulk request + + /** + * Tracks an Ecommerce order. + * + * If the Ecommerce order contains items (products), you must call first the addEcommerceItem() for each item in the order. + * All revenues (grandTotal, subTotal, tax, shipping, discount) will be individually summed and reported in Piwik reports. + * Only the parameters $orderId and $grandTotal are required. + * + * @param string|int $orderId (required) Unique Order ID. + * This will be used to count this order only once in the event the order page is reloaded several times. + * orderId must be unique for each transaction, even on different days, or the transaction will not be recorded by Piwik. + * @param float $grandTotal (required) Grand Total revenue of the transaction (including tax, shipping, etc.) + * @param float $subTotal (optional) Sub total amount, typically the sum of items prices for all items in this order (before Tax and Shipping costs are applied) + * @param float $tax (optional) Tax amount for this order + * @param float $shipping (optional) Shipping amount for this order + * @param float $discount (optional) Discounted amount in this order + * @return mixed Response or true if using bulk request */ public function doTrackEcommerceOrder($orderId, $grandTotal, $subTotal = 0.0, $tax = 0.0, $shipping = 0.0, $discount = 0.0) { - $url = $this->getUrlTrackEcommerceOrder($orderId, $grandTotal, $subTotal, $tax, $shipping, $discount); - return $this->sendRequest($url); + $url = $this->getUrlTrackEcommerceOrder($orderId, $grandTotal, $subTotal, $tax, $shipping, $discount); + return $this->sendRequest($url); } - + /** * Sets the current page view as an item (product) page view, or an Ecommerce Category page view. - * - * This must be called before doTrackPageView() on this product/category page. + * + * This must be called before doTrackPageView() on this product/category page. * It will set 3 custom variables of scope "page" with the SKU, Name and Category for this page view. * Note: Custom Variables of scope "page" slots 3, 4 and 5 will be used. - * + * * On a category page, you may set the parameter $category only and set the other parameters to false. - * - * Tracking Product/Category page views will allow Piwik to report on Product & Categories + * + * Tracking Product/Category page views will allow Piwik to report on Product & Categories * conversion rates (Conversion rate = Ecommerce orders containing this product or category / Visits to the product or category) - * + * * @param string $sku Product SKU being viewed * @param string $name Product Name being viewed - * @param string|array $category Category being viewed. On a Product page, this is the product's category. - * You can also specify an array of up to 5 categories for a given page view. + * @param string|array $category Category being viewed. On a Product page, this is the product's category. + * You can also specify an array of up to 5 categories for a given page view. * @param float $price Specify the price at which the item was displayed */ public function setEcommerceView($sku = '', $name = '', $category = '', $price = 0.0) { - if(!empty($category)) { - if(is_array($category)) { - $category = json_encode($category); - } - } else { - $category = ""; - } - $this->pageCustomVar[5] = array('_pkc', $category); - - if(!empty($price)) { - $this->pageCustomVar[2] = array('_pkp', (float)$price); - } - - // On a category page, do not record "Product name not defined" - if(empty($sku) && empty($name)) - { - return; - } - if(!empty($sku)) { - $this->pageCustomVar[3] = array('_pks', $sku); - } - if(empty($name)) { - $name = ""; - } - $this->pageCustomVar[4] = array('_pkn', $name); + if (!empty($category)) { + if (is_array($category)) { + $category = json_encode($category); + } + } else { + $category = ""; + } + $this->pageCustomVar[5] = array('_pkc', $category); + + if (!empty($price)) { + $this->pageCustomVar[2] = array('_pkp', (float)$price); + } + + // On a category page, do not record "Product name not defined" + if (empty($sku) && empty($name)) { + return; + } + if (!empty($sku)) { + $this->pageCustomVar[3] = array('_pks', $sku); + } + if (empty($name)) { + $name = ""; + } + $this->pageCustomVar[4] = array('_pkn', $name); } - + /** * Returns URL used to track Ecommerce Cart updates - * Calling this function will reinitializes the property ecommerceItems to empty array - * so items will have to be added again via addEcommerceItem() + * Calling this function will reinitializes the property ecommerceItems to empty array + * so items will have to be added again via addEcommerceItem() * @ignore */ public function getUrlTrackEcommerceCartUpdate($grandTotal) { - $url = $this->getUrlTrackEcommerce($grandTotal); - return $url; + $url = $this->getUrlTrackEcommerce($grandTotal); + return $url; } - + /** * Returns URL used to track Ecommerce Orders - * Calling this function will reinitializes the property ecommerceItems to empty array - * so items will have to be added again via addEcommerceItem() + * Calling this function will reinitializes the property ecommerceItems to empty array + * so items will have to be added again via addEcommerceItem() * @ignore */ public function getUrlTrackEcommerceOrder($orderId, $grandTotal, $subTotal = 0.0, $tax = 0.0, $shipping = 0.0, $discount = 0.0) { - if(empty($orderId)) - { - throw new Exception("You must specifiy an orderId for the Ecommerce order"); - } - $url = $this->getUrlTrackEcommerce($grandTotal, $subTotal, $tax, $shipping, $discount); - $url .= '&ec_id=' . urlencode($orderId); - $this->ecommerceLastOrderTimestamp = $this->getTimestamp(); - return $url; + if (empty($orderId)) { + throw new Exception("You must specifiy an orderId for the Ecommerce order"); + } + $url = $this->getUrlTrackEcommerce($grandTotal, $subTotal, $tax, $shipping, $discount); + $url .= '&ec_id=' . urlencode($orderId); + $this->ecommerceLastOrderTimestamp = $this->getTimestamp(); + return $url; } - + /** * Returns URL used to track Ecommerce orders - * Calling this function will reinitializes the property ecommerceItems to empty array - * so items will have to be added again via addEcommerceItem() + * Calling this function will reinitializes the property ecommerceItems to empty array + * so items will have to be added again via addEcommerceItem() * @ignore */ protected function getUrlTrackEcommerce($grandTotal, $subTotal = 0.0, $tax = 0.0, $shipping = 0.0, $discount = 0.0) { - if(!is_numeric($grandTotal)) - { - throw new Exception("You must specifiy a grandTotal for the Ecommerce order (or Cart update)"); - } - - $url = $this->getRequest( $this->idSite ); - $url .= '&idgoal=0'; - if(!empty($grandTotal)) - { - $url .= '&revenue='.$grandTotal; - } - if(!empty($subTotal)) - { - $url .= '&ec_st='.$subTotal; - } - if(!empty($tax)) - { - $url .= '&ec_tx='.$tax; - } - if(!empty($shipping)) - { - $url .= '&ec_sh='.$shipping; - } - if(!empty($discount)) - { - $url .= '&ec_dt='.$discount; - } - if(!empty($this->ecommerceItems)) - { - // Removing the SKU index in the array before JSON encoding - $items = array(); - foreach($this->ecommerceItems as $item) - { - $items[] = $item; - } - $url .= '&ec_items='. urlencode(json_encode($items)); - } - $this->ecommerceItems = array(); - return $url; + if (!is_numeric($grandTotal)) { + throw new Exception("You must specifiy a grandTotal for the Ecommerce order (or Cart update)"); + } + + $url = $this->getRequest($this->idSite); + $url .= '&idgoal=0'; + if (!empty($grandTotal)) { + $url .= '&revenue=' . $grandTotal; + } + if (!empty($subTotal)) { + $url .= '&ec_st=' . $subTotal; + } + if (!empty($tax)) { + $url .= '&ec_tx=' . $tax; + } + if (!empty($shipping)) { + $url .= '&ec_sh=' . $shipping; + } + if (!empty($discount)) { + $url .= '&ec_dt=' . $discount; + } + if (!empty($this->ecommerceItems)) { + // Removing the SKU index in the array before JSON encoding + $items = array(); + foreach ($this->ecommerceItems as $item) { + $items[] = $item; + } + $url .= '&ec_items=' . urlencode(json_encode($items)); + } + $this->ecommerceItems = array(); + return $url; } - + /** - * Builds URL to track a page view. - * + * Builds URL to track a page view. + * * @see doTrackPageView() * @param string $documentTitle Page view name as it will appear in Piwik reports * @return string URL to piwik.php with all parameters set to track the pageview */ - public function getUrlTrackPageView( $documentTitle = '' ) + public function getUrlTrackPageView($documentTitle = '') { - $url = $this->getRequest( $this->idSite ); - if(strlen($documentTitle) > 0) { - $url .= '&action_name=' . urlencode($documentTitle); - } - return $url; + $url = $this->getRequest($this->idSite); + if (strlen($documentTitle) > 0) { + $url .= '&action_name=' . urlencode($documentTitle); + } + return $url; } - /** - * Builds URL to track a site search. - * - * @see doTrackSiteSearch() - * @param string $keyword - * @param string $category - * @param int $countResults - * @return string - */ - public function getUrlTrackSiteSearch($keyword, $category, $countResults) - { - $url = $this->getRequest( $this->idSite ); - $url .= '&search=' . urlencode($keyword); - if(strlen($category) > 0) { - $url .= '&search_cat=' . urlencode($category); - } - if(!empty($countResults) || $countResults === 0) { - $url .= '&search_count=' . (int)$countResults; - } - return $url; - } - - /** - * Builds URL to track a goal with idGoal and revenue. - * + /** + * Builds URL to track a site search. + * + * @see doTrackSiteSearch() + * @param string $keyword + * @param string $category + * @param int $countResults + * @return string + */ + public function getUrlTrackSiteSearch($keyword, $category, $countResults) + { + $url = $this->getRequest($this->idSite); + $url .= '&search=' . urlencode($keyword); + if (strlen($category) > 0) { + $url .= '&search_cat=' . urlencode($category); + } + if (!empty($countResults) || $countResults === 0) { + $url .= '&search_count=' . (int)$countResults; + } + return $url; + } + + /** + * Builds URL to track a goal with idGoal and revenue. + * * @see doTrackGoal() * @param int $idGoal Id Goal to record a conversion * @param float $revenue Revenue for this conversion @@ -688,17 +661,17 @@ class PiwikTracker */ public function getUrlTrackGoal($idGoal, $revenue = 0.0) { - $url = $this->getRequest( $this->idSite ); - $url .= '&idgoal=' . $idGoal; - if(!empty($revenue)) { - $url .= '&revenue=' . $revenue; - } - return $url; + $url = $this->getRequest($this->idSite); + $url .= '&idgoal=' . $idGoal; + if (!empty($revenue)) { + $url .= '&revenue=' . $revenue; + } + return $url; } - + /** - * Builds URL to track a new action. - * + * Builds URL to track a new action. + * * @see doTrackAction() * @param string $actionUrl URL of the download or outlink * @param string $actionType Type of the action: 'download' or 'link' @@ -706,140 +679,137 @@ class PiwikTracker */ public function getUrlTrackAction($actionUrl, $actionType) { - $url = $this->getRequest( $this->idSite ); - $url .= '&'.$actionType.'=' . $actionUrl; - return $url; + $url = $this->getRequest($this->idSite); + $url .= '&' . $actionType . '=' . $actionUrl; + return $url; } /** - * Overrides server date and time for the tracking requests. - * By default Piwik will track requests for the "current datetime" but this function allows you + * Overrides server date and time for the tracking requests. + * By default Piwik will track requests for the "current datetime" but this function allows you * to track visits in the past. All times are in UTC. - * + * * Allowed only for Super User, must be used along with setTokenAuth() * @see setTokenAuth() * @param string $dateTime Date with the format 'Y-m-d H:i:s', or a UNIX timestamp */ public function setForceVisitDateTime($dateTime) { - $this->forcedDatetime = $dateTime; + $this->forcedDatetime = $dateTime; } - + /** * Overrides IP address - * + * * Allowed only for Super User, must be used along with setTokenAuth() * @see setTokenAuth() * @param string $ip IP string, eg. 130.54.2.1 */ public function setIp($ip) { - $this->ip = $ip; + $this->ip = $ip; } - + /** * Forces the requests to be recorded for the specified Visitor ID * rather than using the heuristics based on IP and other attributes. - * + * * This is typically used with the Javascript getVisitorId() function. - * + * * Allowed only for Admin/Super User, must be used along with setTokenAuth(). * @see setTokenAuth() * @param string $visitorId 16 hexadecimal characters visitor ID, eg. "33c31e01394bdc63" - * @throws Exception + * @throws Exception */ public function setVisitorId($visitorId) { $hexChars = '01234567890abcdefABCDEF'; - if(strlen($visitorId) != self::LENGTH_VISITOR_ID - || strspn($visitorId, $hexChars) !== strlen($visitorId)) - { - throw new Exception("setVisitorId() expects a " - .self::LENGTH_VISITOR_ID - ." characters hexadecimal string (containing only the following: " - .$hexChars - .")"); - } - $this->forcedVisitorId = $visitorId; + if (strlen($visitorId) != self::LENGTH_VISITOR_ID + || strspn($visitorId, $hexChars) !== strlen($visitorId) + ) { + throw new Exception("setVisitorId() expects a " + . self::LENGTH_VISITOR_ID + . " characters hexadecimal string (containing only the following: " + . $hexChars + . ")"); + } + $this->forcedVisitorId = $visitorId; } - + /** - * If the user initiating the request has the Piwik first party cookie, + * If the user initiating the request has the Piwik first party cookie, * this function will try and return the ID parsed from this first party cookie (found in $_COOKIE). - * + * * If you call this function from a server, where the call is triggered by a cron or script - * not initiated by the actual visitor being tracked, then it will return + * not initiated by the actual visitor being tracked, then it will return * the random Visitor ID that was assigned to this visit object. - * + * * This can be used if you wish to record more visits, actions or goals for this visitor ID later on. - * + * * @return string 16 hex chars visitor ID string */ public function getVisitorId() { - if(!empty($this->forcedVisitorId)) - { - return $this->forcedVisitorId; - } - - $idCookieName = 'id.'.$this->idSite.'.'; - $idCookie = $this->getCookieMatchingName($idCookieName); - if($idCookie !== false) - { - $visitorId = substr($idCookie, 0, strpos($idCookie, '.')); - if(strlen($visitorId) == self::LENGTH_VISITOR_ID) - { - return $visitorId; - } - } - return $this->visitorId; + if (!empty($this->forcedVisitorId)) { + return $this->forcedVisitorId; + } + + $idCookieName = 'id.' . $this->idSite . '.'; + $idCookie = $this->getCookieMatchingName($idCookieName); + if ($idCookie !== false) { + $visitorId = substr($idCookie, 0, strpos($idCookie, '.')); + if (strlen($visitorId) == self::LENGTH_VISITOR_ID) { + return $visitorId; + } + } + return $this->visitorId; } /** * Returns the currently assigned Attribution Information stored in a first party cookie. - * + * * This function will only work if the user is initiating the current request, and his cookies * can be read by PHP from the $_COOKIE array. - * + * * @return string JSON Encoded string containing the Referer information for Goal conversion attribution. * Will return false if the cookie could not be found * @see Piwik.js getAttributionInfo() */ public function getAttributionInfo() { - $attributionCookieName = 'ref.'.$this->idSite.'.'; - return $this->getCookieMatchingName($attributionCookieName); + $attributionCookieName = 'ref.' . $this->idSite . '.'; + return $this->getCookieMatchingName($attributionCookieName); + } + + /** + * Some Tracking API functionnality requires express authentication, using either the + * Super User token_auth, or a user with 'admin' access to the website. + * + * The following features require access: + * - force the visitor IP + * - force the date & time of the tracking requests rather than track for the current datetime + * - force Piwik to track the requests to a specific VisitorId rather than use the standard visitor matching heuristic + * + * @param string $token_auth token_auth 32 chars token_auth string + */ + public function setTokenAuth($token_auth) + { + $this->token_auth = $token_auth; } - - /** - * Some Tracking API functionnality requires express authentication, using either the - * Super User token_auth, or a user with 'admin' access to the website. - * - * The following features require access: - * - force the visitor IP - * - force the date & time of the tracking requests rather than track for the current datetime - * - force Piwik to track the requests to a specific VisitorId rather than use the standard visitor matching heuristic - * - * @param string $token_auth token_auth 32 chars token_auth string - */ - public function setTokenAuth($token_auth) - { - $this->token_auth = $token_auth; - } /** * Sets local visitor time - * + * * @param string $time HH:MM:SS format */ public function setLocalTime($time) { - list($hour, $minute, $second) = explode(':', $time); - $this->localHour = (int)$hour; - $this->localMinute = (int)$minute; - $this->localSecond = (int)$second; + list($hour, $minute, $second) = explode(':', $time); + $this->localHour = (int)$hour; + $this->localMinute = (int)$minute; + $this->localSecond = (int)$second; } - + /** * Sets user resolution width and height. * @@ -848,32 +818,32 @@ class PiwikTracker */ public function setResolution($width, $height) { - $this->width = $width; - $this->height = $height; + $this->width = $width; + $this->height = $height; } - + /** - * Sets if the browser supports cookies + * Sets if the browser supports cookies * This is reported in "List of plugins" report in Piwik. * * @param bool $bool */ - public function setBrowserHasCookies( $bool ) + public function setBrowserHasCookies($bool) { - $this->hasCookies = $bool ; + $this->hasCookies = $bool; } - + /** - * Will append a custom string at the end of the Tracking request. + * Will append a custom string at the end of the Tracking request. * @param string $string */ - public function setDebugStringAppend( $string ) + public function setDebugStringAppend($string) { - $this->DEBUG_APPEND_URL = $string; + $this->DEBUG_APPEND_URL = $string; } - + /** - * Sets visitor browser supported plugins + * Sets visitor browser supported plugins * * @param bool $flash * @param bool $java @@ -887,374 +857,352 @@ class PiwikTracker */ public function setPlugins($flash = false, $java = false, $director = false, $quickTime = false, $realPlayer = false, $pdf = false, $windowsMedia = false, $gears = false, $silverlight = false) { - $this->plugins = - '&fla='.(int)$flash. - '&java='.(int)$java. - '&dir='.(int)$director. - '&qt='.(int)$quickTime. - '&realp='.(int)$realPlayer. - '&pdf='.(int)$pdf. - '&wma='.(int)$windowsMedia. - '&gears='.(int)$gears. - '&ag='.(int)$silverlight - ; + $this->plugins = + '&fla=' . (int)$flash . + '&java=' . (int)$java . + '&dir=' . (int)$director . + '&qt=' . (int)$quickTime . + '&realp=' . (int)$realPlayer . + '&pdf=' . (int)$pdf . + '&wma=' . (int)$windowsMedia . + '&gears=' . (int)$gears . + '&ag=' . (int)$silverlight; } - /** - * By default, PiwikTracker will read third party cookies - * from the response and sets them in the next request. - * This can be disabled by calling this function. - */ + /** + * By default, PiwikTracker will read third party cookies + * from the response and sets them in the next request. + * This can be disabled by calling this function. + */ public function disableCookieSupport() { - $this->cookieSupport = false; + $this->cookieSupport = false; } - + /** * Returns the maximum number of seconds the tracker will spend waiting for a response * from Piwik. Defaults to 600 seconds. */ public function getRequestTimeout() { - return $this->requestTimeout; + return $this->requestTimeout; } - - /** - * Sets the maximum number of seconds that the tracker will spend waiting for a response - * from Piwik. - * - * @param int $timeout - * @throws Exception - */ - public function setRequestTimeout( $timeout ) + + /** + * Sets the maximum number of seconds that the tracker will spend waiting for a response + * from Piwik. + * + * @param int $timeout + * @throws Exception + */ + public function setRequestTimeout($timeout) { - if (!is_int($timeout) || $timeout < 0) - { - throw new Exception("Invalid value supplied for request timeout: $timeout"); - } - - $this->requestTimeout = $timeout; + if (!is_int($timeout) || $timeout < 0) { + throw new Exception("Invalid value supplied for request timeout: $timeout"); + } + + $this->requestTimeout = $timeout; } - + /** * @ignore */ - protected function sendRequest( $url, $method = 'GET', $data = null, $force = false ) + protected function sendRequest($url, $method = 'GET', $data = null, $force = false) { - // if doing a bulk request, store the url - if ($this->doBulkRequests && !$force) - { - $this->storedTrackingActions[] - = $url - . (!empty($this->userAgent) ? ('&ua='.urlencode($this->userAgent)) : '') - . (!empty($this->acceptLanguage) ? ('&lang='.urlencode($this->acceptLanguage)) : '') - ; - return true; - } - - $response = ''; - - if(!$this->cookieSupport) - { - $this->requestCookie = ''; - } - if(function_exists('curl_init')) - { - $options = array( - CURLOPT_URL => $url, - CURLOPT_USERAGENT => $this->userAgent, - CURLOPT_HEADER => true, - CURLOPT_TIMEOUT => $this->requestTimeout, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_HTTPHEADER => array( - 'Accept-Language: ' . $this->acceptLanguage, - 'Cookie: '. $this->requestCookie, - )); - - switch ($method) - { - case 'POST': - $options[CURLOPT_POST] = TRUE; - break; - default: - break; - } - - // only supports JSON data - if (!empty($data)) - { - $options[CURLOPT_HTTPHEADER][] = 'Content-Type: application/json'; - $options[CURLOPT_HTTPHEADER][] = 'Expect:'; - $options[CURLOPT_POSTFIELDS] = $data; - } - - $ch = curl_init(); - curl_setopt_array($ch, $options); - ob_start(); - $response = @curl_exec($ch); - ob_end_clean(); - $header = $content = ''; - if(!empty($response)) - { - list($header,$content) = explode("\r\n\r\n", $response, $limitCount = 2); - } - } - else if(function_exists('stream_context_create')) - { - $stream_options = array( - 'http' => array( - 'method' => $method, - 'user_agent' => $this->userAgent, - 'header' => "Accept-Language: " . $this->acceptLanguage . "\r\n" . - "Cookie: ".$this->requestCookie. "\r\n" , - 'timeout' => $this->requestTimeout, // PHP 5.2.1 - ) - ); - - // only supports JSON data - if (!empty($data)) - { - $stream_options['http']['header'] .= "Content-Type: application/json \r\n"; - $stream_options['http']['content'] = $data; - } - - $ctx = stream_context_create($stream_options); - $response = file_get_contents($url, 0, $ctx); - $header = implode("\r\n", $http_response_header); - $content = $response; - } - // The cookie in the response will be set in the next request - preg_match_all('/^Set-Cookie: (.*?);/m', $header, $cookie); - if(!empty($cookie[1])) - { - // in case several cookies returned, we keep only the latest one (ie. XDEBUG puts its cookie first in the list) - if(is_array($cookie[1])) - { - $cookie = end($cookie[1]); - } - else - { - $cookie = $cookie[1]; - } - // XDEBUG is a PHP Debugger - if(strpos($cookie, 'XDEBUG') === false) - { - $this->requestCookie = $cookie; - } - } - - return $content; + // if doing a bulk request, store the url + if ($this->doBulkRequests && !$force) { + $this->storedTrackingActions[] + = $url + . (!empty($this->userAgent) ? ('&ua=' . urlencode($this->userAgent)) : '') + . (!empty($this->acceptLanguage) ? ('&lang=' . urlencode($this->acceptLanguage)) : ''); + return true; + } + + $response = ''; + + if (!$this->cookieSupport) { + $this->requestCookie = ''; + } + if (function_exists('curl_init')) { + $options = array( + CURLOPT_URL => $url, + CURLOPT_USERAGENT => $this->userAgent, + CURLOPT_HEADER => true, + CURLOPT_TIMEOUT => $this->requestTimeout, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HTTPHEADER => array( + 'Accept-Language: ' . $this->acceptLanguage, + 'Cookie: ' . $this->requestCookie, + )); + + switch ($method) { + case 'POST': + $options[CURLOPT_POST] = TRUE; + break; + default: + break; + } + + // only supports JSON data + if (!empty($data)) { + $options[CURLOPT_HTTPHEADER][] = 'Content-Type: application/json'; + $options[CURLOPT_HTTPHEADER][] = 'Expect:'; + $options[CURLOPT_POSTFIELDS] = $data; + } + + $ch = curl_init(); + curl_setopt_array($ch, $options); + ob_start(); + $response = @curl_exec($ch); + ob_end_clean(); + $header = $content = ''; + if (!empty($response)) { + list($header, $content) = explode("\r\n\r\n", $response, $limitCount = 2); + } + } else if (function_exists('stream_context_create')) { + $stream_options = array( + 'http' => array( + 'method' => $method, + 'user_agent' => $this->userAgent, + 'header' => "Accept-Language: " . $this->acceptLanguage . "\r\n" . + "Cookie: " . $this->requestCookie . "\r\n", + 'timeout' => $this->requestTimeout, // PHP 5.2.1 + ) + ); + + // only supports JSON data + if (!empty($data)) { + $stream_options['http']['header'] .= "Content-Type: application/json \r\n"; + $stream_options['http']['content'] = $data; + } + + $ctx = stream_context_create($stream_options); + $response = file_get_contents($url, 0, $ctx); + $header = implode("\r\n", $http_response_header); + $content = $response; + } + // The cookie in the response will be set in the next request + preg_match_all('/^Set-Cookie: (.*?);/m', $header, $cookie); + if (!empty($cookie[1])) { + // in case several cookies returned, we keep only the latest one (ie. XDEBUG puts its cookie first in the list) + if (is_array($cookie[1])) { + $cookie = end($cookie[1]); + } else { + $cookie = $cookie[1]; + } + // XDEBUG is a PHP Debugger + if (strpos($cookie, 'XDEBUG') === false) { + $this->requestCookie = $cookie; + } + } + + return $content; } - + /** * Returns current timestamp, or forced timestamp/datetime if it was set * @return string|int */ protected function getTimestamp() { - return !empty($this->forcedDatetime) - ? strtotime($this->forcedDatetime) - : time(); + return !empty($this->forcedDatetime) + ? strtotime($this->forcedDatetime) + : time(); } - + /** * Returns the base URL for the piwik server. */ protected function getBaseUrl() { - if(empty(self::$URL)) - { - throw new Exception('You must first set the Piwik Tracker URL by calling PiwikTracker::$URL = \'http://your-website.org/piwik/\';'); - } - if(strpos(self::$URL, '/piwik.php') === false - && strpos(self::$URL, '/proxy-piwik.php') === false) - { - self::$URL .= '/piwik.php'; - } - return self::$URL; + if (empty(self::$URL)) { + throw new Exception('You must first set the Piwik Tracker URL by calling PiwikTracker::$URL = \'http://your-website.org/piwik/\';'); + } + if (strpos(self::$URL, '/piwik.php') === false + && strpos(self::$URL, '/proxy-piwik.php') === false + ) { + self::$URL .= '/piwik.php'; + } + return self::$URL; } - + /** * @ignore */ - protected function getRequest( $idSite ) + protected function getRequest($idSite) { - $url = $this->getBaseUrl() . - '?idsite=' . $idSite . - '&rec=1' . - '&apiv=' . self::VERSION . - '&r=' . substr(strval(mt_rand()), 2, 6) . - - // XDEBUG_SESSIONS_START and KEY are related to the PHP Debugger, this can be ignored in other languages - (!empty($_GET['XDEBUG_SESSION_START']) ? '&XDEBUG_SESSION_START=' . @urlencode($_GET['XDEBUG_SESSION_START']) : '') . - (!empty($_GET['KEY']) ? '&KEY=' . @urlencode($_GET['KEY']) : '') . - - // Only allowed for Super User, token_auth required, - (!empty($this->ip) ? '&cip=' . $this->ip : '') . - (!empty($this->forcedVisitorId) ? '&cid=' . $this->forcedVisitorId : '&_id=' . $this->visitorId) . - (!empty($this->forcedDatetime) ? '&cdt=' . urlencode($this->forcedDatetime) : '') . - ((!empty($this->token_auth) && !$this->doBulkRequests) ? '&token_auth=' . urlencode($this->token_auth) : '') . - - // These parameters are set by the JS, but optional when using API - (!empty($this->plugins) ? $this->plugins : '') . - (($this->localHour !== false && $this->localMinute !== false && $this->localSecond !== false) ? '&h=' . $this->localHour . '&m=' . $this->localMinute . '&s=' . $this->localSecond : '' ). - (!empty($this->width) && !empty($this->height) ? '&res=' . $this->width . 'x' . $this->height : '') . - (!empty($this->hasCookies) ? '&cookie=' . $this->hasCookies : '') . - (!empty($this->ecommerceLastOrderTimestamp) ? '&_ects=' . urlencode($this->ecommerceLastOrderTimestamp) : '') . - - // Various important attributes - (!empty($this->customData) ? '&data=' . $this->customData : '') . - (!empty($this->visitorCustomVar) ? '&_cvar=' . urlencode(json_encode($this->visitorCustomVar)) : '') . - (!empty($this->pageCustomVar) ? '&cvar=' . urlencode(json_encode($this->pageCustomVar)) : '') . - (!empty($this->generationTime) ? '&generation_time_ms=' . ((int)$this->generationTime) : '') . - - // URL parameters - '&url=' . urlencode($this->pageUrl) . - '&urlref=' . urlencode($this->urlReferrer) . - ((!empty($this->pageCharset) && $this->pageCharset != self::DEFAULT_CHARSET_PARAMETER_VALUES) ? '&cs=' . $this->pageCharset : '') . - - // Attribution information, so that Goal conversions are attributed to the right referrer or campaign - // Campaign name - (!empty($this->attributionInfo[0]) ? '&_rcn=' . urlencode($this->attributionInfo[0]) : '') . - // Campaign keyword - (!empty($this->attributionInfo[1]) ? '&_rck=' . urlencode($this->attributionInfo[1]) : '') . - // Timestamp at which the referrer was set - (!empty($this->attributionInfo[2]) ? '&_refts=' . $this->attributionInfo[2] : '') . - // Referrer URL - (!empty($this->attributionInfo[3]) ? '&_ref=' . urlencode($this->attributionInfo[3]) : '') . - - // custom location info - (!empty($this->country) ? '&country='.urlencode($this->country) : '') . - (!empty($this->region) ? '®ion='.urlencode($this->region) : '') . - (!empty($this->city) ? '&city='.urlencode($this->city) : '') . - (!empty($this->lat) ? '&lat='.urlencode($this->lat) : '') . - (!empty($this->long) ? '&long='.urlencode($this->long) : '') . - - // DEBUG - $this->DEBUG_APPEND_URL - ; - // Reset page level custom variables after this page view - $this->pageCustomVar = false; - - return $url; + $url = $this->getBaseUrl() . + '?idsite=' . $idSite . + '&rec=1' . + '&apiv=' . self::VERSION . + '&r=' . substr(strval(mt_rand()), 2, 6) . + + // XDEBUG_SESSIONS_START and KEY are related to the PHP Debugger, this can be ignored in other languages + (!empty($_GET['XDEBUG_SESSION_START']) ? '&XDEBUG_SESSION_START=' . @urlencode($_GET['XDEBUG_SESSION_START']) : '') . + (!empty($_GET['KEY']) ? '&KEY=' . @urlencode($_GET['KEY']) : '') . + + // Only allowed for Super User, token_auth required, + (!empty($this->ip) ? '&cip=' . $this->ip : '') . + (!empty($this->forcedVisitorId) ? '&cid=' . $this->forcedVisitorId : '&_id=' . $this->visitorId) . + (!empty($this->forcedDatetime) ? '&cdt=' . urlencode($this->forcedDatetime) : '') . + ((!empty($this->token_auth) && !$this->doBulkRequests) ? '&token_auth=' . urlencode($this->token_auth) : '') . + + // These parameters are set by the JS, but optional when using API + (!empty($this->plugins) ? $this->plugins : '') . + (($this->localHour !== false && $this->localMinute !== false && $this->localSecond !== false) ? '&h=' . $this->localHour . '&m=' . $this->localMinute . '&s=' . $this->localSecond : '') . + (!empty($this->width) && !empty($this->height) ? '&res=' . $this->width . 'x' . $this->height : '') . + (!empty($this->hasCookies) ? '&cookie=' . $this->hasCookies : '') . + (!empty($this->ecommerceLastOrderTimestamp) ? '&_ects=' . urlencode($this->ecommerceLastOrderTimestamp) : '') . + + // Various important attributes + (!empty($this->customData) ? '&data=' . $this->customData : '') . + (!empty($this->visitorCustomVar) ? '&_cvar=' . urlencode(json_encode($this->visitorCustomVar)) : '') . + (!empty($this->pageCustomVar) ? '&cvar=' . urlencode(json_encode($this->pageCustomVar)) : '') . + (!empty($this->generationTime) ? '&generation_time_ms=' . ((int)$this->generationTime) : '') . + + // URL parameters + '&url=' . urlencode($this->pageUrl) . + '&urlref=' . urlencode($this->urlReferrer) . + ((!empty($this->pageCharset) && $this->pageCharset != self::DEFAULT_CHARSET_PARAMETER_VALUES) ? '&cs=' . $this->pageCharset : '') . + + // Attribution information, so that Goal conversions are attributed to the right referrer or campaign + // Campaign name + (!empty($this->attributionInfo[0]) ? '&_rcn=' . urlencode($this->attributionInfo[0]) : '') . + // Campaign keyword + (!empty($this->attributionInfo[1]) ? '&_rck=' . urlencode($this->attributionInfo[1]) : '') . + // Timestamp at which the referrer was set + (!empty($this->attributionInfo[2]) ? '&_refts=' . $this->attributionInfo[2] : '') . + // Referrer URL + (!empty($this->attributionInfo[3]) ? '&_ref=' . urlencode($this->attributionInfo[3]) : '') . + + // custom location info + (!empty($this->country) ? '&country=' . urlencode($this->country) : '') . + (!empty($this->region) ? '®ion=' . urlencode($this->region) : '') . + (!empty($this->city) ? '&city=' . urlencode($this->city) : '') . + (!empty($this->lat) ? '&lat=' . urlencode($this->lat) : '') . + (!empty($this->long) ? '&long=' . urlencode($this->long) : '') . + + // DEBUG + $this->DEBUG_APPEND_URL; + // Reset page level custom variables after this page view + $this->pageCustomVar = false; + + return $url; } - - + + /** * Returns a first party cookie which name contains $name - * + * * @param string $name * @return string String value of cookie, or false if not found * @ignore */ protected function getCookieMatchingName($name) { - // Piwik cookie names use dots separators in piwik.js, - // but PHP Replaces . with _ http://www.php.net/manual/en/language.variables.predefined.php#72571 - $name = str_replace('.', '_', $name); - foreach($_COOKIE as $cookieName => $cookieValue) - { - if(strpos($cookieName, $name) !== false) - { - return $cookieValue; - } - } - return false; + // Piwik cookie names use dots separators in piwik.js, + // but PHP Replaces . with _ http://www.php.net/manual/en/language.variables.predefined.php#72571 + $name = str_replace('.', '_', $name); + foreach ($_COOKIE as $cookieName => $cookieValue) { + if (strpos($cookieName, $name) !== false) { + return $cookieValue; + } + } + return false; } - /** - * If current URL is "http://example.org/dir1/dir2/index.php?param1=value1¶m2=value2" - * will return "/dir1/dir2/index.php" - * - * @return string + /** + * If current URL is "http://example.org/dir1/dir2/index.php?param1=value1¶m2=value2" + * will return "/dir1/dir2/index.php" + * + * @return string * @ignore - */ - static protected function getCurrentScriptName() - { - $url = ''; - if( !empty($_SERVER['PATH_INFO']) ) { - $url = $_SERVER['PATH_INFO']; - } - else if( !empty($_SERVER['REQUEST_URI']) ) { - if( ($pos = strpos($_SERVER['REQUEST_URI'], '?')) !== false ) { - $url = substr($_SERVER['REQUEST_URI'], 0, $pos); - } else { - $url = $_SERVER['REQUEST_URI']; - } - } - if(empty($url)) { - $url = $_SERVER['SCRIPT_NAME']; - } - - if($url[0] !== '/') { - $url = '/' . $url; - } - return $url; - } - - /** - * If the current URL is 'http://example.org/dir1/dir2/index.php?param1=value1¶m2=value2" - * will return 'http' - * - * @return string 'https' or 'http' + */ + static protected function getCurrentScriptName() + { + $url = ''; + if (!empty($_SERVER['PATH_INFO'])) { + $url = $_SERVER['PATH_INFO']; + } else if (!empty($_SERVER['REQUEST_URI'])) { + if (($pos = strpos($_SERVER['REQUEST_URI'], '?')) !== false) { + $url = substr($_SERVER['REQUEST_URI'], 0, $pos); + } else { + $url = $_SERVER['REQUEST_URI']; + } + } + if (empty($url)) { + $url = $_SERVER['SCRIPT_NAME']; + } + + if ($url[0] !== '/') { + $url = '/' . $url; + } + return $url; + } + + /** + * If the current URL is 'http://example.org/dir1/dir2/index.php?param1=value1¶m2=value2" + * will return 'http' + * + * @return string 'https' or 'http' * @ignore - */ - static protected function getCurrentScheme() - { - if(isset($_SERVER['HTTPS']) - && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] === true)) - { - return 'https'; - } - return 'http'; - } - - /** - * If current URL is "http://example.org/dir1/dir2/index.php?param1=value1¶m2=value2" - * will return "http://example.org" - * - * @return string + */ + static protected function getCurrentScheme() + { + if (isset($_SERVER['HTTPS']) + && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] === true) + ) { + return 'https'; + } + return 'http'; + } + + /** + * If current URL is "http://example.org/dir1/dir2/index.php?param1=value1¶m2=value2" + * will return "http://example.org" + * + * @return string * @ignore - */ - static protected function getCurrentHost() - { - if(isset($_SERVER['HTTP_HOST'])) { - return $_SERVER['HTTP_HOST']; - } - return 'unknown'; - } - - /** - * If current URL is "http://example.org/dir1/dir2/index.php?param1=value1¶m2=value2" - * will return "?param1=value1¶m2=value2" - * - * @return string + */ + static protected function getCurrentHost() + { + if (isset($_SERVER['HTTP_HOST'])) { + return $_SERVER['HTTP_HOST']; + } + return 'unknown'; + } + + /** + * If current URL is "http://example.org/dir1/dir2/index.php?param1=value1¶m2=value2" + * will return "?param1=value1¶m2=value2" + * + * @return string * @ignore - */ - static protected function getCurrentQueryString() - { - $url = ''; - if(isset($_SERVER['QUERY_STRING']) - && !empty($_SERVER['QUERY_STRING'])) - { - $url .= '?'.$_SERVER['QUERY_STRING']; - } - return $url; - } - - /** - * Returns the current full URL (scheme, host, path and query string. - * - * @return string + */ + static protected function getCurrentQueryString() + { + $url = ''; + if (isset($_SERVER['QUERY_STRING']) + && !empty($_SERVER['QUERY_STRING']) + ) { + $url .= '?' . $_SERVER['QUERY_STRING']; + } + return $url; + } + + /** + * Returns the current full URL (scheme, host, path and query string. + * + * @return string * @ignore - */ + */ static protected function getCurrentUrl() { - return self::getCurrentScheme() . '://' - . self::getCurrentHost() - . self::getCurrentScriptName() - . self::getCurrentQueryString(); - } + return self::getCurrentScheme() . '://' + . self::getCurrentHost() + . self::getCurrentScriptName() + . self::getCurrentQueryString(); + } } /** @@ -1264,10 +1212,10 @@ class PiwikTracker * @param string $documentTitle * @return string */ -function Piwik_getUrlTrackPageView( $idSite, $documentTitle = '' ) +function Piwik_getUrlTrackPageView($idSite, $documentTitle = '') { - $tracker = new PiwikTracker($idSite); - return $tracker->getUrlTrackPageView($documentTitle); + $tracker = new PiwikTracker($idSite); + return $tracker->getUrlTrackPageView($documentTitle); } /** @@ -1280,7 +1228,7 @@ function Piwik_getUrlTrackPageView( $idSite, $documentTitle = '' ) */ function Piwik_getUrlTrackGoal($idSite, $idGoal, $revenue = 0.0) { - $tracker = new PiwikTracker($idSite); - return $tracker->getUrlTrackGoal($idGoal, $revenue); + $tracker = new PiwikTracker($idSite); + return $tracker->getUrlTrackGoal($idGoal, $revenue); } diff --git a/libs/UserAgentParser/UserAgentParser.php b/libs/UserAgentParser/UserAgentParser.php index 03a1f695cd..bac59cea08 100644 --- a/libs/UserAgentParser/UserAgentParser.php +++ b/libs/UserAgentParser/UserAgentParser.php @@ -36,581 +36,571 @@ /** * Example usage - * + * * Browser info: * var_dump(UserAgentParser::getBrowser($_SERVER['HTTP_USER_AGENT'])); - * + * * Outputs: * array - * 'id' => 'FF' + * 'id' => 'FF' * 'name' => 'Firefox' * 'short_name' => 'Firefox' * 'version' => '3.0' * 'major_number' => '3' * 'minor_number' => '0' - * + * * Operating System info: * var_dump(UserAgentParser::getOperatingSystem($_SERVER['HTTP_USER_AGENT'])); * * Outputs: * array * 'id' => 'WXP' - * 'name' => 'Windows XP' - * 'short_name' => 'Win XP' - * + * 'name' => 'Windows XP' + * 'short_name' => 'Win XP' + * */ -class UserAgentParser +class UserAgentParser { - // browser regex => browser ID - // if there are aliases, the common name should be last - static protected $browsers = array( - 'abrowse' => 'AB', - 'amaya' => 'AM', - 'amigavoyager' => 'AV', - 'amiga-aweb' => 'AW', - 'arora' => 'AR', - 'beonex' => 'BE', - - // BlackBerry smartphones and tablets - 'blackberry' => 'BB', // BlackBerry 6 and PlayBook adopted webkit - 'bb10' => 'B2', // BlackBerry 10 - 'playbook' => 'BP', - - 'browsex' => 'BX', - - // Camino (and earlier incarnation) - 'chimera' => 'CA', - 'camino' => 'CA', - - 'cheshire' => 'CS', - - // Chrome, Chromium, and ChromePlus - 'crmo' => 'CH', - 'chrome' => 'CH', - - // Chrome Frame - 'chromeframe' => 'CF', - - 'cometbird' => 'CO', - 'dillo' => 'DI', - 'elinks' => 'EL', - 'epiphany' => 'EP', - 'fennec' => 'FE', - - // Dolfin (or Dolphin) - 'dolfin' => 'DF', - - // Firefox (in its many incarnations and rebranded versions) - 'phoenix' => 'PX', - 'mozilla firebird' => 'FB', - 'firebird' => 'FB', - 'bonecho' => 'FF', - 'minefield' => 'FF', - 'namoroka' => 'FF', - 'shiretoko' => 'FF', - 'granparadiso' => 'FF', - 'iceweasel' => 'FF', - 'icecat' => 'FF', - 'firefox' => 'FF', - - 'thunderbird' => 'TB', - - 'flock' => 'FL', - 'fluid' => 'FD', - 'galeon' => 'GA', - 'google earth' => 'GE', - 'hana' => 'HA', - 'hotjava' => 'HJ', - 'ibrowse' => 'IB', - 'icab' => 'IC', - - // IE (including shells: Acoo, AOL, Avant, Crazy Browser, Green Browser, KKMAN, Maxathon) - 'msie' => 'IE', - 'microsoft internet explorer' => 'IE', - 'internet explorer' => 'IE', - - 'iron' => 'IR', - 'kapiko' => 'KP', - 'kazehakase' => 'KZ', - 'k-meleon' => 'KM', - 'konqueror' => 'KO', - 'links' => 'LI', - 'lynx' => 'LX', - 'midori' => 'MI', - - // SeaMonkey (formerly Mozilla Suite) (and rebranded versions) - 'mozilla' => 'MO', - 'gnuzilla' => 'SM', - 'iceape' => 'SM', - 'seamonkey' => 'SM', - - // NCSA Mosaic (and incarnations) - 'mosaic' => 'MC', - 'ncsa mosaic' => 'MC', - - // Netscape Navigator - 'navigator' => 'NS', - 'netscape6' => 'NS', - 'netscape' => 'NS', - - 'nx' => 'NF', - 'netfront' => 'NF', - - 'omniweb' => 'OW', - - // Opera - 'nitro) opera' => 'OP', - 'opera' => 'OP', - - 'rekonq' => 'RK', - - // Safari - 'safari' => 'SF', - 'applewebkit' => 'SF', - - 'titanium' => 'TI', - - 'webos' => 'WO', - 'webpro' => 'WP', - ); - - // browser family (by layout engine) - static protected $browserType = array( - 'ie' => array('IE'), - 'gecko' => array('NS', 'PX', 'FF', 'FB', 'CA', 'GA', 'KM', 'MO', 'SM', 'CO', 'FE', 'KP', 'KZ', 'TB'), - 'khtml' => array('KO'), - 'webkit' => array('SF', 'CH', 'OW', 'AR', 'EP', 'FL', 'WO', 'AB', 'IR', 'CS', 'FD', 'HA', 'MI', 'GE', 'DF', 'BB', 'BP', 'TI', 'CF', 'RK', 'B2', 'NF'), - 'opera' => array('OP'), - ); - - // WebKit version numbers to Apple Safari version numbers (if Version/X.Y.Z not present) - static protected $safariVersions = array( - '536.25' => array('6', '0'), - '534.48' => array('5', '1'), - '533.16' => array('5', '0'), - '533.4' => array('4', '1'), - '526.11.2' => array('4', '0'), - '525.26' => array('3', '2'), - '525.13' => array('3', '1'), - '522.11' => array('3', '0'), - '412' => array('2', '0'), - '312' => array('1', '3'), - '125' => array('1', '2'), - '100' => array('1', '1'), - '85' => array('1', '0'), - '73' => array('0', '9'), - '48' => array('0', '8'), - ); - - // OmniWeb build numbers to OmniWeb version numbers (if Version/X.Y.Z not present) - static protected $omniWebVersions = array( - '622.15' => array('5', '11'), - '622.10' => array('5', '10'), - '622.8' => array('5', '9'), - '622.3' => array('5', '8'), - '621' => array('5', '7'), - '613' => array('5', '6'), - '607' => array('5', '5'), - '563.34' => array('5', '1'), - '558.36' => array('5', '0'), - '496' => array('4', '5'), - ); - - // OS regex => OS ID - static protected $operatingSystems = array( - 'Android' => 'AND', - 'Maemo' => 'MAE', - 'CrOS ' => 'LIN', - 'Linux' => 'LIN', - - 'Xbox' => 'XBX', - - // workaround for vendors who changed the WinPhone 7 user agent - 'WP7' => 'WPH', - - 'CYGWIN_NT-6.2' => 'WI8', - 'Windows NT 6.2' => 'WI8', - 'Windows 8' => 'WI8', - 'CYGWIN_NT-6.1' => 'WI7', - 'Windows NT 6.1' => 'WI7', - 'Windows 7' => 'WI7', - 'CYGWIN_NT-6.0' => 'WVI', - 'Windows NT 6.0' => 'WVI', - 'Windows Vista' => 'WVI', - 'CYGWIN_NT-5.2' => 'WS3', - 'Windows NT 5.2' => 'WS3', - 'Windows Server 2003 / XP x64' => 'WS3', - 'CYGWIN_NT-5.1' => 'WXP', - 'Windows NT 5.1' => 'WXP', - 'Windows XP' => 'WXP', - 'CYGWIN_NT-5.0' => 'W2K', - 'Windows NT 5.0' => 'W2K', - 'Windows 2000' => 'W2K', - 'CYGWIN_NT-4.0' => 'WNT', - 'Windows NT 4.0' => 'WNT', - 'WinNT' => 'WNT', - 'Windows NT' => 'WNT', - 'CYGWIN_ME-4.90' => 'WME', - 'Win 9x 4.90' => 'WME', - 'Windows ME' => 'WME', - 'CYGWIN_98-4.10' => 'W98', - 'Win98' => 'W98', - 'Windows 98' => 'W98', - 'CYGWIN_95-4.0' => 'W95', - 'Win32' => 'W95', - 'Win95' => 'W95', - 'Windows 95' => 'W95', - - // Windows Phone OS 7 and above - 'Windows Phone OS' => 'WPH', - - // Windows Mobile 6.x and some later versions of Windows Mobile 5 - 'IEMobile' => 'WMO', // fallback - 'Windows Mobile' => 'WMO', - - // Windows CE, Pocket PC, and Windows Mobile 5 are indistinguishable without vendor/device specific detection - 'Windows CE' => 'WCE', - - 'iPod' => 'IPD', - 'iPad' => 'IPA', - 'iPhone' => 'IPH', + // browser regex => browser ID + // if there are aliases, the common name should be last + static protected $browsers = array( + 'abrowse' => 'AB', + 'amaya' => 'AM', + 'amigavoyager' => 'AV', + 'amiga-aweb' => 'AW', + 'arora' => 'AR', + 'beonex' => 'BE', + + // BlackBerry smartphones and tablets + 'blackberry' => 'BB', // BlackBerry 6 and PlayBook adopted webkit + 'bb10' => 'B2', // BlackBerry 10 + 'playbook' => 'BP', + + 'browsex' => 'BX', + + // Camino (and earlier incarnation) + 'chimera' => 'CA', + 'camino' => 'CA', + + 'cheshire' => 'CS', + + // Chrome, Chromium, and ChromePlus + 'crmo' => 'CH', + 'chrome' => 'CH', + + // Chrome Frame + 'chromeframe' => 'CF', + + 'cometbird' => 'CO', + 'dillo' => 'DI', + 'elinks' => 'EL', + 'epiphany' => 'EP', + 'fennec' => 'FE', + + // Dolfin (or Dolphin) + 'dolfin' => 'DF', + + // Firefox (in its many incarnations and rebranded versions) + 'phoenix' => 'PX', + 'mozilla firebird' => 'FB', + 'firebird' => 'FB', + 'bonecho' => 'FF', + 'minefield' => 'FF', + 'namoroka' => 'FF', + 'shiretoko' => 'FF', + 'granparadiso' => 'FF', + 'iceweasel' => 'FF', + 'icecat' => 'FF', + 'firefox' => 'FF', + + 'thunderbird' => 'TB', + + 'flock' => 'FL', + 'fluid' => 'FD', + 'galeon' => 'GA', + 'google earth' => 'GE', + 'hana' => 'HA', + 'hotjava' => 'HJ', + 'ibrowse' => 'IB', + 'icab' => 'IC', + + // IE (including shells: Acoo, AOL, Avant, Crazy Browser, Green Browser, KKMAN, Maxathon) + 'msie' => 'IE', + 'microsoft internet explorer' => 'IE', + 'internet explorer' => 'IE', + + 'iron' => 'IR', + 'kapiko' => 'KP', + 'kazehakase' => 'KZ', + 'k-meleon' => 'KM', + 'konqueror' => 'KO', + 'links' => 'LI', + 'lynx' => 'LX', + 'midori' => 'MI', + + // SeaMonkey (formerly Mozilla Suite) (and rebranded versions) + 'mozilla' => 'MO', + 'gnuzilla' => 'SM', + 'iceape' => 'SM', + 'seamonkey' => 'SM', + + // NCSA Mosaic (and incarnations) + 'mosaic' => 'MC', + 'ncsa mosaic' => 'MC', + + // Netscape Navigator + 'navigator' => 'NS', + 'netscape6' => 'NS', + 'netscape' => 'NS', + + 'nx' => 'NF', + 'netfront' => 'NF', + + 'omniweb' => 'OW', + + // Opera + 'nitro) opera' => 'OP', + 'opera' => 'OP', + + 'rekonq' => 'RK', + + // Safari + 'safari' => 'SF', + 'applewebkit' => 'SF', + + 'titanium' => 'TI', + + 'webos' => 'WO', + 'webpro' => 'WP', + ); + + // browser family (by layout engine) + static protected $browserType = array( + 'ie' => array('IE'), + 'gecko' => array('NS', 'PX', 'FF', 'FB', 'CA', 'GA', 'KM', 'MO', 'SM', 'CO', 'FE', 'KP', 'KZ', 'TB'), + 'khtml' => array('KO'), + 'webkit' => array('SF', 'CH', 'OW', 'AR', 'EP', 'FL', 'WO', 'AB', 'IR', 'CS', 'FD', 'HA', 'MI', 'GE', 'DF', 'BB', 'BP', 'TI', 'CF', 'RK', 'B2', 'NF'), + 'opera' => array('OP'), + ); + + // WebKit version numbers to Apple Safari version numbers (if Version/X.Y.Z not present) + static protected $safariVersions = array( + '536.25' => array('6', '0'), + '534.48' => array('5', '1'), + '533.16' => array('5', '0'), + '533.4' => array('4', '1'), + '526.11.2' => array('4', '0'), + '525.26' => array('3', '2'), + '525.13' => array('3', '1'), + '522.11' => array('3', '0'), + '412' => array('2', '0'), + '312' => array('1', '3'), + '125' => array('1', '2'), + '100' => array('1', '1'), + '85' => array('1', '0'), + '73' => array('0', '9'), + '48' => array('0', '8'), + ); + + // OmniWeb build numbers to OmniWeb version numbers (if Version/X.Y.Z not present) + static protected $omniWebVersions = array( + '622.15' => array('5', '11'), + '622.10' => array('5', '10'), + '622.8' => array('5', '9'), + '622.3' => array('5', '8'), + '621' => array('5', '7'), + '613' => array('5', '6'), + '607' => array('5', '5'), + '563.34' => array('5', '1'), + '558.36' => array('5', '0'), + '496' => array('4', '5'), + ); + + // OS regex => OS ID + static protected $operatingSystems = array( + 'Android' => 'AND', + 'Maemo' => 'MAE', + 'CrOS ' => 'LIN', + 'Linux' => 'LIN', + + 'Xbox' => 'XBX', + + // workaround for vendors who changed the WinPhone 7 user agent + 'WP7' => 'WPH', + + 'CYGWIN_NT-6.2' => 'WI8', + 'Windows NT 6.2' => 'WI8', + 'Windows 8' => 'WI8', + 'CYGWIN_NT-6.1' => 'WI7', + 'Windows NT 6.1' => 'WI7', + 'Windows 7' => 'WI7', + 'CYGWIN_NT-6.0' => 'WVI', + 'Windows NT 6.0' => 'WVI', + 'Windows Vista' => 'WVI', + 'CYGWIN_NT-5.2' => 'WS3', + 'Windows NT 5.2' => 'WS3', + 'Windows Server 2003 / XP x64' => 'WS3', + 'CYGWIN_NT-5.1' => 'WXP', + 'Windows NT 5.1' => 'WXP', + 'Windows XP' => 'WXP', + 'CYGWIN_NT-5.0' => 'W2K', + 'Windows NT 5.0' => 'W2K', + 'Windows 2000' => 'W2K', + 'CYGWIN_NT-4.0' => 'WNT', + 'Windows NT 4.0' => 'WNT', + 'WinNT' => 'WNT', + 'Windows NT' => 'WNT', + 'CYGWIN_ME-4.90' => 'WME', + 'Win 9x 4.90' => 'WME', + 'Windows ME' => 'WME', + 'CYGWIN_98-4.10' => 'W98', + 'Win98' => 'W98', + 'Windows 98' => 'W98', + 'CYGWIN_95-4.0' => 'W95', + 'Win32' => 'W95', + 'Win95' => 'W95', + 'Windows 95' => 'W95', + + // Windows Phone OS 7 and above + 'Windows Phone OS' => 'WPH', + + // Windows Mobile 6.x and some later versions of Windows Mobile 5 + 'IEMobile' => 'WMO', // fallback + 'Windows Mobile' => 'WMO', + + // Windows CE, Pocket PC, and Windows Mobile 5 are indistinguishable without vendor/device specific detection + 'Windows CE' => 'WCE', + + 'iPod' => 'IPD', + 'iPad' => 'IPA', + 'iPhone' => 'IPH', // 'iOS' => 'IOS', - 'Darwin' => 'MAC', - 'Macintosh' => 'MAC', - 'Power Macintosh' => 'MAC', - 'Mac_PowerPC' => 'MAC', - 'Mac PPC' => 'MAC', - 'PPC' => 'MAC', - 'Mac PowerPC' => 'MAC', - 'Mac OS' => 'MAC', - - 'webOS' => 'WOS', - 'Palm webOS' => 'WOS', - 'PalmOS' => 'POS', - 'Palm OS' => 'POS', - - 'BB10' => 'BBX', - 'BlackBerry' => 'BLB', - 'RIM Tablet OS' => 'QNX', - 'QNX' => 'QNX', - - 'SymbOS' => 'SYM', - 'Symbian OS' => 'SYM', - 'SymbianOS' => 'SYM', - - 'bada' => 'SBA', - - 'SunOS' => 'SOS', - 'AIX' => 'AIX', - 'HP-UX' => 'HPX', - 'OpenVMS' => 'VMS', - - 'FreeBSD' => 'BSD', - 'NetBSD' => 'NBS', - 'OpenBSD' => 'OBS', - 'DragonFly' => 'DFB', - 'Syllable' => 'SYL', - - 'Nintendo WiiU' => 'WIU', - 'Nintendo Wii' => 'WII', - 'Nitro' => 'NDS', - 'Nintendo DSi' => 'DSI', - 'Nintendo DS' => 'NDS', - 'Nintendo 3DS' => '3DS', - - 'PlayStation Vita' => 'PSV', - 'PlayStation Portable' => 'PSP', - 'PlayStation 3' => 'PS3', - - 'IRIX' => 'IRI', - 'OSF1' => 'T64', - 'OS/2' => 'OS2', - 'BEOS' => 'BEO', - 'Amiga' => 'AMI', - 'AmigaOS' => 'AMI', - ); - - // os family - // NOTE: The keys in this array are used by plugins/UserSettings/functions.php . Any changes - // made here should also be made in that file. - static protected $osType = array( - 'Windows' => array('WI8', 'WI7', 'WVI', 'WS3', 'WXP', 'W2K', 'WNT', 'WME', 'W98', 'W95'), - 'Linux' => array('LIN'), - 'Mac' => array('MAC'), - 'iOS' => array('IPD', 'IPA', 'IPH'), - 'Android' => array('AND'), - 'Windows Mobile' => array('WPH', 'WMO', 'WCE'), - 'Gaming Console' => array('WII', 'WIU', 'PS3', 'XBX'), - 'Mobile Gaming Console' => array('PSP', 'PSV', 'NDS', 'DSI', '3DS'), - 'Unix' => array('SOS', 'AIX', 'HP-UX', 'BSD', 'NBS', 'OBS', 'DFB', 'SYL', 'IRI', 'T64'), - 'Other Mobile' => array('MAE', 'WOS', 'POS', 'BLB', 'QNX', 'SYM', 'SBA'), - 'Other' => array('VMS', 'OS2', 'BEOS', 'AMI') - ); - - static protected $browserIdToName; - static protected $browserIdToShortName; - static protected $operatingSystemsIdToName; - static protected $operatingSystemsIdToShortName; - static private $init = false; - - /** - * Returns an array of the OS for the submitted user agent - * 'id' => '', - * 'name' => '', - * 'short_name' => '', - * - * @param string $userAgent - * @return string false if OS couldn't be identified, or 3 letters ID (eg. WXP) - * @see UserAgentParser/OperatingSystems.php for the list of OS (also available in self::$operatingSystems) - */ - static public function getOperatingSystem($userAgent) - { - $userAgent = self::cleanupUserAgent($userAgent); - self::init(); - $info = array( - 'id' => '', - 'name' => '', - 'short_name' => '', - ); - foreach(self::$operatingSystems as $key => $value) { - if (stristr($userAgent, $key) !== false) { - $info['id'] = $value; - break; - } - } - if(empty($info['id'])) { - return false; - } - $info['name'] = self::getOperatingSystemNameFromId($info['id']); - $info['short_name'] = self::getOperatingSystemShortNameFromId($info['id']); - return $info; - } - - static protected function cleanupUserAgent($userAgent) - { - // in case value is URL encoded - return urldecode($userAgent); - } - - /** - * Returns the browser information array, given a user agent string. - * - * @param string $userAgent - * @return array false if the browser is "unknown", or - * array( 'id' => '', // 2 letters ID, eg. FF - * 'name' => '', // 2 letters ID, eg. FF - * 'short_name' => '', // 2 letters ID, eg. FF - * 'major_number' => '', // 2 in firefox 2.0.12 - * 'minor_number' => '', // 0 in firefox 2.0.12 - * 'version' => '', // major_number.minor_number - * ); - * @see self::$browsers for the list of OS - */ - static public function getBrowser($userAgent) - { - $userAgent = self::cleanupUserAgent($userAgent); - - self::init(); - - $info = array( - 'id' => '', - 'name' => '', - 'short_name' => '', - 'major_number' => '', - 'minor_number' => '', - 'version' => '', - ); - - $browsers = self::$browsers; - - // derivative browsers often clone the base browser's useragent - unset($browsers['firefox']); - unset($browsers['mozilla']); - unset($browsers['safari']); - unset($browsers['applewebkit']); - - $browsersPattern = str_replace(')', '\)', implode('|', array_keys($browsers))); - - $results = array(); - - // Misbehaving IE add-ons - $userAgent = preg_replace('/[; ]Mozilla\/[0-9.]+ \([^)]+\)/', '', $userAgent); - - // Clean-up BlackBerry device UAs - $userAgent = preg_replace('~^BlackBerry\d+/~', 'BlackBerry/', $userAgent); - - if (preg_match_all("/($browsersPattern)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $results) - || (strpos($userAgent, 'Shiira') === false && preg_match_all("/(firefox|thunderbird|safari)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $results)) - || preg_match_all("/(applewebkit)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $results) - || preg_match_all("/^(mozilla)\/([0-9]+)([\.0-9a-z-]+)?(?: \[[a-z]{2}\])? (?:\([^)]*\))$/i", $userAgent, $results) - || preg_match_all("/^(mozilla)\/[0-9]+(?:[\.0-9a-z-]+)?\s\(.* rv:([0-9]+)([.0-9a-z]+)\) gecko(\/[0-9]{8}|$)(?:.*)/i", $userAgent, $results) + 'Darwin' => 'MAC', + 'Macintosh' => 'MAC', + 'Power Macintosh' => 'MAC', + 'Mac_PowerPC' => 'MAC', + 'Mac PPC' => 'MAC', + 'PPC' => 'MAC', + 'Mac PowerPC' => 'MAC', + 'Mac OS' => 'MAC', + + 'webOS' => 'WOS', + 'Palm webOS' => 'WOS', + 'PalmOS' => 'POS', + 'Palm OS' => 'POS', + + 'BB10' => 'BBX', + 'BlackBerry' => 'BLB', + 'RIM Tablet OS' => 'QNX', + 'QNX' => 'QNX', + + 'SymbOS' => 'SYM', + 'Symbian OS' => 'SYM', + 'SymbianOS' => 'SYM', + + 'bada' => 'SBA', + + 'SunOS' => 'SOS', + 'AIX' => 'AIX', + 'HP-UX' => 'HPX', + 'OpenVMS' => 'VMS', + + 'FreeBSD' => 'BSD', + 'NetBSD' => 'NBS', + 'OpenBSD' => 'OBS', + 'DragonFly' => 'DFB', + 'Syllable' => 'SYL', + + 'Nintendo WiiU' => 'WIU', + 'Nintendo Wii' => 'WII', + 'Nitro' => 'NDS', + 'Nintendo DSi' => 'DSI', + 'Nintendo DS' => 'NDS', + 'Nintendo 3DS' => '3DS', + + 'PlayStation Vita' => 'PSV', + 'PlayStation Portable' => 'PSP', + 'PlayStation 3' => 'PS3', + + 'IRIX' => 'IRI', + 'OSF1' => 'T64', + 'OS/2' => 'OS2', + 'BEOS' => 'BEO', + 'Amiga' => 'AMI', + 'AmigaOS' => 'AMI', + ); + + // os family + // NOTE: The keys in this array are used by plugins/UserSettings/functions.php . Any changes + // made here should also be made in that file. + static protected $osType = array( + 'Windows' => array('WI8', 'WI7', 'WVI', 'WS3', 'WXP', 'W2K', 'WNT', 'WME', 'W98', 'W95'), + 'Linux' => array('LIN'), + 'Mac' => array('MAC'), + 'iOS' => array('IPD', 'IPA', 'IPH'), + 'Android' => array('AND'), + 'Windows Mobile' => array('WPH', 'WMO', 'WCE'), + 'Gaming Console' => array('WII', 'WIU', 'PS3', 'XBX'), + 'Mobile Gaming Console' => array('PSP', 'PSV', 'NDS', 'DSI', '3DS'), + 'Unix' => array('SOS', 'AIX', 'HP-UX', 'BSD', 'NBS', 'OBS', 'DFB', 'SYL', 'IRI', 'T64'), + 'Other Mobile' => array('MAE', 'WOS', 'POS', 'BLB', 'QNX', 'SYM', 'SBA'), + 'Other' => array('VMS', 'OS2', 'BEOS', 'AMI') + ); + + static protected $browserIdToName; + static protected $browserIdToShortName; + static protected $operatingSystemsIdToName; + static protected $operatingSystemsIdToShortName; + static private $init = false; + + /** + * Returns an array of the OS for the submitted user agent + * 'id' => '', + * 'name' => '', + * 'short_name' => '', + * + * @param string $userAgent + * @return string false if OS couldn't be identified, or 3 letters ID (eg. WXP) + * @see UserAgentParser/OperatingSystems.php for the list of OS (also available in self::$operatingSystems) + */ + static public function getOperatingSystem($userAgent) + { + $userAgent = self::cleanupUserAgent($userAgent); + self::init(); + $info = array( + 'id' => '', + 'name' => '', + 'short_name' => '', + ); + foreach (self::$operatingSystems as $key => $value) { + if (stristr($userAgent, $key) !== false) { + $info['id'] = $value; + break; + } + } + if (empty($info['id'])) { + return false; + } + $info['name'] = self::getOperatingSystemNameFromId($info['id']); + $info['short_name'] = self::getOperatingSystemShortNameFromId($info['id']); + return $info; + } + + static protected function cleanupUserAgent($userAgent) + { + // in case value is URL encoded + return urldecode($userAgent); + } + + /** + * Returns the browser information array, given a user agent string. + * + * @param string $userAgent + * @return array false if the browser is "unknown", or + * array( 'id' => '', // 2 letters ID, eg. FF + * 'name' => '', // 2 letters ID, eg. FF + * 'short_name' => '', // 2 letters ID, eg. FF + * 'major_number' => '', // 2 in firefox 2.0.12 + * 'minor_number' => '', // 0 in firefox 2.0.12 + * 'version' => '', // major_number.minor_number + * ); + * @see self::$browsers for the list of OS + */ + static public function getBrowser($userAgent) + { + $userAgent = self::cleanupUserAgent($userAgent); + + self::init(); + + $info = array( + 'id' => '', + 'name' => '', + 'short_name' => '', + 'major_number' => '', + 'minor_number' => '', + 'version' => '', + ); + + $browsers = self::$browsers; + + // derivative browsers often clone the base browser's useragent + unset($browsers['firefox']); + unset($browsers['mozilla']); + unset($browsers['safari']); + unset($browsers['applewebkit']); + + $browsersPattern = str_replace(')', '\)', implode('|', array_keys($browsers))); + + $results = array(); + + // Misbehaving IE add-ons + $userAgent = preg_replace('/[; ]Mozilla\/[0-9.]+ \([^)]+\)/', '', $userAgent); + + // Clean-up BlackBerry device UAs + $userAgent = preg_replace('~^BlackBerry\d+/~', 'BlackBerry/', $userAgent); + + if (preg_match_all("/($browsersPattern)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $results) + || (strpos($userAgent, 'Shiira') === false && preg_match_all("/(firefox|thunderbird|safari)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $results)) + || preg_match_all("/(applewebkit)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $results) + || preg_match_all("/^(mozilla)\/([0-9]+)([\.0-9a-z-]+)?(?: \[[a-z]{2}\])? (?:\([^)]*\))$/i", $userAgent, $results) + || preg_match_all("/^(mozilla)\/[0-9]+(?:[\.0-9a-z-]+)?\s\(.* rv:([0-9]+)([.0-9a-z]+)\) gecko(\/[0-9]{8}|$)(?:.*)/i", $userAgent, $results) || (strpos($userAgent, 'Nintendo 3DS') !== false && preg_match_all("/^(mozilla).*version\/([0-9]+)([.0-9a-z]+)?/i", $userAgent, $results)) - ) - { - // browser code (usually the first match) - $count = 0; - $info['id'] = self::$browsers[strtolower($results[1][0])]; - - // sometimes there's a better match at the end - if(strpos($userAgent, 'chromeframe') !== false) { - $count = count($results[0]) - 1; - $info['id'] = 'CF'; - } - elseif(($info['id'] == 'IE' || $info['id'] == 'LX') && (count($results[0]) > 1)) { - $count = count($results[0]) - 1; - $info['id'] = self::$browsers[strtolower($results[1][$count])]; - } - - // Netscape fix - if($info['id'] == 'MO' && $count == 0) { - if(stripos($userAgent, 'PlayStation') !== false) { - return false; - } - if(strpos($userAgent, 'Nintendo 3DS') !== false) { + ) { + // browser code (usually the first match) + $count = 0; + $info['id'] = self::$browsers[strtolower($results[1][0])]; + + // sometimes there's a better match at the end + if (strpos($userAgent, 'chromeframe') !== false) { + $count = count($results[0]) - 1; + $info['id'] = 'CF'; + } elseif (($info['id'] == 'IE' || $info['id'] == 'LX') && (count($results[0]) > 1)) { + $count = count($results[0]) - 1; + $info['id'] = self::$browsers[strtolower($results[1][$count])]; + } + + // Netscape fix + if ($info['id'] == 'MO' && $count == 0) { + if (stripos($userAgent, 'PlayStation') !== false) { + return false; + } + if (strpos($userAgent, 'Nintendo 3DS') !== false) { $info['id'] = 'NF'; + } elseif (count($results) == 4) { + $info['id'] = 'NS'; + } + } // BlackBerry devices + elseif (strpos($userAgent, 'BlackBerry') !== false) { + $info['id'] = 'BB'; + } elseif (strpos($userAgent, 'RIM Tablet OS') !== false) { + $info['id'] = 'BP'; + } elseif (strpos($userAgent, 'BB10') !== false) { + $info['id'] = 'B2'; + } elseif (strpos($userAgent, 'Playstation Vita') !== false) { + $info['id'] = 'NF'; + + if (preg_match_all("/(silk)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $newResults)) { + $results = $newResults; + $count = count($results[0]) - 1; + } + } + + // Version/X.Y.Z override + if (preg_match_all("/(version)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $newResults)) { + $results = $newResults; + $count = count($results[0]) - 1; + } + + // major version number (1 in mozilla 1.7) + $info['major_number'] = $results[2][$count]; + + // is an minor version number ? If not, 0 + $match = array(); + + preg_match('/([.\0-9]+)?([\.a-z0-9]+)?/i', $results[3][$count], $match); + + if (isset($match[1])) { + // find minor version number (7 in mozilla 1.7, 9 in firefox 0.9.3) + $dot = strpos(substr($match[1], 1), '.'); + if ($dot !== false) { + $info['minor_number'] = substr($match[1], 1, $dot); + } else { + $info['minor_number'] = substr($match[1], 1); + } + } else { + $info['minor_number'] = '0'; + } + $info['version'] = $info['major_number'] . '.' . $info['minor_number']; + + // IE compatibility mode + if ($info['id'] == 'IE' + && strncmp($userAgent, 'Mozilla/4.0', 11) == 0 + && preg_match('~ Trident/([0-9]+)\.[0-9]+~', $userAgent, $tridentVersion) + ) { + $info['major_number'] = $tridentVersion[1] + 4; + $info['minor_number'] = '0'; + $info['version'] = $info['major_number'] . '.' . $info['minor_number']; + } + + // Safari fix + if ($info['id'] == 'SF') { + foreach (self::$safariVersions as $buildVersion => $productVersion) { + if (version_compare($info['version'], $buildVersion) >= 0) { + $info['major_number'] = $productVersion[0]; + $info['minor_number'] = $productVersion[1]; + $info['version'] = $info['major_number'] . '.' . $info['minor_number']; + break; + } + } + } + + // OmniWeb fix + if ($info['id'] == 'OW') { + foreach (self::$omniWebVersions as $buildVersion => $productVersion) { + if (version_compare($info['version'], $buildVersion) >= 0) { + $info['major_number'] = $productVersion[0]; + $info['minor_number'] = $productVersion[1]; + $info['version'] = $info['major_number'] . '.' . $info['minor_number']; + break; + } } - elseif(count($results) == 4) { - $info['id'] = 'NS'; - } - } - // BlackBerry devices - elseif(strpos($userAgent, 'BlackBerry') !== false) { - $info['id'] = 'BB'; - } - elseif(strpos($userAgent, 'RIM Tablet OS') !== false) { - $info['id'] = 'BP'; - } - elseif(strpos($userAgent, 'BB10') !== false) { - $info['id'] = 'B2'; - } - elseif(strpos($userAgent, 'Playstation Vita') !== false) { - $info['id'] = 'NF'; - - if(preg_match_all("/(silk)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $newResults)) - { - $results = $newResults; - $count = count($results[0])-1; - } - } - - // Version/X.Y.Z override - if(preg_match_all("/(version)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $newResults)) - { - $results = $newResults; - $count = count($results[0])-1; - } - - // major version number (1 in mozilla 1.7) - $info['major_number'] = $results[2][$count]; - - // is an minor version number ? If not, 0 - $match = array(); - - preg_match('/([.\0-9]+)?([\.a-z0-9]+)?/i', $results[3][$count], $match); - - if(isset($match[1])) { - // find minor version number (7 in mozilla 1.7, 9 in firefox 0.9.3) - $dot = strpos(substr($match[1], 1), '.'); - if($dot !== false) { - $info['minor_number'] = substr($match[1], 1, $dot); - } - else { - $info['minor_number'] = substr($match[1], 1); - } - } - else { - $info['minor_number'] = '0'; - } - $info['version'] = $info['major_number'] . '.' . $info['minor_number']; - - // IE compatibility mode - if($info['id'] == 'IE' - && strncmp($userAgent, 'Mozilla/4.0', 11) == 0 - && preg_match('~ Trident/([0-9]+)\.[0-9]+~', $userAgent, $tridentVersion)) - { - $info['major_number'] = $tridentVersion[1] + 4; - $info['minor_number'] = '0'; - $info['version'] = $info['major_number'] . '.' .$info['minor_number']; - } - - // Safari fix - if($info['id'] == 'SF') { - foreach(self::$safariVersions as $buildVersion => $productVersion) { - if(version_compare($info['version'], $buildVersion) >= 0) { - $info['major_number'] = $productVersion[0]; - $info['minor_number'] = $productVersion[1]; - $info['version'] = $info['major_number'] . '.' . $info['minor_number']; - break; - } - } - } - - // OmniWeb fix - if($info['id'] == 'OW') { - foreach(self::$omniWebVersions as $buildVersion => $productVersion) { - if(version_compare($info['version'], $buildVersion) >= 0) { - $info['major_number'] = $productVersion[0]; - $info['minor_number'] = $productVersion[1]; - $info['version'] = $info['major_number'] . '.' . $info['minor_number']; - break; - } - } - } - - // SeaMonkey fix - if($info['id'] == 'MO' && $info['version'] == '1.9') { - $info['id'] = 'SM'; - } - - $info['name'] = self::getBrowserNameFromId($info['id']); - $info['short_name'] = self::getBrowserShortNameFromId($info['id']); - - return $info; - } - - return false; - } - - static protected function init() { - if(self::$init) { - return; - } - self::$init = true; - - // init browser names and short names - self::$browserIdToName = array_map('ucwords',array_flip(self::$browsers)); - self::$browserIdToName['AB'] = 'ABrowse'; - self::$browserIdToName['AV'] = 'AmigaVoyager'; - self::$browserIdToName['AW'] = 'Amiga AWeb'; - self::$browserIdToName['BB'] = 'BlackBerry'; - self::$browserIdToName['BP'] = 'PlayBook'; - self::$browserIdToName['B2'] = 'BlackBerry'; - self::$browserIdToName['BX'] = 'BrowseX'; - self::$browserIdToName['CF'] = 'Chrome Frame'; - self::$browserIdToName['CO'] = 'CometBird'; - self::$browserIdToName['EL'] = 'ELinks'; - self::$browserIdToName['FF'] = 'Firefox'; - self::$browserIdToName['HJ'] = 'HotJava'; - self::$browserIdToName['IB'] = 'IBrowse'; - self::$browserIdToName['IC'] = 'iCab'; - self::$browserIdToName['KM'] = 'K-Meleon'; - self::$browserIdToName['MC'] = 'NCSA Mosaic'; - self::$browserIdToName['NF'] = 'NetFront'; - self::$browserIdToName['OW'] = 'OmniWeb'; - self::$browserIdToName['SF'] = 'Safari'; - self::$browserIdToName['SM'] = 'SeaMonkey'; - self::$browserIdToName['WO'] = 'Palm webOS'; - self::$browserIdToName['WP'] = 'WebPro'; - - self::$browserIdToShortName = self::$browserIdToName; - self::$browserIdToShortName['AW'] = 'AWeb'; - self::$browserIdToShortName['FB'] = 'Firebird'; - self::$browserIdToShortName['IE'] = 'IE'; - self::$browserIdToShortName['MC'] = 'Mosaic'; - self::$browserIdToShortName['BP'] = 'PlayBook'; - self::$browserIdToShortName['WO'] = 'webOS'; - - // init OS names and short names + } + + // SeaMonkey fix + if ($info['id'] == 'MO' && $info['version'] == '1.9') { + $info['id'] = 'SM'; + } + + $info['name'] = self::getBrowserNameFromId($info['id']); + $info['short_name'] = self::getBrowserShortNameFromId($info['id']); + + return $info; + } + + return false; + } + + static protected function init() + { + if (self::$init) { + return; + } + self::$init = true; + + // init browser names and short names + self::$browserIdToName = array_map('ucwords', array_flip(self::$browsers)); + self::$browserIdToName['AB'] = 'ABrowse'; + self::$browserIdToName['AV'] = 'AmigaVoyager'; + self::$browserIdToName['AW'] = 'Amiga AWeb'; + self::$browserIdToName['BB'] = 'BlackBerry'; + self::$browserIdToName['BP'] = 'PlayBook'; + self::$browserIdToName['B2'] = 'BlackBerry'; + self::$browserIdToName['BX'] = 'BrowseX'; + self::$browserIdToName['CF'] = 'Chrome Frame'; + self::$browserIdToName['CO'] = 'CometBird'; + self::$browserIdToName['EL'] = 'ELinks'; + self::$browserIdToName['FF'] = 'Firefox'; + self::$browserIdToName['HJ'] = 'HotJava'; + self::$browserIdToName['IB'] = 'IBrowse'; + self::$browserIdToName['IC'] = 'iCab'; + self::$browserIdToName['KM'] = 'K-Meleon'; + self::$browserIdToName['MC'] = 'NCSA Mosaic'; + self::$browserIdToName['NF'] = 'NetFront'; + self::$browserIdToName['OW'] = 'OmniWeb'; + self::$browserIdToName['SF'] = 'Safari'; + self::$browserIdToName['SM'] = 'SeaMonkey'; + self::$browserIdToName['WO'] = 'Palm webOS'; + self::$browserIdToName['WP'] = 'WebPro'; + + self::$browserIdToShortName = self::$browserIdToName; + self::$browserIdToShortName['AW'] = 'AWeb'; + self::$browserIdToShortName['FB'] = 'Firebird'; + self::$browserIdToShortName['IE'] = 'IE'; + self::$browserIdToShortName['MC'] = 'Mosaic'; + self::$browserIdToShortName['BP'] = 'PlayBook'; + self::$browserIdToShortName['WO'] = 'webOS'; + + // init OS names and short names $operatingSystemsIdToName = array( 'IPD' => 'iPod', 'IPA' => 'iPad', @@ -655,74 +645,70 @@ class UserAgentParser 'UNK' => 'Unknown', ); self::$operatingSystemsIdToShortName = array_merge(self::$operatingSystemsIdToName, $operatingSystemsIdToShortName); - } - - static public function getBrowserNameFromId($browserId) - { - self::init(); - if(isset(self::$browserIdToName[$browserId])) { - return self::$browserIdToName[$browserId]; - } - return false; - } - - static public function getBrowserShortNameFromId($browserId) - { - self::init(); - if(isset(self::$browserIdToShortName[$browserId])) { - return self::$browserIdToShortName[$browserId]; - } - return false; - } - - static public function getBrowserFamilyFromId($browserId) - { - self::init(); - $familyNameToUse = 'unknown'; - foreach(self::$browserType as $familyName => $aBrowsers) - { - if(in_array($browserId, $aBrowsers)) - { - $familyNameToUse = $familyName; - break; - } - } - return $familyNameToUse; - } - - static public function getOperatingSystemNameFromId($osId) - { - self::init(); - if(isset(self::$operatingSystemsIdToName[$osId])) { - return self::$operatingSystemsIdToName[$osId]; - } - return false; - } - - static public function getOperatingSystemShortNameFromId($osId) - { - self::init(); - if(isset(self::$operatingSystemsIdToShortName[$osId])) { - return self::$operatingSystemsIdToShortName[$osId]; - } - return false; - } - - static public function getOperatingSystemIdFromName($osName) - { - return isset(self::$operatingSystems[$osName]) ? self::$operatingSystems[$osName] : false; - } - - static public function getOperatingSystemFamilyFromId($osId) - { - self::init(); - foreach (self::$osType as $familyName => $aSystems) - { - if (in_array($osId, $aSystems)) - { - return $familyName; - } - } - return 'unknown'; - } + } + + static public function getBrowserNameFromId($browserId) + { + self::init(); + if (isset(self::$browserIdToName[$browserId])) { + return self::$browserIdToName[$browserId]; + } + return false; + } + + static public function getBrowserShortNameFromId($browserId) + { + self::init(); + if (isset(self::$browserIdToShortName[$browserId])) { + return self::$browserIdToShortName[$browserId]; + } + return false; + } + + static public function getBrowserFamilyFromId($browserId) + { + self::init(); + $familyNameToUse = 'unknown'; + foreach (self::$browserType as $familyName => $aBrowsers) { + if (in_array($browserId, $aBrowsers)) { + $familyNameToUse = $familyName; + break; + } + } + return $familyNameToUse; + } + + static public function getOperatingSystemNameFromId($osId) + { + self::init(); + if (isset(self::$operatingSystemsIdToName[$osId])) { + return self::$operatingSystemsIdToName[$osId]; + } + return false; + } + + static public function getOperatingSystemShortNameFromId($osId) + { + self::init(); + if (isset(self::$operatingSystemsIdToShortName[$osId])) { + return self::$operatingSystemsIdToShortName[$osId]; + } + return false; + } + + static public function getOperatingSystemIdFromName($osName) + { + return isset(self::$operatingSystems[$osName]) ? self::$operatingSystems[$osName] : false; + } + + static public function getOperatingSystemFamilyFromId($osId) + { + self::init(); + foreach (self::$osType as $familyName => $aSystems) { + if (in_array($osId, $aSystems)) { + return $familyName; + } + } + return 'unknown'; + } } diff --git a/libs/UserAgentParser/UserAgentParser.test.php b/libs/UserAgentParser/UserAgentParser.test.php index f5468c1b6b..cd23f36e99 100644 --- a/libs/UserAgentParser/UserAgentParser.test.php +++ b/libs/UserAgentParser/UserAgentParser.test.php @@ -1,48 +1,48 @@ <?php -if(!isset($_GET['setUserAgent']) && !isset($_SERVER['HTTP_USER_AGENT'])) die; +if (!isset($_GET['setUserAgent']) && !isset($_SERVER['HTTP_USER_AGENT'])) die; -require_once dirname(__FILE__).'/UserAgentParser.php'; +require_once dirname(__FILE__) . '/UserAgentParser.php'; echo "<h2>UserAgentParser php library test</h2>"; -$testUserAgent = array( - 'my user agent' => '', - 'ie8 on win7' => 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET CLR 3.0.04506; .NET CLR 3.5.21022; InfoPath.2; SLCC1; Zune 3.0)', - 'ie8 on vista (compatibility view)' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)', - 'ie8 on vista' => 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)', - 'chrome on winxp' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.48 Safari/525.19', - 'IE6 on winxp' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)', - 'safari on winxp' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Version/3.1.2 Safari/525.21', - 'FF3 on winxp' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6', - 'opera 9.63 on winxp' => 'Opera/9.63 (Windows NT 5.1; U; en) Presto/2.1.1', - 'Blackberry' => 'BlackBerry8700/4.1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1', - 'opera 9.30 on Nintendo Wii' => 'Opera/9.30 (Nintendo Wii; U; ; 2047-7; en)', - 'iphone' => 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_2 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5G77 Safari/525.20', - 'iPod touch' => 'Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A100a Safari/419.3', - 'iPod' => 'Mozilla/5.0 (iPod; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11a Safari/525.20', - 'Android' => 'Mozilla/5.0 (Linux; U; Android 1.1; en-us; dream) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2', - 'PalmOS' => 'Mozilla/5.0 [en] (PalmOS; U; WebPro/3.5; Palm-Zi72) ', - 'safari on mac os X' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/527.3+ (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1', - 'opera 9.64 on win ME' => 'Opera/9.64 (Windows ME; U; en) Presto/2.1.1', - 'opera 10.00 on XP' => 'Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.00', - 'iron on win7' => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/531.0 (KHTML, like Gecko) Iron/3.0.189.0 Safari/531.0', - 'firefox 3.6 alpha on vista' => 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2a2pre) Gecko/20090826 Namoroka/3.6a2pre', - 'firefox 3.5 alpha on win7' => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1b4pre) Gecko/20090420 Shiretoko/3.5b4pre (.NET CLR 3.5.30729)', - 'firefox nightly build' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:2.0a1pre) Gecko/2008060602 Minefield/4.0a1pre', - 'thunderbird 14.0 with lightning 1.6' => 'Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20120713 Thunderbird/14.0 Lightning/1.6', +$testUserAgent = array( + 'my user agent' => '', + 'ie8 on win7' => 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET CLR 3.0.04506; .NET CLR 3.5.21022; InfoPath.2; SLCC1; Zune 3.0)', + 'ie8 on vista (compatibility view)' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)', + 'ie8 on vista' => 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)', + 'chrome on winxp' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.48 Safari/525.19', + 'IE6 on winxp' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)', + 'safari on winxp' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Version/3.1.2 Safari/525.21', + 'FF3 on winxp' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6', + 'opera 9.63 on winxp' => 'Opera/9.63 (Windows NT 5.1; U; en) Presto/2.1.1', + 'Blackberry' => 'BlackBerry8700/4.1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1', + 'opera 9.30 on Nintendo Wii' => 'Opera/9.30 (Nintendo Wii; U; ; 2047-7; en)', + 'iphone' => 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_2 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5G77 Safari/525.20', + 'iPod touch' => 'Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A100a Safari/419.3', + 'iPod' => 'Mozilla/5.0 (iPod; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11a Safari/525.20', + 'Android' => 'Mozilla/5.0 (Linux; U; Android 1.1; en-us; dream) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2', + 'PalmOS' => 'Mozilla/5.0 [en] (PalmOS; U; WebPro/3.5; Palm-Zi72) ', + 'safari on mac os X' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/527.3+ (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1', + 'opera 9.64 on win ME' => 'Opera/9.64 (Windows ME; U; en) Presto/2.1.1', + 'opera 10.00 on XP' => 'Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.00', + 'iron on win7' => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/531.0 (KHTML, like Gecko) Iron/3.0.189.0 Safari/531.0', + 'firefox 3.6 alpha on vista' => 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2a2pre) Gecko/20090826 Namoroka/3.6a2pre', + 'firefox 3.5 alpha on win7' => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1b4pre) Gecko/20090420 Shiretoko/3.5b4pre (.NET CLR 3.5.30729)', + 'firefox nightly build' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:2.0a1pre) Gecko/2008060602 Minefield/4.0a1pre', + 'thunderbird 14.0 with lightning 1.6' => 'Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20120713 Thunderbird/14.0 Lightning/1.6', ); echo "Test with another user agent: "; -foreach($testUserAgent as $name => $userAgent) { - echo "<a href='?setUserAgent=".urlencode($userAgent)."'>$name</a>, "; +foreach ($testUserAgent as $name => $userAgent) { + echo "<a href='?setUserAgent=" . urlencode($userAgent) . "'>$name</a>, "; } echo "<hr>"; -if(isset($_GET['setUserAgent']) && !empty($_GET['setUserAgent'])) { - echo "User Agent:"; - $userAgent = urldecode($_GET['setUserAgent']); +if (isset($_GET['setUserAgent']) && !empty($_GET['setUserAgent'])) { + echo "User Agent:"; + $userAgent = urldecode($_GET['setUserAgent']); } else { - echo "Your user agent:"; - $userAgent = $_SERVER['HTTP_USER_AGENT']; + echo "Your user agent:"; + $userAgent = $_SERVER['HTTP_USER_AGENT']; } -echo " <b>".htmlentities($userAgent)."</b><br><br>"; +echo " <b>" . htmlentities($userAgent) . "</b><br><br>"; echo "Browser info:<pre>"; var_dump(UserAgentParser::getBrowser($userAgent)); |