Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
93.88% |
46 / 49 |
|
66.67% |
2 / 3 |
CRAP | |
0.00% |
0 / 1 |
PluginFactory | |
93.88% |
46 / 49 |
|
66.67% |
2 / 3 |
16.06 | |
0.00% |
0 / 1 |
loadConfigFile | |
93.18% |
41 / 44 |
|
0.00% |
0 / 1 |
14.06 | |||
canCreate | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__invoke | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | /** |
4 | * VuFind Config Plugin Factory |
5 | * |
6 | * PHP version 8 |
7 | * |
8 | * Copyright (C) Villanova University 2010. |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2, |
12 | * as published by the Free Software Foundation. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU General Public License |
20 | * along with this program; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 | * |
23 | * @category VuFind |
24 | * @package ServiceManager |
25 | * @author Demian Katz <demian.katz@villanova.edu> |
26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
27 | * @link https://vufind.org/wiki/development Wiki |
28 | */ |
29 | |
30 | namespace VuFind\Config; |
31 | |
32 | use Laminas\Config\Config; |
33 | use Laminas\ServiceManager\Factory\AbstractFactoryInterface; |
34 | use Psr\Container\ContainerInterface; |
35 | use VuFind\Config\Feature\IniReaderTrait; |
36 | |
37 | use function count; |
38 | use function in_array; |
39 | use function is_object; |
40 | |
41 | /** |
42 | * VuFind Config Plugin Factory |
43 | * |
44 | * @category VuFind |
45 | * @package ServiceManager |
46 | * @author Demian Katz <demian.katz@villanova.edu> |
47 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
48 | * @link https://vufind.org/wiki/development Wiki |
49 | */ |
50 | class PluginFactory implements AbstractFactoryInterface |
51 | { |
52 | use IniReaderTrait; |
53 | |
54 | /** |
55 | * Load the specified configuration file. |
56 | * |
57 | * @param string $filename Config file name |
58 | * |
59 | * @return Config |
60 | */ |
61 | protected function loadConfigFile(string $filename): Config |
62 | { |
63 | $configs = []; |
64 | |
65 | // Return empty configuration if file does not exist: |
66 | if (!file_exists($filename)) { |
67 | return new Config([]); |
68 | } |
69 | |
70 | // Retrieve and parse at least one configuration file, and possibly a whole |
71 | // chain of them if the Parent_Config setting is used: |
72 | do { |
73 | $configs[] |
74 | = new Config($this->getIniReader()->fromFile($filename), true); |
75 | |
76 | $i = count($configs) - 1; |
77 | if (isset($configs[$i]->Parent_Config->path)) { |
78 | $filename = $configs[$i]->Parent_Config->path; |
79 | } elseif (isset($configs[$i]->Parent_Config->relative_path)) { |
80 | $filename = pathinfo($filename, PATHINFO_DIRNAME) |
81 | . DIRECTORY_SEPARATOR |
82 | . $configs[$i]->Parent_Config->relative_path; |
83 | } else { |
84 | $filename = false; |
85 | } |
86 | } while ($filename); |
87 | |
88 | // The last element in the array will be the top of the inheritance tree. |
89 | // Let's establish a baseline: |
90 | $config = array_pop($configs); |
91 | |
92 | // Now we'll pull all the children down one at a time and override settings |
93 | // as appropriate: |
94 | while (null !== ($child = array_pop($configs))) { |
95 | $overrideSections = isset($child->Parent_Config->override_full_sections) |
96 | ? explode( |
97 | ',', |
98 | str_replace( |
99 | ' ', |
100 | '', |
101 | $child->Parent_Config->override_full_sections |
102 | ) |
103 | ) |
104 | : []; |
105 | foreach ($child as $section => $contents) { |
106 | // Check if arrays in the current config file should be merged with |
107 | // preceding arrays from config files defined as Parent_Config. |
108 | $mergeArraySettings |
109 | = !empty($child->Parent_Config->merge_array_settings); |
110 | |
111 | // Omit Parent_Config from the returned configuration; it is only |
112 | // needed during loading, and its presence will cause problems in |
113 | // config files that iterate through all of the sections (e.g. |
114 | // combined.ini, permissions.ini). |
115 | if ($section === 'Parent_Config') { |
116 | continue; |
117 | } |
118 | if ( |
119 | in_array($section, $overrideSections) |
120 | || !isset($config->$section) |
121 | ) { |
122 | $config->$section = $child->$section; |
123 | } else { |
124 | foreach (array_keys($contents->toArray()) as $key) { |
125 | // If a key is defined as key[] in the config file the key |
126 | // remains a Laminas\Config\Config object. If the current |
127 | // section is not configured as an override section we try to |
128 | // merge the key[] values instead of overwriting them. |
129 | if ( |
130 | is_object($config->$section->$key) |
131 | && is_object($child->$section->$key) |
132 | && $mergeArraySettings |
133 | ) { |
134 | $config->$section->$key = array_merge( |
135 | $config->$section->$key->toArray(), |
136 | $child->$section->$key->toArray() |
137 | ); |
138 | } else { |
139 | $config->$section->$key = $child->$section->$key; |
140 | } |
141 | } |
142 | } |
143 | } |
144 | } |
145 | |
146 | $config->setReadOnly(); |
147 | return $config; |
148 | } |
149 | |
150 | /** |
151 | * Can we create a service for the specified name? |
152 | * |
153 | * @param ContainerInterface $container Service container |
154 | * @param string $requestedName Name of service |
155 | * |
156 | * @return bool |
157 | * |
158 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) |
159 | */ |
160 | public function canCreate(ContainerInterface $container, $requestedName) |
161 | { |
162 | // Assume that configurations exist: |
163 | return true; |
164 | } |
165 | |
166 | /** |
167 | * Create a service for the specified name. |
168 | * |
169 | * @param ContainerInterface $container Service container |
170 | * @param string $requestedName Name of service |
171 | * @param array $options Options (unused) |
172 | * |
173 | * @return object |
174 | * |
175 | * @SuppressWarnings(PHPMD.UnusedFormalParameter) |
176 | */ |
177 | public function __invoke( |
178 | ContainerInterface $container, |
179 | $requestedName, |
180 | array $options = null |
181 | ) { |
182 | $pathResolver = $container->get(PathResolver::class); |
183 | return $this->loadConfigFile( |
184 | $pathResolver->getConfigPath($requestedName . '.ini') |
185 | ); |
186 | } |
187 | } |