diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6eb37c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.swp +tags diff --git a/README.md b/README.md index 011b757..9d70e76 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -csv -=== +CSV parser/generator +==================== + +A simple PHP library to parse and generate CSV files. + -A simple PHP library to parse and generate CSV files. \ No newline at end of file diff --git a/src/Deblan/Csv/Csv.php b/src/Deblan/Csv/Csv.php new file mode 100644 index 0000000..0886f3e --- /dev/null +++ b/src/Deblan/Csv/Csv.php @@ -0,0 +1,198 @@ +setDelimiter($delimiter); + $this->setEnclosure($enclosure); + $this->setEscapeChar($escape_char); + $this->setEndLine($endline); + $this->setEncoding($encoding); + $this->datas = array(0 => null); + $this->legend = array(); + $this->render = ""; + } + + public function setFilename($v) + { + if (!is_string($v)) { + throw new CsvInvalidParameterException(sprintf('"%s" is not a valid string.', $v)); + } + + $this->filename = $v; + } + + protected function setHasLegend($hasLegend) + { + $this->hasLegend = $hasLegend; + + return $this; + } + + public function getHasLegend() + { + return $this->hasLegend; + } + + public function setLegend(array $values) + { + $this->setHasLegend(true); + + $this->addLine($values, 0); + } + + public function addLine(array $values, $key = null) + { + if ($key !== null) { + $this->datas[$key] = $values; + + return true; + } + + $this->datas[] = $values; + } + + public function setEncoding($encoding) + { + $this->encoding = $encoding; + + return $this; + } + + public function getEncoding() + { + return $this->encoding; + } + + public function setDelimiter($v) + { + if (!is_string($v)) { + throw new CsvInvalidParameterException(sprintf('"%s" is not a valid string.', $v)); + } + + $this->delimiter = $v; + } + + public function setEndline($v) + { + if (!is_string($v)) { + throw new CsvInvalidParameterException(sprintf('"%s" is not a valid string.', $v)); + } + + $this->endline = $v; + } + + public function setEnclosure($v) + { + if (!is_string($v)) { + throw new CsvInvalidParameterException(sprintf('"%s" is not a valid string.', $v)); + } + + $this->enclose = $v; + } + + public function setEscapeChar($v) + { + if (!is_string($v)) { + throw new CsvInvalidParameterException(sprintf('"%s" is not a valid string.', $v)); + } + + $this->escape_char = $v; + } + + public function getLegend() + { + return $this->legend; + } + + public function getDatas() + { + return $this->datas; + } + + public function compile() + { + $this->render = ""; + + if (isset($this->datas[0]) && $this->datas[0] !== null) { + $this->append($this->datasToCsvLine($this->datas[0])); + } + + unset($this->datas[0]); + + foreach ($this->datas as $k => $v) { + $this->append($this->datasToCsvLine($v)); + } + + if ($this->encoding !== 'UTF-8') { + $this->render = iconv( + mb_detect_encoding($this->render), + $this->encoding, + $this->render + ); + } + + return $this->render; + } + + public function hasDatas() + { + return count($this->datas) > ($this->getHasLegend() ? 1 : 0); + } + + protected function datasToCsvLine($datas) + { + foreach ($datas as $k => $v) { + $v = str_replace('\\', '\\\\', $v); + + if ($this->enclose) { + $v = str_replace($this->enclose, '\\'.$this->enclose, $v); + } else { + $v = str_replace($this->delimiter, '\\'.$this->delimiter, $v); + } + + $datas[$k] = $this->enclose.$v.$this->enclose; + } + + $datas = implode($this->delimiter, $datas); + + return $datas; + } + + protected function append($line) + { + $this->render.= sprintf("%s%s", $line, $this->endline); + } + + public function compileToFile($filename) + { + if (file_exists($filename)) { + unlink($filename); + } + + file_put_contents($filename, $this->compile()); + } +} diff --git a/src/Deblan/Csv/CsvParser.php b/src/Deblan/Csv/CsvParser.php new file mode 100644 index 0000000..57369a1 --- /dev/null +++ b/src/Deblan/Csv/CsvParser.php @@ -0,0 +1,141 @@ +setFilename($filename); + $this->setDelimiter($delimiter); + $this->setEnclosure($enclosure); + $this->setEscapeChar($escapeChar); + $this->setHasLegend($hasLegend); + $this->setNullValues($nullValues); + } + + public function setFilename($v) + { + if (!is_string($v)) { + throw new CsvParserInvalidParameterException(sprintf('"%s" is not a valid string.', $v)); + } + + if (!file_exists($v)) { + throw new CsvParserException(sprintf('"%s" does not exist.', $v)); + } + + if (!is_readable($v)) { + throw new CsvParserException(sprintf('"%s" is not readable.', $v)); + } + + $this->filename = $v; + } + + public function setDelimiter($v) + { + if (!is_string($v)) { + throw new CsvParserInvalidParameterException(sprintf('"%s" is not a valid string.', $v)); + } + + $this->delimiter = $v; + } + + public function setEnclosure($v) + { + if (!is_string($v)) { + throw new CsvParserInvalidParameterException(sprintf('"%s" is not a valid string.', $v)); + } + + $this->enclose = $v; + } + + public function setEscapeChar($v) + { + if (!is_string($v)) { + throw new CsvParserInvalidParameterException(sprintf('"%s" is not a valid string.', $v)); + } + + $this->escapeChar = $v; + } + + public function setHasLegend($v) + { + if (!is_bool($v)) { + throw new CsvParserInvalidParameterException(sprintf('"%s" is not a valid bool.', $v)); + } + + $this->hasLegend = $v; + } + + public function getLegend() + { + return $this->legend; + } + + public function setNullValues(array $v) + { + $this->nullValues = $v; + } + + /** + * + * To improve... + * + */ + protected function cleanNullValues($line) + { + return str_replace($this->nullValues, '', $line); + } + + public function getDatas() + { + return $this->datas; + } + + public function parse() + { + $lines = file($this->filename); + + if (empty($lines)) { + return true; + } + + if ($this->hasLegend) { + $this->legend = str_getcsv($lines[0], $this->delimiter, $this->enclosure, $this->escapeChar); + unset($lines[0]); + } + + foreach ($lines as $l => $line) { + $datas = str_getcsv($this->cleanNullValues($line), $this->delimiter, $this->enclosure, $this->escapeChar); + + if ($this->hasLegend) { + foreach ($this->legend as $k => $v) { + $datas[$v] = isset($datas[$k]) ? $datas[$k] : null; + } + } + + $this->datas[] = $datas; + } + + return true; + } +} diff --git a/src/Deblan/Csv/Exception/CsvException.php b/src/Deblan/Csv/Exception/CsvException.php new file mode 100644 index 0000000..c7369b3 --- /dev/null +++ b/src/Deblan/Csv/Exception/CsvException.php @@ -0,0 +1,7 @@ +