Completed
Push — master ( 5ee576...f52338 )
by Shcherbak
03:52
created

ClassPattern::withModifier()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 12
ccs 6
cts 6
cp 1
rs 9.4285
cc 2
eloc 6
nc 1
nop 1
crap 2
1
<?php
2
3
  namespace Funivan\PhpTokenizer\Pattern\Patterns;
4
5
  use Funivan\PhpTokenizer\QuerySequence\QuerySequence;
6
  use Funivan\PhpTokenizer\Strategy\Possible;
7
  use Funivan\PhpTokenizer\Strategy\QueryStrategy;
8
  use Funivan\PhpTokenizer\Strategy\Strict;
9
  use Funivan\PhpTokenizer\Token;
10
11
  /**
12
   * Pattern used to finding classes in tour source code
13
   *
14
   */
15
  class ClassPattern implements PatternInterface {
16
17
    /**
18
     * Result of this pattern will be body of the class
19
     */
20
    const OUTPUT_BODY = 1;
21
22
    /**
23
     * Result of this pattern will be full class
24
     */
25
    const OUTPUT_FULL = 2;
26
27
28
    /**
29
     * @var QueryStrategy
30
     */
31
    private $nameQuery = null;
32
33
    /**
34
     * @var callable
35
     */
36
    private $docCommentChecker;
37
38
    /**
39
     * @var callable
40
     */
41
    private $modifierChecker;
42
43
    /**
44
     * @var int
45
     */
46
    private $outputType = self::OUTPUT_BODY;
47
48
49
    /**
50
     * By default we search for classes with any name
51
     */
52 56
    public function __construct() {
53 56
      $this->nameQuery = Strict::create()->valueLike('!.+!');
54 56
      $this->withPossibleDocComment();
55 56
      $this->withAnyModifier();
56 56
    }
57
58
59
    /**
60
     * @codeCoverageIgnore
61
     * @deprecated
62
     * @param string $name
63
     * @return $this
64
     */
65
    public function nameIs($name) {
66
      trigger_error("Deprecated. Use withName", E_USER_DEPRECATED);
67
      return $this->withName($name);
68
    }
69
70
71
    /**
72
     * @param QueryStrategy|string $name
73
     * @return $this
74
     */
75 14
    public function withName($name) {
76 14
      if (is_string($name)) {
77 8
        $this->nameQuery = Strict::create()->valueIs($name);
78 9
      } elseif ($name instanceof QueryStrategy) {
79 6
        $this->nameQuery = $name;
80 4
      } else {
81 3
        throw new \InvalidArgumentException('Expect string or QueryInterface');
82
      }
83
84 11
      return $this;
85
    }
86
87
88
    /**
89
     * @return $this
90
     */
91 3
    public function withDocComment() {
92
      $this->docCommentChecker = function (Token $comment, QuerySequence $q) {
93 3
        if ($comment->getType() != T_DOC_COMMENT) {
94 3
          $q->setValid(false);
95 2
        }
96 3
      };
97 3
      return $this;
98
    }
99
100
101
    /**
102
     * @return $this
103
     */
104 56
    public function withPossibleDocComment() {
105
      $this->docCommentChecker = function (Token $comment, QuerySequence $q) {
0 ignored issues
show
Unused Code introduced by
The parameter $comment 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...
Unused Code introduced by
The parameter $q 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...
106 47
        return;
107
      };
108 56
      return $this;
109
    }
110
111
112
    /**
113
     * @return $this
114
     */
115 3
    public function withoutDocComment() {
116
      $this->docCommentChecker = function (Token $comment, QuerySequence $q) {
117 3
        if ($comment->getType() == T_DOC_COMMENT) {
118 3
          $q->setValid(false);
119 2
        }
120 3
      };
121 3
      return $this;
122
    }
123
124
125
    /**
126
     * @return $this
127
     */
128 3
    public function outputBody() {
129 3
      $this->outputType = self::OUTPUT_BODY;
130 3
      return $this;
131
    }
132
133
134
    /**
135
     * @return $this
136
     */
137 21
    public function outputFull() {
138 21
      $this->outputType = self::OUTPUT_FULL;
139 21
      return $this;
140
    }
141
142
143
    /**
144
     * @codeCoverageIgnore
145
     * @deprecated
146
     * @param QueryStrategy $strategy
147
     * @return $this
148
     */
149
    public function whereName(QueryStrategy $strategy) {
150
      trigger_error("Deprecated. Use withName", E_USER_DEPRECATED);
151
      return $this->withName($strategy);
152
    }
153
154
155
    /**
156
     * @inheritdoc
157
     */
158 53
    public function __invoke(QuerySequence $querySequence) {
159
160
161 53
      $comment = $querySequence->process(Possible::create()->typeIs(T_DOC_COMMENT));
162
163 53
      $querySequence->possible(T_WHITESPACE);
164 53
      $modifier = $querySequence->process(Possible::create()->valueIs([
165 53
        'abstract',
166 35
        'final',
167 35
      ]));
168
169 53
      $querySequence->possible(T_WHITESPACE);
170 53
      $start = $querySequence->strict('class');
171 53
      $querySequence->strict(T_WHITESPACE);
172 53
      $querySequence->process($this->nameQuery);
173 53
      $startClassBody = $querySequence->search('{');
174 53
      $querySequence->moveToToken($startClassBody);
175 53
      $body = $querySequence->section('{', '}');
176
177 53
      if ($modifier->isValid()) {
178 21
        $start = $modifier;
179 14
      }
180
181 53
      if ($comment->isValid()) {
182 15
        $start = $comment;
183 10
      }
184
185 53
      $docCommentChecker = $this->docCommentChecker;
186 53
      $docCommentChecker($comment, $querySequence);
187
188
189 53
      foreach ($this->modifierChecker as $checker) {
0 ignored issues
show
Bug introduced by
The expression $this->modifierChecker of type callable is not traversable.
Loading history...
190 53
        $checker($modifier, $querySequence);
191 35
      }
192
193
194 53
      if (!$querySequence->isValid()) {
195 53
        return null;
196
      }
197
198
199 50
      if ($this->outputType == self::OUTPUT_BODY) {
200 29
        return $body->extractItems(1, -1);
201
      }
202
203
      # self::OUTPUT_FULL
204 21
      return $querySequence->getCollection()->extractByTokens($start, $body->getLast());
205
    }
206
207
208
    /**
209
     * @return $this
210
     */
211 56
    public function withAnyModifier() {
212 56
      $this->modifierChecker = [];
213
      $this->modifierChecker[] = function (Token $token, QuerySequence $q) {
0 ignored issues
show
Unused Code introduced by
The parameter $token 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...
Unused Code introduced by
The parameter $q 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...
214 53
        return;
215
      };
216 56
      return $this;
217
    }
218
219
220
    /**
221
     * @param string $modifier
222
     * @return $this
223
     */
224 6
    public function withModifier($modifier) {
225
226
      $this->modifierChecker[] = function (Token $token, QuerySequence $q) use ($modifier) {
227 6
        if ($token->getValue() != $modifier) {
228 6
          $q->setValid(false);
229 4
        }
230 6
        return;
231
      };
232
233
234 6
      return $this;
235
    }
236
237
238
    /**
239
     * @param string $modifier
240
     * @return $this
241
     */
242
    public function withoutModifier($modifier) {
243
244 3
      $this->modifierChecker[] = function (Token $token, QuerySequence $q) use ($modifier) {
245 3
        if ($token->getValue() == $modifier) {
246 3
          $q->setValid(false);
247 2
        }
248 3
        return;
249
      };
250 3
      return $this;
251
    }
252
253
254
  }