Skip to content

Commit

Permalink
Merge pull request #1 from nyamsprod/develop
Browse files Browse the repository at this point in the history
Code restructured and simplified
  • Loading branch information
nyamsprod committed Jan 9, 2014
2 parents 26ffd41 + e115955 commit dbb48bb
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 105 deletions.
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ language: php
php:
- 5.4
- 5.5
- hhvm

matrix:
allow_failures:
- php: hhvm

before_script:
- composer self-update
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ Of course, since a `SplFileObject` is returned you are free to modify the flags
<?php


use Bakame\Csv\CsvCodec;
use Bakame\Csv\Codec;

$codec = new CsvCodec;
$codec = new Codec;
$codec->setDelimeter(',');
$codec->setEnclosure('"');
$codec->setEscape('\\');
Expand All @@ -71,7 +71,7 @@ The path to where the data must saved can be given as:
* a simple string
* an `SplFileInfo` instance

If for any reason the
If for any reason the data or the file does not exist an `InvalidArgumentException` will be thrown by the class

```php

Expand Down
179 changes: 101 additions & 78 deletions src/Bakame/Csv/CsvCodec.php → src/Bakame/Csv/Codec.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* @copyright 2013 Ignace Nyamagana Butera
* @link https://github.com/nyamsprod/Bakame.csv
* @license http://opensource.org/licenses/MIT
* @version 1.0.0
* @version 2.0.0
* @package Bakame.csv
*
* MIT LICENSE
Expand Down Expand Up @@ -37,14 +37,13 @@
use SplTempFileObject;
use Traversable;
use InvalidArgumentException;
use RuntimeException;

/**
* A simple Coder/Decoder to ease CSV management in PHP 5.4+
*
* @package Bakame.csv
*/
class CsvCodec
class Codec
{
/**
* the field delimiter (one character only)
Expand All @@ -66,6 +65,20 @@ class CsvCodec
*/
private $escape = '\\';

/**
* The constructor
*
* @param string $delimiter
* @param string $enclosure
* @param string $escape
*/
public function __construct($delimiter = ',', $enclosure = '"', $escape = "\\")
{
$this->setDelimiter($delimiter);
$this->setEnclosure($enclosure);
$this->setEscape($escape);
}

/**
* set the field delimeter
*
Expand All @@ -85,6 +98,16 @@ public function setDelimiter($delimiter = ',')
return $this;
}

/**
* return the current field delimiter
*
* @return string
*/
public function getDelimiter()
{
return $this->delimiter;
}

/**
* set the field enclosure
*
Expand All @@ -104,6 +127,16 @@ public function setEnclosure($enclosure = '"')
return $this;
}

/**
* return the current field enclosure
*
* @return string
*/
public function getEnclosure()
{
return $this->enclosure;
}

/**
* set the field escape character
*
Expand All @@ -124,92 +157,118 @@ public function setEscape($escape = "\\")
}

/**
* return the current field delimiter
* return the current field escape character
*
* @return string
*/
public function getDelimiter()
public function getEscape()
{
return $this->delimiter;
return $this->escape;
}

/**
* return the current field enclosure
* Load a CSV string
*
* @return string
* @param string $str the csv content string
*
* @return \SplTempFileObject
*/
public function getEnclosure()
public function loadString($str)
{
return $this->enclosure;
$file = new SplTempFileObject();
$file->fwrite($str);
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl($this->delimiter, $this->enclosure, $this->escape);

return $file;
}

/**
* return the current field escape character
* Load a CSV File
*
* @return string
* @param string $str the file path
*
* @return \SplFileObject
*/
public function getEscape()
public function loadFile($path, $mode = 'r')
{
return $this->escape;
return $this->create($path, $mode, ['r', 'r+', 'w+', 'x+', 'a+', 'c+']);
}

/**
* The constructor
* Save the given data into a CSV
*
* @param string $delimiter
* @param string $enclosure
* @param string $escape
* @param array|\Traversable $data the data to be saved (Array or Traversable Interface)
* @param string|\SplFileInfo $path where to save the data (String Path or SplFileInfo Instance)
* @param string $mode specifies the type of access you require to the file
*
* @return \SplFileObject
*/
public function __construct($delimiter = ',', $enclosure = '"', $escape = "\\")
public function save($data, $path, $mode = 'w')
{
$this->setDelimiter($delimiter);
$this->setEnclosure($enclosure);
$this->setEscape($escape);
$file = $this->create($path, $mode, ['r+', 'w', 'w+', 'x', 'x+', 'a', 'a+', 'c', 'c+']);
$data = $this->formatData($data);
array_walk($data, function ($row) use ($file) {
$file->fputcsv($row);
});

return $file;
}

/**
* Load a CSV string
* format the data before inclusion into the CSV
*
* @param string $str the csv content string
* @param array|\Traversable $traversable the data to be formatted (Array or Traversable Interface)
*
* @return \SplTempFileObject
* @return array
*
* @throws \InvalidArgumentException If $data is not an array or does not implement the \Traversable interface
*/
public function loadString($str)
private function formatData($traversable)
{
$file = new SplTempFileObject();
$file->fwrite($str);
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl($this->delimiter, $this->enclosure, $this->escape);
if (! is_array($traversable) && ! $traversable instanceof Traversable) {
throw new InvalidArgumentException(
'The provided data must be an Array or an object implementing the `Traversable` interface'
);
}
$res = [];
foreach ($traversable as $row) {
$res[] = $this->extractRowData($row);
}

return $file;
return $res;
}

/**
* Load a CSV File
*
* @param string $str the file path
* extract and format row field data to be string
*
* @return \SplFileObject
* @param mixed $row the data for One CSV line
*
* @throws \RuntimeException if the $file can not be instantiate
* @return array
*/
public function loadFile($path, $mode = 'r')
private function extractRowData($row)
{
return $this->create($path, $mode, ['r', 'r+', 'w+', 'x+', 'a+', 'c+']);
if (is_array($row)) {
return array_map(function ($value) {
return (string) $value;
}, $row);
}

return explode($this->delimiter, (string) $row);
}

/**
* Return a new \SplFileObject
*
* @param string|\SplFileInfo $path where to save the data
* @param string $mode specifies the type of access you require to the file
* @param array $include non valid type of access
* @param mixed $path where to save the data (String or SplFileInfo Instance)
* @param string $mode specifies the type of access you require to the file
* @param array $include non valid type of access
*
* @return \SplFileObject
*
* @throws \InvalidArgumentException If the $file is not set
*/
public function create($path, $mode, array $include = [])
private function create($path, $mode, array $include = [])
{
$include += ['r', 'r+', 'w', 'w+', 'x', 'x+', 'a', 'a+', 'c', 'c+'];
$mode = $this->filterMode($mode, $include);
Expand All @@ -229,42 +288,6 @@ public function create($path, $mode, array $include = [])
throw new InvalidArgumentException('$path must be a `SplFileInfo` object or a valid file path.');
}

/**
* Save the given data into a CSV
*
* @param array|\Traversable $data the data to be saved
* @param string|\SplFileInfo $path where to save the data
* @param string $mode specifies the type of access you require to the file
*
* @return \SplFileObject
*
* @throws \InvalidArgumentException If $data is not an array or does not implement the \Traversable interface
* @throws \InvalidArgumentException If the $mode is invalid
*/
public function save($data, $path, $mode = 'w')
{
$file = $this->create($path, $mode, ['r+', 'w', 'w+', 'x', 'x+', 'a', 'a+', 'c', 'c+']);
if (! is_array($data) && ! $data instanceof Traversable) {
throw new InvalidArgumentException(
'$data must be an Array or an object implementing the `Traversable` interface'
);
}

foreach ($data as $row) {
if (is_string($row)) {
$row = explode($this->delimiter, $row);
}
$row = (array) $row;
array_walk($row, function (&$value) {
$value = (string) $value;
$value = trim($value);
});
$file->fputcsv($row);
}

return $file;
}

/**
* validate the type of access you require for a given file
*
Expand Down
32 changes: 8 additions & 24 deletions test/Bakame/Csv/CsvCodecTest.php → test/Bakame/Csv/CodecTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
use SplFileObject;
use SplFileInfo;

class CsvCodecTest extends \PHPUnit_Framework_TestCase
class CodecTest extends \PHPUnit_Framework_TestCase
{

private $codec;

public function setUp()
{
$this->codec = new CsvCodec;
$this->codec = new Codec;
}

/**
Expand Down Expand Up @@ -59,22 +59,6 @@ public function testloadString()
}
}

/**
* @expectedException InvalidArgumentException
*/
public function testCreateException()
{
$this->codec->create(__DIR__.'/bar.csv', 'z');
}

/**
* @expectedException RuntimeException
*/
public function testCreateException2()
{
$this->codec->create('/etc/foo.csv', 'w');
}

public function testloadFile()
{
$expected = ['foo', 'bar', 'baz'];
Expand Down Expand Up @@ -105,16 +89,16 @@ public function testSaveArray()
['foo', 'bar', ' baz '],
'foo,bar, baz ',
];
$expected = ['foo', 'bar', 'baz'];
$expected = [['foo', 'bar', ' baz '],['foo','bar',' baz ']];
$this->codec
->setDelimiter(',')
->setEnclosure('"')
->setEscape("\\");

$res = $this->codec->save($arr, 'php://temp');
$this->assertInstanceof('SplFileObject', $res);
foreach ($res as $row) {
$this->assertSame($expected, $row);
foreach ($res as $key => $row) {
$this->assertSame($expected[$key], $row);
}
}

Expand All @@ -124,12 +108,12 @@ public function testSaveTransversable()
['foo', 'bar', ' baz '],
'foo,bar, baz ',
];
$expected = ['foo', 'bar', 'baz'];
$expected = [['foo', 'bar', ' baz '],['foo','bar',' baz ']];
$obj = new \ArrayObject($arr);
$res = $this->codec->save($obj, 'php://temp');
$this->assertInstanceof('\SplFileObject', $res);
foreach ($res as $row) {
$this->assertSame($expected, $row);
foreach ($res as $key => $row) {
$this->assertSame($expected[$key], $row);
}
}

Expand Down

0 comments on commit dbb48bb

Please sign in to comment.