Completed
Pull Request — master (#24)
by Adam
02:31
created

Csv::hackRead()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
ccs 6
cts 6
cp 1
rs 9.4285
cc 2
eloc 5
nc 2
nop 2
crap 2
1
<?php
2
3
namespace BestServedCold\PhalueObjects\Format\String;
4
5
use BestServedCold\PhalueObjects\Contract\VOArrayable;
6
use BestServedCold\PhalueObjects\VOArray;
7
8
/**
9
 * Class Csv
10
 *
11
 * @package BestServedCold\PhalueObjects\Format
12
 */
13
class Csv extends AbstractString implements VOArrayable
14
{
15
    /**
16
     * @param  array  $array
17
     * @param  string $delimiter
18
     * @param  string $enclosure
19
     * @param  string $escape
20
     * @return static
21
     */
22 16
    public static function fromArray(
23
        array $array,
24
        $delimiter = ',',
25
        $enclosure = '"',
26
        $escape = '\\'
27
    ) {
28 16
        return new static(self::hack($array, $delimiter, $enclosure, $escape));
29
    }
30
31
    /**
32
     * @param  VOArray $voArray
33
     * @param  string  $delimiter
34
     * @param  string  $enclosure
35
     * @param  string  $escape
36
     * @return static
37
     */
38 1
    public static function fromVOArray(
39
        VOArray $voArray,
40
        $delimiter = ',',
41
        $enclosure = '"',
42
        $escape = '\\'
43
    ) {
44 1
        return static::fromArray($voArray->getValue(), $delimiter, $enclosure, $escape);
45
    }
46
47
    /**
48
     * @param  string $delimiter
49
     * @param  string $enclosure
50
     * @param  string $escape
51
     * @return array
52
     */
53 2
    public function toArray($delimiter = ",", $enclosure = '"', $escape = "\\")
54
    {
55 2
        $lines = explode("\n", $this->getValue());
56
57 2
        return is_array($lines) && count($lines) > 1
58 2
            ? array_map($this->iterateCallback($delimiter, $enclosure, $escape), array_filter($lines))
59 2
            : str_getcsv($this->getValue(), $delimiter, $enclosure, $escape);
60
    }
61
62
    /**
63
     * Move this out into the VOClosure namespace.
64
     *
65
     * @param  $delimiter
66
     * @param  $enclosure
67
     * @param  $escape
68
     * @return \Closure
69
     */
70
    private function iterateCallback($delimiter, $enclosure, $escape)
71
    {
72
        return function ($row) use ($delimiter, $enclosure, $escape) {
73
            return Csv::fromString($row)->toArray($delimiter, $enclosure, $escape);
74
        };
75
    }
76
77
    /**
78
     * Hack
79
     *
80
     * PHP does not have a function to convert an array to CSV, however, fputcsv() does.
81
     * We do this in memory using a file handle.  It's not pretty, but it works.
82
     *
83
     * I'm planning on abstracting this out into the File namespace in the near future.
84
     *
85
     * @param  array  $array
86
     * @param  string $delimiter
87
     * @param  string $enclosure
88
     * @param  string $escape
89
     * @return string
90
     */
91 16
    private static function hack(array $array, $delimiter, $enclosure, $escape)
92
    {
93 16
        $handle = fopen('php://temp', 'r+');
94 16
        VOArray::fromArray($array)->isMultiDim()
95 16
            ? self::hackWrite($handle, $array, $delimiter, $enclosure, $escape)
96 16
            : fputcsv($handle, $array, $delimiter, $enclosure, $escape);
97 16
        rewind($handle);
98 16
        return self::hackRead($handle);
99
    }
100
101
    /**
102
     * @param $handle
103
     * @param array $array
104
     * @param $delimiter
105
     * @param $enclosure
106
     * @param $escape
107
     */
108 1
    private static function hackWrite($handle, array $array, $delimiter, $enclosure, $escape)
109
    {
110 1
        foreach ($array as $line) {
111 1
            fputcsv($handle, $line, $delimiter, $enclosure, $escape);
112 1
        }
113 1
    }
114
115
    /**
116
     * @param  $handle
117
     * @param  string $contents
118
     * @return string
119
     */
120 16
    private static function hackRead($handle, $contents = '')
121
    {
122 16
        while (!feof($handle)) {
123 16
            $contents .= fread($handle, 8192);
124 16
        }
125 16
        fclose($handle);
126 16
        return $contents;
127
    }
128
}
129