1 | <?php |
||
16 | class ChartOutput extends AbstractChartOutput |
||
17 | { |
||
18 | /** @var OptionsOutputInterface */ |
||
19 | private $optionsOutput; |
||
20 | |||
21 | /** @var DataOutputInterface */ |
||
22 | private $dataOutput; |
||
23 | |||
24 | /** @var EventsOutputInterface */ |
||
25 | private $eventsOutput; |
||
26 | |||
27 | /** |
||
28 | * ChartOutput constructor. |
||
29 | * |
||
30 | * @param string $version |
||
31 | * @param string $language |
||
32 | */ |
||
33 | 4 | public function __construct( |
|
46 | |||
47 | 4 | public function startChart(Chart $chart) |
|
48 | { |
||
49 | 4 | if (null === $chart->getElementID()) { |
|
50 | throw new GoogleChartsException('Container is not defined.'); |
||
51 | } |
||
52 | |||
53 | 4 | $js = 'var '.$chart->getName().' = new google.'.$chart->getLibrary().'.'.$chart->getType(). |
|
54 | 4 | '(document.getElementById("'.$chart->getElementID().'"));'; |
|
55 | |||
56 | 4 | if (!$chart instanceof DiffChart) { |
|
57 | 4 | $js .= $this->dataOutput->draw($chart->getData(), $chart->getDataName()); |
|
58 | } else { |
||
59 | $js .= $this->dataOutput->draw($chart->getOldChart()->getData(), 'old_'.$chart->getDataName()). |
||
60 | $this->dataOutput->draw($chart->getNewChart()->getData(), 'new_'.$chart->getDataName()). |
||
61 | 'var '.$chart->getDataName().' = '.$chart->getName(). |
||
62 | '.computeDiff(old_'.$chart->getDataName().', |
||
63 | new_'.$chart->getDataName().');'; |
||
64 | } |
||
65 | |||
66 | 4 | $js .= $this->optionsOutput->draw($chart->getOptions(), $chart->getOptionsName()); |
|
67 | |||
68 | 4 | return $js; |
|
69 | } |
||
70 | |||
71 | 4 | public function endChart(Chart $chart) |
|
72 | { |
||
73 | 4 | if ('visualization' == $chart->getLibrary()) { |
|
74 | 4 | $options = $chart->getOptionsName(); |
|
75 | } else { |
||
76 | /* Options conversion for material charts */ |
||
77 | $options = 'google.'.$chart->getLibrary().'.'.$chart->getType(). |
||
78 | '.convertOptions('.$chart->getOptionsName().')'; |
||
79 | } |
||
80 | |||
81 | 4 | return $this->eventsOutput->draw($chart->getEvents(), $chart->getName()).$chart->getName(). |
|
82 | 4 | '.draw('.$chart->getDataName().', '.$options.');'; |
|
83 | } |
||
84 | |||
85 | 4 | public function startCharts($charts, $elementsID = null) |
|
86 | { |
||
87 | 4 | if ($charts instanceof Chart) { |
|
88 | 4 | $charts = [$charts]; |
|
89 | |||
90 | 4 | if ($elementsID) { |
|
91 | if (!is_string($elementsID)) { |
||
92 | throw new GoogleChartsException('A string is expected for HTML element ID.'); |
||
93 | } |
||
94 | |||
95 | 4 | $elementsID = [$elementsID]; |
|
96 | } |
||
97 | } elseif (is_array($charts) && !empty($charts)) { |
||
98 | $this->checkChartsTypes($charts); |
||
99 | |||
100 | if (null !== $elementsID) { |
||
101 | if (!is_array($elementsID)) { |
||
102 | throw new GoogleChartsException('An array of string is expected for HTML elements IDs.'); |
||
103 | } |
||
104 | |||
105 | $this->checkElementsId($charts, $elementsID); |
||
106 | } |
||
107 | } else { |
||
108 | throw new GoogleChartsException('An instance of Chart or an array of Chart is expected.'); |
||
109 | } |
||
110 | |||
111 | 4 | $packages = []; |
|
112 | 4 | $drawChartName = ''; |
|
113 | 4 | for ($i = 0; $i < count($charts); ++$i) { |
|
|
|||
114 | 4 | if ($elementsID) { |
|
115 | $charts[$i]->setElementID($elementsID[$i]); |
||
116 | } |
||
117 | |||
118 | 4 | if (!in_array($charts[$i]->getPackage(), $packages)) { |
|
119 | 4 | $packages[] = $charts[$i]->getPackage(); |
|
120 | } |
||
121 | 4 | $drawChartName .= $charts[$i]->getElementID(); |
|
122 | } |
||
123 | |||
124 | 4 | $js = $this->loadLibraries($packages); |
|
125 | |||
126 | 4 | $js .= $this->startCallback('drawChart'.ucfirst(md5($drawChartName))); |
|
127 | |||
128 | 4 | foreach ($charts as $chart) { |
|
129 | 4 | $js .= $this->startChart($chart); |
|
130 | } |
||
131 | |||
132 | 4 | return $js; |
|
133 | } |
||
134 | |||
135 | 4 | public function endCharts($charts) |
|
136 | { |
||
137 | 4 | if ($charts instanceof Chart) { |
|
138 | 4 | $js = $this->endChart($charts).$this->endCallback(); |
|
139 | } elseif (is_array($charts) && !empty($charts)) { |
||
140 | $this->checkChartsTypes($charts); |
||
141 | |||
142 | $js = ''; |
||
143 | foreach ($charts as $chart) { |
||
144 | $js .= $this->endChart($chart); |
||
145 | } |
||
146 | |||
147 | $js .= $this->endCallback(); |
||
148 | } else { |
||
149 | throw new GoogleChartsException('An instance of Chart or an array of Chart is expected.'); |
||
150 | } |
||
151 | |||
152 | 4 | return $js; |
|
153 | } |
||
154 | |||
155 | 4 | public function fullCharts($charts, $elementsID = null) |
|
156 | { |
||
157 | 4 | return $this->startCharts($charts, $elementsID).$this->endCharts($charts); |
|
158 | } |
||
159 | |||
160 | public function loadLibraries(array $packages) |
||
161 | { |
||
162 | 4 | array_walk($packages, function (&$item) { |
|
163 | 4 | $item = "'".$item."'"; |
|
164 | 4 | }); |
|
165 | |||
166 | 4 | ($this->language) ? $language = ", language: '".$this->language."'" : $language = ''; |
|
167 | |||
168 | 4 | $load = "'".$this->version."', {packages:[".implode(',', $packages).']'.$language.'}'; |
|
169 | |||
170 | 4 | return "google.charts.load($load);"; |
|
171 | } |
||
172 | |||
173 | 4 | public function startCallback($name) |
|
174 | { |
||
175 | 4 | return "google.charts.setOnLoadCallback($name); function $name() {"; |
|
176 | } |
||
177 | |||
178 | 4 | public function endCallback() |
|
182 | } |
||
183 |
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: