Passed
Push — master ( 7426d3...01dce1 )
by Marc
02:49
created

FbpDumper   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 181
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 71.08%

Importance

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