FbpDumper   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 198
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 73.32%

Importance

Changes 0
Metric Value
wmc 26
lcom 1
cbo 2
dl 0
loc 198
ccs 66
cts 90
cp 0.7332
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A toJson() 0 4 1
A toYaml() 0 4 1
A toFbp() 0 4 1
F createFbp() 0 49 11
A examineConnectionTouple() 0 10 1
B examineProcess() 0 24 3
A hasElement() 0 15 3
A connectPorts() 0 10 1
A throwDumperException() 0 16 4
1
<?php
2
/*
3
 * This file is part of the phpflo\phpflo-fbp package.
4
 *
5
 * (c) Marc Aschmann <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
declare(strict_types=1);
11
namespace PhpFlo\Fbp;
12
13
use PhpFlo\Common\FbpDefinitionsInterface;
14
use PhpFlo\Exception\DumperException;
15
use Symfony\Component\Yaml\Yaml;
16
17
/**
18
 * Class FbpDumper
19
 *
20
 * @package PhpFlo\Fbp
21
 * @author Marc Aschmann <[email protected]>
22
 */
23
final class FbpDumper implements FbpDefinitionsInterface
24
{
25
    /**
26
     * @var array
27
     */
28
    private static $processes;
29
30
    /**
31
     * @param array $definition
32
     * @return string json
33
     */
34 2
    public static function toJson(array $definition) : string
35
    {
36 2
        return json_encode($definition, JSON_PRETTY_PRINT);
37
    }
38
39
    /**
40
     * @param array $definition
41
     * @param int $inline level until inlining starts
42
     * @return string yaml
43
     */
44 2
    public static function toYaml(array $definition, int $inline = 3) : string
45
    {
46 2
        return Yaml::dump($definition, $inline);
47
    }
48
49
    /**
50
     * @param array $definition
51
     * @return string
52
     */
53 1
    public static function toFbp(array $definition) : string
54
    {
55 1
        return self::createFbp($definition);
56
    }
57
58
    /**
59
     * @param array $definition
60
     * @return string
61
     * @throws DumperException
62 2
     */
63
    private static function createFbp(array $definition) : string
64 2
    {
65
        $fbp = [];
66
67
        try {
68 2
69 2
            if (self::hasElement(self::PROPERTIES_LABEL, $definition)) {
70 2
                foreach($definition[self::PROPERTIES_LABEL] as $name => $element) {
71 1
                    if (!empty($element)) {
72 1
                        $fbp[] = '# ' . (string)$element;
73 2
                    }
74 2
                }
75
            }
76
77 2
            // first check for process definitions
78 2
            if (self::hasElement(self::PROCESSES_LABEL, $definition)) {
79 2
                self::$processes = $definition[self::PROCESSES_LABEL];
80
            }
81
82 2
            // handle initializer
83 1
            if (!empty($definition[self::INITIALIZERS_LABEL])) {
84 1
                foreach ($definition[self::INITIALIZERS_LABEL] as $initializer) {
85
                    if (empty($initializer[self::DATA_LABEL])) {
86
                        self::throwDumperException('no_definition', self::DATA_LABEL);
87 1
                    }
88
                    if (empty($initializer[self::TARGET_LABEL])) {
89
                        self::throwDumperException('no_definition', self::TARGET_LABEL);
90 1
                    }
91 1
                    array_push(
92 1
                        $fbp,
93 1
                        self::connectPorts(
94 1
                            $initializer[self::DATA_LABEL],
95 1
                            self::examineProcess(self::TARGET_LABEL, $initializer[self::TARGET_LABEL])
96 1
                        )
97 1
                    );
98 1
                }
99
            }
100 2
101 2
            foreach ($definition[self::CONNECTIONS_LABEL] as $connection) {
102 2
                array_push($fbp, self::examineConnectionTouple($connection));
103
            }
104 2
105
            return implode(self::FILE_LINEFEED, $fbp);
106
        } catch (\Exception $e) {
107
            throw new DumperException(
108
                "Unexpected dumper error \"{$e->getMessage()}\" in {$e->getFile()} on Line {$e->getLine()}"
109
            );
110
        }
111
    }
112
113
    /**
114
     * Look for all needed fields and build a port -> port connection.
115
     *
116
     * @param array $connectionTouple
117
     * @return string
118 1
     */
119
    private static function examineConnectionTouple(array $connectionTouple) : string
120 1
    {
121 1
        self::hasElement(self::SOURCE_LABEL, $connectionTouple);
122
        self::hasElement(self::TARGET_LABEL, $connectionTouple);
123 1
124 1
        return self::connectPorts(
125 1
            self::examineProcess(self::SOURCE_LABEL, $connectionTouple[self::SOURCE_LABEL]),
126 1
            self::examineProcess(self::TARGET_LABEL, $connectionTouple[self::TARGET_LABEL])
127
        );
128
    }
129
130
    /**
131
     * @param string $type
132
     * @param array $processPart
133
     * @throws DumperException
134
     * @return string
135 2
     */
136
    private static function examineProcess(string $type, array $processPart) : string
137 2
    {
138 2
        self::hasElement(self::PROCESS_LABEL, $processPart);
139
        self::hasElement(self::PORT_LABEL, $processPart);
140 2
141 2
        $inport = '';
142 2
        $outport = '';
143 2
        $process = $processPart[self::PROCESS_LABEL];
144
        $port = $processPart[self::PORT_LABEL];
145 2
146 2
        if (self::hasElement($process, self::$processes, false)) {
147 2
            $meta = "(" . self::$processes[$process][self::COMPONENT_LABEL] . ")";
148
        } else {
149
            self::throwDumperException('process', $process);
150
        }
151 2
152 2
        if (self::SOURCE_LABEL == $type) {
153 2
            $outport = " {$port}";
154 2
        } else {
155
            $inport = "{$port} ";
156
        }
157 2
158
        return "{$inport}{$process}{$meta}{$outport}";
159
    }
160
161
    /**
162
     * @param string $needle
163
     * @param array $haystack
164
     * @param bool $triggerException
165
     * @return bool
166 2
     */
167
    private static function hasElement(
168 2
        string $needle,
169
        array $haystack,
170
        bool $triggerException = true
171
    ) : bool {
172
        if (empty($haystack[$needle])) {
173
            if ($triggerException) {
174
                self::throwDumperException('elmeent', $needle);
175
            } else {
176 2
                return false;
177
            }
178
        }
179
180
        return true;
181
    }
182
183
    /**
184 1
     * @param string $sourcePort
185
     * @param string $targetPort
186 1
     * @return string
187 1
     */
188
    private static function connectPorts(string $sourcePort, string $targetPort) : string
189 1
    {
190
        return implode(
191 1
            " " . self::SOURCE_TARGET_SEPARATOR . " ",
192 1
            [
193
                $sourcePort,
194
                $targetPort
195
            ]
196
        );
197
    }
198
199
    /**
200
     * @param string $type
201
     * @param string $value
202
     * @throws DumperException
203
     */
204
    private static function throwDumperException(string $type, string $value)
205
    {
206
        switch ($type) {
207
            case 'element':
208
                throw new DumperException("Element has no {$value}");
209
                break;
210
            case 'process':
211
                throw new DumperException("{$value} is not defined in " . self::PROCESSES_LABEL);
212
                break;
213
            case 'no_definition':
214
                throw new DumperException("Defintion has " .
215
                    self::INITIALIZERS_LABEL . " but no {$value} node"
216
                );
217
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
218
        }
219
    }
220
}
221