PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/wp-content/plugins/zencache/src/vendor/websharks/html-compressor/src/includes/classes/HookApi.php

https://gitlab.com/iamgraeme/royalmile
PHP | 337 lines | 158 code | 26 blank | 153 comment | 18 complexity | 51d9618d95c19324a3ca796c4215323e MD5 | raw file
  1. <?php
  2. namespace WebSharks\HtmlCompressor;
  3. /**
  4. * HTML Compressor (hook API).
  5. *
  6. * @since 150321 Adding hook API for plugins.
  7. *
  8. * @property-read $times Read-only access to times.
  9. * @property-read $data Read-only access to data.
  10. */
  11. class HookApi // For plugins.
  12. {
  13. /*
  14. * Protected Properties
  15. */
  16. /**
  17. * @type array An array of hooks.
  18. *
  19. * @since 150321 Adding hook API for plugins.
  20. */
  21. protected $hooks = array();
  22. /*
  23. * Public API Methods
  24. */
  25. /**
  26. * Class Constructor.
  27. *
  28. * @since 150321 Adding hook API for plugins.
  29. *
  30. * @api Constructor is available for public use.
  31. */
  32. public function __construct()
  33. {
  34. if (empty($GLOBALS[__NAMESPACE__.'_early_hooks'])) {
  35. return; // Nothing more to do here.
  36. }
  37. $GLOBALS[__NAMESPACE__.'_early_hooks'] = (array) $GLOBALS[__NAMESPACE__.'_early_hooks'];
  38. $early_hooks = &$GLOBALS[__NAMESPACE__.'_early_hooks'];
  39. foreach ($early_hooks as $_early_hook) {
  40. if (empty($_early_hook['hook'])) {
  41. continue; // Empty; bypass.
  42. }
  43. if (empty($_early_hook['function'])) {
  44. continue; // Empty; bypass.
  45. }
  46. if (!isset($_early_hook['priority'])) {
  47. $_early_hook['priority'] = 10;
  48. }
  49. if (!isset($_early_hook['accepted_args'])) {
  50. $_early_hook['accepted_args'] = 1;
  51. }
  52. $this->addHook(
  53. $_early_hook['hook'],
  54. $_early_hook['function'],
  55. $_early_hook['priority'],
  56. $_early_hook['accepted_args']
  57. );
  58. }
  59. unset($_early_hook); // Just a little housekeeping.
  60. $early_hooks = array(); // Empty; i.e., reset early hooks.
  61. }
  62. /**
  63. * Magic method for access to read-only properties.
  64. *
  65. * @since 150321 Adding hook API for plugins.
  66. *
  67. * @param string $property Propery by name.
  68. *
  69. * @throws \exception If `$property` does not exist for any reason.
  70. *
  71. * @return mixed Property value.
  72. *
  73. * @internal For internal magic use only.
  74. */
  75. public function __get($property)
  76. {
  77. $property = (string) $property;
  78. if (property_exists($this, $property)) {
  79. return $this->{$property};
  80. }
  81. throw new \Exception(sprintf('Undefined property: `%1$s`.', $property));
  82. }
  83. /**
  84. * Assigns an ID to each callable attached to a hook/filter.
  85. *
  86. * @since 150321 Adding hook API for plugins.
  87. *
  88. * @param string|callable|mixed $function A string or a callable.
  89. *
  90. * @throws \exception If the hook/function is invalid (i.e. it's not possible to generate an ID).
  91. *
  92. * @return string Hook ID for the given `$function`.
  93. */
  94. public function hookId($function)
  95. {
  96. if (is_string($function)) {
  97. return $function;
  98. }
  99. if (is_object($function)) {
  100. $function = array($function, '');
  101. } else {
  102. $function = (array) $function;
  103. }
  104. if (isset($function[0], $function[1])) {
  105. if (is_object($function[0])) {
  106. return spl_object_hash($function[0]).$function[1];
  107. } elseif (is_string($function[0])) {
  108. return $function[0].'::'.$function[1];
  109. }
  110. }
  111. throw new \Exception('Invalid hook.');
  112. }
  113. /**
  114. * Do we have a specific hook?
  115. *
  116. * @since 150821 Enhancing hook support.
  117. *
  118. * @param string $hook The name of a filter hook.
  119. *
  120. * @return bool True if actions/filters exist on this hook.
  121. */
  122. public function hasHook($hook)
  123. {
  124. $hook = (string) $hook;
  125. return $hook && !empty($this->hooks[$hook]);
  126. }
  127. /**
  128. * Do we have a specific action?
  129. *
  130. * @since 150821 Enhancing hook support.
  131. *
  132. * @return bool True if hook exists for this action.
  133. *
  134. * @see hasHook()
  135. */
  136. public function hasAction() // Simple `hasHook()` alias.
  137. {
  138. return call_user_func_array(array($this, 'hasHook'), func_get_args());
  139. }
  140. /**
  141. * Do we have a specific filter?
  142. *
  143. * @since 150821 Enhancing hook support.
  144. *
  145. * @return bool True if hook exists for this filter.
  146. *
  147. * @see hasHook()
  148. */
  149. public function hasFilter() // Simple `hasHook()` alias.
  150. {
  151. return call_user_func_array(array($this, 'hasHook'), func_get_args());
  152. }
  153. /**
  154. * Adds a new hook (works with both actions & filters).
  155. *
  156. * @since 150321 Adding hook API for plugins.
  157. *
  158. * @param string $hook The name of a hook to attach to.
  159. * @param string|callable|mixed $function A string or a callable.
  160. * @param int $priority Hook priority; defaults to `10`.
  161. * @param int $accepted_args Max number of args that should be passed to the `$function`.
  162. *
  163. * @return bool This always returns a `TRUE` value.
  164. */
  165. public function addHook($hook, $function, $priority = 10, $accepted_args = 1)
  166. {
  167. $hook = (string) $hook;
  168. $priority = (integer) $priority;
  169. $accepted_args = max(0, (integer) $accepted_args);
  170. $hook_id = $this->hookId($function);
  171. $this->hooks[$hook][$priority][$hook_id] = array(
  172. 'function' => $function,
  173. 'accepted_args' => (integer) $accepted_args,
  174. );
  175. return true; // Always returns true.
  176. }
  177. /**
  178. * Adds a new action hook.
  179. *
  180. * @since 150321 Adding hook API for plugins.
  181. *
  182. * @return bool This always returns a `TRUE` value.
  183. *
  184. * @see addHook()
  185. */
  186. public function addAction() // Simple `addHook()` alias.
  187. {
  188. return call_user_func_array(array($this, 'addHook'), func_get_args());
  189. }
  190. /**
  191. * Adds a new filter.
  192. *
  193. * @since 150321 Adding hook API for plugins.
  194. *
  195. * @return bool This always returns a `TRUE` value.
  196. *
  197. * @see addHook()
  198. */
  199. public function addFilter() // Simple `addHook()` alias.
  200. {
  201. return call_user_func_array(array($this, 'addHook'), func_get_args());
  202. }
  203. /**
  204. * Removes a hook (works with both actions & filters).
  205. *
  206. * @since 150321 Adding hook API for plugins.
  207. *
  208. * @param string $hook The name of a hook to remove.
  209. * @param string|callable|mixed $function A string or a callable.
  210. * @param int $priority Hook priority; defaults to `10`.
  211. *
  212. * @return bool `TRUE` if removed; else `FALSE` if not removed for any reason.
  213. */
  214. public function removeHook($hook, $function, $priority = 10)
  215. {
  216. $hook = (string) $hook;
  217. $priority = (integer) $priority;
  218. $hook_id = $this->hookId($function);
  219. if (!isset($this->hooks[$hook][$priority][$hook_id])) {
  220. return false; // Nothing to remove.
  221. }
  222. unset($this->hooks[$hook][$priority][$hook_id]);
  223. if (!$this->hooks[$hook][$priority]) {
  224. unset($this->hooks[$hook][$priority]);
  225. }
  226. return true; // Existed before it was removed.
  227. }
  228. /**
  229. * Removes an action.
  230. *
  231. * @since 150321 Adding hook API for plugins.
  232. *
  233. * @return bool `TRUE` if removed; else `FALSE` if not removed for any reason.
  234. *
  235. * @see removeHook()
  236. */
  237. public function removeAction() // Simple `removeHook()` alias.
  238. {
  239. return call_user_func_array(array($this, 'removeHook'), func_get_args());
  240. }
  241. /**
  242. * Removes a filter.
  243. *
  244. * @since 150321 Adding hook API for plugins.
  245. *
  246. * @return bool `TRUE` if removed; else `FALSE` if not removed for any reason.
  247. *
  248. * @see removeHook()
  249. */
  250. public function removeFilter() // Simple `removeHook()` alias.
  251. {
  252. return call_user_func_array(array($this, 'removeHook'), func_get_args());
  253. }
  254. /**
  255. * Runs any callables attached to an action.
  256. *
  257. * @since 150321 Adding hook API for plugins.
  258. *
  259. * @param string $hook The name of an action hook.
  260. */
  261. public function doAction($hook)
  262. {
  263. $hook = (string) $hook;
  264. if (empty($this->hooks[$hook])) {
  265. return; // No hooks.
  266. }
  267. $hook_actions = $this->hooks[$hook];
  268. $args = func_get_args();
  269. ksort($hook_actions);
  270. foreach ($hook_actions as $_hook_action) {
  271. foreach ($_hook_action as $_action) {
  272. if (!isset($_action['function'], $_action['accepted_args'])) {
  273. continue; // Not a valid filter in this case.
  274. }
  275. call_user_func_array($_action['function'], array_slice($args, 1, $_action['accepted_args']));
  276. }
  277. }
  278. unset($_hook_action, $_action); // Housekeeping.
  279. }
  280. /**
  281. * Runs any callables attached to a filter.
  282. *
  283. * @since 150321 Adding hook API for plugins.
  284. *
  285. * @param string $hook The name of a filter hook.
  286. * @param mixed $value The value to filter.
  287. *
  288. * @return mixed The filtered `$value`.
  289. */
  290. public function applyFilters($hook, $value)
  291. {
  292. $hook = (string) $hook;
  293. if (empty($this->hooks[$hook])) {
  294. return $value; // No hooks.
  295. }
  296. $hook_filters = $this->hooks[$hook];
  297. $args = func_get_args();
  298. ksort($hook_filters);
  299. foreach ($hook_filters as $_hook_filter) {
  300. foreach ($_hook_filter as $_filter) {
  301. if (!isset($_filter['function'], $_filter['accepted_args'])) {
  302. continue; // Not a valid filter in this case.
  303. }
  304. $args[1] = $value; // Continously update the argument `$value`.
  305. $value = call_user_func_array($_filter['function'], array_slice($args, 1, $_filter['accepted_args']));
  306. }
  307. }
  308. unset($_hook_filter, $_filter); // Housekeeping.
  309. return $value; // With applied filters.
  310. }
  311. }