Passed
Push — master ( 01dce1...1829db )
by Marc
02:13
created

FbpDumper::createFbp()   F

Complexity

Conditions 11
Paths 281

Size

Total Lines 49
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 12.2227

Importance

Changes 0
Metric Value
dl 0
loc 49
ccs 29
cts 37
cp 0.7838
rs 3.8181
c 0
b 0
f 0
cc 11
eloc 26
nc 281
nop 1
crap 12.2227

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
/*
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
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)
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, $inline = 3)
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)
54
    {
55 1
        return self::createFbp($definition);
56
    }
57
58
    /**
59
     * @param array $definition
60
     * @return string
61
     */
62 2
    private static function createFbp(array $definition)
63
    {
64 2
        $fbp = [];
65
66
        try {
67
68 2
            if (self::hasElement(self::PROPERTIES_LABEL, $definition)) {
69 2
                foreach($definition[self::PROPERTIES_LABEL] as $name => $element) {
70 2
                    if (!empty($element)) {
71 1
                        $fbp[] = '# ' . (string)$element;
72 1
                    }
73 2
                }
74 2
            }
75
76
            // first check for process definitions
77 2
            if (self::hasElement(self::PROCESSES_LABEL, $definition)) {
78 2
                self::$processes = $definition[self::PROCESSES_LABEL];
79 2
            }
80
81
            // handle initializer
82 2
            if (!empty($definition[self::INITIALIZERS_LABEL])) {
83 1
                foreach ($definition[self::INITIALIZERS_LABEL] as $initializer) {
84 1
                    if (empty($initializer[self::DATA_LABEL])) {
85
                        self::throwDumperException('no_definition', self::DATA_LABEL);
86
                    }
87 1
                    if (empty($initializer[self::TARGET_LABEL])) {
88
                        self::throwDumperException('no_definition', self::TARGET_LABEL);
89
                    }
90 1
                    array_push(
91 1
                        $fbp,
92 1
                        self::connectPorts(
93 1
                            $initializer[self::DATA_LABEL],
94 1
                            self::examineProcess(self::TARGET_LABEL, $initializer[self::TARGET_LABEL])
95 1
                        )
96 1
                    );
97 1
                }
98 1
            }
99
100 2
            foreach ($definition[self::CONNECTIONS_LABEL] as $connection) {
101 2
                array_push($fbp, self::examineConnectionTouple($connection));
102 2
            }
103
104 2
            return implode(self::FILE_LINEFEED, $fbp);
105
        } catch (\Exception $e) {
106
            throw new DumperException(
107
                "Unexpected dumper error \"{$e->getMessage()}\" in {$e->getFile()} on Line {$e->getLine()}"
108
            );
109
        }
110
    }
111
112
    /**
113
     * Look for all needed fields and build a port -> port connection.
114
     *
115
     * @param array $connectionTouple
116
     * @return string
117
     */
118 1
    private static function examineConnectionTouple(array $connectionTouple)
119
    {
120 1
        self::hasElement(self::SOURCE_LABEL, $connectionTouple);
121 1
        self::hasElement(self::TARGET_LABEL, $connectionTouple);
122
123 1
        return self::connectPorts(
124 1
            self::examineProcess(self::SOURCE_LABEL, $connectionTouple[self::SOURCE_LABEL]),
125 1
            self::examineProcess(self::TARGET_LABEL, $connectionTouple[self::TARGET_LABEL])
126 1
        );
127
    }
128
129
    /**
130
     * @param string $type
131
     * @param array $processPart
132
     * @throws DumperException
133
     * @return string
134
     */
135 2
    private static function examineProcess($type, array $processPart)
136
    {
137 2
        self::hasElement(self::PROCESS_LABEL, $processPart);
138 2
        self::hasElement(self::PORT_LABEL, $processPart);
139
140 2
        $inport = '';
141 2
        $outport = '';
142 2
        $process = $processPart[self::PROCESS_LABEL];
143 2
        $port = $processPart[self::PORT_LABEL];
144
145 2
        if (self::hasElement($process, self::$processes, false)) {
146 2
            $meta = "(" . self::$processes[$process][self::COMPONENT_LABEL] . ")";
147 2
        } else {
148
            self::throwDumperException('process', $process);
149
        }
150
151 2
        if (self::SOURCE_LABEL == $type) {
152 2
            $outport = " {$port}";
153 2
        } else {
154 2
            $inport = "{$port} ";
155
        }
156
157 2
        return "{$inport}{$process}{$meta}{$outport}";
158
    }
159
160
    /**
161
     * @param string $needle
162
     * @param array $haystack
163
     * @param bool $triggerException
164
     * @return bool
165
     */
166 2
    private static function hasElement($needle, array $haystack, $triggerException = true)
167
    {
168 2
        if (empty($haystack[$needle])) {
169
            if ($triggerException) {
170
                self::throwDumperException('elmeent', $needle);
171
            } else {
172
                return false;
173
            }
174
        }
175
176 2
        return true;
177
    }
178
179
    /**
180
     * @param string $sourcePort
181
     * @param string $targetPort
182
     * @return string
183
     */
184 1
    private static function connectPorts($sourcePort, $targetPort)
185
    {
186 1
        return implode(
187 1
            " " . self::SOURCE_TARGET_SEPARATOR . " ",
188
            [
189 1
                $sourcePort,
190
                $targetPort
191 1
            ]
192 1
        );
193
    }
194
195
    private static function throwDumperException($type, $value)
196
    {
197
        switch ($type) {
198
            case 'element':
199
                throw new DumperException("Element has no {$value}");
200
                break;
201
            case 'process':
202
                throw new DumperException("{$value} is not defined in " . self::PROCESSES_LABEL);
203
                break;
204
            case 'no_definition':
205
                throw new DumperException("Defintion has " .
206
                    self::INITIALIZERS_LABEL . " but no {$value} node"
207
                );
208
                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...
209
        }
210
    }
211
}
212