Completed
Pull Request — master (#234)
by ignace nyamagana
03:15
created

RFC4180FieldFilter::addTo()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 1
dl 0
loc 12
ccs 8
cts 8
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
* This file is part of the League.csv library
4
*
5
* @license http://opensource.org/licenses/MIT
6
* @link https://github.com/thephpleague/csv/
7
* @version 9.0.0
8
* @package League.csv
9
*
10
* For the full copyright and license information, please view the LICENSE
11
* file that was distributed with this source code.
12
*/
13
declare(strict_types=1);
14
15
namespace League\Csv;
16
17
use League\Csv\Exception\InvalidArgumentException;
18
use php_user_filter;
19
use Throwable;
20
21
/**
22
 *  A stream filter to conform the written CSV field to RFC4180
23
 *  This stream filter should be attach to a League\Csv\Writer object
24
 *
25
 * @package League.csv
26
 * @since   9.0.0
27
 * @author  Ignace Nyamagana Butera <[email protected]>
28
 */
29
class RFC4180FieldFilter extends php_user_filter
30
{
31
    use ValidatorTrait;
32
33
    const STREAM_FILTERNAME = 'rfc4180.league.csv';
34
35
    /**
36
     * The value being search for
37
     *
38
     * @var string
39
     */
40
    protected $search;
41
42
    /**
43
     * The replacement value that replace found $search values
44
     *
45
     * @var string
46
     */
47
    protected $replace;
48
49
    /**
50
     * Static method to add the stream filter to a Writer object
51
     *
52
     * @param AbstractCsv $csv
53
     */
54 6
    public static function addTo(AbstractCsv $csv)
55
    {
56 6
        if (!in_array(self::STREAM_FILTERNAME, stream_get_filters())) {
57 2
            stream_filter_register(self::STREAM_FILTERNAME, __CLASS__);
58
        }
59
60 6
        $csv->addStreamFilter(self::STREAM_FILTERNAME, [
61 6
            'enclosure' => $csv->getEnclosure(),
62 6
            'escape' => $csv->getEscape(),
63 6
            'mode' => $csv->getStreamFilterMode(),
64
        ]);
65 6
    }
66
67
    /**
68
     * @inheritdoc
69
     */
70 14
    public function onCreate()
71
    {
72 14
        if (!isset($this->params['enclosure'], $this->params['escape'], $this->params['mode'])) {
73 2
            return false;
74
        }
75
76
        try {
77 12
            $enclosure = $this->filterControl($this->params['enclosure'], 'enclosure', __METHOD__);
78 10
            $escape = $this->filterControl($this->params['escape'], 'escape', __METHOD__);
79 8
            $mode = $this->filterMode($this->params['mode']);
80
81 6
            $this->search = $escape.$enclosure;
82 6
            $this->replace = $enclosure.$enclosure;
83 6
            if (STREAM_FILTER_WRITE === $mode) {
84 4
                $this->replace = $escape.$this->replace;
85
            }
86
87 6
            return true;
88 6
        } catch (Throwable $e) {
89 6
            return false;
90
        }
91
    }
92
93
    /**
94
     * Filter the given mode
95
     *
96
     * @param int $mode stream filter mode
97
     *
98
     * @throws InvalidArgumentException if the mode value is unknown
99
     *
100
     * @return int
101
     */
102 8
    protected function filterMode(int $mode)
103
    {
104 8
        if (in_array($mode, [STREAM_FILTER_READ, STREAM_FILTER_WRITE])) {
105 6
            return $mode;
106
        }
107
108 2
        throw new InvalidArgumentException(sprintf('The given filter mode `%s` is unknown or unsupported', $mode));
109
    }
110
111
    /**
112
     * @inheritdoc
113
     */
114 6
    public function filter($in, $out, &$consumed, $closing)
115
    {
116 6
        while ($bucket = stream_bucket_make_writeable($in)) {
117 6
            $bucket->data = str_replace($this->search, $this->replace, $bucket->data);
118 6
            $consumed += $bucket->datalen;
119 6
            stream_bucket_append($out, $bucket);
120
        }
121
122 6
        return PSFS_PASS_ON;
123
    }
124
}
125