* @license BSD */ namespace Domframework; /** Read the data */ class GraphData { /** Store the data when the user provided them. Store them in array form */ private $data; /** The titles are on the first line */ private $titlesOnFirstLine = null; /** The titles are on the first column */ private $titlesOnFirstColumn = null; /** The data are stored horizontally */ private $horizontalData = null; /** Get the data from an indexed array * @param array $array The data array to graph */ public function arrayIndexed($array) { $this->data = $array; if (! is_array($this->data)) { throw new \Exception( dgettext( "domframework", "Invalid Array Parameter provided: not an array" ), 406 ); } return $this; } /** Get the data from an associative array * The associative array are provided by database results * @param array $array The data array to graph */ public function arrayAssociative($array) { if (! is_array($array)) { throw new \Exception( dgettext( "domframework", "Invalid Array Parameter provided: not an array" ), 406 ); } $titles = array(); $this->data = array(); foreach ($array as $line => $lineArr) { foreach ($lineArr as $key => $cell) { $titles[$key] = ""; $this->data[$line][] = $cell; } } array_unshift($this->data, array_keys($titles)); return $this; } /** Get the data from a CSV string * @param string $csv The CSV string */ public function csv($csv) { $csv = trim($csv); $lines = preg_split('/( *\R)+/s', $csv); $this->data = array_map('str_getcsv', $lines); if (! is_array($this->data)) { throw new \Exception( dgettext( "domframework", "Invalid CSV provided: not converted to array" ), 406 ); } return $this; } /** Get the data from a JSON string * @param string $json The JSON string */ public function json($json) { $this->data = json_decode($json, true); if (! is_array($this->data)) { throw new \Exception( dgettext( "domframework", "Invalid JSON provided: not converted to array" ), 406 ); } return $this; } /** Titles on first line * Set the value if the parameter is provided, get the value if the parameter * is not set * @param boolean|null $titlesOnFirstLine The titles on first line */ public function titlesOnFirstLine($titlesOnFirstLine = null) { if ($titlesOnFirstLine === null) { return $this->titlesOnFirstLine; } if (! is_bool($titlesOnFirstLine)) { throw new \Exception( dgettext( "domframework", "Invalid titlesOnFirstLine provided to graph titlesOnFirstLine" ), 406 ); } $this->titlesOnFirstLine = $titlesOnFirstLine; return $this; } /** Titles on first column * Set the value if the parameter is provided, get the value if the parameter * is not set * @param boolean|null $titlesOnFirstColumn The titles on first column */ public function titlesOnFirstColumn($titlesOnFirstColumn = null) { if ($titlesOnFirstColumn === null) { return $this->titlesOnFirstColumn; } if (! is_bool($titlesOnFirstColumn)) { throw new \Exception( dgettext( "domframework", "Invalid titlesOnFirstColumn provided to graph titlesOnFirstColumn" ), 406 ); } $this->titlesOnFirstColumn = $titlesOnFirstColumn; return $this; } /** The data are stored horizontally in the array * Set the value if the parameter is provided, get the value if the parameter * is not set * @param boolean|null $horizontalData The data are stored horizontally */ public function horizontalData($horizontalData = null) { if ($horizontalData === null) { return $this->horizontalData; } if (! is_bool($horizontalData)) { throw new \Exception( dgettext( "domframework", "Invalid horizontalData provided to graph horizontalData" ), 406 ); } $this->horizontalData = $horizontalData; return $this; } /** Get the series in an array with the associated values */ public function getSeries() { // 0. If there is no data to graph, nothing to do if (count($this->data) === 0) { return array(); } // 1. If $this->titlesOnFirstLine === null, look if the first line contains // titles if ($this->titlesOnFirstLine === null) { $this->titlesOnFirstLine = true; if (count($this->data) === 1) { $this->titlesOnFirstLine = false; } if (is_array($this->data[0])) { foreach ($this->data[0] as $cell) { if (is_numeric($cell)) { $this->titlesOnFirstLine = false; break; } } } else { $this->titlesOnFirstLine = false; } } // 2. If $this->titlesOnFirstColumn === null, look if the first column // contains titles if ($this->titlesOnFirstColumn === null) { if (count($this->data[0]) === 1) { $this->titlesOnFirstColumn = false; } else { $this->titlesOnFirstColumn = true; foreach ($this->data as $lineArr) { if (is_numeric($lineArr[0])) { $this->titlesOnFirstColumn = false; break; } } } } // 3. If $this->horizontalData === null, look for orientation with the // titles states if ($this->horizontalData === null) { if ( $this->titlesOnFirstColumn === true || ! array_key_exists(1, $this->data) ) { $this->horizontalData = true; } else { $this->horizontalData = false; } } // 4. Create the series $colTitles = array(); $lineTitles = array(); $series = array(); foreach ($this->data as $linePos => $lineArr) { if (! is_array($lineArr)) { $lineArr = array($lineArr); } if ($linePos === 0) { if ($this->titlesOnFirstLine) { $colTitles = $lineArr; if ($this->horizontalData === false) { // First line with titles and vertical data: get the series names $series = array_flip($lineArr); foreach ($series as &$value) { $value = array(); } if ($this->titlesOnFirstColumn) { array_shift($series); } } continue; } else { foreach ($lineArr as $i => $value) { $colTitles[$i] = $i; } } } elseif (count($lineArr) !== count($colTitles)) { throw new \Exception(sprintf( dgettext( "domframework", "Invalid data provided: line %d doesn't have the same number " . "of elements as the first line (%d != %d elements)" ), $linePos + 1, count($lineArr), count($colTitles) ), 406); } foreach ($lineArr as $colPos => $cell) { $cell = trim($cell); if ($colPos === 0) { if ($this->titlesOnFirstColumn) { $lineTitles[$linePos] = $cell; if ($this->horizontalData === true) { $series[$cell] = array(); } continue; } else { $lineTitles[$linePos] = $linePos; } } if (! is_numeric($cell)) { $cell = null; } else { $cell = $cell + 0.0; } if ($this->horizontalData === false) { $series[$colTitles[$colPos]][$lineTitles[$linePos]] = $cell; } else { $series[$lineTitles[$linePos]][$colTitles[$colPos]] = $cell; } } } return $series; } }