Ejemplo n.º 1
0
 /**
  * The advanced factory method is easier to use from the API than the factory
  * method above. It doesn't require an instance of Piwik_Date and works for
  * period=range. Generally speaking, anything that can be passed as period
  * and range to the API methods can directly be forwarded to this factory
  * method in order to get a suitable instance of Piwik_Period.
  * 
  * @param string $strPeriod "day", "week", "month", "year", "range"
  * @param string $strDate
  * @return Piwik_Period
  */
 public static function advancedFactory($strPeriod, $strDate)
 {
     if (Piwik_Archive::isMultiplePeriod($strDate, $strPeriod) || $strPeriod == 'range') {
         return new Piwik_Period_Range($strPeriod, $strDate);
     }
     return self::factory($strPeriod, Piwik_Date::factory($strDate));
 }
Ejemplo n.º 2
0
 /**
  * Returns datatable describing the number of visits for each day of the week.
  * 
  * @param string $idSite The site ID. Cannot refer to multiple sites.
  * @param string $period The period type: day, week, year, range...
  * @param string $date The start date of the period. Cannot refer to multiple dates.
  * @param string $segment The segment.
  * @return Piwik_DataTable
  */
 public function getByDayOfWeek($idSite, $period, $date, $segment = false)
 {
     Piwik::checkUserHasViewAccess($idSite);
     // disabled for multiple sites/dates
     if (Piwik_Archive::isMultipleSites($idSite)) {
         throw new Exception("VisitTime.getByDayOfWeek does not support multiple sites.");
     }
     if (Piwik_Archive::isMultiplePeriod($date, $period)) {
         throw new Exception("VisitTime.getByDayOfWeek does not support multiple dates.");
     }
     // metrics to query
     $metrics = Piwik_ArchiveProcessing::getCoreMetrics();
     // get metric data for every day within the supplied period
     $oSite = new Piwik_Site($idSite);
     $oPeriod = Piwik_Archive::makePeriodFromQueryParams($oSite, $period, $date);
     $dateRange = $oPeriod->getDateStart()->toString() . ',' . $oPeriod->getDateEnd()->toString();
     $archive = Piwik_Archive::build($idSite, 'day', $dateRange, $segment);
     $dataTable = $archive->getDataTableFromNumeric($metrics)->mergeChildren();
     // if there's no data for this report, don't bother w/ anything else
     if ($dataTable->getRowsCount() == 0) {
         return $dataTable;
     }
     // group by the day of the week (see below for dayOfWeekFromDate function)
     $dataTable->filter('GroupBy', array('label', 'Piwik_VisitTime_dayOfWeekFromDate'));
     // create new datatable w/ empty rows, then add calculated datatable
     $rows = array();
     foreach (array(1, 2, 3, 4, 5, 6, 7) as $day) {
         $rows[] = array('label' => $day, 'nb_visits' => 0);
     }
     $result = new Piwik_DataTable();
     $result->addRowsFromSimpleArray($rows);
     $result->addDataTable($dataTable);
     // set day of week integer as metadata
     $result->filter('ColumnCallbackAddMetadata', array('label', 'day_of_week'));
     // translate labels
     $result->filter('ColumnCallbackReplace', array('label', 'Piwik_VisitTime_translateDayOfWeek'));
     // set datatable metadata for period start & finish
     $result->setMetadata('date_start', $oPeriod->getDateStart());
     $result->setMetadata('date_end', $oPeriod->getDateEnd());
     return $result;
 }
Ejemplo n.º 3
0
 public function getProcessedReport($idSite, $period, $date, $apiModule, $apiAction, $segment = false, $apiParameters = false, $idGoal = false, $language = false, $showTimer = true)
 {
     $timer = new Piwik_Timer();
     if ($apiParameters === false) {
         $apiParameters = array();
     }
     if (!empty($idGoal) && empty($apiParameters['idGoal'])) {
         $apiParameters['idGoal'] = $idGoal;
     }
     // Is this report found in the Metadata available reports?
     $reportMetadata = $this->getMetadata($idSite, $apiModule, $apiAction, $apiParameters, $language, $period, $date);
     if (empty($reportMetadata)) {
         throw new Exception("Requested report {$apiModule}.{$apiAction} for Website id={$idSite} not found in the list of available reports. \n");
     }
     $reportMetadata = reset($reportMetadata);
     // Generate Api call URL passing custom parameters
     $parameters = array_merge($apiParameters, array('method' => $apiModule . '.' . $apiAction, 'idSite' => $idSite, 'period' => $period, 'date' => $date, 'format' => 'original', 'serialize' => '0', 'language' => $language));
     if (!empty($segment)) {
         $parameters['segment'] = $segment;
     }
     $url = Piwik_Url::getQueryStringFromParameters($parameters);
     $request = new Piwik_API_Request($url);
     try {
         /** @var Piwik_DataTable */
         $dataTable = $request->process();
     } catch (Exception $e) {
         throw new Exception("API returned an error: " . $e->getMessage() . "\n");
     }
     list($newReport, $columns, $rowsMetadata) = $this->handleTableReport($idSite, $dataTable, $reportMetadata, isset($reportMetadata['dimension']));
     foreach ($columns as $columnId => &$name) {
         $name = ucfirst($name);
     }
     $website = new Piwik_Site($idSite);
     //    	$segment = new Piwik_Segment($segment, $idSite);
     if (Piwik_Archive::isMultiplePeriod($date, $period)) {
         $period = new Piwik_Period_Range($period, $date);
     } else {
         if ($period == 'range') {
             $period = new Piwik_Period_Range($period, $date);
         } else {
             $period = Piwik_Period::factory($period, Piwik_Date::factory($date));
         }
     }
     $period = $period->getLocalizedLongString();
     $return = array('website' => $website->getName(), 'prettyDate' => $period, 'metadata' => $reportMetadata, 'columns' => $columns, 'reportData' => $newReport, 'reportMetadata' => $rowsMetadata);
     if ($showTimer) {
         $return['timerMillis'] = $timer->getTimeMs(0);
     }
     return $return;
 }
Ejemplo n.º 4
0
 /** 
  * Given an API report to query (eg. "Referers.getKeywords", and a Label (eg. "free%20software"), 
  * this function will query the API for the previous days/weeks/etc. and will return 
  * a ready to use data structure containing the metrics for the requested Label, along with enriched information (min/max values, etc.) 
  * 
  * @return array
  */
 public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $idGoal = false, $legendAppendMetric = true, $labelUseAbsoluteUrl = true)
 {
     // validation of requested $period & $date
     if ($period == 'range') {
         // load days in the range
         $period = 'day';
     }
     if (!Piwik_Archive::isMultiplePeriod($date, $period)) {
         throw new Exception("Row evolutions can not be processed with this combination of \\'date\\' and \\'period\\' parameters.");
     }
     // this is needed because Piwik_API_Proxy uses Piwik_Common::getRequestVar which in turn
     // uses Piwik_Common::sanitizeInputValue. This causes the > that separates recursive labels
     // to become > and we need to undo that here.
     $label = Piwik_Common::unsanitizeInputValue($label);
     if ($label) {
         $labels = explode(',', $label);
         $labels = array_unique($labels);
     } else {
         $range = new Piwik_Period_Range($period, $date);
         $lastDate = $range->getDateEnd();
         // retrieve top labels for the most recent period
         $mostRecentDataTable = $this->loadRowEvolutionDataFromAPI($idSite, $period, $lastDate, $apiModule, $apiAction, null, $segment, $idGoal);
         $labels = $mostRecentDataTable->getColumn('label');
         //@review $labelCount can be equal to 0, this means there are no data what should this API return in that case?
         if (!count($labels)) {
             return null;
         }
     }
     if (count($labels) > 1) {
         $data = $this->getMultiRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $labels, $segment, $column, $language, $idGoal, $legendAppendMetric, $labelUseAbsoluteUrl);
     } else {
         $data = $this->getSingleRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $labels[0], $segment, $language, $idGoal, $labelUseAbsoluteUrl);
     }
     return $data;
 }
Ejemplo n.º 5
0
 /**
  * @param Piwik_Event_Notification $notification  notification object
  * @return mixed
  */
 public function getReportMetadata($notification)
 {
     $info = $notification->getNotificationInfo();
     $reports =& $notification->getNotificationObject();
     $idSites = $info['idSites'];
     // If only one website is selected, we add the Graph URL
     if (count($idSites) != 1) {
         return;
     }
     $idSite = reset($idSites);
     // in case API.getReportMetadata was not called with date/period we use sane defaults
     if (empty($info['period'])) {
         $info['period'] = 'day';
     }
     if (empty($info['date'])) {
         $info['date'] = 'today';
     }
     // need two sets of period & date, one for single period graphs, one for multiple periods graphs
     if (Piwik_Archive::isMultiplePeriod($info['date'], $info['period'])) {
         $periodForMultiplePeriodGraph = $info['period'];
         $dateForMultiplePeriodGraph = $info['date'];
         $periodForSinglePeriodGraph = 'range';
         $dateForSinglePeriodGraph = $info['date'];
     } else {
         $periodForSinglePeriodGraph = $info['period'];
         $dateForSinglePeriodGraph = $info['date'];
         $piwikSite = new Piwik_Site($idSite);
         if ($periodForSinglePeriodGraph == 'range') {
             $periodForMultiplePeriodGraph = Piwik_Config::getInstance()->General['graphs_default_period_to_plot_when_period_range'];
             $dateForMultiplePeriodGraph = $dateForSinglePeriodGraph;
         } else {
             $periodForMultiplePeriodGraph = $periodForSinglePeriodGraph;
             $dateForMultiplePeriodGraph = Piwik_Controller::getDateRangeRelativeToEndDate($periodForSinglePeriodGraph, 'last' . self::GRAPH_EVOLUTION_LAST_PERIODS, $dateForSinglePeriodGraph, $piwikSite);
         }
     }
     $token_auth = Piwik_Common::getRequestVar('token_auth', false);
     $urlPrefix = "index.php?";
     foreach ($reports as &$report) {
         $reportModule = $report['module'];
         $reportAction = $report['action'];
         $reportUniqueId = $reportModule . '_' . $reportAction;
         $parameters = array();
         $parameters['module'] = 'API';
         $parameters['method'] = 'ImageGraph.get';
         $parameters['idSite'] = $idSite;
         $parameters['apiModule'] = $reportModule;
         $parameters['apiAction'] = $reportAction;
         if (!empty($token_auth)) {
             $parameters['token_auth'] = $token_auth;
         }
         // Forward custom Report parameters to the graph URL
         if (!empty($report['parameters'])) {
             $parameters = array_merge($parameters, $report['parameters']);
         }
         if (empty($report['dimension'])) {
             $parameters['period'] = $periodForMultiplePeriodGraph;
             $parameters['date'] = $dateForMultiplePeriodGraph;
         } else {
             $parameters['period'] = $periodForSinglePeriodGraph;
             $parameters['date'] = $dateForSinglePeriodGraph;
         }
         // add the idSubtable if it exists
         $idSubtable = Piwik_Common::getRequestVar('idSubtable', false);
         if ($idSubtable !== false) {
             $parameters['idSubtable'] = $idSubtable;
         }
         $report['imageGraphUrl'] = $urlPrefix . Piwik_Url::getQueryStringFromParameters($parameters);
         // thanks to API.getRowEvolution, reports with dimensions can now be plotted using an evolution graph
         // however, most reports with a fixed set of dimension values are excluded
         // this is done so Piwik Mobile and Scheduled Reports do not display them
         if (empty($report['constantRowsCount']) || in_array($reportUniqueId, self::$CONSTANT_ROW_COUNT_REPORT_EXCEPTIONS)) {
             $parameters['period'] = $periodForMultiplePeriodGraph;
             $parameters['date'] = $dateForMultiplePeriodGraph;
             $report['imageGraphEvolutionUrl'] = $urlPrefix . Piwik_Url::getQueryStringFromParameters($parameters);
         }
     }
 }
Ejemplo n.º 6
0
 public function getReportMetadata($notification)
 {
     $info = $notification->getNotificationInfo();
     $reports =& $notification->getNotificationObject();
     $idSites = $info['idSites'];
     // If only one website is selected, we add the Graph URL
     if (count($idSites) != 1) {
         return;
     }
     $idSite = reset($idSites);
     // in case API.getReportMetadata was not called with date/period we use sane defaults
     if (empty($info['period'])) {
         $info['period'] = 'day';
     }
     if (empty($info['date'])) {
         $info['date'] = 'today';
     }
     // need two sets of period & date, one for single period graphs, one for multiple periods graphs
     if (Piwik_Archive::isMultiplePeriod($info['date'], $info['period'])) {
         $periodForMultiplePeriodGraph = $info['period'];
         $dateForMultiplePeriodGraph = $info['date'];
         $periodForSinglePeriodGraph = 'range';
         $dateForSinglePeriodGraph = $info['date'];
     } else {
         $periodForSinglePeriodGraph = $info['period'];
         $dateForSinglePeriodGraph = $info['date'];
         $piwikSite = new Piwik_Site($idSite);
         if ($periodForSinglePeriodGraph == 'range') {
             $periodForMultiplePeriodGraph = Zend_Registry::get('config')->General->graphs_default_period_to_plot_when_period_range;
             $dateForMultiplePeriodGraph = $dateForSinglePeriodGraph;
         } else {
             $periodForMultiplePeriodGraph = $periodForSinglePeriodGraph;
             $dateForMultiplePeriodGraph = Piwik_Controller::getDateRangeRelativeToEndDate($periodForSinglePeriodGraph, 'last' . self::GRAPH_EVOLUTION_LAST_PERIODS, $dateForSinglePeriodGraph, $piwikSite);
         }
     }
     $token_auth = Piwik_Common::getRequestVar('token_auth', false);
     $urlPrefix = "index.php?";
     foreach ($reports as &$report) {
         $parameters = array();
         $parameters['module'] = 'API';
         $parameters['method'] = 'ImageGraph.get';
         $parameters['idSite'] = $idSite;
         $parameters['apiModule'] = $report['module'];
         $parameters['apiAction'] = $report['action'];
         if (!empty($token_auth)) {
             $parameters['token_auth'] = $token_auth;
         }
         // Forward custom Report parameters to the graph URL
         if (!empty($report['parameters'])) {
             $parameters = array_merge($parameters, $report['parameters']);
         }
         if (empty($report['dimension'])) {
             $parameters['period'] = $periodForMultiplePeriodGraph;
             $parameters['date'] = $dateForMultiplePeriodGraph;
         } else {
             $parameters['period'] = $periodForSinglePeriodGraph;
             $parameters['date'] = $dateForSinglePeriodGraph;
         }
         $report['imageGraphUrl'] = $urlPrefix . Piwik_Url::getQueryStringFromParameters($parameters);
     }
 }
Ejemplo n.º 7
0
 /**
  * Returns true if it is likely that the data for this report has been purged and if the
  * user should be told about that.
  * 
  * In order for this function to return true, the following must also be true:
  * - The data table for this report must either be empty or not have been fetched.
  * - The period of this report is not a multiple period.
  * - The date of this report must be older than the delete_reports_older_than config option.
  * @return bool
  */
 public function hasReportBeenPurged()
 {
     $strPeriod = Piwik_Common::getRequestVar('period', false);
     $strDate = Piwik_Common::getRequestVar('date', false);
     if ($strPeriod !== false && $strDate !== false && (is_null($this->dataTable) || $this->dataTable->getRowsCount() == 0)) {
         // if range, only look at the first date
         if ($strPeriod == 'range') {
             $idSite = Piwik_Common::getRequestVar('idSite', '');
             if (intval($idSite) != 0) {
                 $site = new Piwik_Site($idSite);
                 $timezone = $site->getTimezone();
             } else {
                 $timezone = 'UTC';
             }
             $period = new Piwik_Period_Range('range', $strDate, $timezone);
             $reportDate = $period->getDateStart();
         } else {
             if (Piwik_Archive::isMultiplePeriod($strDate, $strPeriod)) {
                 return false;
             } else {
                 $reportDate = Piwik_Date::factory($strDate);
             }
         }
         $reportYear = $reportDate->toString('Y');
         $reportMonth = $reportDate->toString('m');
         if (class_exists('Piwik_PrivacyManager') && Piwik_PrivacyManager::shouldReportBePurged($reportYear, $reportMonth)) {
             return true;
         }
     }
     return false;
 }
Ejemplo n.º 8
0
 public function get($idSite, $period, $date, $apiModule, $apiAction, $graphType = false, $outputType = Piwik_ImageGraph_API::GRAPH_OUTPUT_INLINE, $column = false, $showMetricTitle = true, $width = false, $height = false, $fontSize = Piwik_ImageGraph_API::DEFAULT_FONT_SIZE, $aliasedGraph = true, $colors = false)
 {
     Piwik::checkUserHasViewAccess($idSite);
     // Health check - should we also test for GD2 only?
     if (!Piwik::isGdExtensionEnabled()) {
         throw new Exception('Error: To create graphs in Piwik, please enable GD php extension (with Freetype support) in php.ini, and restart your web server.');
     }
     $useUnicodeFont = array('am', 'ar', 'el', 'fa', 'fi', 'he', 'ja', 'ka', 'ko', 'te', 'th', 'zh-cn', 'zh-tw');
     $languageLoaded = Piwik_Translate::getInstance()->getLanguageLoaded();
     $font = self::getFontPath(self::DEFAULT_FONT);
     if (in_array($languageLoaded, $useUnicodeFont)) {
         $unicodeFontPath = self::getFontPath(self::UNICODE_FONT);
         $font = file_exists($unicodeFontPath) ? $unicodeFontPath : $font;
     }
     // save original GET to reset after processing. Important for API-in-API-call
     $savedGET = $_GET;
     try {
         //Fetch the metadata for given api-action
         $metadata = Piwik_API_API::getInstance()->getMetadata($idSite, $apiModule, $apiAction, $apiParameters = array(), $languageLoaded, $period, $date);
         if (!$metadata) {
             throw new Exception('Invalid API Module and/or API Action');
         }
         $metadata = $metadata[0];
         $reportHasDimension = !empty($metadata['dimension']);
         $constantRowsCount = !empty($metadata['constantRowsCount']);
         $isMultiplePeriod = Piwik_Archive::isMultiplePeriod($date, $period);
         if ($reportHasDimension && $isMultiplePeriod || !$reportHasDimension && !$isMultiplePeriod) {
             throw new Exception('The graph cannot be drawn for this combination of \'date\' and \'period\' parameters.');
         }
         if (empty($graphType)) {
             if ($reportHasDimension) {
                 if ($constantRowsCount) {
                     $graphType = Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_VERTICAL_BAR;
                 } else {
                     $graphType = Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_HORIZONTAL_BAR;
                 }
             } else {
                 $graphType = Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_BASIC_LINE;
             }
             $reportUniqueId = $metadata['uniqueId'];
             if (isset(self::$DEFAULT_GRAPH_TYPE_OVERRIDE[$reportUniqueId])) {
                 $graphType = self::$DEFAULT_GRAPH_TYPE_OVERRIDE[$reportUniqueId];
             }
         } else {
             $availableGraphTypes = Piwik_ImageGraph_StaticGraph::getAvailableStaticGraphTypes();
             if (!in_array($graphType, $availableGraphTypes)) {
                 throw new Exception(Piwik_TranslateException('General_ExceptionInvalidStaticGraphType', array($graphType, implode(', ', $availableGraphTypes))));
             }
         }
         if (empty($width)) {
             $width = self::$DEFAULT_PARAMETERS[$graphType][self::WIDTH_KEY];
         }
         if (empty($height)) {
             $height = self::$DEFAULT_PARAMETERS[$graphType][self::HEIGHT_KEY];
         }
         if ($reportHasDimension) {
             $abscissaColumn = 'label';
         } else {
             // if it's a dimension-less report, the abscissa column can only be the date-index
             $abscissaColumn = 'date';
         }
         $reportColumns = array_merge(!empty($metadata['metrics']) ? $metadata['metrics'] : array(), !empty($metadata['processedMetrics']) ? $metadata['processedMetrics'] : array(), !empty($metadata['metricsGoal']) ? $metadata['metricsGoal'] : array(), !empty($metadata['processedMetricsGoal']) ? $metadata['processedMetricsGoal'] : array());
         $ordinateColumn = $column;
         if (empty($ordinateColumn)) {
             $ordinateColumn = self::DEFAULT_ORDINATE_METRIC;
             // if default ordinate metric not available for this report
             if (empty($reportColumns[$ordinateColumn])) {
                 // take the first metric returned in the metadata
                 $ordinateColumn = key($metadata['metrics']);
             }
         }
         // if we still don't have an ordinate column or the one provided by the API caller is invalid
         if (empty($ordinateColumn) || empty($reportColumns[$ordinateColumn])) {
             throw new Exception(Piwik_Translate('ImageGraph_ColumnOrdinateMissing', $ordinateColumn));
         }
         $ordinateLabel = $reportColumns[$ordinateColumn];
         // sort and truncate filters
         $defaultFilterTruncate = self::$DEFAULT_PARAMETERS[$graphType][self::TRUNCATE_KEY];
         switch ($graphType) {
             case Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_3D_PIE:
             case Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_BASIC_PIE:
                 $_GET['filter_sort_column'] = $ordinateColumn;
                 $this->setFilterTruncate($defaultFilterTruncate);
                 break;
             case Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_VERTICAL_BAR:
             case Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_BASIC_LINE:
                 if ($reportHasDimension && !$constantRowsCount) {
                     $this->setFilterTruncate($defaultFilterTruncate);
                 }
                 break;
         }
         $processedReport = Piwik_API_API::getInstance()->getProcessedReport($idSite, $period, $date, $apiModule, $apiAction, $segment = false, $apiParameters = false, $idGoal = false, $languageLoaded);
         // prepare abscissa and ordinate series
         $abscissaSerie = array();
         $ordinateSerie = array();
         $ordinateLogos = array();
         $reportData = $processedReport['reportData'];
         $hasData = false;
         $hasNonZeroValue = false;
         if ($reportHasDimension) {
             $reportMetadata = $processedReport['reportMetadata']->getRows();
             $i = 0;
             // $reportData instanceof Piwik_DataTable
             foreach ($reportData->getRows() as $row) {
                 // $row instanceof Piwik_DataTable_Row
                 $rowData = $row->getColumns();
                 // Associative Array
                 $abscissaSerie[] = Piwik_Common::unsanitizeInputValue($rowData[$abscissaColumn]);
                 $parsedOrdinateValue = $this->parseOrdinateValue($rowData[$ordinateColumn]);
                 $hasData = true;
                 if ($parsedOrdinateValue != 0) {
                     $hasNonZeroValue = true;
                 }
                 $ordinateSerie[] = $parsedOrdinateValue;
                 if (isset($reportMetadata[$i])) {
                     $rowMetadata = $reportMetadata[$i]->getColumns();
                     if (isset($rowMetadata['logo'])) {
                         $ordinateLogos[$i] = $rowMetadata['logo'];
                     }
                 }
                 $i++;
             }
         } else {
             // $reportData instanceof Piwik_DataTable_Array
             $periodsMetadata = array_values($reportData->metadata);
             // $periodsData instanceof Piwik_DataTable_Simple[]
             $periodsData = array_values($reportData->getArray());
             $periodsCount = count($periodsMetadata);
             for ($i = 0; $i < $periodsCount; $i++) {
                 // $periodsData[$i] instanceof Piwik_DataTable_Simple
                 // $rows instanceof Piwik_DataTable_Row[]
                 $rows = $periodsData[$i]->getRows();
                 if (array_key_exists(0, $rows)) {
                     $rowData = $rows[0]->getColumns();
                     // associative Array
                     $ordinateValue = $rowData[$ordinateColumn];
                     $parsedOrdinateValue = $this->parseOrdinateValue($ordinateValue);
                     $hasData = true;
                     if ($parsedOrdinateValue != 0) {
                         $hasNonZeroValue = true;
                     }
                 } else {
                     $parsedOrdinateValue = 0;
                 }
                 $rowId = $periodsMetadata[$i]['period']->getLocalizedShortString();
                 $abscissaSerie[] = Piwik_Common::unsanitizeInputValue($rowId);
                 $ordinateSerie[] = $parsedOrdinateValue;
             }
         }
         if (!$hasData || !$hasNonZeroValue) {
             throw new Exception(Piwik_Translate('General_NoDataForGraph'));
         }
         //Setup the graph
         $graph = Piwik_ImageGraph_StaticGraph::factory($graphType);
         $graph->setWidth($width);
         $graph->setHeight($height);
         $graph->setFont($font);
         $graph->setFontSize($fontSize);
         $graph->setMetricTitle($ordinateLabel);
         $graph->setShowMetricTitle($showMetricTitle);
         $graph->setAliasedGraph($aliasedGraph);
         $graph->setAbscissaSerie($abscissaSerie);
         $graph->setOrdinateSerie($ordinateSerie);
         $graph->setOrdinateLogos($ordinateLogos);
         $graph->setColors(!empty($colors) ? explode(',', $colors) : array());
         // render graph
         $graph->renderGraph();
     } catch (Exception $e) {
         $graph = new Piwik_ImageGraph_StaticGraph_Exception();
         $graph->setWidth($width);
         $graph->setHeight($height);
         $graph->setFont($font);
         $graph->setFontSize($fontSize);
         $graph->setException($e);
         $graph->renderGraph();
     }
     // restoring get parameters
     $_GET = $savedGET;
     switch ($outputType) {
         case self::GRAPH_OUTPUT_FILE:
             // adding the idGoal to the filename
             $idGoal = Piwik_Common::getRequestVar('idGoal', '', 'string');
             if ($idGoal != '') {
                 $idGoal = '_' . $idGoal;
             }
             $fileName = self::$DEFAULT_PARAMETERS[$graphType][self::FILENAME_KEY] . '_' . $apiModule . '_' . $apiAction . $idGoal . ' ' . str_replace(',', '-', $date) . ' ' . $idSite . '.png';
             $fileName = str_replace(array(' ', '/'), '_', $fileName);
             if (!Piwik_Common::isValidFilename($fileName)) {
                 throw new Exception('Error: Image graph filename ' . $fileName . ' is not valid.');
             }
             return $graph->sendToDisk($fileName);
         case self::GRAPH_OUTPUT_PHP:
             return $graph->getRenderedImage();
         case self::GRAPH_OUTPUT_INLINE:
         default:
             $graph->sendToBrowser();
             exit;
     }
 }
Ejemplo n.º 9
0
 public function get($idSite, $period, $date, $apiModule, $apiAction, $graphType = false, $outputType = Piwik_ImageGraph_API::GRAPH_OUTPUT_INLINE, $columns = false, $labels = false, $showLegend = true, $width = false, $height = false, $fontSize = Piwik_ImageGraph_API::DEFAULT_FONT_SIZE, $legendFontSize = false, $aliasedGraph = true, $idGoal = false, $colors = false, $idSubtable = false, $legendAppendMetric = true)
 {
     Piwik::checkUserHasViewAccess($idSite);
     // Health check - should we also test for GD2 only?
     if (!Piwik::isGdExtensionEnabled()) {
         throw new Exception('Error: To create graphs in Piwik, please enable GD php extension (with Freetype support) in php.ini, and restart your web server.');
     }
     $useUnicodeFont = array('am', 'ar', 'el', 'fa', 'fi', 'he', 'ja', 'ka', 'ko', 'te', 'th', 'zh-cn', 'zh-tw');
     $languageLoaded = Piwik_Translate::getInstance()->getLanguageLoaded();
     $font = self::getFontPath(self::DEFAULT_FONT);
     if (in_array($languageLoaded, $useUnicodeFont)) {
         $unicodeFontPath = self::getFontPath(self::UNICODE_FONT);
         $font = file_exists($unicodeFontPath) ? $unicodeFontPath : $font;
     }
     // save original GET to reset after processing. Important for API-in-API-call
     $savedGET = $_GET;
     try {
         $apiParameters = array();
         if (!empty($idGoal)) {
             $apiParameters = array('idGoal' => $idGoal);
         }
         // Fetch the metadata for given api-action
         $metadata = Piwik_API_API::getInstance()->getMetadata($idSite, $apiModule, $apiAction, $apiParameters, $languageLoaded, $period, $date, $hideMetricsDoc = false, $showSubtableReports = true);
         if (!$metadata) {
             throw new Exception('Invalid API Module and/or API Action');
         }
         $metadata = $metadata[0];
         $reportHasDimension = !empty($metadata['dimension']);
         $constantRowsCount = !empty($metadata['constantRowsCount']);
         $isMultiplePeriod = Piwik_Archive::isMultiplePeriod($date, $period);
         if (!$reportHasDimension && !$isMultiplePeriod) {
             throw new Exception('The graph cannot be drawn for this combination of \'date\' and \'period\' parameters.');
         }
         if (empty($legendFontSize)) {
             $legendFontSize = $fontSize + self::DEFAULT_LEGEND_FONT_SIZE_OFFSET;
         }
         if (empty($graphType)) {
             if ($isMultiplePeriod) {
                 $graphType = Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_BASIC_LINE;
             } else {
                 if ($constantRowsCount) {
                     $graphType = Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_VERTICAL_BAR;
                 } else {
                     $graphType = Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_HORIZONTAL_BAR;
                 }
             }
             $reportUniqueId = $metadata['uniqueId'];
             if (isset(self::$DEFAULT_GRAPH_TYPE_OVERRIDE[$reportUniqueId][$isMultiplePeriod])) {
                 $graphType = self::$DEFAULT_GRAPH_TYPE_OVERRIDE[$reportUniqueId][$isMultiplePeriod];
             }
         } else {
             $availableGraphTypes = Piwik_ImageGraph_StaticGraph::getAvailableStaticGraphTypes();
             if (!in_array($graphType, $availableGraphTypes)) {
                 throw new Exception(Piwik_TranslateException('General_ExceptionInvalidStaticGraphType', array($graphType, implode(', ', $availableGraphTypes))));
             }
         }
         $width = (int) $width;
         $height = (int) $height;
         if (empty($width)) {
             $width = self::$DEFAULT_PARAMETERS[$graphType][self::WIDTH_KEY];
         }
         if (empty($height)) {
             $height = self::$DEFAULT_PARAMETERS[$graphType][self::HEIGHT_KEY];
         }
         // Cap width and height to a safe amount
         $width = min($width, self::MAX_WIDTH);
         $height = min($height, self::MAX_HEIGHT);
         $reportColumns = array_merge(!empty($metadata['metrics']) ? $metadata['metrics'] : array(), !empty($metadata['processedMetrics']) ? $metadata['processedMetrics'] : array(), !empty($metadata['metricsGoal']) ? $metadata['metricsGoal'] : array(), !empty($metadata['processedMetricsGoal']) ? $metadata['processedMetricsGoal'] : array());
         $ordinateColumns = array();
         if (empty($columns)) {
             $ordinateColumns[] = empty($reportColumns[self::DEFAULT_ORDINATE_METRIC]) ? key($metadata['metrics']) : self::DEFAULT_ORDINATE_METRIC;
         } else {
             $ordinateColumns = explode(',', $columns);
             foreach ($ordinateColumns as $column) {
                 if (empty($reportColumns[$column])) {
                     throw new Exception(Piwik_Translate('ImageGraph_ColumnOrdinateMissing', array($column, implode(',', array_keys($reportColumns)))));
                 }
             }
         }
         $ordinateLabels = array();
         foreach ($ordinateColumns as $column) {
             $ordinateLabels[$column] = $reportColumns[$column];
         }
         // sort and truncate filters
         $defaultFilterTruncate = self::$DEFAULT_PARAMETERS[$graphType][self::TRUNCATE_KEY];
         switch ($graphType) {
             case Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_3D_PIE:
             case Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_BASIC_PIE:
                 if (count($ordinateColumns) > 1) {
                     // pChart doesn't support multiple series on pie charts
                     throw new Exception("Pie charts do not currently support multiple series");
                 }
                 $_GET['filter_sort_column'] = reset($ordinateColumns);
                 $this->setFilterTruncate($defaultFilterTruncate);
                 break;
             case Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_VERTICAL_BAR:
             case Piwik_ImageGraph_StaticGraph::GRAPH_TYPE_BASIC_LINE:
                 if (!$isMultiplePeriod && !$constantRowsCount) {
                     $this->setFilterTruncate($defaultFilterTruncate);
                 }
                 break;
         }
         $ordinateLogos = array();
         // row evolutions
         if ($isMultiplePeriod && $reportHasDimension) {
             $plottedMetric = reset($ordinateColumns);
             // when no labels are specified, getRowEvolution returns the top N=filter_limit row evolutions
             // rows are sorted using filter_sort_column (see Piwik_API_DataTableGenericFilter for more info)
             if (!$labels) {
                 $savedFilterSortColumnValue = Piwik_Common::getRequestVar('filter_sort_column', '');
                 $_GET['filter_sort_column'] = $plottedMetric;
                 $savedFilterLimitValue = Piwik_Common::getRequestVar('filter_limit', -1, 'int');
                 if ($savedFilterLimitValue == -1 || $savedFilterLimitValue > self::MAX_NB_ROW_LABELS) {
                     $_GET['filter_limit'] = self::DEFAULT_NB_ROW_EVOLUTIONS;
                 }
             }
             $processedReport = Piwik_API_API::getInstance()->getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $labels, $segment = false, $plottedMetric, $languageLoaded, $idGoal, $legendAppendMetric, $labelUseAbsoluteUrl = false);
             //@review this test will need to be updated after evaluating the @review comment in API/API.php
             if (!$processedReport) {
                 throw new Exception(Piwik_Translate('General_NoDataForGraph'));
             }
             // restoring generic filter parameters
             if (!$labels) {
                 $_GET['filter_sort_column'] = $savedFilterSortColumnValue;
                 if ($savedFilterLimitValue != -1) {
                     $_GET['filter_limit'] = $savedFilterLimitValue;
                 }
             }
             // retrieve metric names & labels
             $metrics = $processedReport['metadata']['metrics'];
             $ordinateLabels = array();
             // getRowEvolution returned more than one label
             if (!array_key_exists($plottedMetric, $metrics)) {
                 $ordinateColumns = array();
                 $i = 0;
                 foreach ($metrics as $metric => $info) {
                     $ordinateColumn = $plottedMetric . '_' . $i++;
                     $ordinateColumns[] = $metric;
                     $ordinateLabels[$ordinateColumn] = $info['name'];
                     if (isset($info['logo'])) {
                         $ordinateLogo = $info['logo'];
                         // @review pChart does not support gifs in graph legends, would it be possible to convert all plugin pictures (cookie.gif, flash.gif, ..) to png files?
                         if (!strstr($ordinateLogo, '.gif')) {
                             $absoluteLogoPath = self::getAbsoluteLogoPath($ordinateLogo);
                             if (file_exists($absoluteLogoPath)) {
                                 $ordinateLogos[$ordinateColumn] = $absoluteLogoPath;
                             }
                         }
                     }
                 }
             } else {
                 $ordinateLabels[$plottedMetric] = $processedReport['label'] . ' (' . $metrics[$plottedMetric]['name'] . ')';
             }
         } else {
             $processedReport = Piwik_API_API::getInstance()->getProcessedReport($idSite, $period, $date, $apiModule, $apiAction, $segment = false, $apiParameters = false, $idGoal, $languageLoaded, $showTimer = true, $hideMetricsDoc = false, $idSubtable);
         }
         // prepare abscissa and ordinate series
         $abscissaSeries = array();
         $abscissaLogos = array();
         $ordinateSeries = array();
         $reportData = $processedReport['reportData'];
         $hasData = false;
         $hasNonZeroValue = false;
         if (!$isMultiplePeriod) {
             $reportMetadata = $processedReport['reportMetadata']->getRows();
             $i = 0;
             // $reportData instanceof Piwik_DataTable
             foreach ($reportData->getRows() as $row) {
                 // $row instanceof Piwik_DataTable_Row
                 $rowData = $row->getColumns();
                 // Associative Array
                 $abscissaSeries[] = Piwik_Common::unsanitizeInputValue($rowData['label']);
                 foreach ($ordinateColumns as $column) {
                     $parsedOrdinateValue = $this->parseOrdinateValue($rowData[$column]);
                     $hasData = true;
                     if ($parsedOrdinateValue != 0) {
                         $hasNonZeroValue = true;
                     }
                     $ordinateSeries[$column][] = $parsedOrdinateValue;
                 }
                 if (isset($reportMetadata[$i])) {
                     $rowMetadata = $reportMetadata[$i]->getColumns();
                     if (isset($rowMetadata['logo'])) {
                         $absoluteLogoPath = self::getAbsoluteLogoPath($rowMetadata['logo']);
                         if (file_exists($absoluteLogoPath)) {
                             $abscissaLogos[$i] = $absoluteLogoPath;
                         }
                     }
                 }
                 $i++;
             }
         } else {
             // $reportData instanceof Piwik_DataTable_Array
             $periodsMetadata = array_values($reportData->metadata);
             // $periodsData instanceof Piwik_DataTable_Simple[]
             $periodsData = array_values($reportData->getArray());
             $periodsCount = count($periodsMetadata);
             for ($i = 0; $i < $periodsCount; $i++) {
                 // $periodsData[$i] instanceof Piwik_DataTable_Simple
                 // $rows instanceof Piwik_DataTable_Row[]
                 if (empty($periodsData[$i])) {
                     continue;
                 }
                 $rows = $periodsData[$i]->getRows();
                 if (array_key_exists(0, $rows)) {
                     $rowData = $rows[0]->getColumns();
                     // associative Array
                     foreach ($ordinateColumns as $column) {
                         $ordinateValue = $rowData[$column];
                         $parsedOrdinateValue = $this->parseOrdinateValue($ordinateValue);
                         $hasData = true;
                         if (!empty($parsedOrdinateValue)) {
                             $hasNonZeroValue = true;
                         }
                         $ordinateSeries[$column][] = $parsedOrdinateValue;
                     }
                 } else {
                     foreach ($ordinateColumns as $column) {
                         $ordinateSeries[$column][] = 0;
                     }
                 }
                 $rowId = $periodsMetadata[$i]['period']->getLocalizedShortString();
                 $abscissaSeries[] = Piwik_Common::unsanitizeInputValue($rowId);
             }
         }
         if (!$hasData || !$hasNonZeroValue) {
             throw new Exception(Piwik_Translate('General_NoDataForGraph'));
         }
         //Setup the graph
         $graph = Piwik_ImageGraph_StaticGraph::factory($graphType);
         $graph->setWidth($width);
         $graph->setHeight($height);
         $graph->setFont($font);
         $graph->setFontSize($fontSize);
         $graph->setLegendFontSize($legendFontSize);
         $graph->setOrdinateLabels($ordinateLabels);
         $graph->setShowLegend($showLegend);
         $graph->setAliasedGraph($aliasedGraph);
         $graph->setAbscissaSeries($abscissaSeries);
         $graph->setAbscissaLogos($abscissaLogos);
         $graph->setOrdinateSeries($ordinateSeries);
         $graph->setOrdinateLogos($ordinateLogos);
         $graph->setColors(!empty($colors) ? explode(',', $colors) : array());
         if ($period == 'day') {
             $graph->setForceSkippedLabels(6);
         }
         // render graph
         $graph->renderGraph();
     } catch (Exception $e) {
         $graph = new Piwik_ImageGraph_StaticGraph_Exception();
         $graph->setWidth($width);
         $graph->setHeight($height);
         $graph->setFont($font);
         $graph->setFontSize($fontSize);
         $graph->setException($e);
         $graph->renderGraph();
     }
     // restoring get parameters
     $_GET = $savedGET;
     switch ($outputType) {
         case self::GRAPH_OUTPUT_FILE:
             if ($idGoal != '') {
                 $idGoal = '_' . $idGoal;
             }
             $fileName = self::$DEFAULT_PARAMETERS[$graphType][self::FILENAME_KEY] . '_' . $apiModule . '_' . $apiAction . $idGoal . ' ' . str_replace(',', '-', $date) . ' ' . $idSite . '.png';
             $fileName = str_replace(array(' ', '/'), '_', $fileName);
             if (!Piwik_Common::isValidFilename($fileName)) {
                 throw new Exception('Error: Image graph filename ' . $fileName . ' is not valid.');
             }
             return $graph->sendToDisk($fileName);
         case self::GRAPH_OUTPUT_PHP:
             return $graph->getRenderedImage();
         case self::GRAPH_OUTPUT_INLINE:
         default:
             $graph->sendToBrowser();
             exit;
     }
 }