Completed
Push — master ( 9c95f5...e428dc )
by Paweł
06:06
created

SettingsManager::validateScope()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.2
c 0
b 0
f 0
cc 4
eloc 5
nc 3
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Superdesk Web Publisher Settings Bundle.
7
 *
8
 * Copyright 2017 Sourcefabric z.ú. and contributors.
9
 *
10
 * For the full copyright and license information, please see the
11
 * AUTHORS and LICENSE files distributed with this source code.
12
 *
13
 * @copyright 2017 Sourcefabric z.ú
14
 * @license http://www.superdesk.org/license
15
 */
16
17
namespace SWP\Bundle\SettingsBundle\Manager;
18
19
use Doctrine\Common\Persistence\ObjectManager;
20
use SWP\Bundle\SettingsBundle\Context\ScopeContextInterface;
21
use SWP\Bundle\SettingsBundle\Exception\InvalidOwnerException;
22
use SWP\Bundle\SettingsBundle\Exception\InvalidScopeException;
23
use SWP\Bundle\SettingsBundle\Model\SettingsInterface;
24
use SWP\Bundle\SettingsBundle\Model\SettingsOwnerInterface;
25
use SWP\Bundle\SettingsBundle\Model\SettingsRepositoryInterface;
26
use SWP\Component\Storage\Factory\FactoryInterface;
27
28
class SettingsManager implements SettingsManagerInterface
29
{
30
    /**
31
     * @var array
32
     */
33
    protected $settingsConfiguration;
34
35
    /**
36
     * @var ObjectManager
37
     */
38
    protected $em;
39
40
    /**
41
     * @var SettingsRepositoryInterface
42
     */
43
    protected $settingsRepository;
44
45
    /**
46
     * @var FactoryInterface
47
     */
48
    protected $settingsFactory;
49
50
    /**
51
     * @var ScopeContextInterface
52
     */
53
    protected $scopeContext;
54
55
    /**
56
     * SettingsManager constructor.
57
     *
58
     * @param ObjectManager               $em
59
     * @param array                       $settingsConfiguration
60
     * @param SettingsRepositoryInterface $settingsRepository
61
     * @param FactoryInterface            $settingsFactory
62
     * @param ScopeContextInterface       $scopeContext
63
     */
64
    public function __construct(
65
        ObjectManager $em,
66
        array $settingsConfiguration,
67
        SettingsRepositoryInterface $settingsRepository,
68
        FactoryInterface $settingsFactory,
69
        ScopeContextInterface $scopeContext
70
    ) {
71
        $this->em = $em;
72
        $this->settingsConfiguration = $settingsConfiguration;
73
        $this->settingsRepository = $settingsRepository;
74
        $this->settingsFactory = $settingsFactory;
75
        $this->scopeContext = $scopeContext;
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     */
81
    public function get(string $name, $scope = ScopeContextInterface::SCOPE_GLOBAL, SettingsOwnerInterface $owner = null, $default = null)
82
    {
83
        // Allow scope discovery from configuration
84
        if (null !== $scope) {
85
            $this->validateScope($scope, $owner);
86
        }
87
88
        $defaultSetting = $this->getFromConfiguration($scope, $name);
89
        /** @var SettingsInterface $setting */
90
        $setting = $this->getSettingFromRepository($name, $defaultSetting['scope'], $owner);
91
92
        if (null !== $setting) {
93
            return $this->decodeValue($defaultSetting['type'], $setting->getValue());
94
        }
95
96
        if (null !== $default) {
97
            return $default;
98
        }
99
100
        return $this->decodeValue($defaultSetting['type'], $defaultSetting['value']);
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function all()
107
    {
108
        $settings = $this->getFromConfiguration();
109
        foreach ($this->getSettingsFromRepository() as $setting) {
110
            if (array_key_exists($setting->getName(), $settings)) {
111
                $settings[$setting->getName()]['value'] = $this->decodeValue(
112
                    $settings[$setting->getName()]['type'],
113
                    $setting->getValue()
114
                );
115
            }
116
        }
117
118
        return $settings;
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124
    public function set(string $name, $value, $scope = ScopeContextInterface::SCOPE_GLOBAL, SettingsOwnerInterface $owner = null)
125
    {
126
        $this->validateScope($scope, $owner);
127
        $defaultSetting = $this->getFromConfiguration($scope, $name);
128
129
        /** @var SettingsInterface $setting */
130
        $setting = $this->getSettingFromRepository($name, $scope, $owner);
131
        if (null === $setting) {
132
            /** @var SettingsInterface $setting */
133
            $setting = $this->settingsFactory->create();
134
            $setting->setName($name);
135
            $setting->setScope($scope);
136
            if (null !== $owner) {
137
                $setting->setOwner($owner->getId());
138
            }
139
            $this->settingsRepository->persist($setting);
140
        } else {
141
            $setting->setUpdatedAt(new \DateTime());
142
        }
143
144
        $setting->setValue($this->encodeValue($defaultSetting['type'], $value));
145
        $this->settingsRepository->flush();
146
147
        return $setting;
148
    }
149
150
    /**
151
     * {@inheritdoc}
152
     */
153
    public function clear(string $name, $scope = ScopeContextInterface::SCOPE_GLOBAL, SettingsOwnerInterface $owner = null)
154
    {
155
        $this->validateScope($scope, $owner);
156
157
        $setting = $this->getSettingFromRepository($name, $scope, $owner);
158
        if (null !== $setting) {
159
            $this->settingsRepository->remove($setting);
160
161
            return true;
162
        }
163
164
        return false;
165
    }
166
167
    protected function validateScope($scope, $owner = null)
168
    {
169
        if (!in_array($scope, $this->scopeContext->getScopes())) {
170
            throw new InvalidScopeException($scope);
171
        }
172
173
        if ($scope !== ScopeContextInterface::SCOPE_GLOBAL && null === $owner) {
174
            throw new InvalidOwnerException($scope);
175
        }
176
    }
177
178
    private function getFromConfiguration(string $scope = null, $name = null)
179
    {
180
        $settings = [];
181
        if ($name !== null && array_key_exists($name, $this->settingsConfiguration)) {
182
            $setting = $this->settingsConfiguration[$name];
183
            if ($setting['scope'] === $scope || null === $scope) {
184
                return $settings[$name] = $setting;
185
            }
186
187
            throw new InvalidScopeException($scope);
188
        } elseif ($name !== null) {
189
            throw new \Exception('There is no setting with this name.');
190
        }
191
192
        foreach ($this->settingsConfiguration as $name => $setting) {
193
            if ($setting['scope'] === $scope || null === $scope) {
194
                $setting['value'] = $this->decodeValue($setting['type'], $setting['value']);
195
                $settings[$name] = $setting;
196
            }
197
        }
198
199
        return $settings;
200
    }
201
202
    /**
203
     * @return array|mixed
204
     */
205
    private function getSettingsFromRepository()
206
    {
207
        return $this->settingsRepository->findAllByScopeAndOwner($this->scopeContext)->getQuery()->getResult();
208
    }
209
210
    /**
211
     * @param string                      $name
212
     * @param string                      $scope
213
     * @param SettingsOwnerInterface|null $owner
214
     *
215
     * @return mixed
216
     */
217
    private function getSettingFromRepository(string $name, string $scope, SettingsOwnerInterface $owner = null)
218
    {
219
        return $this->settingsRepository
220
            ->findOneByNameAndScopeAndOwner($name, $scope, $owner)
221
            ->getQuery()
222
            ->getOneOrNullResult();
223
    }
224
225
    /**
226
     * @param $settingType
227
     * @param $value
228
     *
229
     * @return string
230
     *
231
     * @throws \Exception
232
     */
233
    private function encodeValue($settingType, $value)
234
    {
235
        if (($actualType = gettype($value)) !== $settingType) {
236
            throw new \Exception(sprintf('Value type should be "%s" not "%s"', $settingType, $actualType));
237
        }
238
239
        if ('array' === $settingType) {
240
            return json_encode($value);
241
        }
242
243
        return $value;
244
    }
245
246
    /**
247
     * @param $settingType
248
     * @param $value
249
     *
250
     * @return mixed
251
     */
252
    private function decodeValue($settingType, $value)
253
    {
254
        if ('array' === $settingType) {
255
            return json_decode($value, true);
256
        }
257
258
        return $value;
259
    }
260
}
261