/wp-content/plugins/the-events-calendar/common/src/Tribe/Service_Providers/Processes.php

https://github.com/livinglab/openlab · PHP · 278 lines · 116 code · 37 blank · 125 comment · 19 complexity · f66e669378d620ceb0d68ec33f452b98 MD5 · raw file

  1. <?php
  2. /**
  3. * Class Tribe__Service_Providers__Processes
  4. *
  5. * @since 4.7.12
  6. *
  7. * Handles the registration and creation of our async process handlers.
  8. */
  9. class Tribe__Service_Providers__Processes extends tad_DI52_ServiceProvider {
  10. /**
  11. * An array of all handler actions registered in this HTTP request.
  12. *
  13. * This is an array cache with a request lifetime by design.
  14. *
  15. * @var array
  16. */
  17. protected $handler_actions;
  18. /**
  19. * An array of all queue actions registered in this HTTP request.
  20. *
  21. * This is an array cache with a request lifetime by design.
  22. *
  23. * @var array
  24. */
  25. protected $queue_actions;
  26. /**
  27. * An instance of the context abstraction layer.
  28. *
  29. * @var Tribe__Context
  30. */
  31. protected $context;
  32. /**
  33. * Hooks the filters and binds the implementations needed to handle processes.
  34. */
  35. public function register() {
  36. $this->context = tribe( 'context' );
  37. // If the context of this request is neither AJAX or Cron bail.
  38. if ( ! ( $this->context->doing_ajax() || $this->context->doing_cron() ) ) {
  39. return;
  40. }
  41. /** @var Tribe__Feature_Detection $feature_detection */
  42. $feature_detection = tribe( 'feature-detection' );
  43. $action = tribe_get_request_var( 'action', false );
  44. $testing_for_async_support = $action === $this->get_handler_action( 'Tribe__Process__Tester' );
  45. // Dispatch in async mode if testing for it (w/o re-checking) or if async processes are supported.
  46. if ( $testing_for_async_support || $feature_detection->supports_async_process() ) {
  47. $this->dispatch_async();
  48. return;
  49. }
  50. $this->dispatch_cron();
  51. }
  52. /**
  53. * Hooks the correct handler for the action.
  54. *
  55. * @since 4.7.12
  56. *
  57. * @param string $action
  58. */
  59. protected function hook_handler_for( $action ) {
  60. if ( null === $this->handler_actions ) {
  61. $handlers = [
  62. 'Tribe__Process__Tester',
  63. 'Tribe__Process__Post_Thumbnail_Setter',
  64. ];
  65. /**
  66. * Filters the process handler classes the Service Provider should handle.
  67. *
  68. * All handlers should extend the `Tribe__Process__Handler` base class.
  69. *
  70. * @since 4.7.12
  71. *
  72. * @param array $handlers
  73. */
  74. $handlers = array_unique( apply_filters( 'tribe_process_handlers', $handlers ) );
  75. $this->handler_actions = array_combine(
  76. $handlers,
  77. array_map( [ $this, 'get_handler_action' ], $handlers )
  78. );
  79. }
  80. $array_search = array_search( $action, $this->handler_actions, true );
  81. if ( false === $handler_class = $array_search ) {
  82. return;
  83. }
  84. // the handler will handle the hooking
  85. $this->container->make( $handler_class );
  86. }
  87. /**
  88. * Hooks the correct queue for the action.
  89. *
  90. * @since 4.7.12
  91. *
  92. * @param string $action
  93. */
  94. protected function hook_queue_for( $action ) {
  95. if ( null === $this->queue_actions ) {
  96. $queues = [
  97. 'Tribe__Promise',
  98. ];
  99. /**
  100. * Filters the queue processing classes the Service Provider should handle.
  101. *
  102. * All queues should extend the `Tribe__Process__Queue` base class.
  103. *
  104. * @since 4.7.12
  105. *
  106. * @param array $queues An array of class names, each extending the `Tribe__Process__Queue` base class.
  107. */
  108. $queues = array_unique( apply_filters( 'tribe_process_queues', $queues ) );
  109. $all_queues_actions = array_combine(
  110. $queues,
  111. array_map( [ $this, 'get_queue_action' ], $queues )
  112. );
  113. }
  114. $array_search = array_search( $action, $all_queues_actions, true );
  115. if ( false === $queue_class = $array_search ) {
  116. return;
  117. }
  118. // the queue will handle the hooking
  119. $this->container->make( $queue_class );
  120. }
  121. /**
  122. * Returns the action for the handler.
  123. *
  124. * @since 4.7.12
  125. *
  126. * @param string $handler_class
  127. *
  128. * @return string
  129. */
  130. protected function get_handler_action( $handler_class ) {
  131. /** @var Tribe__Process__Handler handler_class */
  132. return 'tribe_process_' . call_user_func( [ $handler_class, 'action' ] );
  133. }
  134. /**
  135. * Returns the action for the queue.
  136. *
  137. * @since 4.7.12
  138. *
  139. * @param string $queue_class
  140. *
  141. * @return string
  142. */
  143. protected function get_queue_action( $queue_class ) {
  144. /** @var Tribe__Process__Queue queue_class */
  145. return 'tribe_queue_' . call_user_func( [ $queue_class, 'action' ] );
  146. }
  147. /**
  148. * Dispatches the request, if in AJAX context of a valid queue processing request,
  149. * to the correct handler.
  150. *
  151. * @since 4.7.23
  152. */
  153. protected function dispatch_async() {
  154. if ( ! (
  155. $this->context->doing_ajax()
  156. && false !== $action = tribe_get_request_var( 'action', false )
  157. ) ) {
  158. return;
  159. }
  160. $this->hook_handler_for_action( $action );
  161. }
  162. /**
  163. * Start the process handlers if in the context of a cron process and
  164. * if any is registered.
  165. *
  166. * @since 4.7.23
  167. */
  168. protected function dispatch_cron() {
  169. if ( ! $this->context->doing_cron() ) {
  170. return;
  171. }
  172. /*
  173. * Here we parse the scheduled cron events to get those scheduled by a queue
  174. * or process handler.
  175. */
  176. $hooks = $this->get_scheduled_like( [ 'tribe_process_', 'tribe_queue_' ] );
  177. if ( empty( $hooks ) ) {
  178. return;
  179. }
  180. foreach ( $hooks as $action ) {
  181. /*
  182. * Building the queue or process handler for an action will make it
  183. * so the handler, in its `__construct` method, will hook on the action
  184. * triggered by its cron event.
  185. */
  186. $this->hook_handler_for_action( $action );
  187. }
  188. }
  189. /**
  190. * Hooks the correct queue or process handler for an action if any.
  191. *
  192. * @since 4.7.23
  193. *
  194. * @param string $action The action to hook the handler, or queue, for.
  195. */
  196. protected function hook_handler_for_action( $action ) {
  197. if (
  198. 0 !== strpos( $action, 'tribe_process_' )
  199. && 0 !== strpos( $action, 'tribe_queue_' )
  200. ) {
  201. return;
  202. }
  203. if ( 0 === strpos( $action, 'tribe_process_' ) ) {
  204. $this->hook_handler_for( $action );
  205. } else {
  206. $this->hook_queue_for( $action );
  207. }
  208. }
  209. /**
  210. * Parses the `cron` array to return the hook names starting with a pattern.
  211. *
  212. * @since 4.7.23
  213. *
  214. * @param string|array $needles A pattern to look for or an array of patterns; if
  215. * this is an array then a match will be an hook that
  216. * matches at least one pattern.
  217. *
  218. * @return array An array of hook names matching the pattern.
  219. */
  220. protected function get_scheduled_like( $needles ) {
  221. $cron = get_option( 'cron', false );
  222. if ( empty( $cron ) ) {
  223. return [];
  224. }
  225. $needles = (array) $needles;
  226. $matching = [];
  227. foreach ( $cron as $time ) {
  228. if ( ! is_array( $time ) ) {
  229. continue;
  230. }
  231. foreach ( $time as $hook => $entry ) {
  232. foreach ( $needles as $needle ) {
  233. if ( false !== strpos( $hook, $needle ) ) {
  234. $matching[] = $hook;
  235. }
  236. }
  237. }
  238. }
  239. return $matching;
  240. }
  241. }