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