Completed
Pull Request — master (#234)
by ignace nyamagana
04:30
created

RFC4180Field::filterMode()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 5
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 2
rs 9.6666
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 CSV field to RFC4180
23
 *
24
 * @package League.csv
25
 * @since   9.0.0
26
 * @author  Ignace Nyamagana Butera <[email protected]>
27
 */
28
class RFC4180Field extends php_user_filter
29
{
30
    use ValidatorTrait;
31
32
    const FILTERNAME = 'league.csv.rfc4180.field';
33
34
    /**
35
     * The value being search for
36
     *
37
     * @var string
38
     */
39
    protected $search;
40
41
    /**
42
     * The replacement value that replace found $search values
43
     *
44
     * @var string
45
     */
46
    protected $replace;
47
48
    /**
49
     * Static method to add the stream filter to a {@link AbstractCsv} object
50
     *
51
     * @param AbstractCsv $csv
52
     */
53 6
    public static function addTo(AbstractCsv $csv)
54
    {
55 6
        if (!in_array(self::FILTERNAME, stream_get_filters())) {
56 2
            stream_filter_register(self::FILTERNAME, __CLASS__);
57
        }
58
59 6
        $csv->addStreamFilter(self::FILTERNAME, [
60 6
            'enclosure' => $csv->getEnclosure(),
61 6
            'escape' => $csv->getEscape(),
62 6
            'mode' => $csv->getStreamFilterMode(),
63
        ]);
64 6
    }
65
66
    /**
67
     * @inheritdoc
68
     */
69 14
    public function onCreate()
70
    {
71 14
        if (!isset($this->params['enclosure'], $this->params['escape'], $this->params['mode'])) {
72 2
            return false;
73
        }
74
75
        try {
76 12
            $enclosure = $this->filterControl($this->params['enclosure'], 'enclosure', __METHOD__);
77 10
            $escape = $this->filterControl($this->params['escape'], 'escape', __METHOD__);
78 8
            $mode = $this->filterMode($this->params['mode']);
79
80 6
            $this->search = $escape.$enclosure;
81 6
            $this->replace = $enclosure.$enclosure;
82 6
            if (STREAM_FILTER_WRITE === $mode) {
83 4
                $this->replace = $escape.$this->replace;
84
            }
85
86 6
            return true;
87 6
        } catch (Throwable $e) {
88 6
            return false;
89
        }
90
    }
91
92
    /**
93
     * Filter the stream filter mode
94
     *
95
     * @param int $mode stream filter mode
96
     *
97
     * @throws InvalidArgumentException if the stream filter mode is unknown or unsupported
98
     *
99
     * @return int
100
     */
101 8
    protected function filterMode(int $mode)
102
    {
103 8
        static $mode_list = [STREAM_FILTER_READ => 1, STREAM_FILTER_WRITE => 1];
104 8
        if (isset($mode_list[$mode])) {
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