PoHeader::parseArithmetic()   F
last analyzed

Complexity

Conditions 22
Paths 241

Size

Total Lines 88
Code Lines 49

Duplication

Lines 6
Ratio 6.82 %

Importance

Changes 0
Metric Value
cc 22
eloc 49
c 0
b 0
f 0
nc 241
nop 1
dl 6
loc 88
rs 3.7415

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
 * @file
5
 * Contains \Drupal\Component\Gettext\PoHeader.
6
 */
7
8
namespace Drupal\Component\Gettext;
9
10
/**
11
 * Gettext PO header handler.
12
 *
13
 * Possible Gettext PO header elements are explained in
14
 * http://www.gnu.org/software/gettext/manual/gettext.html#Header-Entry,
15
 * but we only support a subset of these directly.
16
 *
17
 * Example header:
18
 *
19
 * "Project-Id-Version: Drupal core (7.11)\n"
20
 * "POT-Creation-Date: 2012-02-12 22:59+0000\n"
21
 * "PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
22
 * "Language-Team: Catalan\n"
23
 * "MIME-Version: 1.0\n"
24
 * "Content-Type: text/plain; charset=utf-8\n"
25
 * "Content-Transfer-Encoding: 8bit\n"
26
 * "Plural-Forms: nplurals=2; plural=(n>1);\n"
27
 */
28
class PoHeader {
29
30
  /**
31
   * Language code.
32
   *
33
   * @var string
34
   */
35
  private $_langcode;
36
37
  /**
38
   * Formula for the plural form.
39
   *
40
   * @var string
41
   */
42
  private $_pluralForms;
43
44
  /**
45
   * Author(s) of the file.
46
   *
47
   * @var string
48
   */
49
  private $_authors;
50
51
  /**
52
   * Date the po file got created.
53
   *
54
   * @var string
55
   */
56
  private $_po_date;
57
58
  /**
59
   * Human readable language name.
60
   *
61
   * @var string
62
   */
63
  private $_languageName;
64
65
  /**
66
   * Name of the project the translation belongs to.
67
   *
68
   * @var string
69
   */
70
  private $_projectName;
71
72
  /**
73
   * Constructor, creates a PoHeader with default values.
74
   *
75
   * @param string $langcode
76
   *   Language code.
77
   */
78
  public function __construct($langcode = NULL) {
79
    $this->_langcode = $langcode;
80
    // Ignore errors when run during site installation before
81
    // date_default_timezone_set() is called.
82
    $this->_po_date = @date("Y-m-d H:iO");
83
    $this->_pluralForms = 'nplurals=2; plural=(n > 1);';
84
  }
85
86
  /**
87
   * Gets the plural form.
88
   *
89
   * @return string
90
   *   Plural form component from the header, for example:
91
   *   'nplurals=2; plural=(n > 1);'.
92
   */
93
  function getPluralForms() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
94
    return $this->_pluralForms;
95
  }
96
97
  /**
98
   * Set the human readable language name.
99
   *
100
   * @param string $languageName
101
   *   Human readable language name.
102
   */
103
  function setLanguageName($languageName) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
104
    $this->_languageName = $languageName;
105
  }
106
107
  /**
108
   * Gets the human readable language name.
109
   *
110
   * @return string
111
   *   The human readable language name.
112
   */
113
  function getLanguageName() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
114
    return $this->_languageName;
115
  }
116
117
  /**
118
   * Set the project name.
119
   *
120
   * @param string $projectName
121
   *   Human readable project name.
122
   */
123
  function setProjectName($projectName) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
124
    $this->_projectName = $projectName;
125
  }
126
127
  /**
128
   * Gets the project name.
129
   *
130
   * @return string
131
   *   The human readable project name.
132
   */
133
  function getProjectName() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
134
    return $this->_projectName;
135
  }
136
137
  /**
138
   * Populate internal values from a string.
139
   *
140
   * @param string $header
141
   *   Full header string with key-value pairs.
142
   */
143
  public function setFromString($header) {
144
    // Get an array of all header values for processing.
145
    $values = $this->parseHeader($header);
146
147
    // There is only one value relevant for our header implementation when
148
    // reading, and that is the plural formula.
149
    if (!empty($values['Plural-Forms'])) {
150
      $this->_pluralForms = $values['Plural-Forms'];
151
    }
152
  }
153
154
  /**
155
   * Generate a Gettext PO formatted header string based on data set earlier.
156
   */
157
  public function __toString() {
158
    $output = '';
159
160
    $isTemplate = empty($this->_languageName);
161
162
    $output .= '# ' . ($isTemplate ? 'LANGUAGE' : $this->_languageName) . ' translation of ' . ($isTemplate ? 'PROJECT' : $this->_projectName) . "\n";
163
    if (!empty($this->_authors)) {
164
      $output .= '# Generated by ' . implode("\n# ", $this->_authors) . "\n";
165
    }
166
    $output .= "#\n";
167
168
    // Add the actual header information.
169
    $output .= "msgid \"\"\n";
170
    $output .= "msgstr \"\"\n";
171
    $output .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
172
    $output .= "\"POT-Creation-Date: " . $this->_po_date . "\\n\"\n";
173
    $output .= "\"PO-Revision-Date: " . $this->_po_date . "\\n\"\n";
174
    $output .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
175
    $output .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
176
    $output .= "\"MIME-Version: 1.0\\n\"\n";
177
    $output .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
178
    $output .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
179
    $output .= "\"Plural-Forms: " . $this->_pluralForms . "\\n\"\n";
180
    $output .= "\n";
181
182
    return $output;
183
  }
184
185
  /**
186
   * Parses a Plural-Forms entry from a Gettext Portable Object file header.
187
   *
188
   * @param string $pluralforms
189
   *   The Plural-Forms entry value.
190
   *
191
   * @return
192
   *   An indexed array of parsed plural formula data. Containing:
193
   *   - 'nplurals': The number of plural forms defined by the plural formula.
194
   *   - 'plurals': Array of plural positions keyed by plural value.
195
   *
196
   * @throws Exception
197
   */
198
  function parsePluralForms($pluralforms) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
199
    $plurals = array();
200
    // First, delete all whitespace.
201
    $pluralforms = strtr($pluralforms, array(" " => "", "\t" => ""));
202
203
    // Select the parts that define nplurals and plural.
204
    $nplurals = strstr($pluralforms, "nplurals=");
205 View Code Duplication
    if (strpos($nplurals, ";")) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
206
      // We want the string from the 10th char, because "nplurals=" length is 9.
207
      $nplurals = substr($nplurals, 9, strpos($nplurals, ";") - 9);
208
    }
209
    else {
210
      return FALSE;
211
    }
212
    $plural = strstr($pluralforms, "plural=");
213 View Code Duplication
    if (strpos($plural, ";")) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
214
      // We want the string from the 8th char, because "plural=" length is 7.
215
      $plural = substr($plural, 7, strpos($plural, ";") - 7);
216
    }
217
    else {
218
      return FALSE;
219
    }
220
221
    // If the number of plurals is zero, we return a default result.
222
    if ($nplurals == 0) {
223
      return array($nplurals, array('default' => 0));
224
    }
225
226
    // Calculate possible plural positions of different plural values. All known
227
    // plural formula's are repetitive above 100.
228
    // For data compression we store the last position the array value
229
    // changes and store it as default.
230
    $element_stack = $this->parseArithmetic($plural);
231
    if ($element_stack !== FALSE) {
232
      for ($i = 0; $i <= 199; $i++) {
233
        $plurals[$i] = $this->evaluatePlural($element_stack, $i);
234
      }
235
      $default = $plurals[$i - 1];
236
      $plurals = array_filter($plurals, function ($value) use ($default) {
237
        return ($value != $default);
238
      });
239
      $plurals['default'] = $default;
240
241
      return array($nplurals, $plurals);
242
    }
243
    else {
244
      throw new \Exception('The plural formula could not be parsed.');
245
    }
246
  }
247
248
  /**
249
   * Parses a Gettext Portable Object file header.
250
   *
251
   * @param string $header
252
   *   A string containing the complete header.
253
   *
254
   * @return array
255
   *   An associative array of key-value pairs.
256
   */
257
  private function parseHeader($header) {
258
    $header_parsed = array();
259
    $lines = array_map('trim', explode("\n", $header));
260
    foreach ($lines as $line) {
261
      if ($line) {
262
        list($tag, $contents) = explode(":", $line, 2);
263
        $header_parsed[trim($tag)] = trim($contents);
264
      }
265
    }
266
    return $header_parsed;
267
  }
268
269
  /**
270
   * Parses and sanitizes an arithmetic formula into a plural element stack.
271
   *
272
   * While parsing, we ensure, that the operators have the right
273
   * precedence and associativity.
274
   *
275
   * @param string $string
276
   *   A string containing the arithmetic formula.
277
   *
278
   * @return
279
   *   A stack of values and operations to be evaluated.
280
   */
281
  private function parseArithmetic($string) {
282
    // Operator precedence table.
283
    $precedence = array("(" => -1, ")" => -1, "?" => 1, ":" => 1, "||" => 3, "&&" => 4, "==" => 5, "!=" => 5, "<" => 6, ">" => 6, "<=" => 6, ">=" => 6, "+" => 7, "-" => 7, "*" => 8, "/" => 8, "%" => 8);
284
    // Right associativity.
285
    $right_associativity = array("?" => 1, ":" => 1);
286
287
    $tokens = $this->tokenizeFormula($string);
288
289
    // Parse by converting into infix notation then back into postfix
290
    // Operator stack - holds math operators and symbols.
291
    $operator_stack = array();
292
    // Element Stack - holds data to be operated on.
293
    $element_stack = array();
294
295
    foreach ($tokens as $token) {
296
      $current_token = $token;
297
298
      // Numbers and the $n variable are simply pushed into $element_stack.
299
      if (is_numeric($token)) {
300
        $element_stack[] = $current_token;
301
      }
302
      elseif ($current_token == "n") {
303
        $element_stack[] = '$n';
304
      }
305
      elseif ($current_token == "(") {
306
        $operator_stack[] = $current_token;
307
      }
308
      elseif ($current_token == ")") {
309
        $topop = array_pop($operator_stack);
310
        while (isset($topop) && ($topop != "(")) {
311
          $element_stack[] = $topop;
312
          $topop = array_pop($operator_stack);
313
        }
314
      }
315
      elseif (!empty($precedence[$current_token])) {
316
        // If it's an operator, then pop from $operator_stack into
317
        // $element_stack until the precedence in $operator_stack is less
318
        // than current, then push into $operator_stack.
319
        $topop = array_pop($operator_stack);
320
        while (isset($topop) && ($precedence[$topop] >= $precedence[$current_token]) && !(($precedence[$topop] == $precedence[$current_token]) && !empty($right_associativity[$topop]) && !empty($right_associativity[$current_token]))) {
321
          $element_stack[] = $topop;
322
          $topop = array_pop($operator_stack);
323
        }
324
        if ($topop) {
325
          // Return element to top.
326
          $operator_stack[] = $topop;
327
        }
328
        // Parentheses are not needed.
329
        $operator_stack[] = $current_token;
330
      }
331
      else {
332
        return FALSE;
333
      }
334
    }
335
336
    // Flush operator stack.
337
    $topop = array_pop($operator_stack);
338
    while ($topop != NULL) {
339
      $element_stack[] = $topop;
340
      $topop = array_pop($operator_stack);
341
    }
342
    $return = $element_stack;
343
344
    // Now validate stack.
345
    $previous_size = count($element_stack) + 1;
346
    while (count($element_stack) < $previous_size) {
347
      $previous_size = count($element_stack);
348
      for ($i = 2; $i < count($element_stack); $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...
349
        $op = $element_stack[$i];
350
        if (!empty($precedence[$op])) {
351
          if ($op == ":") {
352
            $f = $element_stack[$i - 2] . "):" . $element_stack[$i - 1] . ")";
353
          }
354 View Code Duplication
          elseif ($op == "?") {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
355
            $f = "(" . $element_stack[$i - 2] . "?(" . $element_stack[$i - 1];
356
          }
357 View Code Duplication
          else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
358
            $f = "(" . $element_stack[$i - 2] . $op . $element_stack[$i - 1] . ")";
359
          }
360
          array_splice($element_stack, $i - 2, 3, $f);
361
          break;
362
        }
363
      }
364
    }
365
366
    // If only one element is left, the number of operators is appropriate.
367
    return count($element_stack) == 1 ? $return : FALSE;
368
  }
369
370
  /**
371
   * Tokenize the formula.
372
   *
373
   * @param string $formula
374
   *   A string containing the arithmetic formula.
375
   *
376
   * @return array
377
   *   List of arithmetic tokens identified in the formula.
378
   */
379
  private function tokenizeFormula($formula) {
380
    $formula = str_replace(" ", "", $formula);
381
    $tokens = array();
382
    for ($i = 0; $i < strlen($formula); $i++) {
383
      if (is_numeric($formula[$i])) {
384
        $num = $formula[$i];
385
        $j = $i + 1;
386
        while ($j < strlen($formula) && is_numeric($formula[$j])) {
387
          $num .= $formula[$j];
388
          $j++;
389
        }
390
        $i = $j - 1;
391
        $tokens[] = $num;
392
      }
393
      elseif ($pos = strpos(" =<>!&|", $formula[$i])) {
394
        $next = $formula[$i + 1];
395
        switch ($pos) {
396
          case 1:
397
          case 2:
398
          case 3:
399 View Code Duplication
          case 4:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
400
            if ($next == '=') {
401
              $tokens[] = $formula[$i] . '=';
402
              $i++;
403
            }
404
            else {
405
              $tokens[] = $formula[$i];
406
            }
407
            break;
408 View Code Duplication
          case 5:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
409
            if ($next == '&') {
410
              $tokens[] = '&&';
411
              $i++;
412
            }
413
            else {
414
              $tokens[] = $formula[$i];
415
            }
416
            break;
417 View Code Duplication
          case 6:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
418
            if ($next == '|') {
419
              $tokens[] = '||';
420
              $i++;
421
            }
422
            else {
423
              $tokens[] = $formula[$i];
424
            }
425
            break;
426
        }
427
      }
428
      else {
429
        $tokens[] = $formula[$i];
430
      }
431
    }
432
    return $tokens;
433
  }
434
435
  /**
436
   * Evaluate the plural element stack using a plural value.
437
   *
438
   * Using an element stack, which represents a plural formula, we calculate
439
   * which plural string should be used for a given plural value.
440
   *
441
   * An example of plural formula parting and evaluation:
442
   *   Plural formula: 'n!=1'
443
   * This formula is parsed by parseArithmetic() to a stack (array) of elements:
444
   *   array(
445
   *     0 => '$n',
446
   *     1 => '1',
447
   *     2 => '!=',
448
   *   );
449
   * The evaluatePlural() method evaluates the $element_stack using the plural
450
   * value $n. Before the actual evaluation, the '$n' in the array is replaced
451
   * by the value of $n.
452
   *   For example: $n = 2 results in:
453
   *   array(
454
   *     0 => '2',
455
   *     1 => '1',
456
   *     2 => '!=',
457
   *   );
458
   * The stack is processed until only one element is (the result) is left. In
459
   * every iteration the top elements of the stack, up until the first operator,
460
   * are evaluated. After evaluation the arguments and the operator itself are
461
   * removed and replaced by the evaluation result. This is typically 2
462
   * arguments and 1 element for the operator.
463
   *   Because the operator is '!=' the example stack is evaluated as:
464
   *   $f = (int) 2 != 1;
465
   *   The resulting stack is:
466
   *   array(
467
   *     0 => 1,
468
   *   );
469
   * With only one element left in the stack (the final result) the loop is
470
   * terminated and the result is returned.
471
   *
472
   * @param array $element_stack
473
   *   Array of plural formula values and operators create by parseArithmetic().
474
   * @param integer $n
475
   *   The @count number for which we are determining the right plural position.
476
   *
477
   * @return integer
478
   *   Number of the plural string to be used for the given plural value.
479
   *
480
   * @see parseArithmetic()
481
   * @throws Exception
482
   */
483
  protected function evaluatePlural($element_stack, $n) {
484
    $count = count($element_stack);
485
    $limit = $count;
486
    // Replace the '$n' value in the formula by the plural value.
487
    for ($i = 0; $i < $count; $i++) {
488
      if ($element_stack[$i] === '$n') {
489
        $element_stack[$i] = $n;
490
      }
491
    }
492
493
    // We process the stack until only one element is (the result) is left.
494
    // We limit the number of evaluation cycles to prevent an endless loop in
495
    // case the stack contains an error.
496
    while (isset($element_stack[1])) {
497
      for ($i = 2; $i < $count; $i++) {
498
        // There's no point in checking non-symbols. Also, switch(TRUE) would
499
        // match any case and so it would break.
500
        if (is_bool($element_stack[$i]) || is_numeric($element_stack[$i])) {
501
          continue;
502
        }
503
        $f = NULL;
504
        $length = 3;
505
        $delta = 2;
506
        switch ($element_stack[$i]) {
507 View Code Duplication
          case '==':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
508
            $f = $element_stack[$i - 2] == $element_stack[$i - 1];
509
            break;
510 View Code Duplication
          case '!=':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
511
            $f = $element_stack[$i - 2] != $element_stack[$i - 1];
512
            break;
513 View Code Duplication
          case '<=':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
514
            $f = $element_stack[$i - 2] <= $element_stack[$i - 1];
515
            break;
516 View Code Duplication
          case '>=':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
517
            $f = $element_stack[$i - 2] >= $element_stack[$i - 1];
518
            break;
519 View Code Duplication
          case '<':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
520
            $f = $element_stack[$i - 2] < $element_stack[$i - 1];
521
            break;
522 View Code Duplication
          case '>':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
523
            $f = $element_stack[$i - 2] > $element_stack[$i - 1];
524
            break;
525 View Code Duplication
          case '+':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
526
            $f = $element_stack[$i - 2] + $element_stack[$i - 1];
527
            break;
528 View Code Duplication
          case '-':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
529
            $f = $element_stack[$i - 2] - $element_stack[$i - 1];
530
            break;
531 View Code Duplication
          case '*':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
532
            $f = $element_stack[$i - 2] * $element_stack[$i - 1];
533
            break;
534 View Code Duplication
          case '/':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
535
            $f = $element_stack[$i - 2] / $element_stack[$i - 1];
536
            break;
537 View Code Duplication
          case '%':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
538
            $f = $element_stack[$i - 2] % $element_stack[$i - 1];
539
            break;
540 View Code Duplication
          case '&&':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
541
            $f = $element_stack[$i - 2] && $element_stack[$i - 1];
542
            break;
543 View Code Duplication
          case '||':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
544
            $f = $element_stack[$i - 2] || $element_stack[$i - 1];
545
            break;
546
          case ':':
547
            $f = $element_stack[$i - 3] ? $element_stack[$i - 2] : $element_stack[$i - 1];
548
            // This operator has 3 preceding elements, instead of the default 2.
549
            $length = 5;
550
            $delta = 3;
551
            break;
552
        }
553
554
        // If the element is an operator we remove the processed elements and
555
        // store the result.
556
        if (isset($f)) {
557
          array_splice($element_stack, $i - $delta, $length, $f);
558
          break;
559
        }
560
      }
561
    }
562
    if (!$limit) {
563
      throw new \Exception('The plural formula could not be evaluated.');
564
    }
565
    return (int) $element_stack[0];
566
  }
567
}
568