PluginProbe
E2Pdf – Export Pdf Tool for WordPress / 1.32.49
E2Pdf – Export Pdf Tool for WordPress v1.32.49
1.32.49 1.32.48 1.32.43 1.32.40 1.32.34 1.32.32 1.32.31 1.32.26 1.32.22 1.32.23 1.32.18 1.32.17 1.32.15 trunk 1.00.00 1.00.13 1.01.01 1.02.02 1.03.07 1.04.07 1.05.03 1.06.02 1.07.11 1.08.00 1.08.06 All 72 releases
e2pdf / vendors / svggraph / CandlestickGraph.php

CandlestickGraph.php in E2Pdf – Export Pdf Tool for WordPress 1.32.49, at vendors/svggraph/CandlestickGraph.php

207 lines 5.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Copyright (C) 2021-2022 Graham Breach
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 /**
19 * For more information, please contact <graham@goat1000.com>
20 */
21
22 namespace Goat1000\SVGGraph;
23
24 class CandlestickGraph extends BarGraph {
25
26 private $min_value = null;
27 private $max_value = null;
28
29 public function __construct($w, $h, array $settings, array $fixed_settings = [])
30 {
31 $fs = [
32 'label_centre' => !isset($settings['datetime_keys']),
33 'require_structured' => ['open', 'high', 'low'],
34 ];
35 $fs = array_merge($fs, $fixed_settings);
36 parent::__construct($w, $h, $settings, $fs);
37 }
38
39 /**
40 * Check that all the values are in the right order
41 */
42 protected function checkValues()
43 {
44 parent::checkValues();
45
46 $fields = ['low', 'high', 'open'];
47 foreach($this->values[0] as $item) {
48 $val = $item->value;
49 if($val === null)
50 continue;
51
52 foreach($fields as $f) {
53 if(!is_numeric($item->$f))
54 throw new \Exception("Data error: field '$f' is not numeric (key:'{$item->key}', value:'{$item->$f}')");
55 }
56
57 $wb = $item->low;
58 $wt = $item->high;
59 $o = $item->open;
60 $b = min($val, $o);
61 $t = max($val, $o);
62 if($wb > $b || $wt < $t) {
63
64 $wb = new Number($wb);
65 $b = new Number($b);
66 $wt = new Number($wt);
67 $t = new Number($t);
68 throw new \Exception('Data problem: ' . $wb . '--[' . $b . ' ' . $t . ']--' . $wt);
69 }
70 }
71 }
72
73 /**
74 * Returns the maximum bar end
75 */
76 public function getMaxValue()
77 {
78 if($this->max_value !== null)
79 return $this->max_value;
80 $max = null;
81 $dataset = $this->getOption(['dataset', 0], 0);
82 foreach($this->values[$dataset] as $item) {
83 if($item->value === null)
84 continue;
85 if($max === null || $item->high > $max)
86 $max = $item->high;
87 }
88 return ($this->max_value = $max);
89 }
90
91 /**
92 * Returns the minimum bar end
93 */
94 public function getMinValue()
95 {
96 if($this->min_value !== null)
97 return $this->min_value;
98 $min = null;
99 $dataset = $this->getOption(['dataset', 0], 0);
100 foreach($this->values[$dataset] as $item) {
101 if($item->value === null)
102 continue;
103 if($min === null || $item->low < $min)
104 $min = $item->low;
105 }
106 return ($this->min_value = $min);
107 }
108
109 /**
110 * Sets up the colours used for the graph
111 */
112 protected function setup()
113 {
114 $dataset = $this->getOption(['dataset', 0], 0);
115
116 // use two datasets for colours
117 $this->colourSetup($this->values->itemsCount($dataset), 2);
118 }
119
120 /**
121 * Returns an array with x, y, width and height set
122 */
123 protected function barDimensions($item, $index, $start, $axis, $dataset)
124 {
125 $bar = [];
126 $bar_x = $this->barX($item, $index, $bar, $axis, $dataset);
127 if($bar_x === null)
128 return [];
129
130 $start = $item->value;
131 $value = $item->open - $start;
132 $y_pos = $this->barY($value, $bar, $start, $axis);
133 if($y_pos === null)
134 return [];
135 return $bar;
136 }
137
138 /**
139 * Returns the SVG code for a bar
140 */
141 protected function drawBar(DataItem $item, $index, $start = 0, $axis = null,
142 $dataset = 0, $options = [])
143 {
144 if($item->value === null)
145 return '';
146
147 // negative bars are a different colour
148 $negative = $item->value < $item->open;
149 if($negative)
150 ++$dataset;
151
152 $bar = $this->barDimensions($item, $index, $start, $axis, $dataset);
153 if(empty($bar))
154 return '';
155
156 if($bar['height'] < 1)
157 $bar['height'] = 1;
158 $this->setStroke($bar, $item, $index, $dataset);
159 $bar['fill'] = $this->getColour($item, $index, $dataset);
160
161 if($this->getOption('semantic_classes'))
162 $bar['class'] = 'series' . $dataset;
163
164 $label_shown = $this->addDataLabel($dataset, $index, $bar, $item,
165 $bar['x'], $bar['y'], $bar['width'], $bar['height']);
166
167 if($this->getOption('show_tooltips'))
168 $this->setTooltip($bar, $item, $dataset, $item->key, $item->value,
169 $label_shown);
170 if($this->getOption('show_context_menu'))
171 $this->setContextMenu($bar, $dataset, $item, $label_shown);
172
173 $round = max($this->getItemOption('bar_round', $dataset, $item), 0);
174 if($round > 0) {
175 // don't allow the round corner to be more than 1/2 bar width or height
176 $bar['rx'] = $bar['ry'] = min($round, $bar['width'] / 2, $bar['height'] / 2);
177 }
178
179 // wick lines
180 $lx = $bar['x'] + ($bar['width'] / 2);
181 $ly1 = $this->gridY($item->high);
182 $ly2 = $bar['y'];
183 $ly3 = $ly2 + $bar['height'];
184 $ly4 = $this->gridY($item->low);
185
186 $wick_width = max(0.25, $this->getOption(['wick_stroke_width', $dataset], 1));
187 $wick_dash = $this->getOption(['wick_dash', $dataset]);
188 $style = [ 'stroke-width' => $wick_width ];
189 if(isset($bar['stroke']))
190 $style['stroke'] = $bar['stroke'];
191 if(!empty($wick_dash))
192 $style['stroke-dasharray'] = $wick_dash;
193
194 $l1 = $l2 = '';
195 if($ly1 != $ly2)
196 $l1 = $this->element('line', array_merge($style,
197 ['x1' => $lx, 'x2' => $lx, 'y1' => $ly1, 'y2' => $ly2]));
198 if($ly3 != $ly4)
199 $l2 = $this->element('line', array_merge($style,
200 ['x1' => $lx, 'x2' => $lx, 'y1' => $ly3, 'y2' => $ly4]));
201
202 $bar_part = $this->element('rect', $bar);
203 return $this->getLink($item, $item->key, $bar_part . $l1 . $l2);
204 }
205 }
206
207