Passed
Push — master ( 536a9f...433a1b )
by Marc
02:23
created

FbpDumper::createFbp()   C

Complexity

Conditions 7
Paths 12

Size

Total Lines 38
Code Lines 20

Duplication

Lines 10
Ratio 26.32 %

Code Coverage

Tests 22
CRAP Score 7.4822

Importance

Changes 0
Metric Value
dl 10
loc 38
ccs 22
cts 28
cp 0.7856
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 20
nc 12
nop 1
crap 7.4822
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
        // first check for process definitions
67 2
        if (self::hasElement(self::PROCESSES_LABEL, $definition)) {
68 2
            self::$processes = $definition[self::PROCESSES_LABEL];
69 2
        }
70
71
        // handle initializer
72 2
        if (!empty($definition[self::INITIALIZERS_LABEL])) {
73 1
            foreach ($definition[self::INITIALIZERS_LABEL] as $initializer) {
74 1 View Code Duplication
                if (empty($initializer[self::DATA_LABEL])) {
75
                    throw new DumperException("Defintion has " .
76
                        self::INITIALIZERS_LABEL . " but no " . self::DATA_LABEL . " node"
77
                    );
78
                }
79 1 View Code Duplication
                if (empty($initializer[self::TARGET_LABEL])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
80
                    throw new DumperException("Defintion has " .
81
                        self::INITIALIZERS_LABEL . " but no " . self::TARGET_LABEL . " node"
82
                    );
83
                }
84 1
                array_push(
85 1
                    $fbp,
86 1
                    self::connectPorts(
87 1
                        $initializer[self::DATA_LABEL],
88 1
                        self::examineProcess(self::TARGET_LABEL, $initializer[self::TARGET_LABEL])
89 1
                    )
90 1
                );
91 1
            }
92 1
        }
93
94 2
        foreach ($definition[self::CONNECTIONS_LABEL] as $connection) {
95 2
            array_push($fbp, self::examineConnectionTouple($connection));
96 2
        }
97
98 2
        return implode(self::FILE_LINEFEED, $fbp);
99
    }
100
101
    /**
102
     * Look for all needed fields and build a port -> port connection.
103
     *
104
     * @param array $connectionTouple
105
     * @return string
106
     */
107 2
    private static function examineConnectionTouple(array $connectionTouple)
108
    {
109 2
        self::hasElement(self::SOURCE_LABEL, $connectionTouple);
110 2
        self::hasElement(self::TARGET_LABEL, $connectionTouple);
111
112 2
        return self::connectPorts(
113 2
            self::examineProcess(self::SOURCE_LABEL, $connectionTouple[self::SOURCE_LABEL]),
114 2
            self::examineProcess(self::TARGET_LABEL, $connectionTouple[self::TARGET_LABEL])
115 2
        );
116
    }
117
118
    /**
119
     * @param string $type
120
     * @param array $processPart
121
     * @throws DumperException
122
     * @return string
123
     */
124 2
    private static function examineProcess($type, array $processPart)
125
    {
126 2
        self::hasElement(self::PROCESS_LABEL, $processPart);
127 2
        self::hasElement(self::PORT_LABEL, $processPart);
128
129 2
        $inport = '';
130 2
        $outport = '';
131 2
        $process = $processPart[self::PROCESS_LABEL];
132 2
        $port = $processPart[self::PORT_LABEL];
133
134 2
        if (self::hasElement($process, self::$processes, false)) {
135 2
            $meta = "(" . self::$processes[$process][self::COMPONENT_LABEL] . ")";
136 2
        } else {
137
            throw new DumperException("{$process} is not defined in " . self::PROCESSES_LABEL);
138
        }
139
140 2
        if (self::SOURCE_LABEL == $type) {
141 2
            $outport = " {$port}";
142 2
        } else {
143 2
            $inport = "{$port} ";
144
        }
145
146 2
        return "{$inport}{$process}{$meta}{$outport}";
147
    }
148
149
    /**
150
     * @param string $needle
151
     * @param array $haystack
152
     * @param bool $triggerException
153
     * @return bool
154
     */
155 2
    private static function hasElement($needle, array $haystack, $triggerException = true)
156
    {
157 2
        if (empty($haystack[$needle])) {
158
            if ($triggerException) {
159
                throw new DumperException("Element has no {$needle}");
160
            } else {
161
                return false;
162
            }
163
        }
164
165 2
        return true;
166
    }
167
168
    /**
169
     * @param string $sourcePort
170
     * @param string $targetPort
171
     * @return string
172
     */
173 2
    private static function connectPorts($sourcePort, $targetPort)
174
    {
175 2
        return implode(
176 2
            " " . self::SOURCE_TARGET_SEPARATOR . " ",
177
            [
178 2
                $sourcePort,
179
                $targetPort
180 2
            ]
181 2
        );
182
    }
183
}
184