ContentParser   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 75
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 37
dl 0
loc 75
rs 10
c 2
b 0
f 0
wmc 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A parse() 0 24 5
A __construct() 0 4 1
A getFunctionArguments() 0 17 3
A callFunction() 0 16 1
1
<?php
2
3
/*
4
 * This file was created by developers working at BitBag
5
 * Do you need more information about us and what we do? Visit our https://bitbag.io website!
6
 * We are hiring developers from all over the world. Join us and start your new, exciting adventure and become part of us: https://bitbag.io/career
7
*/
8
9
declare(strict_types=1);
10
11
namespace BitBag\SyliusCmsPlugin\Twig\Parser;
12
13
use Webmozart\Assert\Assert;
14
15
final class ContentParser implements ContentParserInterface
16
{
17
    /** @var \Twig_Environment */
18
    private $twigEnvironment;
19
20
    /** @var array */
21
    private $enabledFunctions;
22
23
    public function __construct(\Twig_Environment $twigEnvironment, array $enabledFunctions)
24
    {
25
        $this->twigEnvironment = $twigEnvironment;
26
        $this->enabledFunctions = $enabledFunctions;
27
    }
28
29
    public function parse(string $input): string
30
    {
31
        $functions = $this->twigEnvironment->getFunctions();
32
33
        preg_match_all('`{{\s*(?P<method>[^\(]+)\s*\((?P<arguments>[^\)]*)\)\s*}}`', $input, $callMatches);
34
35
        foreach ($callMatches[0] as $index => $call) {
36
            $function = $callMatches['method'][$index];
37
            if (!in_array($function, $this->enabledFunctions, true)) {
38
                continue;
39
            }
40
41
            if (null !== $arguments = $this->getFunctionArguments($function, $call)) {
42
                try {
43
                    $functionResult = $this->callFunction($functions, $function, $arguments);
44
                } catch (\Exception $exception) {
45
                    $functionResult = '';
46
                }
47
48
                $input = str_replace($call, $functionResult, $input);
49
            }
50
        }
51
52
        return $input;
53
    }
54
55
    private function getFunctionArguments(string $functionName, string $input): ?array
56
    {
57
        $start = '{{ ' . $functionName . '(';
58
        $end = ') }}';
59
        /** @var string[]|false $functionParts */
60
        $functionParts = explode($start, $input);
61
62
        if (false !== $functionParts && isset($functionParts[1])) {
63
            $functionParts = explode($end, $functionParts[1]);
64
            $arguments = explode(',', $functionParts[0]);
65
66
            return array_map(function (string $element): string {
67
                return trim(trim($element), '\'');
68
            }, $arguments);
69
        }
70
71
        return null;
72
    }
73
74
    private function callFunction(
75
        array $functions,
76
        string $functionName,
77
        array $arguments
78
    ): string {
79
        Assert::keyExists($functions, $functionName, sprintf('Function %s does not exist!', $functionName));
80
        /** @var \Twig_Function $function */
81
        $function = $functions[$functionName];
82
        $callable = $function->getCallable();
83
        Assert::isArray($callable, sprintf('Function with name "%s" is not callable', $functionName));
84
        $extension = $callable[0];
85
        $extensionMethod = $callable[1];
86
        $callback = [$extension, $extensionMethod];
87
        Assert::isCallable($callback);
88
89
        return call_user_func_array($callback, $arguments);
90
    }
91
}
92