Passed
Push — master ( d8dc61...dfdb64 )
by Sebastian
09:05
created

AbstractIfBase   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 188
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 21
eloc 76
c 0
b 0
f 0
dl 0
loc 188
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getSign() 0 18 3
A getIfType() 0 5 1
A _translate() 0 29 3
A _translateVariable() 0 22 3
A _translateSearch() 0 13 2
A _translateNumberComparison() 0 7 1
A translateBody() 0 13 2
A _translateContains() 0 4 1
A _translateEmpty() 0 13 2
A _translateGeneric() 0 15 3
1
<?php
2
/**
3
 * @package Mailcode
4
 * @subpackage Translator
5
 */
6
7
declare(strict_types=1);
8
9
namespace Mailcode\Translator\Syntax\ApacheVelocity\Base;
10
11
use Mailcode\Commands\ParamsException;
12
use Mailcode\Mailcode_Commands_IfBase;
13
use Mailcode\Mailcode_Commands_LogicKeywords_Keyword;
14
use Mailcode\Mailcode_Exception;
15
use Mailcode\Mailcode_Parser_Statement_Tokenizer_Token_StringLiteral;
16
use Mailcode\Mailcode_Variables_Variable;
17
use Mailcode\Translator\Syntax\ApacheVelocity;
18
use Mailcode\Translator\Syntax\ApacheVelocity\Contains\ContainsStatementBuilder;
19
20
/**
21
 * Abstract base class for the IF/ELSEIF command translation classes.
22
 *
23
 * @package Mailcode
24
 * @subpackage Translator
25
 * @author Sebastian Mordziol <[email protected]>
26
 */
27
abstract class AbstractIfBase extends ApacheVelocity
28
{
29
    public const ERROR_CANNOT_GET_KEYWORD_SIGN = 60801;
30
    public const ERROR_INVALID_KEYWORD_COMMAND_TYPE = 60802;
31
    
32
    abstract protected function getCommandTemplate() : string;
33
34
    protected function getIfType(Mailcode_Commands_IfBase $command) : string
35
    {
36
        $parts = explode('_', get_class($command));
37
38
        return array_pop($parts);
39
    }
40
41
    protected function translateBody(Mailcode_Commands_IfBase $command) : string
42
    {
43
        // The command's getID() method will return "If" for all flavors
44
        // of the command. We use a custom method to determine the actual
45
        // IF type.
46
        $method = 'translate'.$this->getIfType($command);
47
48
        if(method_exists($this, $method))
49
        {
50
            return (string)$this->$method($command);
51
        }
52
53
        return '';
54
    }
55
56
    /**
57
     * @param Mailcode_Commands_IfBase $command
58
     * @return string
59
     * @throws Mailcode_Exception
60
     * @throws ParamsException
61
     */
62
    protected function _translate(Mailcode_Commands_IfBase $command): string
63
    {
64
        $body = $this->translateBody($command);
65
        
66
        $keywords = $command->getLogicKeywords()->getKeywords();
67
        
68
        foreach($keywords as $keyword)
69
        {
70
            $keyCommand = $keyword->getCommand();
71
            
72
            if($keyCommand instanceof Mailcode_Commands_IfBase)
73
            {
74
                $body .= ' '.$this->getSign($keyword).' '.$this->translateBody($keyCommand);
75
            }
76
            else
77
            {
78
                throw new Mailcode_Exception(
79
                    'Keyword command type does not match expected base class.',
80
                    sprintf(
81
                        'Expected instance of [%s], got [%s].',
82
                        Mailcode_Commands_IfBase::class,
83
                        get_class($keyCommand)
84
                    ),
85
                    self::ERROR_INVALID_KEYWORD_COMMAND_TYPE
86
                );
87
            }
88
        }
89
        
90
        return sprintf($this->getCommandTemplate(), $body);
91
    }
92
93
    /**
94
     * @param Mailcode_Commands_LogicKeywords_Keyword $keyword
95
     * @return string
96
     * @throws Mailcode_Exception
97
     */
98
    protected function getSign(Mailcode_Commands_LogicKeywords_Keyword $keyword) : string
99
    {
100
        switch($keyword->getName())
101
        {
102
            case 'and':
103
                return '&&';
104
                
105
            case 'or':
106
                return '||';
107
        }
108
        
109
        throw new Mailcode_Exception(
110
            'Unknown keyword name',
111
            sprintf(
112
                'The keyword name [%s] is not known and cannot be translated to a velocity sign.',
113
                $keyword->getName()
114
            ),
115
            self::ERROR_CANNOT_GET_KEYWORD_SIGN
116
        );
117
    }
118
119
    protected function _translateNumberComparison(Mailcode_Variables_Variable $variable, float $value, string $comparator) : string
120
    {
121
        return sprintf(
122
            '%1$s %2$s %3$s',
123
            $this->renderStringToNumber($variable->getFullName()),
124
            $comparator,
125
            $value
126
        );
127
    }
128
129
    protected function _translateEmpty(Mailcode_Variables_Variable $variable, bool $notEmpty) : string
130
    {
131
        $sign = '';
132
        
133
        if($notEmpty)
134
        {
135
            $sign = '!';
136
        }
137
        
138
        return sprintf(
139
            '%s$StringUtils.isEmpty(%s)',
140
            $sign,
141
            $variable->getFullName()
142
        );
143
    }
144
    
145
    protected function _translateGeneric(Mailcode_Commands_IfBase $command) : string
146
    {
147
        $params = $command->getParams();
148
149
        if(!$params)
150
        {
151
            return '';
152
        }
153
154
        if($command->hasFreeformParameters())
155
        {
156
            return $params->getStatementString();
157
        }
158
159
        return $params->getNormalized();
160
    }
161
    
162
    protected function _translateVariable(Mailcode_Variables_Variable $variable, string $comparator, string $value, bool $insensitive=false) : string
163
    {
164
        $booleanCheck = strtolower(trim($value, '"'));
165
        $fullName = $variable->getFullName();
166
167
        if(in_array($booleanCheck, array('true', 'false')))
168
        {
169
            $insensitive = true;
170
            $value = '"'.$booleanCheck.'"';
171
        }
172
173
        if($insensitive)
174
        {
175
            $fullName .= '.toLowerCase()';
176
            $value = mb_strtolower($value);
177
        }
178
179
        return sprintf(
180
            '%s %s %s',
181
            $fullName,
182
            $comparator,
183
            $value
184
        );
185
    }
186
187
    /**
188
     * @param Mailcode_Variables_Variable $variable
189
     * @param bool $caseSensitive
190
     * @param bool $regexEnabled
191
     * @param Mailcode_Parser_Statement_Tokenizer_Token_StringLiteral[] $searchTerms
192
     * @param string $containsType
193
     * @return string
194
     * @throws Mailcode_Exception
195
     */
196
    protected function _translateContains(Mailcode_Variables_Variable $variable, bool $caseSensitive, bool $regexEnabled, array $searchTerms, string $containsType) : string
197
    {
198
        $builder = new ContainsStatementBuilder($this, $variable, $caseSensitive, $regexEnabled, $searchTerms, $containsType);
199
        return $builder->render();
200
    }
201
202
    protected function _translateSearch(string $mode, Mailcode_Variables_Variable $variable, bool $caseSensitive, string $searchTerm) : string
203
    {
204
        $method = $mode.'With';
205
        if($caseSensitive)
206
        {
207
            $method = $mode.'WithIgnoreCase';
208
        }
209
        
210
        return sprintf(
211
            '$StringUtils.%s(%s, "%s")',
212
            $method,
213
            $variable->getFullName(),
214
            trim($searchTerm, '"')
215
        );
216
    }
217
}
218