/magento/app/code/core/Mage/Adminhtml/Block/Dashboard/Graph.php

https://bitbucket.org/jit_bec/shopifine · PHP · 560 lines · 315 code · 54 blank · 191 comment · 57 complexity · 684420eadfcf98899d03f561c87fa49c MD5 · raw file

  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_Adminhtml
  23. * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * Adminhtml dashboard google chart block
  28. *
  29. * @category Mage
  30. * @package Mage_Adminhtml
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_Adminhtml_Block_Dashboard_Graph extends Mage_Adminhtml_Block_Dashboard_Abstract
  34. {
  35. /**
  36. * Api URL
  37. */
  38. const API_URL = 'http://chart.apis.google.com/chart';
  39. /**
  40. * All series
  41. *
  42. * @var array
  43. */
  44. protected $_allSeries = array();
  45. /**
  46. * Axis labels
  47. *
  48. * @var array
  49. */
  50. protected $_axisLabels = array();
  51. /**
  52. * Axis maps
  53. *
  54. * @var array
  55. */
  56. protected $_axisMaps = array();
  57. /**
  58. * Data rows
  59. *
  60. * @var array
  61. */
  62. protected $_dataRows = array();
  63. /**
  64. * Simple encoding chars
  65. *
  66. * @var string
  67. */
  68. protected $_simpleEncoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  69. /**
  70. * Extended encoding chars
  71. *
  72. * @var string
  73. */
  74. protected $_extendedEncoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.';
  75. /**
  76. * Chart width
  77. *
  78. * @var string
  79. */
  80. protected $_width = '587';
  81. /**
  82. * Chart height
  83. *
  84. * @var string
  85. */
  86. protected $_height = '300';
  87. /**
  88. * Google chart api data encoding
  89. *
  90. * @var string
  91. */
  92. protected $_encoding = 'e';
  93. /**
  94. * Html identifier
  95. *
  96. * @var string
  97. */
  98. protected $_htmlId = '';
  99. /**
  100. * Initialize object
  101. *
  102. * @return void
  103. */
  104. public function __construct()
  105. {
  106. parent::__construct();
  107. $this->setTemplate('dashboard/graph.phtml');
  108. }
  109. /**
  110. * Get tab template
  111. *
  112. * @return string
  113. */
  114. protected function _getTabTemplate()
  115. {
  116. return 'dashboard/graph.phtml';
  117. }
  118. /**
  119. * Set data rows
  120. *
  121. * @param mixed $rows
  122. * @return void
  123. */
  124. public function setDataRows($rows)
  125. {
  126. $this->_dataRows = (array)$rows;
  127. }
  128. /**
  129. * Add series
  130. *
  131. * @param string $seriesId
  132. * @param array $options
  133. * @return void
  134. */
  135. public function addSeries($seriesId, array $options)
  136. {
  137. $this->_allSeries[$seriesId] = $options;
  138. }
  139. /**
  140. * Get series
  141. *
  142. * @param string $seriesId
  143. * @return mixed
  144. */
  145. public function getSeries($seriesId)
  146. {
  147. if (isset($this->_allSeries[$seriesId])) {
  148. return $this->_allSeries[$seriesId];
  149. } else {
  150. return false;
  151. }
  152. }
  153. /**
  154. * Get all series
  155. *
  156. * @return array
  157. */
  158. public function getAllSeries()
  159. {
  160. return $this->_allSeries;
  161. }
  162. /**
  163. * Get chart url
  164. *
  165. * @param bool $directUrl
  166. * @return string
  167. */
  168. public function getChartUrl($directUrl = true)
  169. {
  170. $params = array(
  171. 'cht' => 'lc',
  172. 'chf' => 'bg,s,f4f4f4|c,lg,90,ffffff,0.1,ededed,0',
  173. 'chm' => 'B,f4d4b2,0,0,0',
  174. 'chco' => 'db4814'
  175. );
  176. $this->_allSeries = $this->getRowsData($this->_dataRows);
  177. foreach ($this->_axisMaps as $axis => $attr){
  178. $this->setAxisLabels($axis, $this->getRowsData($attr, true));
  179. }
  180. $timezoneLocal = Mage::app()->getStore()->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_TIMEZONE);
  181. list ($dateStart, $dateEnd) = Mage::getResourceModel('reports/order_collection')
  182. ->getDateRange($this->getDataHelper()->getParam('period'), '', '', true);
  183. $dateStart->setTimezone($timezoneLocal);
  184. $dateEnd->setTimezone($timezoneLocal);
  185. $dates = array();
  186. $datas = array();
  187. while($dateStart->compare($dateEnd) < 0){
  188. switch ($this->getDataHelper()->getParam('period')) {
  189. case '24h':
  190. $d = $dateStart->toString('yyyy-MM-dd HH:00');
  191. $dateStart->addHour(1);
  192. break;
  193. case '7d':
  194. case '1m':
  195. $d = $dateStart->toString('yyyy-MM-dd');
  196. $dateStart->addDay(1);
  197. break;
  198. case '1y':
  199. case '2y':
  200. $d = $dateStart->toString('yyyy-MM');
  201. $dateStart->addMonth(1);
  202. break;
  203. }
  204. foreach ($this->getAllSeries() as $index=>$serie) {
  205. if (in_array($d, $this->_axisLabels['x'])) {
  206. $datas[$index][] = (float)array_shift($this->_allSeries[$index]);
  207. } else {
  208. $datas[$index][] = 0;
  209. }
  210. }
  211. $dates[] = $d;
  212. }
  213. /**
  214. * setting skip step
  215. */
  216. if (count($dates) > 8 && count($dates) < 15) {
  217. $c = 1;
  218. } else if (count($dates) >= 15){
  219. $c = 2;
  220. } else {
  221. $c = 0;
  222. }
  223. /**
  224. * skipping some x labels for good reading
  225. */
  226. $i=0;
  227. foreach ($dates as $k => $d) {
  228. if ($i == $c) {
  229. $dates[$k] = $d;
  230. $i = 0;
  231. } else {
  232. $dates[$k] = '';
  233. $i++;
  234. }
  235. }
  236. $this->_axisLabels['x'] = $dates;
  237. $this->_allSeries = $datas;
  238. //Google encoding values
  239. if ($this->_encoding == "s") {
  240. // simple encoding
  241. $params['chd'] = "s:";
  242. $dataDelimiter = "";
  243. $dataSetdelimiter = ",";
  244. $dataMissing = "_";
  245. } else {
  246. // extended encoding
  247. $params['chd'] = "e:";
  248. $dataDelimiter = "";
  249. $dataSetdelimiter = ",";
  250. $dataMissing = "__";
  251. }
  252. // process each string in the array, and find the max length
  253. foreach ($this->getAllSeries() as $index => $serie) {
  254. $localmaxlength[$index] = sizeof($serie);
  255. $localmaxvalue[$index] = max($serie);
  256. $localminvalue[$index] = min($serie);
  257. }
  258. if (is_numeric($this->_max)) {
  259. $maxvalue = $this->_max;
  260. } else {
  261. $maxvalue = max($localmaxvalue);
  262. }
  263. if (is_numeric($this->_min)) {
  264. $minvalue = $this->_min;
  265. } else {
  266. $minvalue = min($localminvalue);
  267. }
  268. // default values
  269. $yrange = 0;
  270. $yLabels = array();
  271. $miny = 0;
  272. $maxy = 0;
  273. $yorigin = 0;
  274. $maxlength = max($localmaxlength);
  275. if ($minvalue >= 0 && $maxvalue >= 0) {
  276. $miny = 0;
  277. if ($maxvalue > 10) {
  278. $p = pow(10, $this->_getPow($maxvalue));
  279. $maxy = (ceil($maxvalue/$p))*$p;
  280. $yLabels = range($miny, $maxy, $p);
  281. } else {
  282. $maxy = ceil($maxvalue+1);
  283. $yLabels = range($miny, $maxy, 1);
  284. }
  285. $yrange = $maxy;
  286. $yorigin = 0;
  287. }
  288. $chartdata = array();
  289. foreach ($this->getAllSeries() as $index => $serie) {
  290. $thisdataarray = $serie;
  291. if ($this->_encoding == "s") {
  292. // SIMPLE ENCODING
  293. for ($j = 0; $j < sizeof($thisdataarray); $j++) {
  294. $currentvalue = $thisdataarray[$j];
  295. if (is_numeric($currentvalue)) {
  296. $ylocation = round((strlen($this->_simpleEncoding)-1) * ($yorigin + $currentvalue) / $yrange);
  297. array_push($chartdata, substr($this->_simpleEncoding, $ylocation, 1) . $dataDelimiter);
  298. } else {
  299. array_push($chartdata, $dataMissing . $dataDelimiter);
  300. }
  301. }
  302. // END SIMPLE ENCODING
  303. } else {
  304. // EXTENDED ENCODING
  305. for ($j = 0; $j < sizeof($thisdataarray); $j++) {
  306. $currentvalue = $thisdataarray[$j];
  307. if (is_numeric($currentvalue)) {
  308. if ($yrange) {
  309. $ylocation = (4095 * ($yorigin + $currentvalue) / $yrange);
  310. } else {
  311. $ylocation = 0;
  312. }
  313. $firstchar = floor($ylocation / 64);
  314. $secondchar = $ylocation % 64;
  315. $mappedchar = substr($this->_extendedEncoding, $firstchar, 1)
  316. . substr($this->_extendedEncoding, $secondchar, 1);
  317. array_push($chartdata, $mappedchar . $dataDelimiter);
  318. } else {
  319. array_push($chartdata, $dataMissing . $dataDelimiter);
  320. }
  321. }
  322. // ============= END EXTENDED ENCODING =============
  323. }
  324. array_push($chartdata, $dataSetdelimiter);
  325. }
  326. $buffer = implode('', $chartdata);
  327. $buffer = rtrim($buffer, $dataSetdelimiter);
  328. $buffer = rtrim($buffer, $dataDelimiter);
  329. $buffer = str_replace(($dataDelimiter . $dataSetdelimiter), $dataSetdelimiter, $buffer);
  330. $params['chd'] .= $buffer;
  331. $labelBuffer = "";
  332. $valueBuffer = array();
  333. $rangeBuffer = "";
  334. if (sizeof($this->_axisLabels) > 0) {
  335. $params['chxt'] = implode(',', array_keys($this->_axisLabels));
  336. $indexid = 0;
  337. foreach ($this->_axisLabels as $idx=>$labels){
  338. if ($idx == 'x') {
  339. /**
  340. * Format date
  341. */
  342. foreach ($this->_axisLabels[$idx] as $_index=>$_label) {
  343. if ($_label != '') {
  344. switch ($this->getDataHelper()->getParam('period')) {
  345. case '24h':
  346. $this->_axisLabels[$idx][$_index] = $this->formatTime(
  347. new Zend_Date($_label, 'yyyy-MM-dd HH:00'), 'short', false
  348. );
  349. break;
  350. case '7d':
  351. case '1m':
  352. $this->_axisLabels[$idx][$_index] = $this->formatDate(
  353. new Zend_Date($_label, 'yyyy-MM-dd')
  354. );
  355. break;
  356. case '1y':
  357. case '2y':
  358. $formats = Mage::app()->getLocale()->getTranslationList('datetime');
  359. $format = isset($formats['yyMM']) ? $formats['yyMM'] : 'MM/yyyy';
  360. $format = str_replace(array("yyyy", "yy", "MM"), array("Y", "y", "m"), $format);
  361. $this->_axisLabels[$idx][$_index] = date($format, strtotime($_label));
  362. break;
  363. }
  364. } else {
  365. $this->_axisLabels[$idx][$_index] = '';
  366. }
  367. }
  368. $tmpstring = implode('|', $this->_axisLabels[$idx]);
  369. $valueBuffer[] = $indexid . ":|" . $tmpstring;
  370. if (sizeof($this->_axisLabels[$idx]) > 1) {
  371. $deltaX = 100/(sizeof($this->_axisLabels[$idx])-1);
  372. } else {
  373. $deltaX = 100;
  374. }
  375. } else if ($idx == 'y') {
  376. $valueBuffer[] = $indexid . ":|" . implode('|', $yLabels);
  377. if (sizeof($yLabels)-1) {
  378. $deltaY = 100/(sizeof($yLabels)-1);
  379. } else {
  380. $deltaY = 100;
  381. }
  382. // setting range values for y axis
  383. $rangeBuffer = $indexid . "," . $miny . "," . $maxy . "|";
  384. }
  385. $indexid++;
  386. }
  387. $params['chxl'] = implode('|', $valueBuffer);
  388. };
  389. // chart size
  390. $params['chs'] = $this->getWidth().'x'.$this->getHeight();
  391. if (isset($deltaX) && isset($deltaY)) {
  392. $params['chg'] = $deltaX . ',' . $deltaY . ',1,0';
  393. }
  394. // return the encoded data
  395. if ($directUrl) {
  396. $p = array();
  397. foreach ($params as $name => $value) {
  398. $p[] = $name . '=' .urlencode($value);
  399. }
  400. return self::API_URL . '?' . implode('&', $p);
  401. } else {
  402. $gaData = urlencode(base64_encode(serialize($params)));
  403. $gaHash = Mage::helper('adminhtml/dashboard_data')->getChartDataHash($gaData);
  404. $params = array('ga' => $gaData, 'h' => $gaHash);
  405. return $this->getUrl('*/*/tunnel', array('_query' => $params));
  406. }
  407. }
  408. /**
  409. * Get rows data
  410. *
  411. * @param array $attributes
  412. * @param bool $single
  413. * @return array
  414. */
  415. protected function getRowsData($attributes, $single = false)
  416. {
  417. $items = $this->getCollection()->getItems();
  418. $options = array();
  419. foreach ($items as $item){
  420. if ($single) {
  421. $options[] = max(0, $item->getData($attributes));
  422. } else {
  423. foreach ((array)$attributes as $attr){
  424. $options[$attr][] = max(0, $item->getData($attr));
  425. }
  426. }
  427. }
  428. return $options;
  429. }
  430. /**
  431. * Set axis labels
  432. *
  433. * @param string $axis
  434. * @param array $labels
  435. * @return void
  436. */
  437. public function setAxisLabels($axis, $labels)
  438. {
  439. $this->_axisLabels[$axis] = $labels;
  440. }
  441. /**
  442. * Set html id
  443. *
  444. * @param string $htmlId
  445. * @return void
  446. */
  447. public function setHtmlId($htmlId)
  448. {
  449. $this->_htmlId = $htmlId;
  450. }
  451. /**
  452. * Get html id
  453. *
  454. * @return string
  455. */
  456. public function getHtmlId()
  457. {
  458. return $this->_htmlId;
  459. }
  460. /**
  461. * Return pow
  462. *
  463. * @param int $number
  464. * @return int
  465. */
  466. protected function _getPow($number)
  467. {
  468. $pow = 0;
  469. while ($number >= 10) {
  470. $number = $number/10;
  471. $pow++;
  472. }
  473. return $pow;
  474. }
  475. /**
  476. * Return chart width
  477. *
  478. * @return string
  479. */
  480. protected function getWidth()
  481. {
  482. return $this->_width;
  483. }
  484. /**
  485. * Return chart height
  486. *
  487. * @return string
  488. */
  489. protected function getHeight()
  490. {
  491. return $this->_height;
  492. }
  493. /**
  494. * Prepare chart data
  495. *
  496. * @return void
  497. */
  498. protected function _prepareData()
  499. {
  500. $availablePeriods = array_keys($this->helper('adminhtml/dashboard_data')->getDatePeriods());
  501. $period = $this->getRequest()->getParam('period');
  502. $this->getDataHelper()->setParam('period',
  503. ($period && in_array($period, $availablePeriods)) ? $period : '24h'
  504. );
  505. }
  506. }