1: <?php
2: /**
3: * This file is part of the PHPLucidFrame library.
4: *
5: * @package PHPLucidFrame\Core
6: * @since PHPLucidFrame v 1.0.0
7: * @copyright Copyright (c), PHPLucidFrame.
8: * @link http://phplucidframe.com
9: * @license http://www.opensource.org/licenses/mit-license.php MIT License
10: *
11: * This source file is subject to the MIT license that is bundled
12: * with this source code in the file LICENSE
13: */
14:
15: use LucidFrame\Core\SchemaManager;
16:
17: /**
18: * @ignore Flag for image resize to the fitted dimension to the given dimension
19: */
20: define('FILE_RESIZE_BOTH', 'both');
21: /**
22: * @ignore Flag for image resize to the given height, but width is aspect ratio of the height
23: */
24: define('FILE_RESIZE_HEIGHT', 'height');
25: /**
26: * @ignore Flag for image resize to the given width, but height is aspect ratio of the width
27: */
28: define('FILE_RESIZE_WIDTH', 'width');
29: /**
30: * @ignore File upload error flag for the failure of `move_uploaded_file()`
31: */
32: define('FILE_UPLOAD_ERR_MOVE', 100);
33: /**
34: * @ignore File upload error flag for the failure of image creation of GD functions
35: */
36: define('FILE_UPLOAD_ERR_IMAGE_CREATE', 101);
37: /**
38: * Query fetch types
39: */
40: define('LC_FETCH_ASSOC', 1);
41: define('LC_FETCH_ARRAY', 2);
42: define('LC_FETCH_OBJECT', 3);
43: /**
44: * Console command option types
45: */
46: define('LC_CONSOLE_OPTION_REQUIRED', 4);
47: define('LC_CONSOLE_OPTION_OPTIONAL', 5);
48: define('LC_CONSOLE_OPTION_NOVALUE', 6);
49:
50: /**
51: * @internal
52: * @ignore
53: * HTTP status code
54: */
55: $lc_httpStatusCode = 200;
56: /**
57: * @internal
58: * @ignore
59: * Site-wide warnings to be shown
60: */
61: $lc_sitewideWarnings = array();
62: /**
63: * @internal
64: * @ignore
65: * Auto load/unload configuration
66: */
67: $lc_autoload = array();
68: /**
69: * @internal
70: * @ignore
71: * Namespace which will later be available as a constant LC_NAMESPACE
72: */
73: $lc_namespace = '';
74: /**
75: * @internal
76: * @ignore
77: * The clean route without query string or without file name
78: */
79: $lc_cleanRoute = '';
80: /**
81: * @internal
82: * @ignore
83: * The global javascript variables that will be rentered in the <head> section
84: */
85: $lc_jsVars = array();
86: /**
87: * @internal
88: * @ignore
89: * The canonical URL for the current page
90: */
91: $lc_canonical = '';
92: /**
93: * @internal
94: * @ignore
95: * The array of configurations from parameter.env.inc
96: */
97: $lc_envParameters = null;
98: /**
99: * @internal
100: * @ignore
101: * Meta information for the current page
102: */
103: $_meta = array();
104: /**
105: * @internal
106: * @ignore
107: * @type array It contains the built and executed queries through out the script execution
108: */
109: global $db_builtQueries;
110: $db_builtQueries = array();
111: $db_printQuery = false;
112:
113: /***************************/
114: /* Internal functions here */
115: /***************************/
116:
117: /**
118: * @internal
119: * @ignore
120: * Prerequisite check
121: */
122: function __prerequisite()
123: {
124: if (version_compare(phpversion(), '5.3.0', '<')) {
125: die('PHPLucidFrame requires at least PHP 5.3.0. Your PHP installation is ' . phpversion() . '.');
126: }
127:
128: /**
129: * Check config.php
130: */
131: if (!file_exists(INC . 'config.php')) {
132: copy(INC . 'config.default.php', INC . 'config.php');
133: }
134:
135: if (PHP_SAPI !== 'cli') {
136: register_shutdown_function('__kernelShutdownHandler');
137: }
138: }
139:
140: /**
141: * @internal
142: * @ignore
143: * Dot notation access to multi-dimensional array
144: * Get the values by providing dot notation string key
145: * Set the values by providing dot notation string key
146: *
147: * @param string $key The string separated by dot (period)
148: * @param string $scope What scope in which the values will be stored - global or session
149: * @param mixed $value The optional value to set or updated
150: * @param boolean $serialize The value is to be serialized or not
151: *
152: * @return mixed The value assigned
153: */
154: function __dotNotationToArray($key, $scope = 'global', $value = '', $serialize = false)
155: {
156: if (empty($key)) {
157: return null;
158: }
159:
160: if (!in_array($scope, array('global', 'session')) && !is_array($scope)) {
161: return null;
162: }
163:
164: if (is_array($scope)) {
165: $input = &$scope;
166: }
167:
168: $type = count(func_get_args()) > 2 ? 'setter' : 'getter';
169: $keys = explode(".", $key);
170: # extract the first key
171: $firstKey = array_shift($keys);
172: # extract the last key
173: $lastKey = end($keys);
174: # No. of keys exclusive of the first key
175: $count = count($keys); # more than 0 if there is at least one dot
176: $justOneLevelKey = ($count === 0);
177:
178: if ($type == 'getter' && $justOneLevelKey) {
179: # just one-level key
180: if ($scope == 'session') {
181: $firstKey = S_PREFIX . $firstKey;
182: return (array_key_exists($firstKey, $_SESSION)) ? $_SESSION[$firstKey] : null;
183: } elseif ($scope == 'global') {
184: return (array_key_exists($firstKey, $GLOBALS)) ? $GLOBALS[$firstKey] : null;
185: } elseif (is_array($scope) && isset($input)) {
186: return (array_key_exists($firstKey, $input)) ? $input[$firstKey] : null;
187: }
188: }
189:
190: $current = null;
191: if ($scope == 'session') {
192: $firstKey = S_PREFIX . $firstKey;
193: if (!array_key_exists($firstKey, $_SESSION)) {
194: $_SESSION[$firstKey] = null;
195: }
196: $current = &$_SESSION[$firstKey];
197: } elseif ($scope == 'global') {
198: if (!array_key_exists($firstKey, $GLOBALS)) {
199: $GLOBALS[$firstKey] = null;
200: }
201: $current = &$GLOBALS[$firstKey];
202: } elseif (is_array($scope) && isset($input)) {
203: if (!array_key_exists($firstKey, $input)) {
204: $input[$firstKey] = null;
205: }
206: $current = &$input[$firstKey];
207: }
208:
209: $theLastHasValue = false;
210: if (($type == 'setter' && $count) || ($type == 'getter' && $count > 1)) {
211: # this will be skipped if no dot notation
212: foreach ($keys as $k) {
213: if ($k == $lastKey && isset($current[$lastKey])) {
214: if ($type === 'getter') {
215: return $current[$lastKey];
216: }
217:
218: $theLastHasValue = true;
219: if ($scope != 'session') {
220: # if the last-key has the value of not-array, create array and push the later values.
221: $current[$lastKey] = is_array($current[$k]) ? $current[$k] : array($current[$k]);
222: }
223: break;
224: }
225: if ($count && !isset($current[$k]) && !is_array($current)) {
226: $current = array($k => null);
227: }
228: $current = &$current[$k];
229: }
230: }
231: # Set the values if it is setter
232: if ($type == 'setter') {
233: if (is_array($current) && $theLastHasValue) {
234: # when $theLastHasValue, dot notation is given and it is array
235: $current[$lastKey] = ($serialize) ? serialize($value) : $value;
236: } else {
237: $current = ($serialize) ? serialize($value) : $value;
238: }
239: return $current;
240: } elseif ($type == 'getter') {
241: # Get the values if it is getter
242: return $count ? (isset($current[$lastKey]) ? $current[$lastKey] : null) : $current;
243: }
244: return null;
245: }
246:
247: /**
248: * @internal
249: * @ignore
250: * Load running environment settings
251: * Initialize the site language(s), error reporting
252: * Define two constants - REQUEST_URI and LC_NAMESPACE
253: *
254: * @return void
255: */
256: function __envLoader()
257: {
258: global $lc_languages;
259: global $lc_baseURL;
260: global $lc_sites;
261: global $lc_env;
262: global $lc_debugLevel;
263: global $lc_minifyHTML;
264: global $lc_timeZone;
265: global $lc_memoryLimit;
266: global $lc_maxExecTime;
267:
268: /**
269: * Don't escape quotes when reading files from the database, disk, etc.
270: */
271: ini_set('magic_quotes_runtime', '0');
272: /**
273: * Set the maximum amount of memory in bytes that a script is allowed to allocate.
274: * This helps prevent poorly written scripts for eating up all available memory on a server
275: */
276: ini_set('memory_limit', $lc_memoryLimit);
277: /**
278: * Set the maximum time in seconds a script is allowed to run before it is terminated by the parser.
279: * This helps prevent poorly written scripts from tying up the server. The default setting is 30.
280: */
281: ini_set('max_execution_time', $lc_maxExecTime);
282:
283: /**
284: * Default Time Zone
285: */
286: date_default_timezone_set($lc_timeZone);
287:
288: $lc_env = strtolower($lc_env);
289: if (!in_array($lc_env, __envList())) {
290: $lc_env = ENV_PROD;
291: }
292: if ($lc_env == ENV_PROD) {
293: error_reporting(0);
294: ini_set('display_errors', 0);
295: ini_set('display_startup_errors', 0);
296: } else {
297: $lc_minifyHTML = false;
298: switch($lc_debugLevel) {
299: case 1:
300: error_reporting(E_ERROR | E_PARSE);
301: ini_set('display_errors', 1);
302: ini_set('display_startup_errors', 0);
303: break;
304: case 2:
305: error_reporting(E_ERROR | E_PARSE | E_NOTICE | E_WARNING);
306: ini_set('display_errors', 1);
307: ini_set('display_startup_errors', 1);
308: break;
309: case 3:
310: error_reporting(E_ALL);
311: ini_set('display_errors', 1);
312: ini_set('display_startup_errors', 1);
313: break;
314: default:
315: error_reporting($lc_debugLevel);
316: ini_set('display_errors', 1);
317: ini_set('display_startup_errors', 1);
318: }
319: }
320:
321: if (empty($lc_languages) || !is_array($lc_languages)) {
322: $lc_languages = array('en' => 'English');
323: }
324:
325: $REQUEST_URI = $_SERVER['REQUEST_URI'];
326:
327: $requestURI = substr($REQUEST_URI, strpos($REQUEST_URI, '/'.$lc_baseURL) + strlen($lc_baseURL) + 1);
328: $requestURI = ltrim($requestURI, '/');
329: $request = explode('/', $requestURI);
330: $lc_namespace = $request[0];
331:
332: # Clean lang code in URL
333: if (array_key_exists($lc_namespace, $lc_languages)) {
334: array_shift($request);
335: $requestURI = ltrim(ltrim($requestURI, $lc_namespace), '/'); # clean the language code from URI
336: $lc_namespace = count($request) ? $request[0] : '';
337: }
338:
339: if (!(isset($lc_sites) && is_array($lc_sites) && array_key_exists($lc_namespace, $lc_sites))) {
340: $lc_namespace = '';
341: }
342:
343: # REQUEST_URI excluding the base URL
344: define('REQUEST_URI', trim($requestURI, '/'));
345: # Namespace according to the site directories
346: define('LC_NAMESPACE', $lc_namespace);
347:
348: unset($requestURI);
349: unset($request);
350: }
351:
352: /**
353: * @internal
354: * @ignore
355: * Read .secret and return the hash string which is the value for $lc_securitySecret
356: * @param string $file The optional file path
357: * @return string
358: */
359: function __secret($file = null)
360: {
361: if ($file !== null && is_file($file) && file_exists($file)) {
362: return trim(file_get_contents($file));
363: }
364:
365: $file = INC . '.secret';
366: return (is_file($file) && file_exists($file)) ? trim(file_get_contents($file)) : '';
367: }
368:
369: /**
370: * @internal
371: * @ignore
372: * Read and get the environment setting from .lcenv
373: * @return string
374: */
375: function __env()
376: {
377: $defaultEnv = ENV_DEV;
378:
379: $oldFile = ROOT . '.env';
380: if (is_file($oldFile) && file_exists($oldFile)) {
381: $defaultEnv = trim(file_get_contents($oldFile));
382: if (in_array($defaultEnv, __envList())) {
383: unlink($oldFile);
384: }
385: }
386:
387: $file = ROOT . FILE_ENV;
388: if (!(is_file($file) && file_exists($file))) {
389: file_put_contents($file, $defaultEnv);
390: }
391:
392: $env = trim(file_get_contents($file));
393: if (!in_array($env, __envList())) {
394: $env = ENV_PROD;
395: }
396:
397: return $env;
398: }
399:
400: /**
401: * @internal
402: * @ignore
403: * Return list of env name array
404: * @return array
405: */
406: function __envList()
407: {
408: return array(ENV_PROD, ENV_STAGING, ENV_DEV, ENV_TEST, 'dev', 'prod');
409: }
410:
411: /**
412: * @internal
413: * @ignore
414: *
415: * Custom error handler
416: *
417: * @param integer $code Error code
418: * @param string $message Error message
419: * @param string $file File name
420: * @param integer $line Error line number
421: * @return boolean
422: */
423: function __kernelErrorHandler($code, $message, $file, $line)
424: {
425: if (!(error_reporting() & $code)) {
426: // This error code is not included in error_reporting, so let it fall
427: // through to the standard PHP error handler
428: return false;
429: }
430:
431: $type = __kernelErrorTypes($code);
432: $trace = array_reverse(debug_backtrace());
433:
434: $status = _g('httpStatusCode');
435: if (empty($status) || $status == 200) {
436: $status = 500;
437: _g('httpStatusCode', $status);
438: }
439:
440: _header($status);
441:
442: include( _i('inc/tpl/exception.php') );
443: exit;
444: }
445:
446: /**
447: * @internal
448: * @ignore
449: *
450: * Custom shutdown handler
451: */
452: function __kernelShutdownHandler()
453: {
454: $error = error_get_last();
455:
456: if (is_array($error)) {
457: __kernelErrorHandler($error['type'], $error['message'], $error['file'], $error['line']);
458: }
459: }
460:
461: /**
462: * @internal
463: * @ignore
464: *
465: * Get friendly error type by code
466: * @param integer $code Error code
467: * @return string The friendly error type
468: */
469: function __kernelErrorTypes($code)
470: {
471: switch($code) {
472: case E_ERROR: # 1
473: return 'E_ERROR: Fatal error';
474:
475: case E_WARNING: # 2
476: return 'E_WARNING: Warning';
477:
478: case E_PARSE: # 4
479: return 'E_PARSE: Parse error';
480:
481: case E_NOTICE: # 8
482: return 'E_NOTICE: Notice';
483:
484: case E_CORE_ERROR: # 16
485: return 'E_CORE_ERROR: Fatal error';
486:
487: case E_CORE_WARNING: # 32
488: return 'E_CORE_WARNING: Warning';
489:
490: case E_COMPILE_ERROR: # 64
491: return 'E_COMPILE_ERROR: Fatal error';
492:
493: case E_COMPILE_WARNING: # 128
494: return 'E_COMPILE_WARNING: Warning';
495:
496: case E_USER_ERROR: # 256
497: return 'E_USER_ERROR: User-generated error';
498:
499: case E_USER_WARNING: # 512
500: return 'E_USER_WARNING: User-generated warning';
501:
502: case E_USER_NOTICE: # 1024
503: return 'E_USER_NOTICE: User-generated notice';
504:
505: case E_STRICT: # 2048
506: return 'E_STRICT: Information';
507:
508: case E_RECOVERABLE_ERROR: # 4096
509: return 'E_RECOVERABLE_ERROR: Catchable fatal error';
510:
511: case E_DEPRECATED: # 8192
512: return 'E_DEPRECATED: Deprecated warning';
513:
514: case E_USER_DEPRECATED: # 16384
515: return 'E_USER_DEPRECATED: User-generated deprecated warning';
516: }
517:
518: return 'E_ERROR, Error';
519: }
520:
521: /**
522: * Autoload helper
523: * @param string|array $modules The module file name
524: */
525: function __autoloadHelper($modules)
526: {
527: $modules = is_array($modules) ? $modules : array($modules);
528: $helperDirs = _baseDirs('helpers');
529:
530: foreach ($modules as $helper) {
531: foreach ($helperDirs as $dir) {
532: $moduleFile = $dir . $helper . '_helper.php';
533: if (is_file($moduleFile) && file_exists($moduleFile)) {
534: include($moduleFile);
535: }
536: }
537: }
538: }
539:
540: /**
541: * @internal
542: * @ignore
543: *
544: * Check if db is loadable (skip db initialization upon some CLI commands execution)
545: * @return bool
546: */
547: function __dbLoadable()
548: {
549: global $argv;
550:
551: return !(PHP_SAPI == 'cli' && $argv[0] === 'lucidframe' && in_array($argv[1], ['list', 'env', 'secret:generate']));
552: }
553:
554: /*************************/
555: /* Public functions here */
556: /*************************/
557:
558: /**
559: * Get schema definition file
560: * @param string $dbNamespace The namespace for the database
561: * @param boolean TRUE to look for the file in /db/build/; FALSE in /db/
562: * `TRUE` to look for the file in such priority
563: * 1. /db/build/schema.{namespace}.lock
564: * 2. /db/build/schema.lock (only for default)
565: * 3. /db/schema.{namespace}.php
566: * 4. /db/schema.php (only for default)
567: *
568: * `FALSE` to look in this priority
569: * 1. /db/schema.{namespace}.php
570: * 2. /db/schema.php (only for default)
571: *
572: * @return mixed
573: * array The schema definition
574: * null Incorrect schema definition
575: * boolean False when the file doesn't exist
576: */
577: function _schema($dbNamespace = 'default', $cache = false)
578: {
579: $files = array();
580: if ($cache) {
581: $files[] = SchemaManager::getSchemaLockFileName($dbNamespace);
582: $files[] = SchemaManager::getSchemaLockFileName();
583: }
584:
585: $files[] = DB."schema.{$dbNamespace}.php";
586: $files[] = DB."schema.php";
587:
588: foreach ($files as $f) {
589: if (is_file($f) && file_exists($f)) {
590: $file = $f;
591: if (pathinfo($file, PATHINFO_EXTENSION) == 'lock') {
592: return unserialize(file_get_contents($file));
593: } else {
594: $schema = include($file);
595: return is_array($schema) ? $schema : null;
596: }
597: }
598: }
599:
600: return false;
601: }
602:
603: /**
604: * File include helper
605: * Find files under the default directories inc/, js/, css/ according to the defined site directories $lc_sites
606: *
607: * @param $file string File name with directory path
608: * @param $recursive boolean True to find the file name until the site root
609: *
610: * @return string File name with absolute path if it is found, otherwise return an empty string
611: */
612: function _i($file, $recursive = true)
613: {
614: global $lc_baseURL;
615: global $lc_sites;
616: global $lc_languages;
617:
618: $ext = strtolower(substr($file, strrpos($file, '.')+1)); # get the file extension
619: if (in_array($ext, array('js', 'css'))) {
620: $appRoot = WEB_APP_ROOT;
621: $root = WEB_ROOT;
622: } else {
623: $appRoot = APP_ROOT;
624: $root = ROOT;
625: }
626:
627: if (!is_array($lc_languages)) {
628: $lc_languages = array('en' => 'English');
629: }
630:
631: $REQUEST_URI = $_SERVER['REQUEST_URI'];
632:
633: $requestURI = trim(ltrim($REQUEST_URI, '/'.$lc_baseURL)); # /base-dir/path/to/sub/dir to path/to/sub/dir
634: $request = explode('/', $requestURI);
635:
636: $needle = $request[0];
637: # Clean lang code in URL
638: if (array_key_exists($needle, $lc_languages)) {
639: array_shift($request);
640: }
641:
642: $folders = array();
643: if (LC_NAMESPACE == '') {
644: # Find in APP_ROOT -> ROOT
645: $folders = array(
646: APP_ROOT => $appRoot,
647: ROOT => $root
648: );
649: }
650:
651: if (isset($lc_sites) && is_array($lc_sites) && count($lc_sites)) {
652: if (array_key_exists(LC_NAMESPACE, $lc_sites)) {
653: # Find in SUB-DIR -> APP_ROOT -> ROOT
654: $folders = array(
655: APP_ROOT.$lc_sites[LC_NAMESPACE]._DS_ => $appRoot . $lc_sites[LC_NAMESPACE] . _DS_,
656: APP_ROOT => $appRoot,
657: ROOT => $root
658: );
659: }
660: }
661:
662: # $key is for file_exists()
663: # $value is for include() or <script> or <link>
664: foreach ($folders as $key => $value) {
665: if ($key === ROOT && substr($file, 0, 7) === 'helpers') {
666: $fileWithPath = LIB . $file;
667: $libHelper = true;
668: } else {
669: $fileWithPath = $key . $file;
670: $libHelper = false;
671: }
672:
673: if (is_file($fileWithPath) && file_exists($fileWithPath)) {
674: if ($libHelper === false) {
675: $fileWithPath = $value . $file;
676: }
677:
678: return $fileWithPath;
679: }
680:
681: if ($recursive == false) {
682: break;
683: }
684: }
685:
686: if (strstr($_SERVER['PHP_SELF'], APP_DIR)) {
687: if ($recursive == true) {
688: if ($root === ROOT && substr($file, 0, 7) === 'helpers') {
689: $file = LIB . $file;
690: } else {
691: $file = $root . $file;
692: }
693: } else {
694: $file = $root . $file;
695: }
696:
697: if (is_file($file) && file_exists($file)) {
698: return $file;
699: }
700: }
701:
702: return '';
703: }
704:
705: /**
706: * Get the host name or server name
707: */
708: function _host()
709: {
710: return !isset($_SERVER['HTTP_HOST']) ? isset($_SERVER['SERVER_NAME'])
711: ? $_SERVER['SERVER_NAME'] : php_uname('n') : $_SERVER['HTTP_HOST'];
712: }
713: /**
714: * Convenience method to get/set a config variable without global declaration within the calling function
715: *
716: * @param string $key The config variable name without prefix
717: * @param mixed $value The value to set to the config variable; if it is omitted, it is Getter method.
718: * @return mixed The value of the config variable
719: */
720: function _cfg($key, $value = '')
721: {
722: if (strrpos($key, 'lc_') === 0) {
723: $key = substr($key, 3);
724: }
725:
726: $key = 'lc_' . $key;
727:
728: return count(func_get_args()) == 2 ? __dotNotationToArray($key, 'global', $value) : __dotNotationToArray($key, 'global');
729: }
730:
731: /**
732: * Convenience method to get the value of the array config variable by its key
733: *
734: * @param string $name The config array variable name without prefix
735: * @param string $key The key of the config array of which value to be retrieved
736: * @return mixed|string|null The value of a single column of the config array variable
737: */
738: function _cfgOption($name, $key)
739: {
740: $config = _cfg($name);
741:
742: return isset($config[$key]) ? $config[$key] : null;
743: }
744:
745: /**
746: * Get the parameter value by name defined in `/inc/parameter/(development|production|staging|test).php`
747: * @param string $name The parameter name defined as key in `/inc/parameter/(development|production|staging|test).php`.
748: * The file development, production, staging or test will be determined according to the value from `.lcenv`.
749: * If `$name` is `env` (by default), it returns the current environment setting from `.lcenv`.
750: * @return mixed The value defined `/inc/parameter/(development|production|staging|test).php`
751: */
752: function _p($name = 'env')
753: {
754: if ($name == 'env') {
755: return __env();
756: }
757:
758: global $argv;
759:
760: if (PHP_SAPI == 'cli' && $argv[0] === 'lucidframe') {
761: # keep the current environment when `php lucidframe` is run
762: $env = _cfg('env');
763: } elseif (PHP_SAPI == 'cli' || stripos($_SERVER['REQUEST_URI'], 'tests/') !== false) {
764: # force change to "test" environment when run `php tests/tests.php` from CLI
765: # or when run `/tests/tests.php` from browser
766: $env = 'test';
767: _cfg('env', $env);
768: } else {
769: # neither CLI nor test
770: $env = _cfg('env');
771: }
772:
773: if (!in_array($env, __envList())) {
774: die(sprintf('Wrong environment configuration. Use "%s" or "%s" or "%s" or "%s".', ENV_DEV, ENV_STAGING, ENV_PROD, ENV_TEST));
775: }
776:
777: $param = include(INC . 'parameter/' . $env . '.php');
778:
779: return __dotNotationToArray($name, $param);
780: }
781:
782: /**
783: * Get the parameter value by name defined in `/inc/parameter/parameter.env.inc`
784: * @param string $name The parameter name in dot annotation format such as `prod.db.default.database`
785: * @param mixed $default The default value if the parameter name doesn't exist
786: * @return mixed The value defined in `/inc/parameter/parameter.env.inc`
787: */
788: function _env($name, $default = '')
789: {
790: global $lc_envParameters;
791:
792: if ($lc_envParameters === null) {
793: $file = INC . 'parameter/parameter.env.inc';
794: if (is_file($file) && file_exists($file)) {
795: $lc_envParameters = include($file);
796: } else {
797: return $default;
798: }
799: }
800:
801: $value = __dotNotationToArray($name, $lc_envParameters);
802:
803: return $value ?: $default;
804: }
805:
806: /**
807: * Get base URL with protocol
808: * @return bool|string
809: */
810: function _baseUrlWithProtocol()
811: {
812: if (isset($_SERVER['SERVER_PROTOCOL'])) {
813: $baseUrl = _cfg('baseURL');
814: $protocol = _cfg('ssl') ? 'https' : 'http';
815: $base = strtolower($protocol) . '://' . $_SERVER['HTTP_HOST'];
816: if ($baseUrl) {
817: $base .= '/' . $baseUrl;
818: }
819:
820: return $base;
821: }
822:
823: return false;
824: }
825:
826: /**
827: * Get base directory list by priority
828: * @param string $subDir The sub-directory name
829: * @return string[]
830: */
831: function _baseDirs($subDir = '')
832: {
833: $folders = array();
834:
835: $namespace = LC_NAMESPACE;
836: if (!empty($_GET['lc_namespace'])) {
837: $namespace = $_GET['lc_namespace'];
838: }
839:
840: $sites = _cfg('sites');
841: if (count($sites) && array_key_exists($namespace, $sites)) {
842: $folders[] = rtrim(APP_ROOT . $sites[$namespace] . _DS_ . $subDir, _DS_) . _DS_;
843: }
844:
845: $folders[] = rtrim(APP_ROOT . $subDir, _DS_) . _DS_;
846: $folders[] = rtrim(LIB . $subDir, _DS_) . _DS_;
847:
848: return $folders;
849: }
850:
851:
852: __prerequisite();
853: