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.9KB

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