Reader.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. <?php
  2. /**
  3. * File-based configuration reader. Multiple configuration directories can be
  4. * used by attaching multiple instances of this class to [KO7_Config].
  5. *
  6. * @package KO7
  7. * @category Configuration
  8. *
  9. * @copyright (c) 2007-2016 Kohana Team
  10. * @copyright (c) since 2020 Koseven Team
  11. * @license https://koseven.dev/LICENSE
  12. */
  13. abstract class KO7_Config_File_Reader implements KO7_Config_Reader {
  14. /**
  15. * @var string The directory where config files are located
  16. */
  17. protected $_directory = 'config';
  18. /**
  19. * @var array Cached configurations
  20. */
  21. protected static $_cache = [];
  22. /**
  23. * Creates a new file reader using the given directory as a config source.
  24. *
  25. * @param string $directory Configuration directory to search
  26. */
  27. public function __construct($directory = null)
  28. {
  29. if ($directory !== null)
  30. {
  31. $this->_directory = trim($directory, '\/');
  32. }
  33. }
  34. /**
  35. * Load and merge all of the configuration files in this group.
  36. *
  37. * @param string $group Configuration group name
  38. * @return array Configuration
  39. * @throws KO7_Exception YAML extension/package not loaded
  40. */
  41. public function load($group): array
  42. {
  43. // @codeCoverageIgnoreStart
  44. // Check cache
  45. $cache_key = $this->_directory.' '.$group;
  46. if (KO7::$caching && isset(static::$_cache[$cache_key]))
  47. {
  48. return static::$_cache[$cache_key];
  49. }
  50. // @codeCoverageIgnoreEnd
  51. if (KO7::$profiling)
  52. {
  53. // Start a new benchmark
  54. $benchmark = Profiler::start('Config ('.$this->_directory.')', __FUNCTION__);
  55. }
  56. $config = [];
  57. // Loop through paths. Notice: reverse paths, so system and modules files get overwritten by application files
  58. foreach (array_reverse(KO7::include_paths()) as $path)
  59. {
  60. // Build path
  61. $file = $path.$this->_directory.DIRECTORY_SEPARATOR.$group;
  62. $value = false;
  63. // Try ".php", ".json" and ".yaml" extensions and parse contents with PHP support
  64. if (file_exists($file.'.php'))
  65. {
  66. $value = KO7::load($file.'.php');
  67. }
  68. elseif (file_exists($file.'.json'))
  69. {
  70. $value = json_decode($this->read_from_ob($file.'.json'), true);
  71. }
  72. elseif (file_exists($file.'.yaml'))
  73. {
  74. // @codeCoverageIgnoreStart
  75. if ( ! function_exists('yaml_parse'))
  76. {
  77. throw new KO7_Exception('YAML extension/package is required in order to parse YAML files');
  78. }
  79. // @codeCoverageIgnoreEnd
  80. $value = yaml_parse($this->read_from_ob($file.'.yaml'));
  81. }
  82. // Merge configurations
  83. if (is_iterable($value))
  84. {
  85. $config = Arr::merge($config, $value);
  86. }
  87. }
  88. // @codeCoverageIgnoreStart
  89. if (KO7::$caching)
  90. {
  91. static::$_cache[$cache_key] = $config;
  92. }
  93. // @codeCoverageIgnoreEnd
  94. if (isset($benchmark))
  95. {
  96. // Stop the benchmark
  97. Profiler::stop($benchmark);
  98. }
  99. return $config;
  100. }
  101. /**
  102. * Read contents from file with output buffering. Used to support `<?php` `?>` tags and code inside configurations.
  103. *
  104. * @param string $path Path to File
  105. * @return string
  106. * @codeCoverageIgnore
  107. */
  108. protected function read_from_ob(string $path): string
  109. {
  110. // Start output buffer
  111. ob_start();
  112. KO7::load($path);
  113. // Return contents of buffer
  114. return (string) ob_get_clean();
  115. }
  116. }