Completed
Push — master ( 494091...32c874 )
by David
27s
created

PluginMath::compile()   D

Complexity

Conditions 16
Paths 53

Size

Total Lines 145
Code Lines 110

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 110
nc 53
nop 5
dl 0
loc 145
rs 4.8736
c 0
b 0
f 0

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
 * Copyright (c) 2013-2017
4
 *
5
 * @category  Library
6
 * @package   Dwoo\Plugins\Functions
7
 * @author    Jordi Boggiano <[email protected]>
8
 * @author    David Sanchez <[email protected]>
9
 * @copyright 2008-2013 Jordi Boggiano
10
 * @copyright 2013-2017 David Sanchez
11
 * @license   http://dwoo.org/LICENSE Modified BSD License
12
 * @version   1.3.2
13
 * @date      2017-01-06
14
 * @link      http://dwoo.org/
15
 */
16
17
namespace Dwoo\Plugins\Functions;
18
19
use Dwoo\Compiler;
20
use Dwoo\Compilation\Exception as CompilationException;
21
use Dwoo\ICompilable;
22
use Dwoo\Plugin;
23
24
/**
25
 * Computes a mathematical equation
26
 * <pre>
27
 *  * equation : the equation to compute, it can include normal variables with $foo or special math variables without
28
 *  the dollar sign
29
 *  * format : output format, see {@link http://php.net/sprintf} for details
30
 *  * assign : if set, the output is assigned into the given variable name instead of being output
31
 *  * rest : all math specific variables that you use must be defined, see the example
32
 * </pre>
33
 * Example :.
34
 * <code>
35
 * {$c=2}
36
 * {math "(a+b)*$c/4" a=3 b=5}
37
 * output is : 4 ( = (3+5)*2/4)
38
 * </code>
39
 * This software is provided 'as-is', without any express or implied warranty.
40
 * In no event will the authors be held liable for any damages arising from the use of this software.
41
 */
42
class PluginMath extends Plugin implements ICompilable
43
{
44
    /**
45
     * @param Compiler $compiler
46
     * @param string   $equation
47
     * @param string   $format
48
     * @param string   $assign
49
     * @param array    $rest
50
     *
51
     * @return string
52
     * @throws CompilationException
53
     */
54
    public static function compile(Compiler $compiler, $equation, $format = '', $assign = '', array $rest = array())
55
    {
56
        /*
57
         * Holds the allowed function, characters, operators and constants
58
         */
59
        $allowed = array(
60
            '0',
61
            '1',
62
            '2',
63
            '3',
64
            '4',
65
            '5',
66
            '6',
67
            '7',
68
            '8',
69
            '9',
70
            '+',
71
            '-',
72
            '/',
73
            '*',
74
            '.',
75
            ' ',
76
            '<<',
77
            '>>',
78
            '%',
79
            '&',
80
            '^',
81
            '|',
82
            '~',
83
            'abs(',
84
            'ceil(',
85
            'floor(',
86
            'exp(',
87
            'log10(',
88
            'cos(',
89
            'sin(',
90
            'sqrt(',
91
            'tan(',
92
            'M_PI',
93
            'INF',
94
            'M_E',
95
        );
96
97
        /*
98
         * Holds the functions that can accept multiple arguments
99
         */
100
        $funcs = array(
101
            'round(',
102
            'log(',
103
            'pow(',
104
            'max(',
105
            'min(',
106
            'rand(',
107
        );
108
109
        $equation = $equationSrc = str_ireplace(array(
110
            'pi',
111
            'M_PI()',
112
            'inf',
113
            ' e '
114
        ),
115
            array(
116
                'M_PI',
117
                'M_PI',
118
                'INF',
119
                ' M_E '
120
            ),
121
            $equation);
122
123
        $delim      = $equation[0];
124
        $open       = $delim . '.';
125
        $close      = '.' . $delim;
126
        $equation   = substr($equation, 1, - 1);
127
        $out        = '';
128
        $ptr        = 1;
129
        $allowcomma = 0;
130
        while (strlen($equation) > 0) {
131
            $substr = substr($equation, 0, $ptr);
132
            if (array_search($substr, $allowed) !== false) {
133
                // allowed string
134
                $out .= $substr;
135
                $equation = substr($equation, $ptr);
136
                $ptr      = 0;
137
            } elseif (array_search($substr, $funcs) !== false) {
138
                // allowed func
139
                $out .= $substr;
140
                $equation = substr($equation, $ptr);
141
                $ptr      = 0;
142
                ++ $allowcomma;
143
                if ($allowcomma === 1) {
144
                    $allowed[] = ',';
145
                }
146
            } elseif (isset($rest[$substr])) {
147
                // variable
148
                $out .= $rest[$substr];
149
                $equation = substr($equation, $ptr);
150
                $ptr      = 0;
151
            } elseif ($substr === $open) {
152
                // pre-replaced variable
153
                preg_match('#.*\((?:[^()]*?|(?R))\)' . str_replace('.', '\\.', $close) . '#', substr($equation, 2), $m);
154
                if (empty($m)) {
155
                    preg_match('#.*?' . str_replace('.', '\\.', $close) . '#', substr($equation, 2), $m);
156
                }
157
                $out .= substr($m[0], 0, - 2);
158
                $equation = substr($equation, strlen($m[0]) + 2);
159
                $ptr      = 0;
160
            } elseif ($substr === '(') {
161
                // opening parenthesis
162
                if ($allowcomma > 0) {
163
                    ++ $allowcomma;
164
                }
165
166
                $out .= $substr;
167
                $equation = substr($equation, $ptr);
168
                $ptr      = 0;
169
            } elseif ($substr === ')') {
170
                // closing parenthesis
171
                if ($allowcomma > 0) {
172
                    -- $allowcomma;
173
                    if ($allowcomma === 0) {
174
                        array_pop($allowed);
175
                    }
176
                }
177
178
                $out .= $substr;
179
                $equation = substr($equation, $ptr);
180
                $ptr      = 0;
181
            } elseif ($ptr >= strlen($equation)) {
182
                // parse error if we've consumed the entire equation without finding anything valid
183
                throw new CompilationException($compiler,
184
                    'Math : Syntax error or variable undefined in equation ' . $equationSrc . ' at ' . $substr);
185
            } else {
186
                // nothing special, advance
187
                ++ $ptr;
188
            }
189
        }
190
        if ($format !== '\'\'') {
191
            $out = 'sprintf(' . $format . ', ' . $out . ')';
192
        }
193
        if ($assign !== '\'\'') {
194
            return '($this->assignInScope(' . $out . ', ' . $assign . '))';
195
        }
196
197
        return '(' . $out . ')';
198
    }
199
}