PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.2.2
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.2.2
2.4.0 2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 All 67 releases
better-payment / vendor / league / csv / src / RFC4180Field.php

RFC4180Field.php in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.2.2, at vendor/league/csv/src/RFC4180Field.php

183 lines 5.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * League.Csv (https://csv.thephpleague.com)
5 *
6 * (c) Ignace Nyamagana Butera <[email protected]>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 declare(strict_types=1);
13
14 namespace League\Csv;
15
16 use InvalidArgumentException;
17 use php_user_filter;
18 use function array_map;
19 use function in_array;
20 use function is_string;
21 use function str_replace;
22 use function strcspn;
23 use function stream_bucket_append;
24 use function stream_bucket_make_writeable;
25 use function stream_filter_register;
26 use function stream_get_filters;
27 use function strlen;
28 use const STREAM_FILTER_READ;
29 use const STREAM_FILTER_WRITE;
30
31 /**
32 * A stream filter to conform the CSV field to RFC4180.
33 *
34 * DEPRECATION WARNING! This class will be removed in the next major point release
35 *
36 * @deprecated since version 9.2.0
37 * @see AbstractCsv::setEscape
38 *
39 * @see https://tools.ietf.org/html/rfc4180#section-2
40 */
41 class RFC4180Field extends php_user_filter
42 {
43 public const FILTERNAME = 'convert.league.csv.rfc4180';
44
45 /**
46 * The value being search for.
47 *
48 * @var string[]
49 */
50 protected array $search;
51
52 /**
53 * The replacement value that replace found $search values.
54 *
55 * @var string[]
56 */
57 protected array $replace;
58
59 /**
60 * Characters that triggers enclosure with PHP fputcsv.
61 *
62 */
63 protected static string $force_enclosure = "\n\r\t ";
64
65 /**
66 * Static method to add the stream filter to a {@link AbstractCsv} object.
67 */
68 public static function addTo(AbstractCsv $csv, string $whitespace_replace = ''): AbstractCsv
69 {
70 self::register();
71
72 $params = [
73 'enclosure' => $csv->getEnclosure(),
74 'escape' => $csv->getEscape(),
75 'mode' => $csv->getStreamFilterMode(),
76 ];
77
78 if ($csv instanceof Writer && '' != $whitespace_replace) {
79 self::addFormatterTo($csv, $whitespace_replace);
80 $params['whitespace_replace'] = $whitespace_replace;
81 }
82
83 return $csv->addStreamFilter(self::FILTERNAME, $params);
84 }
85
86 /**
87 * Add a formatter to the {@link Writer} object to format the record
88 * field to avoid enclosure around a field with an empty space.
89 */
90 public static function addFormatterTo(Writer $csv, string $whitespace_replace): Writer
91 {
92 if ('' == $whitespace_replace || strlen($whitespace_replace) != strcspn($whitespace_replace, self::$force_enclosure)) {
93 throw new InvalidArgumentException('The sequence contains a character that enforces enclosure or is a CSV control character or is the empty string.');
94 }
95
96 $mapper = fn ($value) => is_string($value)
97 ? str_replace(' ', $whitespace_replace, $value)
98 : $value;
99
100 return $csv->addFormatter(fn (array $record): array => array_map($mapper, $record));
101 }
102
103 /**
104 * Static method to register the class as a stream filter.
105 */
106 public static function register(): void
107 {
108 if (!in_array(self::FILTERNAME, stream_get_filters(), true)) {
109 stream_filter_register(self::FILTERNAME, self::class);
110 }
111 }
112
113 /**
114 * Static method to return the stream filter filtername.
115 */
116 public static function getFiltername(): string
117 {
118 return self::FILTERNAME;
119 }
120
121 /**
122 * @param resource $in
123 * @param resource $out
124 * @param int $consumed
125 * @param bool $closing
126 */
127 public function filter($in, $out, &$consumed, $closing): int
128 {
129 while (null !== ($bucket = stream_bucket_make_writeable($in))) {
130 $bucket->data = str_replace($this->search, $this->replace, $bucket->data);
131 $consumed += $bucket->datalen;
132 stream_bucket_append($out, $bucket);
133 }
134
135 return PSFS_PASS_ON;
136 }
137
138 public function onCreate(): bool
139 {
140 if (!$this->isValidParams($this->params)) {
141 return false;
142 }
143
144 $this->search = [$this->params['escape'].$this->params['enclosure']];
145 $this->replace = [$this->params['enclosure'].$this->params['enclosure']];
146 if (STREAM_FILTER_WRITE != $this->params['mode']) {
147 return true;
148 }
149
150 $this->search = [$this->params['escape'].$this->params['enclosure']];
151 $this->replace = [$this->params['escape'].$this->params['enclosure'].$this->params['enclosure']];
152 if ($this->isValidSequence($this->params)) {
153 $this->search[] = $this->params['whitespace_replace'];
154 $this->replace[] = ' ';
155 }
156
157 return true;
158 }
159
160 /**
161 * Validate params property.
162 */
163 protected function isValidParams(array $params): bool
164 {
165 static $mode_list = [STREAM_FILTER_READ => 1, STREAM_FILTER_WRITE => 1];
166
167 return isset($params['enclosure'], $params['escape'], $params['mode'], $mode_list[$params['mode']])
168 && 1 == strlen($params['enclosure'])
169 && 1 == strlen($params['escape']);
170 }
171
172 /**
173 * Is Valid White space replaced sequence.
174 *
175 * @return bool
176 */
177 protected function isValidSequence(array $params)
178 {
179 return isset($params['whitespace_replace'])
180 && strlen($params['whitespace_replace']) == strcspn($params['whitespace_replace'], self::$force_enclosure);
181 }
182 }
183