PhpdocParser::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Jasny\PhpdocParser;
6
7
use Jasny\PhpdocParser\TagInterface;
8
use Jasny\PhpdocParser\TagSet;
9
10
/**
11
 * Class PhpdocParser
12
 */
13
class PhpdocParser
14
{
15
    /**
16
     * @var TagSet|TagInterface[]
17
     */
18
    protected $tags;
19
20
    /**
21
     * PhpdocParser constructor.
22
     *
23
     * @param TagSet|TagInterface[] $tags
24
     */
25 9
    public function __construct(TagSet $tags)
26
    {
27 9
        $this->tags = $tags;
28
    }
29
30
    /**
31
     * Parse a PHP doc comment
32
     *
33
     * @param string $doc
34
     * @param callable $callback
35
     * @return array
36
     */
37 9
    public function parse(string $doc, ?callable $callback = null): array
38
    {
39 9
        $notations = [];
40 9
        $rawNotations = $this->extractNotations($doc);
41 9
        $rawNotations = $this->joinMultilineNotations($rawNotations);
42
43 9
        foreach ($rawNotations as $item) {
44 8
            if (!isset($this->tags[$item['tag']])) {
45 2
                continue;
46
            }
47
48 7
            $notations = $this->tags[$item['tag']]->process($notations, $item['value'] ?? '');
49
        }
50
51 9
        if (isset($this->tags['summery'])) {
52 1
            $notations = $this->tags['summery']->process($notations, $doc);
53
        }
54
55 9
        if ($callback !== null) {
56 1
            $notations = $callback($notations);
57
        }
58
59 9
        return $notations;
60
    }
61
62
63
    /**
64
     * Extract notation from doc comment
65
     *
66
     * @param string $doc
67
     * @return array
68
     */
69 9
    protected function extractNotations(string $doc): array
70
    {
71 9
        $matches = null;
72
73 9
        $tag = '\s*@(?<tag>\S+)(?:\h+(?<value>\S.*?)|\h*)';
74 9
        $tagContinue = '(?:\040){2}(?<multiline_value>\S.*?)';
75 9
        $regex = '/^\s*(?:(?:\/\*)?\*)?(?:' . $tag . '|' . $tagContinue . ')(?:\s*\*\*\/)?\r?$/m';
76
77 9
        return preg_match_all($regex, $doc, $matches, PREG_SET_ORDER) ? $matches : [];
78
    }
79
80
    /**
81
     * Join multiline notations
82
     *
83
     * @param array $rawNotations
84
     * @return array
85
     */
86 9
    protected function joinMultilineNotations(array $rawNotations): array
87
    {
88 9
        $result = [];
89 9
        $tagsNotations = $this->filterTagsNotations($rawNotations);
90
91 9
        foreach ($tagsNotations as $item) {
92 8
            if ($item['tag'] !== '') {
93 8
                $result[] = $item;
94
            } else {
95 1
                $lastIdx = count($result) - 1;
96
97 1
                if (!isset($result[$lastIdx]['value'])) {
98
                    $result[$lastIdx]['value'] = '';
99
                }
100
101 1
                $result[$lastIdx]['value'] = trim($result[$lastIdx]['value'])
102 1
                    . ' ' . trim($item['multiline_value']);
103
            }
104
        }
105
106 9
        return $result;
107
    }
108
109
    /**
110
     * Remove everything that goes before tags
111
     *
112
     * @param array $rawNotations
113
     * @return array
114
     */
115 9
    protected function filterTagsNotations(array $rawNotations): array
116
    {
117 9
        for ($i = 0; $i < count($rawNotations); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
118 8
            if ($rawNotations[$i]['tag'] !== '') {
119 8
                return array_slice($rawNotations, $i);
120
            }
121
        }
122
123 1
        return [];
124
    }
125
}
126