dolgraph.class.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. <?php
  2. /* Copyright (c) 2003-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (c) 2004-2015 Laurent Destailleur <eldy@users.sourceforge.net>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /**
  19. * \file htdocs/core/class/dolgraph.class.php
  20. * \ingroup core
  21. * \brief File for class to generate graph
  22. */
  23. /**
  24. * Parent class of graph classes
  25. */
  26. class DolGraph
  27. {
  28. var $type=array(); // Array with type of each series. Example: array('bars', 'lines', ...)
  29. var $mode='side'; // Mode bars graph: side, depth
  30. private $_library='jflot'; // Graphic library to use (jflot, artichow)
  31. //! Array of data
  32. var $data; // Data of graph: array(array('abs1',valA1,valB1), array('abs2',valA2,valB2), ...)
  33. var $title; // Title of graph
  34. var $cssprefix=''; // To add into css styles
  35. var $width=380;
  36. var $height=200;
  37. var $MaxValue=0;
  38. var $MinValue=0;
  39. var $SetShading=0;
  40. var $PrecisionY=-1;
  41. var $horizTickIncrement=-1;
  42. var $SetNumXTicks=-1;
  43. var $labelInterval=-1;
  44. var $hideXGrid=false;
  45. var $hideYGrid=false;
  46. var $Legend=array();
  47. var $LegendWidthMin=0;
  48. var $showlegend=1;
  49. var $showpointvalue=1;
  50. var $showpercent=0;
  51. var $combine=0; // 0.05 if you want to combine records < 5% into "other"
  52. var $graph; // Objet Graph (Artichow, Phplot...)
  53. var $error;
  54. var $bordercolor; // array(R,G,B)
  55. var $bgcolor; // array(R,G,B)
  56. var $bgcolorgrid=array(255,255,255); // array(R,G,B)
  57. var $datacolor; // array(array(R,G,B),...)
  58. private $stringtoshow; // To store string to output graph into HTML page
  59. /**
  60. * Constructor
  61. */
  62. function __construct()
  63. {
  64. global $conf;
  65. global $theme_bordercolor, $theme_datacolor, $theme_bgcolor, $theme_bgcoloronglet;
  66. // To use old feature
  67. if (isset($conf->global->MAIN_GRAPH_LIBRARY) && $conf->global->MAIN_GRAPH_LIBRARY == 'artichow')
  68. {
  69. $this->_library='artichow';
  70. // Test if module GD present
  71. $modules_list = get_loaded_extensions();
  72. $isgdinstalled=0;
  73. foreach ($modules_list as $module)
  74. {
  75. if ($module == 'gd') $isgdinstalled=1;
  76. }
  77. if (! $isgdinstalled)
  78. {
  79. $this->error="Error: PHP GD module is not available. It is required to build graphics.";
  80. return -1;
  81. }
  82. }
  83. $this->bordercolor = array(235,235,224);
  84. $this->datacolor = array(array(120,130,150), array(160,160,180), array(190,190,220));
  85. $this->bgcolor = array(235,235,224);
  86. $color_file = DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/graph-color.php';
  87. if (is_readable($color_file))
  88. {
  89. include_once $color_file;
  90. if (isset($theme_bordercolor)) $this->bordercolor = $theme_bordercolor;
  91. if (isset($theme_datacolor)) $this->datacolor = $theme_datacolor;
  92. if (isset($theme_bgcolor)) $this->bgcolor = $theme_bgcolor;
  93. }
  94. //print 'bgcolor: '.join(',',$this->bgcolor).'<br>';
  95. }
  96. /**
  97. * Set Y precision
  98. *
  99. * @param float $which_prec Precision
  100. * @return boolean
  101. */
  102. function SetPrecisionY($which_prec)
  103. {
  104. $this->PrecisionY = $which_prec;
  105. return true;
  106. }
  107. /**
  108. * Utiliser SetNumTicks ou SetHorizTickIncrement mais pas les 2
  109. *
  110. * @param float $xi Xi
  111. * @return boolean True
  112. */
  113. function SetHorizTickIncrement($xi)
  114. {
  115. $this->horizTickIncrement = $xi;
  116. return true;
  117. }
  118. /**
  119. * Utiliser SetNumTicks ou SetHorizTickIncrement mais pas les 2
  120. *
  121. * @param float $xt Xt
  122. * @return boolean True
  123. */
  124. function SetNumXTicks($xt)
  125. {
  126. $this->SetNumXTicks = $xt;
  127. return true;
  128. }
  129. /**
  130. * Set label interval to reduce number of labels
  131. *
  132. * @param float $x Label interval
  133. * @return boolean True
  134. */
  135. function SetLabelInterval($x)
  136. {
  137. $this->labelInterval = $x;
  138. return true;
  139. }
  140. /**
  141. * Hide X grid
  142. *
  143. * @param boolean $bool XGrid or not
  144. * @return boolean true
  145. */
  146. function SetHideXGrid($bool)
  147. {
  148. $this->hideXGrid = $bool;
  149. return true;
  150. }
  151. /**
  152. * Hide Y grid
  153. *
  154. * @param boolean $bool YGrid or not
  155. * @return boolean true
  156. */
  157. function SetHideYGrid($bool)
  158. {
  159. $this->hideYGrid = $bool;
  160. return true;
  161. }
  162. /**
  163. * Set y label
  164. *
  165. * @param string $label Y label
  166. * @return boolean|null True
  167. */
  168. function SetYLabel($label)
  169. {
  170. $this->YLabel = $label;
  171. }
  172. /**
  173. * Set width
  174. *
  175. * @param int $w Width
  176. * @return boolean|null True
  177. */
  178. function SetWidth($w)
  179. {
  180. $this->width = $w;
  181. }
  182. /**
  183. * Set title
  184. *
  185. * @param string $title Title
  186. * @return void
  187. */
  188. function SetTitle($title)
  189. {
  190. $this->title = $title;
  191. }
  192. /**
  193. * Set data
  194. *
  195. * @param array $data Data
  196. * @return void
  197. * @see draw_jflot for syntax of data array
  198. */
  199. function SetData($data)
  200. {
  201. $this->data = $data;
  202. }
  203. /**
  204. * Set data
  205. *
  206. * @param array $datacolor Data color array(array(R,G,B),array(R,G,B)...)
  207. * @return void
  208. */
  209. function SetDataColor($datacolor)
  210. {
  211. $this->datacolor = $datacolor;
  212. }
  213. /**
  214. * Set type
  215. *
  216. * @param array $type Array with type for each serie. Example: array('pie'), array('lines',...,'bars')
  217. * @return void
  218. */
  219. function SetType($type)
  220. {
  221. $this->type = $type;
  222. }
  223. /**
  224. * Set legend
  225. *
  226. * @param array $legend Legend. Example: array('seriename1','seriname2',...)
  227. * @return void
  228. */
  229. function SetLegend($legend)
  230. {
  231. $this->Legend = $legend;
  232. }
  233. /**
  234. * Set min width
  235. *
  236. * @param int $legendwidthmin Min width
  237. * @return void
  238. */
  239. function SetLegendWidthMin($legendwidthmin)
  240. {
  241. $this->LegendWidthMin = $legendwidthmin;
  242. }
  243. /**
  244. * Set max value
  245. *
  246. * @param int $max Max value
  247. * @return void
  248. */
  249. function SetMaxValue($max)
  250. {
  251. $this->MaxValue = $max;
  252. }
  253. /**
  254. * Get max value
  255. *
  256. * @return int Max value
  257. */
  258. function GetMaxValue()
  259. {
  260. return $this->MaxValue;
  261. }
  262. /**
  263. * Set min value
  264. *
  265. * @param int $min Min value
  266. * @return void
  267. */
  268. function SetMinValue($min)
  269. {
  270. $this->MinValue = $min;
  271. }
  272. /**
  273. * Get min value
  274. *
  275. * @return int Max value
  276. */
  277. function GetMinValue()
  278. {
  279. return $this->MinValue;
  280. }
  281. /**
  282. * Set height
  283. *
  284. * @param int $h Height
  285. * @return void
  286. */
  287. function SetHeight($h)
  288. {
  289. $this->height = $h;
  290. }
  291. /**
  292. * Set shading
  293. *
  294. * @param string $s Shading
  295. * @return void
  296. */
  297. function SetShading($s)
  298. {
  299. $this->SetShading = $s;
  300. }
  301. /**
  302. * Set shading
  303. *
  304. * @param string $s Shading
  305. * @return void
  306. */
  307. function SetCssPrefix($s)
  308. {
  309. $this->cssprefix = $s;
  310. }
  311. /**
  312. * Reset bg color
  313. *
  314. * @return void
  315. */
  316. function ResetBgColor()
  317. {
  318. unset($this->bgcolor);
  319. }
  320. /**
  321. * Reset bgcolorgrid
  322. *
  323. * @return void
  324. */
  325. function ResetBgColorGrid()
  326. {
  327. unset($this->bgcolorgrid);
  328. }
  329. /**
  330. * Is graph ko
  331. *
  332. * @return string Error
  333. */
  334. function isGraphKo()
  335. {
  336. return $this->error;
  337. }
  338. /**
  339. * Show legend or not
  340. *
  341. * @param int $showlegend 1=Show legend (default), 0=Hide legend
  342. * @return void
  343. */
  344. function setShowLegend($showlegend)
  345. {
  346. $this->showlegend=$showlegend;
  347. }
  348. /**
  349. * Show pointvalue or not
  350. *
  351. * @param int $showpointvalue 1=Show value for each point, as tooltip or inline (default), 0=Hide value
  352. * @return void
  353. */
  354. function setShowPointValue($showpointvalue)
  355. {
  356. $this->showpointvalue=$showpointvalue;
  357. }
  358. /**
  359. * Show percent or not
  360. *
  361. * @param int $showpercent 1=Show percent for each point, as tooltip or inline, 0=Hide percent (default)
  362. * @return void
  363. */
  364. function setShowPercent($showpercent)
  365. {
  366. $this->showpercent=$showpercent;
  367. }
  368. /**
  369. * Define background color of complete image
  370. *
  371. * @param array $bg_color array(R,G,B) ou 'onglet' ou 'default'
  372. * @return void
  373. */
  374. function SetBgColor($bg_color = array(255,255,255))
  375. {
  376. global $theme_bgcolor,$theme_bgcoloronglet;
  377. if (! is_array($bg_color))
  378. {
  379. if ($bg_color == 'onglet')
  380. {
  381. //print 'ee'.join(',',$theme_bgcoloronglet);
  382. $this->bgcolor = $theme_bgcoloronglet;
  383. }
  384. else
  385. {
  386. $this->bgcolor = $theme_bgcolor;
  387. }
  388. }
  389. else
  390. {
  391. $this->bgcolor = $bg_color;
  392. }
  393. }
  394. /**
  395. * Define background color of grid
  396. *
  397. * @param array $bg_colorgrid array(R,G,B) ou 'onglet' ou 'default'
  398. * @return void
  399. */
  400. function SetBgColorGrid($bg_colorgrid = array(255,255,255))
  401. {
  402. global $theme_bgcolor,$theme_bgcoloronglet;
  403. if (! is_array($bg_colorgrid))
  404. {
  405. if ($bg_colorgrid == 'onglet')
  406. {
  407. //print 'ee'.join(',',$theme_bgcoloronglet);
  408. $this->bgcolorgrid = $theme_bgcoloronglet;
  409. }
  410. else
  411. {
  412. $this->bgcolorgrid = $theme_bgcolor;
  413. }
  414. }
  415. else
  416. {
  417. $this->bgcolorgrid = $bg_colorgrid;
  418. }
  419. }
  420. /**
  421. * Reset data color
  422. *
  423. * @return void
  424. */
  425. function ResetDataColor()
  426. {
  427. unset($this->datacolor);
  428. }
  429. /**
  430. * Get max value
  431. *
  432. * @return int Max value
  433. */
  434. function GetMaxValueInData()
  435. {
  436. $k = 0;
  437. $vals = array();
  438. $nblines = count($this->data);
  439. $nbvalues = count($this->data[0]) - 1;
  440. for ($j = 0 ; $j < $nblines ; $j++)
  441. {
  442. for ($i = 0 ; $i < $nbvalues ; $i++)
  443. {
  444. $vals[$k] = $this->data[$j][$i+1];
  445. $k++;
  446. }
  447. }
  448. rsort($vals);
  449. return $vals[0];
  450. }
  451. /**
  452. * Return min value of all data
  453. *
  454. * @return int Min value of all data
  455. */
  456. function GetMinValueInData()
  457. {
  458. $k = 0;
  459. $vals = array();
  460. $nblines = count($this->data);
  461. $nbvalues = count($this->data[0]) - 1;
  462. for ($j = 0 ; $j < $nblines ; $j++)
  463. {
  464. for ($i = 0 ; $i < $nbvalues ; $i++)
  465. {
  466. $vals[$k] = $this->data[$j][$i+1];
  467. $k++;
  468. }
  469. }
  470. sort($vals);
  471. return $vals[0];
  472. }
  473. /**
  474. * Return max value of all data
  475. *
  476. * @return int Max value of all data
  477. */
  478. function GetCeilMaxValue()
  479. {
  480. $max = $this->GetMaxValueInData();
  481. if ($max != 0) $max++;
  482. $size=dol_strlen(abs(ceil($max)));
  483. $factor=1;
  484. for ($i=0; $i < ($size-1); $i++)
  485. {
  486. $factor*=10;
  487. }
  488. $res=0;
  489. if (is_numeric($max)) $res=ceil($max/$factor)*$factor;
  490. //print "max=".$max." res=".$res;
  491. return $res;
  492. }
  493. /**
  494. * Return min value of all data
  495. *
  496. * @return double Max value of all data
  497. */
  498. function GetFloorMinValue()
  499. {
  500. $min = $this->GetMinValueInData();
  501. if ($min != 0) $min--;
  502. $size=dol_strlen(abs(floor($min)));
  503. $factor=1;
  504. for ($i=0; $i < ($size-1); $i++)
  505. {
  506. $factor*=10;
  507. }
  508. $res=floor($min/$factor)*$factor;
  509. //print "min=".$min." res=".$res;
  510. return $res;
  511. }
  512. /**
  513. * Build a graph onto disk using correct library
  514. *
  515. * @param string $file Image file name to use to save onto disk (also used as javascript unique id)
  516. * @param string $fileurl Url path to show image if saved onto disk
  517. * @return integer|null
  518. */
  519. function draw($file,$fileurl='')
  520. {
  521. if (empty($file))
  522. {
  523. $this->error="Call to draw method was made with empty value for parameter file.";
  524. dol_syslog(get_class($this)."::draw ".$this->error, LOG_ERR);
  525. return -2;
  526. }
  527. if (! is_array($this->data) || count($this->data) < 1)
  528. {
  529. $this->error="Call to draw method was made but SetData was not called or called with an empty dataset for parameters";
  530. dol_syslog(get_class($this)."::draw ".$this->error, LOG_ERR);
  531. return -1;
  532. }
  533. $call = "draw_".$this->_library;
  534. call_user_func_array(array($this,$call), array($file,$fileurl));
  535. }
  536. /**
  537. * Build a graph onto disk using Artichow library and return img string to it
  538. *
  539. * @param string $file Image file name to use if we save onto disk
  540. * @param string $fileurl Url path to show image if saved onto disk
  541. * @return void
  542. */
  543. private function draw_artichow($file,$fileurl)
  544. {
  545. global $artichow_defaultfont;
  546. dol_syslog(get_class($this)."::draw_artichow this->type=".join(',',$this->type));
  547. if (! defined('SHADOW_RIGHT_TOP')) define('SHADOW_RIGHT_TOP',3);
  548. if (! defined('LEGEND_BACKGROUND')) define('LEGEND_BACKGROUND',2);
  549. if (! defined('LEGEND_LINE')) define('LEGEND_LINE',1);
  550. // Create graph
  551. $classname='';
  552. if (! isset($this->type[0]) || $this->type[0] == 'bars') $classname='BarPlot'; // Only one type (first one) is supported by artichow
  553. else if ($this->type[0] == 'lines') $classname='LinePlot';
  554. else $classname='TypeUnknown';
  555. include_once ARTICHOW_PATH.$classname.'.class.php';
  556. // Definition de couleurs
  557. $bgcolor=new Color($this->bgcolor[0],$this->bgcolor[1],$this->bgcolor[2]);
  558. $bgcolorgrid=new Color($this->bgcolorgrid[0],$this->bgcolorgrid[1],$this->bgcolorgrid[2]);
  559. $colortrans=new Color(0,0,0,100);
  560. $colorsemitrans=new Color(255,255,255,60);
  561. $colorgradient= new LinearGradient(new Color(235, 235, 235),new Color(255, 255, 255),0);
  562. $colorwhite=new Color(255,255,255);
  563. // Graph
  564. $graph = new Graph($this->width, $this->height);
  565. $graph->border->hide();
  566. $graph->setAntiAliasing(true);
  567. if (isset($this->title))
  568. {
  569. $graph->title->set($this->title);
  570. //print $artichow_defaultfont;exit;
  571. $graph->title->setFont(new $artichow_defaultfont(10));
  572. }
  573. if (is_array($this->bgcolor)) $graph->setBackgroundColor($bgcolor);
  574. else $graph->setBackgroundGradient($colorgradient);
  575. $group = new PlotGroup;
  576. //$group->setSpace(5, 5, 0, 0);
  577. $paddleft=50;
  578. $paddright=10;
  579. $strl=dol_strlen(max(abs($this->MaxValue),abs($this->MinValue)));
  580. if ($strl > 6) $paddleft += ($strl * 4);
  581. $group->setPadding($paddleft, $paddright); // Width on left and right for Y axis values
  582. $group->legend->setSpace(0);
  583. $group->legend->setPadding(2,2,2,2);
  584. $group->legend->setPosition(NULL,0.1);
  585. $group->legend->setBackgroundColor($colorsemitrans);
  586. if (is_array($this->bgcolorgrid)) $group->grid->setBackgroundColor($bgcolorgrid);
  587. else $group->grid->setBackgroundColor($colortrans);
  588. if ($this->hideXGrid) $group->grid->hideVertical(true);
  589. if ($this->hideYGrid) $group->grid->hideHorizontal(true);
  590. // On boucle sur chaque lot de donnees
  591. $legends=array();
  592. $i=0;
  593. $nblot=count($this->data[0])-1;
  594. while ($i < $nblot)
  595. {
  596. $x=0;
  597. $values=array();
  598. foreach($this->data as $key => $valarray)
  599. {
  600. $legends[$x] = $valarray[0];
  601. $values[$x] = $valarray[$i+1];
  602. $x++;
  603. }
  604. // We fix unknown values to null
  605. $newvalues=array();
  606. foreach($values as $val)
  607. {
  608. $newvalues[]=(is_numeric($val) ? $val : null);
  609. }
  610. if ($this->type[0] == 'bars')
  611. {
  612. //print "Lot de donnees $i<br>";
  613. //print_r($values);
  614. //print '<br>';
  615. $color=new Color($this->datacolor[$i][0],$this->datacolor[$i][1],$this->datacolor[$i][2],20);
  616. $colorbis=new Color(min($this->datacolor[$i][0]+50,255),min($this->datacolor[$i][1]+50,255),min($this->datacolor[$i][2]+50,255),50);
  617. $colorgrey=new Color(100,100,100);
  618. $colorborder=new Color($this->datacolor[$i][0],$this->datacolor[$i][1],$this->datacolor[$i][2]);
  619. if ($this->mode == 'side') $plot = new BarPlot($newvalues, $i+1, $nblot);
  620. if ($this->mode == 'depth') $plot = new BarPlot($newvalues, 1, 1, ($nblot-$i-1)*5);
  621. $plot->barBorder->setColor($colorgrey);
  622. //$plot->setBarColor($color);
  623. $plot->setBarGradient(new LinearGradient($colorbis, $color, 90));
  624. if ($this->mode == 'side') $plot->setBarPadding(0.1, 0.1);
  625. if ($this->mode == 'depth') $plot->setBarPadding(0.1, 0.4);
  626. if ($this->mode == 'side') $plot->setBarSpace(5);
  627. if ($this->mode == 'depth') $plot->setBarSpace(2);
  628. $plot->barShadow->setSize($this->SetShading);
  629. $plot->barShadow->setPosition(SHADOW_RIGHT_TOP);
  630. $plot->barShadow->setColor(new Color(160, 160, 160, 50));
  631. $plot->barShadow->smooth(TRUE);
  632. //$plot->setSize(1, 0.96);
  633. //$plot->setCenter(0.5, 0.52);
  634. // Le mode automatique est plus efficace
  635. $plot->SetYMax($this->MaxValue);
  636. $plot->SetYMin($this->MinValue);
  637. }
  638. if ($this->type[0] == 'lines')
  639. {
  640. $color=new Color($this->datacolor[$i][0],$this->datacolor[$i][1],$this->datacolor[$i][2],20);
  641. $colorbis=new Color(min($this->datacolor[$i][0]+20,255),min($this->datacolor[$i][1]+20,255),min($this->datacolor[$i][2]+20,255),60);
  642. $colorter=new Color(min($this->datacolor[$i][0]+50,255),min($this->datacolor[$i][1]+50,255),min($this->datacolor[$i][2]+50,255),90);
  643. $plot = new LinePlot($newvalues);
  644. //$plot->setSize(1, 0.96);
  645. //$plot->setCenter(0.5, 0.52);
  646. $plot->setColor($color);
  647. $plot->setThickness(1);
  648. // Set line background gradient
  649. $plot->setFillGradient(new LinearGradient($colorter, $colorbis, 90));
  650. $plot->xAxis->setLabelText($legends);
  651. // Le mode automatique est plus efficace
  652. $plot->SetYMax($this->MaxValue);
  653. $plot->SetYMin($this->MinValue);
  654. //$plot->setYAxis(0);
  655. //$plot->hideLine(true);
  656. }
  657. //$plot->reduce(80); // Evite temps d'affichage trop long et nombre de ticks absisce satures
  658. $group->legend->setTextFont(new $artichow_defaultfont(10)); // This is to force Artichow to use awFileFontDriver to
  659. // solve a bug in Artichow with UTF8
  660. if (count($this->Legend))
  661. {
  662. if ($this->type[0] == 'bars') $group->legend->add($plot, $this->Legend[$i], LEGEND_BACKGROUND);
  663. if ($this->type[0] == 'lines') $group->legend->add($plot, $this->Legend[$i], LEGEND_LINE);
  664. }
  665. $group->add($plot);
  666. $i++;
  667. }
  668. $group->axis->bottom->setLabelText($legends);
  669. $group->axis->bottom->label->setFont(new $artichow_defaultfont(7));
  670. //print $group->axis->bottom->getLabelNumber();
  671. if ($this->labelInterval > 0) $group->axis->bottom->setLabelInterval($this->labelInterval);
  672. $graph->add($group);
  673. // Generate file
  674. $graph->draw($file);
  675. $this->stringtoshow='<!-- Build using '.$this->_library.' --><img src="'.$fileurl.'" title="'.dol_escape_htmltag($this->title?$this->title:$this->YLabel).'" alt="'.dol_escape_htmltag($this->title?$this->title:$this->YLabel).'">';
  676. }
  677. /**
  678. * Build a graph using JFlot library. Input when calling this method should be:
  679. * $this->data = array(array( 0=>'labelxA', 1=>yA), array('labelxB',yB)); or
  680. * $this->data = array(array('label'=>'labelxA','data'=>yA), array('labelxB',yB)); // TODO Syntax not supported. Removed when dol_print_graph_removed
  681. * $this->data = array(array(0=>'labelxA',1=>yA1,...,n=>yAn), array('labelxB',yB1,...yBn)); // when there is n series to show for each x
  682. * $this->legend= array("Val1",...,"Valn"); // list of n series name
  683. * $this->type = array('bars',...'lines'); or array('pie')
  684. * $this->mode = 'depth' ???
  685. * $this->bgcolorgrid
  686. * $this->datacolor
  687. * $this->shownodatagraph
  688. *
  689. * @param string $file Image file name to use to save onto disk (also used as javascript unique id)
  690. * @param string $fileurl Url path to show image if saved onto disk. Never used here.
  691. * @return void
  692. */
  693. private function draw_jflot($file,$fileurl)
  694. {
  695. global $artichow_defaultfont;
  696. dol_syslog(get_class($this)."::draw_jflot this->type=".join(',',$this->type));
  697. if (empty($this->width) && empty($this->height))
  698. {
  699. print 'Error width or height not set';
  700. return;
  701. }
  702. $legends=array();
  703. $nblot=count($this->data[0])-1; // -1 to remove legend
  704. if ($nblot < 0) dol_print_error('Bad value for property ->data. Must be set by mydolgraph->SetData before callinf mydolgrapgh->draw');
  705. $firstlot=0;
  706. // Works with line but not with bars
  707. //if ($nblot > 2) $firstlot = ($nblot - 2); // We limit nblot to 2 because jflot can't manage more than 2 bars on same x
  708. $i=$firstlot;
  709. $serie=array();
  710. while ($i < $nblot) // Loop on each serie
  711. {
  712. $values=array(); // Array with horizontal y values (specific values of a serie) for each abscisse x
  713. $serie[$i]="var d".$i." = [];\n";
  714. // Fill array $values
  715. $x=0;
  716. foreach($this->data as $valarray) // Loop on each x
  717. {
  718. $legends[$x] = $valarray[0];
  719. $values[$x] = (is_numeric($valarray[$i+1]) ? $valarray[$i+1] : null);
  720. $x++;
  721. }
  722. // TODO Avoid push by adding generated long array...
  723. if (isset($this->type[$firstlot]) && $this->type[$firstlot] == 'pie')
  724. {
  725. foreach($values as $x => $y) {
  726. if (isset($y)) $serie[$i].='d'.$i.'.push({"label":"'.dol_escape_js($legends[$x]).'", "data":'.$y.'});'."\n";
  727. }
  728. }
  729. else
  730. {
  731. foreach($values as $x => $y) {
  732. if (isset($y)) $serie[$i].='d'.$i.'.push(['.$x.', '.$y.']);'."\n";
  733. }
  734. }
  735. unset($values);
  736. $i++;
  737. }
  738. $tag=dol_escape_htmltag(dol_string_unaccent(dol_string_nospecial(basename($file),'_',array('-','.'))));
  739. $this->stringtoshow ='<!-- Build using '.$this->_library.' -->'."\n";
  740. if (! empty($this->title)) $this->stringtoshow.='<div align="center" class="dolgraphtitle'.(empty($this->cssprefix)?'':' dolgraphtitle'.$this->cssprefix).'">'.$this->title.'</div>';
  741. if (! empty($this->shownographyet))
  742. {
  743. $this->stringtoshow.='<div style="width:'.$this->width.'px;height:'.$this->height.'px;" class="nographyet"></div>';
  744. $this->stringtoshow.='<div class="nographyettext">'.$langs->trans("NotEnoughDataYet").'</div>';
  745. return;
  746. }
  747. $this->stringtoshow.='<div id="placeholder_'.$tag.'" style="width:'.$this->width.'px;height:'.$this->height.'px;" class="dolgraph'.(empty($this->cssprefix)?'':' dolgraph'.$this->cssprefix).'"></div>'."\n";
  748. $this->stringtoshow.='<script id="'.$tag.'">'."\n";
  749. $this->stringtoshow.='$(function () {'."\n";
  750. $i=$firstlot;
  751. while ($i < $nblot)
  752. {
  753. $this->stringtoshow.=$serie[$i];
  754. $i++;
  755. }
  756. $this->stringtoshow.="\n";
  757. // Special case for Graph of type 'pie'
  758. if (isset($this->type[$firstlot]) && $this->type[$firstlot] == 'pie')
  759. {
  760. $datacolor=array();
  761. foreach($this->datacolor as $val) $datacolor[]="#".sprintf("%02x%02x%02x",$val[0],$val[1],$val[2]);
  762. $urltemp=''; // TODO Add support for url link into labels
  763. $showlegend=$this->showlegend;
  764. $showpointvalue=$this->showpointvalue;
  765. $showpercent=$this->showpercent;
  766. $this->stringtoshow.= '
  767. function plotWithOptions_'.$tag.'() {
  768. $.plot($("#placeholder_'.$tag.'"), d0,
  769. {
  770. series: {
  771. pie: {
  772. show: true,
  773. radius: 0.8,
  774. '.($this->combine ? '
  775. combine: {
  776. threshold: '.$this->combine.'
  777. },' : '') . '
  778. label: {
  779. show: true,
  780. radius: 0.9,
  781. formatter: function(label, series) {
  782. var percent=Math.round(series.percent);
  783. var number=series.data[0][1];
  784. return \'';
  785. $this->stringtoshow.='<div style="font-size:8pt;text-align:center;padding:2px;color:black;">';
  786. if ($urltemp) $this->stringtoshow.='<a style="color: #FFFFFF;" border="0" href="'.$urltemp.'">';
  787. $this->stringtoshow.='\'+';
  788. $this->stringtoshow.=($showlegend?'':'label+\' \'+'); // Hide label if already shown in legend
  789. $this->stringtoshow.=($showpointvalue?'number+':'');
  790. $this->stringtoshow.=($showpercent?'\'<br/>\'+percent+\'%\'+':'');
  791. $this->stringtoshow.='\'';
  792. if ($urltemp) $this->stringtoshow.='</a>';
  793. $this->stringtoshow.='</div>\';
  794. },
  795. background: {
  796. opacity: 0.0,
  797. color: \'#000000\'
  798. }
  799. }
  800. }
  801. },
  802. zoom: {
  803. interactive: true
  804. },
  805. pan: {
  806. interactive: true
  807. },';
  808. if (count($datacolor))
  809. {
  810. $this->stringtoshow.='colors: '.(! empty($data['seriescolor']) ? json_encode($data['seriescolor']) : json_encode($datacolor)).',';
  811. }
  812. $this->stringtoshow.='legend: {show: '.($showlegend?'true':'false').', position: \'ne\' }
  813. });
  814. }'."\n";
  815. }
  816. // Other cases, graph of type 'bars', 'lines'
  817. else
  818. {
  819. // Add code to support tooltips
  820. $this->stringtoshow.='
  821. function showTooltip_'.$tag.'(x, y, contents) {
  822. $(\'<div id="tooltip_'.$tag.'">\' + contents + \'</div>\').css({
  823. position: \'absolute\',
  824. display: \'none\',
  825. top: y + 5,
  826. left: x + 5,
  827. border: \'1px solid #ddd\',
  828. padding: \'2px\',
  829. \'background-color\': \'#ffe\',
  830. width: 200,
  831. opacity: 0.80
  832. }).appendTo("body").fadeIn(20);
  833. }
  834. var previousPoint = null;
  835. $("#placeholder_'.$tag.'").bind("plothover", function (event, pos, item) {
  836. $("#x").text(pos.x.toFixed(2));
  837. $("#y").text(pos.y.toFixed(2));
  838. if (item) {
  839. if (previousPoint != item.dataIndex) {
  840. previousPoint = item.dataIndex;
  841. $("#tooltip").remove();
  842. /* console.log(item); */
  843. var x = item.datapoint[0].toFixed(2);
  844. var y = item.datapoint[1].toFixed(2);
  845. var z = item.series.xaxis.ticks[item.dataIndex].label;
  846. ';
  847. if ($this->showpointvalue > 0) $this->stringtoshow.='
  848. showTooltip_'.$tag.'(item.pageX, item.pageY, item.series.label + "<br>" + z + " => " + y);
  849. ';
  850. $this->stringtoshow.='
  851. }
  852. }
  853. else {
  854. $("#tooltip_'.$tag.'").remove();
  855. previousPoint = null;
  856. }
  857. });
  858. ';
  859. $this->stringtoshow.='var stack = null, steps = false;'."\n";
  860. $this->stringtoshow.='function plotWithOptions_'.$tag.'() {'."\n";
  861. $this->stringtoshow.='$.plot($("#placeholder_'.$tag.'"), [ '."\n";
  862. $i=$firstlot;
  863. while ($i < $nblot)
  864. {
  865. if ($i > $firstlot) $this->stringtoshow.=', '."\n";
  866. $color=sprintf("%02x%02x%02x",$this->datacolor[$i][0],$this->datacolor[$i][1],$this->datacolor[$i][2]);
  867. $this->stringtoshow.='{ ';
  868. if (! isset($this->type[$i]) || $this->type[$i] == 'bars') $this->stringtoshow.='bars: { show: true, align: "'.($i==$firstlot?'center':'left').'", barWidth: 0.5 }, ';
  869. if (isset($this->type[$i]) && $this->type[$i] == 'lines') $this->stringtoshow.='lines: { show: true, fill: false }, ';
  870. $this->stringtoshow.='color: "#'.$color.'", label: "'.(isset($this->Legend[$i]) ? dol_escape_js($this->Legend[$i]) : '').'", data: d'.$i.' }';
  871. $i++;
  872. }
  873. $this->stringtoshow.="\n".' ], { series: { stack: stack, lines: { fill: false, steps: steps }, bars: { barWidth: 0.6 } }'."\n";
  874. // Xaxis
  875. $this->stringtoshow.=', xaxis: { ticks: ['."\n";
  876. $x=0;
  877. foreach($this->data as $key => $valarray)
  878. {
  879. if ($x > 0) $this->stringtoshow.=', '."\n";
  880. $this->stringtoshow.= ' ['.$x.', "'.$valarray[0].'"]';
  881. $x++;
  882. }
  883. $this->stringtoshow.='] }'."\n";
  884. // Yaxis
  885. $this->stringtoshow.=', yaxis: { min: '.$this->MinValue.', max: '.($this->MaxValue).' }'."\n";
  886. // Background color
  887. $color1=sprintf("%02x%02x%02x",$this->bgcolorgrid[0],$this->bgcolorgrid[0],$this->bgcolorgrid[2]);
  888. $color2=sprintf("%02x%02x%02x",$this->bgcolorgrid[0],$this->bgcolorgrid[1],$this->bgcolorgrid[2]);
  889. $this->stringtoshow.=', grid: { hoverable: true, backgroundColor: { colors: ["#'.$color1.'", "#'.$color2.'"] } }'."\n";
  890. //$this->stringtoshow.=', shadowSize: 20'."\n"; TODO Uncommet this
  891. $this->stringtoshow.='});'."\n";
  892. $this->stringtoshow.='}'."\n";
  893. }
  894. $this->stringtoshow.='plotWithOptions_'.$tag.'();'."\n";
  895. $this->stringtoshow.='});'."\n";
  896. $this->stringtoshow.='</script>'."\n";
  897. }
  898. /**
  899. * Output HTML string to show graph
  900. *
  901. * @return string HTML string to show graph
  902. */
  903. function show()
  904. {
  905. return $this->stringtoshow;
  906. }
  907. /**
  908. * getDefaultGraphSizeForStats
  909. *
  910. * @param string $direction 'width' or 'height'
  911. * @param string $defaultsize Value we want as default size
  912. * @return int Value of width or height to use by default
  913. */
  914. static function getDefaultGraphSizeForStats($direction,$defaultsize='')
  915. {
  916. global $conf;
  917. if ($direction == 'width')
  918. {
  919. if (empty($conf->dol_optimize_smallscreen)) return ($defaultsize ? $defaultsize : '500');
  920. else return (empty($_SESSION['dol_screen_width']) ? '280' : ($_SESSION['dol_screen_width']-40));
  921. }
  922. if ($direction == 'height')
  923. {
  924. return (empty($conf->dol_optimize_smallscreen)?($defaultsize?$defaultsize:'200'):'160');
  925. }
  926. return 0;
  927. }
  928. }