1 | <?php |
||
20 | class SniffQuoteStyle extends AbstractSniffer |
||
21 | { |
||
22 | /** |
||
23 | * Guess quoting style |
||
24 | * |
||
25 | * The quoting style refers to which types of columns are quoted within a csv dataset. The dialect class defines |
||
26 | * four possible quoting styles; all, none, minimal, or non-numeric. This class attempts to determine which of those |
||
27 | * four it is by analyzing the content within each quoted value. |
||
28 | * |
||
29 | * @param string $data The data to analyze |
||
30 | * |
||
31 | * @return int |
||
32 | */ |
||
33 | 1 | public function sniff($data) |
|
34 | { |
||
35 | 1 | $styles = collect([ |
|
36 | 1 | Dialect::QUOTE_NONE => true, |
|
37 | 1 | Dialect::QUOTE_ALL => true, |
|
38 | 1 | Dialect::QUOTE_MINIMAL => true, |
|
39 | 1 | Dialect::QUOTE_NONNUMERIC => true |
|
40 | 1 | ]); |
|
41 | |||
42 | 1 | $delimiter = $this->getOption('delimiter'); |
|
43 | 1 | $lineTerminator = $this->getOption('lineTerminator') ?: "\n"; |
|
44 | 1 | $quoted = collect(); |
|
45 | 1 | collect(explode($lineTerminator, $this->replaceQuotedSpecialChars($data, $delimiter, $lineTerminator))) |
|
46 | ->each(function($line, $line_no) use (&$styles, $quoted, $delimiter) { |
||
|
|||
47 | 1 | $values = explode($delimiter, $line); |
|
48 | 1 | foreach ($values as $value) { |
|
49 | 1 | if ($this->isQuoted($value)) { |
|
50 | // remove surrounding quotes |
||
51 | 1 | $value = $this->unQuote($value); |
|
52 | 1 | $styles[Dialect::QUOTE_NONE] = false; |
|
53 | 1 | if (s($value)->containsAny([static::PLACEHOLDER_DELIM, static::PLACEHOLDER_NEWLINE, '"', "'"])) { |
|
54 | 1 | $quoted->add(Dialect::QUOTE_MINIMAL); |
|
55 | 1 | } elseif (!is_numeric((string) $value)) { |
|
56 | 1 | $quoted->add(Dialect::QUOTE_NONNUMERIC); |
|
57 | 1 | } else { |
|
58 | 1 | $quoted->add(Dialect::QUOTE_ALL); |
|
59 | } |
||
60 | 1 | } else { |
|
61 | 1 | $styles[Dialect::QUOTE_ALL] = false; |
|
62 | } |
||
63 | 1 | } |
|
64 | 1 | }); |
|
65 | |||
66 | // @todo the following can almost certainly be cleaned up considerably |
||
67 | 1 | if ($styles[Dialect::QUOTE_ALL]) { |
|
68 | 1 | return Dialect::QUOTE_ALL; |
|
69 | 1 | } elseif ($styles[Dialect::QUOTE_NONE]) { |
|
70 | 1 | return Dialect::QUOTE_NONE; |
|
71 | } |
||
72 | |||
73 | 1 | $types = $quoted->distinct(); |
|
74 | |||
75 | 1 | if ($types->contains(Dialect::QUOTE_NONNUMERIC) && $types->contains(Dialect::QUOTE_MINIMAL)) { |
|
76 | // if both non-numeric and minimal then it isn't minimal |
||
77 | $types = $types->filter(function($type) { |
||
78 | return $type !== Dialect::QUOTE_MINIMAL; |
||
79 | }); |
||
80 | } |
||
81 | |||
82 | 1 | if ($types->count() == 1) { |
|
83 | 1 | return $types->getValueAt(1); |
|
84 | } |
||
85 | |||
86 | return Dialect::QUOTE_MINIMAL; |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * Determine whether a particular string of data has quotes around it. |
||
91 | * |
||
92 | * @param string $data The data to check |
||
93 | * |
||
94 | * @return bool |
||
95 | */ |
||
96 | 1 | protected function isQuoted($data) |
|
100 | } |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.