Passed
Push — master ( e82656...5198fb )
by Thierry
03:06
created

PackageManager::getPackageOptions()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
nc 3
nop 1
dl 0
loc 16
rs 10
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * PackageManager.php - Jaxon package manager
5
 *
6
 * Register Jaxon plugins, packages and callables from a config file.
7
 *
8
 * @package jaxon-core
0 ignored issues
show
Coding Style introduced by
Package name "jaxon-core" is not valid; consider "Jaxoncore" instead
Loading history...
9
 * @author Thierry Feuzeu <[email protected]>
10
 * @copyright 2022 Thierry Feuzeu <[email protected]>
11
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
12
 * @link https://github.com/jaxon-php/jaxon-core
13
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
14
15
namespace Jaxon\Plugin\Manager;
16
17
use Jaxon\Jaxon;
18
use Jaxon\Config\ConfigManager;
19
use Jaxon\Di\Container;
20
use Jaxon\Exception\SetupException;
21
use Jaxon\Plugin\Code\CodeGenerator;
22
use Jaxon\Plugin\Package;
23
use Jaxon\Ui\View\ViewManager;
24
use Jaxon\Utils\Config\Config;
25
use Jaxon\Utils\Translation\Translator;
26
27
use function is_array;
28
use function is_integer;
29
use function is_string;
30
use function is_subclass_of;
31
use function trim;
32
33
class PackageManager
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class PackageManager
Loading history...
34
{
35
    /**
36
     * @var Container
37
     */
38
    protected $di;
0 ignored issues
show
Coding Style introduced by
Expected 1 blank line(s) before first member var; 0 found
Loading history...
39
40
    /**
41
     * @var PluginManager
42
     */
43
    protected $xPluginManager;
44
45
    /**
46
     * @var ConfigManager
47
     */
48
    protected $xConfigManager;
49
50
    /**
51
     * @var ViewManager
52
     */
53
    protected $xViewManager;
54
55
    /**
56
     * The code generator
57
     *
58
     * @var CodeGenerator
59
     */
60
    private $xCodeGenerator;
61
62
    /**
63
     * @var Translator
64
     */
65
    protected $xTranslator;
66
67
    /**
68
     * The constructor
69
     *
70
     * @param Container $di
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 5 spaces after parameter type; 1 found
Loading history...
71
     * @param PluginManager $xPluginManager
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
72
     * @param ConfigManager $xConfigManager
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
73
     * @param ViewManager $xViewManager
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
74
     * @param CodeGenerator $xCodeGenerator
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
75
     * @param Translator $xTranslator
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
76
     */
77
    public function __construct(Container $di, PluginManager $xPluginManager, ConfigManager $xConfigManager,
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines before function; 1 found
Loading history...
78
        ViewManager $xViewManager, CodeGenerator $xCodeGenerator, Translator $xTranslator)
79
    {
80
        $this->di = $di;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 13 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
81
        $this->xPluginManager = $xPluginManager;
82
        $this->xConfigManager = $xConfigManager;
83
        $this->xViewManager = $xViewManager;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
84
        $this->xCodeGenerator = $xCodeGenerator;
85
        $this->xTranslator = $xTranslator;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
86
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
87
88
    /**
89
     * Save items in the DI container
90
     *
91
     * @param Config $xConfig
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
92
     *
93
     * @return void
94
     */
95
    private function updateContainer(Config $xConfig)
96
    {
97
        $aOptions = $xConfig->getOption('container.set', []);
98
        foreach($aOptions as $xKey => $xValue)
99
        {
100
            // The key is the class name. It must be a string.
101
            $this->di->set((string)$xKey, $xValue);
102
        }
103
        $aOptions = $xConfig->getOption('container.val', []);
104
        foreach($aOptions as $xKey => $xValue)
105
        {
106
            // The key is the class name. It must be a string.
107
            $this->di->val((string)$xKey, $xValue);
108
        }
109
        $aOptions = $xConfig->getOption('container.auto', []);
110
        foreach($aOptions as $xValue)
111
        {
112
            // The key is the class name. It must be a string.
113
            $this->di->auto((string)$xValue);
114
        }
115
        $aOptions = $xConfig->getOption('container.alias', []);
116
        foreach($aOptions as $xKey => $xValue)
117
        {
118
            // The key is the class name. It must be a string.
119
            $this->di->alias((string)$xKey, (string)$xValue);
120
        }
121
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
122
123
    /**
124
     * Register callables from a section of the config
125
     *
126
     * @param array $aOptions    The content of the config section
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 6 spaces after parameter name; 4 found
Loading history...
127
     * @param string $sCallableType    The type of callable to register
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
128
     *
129
     * @return void
130
     * @throws SetupException
131
     */
132
    private function registerCallables(array $aOptions, string $sCallableType)
133
    {
134
        foreach($aOptions as $xKey => $xValue)
135
        {
136
            if(is_integer($xKey) && is_string($xValue))
137
            {
138
                // Register a function without options
139
                $this->xPluginManager->registerCallable($sCallableType, $xValue);
140
            }
141
            elseif(is_string($xKey) && (is_array($xValue) || is_string($xValue)))
142
            {
143
                // Register a function with options
144
                $this->xPluginManager->registerCallable($sCallableType, $xKey, $xValue);
145
            }
146
        }
147
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
148
149
    /**
150
     * Read and set Jaxon options from a JSON config file
151
     *
152
     * @param Config $xConfig The config options
0 ignored issues
show
Coding Style introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
153
     * @param Config|null $xPkgConfig The user provided package options
154
     *
155
     * @return void
156
     * @throws SetupException
157
     */
158
    private function registerItemsFromConfig(Config $xConfig, ?Config $xPkgConfig = null)
159
    {
160
        // Register functions, classes and directories
161
        $this->registerCallables($xConfig->getOption('functions', []), Jaxon::CALLABLE_FUNCTION);
162
        $this->registerCallables($xConfig->getOption('classes', []), Jaxon::CALLABLE_CLASS);
163
        $this->registerCallables($xConfig->getOption('directories', []), Jaxon::CALLABLE_DIR);
164
        // Register the view namespaces
165
        // Note: the $xPkgConfig can provide a "template" option, which is used to customize
166
        // the user defined view namespaces. That's why it is needed here.
167
        $this->xViewManager->addNamespaces($xConfig, $xPkgConfig);
168
        // Save items in the DI container
169
        $this->updateContainer($xConfig);
170
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
171
172
    /**
173
     * Get the options provided by the package library
174
     *
175
     * @param string $sClassName    The package class
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
176
     *
177
     * @return array
178
     * @throws SetupException
179
     */
180
    private function getPackageOptions(string $sClassName): array
181
    {
182
        // $this->aPackages contains packages config file paths.
183
        $aLibOptions = $sClassName::config();
184
        if(is_string($aLibOptions))
185
        {
186
            // A string is supposed to be the path to a config file.
187
            $aLibOptions = $this->xConfigManager->read($aLibOptions);
188
        }
189
        elseif(!is_array($aLibOptions))
190
        {
191
            // Otherwise, anything else than an array is not accepted.
192
            $sMessage = $this->xTranslator->trans('errors.register.invalid', ['name' => $sClassName]);
193
            throw new SetupException($sMessage);
194
        }
195
        return $aLibOptions;
196
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
197
198
    /**
199
     * Register a package
200
     *
201
     * @param string $sClassName    The package class
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 4 found
Loading history...
202
     * @param array $aPkgOptions    The user provided package options
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
203
     *
204
     * @return void
205
     * @throws SetupException
206
     */
207
    public function registerPackage(string $sClassName, array $aPkgOptions)
208
    {
209
        $sClassName = trim($sClassName, '\\ ');
210
        if(!is_subclass_of($sClassName, Package::class))
211
        {
212
            $sMessage = $this->xTranslator->trans('errors.register.invalid', ['name' => $sClassName]);
213
            throw new SetupException($sMessage);
214
        }
215
        $aLibOptions = $this->getPackageOptions($sClassName);
216
        // Add the package name to the config
217
        $aLibOptions['package'] = $sClassName;
218
        $xLibConfig = $this->xConfigManager->newConfig($aLibOptions);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 13 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
219
        $xPkgConfig = $this->xConfigManager->newConfig($aPkgOptions);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 13 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
220
        $this->di->registerPackage($sClassName, $xPkgConfig);
221
        // Register the declarations in the package config.
222
        $this->registerItemsFromConfig($xLibConfig, $xPkgConfig);
223
        // Register the package as a code generator.
224
        $this->xCodeGenerator->addGenerator($sClassName, 500);
225
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
226
227
    /**
228
     * Get a package instance
229
     *
230
     * @param string $sClassName    The package class name
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
231
     *
232
     * @return Package|null
233
     */
234
    public function getPackage(string $sClassName): ?Package
235
    {
236
        $sClassName = trim($sClassName, '\\ ');
237
        return $this->di->h($sClassName) ? $this->di->g($sClassName) : null;
238
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 1 found
Loading history...
239
240
    /**
241
     * Read and set Jaxon options from the config
242
     *
243
     * @param Config $xAppConfig    The config options
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 4 found
Loading history...
244
     *
245
     * @return void
246
     * @throws SetupException
247
     */
248
    public function registerFromConfig(Config $xAppConfig)
249
    {
250
        $this->registerItemsFromConfig($xAppConfig);
251
252
        // Register packages
253
        $aPackageConfig = $xAppConfig->getOption('packages', []);
254
        foreach($aPackageConfig as $sClassName => $aPkgOptions)
255
        {
256
            $this->registerPackage($sClassName, $aPkgOptions);
257
        }
258
    }
0 ignored issues
show
Coding Style introduced by
Expected 2 blank lines after function; 0 found
Loading history...
259
}
260