Completed
Pull Request — master (#1121)
by Rafał
11:09
created

TenantAwareThemeLoader::initializeThemes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Superdesk Web Publisher Core Bundle.
5
 *
6
 * Copyright 2016 Sourcefabric z.u. and contributors.
7
 *
8
 * For the full copyright and license information, please see the
9
 * AUTHORS and LICENSE files distributed with this source code.
10
 *
11
 * @copyright 2016 Sourcefabric z.ú
12
 * @license http://www.superdesk.org/license
13
 */
14
15
namespace SWP\Bundle\CoreBundle\Theme\Loader;
16
17
use Sylius\Bundle\ThemeBundle\Configuration\ConfigurationProviderInterface;
18
use Sylius\Bundle\ThemeBundle\Factory\ThemeAuthorFactoryInterface;
19
use Sylius\Bundle\ThemeBundle\Factory\ThemeFactoryInterface;
20
use Sylius\Bundle\ThemeBundle\Factory\ThemeScreenshotFactoryInterface;
21
use Sylius\Bundle\ThemeBundle\Loader\CircularDependencyCheckerInterface;
22
use Sylius\Bundle\ThemeBundle\Loader\CircularDependencyFoundException;
23
use Sylius\Bundle\ThemeBundle\Loader\ThemeLoaderInterface;
24
use Sylius\Bundle\ThemeBundle\Loader\ThemeLoadingFailedException;
25
use Sylius\Bundle\ThemeBundle\Model\ThemeInterface;
26
27
/**
28
 * @author Kamil Kokot <[email protected]>
29
 * @author Paweł Mikołajczuk <[email protected]>
30
 */
31
final class TenantAwareThemeLoader implements ThemeLoaderInterface
32
{
33
    /**
34
     * @var ConfigurationProviderInterface
35
     */
36
    private $configurationProvider;
37
38
    /**
39
     * @var ThemeFactoryInterface
40
     */
41
    private $themeFactory;
42
43
    /**
44
     * @var ThemeAuthorFactoryInterface
45
     */
46
    private $themeAuthorFactory;
47
48
    /**
49
     * @var ThemeScreenshotFactoryInterface
50
     */
51
    private $themeScreenshotFactory;
52
53
    /**
54
     * @var CircularDependencyCheckerInterface
55
     */
56
    private $circularDependencyChecker;
57
58
    /**
59
     * @param ConfigurationProviderInterface     $configurationProvider
60
     * @param ThemeFactoryInterface              $themeFactory
61
     * @param ThemeAuthorFactoryInterface        $themeAuthorFactory
62
     * @param ThemeScreenshotFactoryInterface    $themeScreenshotFactory
63
     * @param CircularDependencyCheckerInterface $circularDependencyChecker
64
     */
65
    public function __construct(
66
        ConfigurationProviderInterface $configurationProvider,
67
        ThemeFactoryInterface $themeFactory,
68
        ThemeAuthorFactoryInterface $themeAuthorFactory,
69
        ThemeScreenshotFactoryInterface $themeScreenshotFactory,
70
        CircularDependencyCheckerInterface $circularDependencyChecker
71
    ) {
72
        $this->configurationProvider = $configurationProvider;
73
        $this->themeFactory = $themeFactory;
74
        $this->themeAuthorFactory = $themeAuthorFactory;
75
        $this->themeScreenshotFactory = $themeScreenshotFactory;
76
        $this->circularDependencyChecker = $circularDependencyChecker;
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82
    public function load(): array
83
    {
84
        $configurations = $this->configurationProvider->getConfigurations();
85
86
        $themes = $this->hydrateThemes($configurations);
87
88
        $this->checkForCircularDependencies($themes);
89
90
        return array_values($themes);
91
    }
92
93
    private function hydrateThemes(array $configurations): array
94
    {
95
        $themes = [];
96
97
        foreach ($configurations as $configuration) {
98
            $themes[$configuration['name']] = $this->themeFactory->create($configuration['name'], $configuration['path']);
99
        }
100
101
        foreach ($configurations as $configuration) {
102
            $theme = $themes[$configuration['name']];
103
104
            $theme->setTitle($configuration['title'] ?? null);
105
            $theme->setDescription($configuration['description'] ?? null);
106
107
            $parentThemes = $this->convertParentsNamesToParentsObjects($configuration['name'], $configuration['parents'], $themes);
108
            foreach ($parentThemes as $parentTheme) {
109
                $theme->addParent($parentTheme);
110
            }
111
112
            $themeAuthors = $this->convertAuthorsArraysToAuthorsObjects($configuration['authors']);
113
            foreach ($themeAuthors as $themeAuthor) {
114
                $theme->addAuthor($themeAuthor);
115
            }
116
117
            $themeScreenshots = $this->convertScreenshotsArraysToScreenshotsObjects($configuration['screenshots']);
118
            foreach ($themeScreenshots as $themeScreenshot) {
119
                $theme->addScreenshot($themeScreenshot);
120
            }
121
        }
122
123
        return $themes;
124
    }
125
126
    /**
127
     * @param ThemeInterface[] $themes
128
     */
129
    private function checkForCircularDependencies(array $themes): void
130
    {
131
        try {
132
            foreach ($themes as $theme) {
133
                $this->circularDependencyChecker->check($theme);
134
            }
135
        } catch (CircularDependencyFoundException $exception) {
136
            throw new ThemeLoadingFailedException('Circular dependency found.', 0, $exception);
137
        }
138
    }
139
140
    private function convertParentsNamesToParentsObjects($themeName, array $parentsNames, array $existingThemes): array
141
    {
142
        $tenantCode = substr($themeName, strpos($themeName, '@') + 1);
143
144
        return array_map(function ($parentName) use ($themeName, $existingThemes, $tenantCode) {
145
            $parentName .= '@'.$tenantCode;
146
            if (!isset($existingThemes[$parentName])) {
147
                throw new ThemeLoadingFailedException(sprintf(
148
                    'Unexisting theme "%s" is required by "%s".',
149
                    $parentName,
150
                    $themeName
151
                ));
152
            }
153
154
            return $existingThemes[$parentName];
155
        }, $parentsNames);
156
    }
157
158
    private function convertAuthorsArraysToAuthorsObjects(array $authorsArrays): array
159
    {
160
        return array_map(function (array $authorArray) {
161
            return $this->themeAuthorFactory->createFromArray($authorArray);
162
        }, $authorsArrays);
163
    }
164
165
    private function convertScreenshotsArraysToScreenshotsObjects(array $screenshotsArrays): array
166
    {
167
        return array_map(function (array $screenshotArray) {
168
            return $this->themeScreenshotFactory->createFromArray($screenshotArray);
169
        }, $screenshotsArrays);
170
    }
171
}
172