File Manager

Current Directory: /home/astoriaah/www/old15/administrator/components/com_sh404sef/helpers
Viewing File: /home/astoriaah/www/old15/administrator/components/com_sh404sef/helpers/analytics.php
<?php /** * sh404SEF - SEO extension for Joomla! * * @author Yannick Gaultier * @copyright (c) Yannick Gaultier 2014 * @package sh404SEF * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL * @version 4.4.4.1791 * @date 2014-07-01 */ // Security check to ensure this file is being included by a parent file. if (!defined('_JEXEC')) die('Direct Access to this location is not allowed.'); class Sh404sefHelperAnalytics { // store whether doing a forced update. Reason to store it // is to keep _doCheck() method w/o any parameters // as this would otherwise prevent caching from operating // normally private static $_options = false; /** * Figure out if analytics collection is enabled * */ public static function isEnabled() { $config = Sh404sefFactory::getConfig(); return $config->analyticsEdition != 'none'; } /** * Obtain analytics information, as stored in cache * by checkAnalytics * */ public static function getData( $options) { // main option: are we forcing update, or only using the cached data ? $options['forced'] = empty( $options['forced']) ? 0 : $options['forced']; $sefConfig = Sh404sefFactory::getConfig(); $dataTypeString = str_replace( 'ga:', '', $sefConfig->analyticsDashboardDataType); // store options self::$_options = $options; // create cache Id and get cache object $cacheId = md5( $dataTypeString . $options['accountId'] . $options['showFilters'] . $options['groupBy'] . $options['startDate'] . $options['endDate'] . $options['cpWidth'] . $options['report'] . $options['subrequest']); $cache = JFactory::getCache( 'sh404sef_analytics'); $cache->setLifetime( 60); // cache result for 1 hours $cache->setCaching(1); // force caching on // empty cache if we are going to look for updates or if reports are disabled (so that next time // they enabled, we start wih fresh data if(self::$_options['forced'] || !$sefConfig->analyticsReportsEnabled) { // clean our cache $cache->remove( $cacheId); } $response = $cache->get( array( 'Sh404sefHelperAnalytics', '_doCheck'), $args = array(), $cacheId); // return response, either dummy or from cache return $response; } public static function _doCheck() { jimport( 'joomla.error.profiler' ); // creating the profiler object will start the counter $profiler = JProfiler::getInstance( 'sh404sef_analytics_profiler' ); // if not set to auto check and not forced to do so // when user click on "check updates" button // we don't actually try to get updates info $sefConfig = & Sh404sefFactory::getConfig(); // check if allowed to auto check, w/o user clicking on button if (!$sefConfig->autoCheckNewAnalytics && !self::$_options['forced']) { // prepare a default response object $response = new stdClass(); $response->status = true; $response->statusMessage = JText::_('COM_SH404SEF_CLICK_TO_CHECK_ANALYTICS'); $response->note = ''; return $response; } // calculate adapted class name $className = 'Sh404sefAdapterAnalytics' . strtolower( $sefConfig->analyticsType); $handler = new $className(); // ask specialized class to fetch analytics data $response = $handler->fetchAnalytics( $sefConfig, self::$_options); // done; send response back return $response; } public static function getHttpClient() { static $_instance = null; if (is_null( $_instance)) { // get an http client $_instance = new Zendshl_Http_Client; // set params $_instance->setConfig( array ( 'maxredirects' => 5, 'timeout' => 10)); } return $_instance; } public static function verifyAuthResponse( $response) { // check if valid response http code $status = $response->getStatus(); if ($status != 200) { throw new Sh404sefExceptionDefault( JText::_('COM_SH404SEF_ERROR_AUTH_ANALYTICS') . '(' . $status . ')'); } } public static function getRequestOptions( $context = '') { $options = array(); // if showing filter, we're on the main analytics manager view $options['showFilters'] = JRequest::getCmd( 'showFilters', 'yes'); // use that in the context where display options are stored, to differentiate // dashboard from analytics manager $context = empty( $context) ? 'sh404sef_analytics_' : $context; $context .= '_' . ( $options['showFilters'] == 'yes' ? 'manager' : 'dashboard'); $options['forced'] = JRequest::getInt( 'forced', 0); $options['startDate'] = JRequest::getString( 'startDate', ''); $options['endDate'] = JRequest::getString( 'endDate', ''); $options['groupBy'] = JRequest::getString( 'groupBy', ''); $options['cpWidth'] = JRequest::getInt( 'cpWidth'); $options['report'] = JRequest::getCmd( 'report', 'dashboard'); $options['subrequest'] = JRequest::getCmd( 'subrequest', ''); // default max number of results $options['max-results'] = '100'; // max out width for dashboard if ($options['report'] == 'dashboard' && $options['cpWidth'] > 800) { $options['cpWidth'] = 800; } // start and end dates $app = JFactory::getApplication(); // which web site to look at ? $options['accountId'] = ''; // if on dashboard, we use dates calculated from backend settings // else we use user set values (using calendar input boxes displayed // the Filters area if ($options['showFilters'] == 'yes') { // user selected dates, read user input $options['startDate'] = $app->getUserstateFromRequest( $context . 'startDate', 'startDate', '', 'string'); $options['endDate'] = $app->getUserstateFromRequest( $context . 'endDate', 'endDate', '', 'string'); $options['groupBy'] = $app->getUserstateFromRequest( $context . 'groupBy', 'groupBy', '', 'string'); if(empty( $options['groupBy'])) { // default to grouping by day $options['groupBy'] = self::_getDefaultGroupBy(); } $options['max-top-referrers'] = 15; $options['max-top-urls'] = 15; } else { $options['max-top-referrers'] = 5; $options['max-top-urls'] = 5; } if (empty( $options['startDate']) || empty( $options['endDate']) || $options['showFilters'] != 'yes') { // dashboard: calculate dates based on backend settings // end date is always yesterday $date = new DateTime( 'yesterday'); $options['endDate'] = $date->format('Y-m-d'); // use config to find what date range we should display : week, month or year $sefConfig = Sh404sefFactory::getConfig(); $date->modify( '-1 ' . $sefConfig->analyticsDashboardDateRange); $options['startDate'] = $date->format('Y-m-d'); // calculate groupBy options $options['groupBy'] = self::_getDefaultGroupBy(); } return $options; } /** * Search for current site in account list, in order * to find its Google id. If not found, defaults to * first site in list * * @param array of object $accounts */ public static function getDefaultAccountId( $accounts) { $id = 0; if (!empty( $accounts)) { // search for current site $current = Sh404sefHelperAnalytics::getWebsiteName(); foreach( $accounts as $account) { if (strpos( $current, $account->title) !== false or strpos( str_replace( 'www.', '', $current), $account->title) !== false) { $id = $account->id; break; } } // default to first account if no match found $id = empty( $id) ? $accounts[0]->id : $id; } return $id; } /** * Get this web site name, w/o scheme, port, etc * */ public static function getWebsiteName() { static $site; // Get the scheme if(!isset($site)) { $uri = JURI::getInstance( JURI::base()); $site = $uri->toString( array('host')); } return $site; } protected static function _getDefaultGroupBy() { $sefConfig = Sh404sefFactory::getConfig(); switch ($sefConfig->analyticsDashboardDateRange) { default: case 'week': $groupBy = 'ga:year,ga:month,ga:week,ga:day'; break; case 'month': $groupBy = 'ga:year,ga:month,ga:week'; break; case 'year': $groupBy = 'ga:year,ga:month'; break; } return $groupBy; } /** * Format an array of date strings for display as abscise * of a graphic * * @param array of object $entries * @param array $options */ public static function formatAbciseDates( $entries, $options) { // array to receive X labels $formattedDates = array(); // various cases of dimensions requested switch( $options['groupBy']) { case 'ga:year,ga:month,ga:week,ga:day': // date string represents a day. we use : mm/dd foreach( $entries as $entry) { $formattedDates[] = self::_getShortMonthString( $entry->dimension['month']) . ' ' . $entry->dimension['day']; } break; // date string represents a week number case 'ga:year,ga:month,ga:week': foreach( $entries as $entry) { $formattedDates[] = self::_getWeekPeriodString( $entry->dimension); } break; case 'ga:year,ga:month': // date string is a month number foreach( $entries as $entry) { $formattedDates[] = self::_getShortMonthString( $entry->dimension['month']) . ' ' . substr( $entry->dimension['year'], 2, 2); } break; } return $formattedDates; } protected static function _getShortMonthString( $month) { switch ($month) { case 1: $m = JText::_('JANUARY_SHORT'); break; case 2: $m = JText::_('FEBRUARY_SHORT'); break; case 3: $m = JText::_('MARCH_SHORT'); break; case 4: $m = JText::_('APRIL_SHORT'); break; case 5: $m = JText::_('MAY_SHORT'); break; case 6: $m = JText::_('JUNE_SHORT'); break; case 7: $m = JText::_('JULY_SHORT'); break; case 8: $m = JText::_('AUGUST_SHORT'); break; case 9: $m = JText::_('SEPTEMBER_SHORT'); break; case 10: $m = JText::_('OCTOBER_SHORT'); break; case 11: $m = JText::_('NOVEMBER_SHORT'); break; case 12: $m = JText::_('DECEMBER_SHORT'); break; } return $m; } protected static function _getWeekPeriodString ( $dimension) { // start jan 1st of that year $date = new DateTime ( $dimension['year'] . '-01-01'); // what day of week is that ? $janFirst = $date->format( 'w'); // if not a Sunday, we have at partial first week of year if ($janFirst != 0) { // jan first is not a Sunday, first add days for this first partial week $days = 6 - $janFirst; // then add days corresponding to the remaining number of weeks if ($dimension['week'] > 1) { $days += 7 * ($dimension['week']-1); } } else { // jan first is a sunday, we add 7 x number of weeks to jan first // to find date of LAST day of week #XX $days = 7 * $dimension['week'] -1; } // add as many days as required to find LAST day of week $date->modify( '+' . $days . ' days'); // then format result as needed $string = self::_getShortMonthString( $date->format( 'm')) . ' ' . $date->format( 'd'); return $string; } /** * Calculates a displayable label for Google raw medium type */ public static function getReferralLabel( $rawReferralType) { switch ($rawReferralType) { case '(none)': $label = JText::_('COM_SH404SEF_ANALYTICS_REF_LABEL_DIRECT'); break; case 'organic': $label = JText::_('COM_SH404SEF_ANALYTICS_REF_LABEL_ORGANIC'); break; case 'referral': $label = JText::_('COM_SH404SEF_ANALYTICS_REF_LABEL_REFERRAL'); break; default: $label = $rawReferralType; break; } return $label; } public static function getDataTypeTitle() { // need config, to know which data user wants to display : visits, unique visitors, pageviews $sefConfig = Sh404sefFactory::getConfig(); $dataType = $sefConfig->analyticsDashboardDataType; $dataTypeString = str_replace( 'ga:', '', $dataType); $label = JText::_( 'COM_SH404SEF_ANALYTICS_DATA_' . strtoupper( $dataTypeString)); return $label; } /** * Method to create a select list of possible analytics reports * * @access public * @param int ID of current item * @param string name of select list * @param boolean if true, changing selected item will submit the form (assume is an "adminForm") * @param boolean, if true, a line 'Select all' is inserted at the start of the list * @param string the "Select all" to be displayed, if $addSelectAll is true * @return string HTML output */ public static function buildAnalyticsReportSelectList( $current, $name, $autoSubmit = false, $addSelectAll = false, $selectAllTitle = '', $customSubmit = '') { // available reports, should not be hardcoded though ! $data = array( array( 'id' => 'dashboard', 'title' => JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_DASHBOARD')) ,array( 'id' => 'visits', 'title' => JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_VISITS')) ,array( 'id' => 'sources', 'title' => JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_SOURCES')) ,array( 'id' => 'keywords', 'title' => JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_KEYWORDS')) ,array( 'id' => 'urls', 'title' => JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_URLS')) ,array( 'id' => 'equipment', 'title' => JText::_( 'COM_SH404SEF_ANALYTICS_REPORT_VISITORS_EQUIPMENT')) ); // use helper to build html $list = Sh404sefHelperHtml::buildSelectList( $data, $current, $name, $autoSubmit, $addSelectAll, $selectAllTitle, $customSubmit); // return list return $list; } /** * Method to create a select list of possible ways to group data on analytics reports * * @access public * @param int ID of current item * @param string name of select list * @param boolean if true, changing selected item will submit the form (assume is an "adminForm") * @param boolean, if true, a line 'Select all' is inserted at the start of the list * @param string the "Select all" to be displayed, if $addSelectAll is true * @return string HTML output */ public static function buildAnalyticsGroupBySelectList( $current, $name, $autoSubmit = false, $addSelectAll = false, $selectAllTitle = '', $customSubmit = '') { // available reports, should not be hardcoded though ! $data = array( array( 'id' => 'ga:year,ga:month,ga:week,ga:day', 'title' => JText::_( 'Day')) ,array( 'id' => 'ga:year,ga:month,ga:week', 'title' => JText::_( 'Week')) ,array( 'id' => 'ga:year,ga:month', 'title' => JText::_( 'Month')) ); // use helper to build html $list = Sh404sefHelperHtml::buildSelectList( $data, $current, $name, $autoSubmit, $addSelectAll, $selectAllTitle, $customSubmit); // return list return $list; } public static function createTempFile( $basePath, $report) { // we use a temporary png file to display graphic // make sure we also have on in the base cache directory // compute filename, using current time, up to 1/100 of a sec $timestamp = floor(microtime(true) *100); $timestamp = str_replace( '.', '', $timestamp); $imageFileName = str_replace( DIRECTORY_SEPARATOR, '/', $basePath) . $timestamp . '.' . strtolower($report) .'.png'; return $imageFileName; } /** * Remove all png files older than a set time in provided directory * * @param $basePath * @param $age en secondes */ public static function cleanReportsImageFiles( $basePath, $age = 300) { // collect all png files in that directory $fileList = JFolder::files( $basePath, '.png'); // if any file, check them against age if (!empty( $fileList)) { // heure courante $timestamp = floor(microtime(true) *100) ; $timestamp = str_replace( '.', '', $timestamp); // ajuster l'age en centième de secondes $age = $age * 100; // calculate oldest file we can accept $oldestAllowed = $timestamp - $age; // iterate over files and delete the old ones foreach( $fileList as $file) { // file name format : timestamp.type.png, ie: "123456789.visits.datatype.png" $bits = explode('.', $file); $ts = $bits[0]; if ($ts < $oldestAllowed) { // remove that file jimport( 'joomla.filesystem.file'); $deleted = JFile::delete( $basePath . $file ); } } } } /** * Encode a time value, in seconds * to predefined numerical codes * using 6 bits (64 values) * @param float $time */ public static function classifyTime( $time) { // default $time = floatval( $time); // break it down to classes if ($time < 4.95) { // max value for that case is going to be 49 // convert to 1/10th of second $time = round($time * 10); // ie 1.9 sec becomes 19 } else if ($time < 6.0) { $time = 50; } else if ($time < 7) { $time = 51; } else if ($time < 8) { $time = 52; } else if ($time < 9) { $time = 53; } else if ($time < 10){ $time = 54; } else if ($time < 11){ $time = 55; } else if ($time < 12){ $time = 56; } else if ($time < 13){ $time = 57; } else if ($time < 14){ $time = 58; } else if ($time < 15){ $time = 59; } else if ($time < 20){ $time = 60; } else if ($time < 25){ $time = 61; } else if ($time < 30){ $time = 62; } else { $time = 63; } return $time; } /** * Revert classification of page creation time * to get back approximate time from value range * encoded in analytics data * * @param integer $time code as per classification function */ public static function declassifyTime( $time) { // break it down to classes if ($time < 50) { // actual time in 1/10th of sec // convert back to secondd $time = $time / 10; // ie 1.9 sec becomes 19 } else if ($time == 50) { // $time = 5.5; } else if ($time == 51) { // $time = 6.5; } else if ($time == 52) { // $time = 7.5; } else if ($time == 53) { // $time = 8.5; } else if ($time == 54) { // $time = 9.5; } else if ($time == 55) { // $time = 10.5; } else if ($time == 56) { // $time = 11.5; } else if ($time == 57) { // $time = 12.5; } else if ($time == 58) { // $time = 13.5; } else if ($time == 59) { // $time = 14.5; } else if ($time == 60) { // $time = 17.5; } else if ($time == 61) { // $time = 22.5; } else if ($time == 62) { // $time = 27.5; } else { $time = 40.0; // default value if time exceeds 30 seconds } return $time; } /** * Classify memory consumption into predefined * value ranges, to encode it into only 16 values * * @param float $ram ram used up by page creation */ public static function classifyMemory( $ram) { // default $ram = floatval( $ram); // break it down to classes if ($ram < 6) { $ram = 0; } else if ($ram < 8) { $ram = 1; } else if ($ram < 10) { $ram = 2; } else if ($ram < 12) { $ram = 3; } else if ($ram < 14) { $ram = 4; } else if ($ram < 16) { $ram = 5; } else if ($ram < 18) { $ram = 6; } else if ($ram < 20) { $ram = 7; } else if ($ram < 22) { $ram = 8; } else if ($ram < 24) { $ram = 9; } else if ($ram < 28) { $ram = 10; } else if ($ram < 32) { $ram = 11; } else if ($ram < 48) { $ram = 12; } else if ($ram < 64) { $ram = 13; } else if ($ram < 128) { $ram = 14; } else { $ram = 15; } return $ram; } /** * Revert classification of ram consumption * to get back approximate memory from value range * encoded in analytics data * * @param integer $ram code as per classification function */ public static function declassifyMemory( $ram) { $ramValues = array(3, 7, 9, 11, 13, 15, 17, 19, 21, 23, 26, 30, 40, 56, 96, 128); if (isset( $ramValues[$ram])) { $ram = $ramValues[$ram]; } else { $ram = 0; } return $ram; } }