Passed
Pull Request — master (#183)
by Luke
03:12
created

SniffQuoteStyle::sniff()   C

Complexity

Conditions 11
Paths 12

Size

Total Lines 55

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 11.2548

Importance

Changes 0
Metric Value
cc 11
nc 12
nop 1
dl 0
loc 55
ccs 34
cts 39
cp 0.8718
crap 11.2548
rs 6.8351
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
 * @copyright Copyright (c) 2018 Luke Visinoni
10
 * @author    Luke Visinoni <[email protected]>
11
 * @license   See LICENSE file (MIT license)
12
 */
13
namespace CSVelte\Sniffer;
14
15
use CSVelte\Dialect;
16
17
use function Noz\collect;
18
use function Stringy\create as s;
19
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) {
0 ignored issues
show
Unused Code introduced by
The parameter $line_no is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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)
97
    {
98 1
        return preg_match('/^([\'"])[^\1]*\1$/', $data);
99
    }
100
}