BioTorrents.de’s version of Gazelle
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

env.class.php 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. <?php
  2. /**
  3. * ENV
  4. *
  5. * The PHP singleton is considered bad design for nebulous reasons,
  6. * but for securely loading a site config it does exactly what we need:
  7. *
  8. * - Ensure that only one instance of itself can ever exist
  9. * - Load the instance everywhere we need to do $ENV->VALUE
  10. * - No memory penalty because of multiple $ENV instances
  11. * - Static values in classes/config.php are immutable
  12. * - Site configs don't exist in the constants table
  13. * - Separate public and private config values
  14. *
  15. * @see https://stackoverflow.com/a/3724689
  16. * @see https://phpenthusiast.com/blog/the-singleton-design-pattern-in-php
  17. */
  18. class ENV
  19. {
  20. # Disinstantiates itself
  21. private static $ENV = null;
  22. # Config options receptacles
  23. private static $Priv = []; # Passwords, app keys, database, etc.
  24. private static $Pub = []; # Site meta, options, resources, etc.
  25. /**
  26. * __functions()
  27. */
  28. # Prevents outside construction
  29. private function __construct()
  30. {
  31. # Would be expensive, e.g.,
  32. # $ENV = new ENV();
  33. return;
  34. }
  35. # Prevents multiple instances
  36. public function __clone()
  37. {
  38. return trigger_error(
  39. 'clone() not allowed',
  40. E_USER_ERROR
  41. );
  42. }
  43. # $this->key returns public->key
  44. public function __get($key)
  45. {
  46. return isset(self::$Pub[$key])
  47. ? self::$Pub[$key]
  48. : false;
  49. }
  50. # isset()
  51. public function __isset($key)
  52. {
  53. return isset(self::$Pub[$key]);
  54. }
  55. /**
  56. * Gets n' Sets
  57. */
  58. # Calls its self's creation or returns itself
  59. public static function go()
  60. {
  61. return (self::$ENV === null)
  62. ? self::$ENV = new ENV()
  63. : self::$ENV;
  64. }
  65. # get
  66. public static function getPriv($key)
  67. {
  68. return isset(self::$Priv[$key])
  69. ? self::$Priv[$key]
  70. : false;
  71. }
  72. public static function getPub($key)
  73. {
  74. return isset(self::$Pub[$key])
  75. ? self::$Pub[$key]
  76. : false;
  77. }
  78. # set
  79. public static function setPriv($key, $value)
  80. {
  81. return self::$Priv[$key] = $value;
  82. }
  83. public static function setPub($key, $value)
  84. {
  85. return self::$Pub[$key] = $value;
  86. }
  87. /**
  88. * toArray
  89. * @see https://ben.lobaugh.net/blog/567/php-recursively-convert-an-object-to-an-array
  90. */
  91. public function toArray($obj)
  92. {
  93. if (is_object($obj)) {
  94. $obj = (array) $obj;
  95. }
  96. if (is_array($obj)) {
  97. $new = array();
  98. foreach ($obj as $key => $value) {
  99. $new[$key] = $this->toArray($value);
  100. }
  101. } else {
  102. $new = $obj;
  103. }
  104. return $new;
  105. }
  106. /**
  107. * fromJson
  108. *
  109. * @param string $JSON Valid JavaScript object string
  110. * @return RecursiveArrayObject Not stdClass as in json_decode()
  111. */
  112. public function fromJson($str)
  113. {
  114. if (!is_string($str) || is_empty($str)) {
  115. error('$ENV->fromJson() expects a string.');
  116. }
  117. # Decode to array and construct RAO
  118. return $RAO = new RecursiveArrayObject(
  119. json_decode($str, true)
  120. );
  121. }
  122. /**
  123. * dedupe
  124. *
  125. * Takes a collection (usually an array) of various jumbled $ENV slices.
  126. * Returns a once-deduplicated RecursiveArrayObject with original nesting intact.
  127. * Simple and handy if you need to populate a form with arbitrary collections of metadata.
  128. */
  129. public function dedupe($obj)
  130. {
  131. if (is_object($obj)) {
  132. $obj = (array) $obj;
  133. }
  134. return $RAO = new RecursiveArrayObject(
  135. array_unique($this->toArray($obj))
  136. );
  137. }
  138. /**
  139. * map
  140. *
  141. * Simple array_map() object wrapper.
  142. * Maps a callback (or default) to an object.
  143. *
  144. * Example output:
  145. * $Hashes = $ENV->map('md5', $ENV->CATS->SEQ);
  146. *
  147. * var_dump($Hashes);
  148. * object(RecursiveArrayObject)#324 (1) {
  149. * ["storage":"ArrayObject":private]=>
  150. * array(6) {
  151. * ["ID"]=>
  152. * string(32) "28c8edde3d61a0411511d3b1866f0636"
  153. * ["Name"]=>
  154. * string(32) "fe83ccb5dc96dbc0658b3c4672c7d5fe"
  155. * ["Icon"]=>
  156. * string(32) "52963afccc006d2bce3c890ad9e8f73a"
  157. * ["Platforms"]=>
  158. * string(32) "d41d8cd98f00b204e9800998ecf8427e"
  159. * ["Formats"]=>
  160. * string(32) "d41d8cd98f00b204e9800998ecf8427e"
  161. * ["Description"]=>
  162. * string(32) "ca6628e8c13411c800d1d9d0eaccd849"
  163. * }
  164. * }
  165. *
  166. * var_dump($Hashes->Icon);
  167. * string(32) "52963afccc006d2bce3c890ad9e8f73a"
  168. *
  169. * @param string $fn Callback function
  170. * @param object $obj Object to operate on
  171. * @return object $RAO Mapped RecursiveArrayObject
  172. */
  173. public function map($fn = '', $obj = null)
  174. {
  175. # Set a default function if desired
  176. if (empty($fn) && !is_object($fn)) {
  177. $fn = 'array_filter';
  178. }
  179. # Quick sanity check
  180. if ($fn === 'array_map') {
  181. error("map() can't invoke the function it wraps.");
  182. }
  183. /**
  184. * $fn not a closure
  185. *
  186. * var_dump(
  187. * gettype(
  188. * (function() { return; })
  189. * ));
  190. * string(6) "object"
  191. */
  192. if (is_string($fn) && !is_object($fn)) {
  193. $fn = trim(strtok($fn, ' '));
  194. }
  195. # Map the sanitized function name
  196. # to a mapped array conversion
  197. return $RAO = new RecursiveArrayObject(
  198. array_map(
  199. $fn,
  200. array_map(
  201. $fn,
  202. $this->toArray($obj)
  203. )
  204. )
  205. );
  206. }
  207. }
  208. /**
  209. * @author: etconsilium@github
  210. * @license: BSDLv2
  211. * @see https://github.com/etconsilium/php-recursive-array-object
  212. */
  213. class RecursiveArrayObject extends \ArrayObject
  214. {
  215. /**
  216. * __construct
  217. */
  218. public function __construct($input = null, $flags = self::ARRAY_AS_PROPS, $iterator_class = "ArrayIterator")
  219. {
  220. foreach ($input as $key => $value) {
  221. $this->__set($key, $value);
  222. }
  223. return $this;
  224. }
  225. /**
  226. * __set
  227. */
  228. public function __set($name, $value)
  229. {
  230. if (is_array($value) || is_object($value)) {
  231. $this->offsetSet($name, (new self($value)));
  232. } else {
  233. $this->offsetSet($name, $value);
  234. }
  235. }
  236. /**
  237. * __get
  238. */
  239. public function __get($name)
  240. {
  241. if ($this->offsetExists($name)) {
  242. return $this->offsetGet($name);
  243. } elseif (array_key_exists($name, $this)) {
  244. return $this[$name];
  245. } else {
  246. throw new \InvalidArgumentException(sprintf('$this have not prop `%s`', $name));
  247. }
  248. }
  249. /**
  250. * __isset
  251. */
  252. public function __isset($name)
  253. {
  254. return array_key_exists($name, $this);
  255. }
  256. /**
  257. * __unset
  258. */
  259. public function __unset($name)
  260. {
  261. unset($this[$name]);
  262. }
  263. }