Completed
Pull Request — master (#1)
by Julien
03:42
created

Utils::parsePayload()   D

Complexity

Conditions 12
Paths 111

Size

Total Lines 79
Code Lines 53

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 53
nc 111
nop 2
dl 0
loc 79
rs 4.9151
c 0
b 0
f 0

How to fix   Long Method    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
namespace TheAentMachine\AentDockerCompose\Command;
4
5
use Symfony\Component\Console\Output\OutputInterface;
6
use Symfony\Component\Process\Process;
7
8
class Utils
9
{
10
    /**
11
     * Delete all key/value pairs with empty value by recursively using array_filter
12
     * @param array $input
13
     * @return mixed[] array
14
     */
15
    public static function arrayFilterRec(array $input): array
16
    {
17
        foreach ($input as &$value) {
18
            if (is_array($value)) {
19
                $value = Utils::arrayFilterRec($value);
20
            }
21
        }
22
        return array_filter($input);
23
    }
24
25
    /**
26
     * @param string $payload
27
     * @return mixed[] array
28
     */
29
    public static function parsePayload(string $payload, OutputInterface $output): array
30
    {
31
        $p = json_decode($payload, true);
32
        if (!$p) {
33
            $output->writeln("   ⨯ payload error: invalid payload");
34
            exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return array. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
35
        }
36
37
        $serviceName = $p[Cst::SERVICE_NAME_KEY] ?? "";
38
        if (empty($serviceName)) {
39
            $output->writeln("   ⨯ payload error: empty " . Cst::SERVICE_NAME_KEY);
40
            exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
41
        }
42
43
        $service = $p['service'] ?? array();
44
        if (!empty($service)) {
45
            $image = $service['image'] ?? "";
46
            $dependsOn = $service['dependsOn'] ?? "";
47
48
            $ports = array();
49
            foreach ($service['ports'] ?? array() as $port) {
50
                $str = sprintf("%d:%d", $port['source'], $port['target']);
51
                $ports[] = $str;
52
            }
53
            $labels = array();
54
            foreach ($service['labels'] ?? array() as $label) {
55
                $str = $label['value'] ? sprintf("%s=%s", $label['key'], $label['value']) : $label['key'];
56
                $labels[] = $str;
57
            }
58
            $environments = array();
59
            foreach ($service['environments'] ?? array() as $env) {
60
                $str = $env['value'] ? sprintf("%s=%s", $env['key'], $env['value']) : $env['key'];
61
                $environments[] = $str;
62
            }
63
64
            $volumes = $p['volumes'] ?? array();
65
            $namedVolumes = array();
66
            foreach ($service['volumes'] ?? array() as $volume) {
67
                $type = $volume['type'] ?? "";
68
                $source = $volume['source'] ?? "";
69
70
                $formattedVolume = array(
71
                    "type" => $type,
72
                    "source" => $source,
73
                    "target" => $volume['target'] ?? "",
74
                    "read_only" => $volume['readOnly'] ?? "",
75
                );
76
                $volumes[] = $formattedVolume;
77
78
                // case it's a named volume
79
                if ($type === "volume") {
80
                    // for now we just add them without any option
81
                    $namedVolumes[$source] = null;
82
                }
83
            }
84
85
            $formattedPayload = array(
86
                "services" => Utils::arrayFilterRec(array(
87
                    $serviceName => array(
88
                        "image" => $image,
89
                        "depends_on" => $dependsOn,
90
                        "ports" => $ports,
91
                        "labels" => $labels,
92
                        "environments" => $environments,
93
                        "volumes" => $volumes,
94
                    ),
95
                )),
96
            );
97
            if (!empty($namedVolumes)) {
98
                $formattedPayload['volumes'] = $namedVolumes;
99
            }
100
101
            return $formattedPayload;
102
        } else {
103
            $output->writeln("  ⨯ payload error: empty " . Cst::SERVICE_KEY);
104
            exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
105
        }
106
107
        exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
Unused Code introduced by
ExitNode is not 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...
108
    }
109
110
    /**
111
     * Run a process and return the exit code
112
     * @param mixed $cmd command line in a single string or an array of strings
113
     * @param OutputInterface $output
114
     * @return Process
115
     */
116
    public static function runAndGetProcess($cmd, OutputInterface $output): Process
117
    {
118
        if (!is_array($cmd)) {
119
            $cmd = explode(' ', $cmd);
120
        }
121
122
        $process = new Process($cmd);
123
124
        $process->start();
125
        foreach ($process as $type => $buffer) {
126
            $output->write($buffer);
127
        }
128
129
        return $process;
130
    }
131
}
132