Completed
Pull Request — master (#470)
by Claus
01:35
created

CastViewHelper::convertToArray()   B

Complexity

Conditions 10
Paths 7

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
nc 7
nop 1
dl 0
loc 20
rs 7.6666
c 0
b 0
f 0

How to fix   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
declare(strict_types=1);
3
namespace TYPO3Fluid\Fluid\ViewHelpers\Expression;
4
5
/*
6
 * This file belongs to the package "TYPO3 Fluid".
7
 * See LICENSE.txt that was shipped with this package.
8
 */
9
10
use TYPO3Fluid\Fluid\Component\ExpressionComponentInterface;
11
use TYPO3Fluid\Fluid\Core\Parser\ExpressionException;
12
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
13
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
14
15
/**
16
 * Math Expression ViewHelper, seconds as expression type
17
 */
18
class CastViewHelper extends AbstractViewHelper implements ExpressionComponentInterface
19
{
20
    protected $parts = [];
21
22
    protected static $validTypes = [
23
        'integer', 'boolean', 'string', 'float', 'array', \DateTime::class
24
    ];
25
26
    public function __construct(iterable $parts = [])
27
    {
28
        $this->parts = $parts;
29
    }
30
31
    protected function initializeArguments()
32
    {
33
        $this->registerArgument('subject', 'mixed', 'Numeric first value to calculate', true);
34
        $this->registerArgument('as', 'string', 'Type to cast, valid values are: integer, boolean, string, float and array', true);
35
    }
36
37
    public function evaluate(RenderingContextInterface $renderingContext)
38
    {
39
        $arguments = $this->getArguments()->setRenderingContext($renderingContext)->getArrayCopy();
40
        if (!empty($this->parts)) {
41
            $parts = $this->parts;
42
        } else {
43
            $parts = [$arguments['subject'], 'as', $arguments['as']];
44
        }
45
        return $this->evaluateParts($renderingContext, $parts);
46
    }
47
48
    protected function evaluateParts(RenderingContextInterface $renderingContext, iterable $parts)
49
    {
50
        $subject = $parts[0];
51
        if (is_string($subject)) {
52
            $subject = $renderingContext->getVariableProvider()->get($subject) ?? $subject;
53
        }
54
        return static::convert($subject, $parts[2]);
55
    }
56
57
    /**
58
     * Requires exactly three parts: X as Y. Match a size of 3 parts
59
     * and verify the middle part is string "as".
60
     *
61
     * @param array $parts
62
     * @return bool
63
     */
64
    public static function matches(array $parts): bool
65
    {
66
        $valid = !isset($parts[3]) && ($parts[1] ?? null) === 'as';
67
        if ($valid && !in_array($parts[2], self::$validTypes, true)) {
68
            throw new ExpressionException(
69
                sprintf(
70
                    'Invalid target conversion type "%s" specified in casting expression "{%s}".',
71
                    $parts[2],
72
                    implode(' ', $parts)
73
                ),
74
                1559248372
75
            );
76
        }
77
        return $valid;
78
    }
79
80
    /**
81
     * @param mixed $variable
82
     * @param string $type
83
     * @return mixed
84
     */
85
    protected static function convert($variable, string $type)
86
    {
87
        $value = null;
88
        if ($type === 'integer') {
89
            $value = (integer) $variable;
90
        } elseif ($type === 'boolean') {
91
            $value = (boolean) $variable;
92
        } elseif ($type === 'string') {
93
            $value = (string) $variable;
94
        } elseif ($type === 'float') {
95
            $value = (float) $variable;
96
        } elseif ($type === \DateTime::class) {
97
            $value = self::convertToDateTime($variable);
98
        } elseif ($type === 'array') {
99
            $value = (array) self::convertToArray($variable);
100
        }
101
        return $value;
102
    }
103
104
    /**
105
     * @param mixed $variable
106
     * @return \DateTime|false
107
     */
108
    protected static function convertToDateTime($variable)
109
    {
110
        if (!is_numeric($variable)) {
111
            return new \DateTime($variable);
112
        }
113
        return \DateTime::createFromFormat('U', (string) $variable);
114
    }
115
116
    protected static function convertToArray($variable): array
117
    {
118
        if (is_array($variable)) {
119
            return $variable;
120
        } elseif (is_string($variable) && strpos($variable, ',')) {
121
            return array_map('trim', explode(',', $variable));
122
        } elseif (is_object($variable) && $variable instanceof \Iterator) {
123
            $array = [];
124
            foreach ($variable as $key => $value) {
125
                $array[$key] = $value;
126
            }
127
            return $array;
128
        } elseif (is_object($variable) && method_exists($variable, 'toArray')) {
129
            return $variable->toArray();
130
        } elseif (is_bool($variable)) {
131
            return [];
132
        } else {
133
            return [$variable];
134
        }
135
    }
136
}
137