Config.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. /**
  3. * Wrapper for configuration arrays. Multiple configuration readers can be
  4. * attached to allow loading configuration from files, database, etc.
  5. *
  6. * Configuration directives cascade across config sources in the same way that
  7. * files cascade across the filesystem.
  8. *
  9. * Directives from sources high in the sources list will override ones from those
  10. * below them.
  11. *
  12. * @package KO7
  13. * @category Configuration
  14. *
  15. * @copyright (c) 2007-2016 Kohana Team
  16. * @copyright (c) since 2016 Koseven Team
  17. * @license https://koseven.dev/LICENSE
  18. */
  19. class KO7_Config {
  20. // Configuration readers
  21. protected $_sources = [];
  22. // Array of config groups
  23. protected $_groups = [];
  24. /**
  25. * Attach a configuration reader. By default, the reader will be added as
  26. * the first used reader. However, if the reader should be used only when
  27. * all other readers fail, use `FALSE` for the second parameter.
  28. *
  29. * $config->attach($reader); // Try first
  30. * $config->attach($reader, FALSE); // Try last
  31. *
  32. * @param KO7_Config_Source $source instance
  33. * @param boolean $first add the reader as the first used object
  34. * @return $this
  35. */
  36. public function attach(KO7_Config_Source $source, $first = TRUE)
  37. {
  38. if ($first === TRUE)
  39. {
  40. // Place the log reader at the top of the stack
  41. array_unshift($this->_sources, $source);
  42. }
  43. else
  44. {
  45. // Place the reader at the bottom of the stack
  46. $this->_sources[] = $source;
  47. }
  48. // Clear any cached _groups
  49. $this->_groups = [];
  50. return $this;
  51. }
  52. /**
  53. * Detach a configuration reader.
  54. *
  55. * $config->detach($reader);
  56. *
  57. * @param KO7_Config_Source $source instance
  58. * @return $this
  59. */
  60. public function detach(KO7_Config_Source $source)
  61. {
  62. if (($key = array_search($source, $this->_sources)) !== FALSE)
  63. {
  64. // Remove the writer
  65. unset($this->_sources[$key]);
  66. }
  67. return $this;
  68. }
  69. /**
  70. * Load a configuration group. Searches all the config sources, merging all the
  71. * directives found into a single config group. Any changes made to the config
  72. * in this group will be mirrored across all writable sources.
  73. *
  74. * $array = $config->load($name);
  75. *
  76. * See [KO7_Config_Group] for more info
  77. *
  78. * @param string $group configuration group name
  79. * @return KO7_Config_Group
  80. * @throws KO7_Exception
  81. */
  82. public function load($group)
  83. {
  84. if ( ! count($this->_sources))
  85. {
  86. throw new KO7_Exception('No configuration sources attached');
  87. }
  88. if (empty($group))
  89. {
  90. throw new KO7_Exception("Need to specify a config group");
  91. }
  92. if ( ! is_string($group))
  93. {
  94. throw new KO7_Exception("Config group must be a string");
  95. }
  96. if (strpos($group, '.') !== FALSE)
  97. {
  98. // Split the config group and path
  99. list($group, $path) = explode('.', $group, 2);
  100. }
  101. if (isset($this->_groups[$group]))
  102. {
  103. if (isset($path))
  104. {
  105. return Arr::path($this->_groups[$group], $path, NULL, '.');
  106. }
  107. return $this->_groups[$group];
  108. }
  109. $config = [];
  110. // We search from the "lowest" source and work our way up
  111. $sources = array_reverse($this->_sources);
  112. foreach ($sources as $source)
  113. {
  114. if ($source instanceof KO7_Config_Reader)
  115. {
  116. if ($source_config = $source->load($group))
  117. {
  118. $config = Arr::merge($config, $source_config);
  119. }
  120. }
  121. }
  122. $this->_groups[$group] = new Config_Group($this, $group, $config);
  123. if (isset($path))
  124. {
  125. return Arr::path($config, $path, NULL, '.');
  126. }
  127. return $this->_groups[$group];
  128. }
  129. /**
  130. * Copy one configuration group to all of the other writers.
  131. *
  132. * $config->copy($name);
  133. *
  134. * @param string $group configuration group name
  135. * @return $this
  136. */
  137. public function copy($group)
  138. {
  139. // Load the configuration group
  140. $config = $this->load($group);
  141. foreach ($config->as_array() as $key => $value)
  142. {
  143. $this->_write_config($group, $key, $value);
  144. }
  145. return $this;
  146. }
  147. /**
  148. * Callback used by the config group to store changes made to configuration
  149. *
  150. * @param string $group Group name
  151. * @param string $key Variable name
  152. * @param mixed $value The new value
  153. * @return KO7_Config Chainable instance
  154. */
  155. public function _write_config($group, $key, $value)
  156. {
  157. foreach ($this->_sources as $source)
  158. {
  159. if ( ! ($source instanceof KO7_Config_Writer))
  160. {
  161. continue;
  162. }
  163. // Copy each value in the config
  164. $source->write($group, $key, $value);
  165. }
  166. return $this;
  167. }
  168. }