1
2 #ifdef HAVE_CONFIG_H
3 #include "../ext_config.h"
4 #endif
5
6 #include <php.h>
7 #include "../php_ext.h"
8 #include "../ext.h"
9
10 #include <Zend/zend_operators.h>
11 #include <Zend/zend_exceptions.h>
12 #include <Zend/zend_interfaces.h>
13
14 #include "kernel/main.h"
15 #include "kernel/object.h"
16 #include "kernel/operators.h"
17 #include "kernel/memory.h"
18 #include "kernel/fcall.h"
19 #include "kernel/exception.h"
20 #include "kernel/string.h"
21 #include "kernel/array.h"
22
23
24 /**
25 * This file is part of the Phalcon Framework.
26 *
27 * (c) Phalcon Team <team@phalcon.io>
28 *
29 * For the full copyright and license information, please view the LICENSE.txt
30 * file that was distributed with this source code.
31 */
32 /**
33 * `Phalcon\Config` is designed to simplify the access to, and the use of,
34 * configuration data within applications. It provides a nested object property
35 * based user interface for accessing this configuration data within application
36 * code.
37 *
38 *```php
39 * $config = new \Phalcon\Config(
40 * [
41 * "database" => [
42 * "adapter" => "Mysql",
43 * "host" => "localhost",
44 * "username" => "scott",
45 * "password" => "cheetah",
46 * "dbname" => "test_db",
47 * ],
48 * "phalcon" => [
49 * "controllersDir" => "../app/controllers/",
50 * "modelsDir" => "../app/models/",
51 * "viewsDir" => "../app/views/",
52 * ],
53 * ]
54 * );
55 *```
56 */
ZEPHIR_INIT_CLASS(Phalcon_Config)57 ZEPHIR_INIT_CLASS(Phalcon_Config) {
58
59 ZEPHIR_REGISTER_CLASS_EX(Phalcon, Config, phalcon, config, phalcon_collection_ce, phalcon_config_method_entry, 0);
60
61 /**
62 * @var string
63 */
64 zend_declare_property_null(phalcon_config_ce, SL("pathDelimiter"), ZEND_ACC_PROTECTED);
65
66 zephir_declare_class_constant_string(phalcon_config_ce, SL("DEFAULT_PATH_DELIMITER"), ".");
67
68 zend_class_implements(phalcon_config_ce, 1, phalcon_config_configinterface_ce);
69 return SUCCESS;
70
71 }
72
73 /**
74 * Gets the default path delimiter
75 *
76 * @return string
77 */
PHP_METHOD(Phalcon_Config,getPathDelimiter)78 PHP_METHOD(Phalcon_Config, getPathDelimiter) {
79
80 zval _0, _1$$3;
81 zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL;
82 zval *this_ptr = getThis();
83
84 ZVAL_UNDEF(&_0);
85 ZVAL_UNDEF(&_1$$3);
86
87 ZEPHIR_MM_GROW();
88
89 zephir_read_property(&_0, this_ptr, ZEND_STRL("pathDelimiter"), PH_NOISY_CC | PH_READONLY);
90 if (UNEXPECTED(!zephir_is_true(&_0))) {
91 ZEPHIR_INIT_VAR(&_1$$3);
92 ZEPHIR_INIT_NVAR(&_1$$3);
93 ZVAL_STRING(&_1$$3, ".");
94 zephir_update_property_zval(this_ptr, ZEND_STRL("pathDelimiter"), &_1$$3);
95 }
96 RETURN_MM_MEMBER(getThis(), "pathDelimiter");
97
98 }
99
100 /**
101 * Merges a configuration into the current one
102 *
103 *```php
104 * $appConfig = new \Phalcon\Config(
105 * [
106 * "database" => [
107 * "host" => "localhost",
108 * ],
109 * ]
110 * );
111 *
112 * $globalConfig->merge($appConfig);
113 *```
114 */
PHP_METHOD(Phalcon_Config,merge)115 PHP_METHOD(Phalcon_Config, merge) {
116
117 zend_bool _0;
118 zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL;
119 zend_long ZEPHIR_LAST_CALL_STATUS;
120 zval *toMerge, toMerge_sub, config, result, source, target;
121 zval *this_ptr = getThis();
122
123 ZVAL_UNDEF(&toMerge_sub);
124 ZVAL_UNDEF(&config);
125 ZVAL_UNDEF(&result);
126 ZVAL_UNDEF(&source);
127 ZVAL_UNDEF(&target);
128
129 ZEPHIR_MM_GROW();
130 zephir_fetch_params(1, 1, 0, &toMerge);
131
132
133
134 _0 = Z_TYPE_P(toMerge) == IS_OBJECT;
135 if (_0) {
136 _0 = zephir_instance_of_ev(toMerge, phalcon_config_configinterface_ce);
137 }
138 if (Z_TYPE_P(toMerge) == IS_ARRAY) {
139 ZEPHIR_INIT_VAR(&config);
140 object_init_ex(&config, phalcon_config_ce);
141 ZEPHIR_CALL_METHOD(NULL, &config, "__construct", NULL, 22, toMerge);
142 zephir_check_call_status();
143 } else if (_0) {
144 ZEPHIR_CPY_WRT(&config, toMerge);
145 } else {
146 ZEPHIR_THROW_EXCEPTION_DEBUG_STR(phalcon_config_exception_ce, "Invalid data type for merge.", "phalcon/Config.zep", 89);
147 return;
148 }
149 ZEPHIR_CALL_METHOD(&source, this_ptr, "toarray", NULL, 0);
150 zephir_check_call_status();
151 ZEPHIR_CALL_METHOD(&target, &config, "toarray", NULL, 0);
152 zephir_check_call_status();
153 ZEPHIR_CALL_METHOD(&result, this_ptr, "internalmerge", NULL, 23, &source, &target);
154 zephir_check_call_status();
155 ZEPHIR_CALL_METHOD(NULL, this_ptr, "clear", NULL, 0);
156 zephir_check_call_status();
157 ZEPHIR_CALL_METHOD(NULL, this_ptr, "init", NULL, 0, &result);
158 zephir_check_call_status();
159 RETURN_THIS();
160
161 }
162
163 /**
164 * Returns a value from current config using a dot separated path.
165 *
166 *```php
167 * echo $config->path("unknown.path", "default", ".");
168 *```
169 */
PHP_METHOD(Phalcon_Config,path)170 PHP_METHOD(Phalcon_Config, path) {
171
172 zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL;
173 zephir_fcall_cache_entry *_1 = NULL;
174 zend_long ZEPHIR_LAST_CALL_STATUS;
175 zval *path_param = NULL, *defaultValue = NULL, defaultValue_sub, *delimiter = NULL, delimiter_sub, __$null, config, key, keys, _0, _2$$5, _3$$5;
176 zval path;
177 zval *this_ptr = getThis();
178
179 ZVAL_UNDEF(&path);
180 ZVAL_UNDEF(&defaultValue_sub);
181 ZVAL_UNDEF(&delimiter_sub);
182 ZVAL_NULL(&__$null);
183 ZVAL_UNDEF(&config);
184 ZVAL_UNDEF(&key);
185 ZVAL_UNDEF(&keys);
186 ZVAL_UNDEF(&_0);
187 ZVAL_UNDEF(&_2$$5);
188 ZVAL_UNDEF(&_3$$5);
189
190 ZEPHIR_MM_GROW();
191 zephir_fetch_params(1, 1, 2, &path_param, &defaultValue, &delimiter);
192
193 zephir_get_strval(&path, path_param);
194 if (!defaultValue) {
195 defaultValue = &defaultValue_sub;
196 defaultValue = &__$null;
197 }
198 if (!delimiter) {
199 delimiter = &delimiter_sub;
200 ZEPHIR_CPY_WRT(delimiter, &__$null);
201 } else {
202 ZEPHIR_SEPARATE_PARAM(delimiter);
203 }
204
205
206 ZEPHIR_CALL_METHOD(&_0, this_ptr, "has", NULL, 0, &path);
207 zephir_check_call_status();
208 if (zephir_is_true(&_0)) {
209 ZEPHIR_RETURN_CALL_METHOD(this_ptr, "get", NULL, 0, &path);
210 zephir_check_call_status();
211 RETURN_MM();
212 }
213 if (EXPECTED(ZEPHIR_IS_EMPTY(delimiter))) {
214 ZEPHIR_CALL_METHOD(delimiter, this_ptr, "getpathdelimiter", NULL, 0);
215 zephir_check_call_status();
216 }
217 ZEPHIR_INIT_VAR(&config);
218 if (zephir_clone(&config, this_ptr) == FAILURE) {
219 RETURN_MM();
220 }
221 ZEPHIR_INIT_VAR(&keys);
222 zephir_fast_explode(&keys, delimiter, &path, LONG_MAX);
223 while (1) {
224 if (!(!(ZEPHIR_IS_EMPTY(&keys)))) {
225 break;
226 }
227 ZEPHIR_MAKE_REF(&keys);
228 ZEPHIR_CALL_FUNCTION(&key, "array_shift", &_1, 24, &keys);
229 ZEPHIR_UNREF(&keys);
230 zephir_check_call_status();
231 ZEPHIR_CALL_METHOD(&_2$$5, &config, "has", NULL, 0, &key);
232 zephir_check_call_status();
233 if (!(zephir_is_true(&_2$$5))) {
234 break;
235 }
236 if (ZEPHIR_IS_EMPTY(&keys)) {
237 ZEPHIR_RETURN_CALL_METHOD(&config, "get", NULL, 0, &key);
238 zephir_check_call_status();
239 RETURN_MM();
240 }
241 ZEPHIR_CALL_METHOD(&_3$$5, &config, "get", NULL, 0, &key);
242 zephir_check_call_status();
243 ZEPHIR_CPY_WRT(&config, &_3$$5);
244 if (ZEPHIR_IS_EMPTY(&config)) {
245 break;
246 }
247 }
248 RETVAL_ZVAL(defaultValue, 1, 0);
249 RETURN_MM();
250
251 }
252
253 /**
254 * Sets the default path delimiter
255 */
PHP_METHOD(Phalcon_Config,setPathDelimiter)256 PHP_METHOD(Phalcon_Config, setPathDelimiter) {
257
258 zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL;
259 zval *delimiter_param = NULL;
260 zval delimiter;
261 zval *this_ptr = getThis();
262
263 ZVAL_UNDEF(&delimiter);
264
265 ZEPHIR_MM_GROW();
266 zephir_fetch_params(1, 0, 1, &delimiter_param);
267
268 if (!delimiter_param) {
269 ZEPHIR_INIT_VAR(&delimiter);
270 ZVAL_STRING(&delimiter, "");
271 } else {
272 zephir_get_strval(&delimiter, delimiter_param);
273 }
274
275
276 zephir_update_property_zval(this_ptr, ZEND_STRL("pathDelimiter"), &delimiter);
277 RETURN_THIS();
278
279 }
280
281 /**
282 * Converts recursively the object to an array
283 *
284 *```php
285 * print_r(
286 * $config->toArray()
287 * );
288 *```
289 */
PHP_METHOD(Phalcon_Config,toArray)290 PHP_METHOD(Phalcon_Config, toArray) {
291
292 zend_bool _5$$3, _7$$5;
293 zend_string *_4;
294 zend_ulong _3;
295 zval results;
296 zval data, key, value, *_1, _2, _6$$4, _8$$6;
297 zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL;
298 zend_long ZEPHIR_LAST_CALL_STATUS;
299 zephir_fcall_cache_entry *_0 = NULL;
300 zval *this_ptr = getThis();
301
302 ZVAL_UNDEF(&data);
303 ZVAL_UNDEF(&key);
304 ZVAL_UNDEF(&value);
305 ZVAL_UNDEF(&_2);
306 ZVAL_UNDEF(&_6$$4);
307 ZVAL_UNDEF(&_8$$6);
308 ZVAL_UNDEF(&results);
309
310 ZEPHIR_MM_GROW();
311
312 ZEPHIR_INIT_VAR(&results);
313 array_init(&results);
314 ZEPHIR_CALL_PARENT(&data, phalcon_config_ce, getThis(), "toarray", &_0, 0);
315 zephir_check_call_status();
316 zephir_is_iterable(&data, 0, "phalcon/Config.zep", 179);
317 if (Z_TYPE_P(&data) == IS_ARRAY) {
318 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(&data), _3, _4, _1)
319 {
320 ZEPHIR_INIT_NVAR(&key);
321 if (_4 != NULL) {
322 ZVAL_STR_COPY(&key, _4);
323 } else {
324 ZVAL_LONG(&key, _3);
325 }
326 ZEPHIR_INIT_NVAR(&value);
327 ZVAL_COPY(&value, _1);
328 _5$$3 = Z_TYPE_P(&value) == IS_OBJECT;
329 if (_5$$3) {
330 _5$$3 = (zephir_method_exists_ex(&value, ZEND_STRL("toarray")) == SUCCESS);
331 }
332 if (_5$$3) {
333 ZEPHIR_CALL_METHOD(&_6$$4, &value, "toarray", NULL, 0);
334 zephir_check_call_status();
335 ZEPHIR_CPY_WRT(&value, &_6$$4);
336 }
337 zephir_array_update_zval(&results, &key, &value, PH_COPY | PH_SEPARATE);
338 } ZEND_HASH_FOREACH_END();
339 } else {
340 ZEPHIR_CALL_METHOD(NULL, &data, "rewind", NULL, 0);
341 zephir_check_call_status();
342 while (1) {
343 ZEPHIR_CALL_METHOD(&_2, &data, "valid", NULL, 0);
344 zephir_check_call_status();
345 if (!zend_is_true(&_2)) {
346 break;
347 }
348 ZEPHIR_CALL_METHOD(&key, &data, "key", NULL, 0);
349 zephir_check_call_status();
350 ZEPHIR_CALL_METHOD(&value, &data, "current", NULL, 0);
351 zephir_check_call_status();
352 _7$$5 = Z_TYPE_P(&value) == IS_OBJECT;
353 if (_7$$5) {
354 _7$$5 = (zephir_method_exists_ex(&value, ZEND_STRL("toarray")) == SUCCESS);
355 }
356 if (_7$$5) {
357 ZEPHIR_CALL_METHOD(&_8$$6, &value, "toarray", NULL, 0);
358 zephir_check_call_status();
359 ZEPHIR_CPY_WRT(&value, &_8$$6);
360 }
361 zephir_array_update_zval(&results, &key, &value, PH_COPY | PH_SEPARATE);
362 ZEPHIR_CALL_METHOD(NULL, &data, "next", NULL, 0);
363 zephir_check_call_status();
364 }
365 }
366 ZEPHIR_INIT_NVAR(&value);
367 ZEPHIR_INIT_NVAR(&key);
368 RETURN_CTOR(&results);
369
370 }
371
372 /**
373 * Performs a merge recursively
374 */
PHP_METHOD(Phalcon_Config,internalMerge)375 PHP_METHOD(Phalcon_Config, internalMerge) {
376
377 zend_bool _4$$3, _5$$3, _10$$7, _11$$7;
378 zend_string *_3;
379 zend_ulong _2;
380 zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL;
381 zephir_fcall_cache_entry *_9 = NULL;
382 zend_long ZEPHIR_LAST_CALL_STATUS;
383 zval *source_param = NULL, *target_param = NULL, key, value, *_0, _1, _6$$3, _7$$4, _8$$4, _12$$7, _13$$8, _14$$8;
384 zval source, target;
385 zval *this_ptr = getThis();
386
387 ZVAL_UNDEF(&source);
388 ZVAL_UNDEF(&target);
389 ZVAL_UNDEF(&key);
390 ZVAL_UNDEF(&value);
391 ZVAL_UNDEF(&_1);
392 ZVAL_UNDEF(&_6$$3);
393 ZVAL_UNDEF(&_7$$4);
394 ZVAL_UNDEF(&_8$$4);
395 ZVAL_UNDEF(&_12$$7);
396 ZVAL_UNDEF(&_13$$8);
397 ZVAL_UNDEF(&_14$$8);
398
399 ZEPHIR_MM_GROW();
400 zephir_fetch_params(1, 2, 0, &source_param, &target_param);
401
402 zephir_get_arrval(&source, source_param);
403 zephir_get_arrval(&target, target_param);
404
405
406 zephir_is_iterable(&target, 0, "phalcon/Config.zep", 199);
407 if (Z_TYPE_P(&target) == IS_ARRAY) {
408 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(&target), _2, _3, _0)
409 {
410 ZEPHIR_INIT_NVAR(&key);
411 if (_3 != NULL) {
412 ZVAL_STR_COPY(&key, _3);
413 } else {
414 ZVAL_LONG(&key, _2);
415 }
416 ZEPHIR_INIT_NVAR(&value);
417 ZVAL_COPY(&value, _0);
418 _4$$3 = Z_TYPE_P(&value) == IS_ARRAY;
419 if (_4$$3) {
420 _4$$3 = zephir_array_isset(&source, &key);
421 }
422 _5$$3 = _4$$3;
423 if (_5$$3) {
424 ZEPHIR_OBS_NVAR(&_6$$3);
425 zephir_array_fetch(&_6$$3, &source, &key, PH_NOISY, "phalcon/Config.zep", 190);
426 _5$$3 = Z_TYPE_P(&_6$$3) == IS_ARRAY;
427 }
428 if (_5$$3) {
429 zephir_array_fetch(&_8$$4, &source, &key, PH_NOISY | PH_READONLY, "phalcon/Config.zep", 191);
430 ZEPHIR_CALL_METHOD(&_7$$4, this_ptr, "internalmerge", &_9, 23, &_8$$4, &value);
431 zephir_check_call_status();
432 zephir_array_update_zval(&source, &key, &_7$$4, PH_COPY | PH_SEPARATE);
433 } else if (Z_TYPE_P(&key) == IS_LONG) {
434 zephir_array_append(&source, &value, PH_SEPARATE, "phalcon/Config.zep", 193);
435 } else {
436 zephir_array_update_zval(&source, &key, &value, PH_COPY | PH_SEPARATE);
437 }
438 } ZEND_HASH_FOREACH_END();
439 } else {
440 ZEPHIR_CALL_METHOD(NULL, &target, "rewind", NULL, 0);
441 zephir_check_call_status();
442 while (1) {
443 ZEPHIR_CALL_METHOD(&_1, &target, "valid", NULL, 0);
444 zephir_check_call_status();
445 if (!zend_is_true(&_1)) {
446 break;
447 }
448 ZEPHIR_CALL_METHOD(&key, &target, "key", NULL, 0);
449 zephir_check_call_status();
450 ZEPHIR_CALL_METHOD(&value, &target, "current", NULL, 0);
451 zephir_check_call_status();
452 _10$$7 = Z_TYPE_P(&value) == IS_ARRAY;
453 if (_10$$7) {
454 _10$$7 = zephir_array_isset(&source, &key);
455 }
456 _11$$7 = _10$$7;
457 if (_11$$7) {
458 ZEPHIR_OBS_NVAR(&_12$$7);
459 zephir_array_fetch(&_12$$7, &source, &key, PH_NOISY, "phalcon/Config.zep", 190);
460 _11$$7 = Z_TYPE_P(&_12$$7) == IS_ARRAY;
461 }
462 if (_11$$7) {
463 zephir_array_fetch(&_14$$8, &source, &key, PH_NOISY | PH_READONLY, "phalcon/Config.zep", 191);
464 ZEPHIR_CALL_METHOD(&_13$$8, this_ptr, "internalmerge", &_9, 23, &_14$$8, &value);
465 zephir_check_call_status();
466 zephir_array_update_zval(&source, &key, &_13$$8, PH_COPY | PH_SEPARATE);
467 } else if (Z_TYPE_P(&key) == IS_LONG) {
468 zephir_array_append(&source, &value, PH_SEPARATE, "phalcon/Config.zep", 193);
469 } else {
470 zephir_array_update_zval(&source, &key, &value, PH_COPY | PH_SEPARATE);
471 }
472 ZEPHIR_CALL_METHOD(NULL, &target, "next", NULL, 0);
473 zephir_check_call_status();
474 }
475 }
476 ZEPHIR_INIT_NVAR(&value);
477 ZEPHIR_INIT_NVAR(&key);
478 RETURN_CTOR(&source);
479
480 }
481
482 /**
483 * Sets the collection data
484 */
PHP_METHOD(Phalcon_Config,setData)485 PHP_METHOD(Phalcon_Config, setData) {
486
487 zval _0;
488 zephir_method_globals *ZEPHIR_METHOD_GLOBALS_PTR = NULL;
489 zend_long ZEPHIR_LAST_CALL_STATUS;
490 zval *element = NULL, element_sub, *value, value_sub, data, key, _1;
491 zval *this_ptr = getThis();
492
493 ZVAL_UNDEF(&element_sub);
494 ZVAL_UNDEF(&value_sub);
495 ZVAL_UNDEF(&data);
496 ZVAL_UNDEF(&key);
497 ZVAL_UNDEF(&_1);
498 ZVAL_UNDEF(&_0);
499
500 ZEPHIR_MM_GROW();
501 zephir_fetch_params(1, 2, 0, &element, &value);
502
503 ZEPHIR_SEPARATE_PARAM(element);
504
505
506 zephir_get_strval(&_0, element);
507 ZEPHIR_CPY_WRT(element, &_0);
508 zephir_read_property(&_1, this_ptr, ZEND_STRL("insensitive"), PH_NOISY_CC | PH_READONLY);
509 if (zephir_is_true(&_1)) {
510 ZEPHIR_CALL_FUNCTION(&key, "mb_strtolower", NULL, 25, element);
511 zephir_check_call_status();
512 } else {
513 ZEPHIR_CPY_WRT(&key, element);
514 }
515 zephir_update_property_array(this_ptr, SL("lowerKeys"), &key, element);
516 if (Z_TYPE_P(value) == IS_ARRAY) {
517 ZEPHIR_INIT_VAR(&data);
518 object_init_ex(&data, phalcon_config_ce);
519 ZEPHIR_CALL_METHOD(NULL, &data, "__construct", NULL, 22, value);
520 zephir_check_call_status();
521 } else {
522 ZEPHIR_CPY_WRT(&data, value);
523 }
524 zephir_update_property_array(this_ptr, SL("data"), element, &data);
525 ZEPHIR_MM_RESTORE();
526
527 }
528
529