Completed
Push — master ( 88814d...52606f )
by Eric
04:51
created

CsvSerializationVisitor::visitFloat()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 10
Ratio 100 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 10
loc 10
rs 9.4285
c 0
b 0
f 0
ccs 6
cts 6
cp 1
cc 2
eloc 5
nc 2
nop 3
crap 2
1
<?php
2
3
/*
4
 * This file is part of the Ivory Serializer package.
5
 *
6
 * (c) Eric GELOEN <[email protected]>
7
 *
8
 * For the full copyright and license information, please read the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ivory\Serializer\Visitor\Csv;
13
14
use Ivory\Serializer\Accessor\AccessorInterface;
15
use Ivory\Serializer\Context\ContextInterface;
16
use Ivory\Serializer\Mapping\TypeMetadataInterface;
17
use Ivory\Serializer\Visitor\AbstractSerializationVisitor;
18
19
/**
20
 * @author GeLo <[email protected]>
21
 */
22
class CsvSerializationVisitor extends AbstractSerializationVisitor
23
{
24
    /**
25
     * @var string
26
     */
27
    private $delimiter;
28
29
    /**
30
     * @var string
31
     */
32
    private $enclosure;
33
34
    /**
35
     * @var string
36
     */
37
    private $escapeChar;
38
39
    /**
40
     * @var string
41
     */
42
    private $keySeparator;
43
44
    /**
45
     * @param AccessorInterface $accessor
46
     * @param string            $delimiter
47
     * @param string            $enclosure
48
     * @param string            $escapeChar
49
     * @param string            $keySeparator
50
     */
51 1440
    public function __construct(
52
        AccessorInterface $accessor,
53
        $delimiter = ',',
54
        $enclosure = '"',
55
        $escapeChar = '\\',
56
        $keySeparator = '.'
57
    ) {
58 1440
        parent::__construct($accessor);
59
60 1440
        $this->delimiter = $delimiter;
61 1440
        $this->enclosure = $enclosure;
62 1440
        $this->escapeChar = $escapeChar;
63 1440
        $this->keySeparator = $keySeparator;
64 1440
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69 56 View Code Duplication
    public function visitArray($data, TypeMetadataInterface $type, ContextInterface $context)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
70
    {
71 56
        if ($data === []) {
72 28
            return $this->visitData('[]', $type, $context);
73
        }
74
75 40
        return parent::visitArray($data, $type, $context);
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81 12
    public function visitBoolean($data, TypeMetadataInterface $type, ContextInterface $context)
82
    {
83 12
        return $this->visitData($data ? 'true' : 'false', $type, $context);
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89 12 View Code Duplication
    public function visitFloat($data, TypeMetadataInterface $type, ContextInterface $context)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
90
    {
91 12
        $data = (string) $data;
92
93 12
        if (strpos($data, '.') === false) {
94 12
            $data .= '.0';
95 6
        }
96
97 12
        return $this->visitData($data, $type, $context);
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103 220
    protected function encode($data)
104
    {
105 220
        $resource = fopen('php://temp,', 'w+');
106 220
        $headers = null;
107
108 220
        if (!is_array($data)) {
109 32
            $data = [[$data]];
110 204
        } elseif (!empty($data) && !$this->isIndexedArray($data)) {
111 184
            $data = [$data];
112 92
        }
113
114 220
        foreach ($data as $value) {
115 216
            $result = [];
116 216
            $this->flatten($value, $result);
117
118 216
            if ($headers === null) {
119 216
                if (!$this->isIndexedArray($result)) {
120 184
                    $headers = array_keys($result);
121 184
                    fputcsv($resource, $headers, $this->delimiter, $this->enclosure, $this->escapeChar);
122 92
                } else {
123 124
                    $headers = count($result);
124
                }
125 108
            } elseif (is_array($headers) && $headers !== array_keys($result)) {
126
                fclose($resource);
127
128
                throw new \InvalidArgumentException(sprintf(
129
                    'The input dimension is not equals for all entries (Expected: %d, got %d).',
130
                    count($headers),
131
                    count($result)
132
                ));
133
            } elseif ($headers !== count($result)) {
134
                fclose($resource);
135
136
                throw new \InvalidArgumentException(sprintf(
137
                    'The input dimension is not equals for all entries (Expected: %d, got %d).',
138
                    $headers,
139
                    count($result)
140
                ));
141
            }
142
143 216
            fputcsv($resource, $result, $this->delimiter, $this->enclosure, $this->escapeChar);
144 110
        }
145
146 220
        rewind($resource);
147 220
        $result = stream_get_contents($resource);
148 220
        fclose($resource);
149
150 220
        return $result;
151
    }
152
153
    /**
154
     * @param mixed[] $array
155
     * @param mixed[] $result
156
     * @param string  $parentKey
157
     */
158 216
    private function flatten(array $array, array &$result, $parentKey = '')
159
    {
160 216
        foreach ($array as $key => $value) {
161 216
            $key = $parentKey.$key;
162
163 216
            if ($value === []) {
164 8
                $value = null;
165 4
            }
166
167 216
            if (is_array($value)) {
168 36
                $this->flatten($value, $result, $key.$this->keySeparator);
169 18
            } else {
170 216
                $result[$key] = is_string($value) ? str_replace(PHP_EOL, '', $value) : $value;
171
            }
172 108
        }
173 216
    }
174
175
    /**
176
     * @param mixed[] $array
177
     *
178
     * @return bool
179
     */
180 216
    private function isIndexedArray(array $array)
181
    {
182 216
        return ctype_digit(implode('', array_keys($array)));
183
    }
184
}
185