/lib/phpspreadsheet/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeriesValues.php

https://github.com/sbourget/moodle · PHP · 397 lines · 185 code · 45 blank · 167 comment · 20 complexity · a9fb30c95548e764f0667022427924a5 MD5 · raw file

  1. <?php
  2. namespace PhpOffice\PhpSpreadsheet\Chart;
  3. use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
  4. use PhpOffice\PhpSpreadsheet\Calculation\Functions;
  5. use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
  6. use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
  7. class DataSeriesValues
  8. {
  9. const DATASERIES_TYPE_STRING = 'String';
  10. const DATASERIES_TYPE_NUMBER = 'Number';
  11. private static $dataTypeValues = [
  12. self::DATASERIES_TYPE_STRING,
  13. self::DATASERIES_TYPE_NUMBER,
  14. ];
  15. /**
  16. * Series Data Type.
  17. *
  18. * @var string
  19. */
  20. private $dataType;
  21. /**
  22. * Series Data Source.
  23. *
  24. * @var string
  25. */
  26. private $dataSource;
  27. /**
  28. * Format Code.
  29. *
  30. * @var string
  31. */
  32. private $formatCode;
  33. /**
  34. * Series Point Marker.
  35. *
  36. * @var string
  37. */
  38. private $pointMarker;
  39. /**
  40. * Point Count (The number of datapoints in the dataseries).
  41. *
  42. * @var int
  43. */
  44. private $pointCount = 0;
  45. /**
  46. * Data Values.
  47. *
  48. * @var mixed[]
  49. */
  50. private $dataValues = [];
  51. /**
  52. * Fill color (can be array with colors if dataseries have custom colors).
  53. *
  54. * @var string|string[]
  55. */
  56. private $fillColor;
  57. /**
  58. * Line Width.
  59. *
  60. * @var int
  61. */
  62. private $lineWidth = 12700;
  63. /**
  64. * Create a new DataSeriesValues object.
  65. *
  66. * @param string $dataType
  67. * @param string $dataSource
  68. * @param null|mixed $formatCode
  69. * @param int $pointCount
  70. * @param mixed $dataValues
  71. * @param null|mixed $marker
  72. * @param null|string|string[] $fillColor
  73. */
  74. public function __construct($dataType = self::DATASERIES_TYPE_NUMBER, $dataSource = null, $formatCode = null, $pointCount = 0, $dataValues = [], $marker = null, $fillColor = null)
  75. {
  76. $this->setDataType($dataType);
  77. $this->dataSource = $dataSource;
  78. $this->formatCode = $formatCode;
  79. $this->pointCount = $pointCount;
  80. $this->dataValues = $dataValues;
  81. $this->pointMarker = $marker;
  82. $this->fillColor = $fillColor;
  83. }
  84. /**
  85. * Get Series Data Type.
  86. *
  87. * @return string
  88. */
  89. public function getDataType()
  90. {
  91. return $this->dataType;
  92. }
  93. /**
  94. * Set Series Data Type.
  95. *
  96. * @param string $dataType Datatype of this data series
  97. * Typical values are:
  98. * DataSeriesValues::DATASERIES_TYPE_STRING
  99. * Normally used for axis point values
  100. * DataSeriesValues::DATASERIES_TYPE_NUMBER
  101. * Normally used for chart data values
  102. *
  103. * @return $this
  104. */
  105. public function setDataType($dataType)
  106. {
  107. if (!in_array($dataType, self::$dataTypeValues)) {
  108. throw new Exception('Invalid datatype for chart data series values');
  109. }
  110. $this->dataType = $dataType;
  111. return $this;
  112. }
  113. /**
  114. * Get Series Data Source (formula).
  115. *
  116. * @return string
  117. */
  118. public function getDataSource()
  119. {
  120. return $this->dataSource;
  121. }
  122. /**
  123. * Set Series Data Source (formula).
  124. *
  125. * @param string $dataSource
  126. *
  127. * @return $this
  128. */
  129. public function setDataSource($dataSource)
  130. {
  131. $this->dataSource = $dataSource;
  132. return $this;
  133. }
  134. /**
  135. * Get Point Marker.
  136. *
  137. * @return string
  138. */
  139. public function getPointMarker()
  140. {
  141. return $this->pointMarker;
  142. }
  143. /**
  144. * Set Point Marker.
  145. *
  146. * @param string $marker
  147. *
  148. * @return $this
  149. */
  150. public function setPointMarker($marker)
  151. {
  152. $this->pointMarker = $marker;
  153. return $this;
  154. }
  155. /**
  156. * Get Series Format Code.
  157. *
  158. * @return string
  159. */
  160. public function getFormatCode()
  161. {
  162. return $this->formatCode;
  163. }
  164. /**
  165. * Set Series Format Code.
  166. *
  167. * @param string $formatCode
  168. *
  169. * @return $this
  170. */
  171. public function setFormatCode($formatCode)
  172. {
  173. $this->formatCode = $formatCode;
  174. return $this;
  175. }
  176. /**
  177. * Get Series Point Count.
  178. *
  179. * @return int
  180. */
  181. public function getPointCount()
  182. {
  183. return $this->pointCount;
  184. }
  185. /**
  186. * Get fill color.
  187. *
  188. * @return string|string[] HEX color or array with HEX colors
  189. */
  190. public function getFillColor()
  191. {
  192. return $this->fillColor;
  193. }
  194. /**
  195. * Set fill color for series.
  196. *
  197. * @param string|string[] $color HEX color or array with HEX colors
  198. *
  199. * @return DataSeriesValues
  200. */
  201. public function setFillColor($color)
  202. {
  203. if (is_array($color)) {
  204. foreach ($color as $colorValue) {
  205. $this->validateColor($colorValue);
  206. }
  207. } else {
  208. $this->validateColor($color);
  209. }
  210. $this->fillColor = $color;
  211. return $this;
  212. }
  213. /**
  214. * Method for validating hex color.
  215. *
  216. * @param string $color value for color
  217. *
  218. * @return bool true if validation was successful
  219. */
  220. private function validateColor($color)
  221. {
  222. if (!preg_match('/^[a-f0-9]{6}$/i', $color)) {
  223. throw new Exception(sprintf('Invalid hex color for chart series (color: "%s")', $color));
  224. }
  225. return true;
  226. }
  227. /**
  228. * Get line width for series.
  229. *
  230. * @return int
  231. */
  232. public function getLineWidth()
  233. {
  234. return $this->lineWidth;
  235. }
  236. /**
  237. * Set line width for the series.
  238. *
  239. * @param int $width
  240. *
  241. * @return $this
  242. */
  243. public function setLineWidth($width)
  244. {
  245. $minWidth = 12700;
  246. $this->lineWidth = max($minWidth, $width);
  247. return $this;
  248. }
  249. /**
  250. * Identify if the Data Series is a multi-level or a simple series.
  251. *
  252. * @return null|bool
  253. */
  254. public function isMultiLevelSeries()
  255. {
  256. if (count($this->dataValues) > 0) {
  257. return is_array(array_values($this->dataValues)[0]);
  258. }
  259. return null;
  260. }
  261. /**
  262. * Return the level count of a multi-level Data Series.
  263. *
  264. * @return int
  265. */
  266. public function multiLevelCount()
  267. {
  268. $levelCount = 0;
  269. foreach ($this->dataValues as $dataValueSet) {
  270. $levelCount = max($levelCount, count($dataValueSet));
  271. }
  272. return $levelCount;
  273. }
  274. /**
  275. * Get Series Data Values.
  276. *
  277. * @return mixed[]
  278. */
  279. public function getDataValues()
  280. {
  281. return $this->dataValues;
  282. }
  283. /**
  284. * Get the first Series Data value.
  285. *
  286. * @return mixed
  287. */
  288. public function getDataValue()
  289. {
  290. $count = count($this->dataValues);
  291. if ($count == 0) {
  292. return null;
  293. } elseif ($count == 1) {
  294. return $this->dataValues[0];
  295. }
  296. return $this->dataValues;
  297. }
  298. /**
  299. * Set Series Data Values.
  300. *
  301. * @param array $dataValues
  302. *
  303. * @return $this
  304. */
  305. public function setDataValues($dataValues)
  306. {
  307. $this->dataValues = Functions::flattenArray($dataValues);
  308. $this->pointCount = count($dataValues);
  309. return $this;
  310. }
  311. public function refresh(Worksheet $worksheet, $flatten = true): void
  312. {
  313. if ($this->dataSource !== null) {
  314. $calcEngine = Calculation::getInstance($worksheet->getParent());
  315. $newDataValues = Calculation::unwrapResult(
  316. $calcEngine->_calculateFormulaValue(
  317. '=' . $this->dataSource,
  318. null,
  319. $worksheet->getCell('A1')
  320. )
  321. );
  322. if ($flatten) {
  323. $this->dataValues = Functions::flattenArray($newDataValues);
  324. foreach ($this->dataValues as &$dataValue) {
  325. if (is_string($dataValue) && !empty($dataValue) && $dataValue[0] == '#') {
  326. $dataValue = 0.0;
  327. }
  328. }
  329. unset($dataValue);
  330. } else {
  331. [$worksheet, $cellRange] = Worksheet::extractSheetTitle($this->dataSource, true);
  332. $dimensions = Coordinate::rangeDimension(str_replace('$', '', $cellRange));
  333. if (($dimensions[0] == 1) || ($dimensions[1] == 1)) {
  334. $this->dataValues = Functions::flattenArray($newDataValues);
  335. } else {
  336. $newArray = array_values(array_shift($newDataValues));
  337. foreach ($newArray as $i => $newDataSet) {
  338. $newArray[$i] = [$newDataSet];
  339. }
  340. foreach ($newDataValues as $newDataSet) {
  341. $i = 0;
  342. foreach ($newDataSet as $newDataVal) {
  343. array_unshift($newArray[$i++], $newDataVal);
  344. }
  345. }
  346. $this->dataValues = $newArray;
  347. }
  348. }
  349. $this->pointCount = count($this->dataValues);
  350. }
  351. }
  352. }