Passed
Push — main ( 02d0e2...a48ca0 )
by Thierry
12:44 queued 11:20
created

DialogManager::onChange()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 23
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 17
nc 5
nop 2
dl 0
loc 23
rs 9.3888
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * DialogManager.php
5
 *
6
 * Manage dialog library list and defaults.
7
 *
8
 * @author Thierry Feuzeu <[email protected]>
9
 * @copyright 2019 Thierry Feuzeu <[email protected]>
10
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
11
 * @link https://github.com/jaxon-php/jaxon-core
12
 */
13
14
namespace Jaxon\Dialogs;
15
16
use Jaxon\App\Config\ConfigListenerInterface;
17
use Jaxon\App\Config\ConfigManager;
18
use Jaxon\App\Dialog\Library\AlertInterface;
19
use Jaxon\App\Dialog\Library\ConfirmInterface;
20
use Jaxon\App\Dialog\Library\LibraryInterface;
21
use Jaxon\App\Dialog\Library\ModalInterface;
22
use Jaxon\App\Dialog\Manager\LibraryRegistryInterface;
23
use Jaxon\App\I18n\Translator;
24
use Jaxon\Dialogs\Dialog\LibraryHelper;
25
use Jaxon\Dialogs\Dialog\Library\Alert;
26
use Jaxon\Di\Container;
27
use Jaxon\Exception\SetupException;
28
use Jaxon\Utils\Config\Config;
29
use Jaxon\Utils\Template\TemplateEngine;
30
31
use function array_map;
32
use function array_keys;
33
use function class_implements;
34
use function in_array;
35
use function substr;
36
37
class DialogManager implements ConfigListenerInterface, LibraryRegistryInterface
38
{
39
    /**
40
     * @var array
41
     */
42
    protected $aLibraries = [];
43
44
    /**
45
     * The ConfirmInterface class name
46
     *
47
     * @var string
48
     */
49
    private $sConfirmLibrary = '';
50
51
    /**
52
     * The AlertInterface class name
53
     *
54
     * @var string
55
     */
56
    private $sAlertLibrary = '';
57
58
    /**
59
     * The ModalInterface class name
60
     *
61
     * @var string
62
     */
63
    private $sModalLibrary = '';
64
65
    /**
66
     * The constructor
67
     *
68
     * @param Container $di
69
     * @param ConfigManager $xConfigManager
70
     * @param Translator $xTranslator
71
     */
72
    public function __construct(private Container $di,
73
        private ConfigManager $xConfigManager, private Translator $xTranslator)
74
    {}
75
76
    /**
77
     * Register a javascript dialog library adapter.
78
     *
79
     * @param string $sClass
80
     * @param string $sLibraryName
81
     *
82
     * @return void
83
     */
84
    private function _registerLibrary(string $sClass, string $sLibraryName)
85
    {
86
        $this->di->set($sClass, function($di) use($sClass) {
87
            return $di->make($sClass);
88
        });
89
        $this->di->set("dialog_library_helper_$sLibraryName", function($di) use($sClass) {
90
            return new LibraryHelper($di->g($sClass), $di->g(ConfigManager::class),
91
                $di->g(TemplateEngine::class));
92
        });
93
        // Set the alias, so the libraries can be found by their names.
94
        $this->di->alias("dialog_library_$sLibraryName", $sClass);
95
    }
96
97
    /**
98
     * Register a javascript dialog library adapter.
99
     *
100
     * @param string $sClassName
101
     * @param string $sLibraryName
102
     *
103
     * @return void
104
     * @throws SetupException
105
     */
106
    public function registerLibrary(string $sClassName, string $sLibraryName)
107
    {
108
        if(isset($this->aLibraries[$sLibraryName]))
109
        {
110
            return;
111
        }
112
        if(!($aInterfaces = class_implements($sClassName)))
113
        {
114
            // The class is invalid.
115
            $sMessage = $this->xTranslator->trans('errors.register.invalid', ['name' => $sClassName]);
116
            throw new SetupException($sMessage);
117
        }
118
119
        $bIsConfirm = in_array(ConfirmInterface::class, $aInterfaces);
120
        $bIsAlert = in_array(AlertInterface::class, $aInterfaces);
121
        $bIsModal = in_array(ModalInterface::class, $aInterfaces);
122
        if(!$bIsConfirm && !$bIsAlert && !$bIsModal)
123
        {
124
            // The class is invalid.
125
            $sMessage = $this->xTranslator->trans('errors.register.invalid', ['name' => $sClassName]);
126
            throw new SetupException($sMessage);
127
        }
128
129
        // Save the library
130
        $this->aLibraries[$sLibraryName] = [
131
            'confirm' => $bIsConfirm,
132
            'alert' => $bIsAlert,
133
            'modal' => $bIsModal,
134
            'used' => false,
135
        ];
136
        // Register the library class in the container
137
        $this->_registerLibrary($sClassName, $sLibraryName);
138
    }
139
140
    /**
141
     * Get the dialog library helper
142
     *
143
     * @param string $sLibraryName
144
     *
145
     * @return LibraryHelper
146
     */
147
    public function getLibraryHelper(string $sLibraryName): LibraryHelper
148
    {
149
        return $this->di->g("dialog_library_helper_$sLibraryName");
150
    }
151
152
    /**
153
     * Set the ConfirmInterface library
154
     *
155
     * @param string $sLibraryName The ConfirmInterface library name
156
     *
157
     * @return void
158
     * @throws SetupException
159
     */
160
    public function setConfirmLibrary(string $sLibraryName)
161
    {
162
        if(!isset($this->aLibraries[$sLibraryName]) || !$this->aLibraries[$sLibraryName]['confirm'])
163
        {
164
            $sMessage = $this->xTranslator->trans('errors.dialog.library',
165
                ['type' => 'confirm', 'name' => $sLibraryName]);
166
            throw new SetupException($sMessage);
167
        }
168
        $this->sConfirmLibrary = $sLibraryName;
169
    }
170
171
    /**
172
     * Get the ConfirmInterface library
173
     *
174
     * @return ConfirmInterface
175
     */
176
    public function getConfirmLibrary(): ConfirmInterface
177
    {
178
        $sKey = "dialog_library_{$this->sConfirmLibrary}";
179
        return $this->di->h($sKey) ? $this->di->g($sKey) : $this->di->g(Alert::class);
180
    }
181
182
    /**
183
     * Set AlertInterface library
184
     *
185
     * @param string $sLibraryName The AlertInterface library name
186
     *
187
     * @return void
188
     * @throws SetupException
189
     */
190
    public function setAlertLibrary(string $sLibraryName)
191
    {
192
        if(!isset($this->aLibraries[$sLibraryName]) || !$this->aLibraries[$sLibraryName]['alert'])
193
        {
194
            $sMessage = $this->xTranslator->trans('errors.dialog.library',
195
                ['type' => 'alert', 'name' => $sLibraryName]);
196
            throw new SetupException($sMessage);
197
        }
198
        $this->sAlertLibrary = $sLibraryName;
199
    }
200
201
    /**
202
     * Get the AlertInterface library
203
     *
204
     * @return AlertInterface
205
     */
206
    public function getAlertLibrary(): AlertInterface
207
    {
208
        $sKey = "dialog_library_{$this->sAlertLibrary}";
209
        return $this->di->h($sKey) ? $this->di->g($sKey) : $this->di->g(Alert::class);
210
    }
211
212
    /**
213
     * Set the ModalInterface library
214
     *
215
     * @param string $sLibraryName The ModalInterface library name
216
     *
217
     * @return void
218
     * @throws SetupException
219
     */
220
    public function setModalLibrary(string $sLibraryName)
221
    {
222
        if(!isset($this->aLibraries[$sLibraryName]) || !$this->aLibraries[$sLibraryName]['modal'])
223
        {
224
            $sMessage = $this->xTranslator->trans('errors.dialog.library',
225
                ['type' => 'modal', 'name' => $sLibraryName]);
226
            throw new SetupException($sMessage);
227
        }
228
        $this->sModalLibrary = $sLibraryName;
229
    }
230
231
    /**
232
     * Get the ModalInterface library
233
     *
234
     * @return ModalInterface|null
235
     */
236
    public function getModalLibrary(): ?ModalInterface
237
    {
238
        $sKey = "dialog_library_{$this->sModalLibrary}";
239
        return $this->di->h($sKey) ? $this->di->g($sKey) : null;
240
    }
241
242
    /**
243
     * Register the javascript dialog libraries from config options.
244
     *
245
     * @return void
246
     * @throws SetupException
247
     */
248
    protected function registerLibraries()
249
    {
250
        $aLibraries = $this->xConfigManager->getAppOption('dialogs.lib.ext', []);
251
        foreach($aLibraries as $sLibraryName => $sClassName)
252
        {
253
            $this->registerLibrary($sClassName, $sLibraryName);
254
        }
255
    }
256
257
    /**
258
     * Set the default library for each dialog feature.
259
     *
260
     * @return void
261
     * @throws SetupException
262
     */
263
    protected function setDefaultLibraries()
264
    {
265
        // Set the default modal library
266
        if(($sLibraryName = $this->xConfigManager->getAppOption('dialogs.default.modal', '')))
267
        {
268
            $this->setModalLibrary($sLibraryName);
269
            $this->aLibraries[$sLibraryName]['used'] = true;
270
        }
271
        // Set the default alert library
272
        if(($sLibraryName = $this->xConfigManager->getAppOption('dialogs.default.alert', '')))
273
        {
274
            $this->setAlertLibrary($sLibraryName);
275
            $this->aLibraries[$sLibraryName]['used'] = true;
276
        }
277
        // Set the default confirm library
278
        if(($sLibraryName = $this->xConfigManager->getAppOption('dialogs.default.confirm', '')))
279
        {
280
            $this->setConfirmLibrary($sLibraryName);
281
            $this->aLibraries[$sLibraryName]['used'] = true;
282
        }
283
    }
284
285
    /**
286
     * Set the libraries in use.
287
     *
288
     * @return void
289
     */
290
    protected function setUsedLibraries()
291
    {
292
        // Set the other libraries in use
293
        $aLibraries = $this->xConfigManager->getAppOption('dialogs.lib.use', []);
294
        foreach($aLibraries as $sLibraryName)
295
        {
296
            if(isset($this->aLibraries[$sLibraryName])) // Make sure the library exists
297
            {
298
                $this->aLibraries[$sLibraryName]['used'] = true;
299
            }
300
        }
301
    }
302
303
    /**
304
     * Get the dialog libraries class instances
305
     *
306
     * @return LibraryInterface[]
307
     */
308
    public function getLibraries(): array
309
    {
310
        // Reset the default libraries any time the config is changed.
311
        $this->registerLibraries();
312
        $this->setDefaultLibraries();
313
        $this->setUsedLibraries();
314
315
        // Only return the libraries that are used.
316
        $aLibraries = array_filter($this->aLibraries, function($aLibrary) {
317
            return $aLibrary['used'];
318
        });
319
        return array_map(function($sLibraryName) {
320
            return $this->di->g("dialog_library_$sLibraryName");
321
        }, array_keys($aLibraries));
322
    }
323
324
    /**
325
     * @inheritDoc
326
     * @throws SetupException
327
     */
328
    public function onChange(Config $xConfig, string $sName)
329
    {
330
        if($sName === '')
331
        {
332
            // Reset the default libraries any time the config is changed.
333
            $this->registerLibraries();
334
            $this->setDefaultLibraries();
335
            $this->setUsedLibraries();
336
            return;
337
        }
338
        $sPrefix = substr($sName, 0, 15);
339
        switch($sPrefix)
340
        {
341
        case 'dialogs.default':
342
            $this->setDefaultLibraries();
343
            return;
344
        case 'dialogs.lib.ext':
345
            $this->registerLibraries();
346
            return;
347
        case 'dialogs.lib.use':
348
            $this->setUsedLibraries();
349
            return;
350
        default:
351
        }
352
    }
353
}
354