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 / EscapeFormula.php

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

147 lines 3.8 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 function array_fill_keys;
18 use function array_keys;
19 use function array_map;
20 use function array_merge;
21 use function array_unique;
22 use function is_object;
23 use function is_string;
24 use function method_exists;
25
26 /**
27 * A Formatter to tackle CSV Formula Injection.
28 *
29 * @see http://georgemauer.net/2017/10/07/csv-injection.html
30 */
31 class EscapeFormula
32 {
33 /** Spreadsheet formula starting character. */
34 const FORMULA_STARTING_CHARS = ['=', '-', '+', '@', "\t", "\r"];
35
36 /** Effective Spreadsheet formula starting characters. */
37 protected array $special_chars = [];
38 /** Escape character to escape each CSV formula field. */
39 protected string $escape;
40
41 /**
42 * @param string $escape escape character to escape each CSV formula field
43 * @param string[] $special_chars additional spreadsheet formula starting characters
44 */
45 public function __construct(string $escape = "'", array $special_chars = [])
46 {
47 $this->escape = $escape;
48 if ([] !== $special_chars) {
49 $special_chars = $this->filterSpecialCharacters(...$special_chars);
50 }
51
52 $chars = array_unique(array_merge(self::FORMULA_STARTING_CHARS, $special_chars));
53 $this->special_chars = array_fill_keys($chars, 1);
54 }
55
56 /**
57 * Filter submitted special characters.
58 *
59 * @param string ...$characters
60 *
61 * @throws InvalidArgumentException if the string is not a single character
62 *
63 * @return array<string>
64 */
65 protected function filterSpecialCharacters(string ...$characters): array
66 {
67 foreach ($characters as $str) {
68 if (1 != strlen($str)) {
69 throw new InvalidArgumentException('The submitted string '.$str.' must be a single character');
70 }
71 }
72
73 return $characters;
74 }
75
76 /**
77 * Returns the list of character the instance will escape.
78 *
79 * @return array<string>
80 */
81 public function getSpecialCharacters(): array
82 {
83 return array_keys($this->special_chars);
84 }
85
86 /**
87 * Returns the escape character.
88 */
89 public function getEscape(): string
90 {
91 return $this->escape;
92 }
93
94 /**
95 * League CSV formatter hook.
96 *
97 * @see escapeRecord
98 */
99 public function __invoke(array $record): array
100 {
101 return $this->escapeRecord($record);
102 }
103
104 /**
105 * Escape a CSV record.
106 */
107 public function escapeRecord(array $record): array
108 {
109 return array_map([$this, 'escapeField'], $record);
110 }
111
112 /**
113 * Escape a CSV cell if its content is stringable.
114 *
115 * @param int|float|string|object|resource|array $cell the content of the cell
116 *
117 * @return mixed the escaped content
118 */
119 protected function escapeField($cell)
120 {
121 if (!is_string($cell) && (!is_object($cell) || !method_exists($cell, '__toString'))) {
122 return $cell;
123 }
124
125 $str_cell = (string) $cell;
126 if (isset($str_cell[0], $this->special_chars[$str_cell[0]])) {
127 return $this->escape.$str_cell;
128 }
129
130 return $cell;
131 }
132
133 /**
134 * @deprecated since 9.7.2 will be removed in the next major release
135 * @codeCoverageIgnore
136 *
137 * Tells whether the submitted value is stringable.
138 *
139 * @param mixed $value value to check if it is stringable
140 */
141 protected function isStringable($value): bool
142 {
143 return is_string($value)
144 || (is_object($value) && method_exists($value, '__toString'));
145 }
146 }
147