Completed
Pull Request — master (#7)
by
unknown
02:17
created

TableParser::parse()   C

Complexity

Conditions 10
Paths 6

Size

Total Lines 61
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 10.0186

Importance

Changes 0
Metric Value
dl 0
loc 61
ccs 33
cts 35
cp 0.9429
rs 6.4757
c 0
b 0
f 0
cc 10
eloc 35
nc 6
nop 2
crap 10.0186

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
/*
4
 * This is part of the webuni/commonmark-table-extension package.
5
 *
6
 * (c) Martin Hasoň <[email protected]>
7
 * (c) Webuni s.r.o. <[email protected]>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace Webuni\CommonMark\TableExtension;
14
15
use League\CommonMark\Block\Element\Paragraph;
16
use League\CommonMark\Block\Parser\AbstractBlockParser;
17
use League\CommonMark\ContextInterface;
18
use League\CommonMark\Cursor;
19
use League\CommonMark\Util\RegexHelper;
20
21
class TableParser extends AbstractBlockParser
22
{
23
    const REGEXP_DEFINITION = '/(?: *(:?) *-+ *(:?) *)+(?=\||$)/';
24
    const REGEXP_CELLS = '/(?:`[^`]*`|\\\\\\\\|\\\\\||[^|`\\\\]+)+(?=\||$)/';
25
    const REGEXP_CAPTION = '/^\[(.+?)\](?:\[(.+)\])?\s*$/';
26
27 16
    public function parse(ContextInterface $context, Cursor $cursor)
28
    {
29 16
        $container = $context->getContainer();
30
31 16
        if (!$container instanceof Paragraph) {
32 16
            return false;
33
        }
34
35 16
        $lines = $container->getStrings();
36 16
        if (count($lines) < 1) {
37
            return false;
38
        }
39
40 16
        $match = RegexHelper::matchAll(self::REGEXP_DEFINITION, $cursor->getLine(), $cursor->getFirstNonSpacePosition());
41 16
        if (null === $match) {
42 2
            return false;
43
        }
44
45 16
        $columns = $this->parseColumns($match);
46 16
        $head = $this->parseRow(trim(array_pop($lines)), $columns, TableCell::TYPE_HEAD);
47 16
        if (null === $head) {
48
            return false;
49
        }
50
51 16
        $table = new Table(function (Cursor $cursor) use (&$table, $columns) {
52 16
            $row = $this->parseRow($cursor->getLine(), $columns);
53 16
            if (null === $row) {
54 5
                if (null !== $table->getCaption()) {
55 2
                    return false;
56
                }
57
58 5
                if (null !== ($caption = $this->parseCaption($cursor->getLine()))) {
59 2
                    $table->setCaption($caption);
60
61 2
                    return true;
62
                }
63
64 3
                return false;
65
            }
66
67 16
            $table->getBody()->appendChild($row);
68
69 16
            return true;
70 16
        });
71
72 16
        $table->getHead()->appendChild($head);
73
74 16
        if (count($lines) >= 1) {
75 2
            $paragraph = new Paragraph();
76 2
            foreach ($lines as $line) {
77 2
                $paragraph->addLine($line);
78
            }
79
80 2
            $context->replaceContainerBlock($paragraph);
81 2
            $context->addBlock($table);
82
        } else {
83 15
            $context->replaceContainerBlock($table);
84
        }
85
86 16
        return true;
87
    }
88
89 16
    private function parseColumns(array $match)
90
    {
91 16
        $columns = [];
92 16
        foreach ((array) $match[0] as $i => $column) {
93 16
            if (isset($match[1][$i]) && $match[1][$i] && isset($match[2][$i]) && $match[2][$i]) {
94 3
                $columns[] = TableCell::ALIGN_CENTER;
95 16
            } elseif (isset($match[1][$i]) && $match[1][$i]) {
96 3
                $columns[] = TableCell::ALIGN_LEFT;
97 16
            } elseif (isset($match[2][$i]) && $match[2][$i]) {
98 3
                $columns[] = TableCell::ALIGN_RIGHT;
99
            } else {
100 16
                $columns[] = null;
101
            }
102
        }
103
104 16
        return $columns;
105
    }
106
107 16
    private function parseRow($line, array $columns, $type = TableCell::TYPE_BODY)
108
    {
109 16
        $cells = RegexHelper::matchAll(self::REGEXP_CELLS, $line);
110
111 16
        if (null === $cells) {
112 4
            return;
113
        }
114
115
        // If we have a single match we might be using a single-column table
116 16
        if (!is_array($cells[0])) {
117
            // If no indication of the existence of a cell, it's not a valid row
118 5
            if (strpos($line, "|") === false) {
119 4
                return;
120
            }
121
122
            // Fake single match as array of matches for the code below
123 3
            $cells = [$cells];
124
        }
125
126 16
        $row = new TableRow();
127 16
        foreach ($cells[0] as $i => $cell) {
128 16
            $row->appendChild(new TableCell(trim($cell), $type, isset($columns[$i]) ? $columns[$i] : null));
129
        }
130
131 16
        for ($j = count($columns) - 1; $j > $i; --$j) {
0 ignored issues
show
Bug introduced by
The variable $i seems to be defined by a foreach iteration on line 127. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
132 1
            $row->appendChild(new TableCell('', $type, null));
133
        }
134
135 16
        return $row;
136
    }
137
138 5
    private function parseCaption($line)
139
    {
140 5
        $caption = RegexHelper::matchAll(self::REGEXP_CAPTION, $line);
141
142 5
        if (null === $caption) {
143 3
            return;
144
        }
145
146 2
        return new TableCaption($caption[1], $caption[2]);
147
    }
148
}
149