These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * CSVelte: Slender, elegant CSV for PHP |
||
4 | * |
||
5 | * Inspired by Python's CSV module and Frictionless Data and the W3C's CSV |
||
6 | * standardization efforts, CSVelte was written in an effort to take all the |
||
7 | * suck out of working with CSV. |
||
8 | * |
||
9 | * @version v0.2.1 |
||
10 | * @copyright Copyright (c) 2016 Luke Visinoni <[email protected]> |
||
11 | * @author Luke Visinoni <[email protected]> |
||
12 | * @license https://github.com/deni-zen/csvelte/blob/master/LICENSE The MIT License (MIT) |
||
13 | */ |
||
14 | namespace CSVelte; |
||
15 | |||
16 | use \InvalidArgumentException; |
||
17 | use CSVelte\Exception\ImmutableException; |
||
18 | |||
19 | /** |
||
20 | * CSV Flavor |
||
21 | * |
||
22 | * Represents a particular "flavor" of CSV. Inspired by python's csv "dialects". |
||
23 | * Also inspired by Frictionless Data's "dialect description" format and the W3C's |
||
24 | * CSV on the Web Working Group and their work on CSV dialects. |
||
25 | * |
||
26 | * @package CSVelte |
||
27 | * @subpackage Flavor |
||
28 | * @since v0.1 |
||
29 | * @property-read string $delimiter The delimiter character |
||
30 | * @property-read string $quoteChar The quoting character |
||
31 | * @property-read string $lineTerminator The character sequence used to terminate rows of data |
||
32 | * @property-read string $escapeChar The character used to escape quotes within a quoted string |
||
33 | * Mutually exclusive to $doubleQuote |
||
34 | * @property-read bool $doubleQuote If true, quote characters will be escaped by preceding them |
||
35 | * with another quote character. Mutually exclusive to $escapeChar |
||
36 | * @property-read string $quoteStyle One of four class constants that determine which cells are quoted |
||
37 | * @property-read bool $header If true, first row should be treated as a header row |
||
38 | */ |
||
39 | class Flavor |
||
40 | { |
||
41 | /** |
||
42 | * Quote all cells. |
||
43 | * Set Flavor::$quoteStyle to this to quote all cells, regardless of data type |
||
44 | * @var string |
||
45 | */ |
||
46 | const QUOTE_ALL = 'quote_all'; |
||
47 | |||
48 | /** |
||
49 | * Quote no cells. |
||
50 | * Set Flavor::$quoteStyle to this to quote no columns, regardless of data type |
||
51 | * @var string |
||
52 | */ |
||
53 | const QUOTE_NONE = 'quote_none'; |
||
54 | |||
55 | /** |
||
56 | * Quote minimal columns. |
||
57 | * Set Flavor::$quoteStyle to this to quote only cells that contain special |
||
58 | * characters such as newlines or the delimiter character |
||
59 | * @var string |
||
60 | */ |
||
61 | const QUOTE_MINIMAL = 'quote_minimal'; |
||
62 | |||
63 | /** |
||
64 | * Quote non-numeric cells. |
||
65 | * Set Flavor::$quoteStyle to this to quote only cells that contain |
||
66 | * non-numeric data |
||
67 | * @var string |
||
68 | */ |
||
69 | const QUOTE_NONNUMERIC = 'quote_nonnumeric'; |
||
70 | |||
71 | /** |
||
72 | * Delimiter character. |
||
73 | * This is the character that will be used to separate data cells within a |
||
74 | * row of CSV data. Usually a comma. |
||
75 | * @var string |
||
76 | */ |
||
77 | protected $delimiter = ","; |
||
78 | |||
79 | /** |
||
80 | * Quote character. |
||
81 | * This is the character that will be used to enclose (quote) data cells. It |
||
82 | * is usually a double quote character but single quote is allowed. |
||
83 | * @var string |
||
84 | */ |
||
85 | protected $quoteChar = '"'; |
||
86 | |||
87 | /** |
||
88 | * Escape character. |
||
89 | * This character will be used to escape quotes within quoted text. It is |
||
90 | * mutually exclusive to the doubleQuote attribute. Usually a backspace. |
||
91 | * @var string |
||
92 | */ |
||
93 | protected $escapeChar = '\\'; |
||
94 | |||
95 | /** |
||
96 | * Double quote escape mode. |
||
97 | * If set to true, quote characters within quoted text will be escaped by |
||
98 | * preceding them with the same quote character. |
||
99 | * @var boolean |
||
100 | */ |
||
101 | protected $doubleQuote = true; |
||
102 | |||
103 | /** |
||
104 | * Not yet implemented |
||
105 | * @ignore |
||
106 | */ |
||
107 | // protected $skipInitialSpace = false; |
||
1 ignored issue
–
show
|
|||
108 | |||
109 | /** |
||
110 | * Quoting style. |
||
111 | * This may be set to one of four values: |
||
112 | * * *Flavor::QUOTE_NONE* - To never quote data cells |
||
113 | * * *Flavor::QUOTE_ALL* - To always quote data cells |
||
114 | * * *Flavor::QUOTE_MINIMAL* - To only quote data cells that contain special characters such as quote character or delimiter character |
||
115 | * * *Flavor::QUOTE_NONNUMERIC* - To quote data cells that contain non-numeric data |
||
116 | * @var string |
||
117 | */ |
||
118 | protected $quoteStyle = self::QUOTE_MINIMAL; |
||
119 | |||
120 | /** |
||
121 | * Line terminator string sequence. |
||
122 | * This is a character or sequence of characters that will be used to denote |
||
123 | * the end of a row within the data |
||
124 | * @var string |
||
125 | */ |
||
126 | protected $lineTerminator = "\r\n"; |
||
127 | |||
128 | /** |
||
129 | * Header. |
||
130 | * If set to true, this means the first line of the CSV data is to be treated |
||
131 | * as the column headers. |
||
132 | * @var boolean |
||
133 | */ |
||
134 | protected $header; |
||
135 | |||
136 | /** |
||
137 | * Class constructor |
||
138 | * |
||
139 | * The attributes that make up a flavor object can only be specified by |
||
140 | * passing them in an array as key => value pairs to the constructor. Once |
||
141 | * the flavor object is created, its attributes cannot be changed. |
||
142 | * |
||
143 | * @param array $attributes The attributes that define this particular flavor. These |
||
144 | * attributes are immutable. They can only be set here. |
||
145 | */ |
||
146 | 49 | public function __construct($attributes = null) |
|
147 | { |
||
148 | 49 | if (!is_null($attributes)) { |
|
149 | 37 | if (!is_array($attributes)) { |
|
150 | // @todo throw exception? |
||
151 | 1 | return; |
|
152 | } |
||
153 | 36 | foreach ($attributes as $attr => $val) { |
|
154 | 36 | $this->assertValidAttribute($attr); |
|
155 | 36 | $this->$attr = $val; |
|
156 | 36 | } |
|
157 | 36 | } |
|
158 | 49 | } |
|
159 | |||
160 | /** |
||
161 | * Does this flavor of CSV have a header row? |
||
162 | * |
||
163 | * The difference between $flavor->header and $flavor->hasHeader() is that |
||
164 | * hasHeader() is always going to give you a boolean value, whereas |
||
165 | * $flavor->header may be null. A null value for header could mean that the |
||
166 | * taster class could not reliably determine whether or not there was a |
||
167 | * header row or it could simply mean that the flavor was instantiated with |
||
168 | * no value for the header property. |
||
169 | * |
||
170 | * @return boolean |
||
171 | */ |
||
172 | 1 | public function hasHeader() |
|
173 | { |
||
174 | 1 | return (bool) $this->header; |
|
175 | } |
||
176 | |||
177 | /** |
||
178 | * Assert valid attribute name. |
||
179 | * Assert that a particular attribute is valid (basically just that it exists) |
||
180 | * and throw an exception otherwise |
||
181 | * |
||
182 | * @param string $attr The attribute to check validity of |
||
183 | * @throws InvalidArgumentException |
||
184 | * @internal |
||
185 | * @todo This should accept a second parameter for value that asserts the value |
||
186 | * is a valid value |
||
187 | */ |
||
188 | 45 | protected function assertValidAttribute($attr) |
|
189 | { |
||
190 | 45 | if (!property_exists(self::class, $attr)) |
|
191 | 45 | throw new InvalidArgumentException("Unknown attribute: " . $attr); |
|
192 | 44 | } |
|
193 | |||
194 | /** |
||
195 | * Copy this flavor object |
||
196 | * |
||
197 | * Because flavor attributes are immutable, it is implossible to change their |
||
198 | * attributes. If you need to change a flavor's attributes, call this method |
||
199 | * instead, specifying which attributes are to be changed. |
||
200 | * |
||
201 | * @param array $attribs An array of attribute name/values to change in the copied flavor |
||
202 | * @return Flavor A flavor object with your new attributes |
||
203 | * @todo I may want to remove the array type-hint so that this can accept |
||
204 | * array-like objects and iterables as well. Not sure... |
||
205 | */ |
||
206 | 6 | public function copy(array $attribs = array()) |
|
207 | { |
||
208 | 6 | return new Flavor(array_merge($this->toArray(), $attribs)); |
|
209 | } |
||
210 | |||
211 | /** |
||
212 | * Attribute accessor magic method |
||
213 | * |
||
214 | * @param string $attr The attribute to "get" |
||
215 | * @return string The attribute value |
||
216 | * @internal |
||
217 | * @throws InvalidArgumentException |
||
218 | */ |
||
219 | 38 | public function __get($attr) |
|
220 | { |
||
221 | 38 | $this->assertValidAttribute($attr); |
|
222 | 37 | return $this->$attr; |
|
223 | } |
||
224 | |||
225 | /** |
||
226 | * Attribute accessor (setter) magic method. |
||
227 | * Disabled because attributes are immutable (read-only) |
||
228 | * |
||
229 | * @param string $attr The attribute name you're attempting to set |
||
230 | * @param mixed $val The attribute value |
||
231 | * @throws ImmutableException |
||
232 | * @internal param The $string attribute to "set" |
||
233 | * @internal param The $string attribute value |
||
234 | * @internal |
||
235 | */ |
||
236 | 1 | public function __set($attr, $val) |
|
237 | { |
||
238 | 1 | throw new ImmutableException("Cannot change attributes on an immutable object: " . self::class . "::\$" . $attr); |
|
239 | } |
||
240 | |||
241 | /** |
||
242 | * Get this object as an array |
||
243 | * |
||
244 | * @return array This object as an array |
||
245 | */ |
||
246 | 9 | public function toArray() |
|
247 | { |
||
248 | 9 | return get_object_vars($this); |
|
249 | } |
||
250 | |||
251 | } |
||
252 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.