1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27: 28: 29: 30: 31: 32: 33:
34:
35: class Mage_Adminhtml_Block_Dashboard_Graph extends Mage_Adminhtml_Block_Dashboard_Abstract
36: {
37: 38: 39:
40: const API_URL = 'http://chart.apis.google.com/chart';
41:
42: 43: 44: 45: 46:
47: protected $_allSeries = array();
48:
49: 50: 51: 52: 53:
54: protected $_axisLabels = array();
55:
56: 57: 58: 59: 60:
61: protected $_axisMaps = array();
62:
63: 64: 65: 66: 67:
68: protected $_dataRows = array();
69:
70: 71: 72: 73: 74:
75: protected $_simpleEncoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
76:
77: 78: 79: 80: 81:
82: protected $_extendedEncoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.';
83:
84: 85: 86: 87: 88:
89: protected $_width = '587';
90:
91: 92: 93: 94: 95:
96: protected $_height = '300';
97:
98: 99: 100: 101: 102:
103: protected $_encoding = 'e';
104:
105: 106: 107: 108: 109:
110: protected $_htmlId = '';
111:
112: 113: 114: 115: 116:
117: public function __construct()
118: {
119: parent::__construct();
120: $this->setTemplate('dashboard/graph.phtml');
121: }
122:
123: 124: 125: 126: 127:
128: protected function _getTabTemplate()
129: {
130: return 'dashboard/graph.phtml';
131: }
132:
133: 134: 135: 136: 137: 138:
139: public function setDataRows($rows)
140: {
141: $this->_dataRows = (array)$rows;
142: }
143:
144: 145: 146: 147: 148: 149: 150:
151: public function addSeries($seriesId, array $options)
152: {
153: $this->_allSeries[$seriesId] = $options;
154: }
155:
156: 157: 158: 159: 160: 161:
162: public function getSeries($seriesId)
163: {
164: if (isset($this->_allSeries[$seriesId])) {
165: return $this->_allSeries[$seriesId];
166: } else {
167: return false;
168: }
169: }
170:
171: 172: 173: 174: 175:
176: public function getAllSeries()
177: {
178: return $this->_allSeries;
179: }
180:
181: 182: 183: 184: 185: 186:
187: public function getChartUrl($directUrl = true)
188: {
189: $params = array(
190: 'cht' => 'lc',
191: 'chf' => 'bg,s,f4f4f4|c,lg,90,ffffff,0.1,ededed,0',
192: 'chm' => 'B,f4d4b2,0,0,0',
193: 'chco' => 'db4814'
194: );
195:
196: $this->_allSeries = $this->getRowsData($this->_dataRows);
197:
198: foreach ($this->_axisMaps as $axis => $attr){
199: $this->setAxisLabels($axis, $this->getRowsData($attr, true));
200: }
201:
202: $timezoneLocal = Mage::app()->getStore()->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_TIMEZONE);
203:
204: list ($dateStart, $dateEnd) = Mage::getResourceModel('reports/order_collection')
205: ->getDateRange($this->getDataHelper()->getParam('period'), '', '', true);
206:
207: $dateStart->setTimezone($timezoneLocal);
208: $dateEnd->setTimezone($timezoneLocal);
209:
210: $dates = array();
211: $datas = array();
212:
213: while($dateStart->compare($dateEnd) < 0){
214: switch ($this->getDataHelper()->getParam('period')) {
215: case '24h':
216: $d = $dateStart->toString('yyyy-MM-dd HH:00');
217: $dateStart->addHour(1);
218: break;
219: case '7d':
220: case '1m':
221: $d = $dateStart->toString('yyyy-MM-dd');
222: $dateStart->addDay(1);
223: break;
224: case '1y':
225: case '2y':
226: $d = $dateStart->toString('yyyy-MM');
227: $dateStart->addMonth(1);
228: break;
229: }
230: foreach ($this->getAllSeries() as $index=>$serie) {
231: if (in_array($d, $this->_axisLabels['x'])) {
232: $datas[$index][] = (float)array_shift($this->_allSeries[$index]);
233: } else {
234: $datas[$index][] = 0;
235: }
236: }
237: $dates[] = $d;
238: }
239:
240: 241: 242:
243: if (count($dates) > 8 && count($dates) < 15) {
244: $c = 1;
245: } else if (count($dates) >= 15){
246: $c = 2;
247: } else {
248: $c = 0;
249: }
250: 251: 252:
253: $i=0;
254: foreach ($dates as $k => $d) {
255: if ($i == $c) {
256: $dates[$k] = $d;
257: $i = 0;
258: } else {
259: $dates[$k] = '';
260: $i++;
261: }
262: }
263:
264: $this->_axisLabels['x'] = $dates;
265: $this->_allSeries = $datas;
266:
267:
268: if ($this->_encoding == "s") {
269:
270: $params['chd'] = "s:";
271: $dataDelimiter = "";
272: $dataSetdelimiter = ",";
273: $dataMissing = "_";
274: } else {
275:
276: $params['chd'] = "e:";
277: $dataDelimiter = "";
278: $dataSetdelimiter = ",";
279: $dataMissing = "__";
280: }
281:
282:
283: foreach ($this->getAllSeries() as $index => $serie) {
284: $localmaxlength[$index] = sizeof($serie);
285: $localmaxvalue[$index] = max($serie);
286: $localminvalue[$index] = min($serie);
287: }
288:
289: if (is_numeric($this->_max)) {
290: $maxvalue = $this->_max;
291: } else {
292: $maxvalue = max($localmaxvalue);
293: }
294: if (is_numeric($this->_min)) {
295: $minvalue = $this->_min;
296: } else {
297: $minvalue = min($localminvalue);
298: }
299:
300:
301: $yrange = 0;
302: $yLabels = array();
303: $miny = 0;
304: $maxy = 0;
305: $yorigin = 0;
306:
307: $maxlength = max($localmaxlength);
308: if ($minvalue >= 0 && $maxvalue >= 0) {
309: $miny = 0;
310: if ($maxvalue > 10) {
311: $p = pow(10, $this->_getPow($maxvalue));
312: $maxy = (ceil($maxvalue/$p))*$p;
313: $yLabels = range($miny, $maxy, $p);
314: } else {
315: $maxy = ceil($maxvalue+1);
316: $yLabels = range($miny, $maxy, 1);
317: }
318: $yrange = $maxy;
319: $yorigin = 0;
320: }
321:
322: $chartdata = array();
323:
324: foreach ($this->getAllSeries() as $index => $serie) {
325: $thisdataarray = $serie;
326: if ($this->_encoding == "s") {
327:
328: for ($j = 0; $j < sizeof($thisdataarray); $j++) {
329: $currentvalue = $thisdataarray[$j];
330: if (is_numeric($currentvalue)) {
331: $ylocation = round((strlen($this->_simpleEncoding)-1) * ($yorigin + $currentvalue) / $yrange);
332: array_push($chartdata, substr($this->_simpleEncoding, $ylocation, 1) . $dataDelimiter);
333: } else {
334: array_push($chartdata, $dataMissing . $dataDelimiter);
335: }
336: }
337:
338: } else {
339:
340: for ($j = 0; $j < sizeof($thisdataarray); $j++) {
341: $currentvalue = $thisdataarray[$j];
342: if (is_numeric($currentvalue)) {
343: if ($yrange) {
344: $ylocation = (4095 * ($yorigin + $currentvalue) / $yrange);
345: } else {
346: $ylocation = 0;
347: }
348: $firstchar = floor($ylocation / 64);
349: $secondchar = $ylocation % 64;
350: $mappedchar = substr($this->_extendedEncoding, $firstchar, 1)
351: . substr($this->_extendedEncoding, $secondchar, 1);
352: array_push($chartdata, $mappedchar . $dataDelimiter);
353: } else {
354: array_push($chartdata, $dataMissing . $dataDelimiter);
355: }
356: }
357:
358: }
359: array_push($chartdata, $dataSetdelimiter);
360: }
361: $buffer = implode('', $chartdata);
362:
363: $buffer = rtrim($buffer, $dataSetdelimiter);
364: $buffer = rtrim($buffer, $dataDelimiter);
365: $buffer = str_replace(($dataDelimiter . $dataSetdelimiter), $dataSetdelimiter, $buffer);
366:
367: $params['chd'] .= $buffer;
368:
369: $labelBuffer = "";
370: $valueBuffer = array();
371: $rangeBuffer = "";
372:
373: if (sizeof($this->_axisLabels) > 0) {
374: $params['chxt'] = implode(',', array_keys($this->_axisLabels));
375: $indexid = 0;
376: foreach ($this->_axisLabels as $idx=>$labels){
377: if ($idx == 'x') {
378: 379: 380:
381: foreach ($this->_axisLabels[$idx] as $_index=>$_label) {
382: if ($_label != '') {
383: switch ($this->getDataHelper()->getParam('period')) {
384: case '24h':
385: $this->_axisLabels[$idx][$_index] = $this->formatTime(
386: new Zend_Date($_label, 'yyyy-MM-dd HH:00'), 'short', false
387: );
388: break;
389: case '7d':
390: case '1m':
391: $this->_axisLabels[$idx][$_index] = $this->formatDate(
392: new Zend_Date($_label, 'yyyy-MM-dd')
393: );
394: break;
395: case '1y':
396: case '2y':
397: $formats = Mage::app()->getLocale()->getTranslationList('datetime');
398: $format = isset($formats['yyMM']) ? $formats['yyMM'] : 'MM/yyyy';
399: $format = str_replace(array("yyyy", "yy", "MM"), array("Y", "y", "m"), $format);
400: $this->_axisLabels[$idx][$_index] = date($format, strtotime($_label));
401: break;
402: }
403: } else {
404: $this->_axisLabels[$idx][$_index] = '';
405: }
406:
407: }
408:
409: $tmpstring = implode('|', $this->_axisLabels[$idx]);
410:
411: $valueBuffer[] = $indexid . ":|" . $tmpstring;
412: if (sizeof($this->_axisLabels[$idx]) > 1) {
413: $deltaX = 100/(sizeof($this->_axisLabels[$idx])-1);
414: } else {
415: $deltaX = 100;
416: }
417: } else if ($idx == 'y') {
418: $valueBuffer[] = $indexid . ":|" . implode('|', $yLabels);
419: if (sizeof($yLabels)-1) {
420: $deltaY = 100/(sizeof($yLabels)-1);
421: } else {
422: $deltaY = 100;
423: }
424:
425: $rangeBuffer = $indexid . "," . $miny . "," . $maxy . "|";
426: }
427: $indexid++;
428: }
429: $params['chxl'] = implode('|', $valueBuffer);
430: };
431:
432:
433: $params['chs'] = $this->getWidth().'x'.$this->getHeight();
434:
435: if (isset($deltaX) && isset($deltaY)) {
436: $params['chg'] = $deltaX . ',' . $deltaY . ',1,0';
437: }
438:
439:
440: if ($directUrl) {
441: $p = array();
442: foreach ($params as $name => $value) {
443: $p[] = $name . '=' .urlencode($value);
444: }
445: return self::API_URL . '?' . implode('&', $p);
446: } else {
447: $gaData = urlencode(base64_encode(serialize($params)));
448: $gaHash = Mage::helper('adminhtml/dashboard_data')->getChartDataHash($gaData);
449: $params = array('ga' => $gaData, 'h' => $gaHash);
450: return $this->getUrl('*/*/tunnel', array('_query' => $params));
451: }
452: }
453:
454: 455: 456: 457: 458: 459: 460:
461: protected function getRowsData($attributes, $single = false)
462: {
463: $items = $this->getCollection()->getItems();
464: $options = array();
465: foreach ($items as $item){
466: if ($single) {
467: $options[] = max(0, $item->getData($attributes));
468: } else {
469: foreach ((array)$attributes as $attr){
470: $options[$attr][] = max(0, $item->getData($attr));
471: }
472: }
473: }
474: return $options;
475: }
476:
477: 478: 479: 480: 481: 482: 483:
484: public function setAxisLabels($axis, $labels)
485: {
486: $this->_axisLabels[$axis] = $labels;
487: }
488:
489: 490: 491: 492: 493: 494:
495: public function setHtmlId($htmlId)
496: {
497: $this->_htmlId = $htmlId;
498: }
499:
500: 501: 502: 503: 504:
505: public function getHtmlId()
506: {
507: return $this->_htmlId;
508: }
509:
510: 511: 512: 513: 514: 515:
516: protected function _getPow($number)
517: {
518: $pow = 0;
519: while ($number >= 10) {
520: $number = $number/10;
521: $pow++;
522: }
523: return $pow;
524: }
525:
526: 527: 528: 529: 530:
531: protected function getWidth()
532: {
533: return $this->_width;
534: }
535:
536: 537: 538: 539: 540:
541: protected function getHeight()
542: {
543: return $this->_height;
544: }
545:
546: 547: 548: 549: 550:
551: protected function _prepareData()
552: {
553: $availablePeriods = array_keys($this->helper('adminhtml/dashboard_data')->getDatePeriods());
554: $period = $this->getRequest()->getParam('period');
555:
556: $this->getDataHelper()->setParam('period',
557: ($period && in_array($period, $availablePeriods)) ? $period : '24h'
558: );
559: }
560: }
561: