Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions src/CsvOptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace SubjectivePHP\Csv;

use InvalidArgumentException;

final class CsvOptions
{
/**
* @var string
*/
private $delimiter;

/**
* @var string
*/
private $enclosure;

/**
* @var string
*/
private $escapeChar;

/**
* Construct a new CsvOptions instance.
*
* @param string $delimiter The field delimiter (one character only).
* @param string $enclosure The field enclosure character (one character only).
* @param string $escapeChar The escape character (one character only).
*
* @throws InvalidArgumentException Thrown if $delimiter is not one character.
* @throws InvalidArgumentException Thrown if $enclosure is not one character.
* @throws InvalidArgumentException Thrown if $escapeChar is not one character.
*/
public function __construct(string $delimiter = ',', string $enclosure = '"', string $escapeChar = '\\')
{
if (strlen($delimiter) !== 1) {
throw new InvalidArgumentException('$delimiter must be a single character string');
}

if (strlen($enclosure) !== 1) {
throw new InvalidArgumentException('$enclosure must be a single character string');
}

if (strlen($escapeChar) !== 1) {
throw new InvalidArgumentException('$escapeChar must be a single character string');
}

$this->delimiter = $delimiter;
$this->enclosure = $enclosure;
$this->escapeChar = $escapeChar;
}

/**
* Gets the field delimiter (one character only).
*
* @return string
*/
public function getDelimiter() : string
{
return $this->delimiter;
}

/**
* Gets the field enclosure character (one character only).
*
* @return string
*/
public function getEnclosure() : string
{
return $this->enclosure;
}

/**
* Gets the escape character (one character only).
*
* @return string
*/
public function getEscapeChar() : string
{
return $this->escapeChar;
}
}
40 changes: 40 additions & 0 deletions src/DeriveHeaderStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace SubjectivePHP\Csv;

use SplFileObject;

/**
* Header strategy which derives the headers from the first line of the file.
*/
final class DeriveHeaderStrategy implements HeaderStrategyInterface
{
/**
* @var array
*/
private $headers;

/**
* Extracts headers from the given SplFileObject.
*
* @param SplFileObject $fileObject The delimited file containing the headers.
*
* @return array
*/
public function getHeaders(SplFileObject $fileObject) : array
{
$this->headers = $fileObject->fgetcsv() ?? [];
$fileObject->rewind();
return $this->headers;
}

public function isHeaderRow(array $row) : bool
{
return $row === $this->headers;
}

public function createDataRow(array $row) : array
{
return array_combine($this->headers, $row);
}
}
14 changes: 14 additions & 0 deletions src/HeaderStrategyInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace SubjectivePHP\Csv;

use SplFileObject;

interface HeaderStrategyInterface
{
public function getHeaders(SplFileObject $fileObject) : array;

public function isHeaderRow(array $row) : bool;

public function createDataRow(array $row) : array;
}
46 changes: 46 additions & 0 deletions src/MappedHeaderStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace SubjectivePHP\Csv;

use SplFileObject;

/**
* Header strategy that uses a map array to provide custom headers for a csv file.
*/
final class MappedHeaderStrategy implements HeaderStrategyInterface
{
/**
* @var array
*/
private $headerMap;

public function __construct(array $headerMap)
{
$this->headerMap = $headerMap;
}

public function getHeaders(SplFileObject $fileObject) : array
{
return array_values($this->headerMap);
}

public function isHeaderRow(array $row) : bool
{
$headers = array_keys($this->headerMap);
sort($row);
sort($headers);
return $row === $headers;
}

public function createDataRow(array $row) : array
{
$result = [];
$originalHeaders = array_keys($this->headerMap);
foreach ($originalHeaders as $index => $key) {
$newHeader = $this->headerMap[$key];
$result[$newHeader] = $row[$index] ?? null;
}

return $result;
}
}
29 changes: 29 additions & 0 deletions src/NoHeaderStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace SubjectivePHP\Csv;

use SplFileObject;

/**
* Header strategy which generates a numeric array whose size is the number of columns in the given file.
*/
final class NoHeaderStrategy implements HeaderStrategyInterface
{
public function getHeaders(SplFileObject $fileObject) : array
{
$firstRow = $fileObject->fgetcsv();
$headers = array_keys($firstRow);
$fileObject->rewind();
return $headers;
}

public function isHeaderRow(array $row) : bool
{
return false;
}

public function createDataRow(array $row) : array
{
return $row;
}
}
36 changes: 36 additions & 0 deletions src/ProvidedHeaderStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace SubjectivePHP\Csv;

use SplFileObject;

/**
* Header strategy which uses the provided headers array.
*/
final class ProvidedHeaderStrategy implements HeaderStrategyInterface
{
/**
* @var array
*/
private $headers;

public function __construct(array $headers)
{
$this->headers = $headers;
}

public function getHeaders(SplFileObject $fileObject) : array
{
return $this->headers;
}

public function isHeaderRow(array $row) : bool
{
return $row === $this->headers;
}

public function createDataRow(array $row) : array
{
return array_combine($this->headers, $row);
}
}
Loading