Completed
Pull Request — master (#1)
by Dorian
02:14
created

Kernel::getRootPathPart()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 5
nc 1
nop 1
1
<?php declare(strict_types=1);
2
3
namespace App;
4
5
use App\Domain\Content;
6
use App\Domain\PathPart;
7
use App\UI\UserInterface;
8
use Symfony\Component\Filesystem\Filesystem;
9
use Symfony\Component\Yaml\Yaml;
10
11
final class Kernel
12
{
13
    public const DEFAULT_CONFIG = 'config/app.yml';
14
15
    /**
16
     * @param string $configFilePath
17
     * @param \App\UI\UserInterface $ui
18
     *
19
     * @throws \RuntimeException
20
     * @throws \Symfony\Component\Filesystem\Exception\IOException
21
     * @throws \Symfony\Component\Yaml\Exception\ParseException
22
     */
23
    public function __invoke($configFilePath, UserInterface $ui): void
24
    {
25
        $config = (array) Yaml::parseFile($this->getConfigAbsoluteFilePath($configFilePath));
26
        $rootPathPart = $this->getRootPathPart($config['path_part'] ?? []);
27
28
        foreach ((array) $config['sources'] as $sources) {
29
            foreach ((array) $sources as $sourceClassName => $sourceData) {
30
31
                /** @var \App\Domain\Source $source */
32
                $source = new $sourceClassName($ui, $sourceData['config'] ?? []);
33
34
                // Add the root path part to the contents' path
35
                $contents = $source->getContents()
36
                    ->map(function (Content $content) use ($rootPathPart) {
37
                        $content->getPath()->add($rootPathPart);
38
39
                        return $content;
40
                    });
41
42
                foreach ((array) $sourceData['downloaders'] as $downloaders) {
43
                    foreach ((array) $downloaders as $downloaderClassName => $downloaderData) {
44
45
                        /** @var \App\Domain\Downloader $downloader */
46
                        $downloader = new $downloaderClassName($ui, $downloaderData['config'] ?? []);
47
                        $downloader->synchronizeContents($contents, $rootPathPart);
1 ignored issue
show
Bug introduced by
It seems like $contents defined by $source->getContents()->... return $content; }) on line 35 can also be of type array<integer,object<App\Domain\Content>>; however, App\Domain\Downloader::synchronizeContents() does only seem to accept object<App\Domain\Contents>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
48
                    }
49
                }
50
            }
51
        }
52
    }
53
54
    /**
55
     * @return string
56
     *
57
     * @throws \RuntimeException
58
     */
59
    private function getProjectDir(): string
60
    {
61
        if (!($projectRoot = getenv('PROJECT_ROOT'))) {
62
            throw new \RuntimeException('The environment variable "PROJECT_ROOT" has not been defined.');
63
        }
64
65
        return rtrim($projectRoot, DIRECTORY_SEPARATOR);
66
    }
67
68
    /**
69
     * @param array $config
70
     *
71
     * @return \App\Domain\PathPart
72
     *
73
     * @throws \RuntimeException
74
     * @throws \Symfony\Component\Filesystem\Exception\IOException
75
     */
76
    private function getRootPathPart(array $config): PathPart
77
    {
78
        $config['substitutions'] = ['%project_root%' => $this->getProjectDir()] + ($config['substitutions'] ?? []);
79
        $rootPathPart = new PathPart($config);
80
81
        // Try to create the root directory... 'cause if it fails, nothing will work.
82
        (new Filesystem())->mkdir($rootPathPart->getPath());
83
84
        return $rootPathPart;
85
    }
86
87
    /**
88
     * @param string $configFilePath
89
     *
90
     * @return string
91
     * @throws \RuntimeException
92
     */
93
    private function getConfigAbsoluteFilePath(string $configFilePath): string
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
94
    {
95
        if (DIRECTORY_SEPARATOR === $configFilePath{0}) {
96
            return $configFilePath;
97
        }
98
99
        return $this->getProjectDir().DIRECTORY_SEPARATOR.$configFilePath;
100
    }
101
}
102