Completed
Push — master ( 5844c1...ab7dfd )
by Shcherbak
02:28
created

ArgumentsPattern::getArguments()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 7.0046

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 31
ccs 21
cts 22
cp 0.9545
rs 6.7272
cc 7
eloc 18
nc 7
nop 1
crap 7.0046
1
<?php
2
3
  namespace Funivan\PhpTokenizer\Pattern\Patterns;
4
5
  use Funivan\PhpTokenizer\Collection;
6
  use Funivan\PhpTokenizer\QuerySequence\QuerySequence;
7
  use Funivan\PhpTokenizer\Strategy\Section;
8
  use Funivan\PhpTokenizer\Token;
9
10
  /**
11
   *
12
   */
13
  class ArgumentsPattern implements PatternInterface {
14
15
    /**
16
     * @var array
17
     */
18
    private $argumentCheck = [];
19
20
    /**
21
     * @var int|null
22
     */
23
    private $outputArgument = null;
24
25
26
    /**
27
     *
28
     */
29 26
    public function __construct() {
30 20
      $this->outputFull();
31 26
    }
32
33
34
    /**
35
     * @param QuerySequence $querySequence
36
     * @return Collection|null
37
     * @throws \Exception
38
     */
39 26
    public function __invoke(QuerySequence $querySequence) {
40 20
      $section = $querySequence->section('(', ')');
41 20
      if ($section->count() === 0) {
42 16
        return null;
43
      }
44
45 20
      $section->slice(1, -1);
46
47 24
      if (empty($this->argumentCheck) and $this->outputArgument === null) {
48 10
        return $section;
49
      }
50
51
52
      /** @var Collection[] $arguments */
53 18
      $arguments = $this->getArguments($section);
54
55 22
      foreach ($this->argumentCheck as $index => $check) {
56
57 13
        $argumentTokens = isset($arguments[$index]) ? $arguments[$index] : new Collection();
58 12
        $result = $check($argumentTokens);
59
60 18
        if (!is_bool($result)) {
61 2
          throw new \Exception('Argument check function should return boolean');
62
        }
63
64 10
        if ($result === false) {
65 13
          return null;
66
        }
67 20
      }
68
69 22
      if ($this->outputArgument !== null) {
70 9
        $argumentCollection = !empty($arguments[$this->outputArgument]) ? $arguments[$this->outputArgument] : null;
71
72 9
        return $argumentCollection;
73
      }
74
75
      # output full
76 13
      return $section;
77
    }
78
79
80
    /**
81
     * @param int $int
82
     * @param callable $check
83
     * @return $this
84
     */
85 16
    public function withArgument($int, callable $check = null) {
86 16
      if ($check === null) {
87
        $check = function (Collection $argumentTokens) {
88 8
          return $argumentTokens->count() !== 0;
89 8
        };
90 8
      }
91 16
      $this->argumentCheck[$int] = $check;
92 16
      return $this;
93 4
    }
94
95
96
    /**
97
     * @param int $int
98
     * @return $this
99
     */
100
    public function withoutArgument($int) {
101 2
      $check = function (Collection $argumentTokens) {
102 2
        return $argumentTokens->count() === 0;
103 2
      };
104
105 3
      $this->argumentCheck[$int] = $check;
106 3
      return $this;
107
    }
108
109
110
    /**
111
     * @param $section
112
     * @return array
113
     */
114 25
    protected function getArguments(Collection $section) {
115
      /** @var Token $skipToToken */
116 22
      $skipToToken = null;
117 22
      $argumentIndex = 1;
118 22
      $arguments = [];
119 18
      $tokensNum = ($section->count() - 1);
120 18
      for ($tokenIndex = 0; $tokenIndex <= $tokensNum; $tokenIndex++) {
121
122 18
        $token = $section->offsetGet($tokenIndex);
123
124 18
        if ($token === null) {
125
          return null;
126
        }
127
128 18
        if ($skipToToken === null or $token->getIndex() >= $skipToToken->getIndex()) {
129 18
          if ($token->getValue() === ',') {
130 25
            $argumentIndex++;
131 25
            continue;
132
          }
133 18
          $skipToToken = $this->getEndArray($token, $section, $tokenIndex);
134 18
        }
135
136
137 18
        if (!isset($arguments[$argumentIndex])) {
138 18
          $arguments[$argumentIndex] = new Collection();
139 18
        }
140 18
        $arguments[$argumentIndex][] = $token;
141 18
      }
142
143 22
      return $arguments;
144 4
    }
145
146
147
    /**
148
     * @param Token $token
149
     * @param Collection $section
150
     * @param $index
151
     * @return Token
152
     */
153 18
    private function getEndArray(Token $token, Collection $section, $index) {
154
      // # check if we have array start
155
156 18
      if ($token->getValue() === '[') {
157 10
        $result = (new Section())->setDelimiters('[', ']')->process($section, $index);
158 10
        return $result->getToken();
159
      }
160
161 18
      if ($token->getValue() === '(') {
162 4
        $result = (new Section())->setDelimiters('(', ')')->process($section, $index);
163 4
        return $result->getToken();
164
      }
165
166 18
      return null;
167
    }
168
169
170
    /**
171
     * @return $this
172
     */
173 26
    public function outputFull() {
174 26
      $this->outputArgument = null;
175 26
      return $this;
176
    }
177
178
179
    /**
180
     * @param $int
181
     * @return $this
182
     */
183 9
    public function outputArgument($int) {
184 9
      $this->outputArgument = $int;
185 9
      return $this;
186
    }
187
188
  }