123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Backend\Block\Dashboard;
- /**
- * Adminhtml dashboard google chart block
- *
- * @author Magento Core Team <core@magentocommerce.com>
- */
- class Graph extends \Magento\Backend\Block\Dashboard\AbstractDashboard
- {
- /**
- * Api URL
- */
- const API_URL = 'http://chart.apis.google.com/chart';
- /**
- * All series
- *
- * @var array
- */
- protected $_allSeries = [];
- /**
- * Axis labels
- *
- * @var array
- */
- protected $_axisLabels = [];
- /**
- * Axis maps
- *
- * @var array
- */
- protected $_axisMaps = [];
- /**
- * Data rows
- *
- * @var array
- */
- protected $_dataRows = [];
- /**
- * Simple encoding chars
- *
- * @var string
- */
- protected $_simpleEncoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
- /**
- * Extended encoding chars
- *
- * @var string
- */
- protected $_extendedEncoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.';
- /**
- * Chart width
- *
- * @var string
- */
- protected $_width = '780';
- /**
- * Chart height
- *
- * @var string
- */
- protected $_height = '384';
- /**
- * Google chart api data encoding
- *
- * @var string
- */
- protected $_encoding = 'e';
- /**
- * Html identifier
- *
- * @var string
- */
- protected $_htmlId = '';
- /**
- * @var string
- */
- protected $_template = 'Magento_Backend::dashboard/graph.phtml';
- /**
- * Adminhtml dashboard data
- *
- * @var \Magento\Backend\Helper\Dashboard\Data
- */
- protected $_dashboardData = null;
- /**
- * @param \Magento\Backend\Block\Template\Context $context
- * @param \Magento\Reports\Model\ResourceModel\Order\CollectionFactory $collectionFactory
- * @param \Magento\Backend\Helper\Dashboard\Data $dashboardData
- * @param array $data
- */
- public function __construct(
- \Magento\Backend\Block\Template\Context $context,
- \Magento\Reports\Model\ResourceModel\Order\CollectionFactory $collectionFactory,
- \Magento\Backend\Helper\Dashboard\Data $dashboardData,
- array $data = []
- ) {
- $this->_dashboardData = $dashboardData;
- parent::__construct($context, $collectionFactory, $data);
- }
- /**
- * Get tab template
- *
- * @return string
- */
- protected function _getTabTemplate()
- {
- return 'dashboard/graph.phtml';
- }
- /**
- * Set data rows
- *
- * @param array $rows
- * @return void
- */
- public function setDataRows($rows)
- {
- $this->_dataRows = (array)$rows;
- }
- /**
- * Add series
- *
- * @param string $seriesId
- * @param array $options
- * @return void
- */
- public function addSeries($seriesId, array $options)
- {
- $this->_allSeries[$seriesId] = $options;
- }
- /**
- * Get series
- *
- * @param string $seriesId
- * @return array|false
- */
- public function getSeries($seriesId)
- {
- if (isset($this->_allSeries[$seriesId])) {
- return $this->_allSeries[$seriesId];
- } else {
- return false;
- }
- }
- /**
- * Get all series
- *
- * @return array
- */
- public function getAllSeries()
- {
- return $this->_allSeries;
- }
- /**
- * Get chart url
- *
- * @param bool $directUrl
- * @return string
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
- * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
- * @SuppressWarnings(PHPMD.UnusedLocalVariable)
- */
- public function getChartUrl($directUrl = true)
- {
- $params = [
- 'cht' => 'lc',
- 'chf' => 'bg,s,ffffff',
- 'chco' => 'ef672f',
- 'chls' => '7',
- 'chxs' => '0,676056,15,0,l,676056|1,676056,15,0,l,676056',
- 'chm' => 'h,f2ebde,0,0:1:.1,1,-1',
- ];
- $this->_allSeries = $this->getRowsData($this->_dataRows);
- foreach ($this->_axisMaps as $axis => $attr) {
- $this->setAxisLabels($axis, $this->getRowsData($attr, true));
- }
- $timezoneLocal = $this->_localeDate->getConfigTimezone();
- /** @var \DateTime $dateStart */
- /** @var \DateTime $dateEnd */
- list($dateStart, $dateEnd) = $this->_collectionFactory->create()->getDateRange(
- $this->getDataHelper()->getParam('period'),
- '',
- '',
- true
- );
- $dateStart->setTimezone(new \DateTimeZone($timezoneLocal));
- $dateEnd->setTimezone(new \DateTimeZone($timezoneLocal));
- if ($this->getDataHelper()->getParam('period') == '24h') {
- $dateEnd->modify('-1 hour');
- } else {
- $dateEnd->setTime(23, 59, 59);
- $dateStart->setTime(0, 0, 0);
- }
- $dates = [];
- $datas = [];
- while ($dateStart <= $dateEnd) {
- switch ($this->getDataHelper()->getParam('period')) {
- case '7d':
- case '1m':
- $d = $dateStart->format('Y-m-d');
- $dateStart->modify('+1 day');
- break;
- case '1y':
- case '2y':
- $d = $dateStart->format('Y-m');
- $dateStart->modify('+1 month');
- break;
- default:
- $d = $dateStart->format('Y-m-d H:00');
- $dateStart->modify('+1 hour');
- }
- foreach ($this->getAllSeries() as $index => $serie) {
- if (in_array($d, $this->_axisLabels['x'])) {
- $datas[$index][] = (double)array_shift($this->_allSeries[$index]);
- } else {
- $datas[$index][] = 0;
- }
- }
- $dates[] = $d;
- }
- /**
- * setting skip step
- */
- if (count($dates) > 8 && count($dates) < 15) {
- $c = 1;
- } else {
- if (count($dates) >= 15) {
- $c = 2;
- } else {
- $c = 0;
- }
- }
- /**
- * skipping some x labels for good reading
- */
- $i = 0;
- foreach ($dates as $k => $d) {
- if ($i == $c) {
- $dates[$k] = $d;
- $i = 0;
- } else {
- $dates[$k] = '';
- $i++;
- }
- }
- $this->_axisLabels['x'] = $dates;
- $this->_allSeries = $datas;
- //Google encoding values
- if ($this->_encoding == "s") {
- // simple encoding
- $params['chd'] = "s:";
- $dataDelimiter = "";
- $dataSetdelimiter = ",";
- $dataMissing = "_";
- } else {
- // extended encoding
- $params['chd'] = "e:";
- $dataDelimiter = "";
- $dataSetdelimiter = ",";
- $dataMissing = "__";
- }
- // process each string in the array, and find the max length
- $localmaxvalue = [0];
- $localminvalue = [0];
- foreach ($this->getAllSeries() as $index => $serie) {
- $localmaxvalue[$index] = max($serie);
- $localminvalue[$index] = min($serie);
- }
- $maxvalue = max($localmaxvalue);
- $minvalue = min($localminvalue);
- // default values
- $yrange = 0;
- $yLabels = [];
- $miny = 0;
- $maxy = 0;
- $yorigin = 0;
- if ($minvalue >= 0 && $maxvalue >= 0) {
- if ($maxvalue > 10) {
- $p = pow(10, $this->_getPow($maxvalue));
- $maxy = ceil($maxvalue / $p) * $p;
- $yLabels = range($miny, $maxy, $p);
- } else {
- $maxy = ceil($maxvalue + 1);
- $yLabels = range($miny, $maxy, 1);
- }
- $yrange = $maxy;
- $yorigin = 0;
- }
- $chartdata = [];
- foreach ($this->getAllSeries() as $index => $serie) {
- $thisdataarray = $serie;
- if ($this->_encoding == "s") {
- // SIMPLE ENCODING
- for ($j = 0; $j < sizeof($thisdataarray); $j++) {
- $currentvalue = $thisdataarray[$j];
- if (is_numeric($currentvalue)) {
- $ylocation = round(
- (strlen($this->_simpleEncoding) - 1) * ($yorigin + $currentvalue) / $yrange
- );
- $chartdata[] = substr($this->_simpleEncoding, $ylocation, 1) . $dataDelimiter;
- } else {
- $chartdata[] = $dataMissing . $dataDelimiter;
- }
- }
- } else {
- // EXTENDED ENCODING
- for ($j = 0; $j < sizeof($thisdataarray); $j++) {
- $currentvalue = $thisdataarray[$j];
- if (is_numeric($currentvalue)) {
- if ($yrange) {
- $ylocation = 4095 * ($yorigin + $currentvalue) / $yrange;
- } else {
- $ylocation = 0;
- }
- $firstchar = floor($ylocation / 64);
- $secondchar = $ylocation % 64;
- $mappedchar = substr(
- $this->_extendedEncoding,
- $firstchar,
- 1
- ) . substr(
- $this->_extendedEncoding,
- $secondchar,
- 1
- );
- $chartdata[] = $mappedchar . $dataDelimiter;
- } else {
- $chartdata[] = $dataMissing . $dataDelimiter;
- }
- }
- }
- $chartdata[] = $dataSetdelimiter;
- }
- $buffer = implode('', $chartdata);
- $buffer = rtrim($buffer, $dataSetdelimiter);
- $buffer = rtrim($buffer, $dataDelimiter);
- $buffer = str_replace($dataDelimiter . $dataSetdelimiter, $dataSetdelimiter, $buffer);
- $params['chd'] .= $buffer;
- $valueBuffer = [];
- if (sizeof($this->_axisLabels) > 0) {
- $params['chxt'] = implode(',', array_keys($this->_axisLabels));
- $indexid = 0;
- foreach ($this->_axisLabels as $idx => $labels) {
- if ($idx == 'x') {
- /**
- * Format date
- */
- foreach ($this->_axisLabels[$idx] as $_index => $_label) {
- if ($_label != '') {
- $period = new \DateTime($_label, new \DateTimeZone($timezoneLocal));
- switch ($this->getDataHelper()->getParam('period')) {
- case '24h':
- $this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime(
- $period->setTime($period->format('H'), 0, 0),
- \IntlDateFormatter::NONE,
- \IntlDateFormatter::SHORT
- );
- break;
- case '7d':
- case '1m':
- $this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime(
- $period,
- \IntlDateFormatter::SHORT,
- \IntlDateFormatter::NONE
- );
- break;
- case '1y':
- case '2y':
- $this->_axisLabels[$idx][$_index] = date('m/Y', strtotime($_label));
- break;
- }
- } else {
- $this->_axisLabels[$idx][$_index] = '';
- }
- }
- $tmpstring = implode('|', $this->_axisLabels[$idx]);
- $valueBuffer[] = $indexid . ":|" . $tmpstring;
- } elseif ($idx == 'y') {
- $valueBuffer[] = $indexid . ":|" . implode('|', $yLabels);
- }
- $indexid++;
- }
- $params['chxl'] = implode('|', $valueBuffer);
- }
- // chart size
- $params['chs'] = $this->getWidth() . 'x' . $this->getHeight();
- // return the encoded data
- if ($directUrl) {
- $p = [];
- foreach ($params as $name => $value) {
- $p[] = $name . '=' . urlencode($value);
- }
- return self::API_URL . '?' . implode('&', $p);
- } else {
- $gaData = urlencode(base64_encode(json_encode($params)));
- $gaHash = $this->_dashboardData->getChartDataHash($gaData);
- $params = ['ga' => $gaData, 'h' => $gaHash];
- return $this->getUrl('adminhtml/*/tunnel', ['_query' => $params]);
- }
- }
- /**
- * Get rows data
- *
- * @param array $attributes
- * @param bool $single
- * @return array
- */
- protected function getRowsData($attributes, $single = false)
- {
- $items = $this->getCollection()->getItems();
- $options = [];
- foreach ($items as $item) {
- if ($single) {
- $options[] = max(0, $item->getData($attributes));
- } else {
- foreach ((array)$attributes as $attr) {
- $options[$attr][] = max(0, $item->getData($attr));
- }
- }
- }
- return $options;
- }
- /**
- * Set axis labels
- *
- * @param string $axis
- * @param array $labels
- * @return void
- */
- public function setAxisLabels($axis, $labels)
- {
- $this->_axisLabels[$axis] = $labels;
- }
- /**
- * Set html id
- *
- * @param string $htmlId
- * @return void
- */
- public function setHtmlId($htmlId)
- {
- $this->_htmlId = $htmlId;
- }
- /**
- * Get html id
- *
- * @return string
- */
- public function getHtmlId()
- {
- return $this->_htmlId;
- }
- /**
- * Return pow
- *
- * @param int $number
- * @return int
- */
- protected function _getPow($number)
- {
- $pow = 0;
- while ($number >= 10) {
- $number = $number / 10;
- $pow++;
- }
- return $pow;
- }
- /**
- * Return chart width
- *
- * @return string
- */
- protected function getWidth()
- {
- return $this->_width;
- }
- /**
- * Return chart height
- *
- * @return string
- */
- protected function getHeight()
- {
- return $this->_height;
- }
- /**
- * @param \Magento\Backend\Helper\Dashboard\AbstractDashboard $dataHelper
- * @return void
- */
- public function setDataHelper(\Magento\Backend\Helper\Dashboard\AbstractDashboard $dataHelper)
- {
- $this->_dataHelper = $dataHelper;
- }
- /**
- * Prepare chart data
- *
- * @return void
- */
- protected function _prepareData()
- {
- if ($this->_dataHelper !== null) {
- $availablePeriods = array_keys($this->_dashboardData->getDatePeriods());
- $period = $this->getRequest()->getParam('period');
- $this->getDataHelper()->setParam(
- 'period',
- $period && in_array($period, $availablePeriods) ? $period : '24h'
- );
- }
- }
- }
|