Completed
Push — master ( df6d51...f1c79d )
by ignace nyamagana
04:36 queued 03:24
created

EncloseField::getFiltername()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
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.1.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 InvalidArgumentException;
18
use php_user_filter;
19
20
/**
21
 * A stream filter to improve enclosure character usage
22
 *
23
 * @see https://tools.ietf.org/html/rfc4180#section-2
24
 * @see https://bugs.php.net/bug.php?id=38301
25
 *
26
 * @package League.csv
27
 * @since   9.0.0
28
 * @author  Ignace Nyamagana Butera <[email protected]>
29
 */
30
class EncloseField extends php_user_filter
31
{
32
    const FILTERNAME = 'convert.league.csv.enclosure';
33
34
    /**
35
     * the filter name used to instantiate the class with
36
     *
37
     * @var string
38
     */
39
    public $filtername;
40
41
    /**
42
     * Contents of the params parameter passed to stream_filter_append
43
     * or stream_filter_prepend functions
44
     *
45
     * @var mixed
46
     */
47
    public $params;
48
49
    /**
50
     * Default sequence
51
     *
52
     * @var string
53
     */
54
    protected $sequence;
55
56
    /**
57
     * Characters that triggers enclosure in PHP
58
     *
59
     * @var string
60
     */
61
    protected static $force_enclosure = "\n\r\t ";
62
63
    /**
64
     * Static method to return the stream filter filtername
65
     *
66
     * @return string
67
     */
68 2
    public static function getFiltername(): string
69
    {
70 2
        return self::FILTERNAME;
71
    }
72
73
    /**
74
     * Static method to register the class as a stream filter
75
     */
76 2
    public static function register()
77
    {
78 2
        if (!in_array(self::FILTERNAME, stream_get_filters())) {
79 2
            stream_filter_register(self::FILTERNAME, __CLASS__);
80
        }
81 2
    }
82
83
    /**
84
     * Static method to add the stream filter to a {@link Writer} object
85
     *
86
     * @param Writer $csv
87
     * @param string $sequence
88
     *
89
     * @throws InvalidArgumentException if the sequence is malformed
90
     *
91
     * @return AbstractCsv
92
     */
93 4
    public static function addTo(Writer $csv, string $sequence): Writer
94
    {
95 4
        self::register();
96
97 4
        if (!self::isValidSequence($sequence)) {
98 2
            throw new InvalidArgumentException('The sequence must contain at least one character to force enclosure');
99
        }
100
101 2
        $formatter = function (array $record) use ($sequence) {
102 2
            foreach ($record as &$value) {
103 2
                $value = $sequence.$value;
104
            }
105 2
            unset($value);
106
107 2
            return $record;
108 2
        };
109
110
        return $csv
111 2
            ->addFormatter($formatter)
112 2
            ->addStreamFilter(self::FILTERNAME, ['sequence' => $sequence]);
113
    }
114
115
    /**
116
     * Filter type and sequence parameters
117
     *
118
     * - The sequence to force enclosure MUST contains one of the following character ("\n\r\t ")
119
     *
120
     * @param string $sequence
121
     *
122
     * @return bool
123
     */
124 4
    protected static function isValidSequence(string $sequence): bool
125
    {
126 4
        return strlen($sequence) != strcspn($sequence, self::$force_enclosure);
127
    }
128
129
    /**
130
     * @inheritdoc
131
     */
132 8
    public function onCreate()
133
    {
134 8
        return isset($this->params['sequence'])
135 8
            && $this->isValidSequence($this->params['sequence']);
136
    }
137
138
    /**
139
     * @inheritdoc
140
     */
141 2
    public function filter($in, $out, &$consumed, $closing)
142
    {
143 2
        while ($res = stream_bucket_make_writeable($in)) {
144 2
            $res->data = str_replace($this->params['sequence'], '', $res->data);
145 2
            $consumed += $res->datalen;
146 2
            stream_bucket_append($out, $res);
147
        }
148
149 2
        return PSFS_PASS_ON;
150
    }
151
}
152