Source: php/delivery/class-bypass.php

  1. <?php
  2. /**
  3. * Bypass class for the Cloudinary plugin.
  4. *
  5. * @package Cloudinary
  6. */
  7. namespace Cloudinary\Delivery;
  8. use Cloudinary\Plugin;
  9. use Cloudinary\Sync;
  10. use Cloudinary\Media;
  11. use Cloudinary\Settings;
  12. use WP_Post;
  13. /**
  14. * Class Bypass
  15. */
  16. class Bypass {
  17. /**
  18. * Holds the plugin instance.
  19. *
  20. * @var Plugin Instance of the global plugin.
  21. */
  22. public $plugin;
  23. /**
  24. * Holds the Media instance.
  25. *
  26. * @var Media
  27. */
  28. protected $media;
  29. /**
  30. * Holds the main settings.
  31. *
  32. * @var Settings
  33. */
  34. protected $settings;
  35. /**
  36. * Flag to determine if bypassing is allowed.
  37. *
  38. * @var bool
  39. */
  40. protected $enabled;
  41. /**
  42. * Holds the bypass action keys.
  43. */
  44. const BYPASS_KEYS = array(
  45. 'wp' => 'wp-delivery',
  46. 'cld' => 'cld-delivery',
  47. );
  48. /**
  49. * Bypass constructor.
  50. *
  51. * @param Plugin $plugin Global instance of the main plugin.
  52. */
  53. public function __construct( Plugin $plugin ) {
  54. $this->plugin = $plugin;
  55. // Hook into settings init, to get settings ans start hooks.
  56. add_action( 'cloudinary_init_settings', array( $this, 'init_settings' ) );
  57. }
  58. /**
  59. * Setup the filters and actions.
  60. */
  61. protected function setup_hooks() {
  62. // Start delivery bypasses if enabled.
  63. if ( $this->enabled ) {
  64. add_filter( 'handle_bulk_actions-upload', array( $this, 'handle_bulk_actions' ), 10, 3 );
  65. add_filter( 'media_row_actions', array( $this, 'add_inline_action' ), 10, 2 );
  66. add_filter( 'bulk_actions-upload', array( $this, 'add_bulk_actions' ) );
  67. add_action( 'attachment_submitbox_misc_actions', array( $this, 'delivery_actions' ), 11 );
  68. add_filter( 'wp_insert_attachment_data', array( $this, 'handle_save_attachment_delivery' ), 10, 2 );
  69. add_filter( 'cloudinary_can_sync_asset', array( $this, 'can_sync' ), 10, 2 );
  70. add_filter( 'cloudinary_cache_media_asset', array( $this, 'can_sync' ), 10, 2 );
  71. add_filter( 'cloudinary_media_status', array( $this, 'filter_status' ), 11, 2 );
  72. }
  73. }
  74. /**
  75. * Init the main settings.
  76. *
  77. * @param Plugin $plugin The plugin instance.
  78. */
  79. public function init_settings( $plugin ) {
  80. $this->media = $plugin->get_component( 'media' );
  81. $this->settings = $plugin->settings;
  82. $this->enabled = 'on' === $this->settings->get_value( 'auto_sync' ) && 'cld' !== $this->settings->get_value( 'offload' );
  83. $this->setup_hooks();
  84. }
  85. /**
  86. * Handles bulk actions for attachments.
  87. *
  88. * @param string $location The location to redirect after.
  89. * @param string $action The action to handle.
  90. * @param array $post_ids Post ID's to action.
  91. *
  92. * @return string
  93. */
  94. public function handle_bulk_actions( $location, $action, $post_ids ) {
  95. $delivery = null;
  96. switch ( $action ) {
  97. case self::BYPASS_KEYS['wp']:
  98. $delivery = true;
  99. break;
  100. case self::BYPASS_KEYS['cld']:
  101. $delivery = false;
  102. break;
  103. }
  104. if ( ! is_null( $delivery ) ) {
  105. foreach ( $post_ids as $id ) {
  106. if ( true === $delivery ) {
  107. $this->media->sync->managers['unsync']->unsync_attachment( $id );
  108. }
  109. $this->set_attachment_delivery( $id, $delivery );
  110. }
  111. /**
  112. * Action to flush delivery caches.
  113. *
  114. * @hook cloudinary_flush_cache
  115. * @since 3.0.0
  116. */
  117. do_action( 'cloudinary_flush_cache' );
  118. }
  119. return $location;
  120. }
  121. /**
  122. * Get the actions for delivery types.
  123. *
  124. * @param int|null $attachment_id The attachment ID to get action or generic action.
  125. *
  126. * @return array
  127. */
  128. protected function get_actions( $attachment_id = null ) {
  129. $actions = array();
  130. if (
  131. null === $attachment_id
  132. || $this->plugin->get_component( 'delivery' )->is_deliverable( $attachment_id )
  133. ) {
  134. $actions = array(
  135. self::BYPASS_KEYS['wp'] => __( 'Deliver from WordPress', 'cloudinary' ),
  136. );
  137. }
  138. return $actions;
  139. }
  140. /**
  141. * Add an inline action for manual sync.
  142. *
  143. * @param array $actions All actions.
  144. * @param \WP_Post $post The current post object.
  145. *
  146. * @return array
  147. */
  148. public function add_inline_action( $actions, $post ) {
  149. $bypassed = $this->is_bypassed( $post->ID );
  150. $action = $bypassed ? self::BYPASS_KEYS['cld'] : self::BYPASS_KEYS['wp'];
  151. $messages = $this->get_actions( $post->ID );
  152. if ( ! empty( $messages[ $action ] ) ) {
  153. // Set url for action handling.
  154. $action_url = add_query_arg(
  155. array(
  156. 'action' => $action,
  157. 'media[]' => $post->ID,
  158. '_wpnonce' => wp_create_nonce( 'bulk-media' ),
  159. ),
  160. 'upload.php'
  161. );
  162. // Add link th actions.
  163. $actions[ $action ] = sprintf(
  164. '<a href="%1$s" aria-label="%2$s">%2$s</a>',
  165. $action_url,
  166. $messages[ $action ]
  167. );
  168. }
  169. return $actions;
  170. }
  171. /**
  172. * Handle saving the deliver setting in single attachment edit.
  173. *
  174. * @param array $post_data The post array (unused).
  175. * @param array $data The submitted data to save.
  176. *
  177. * @return array
  178. */
  179. public function handle_save_attachment_delivery( $post_data, $data ) {
  180. $this->set_attachment_delivery( $data['ID'], isset( $data['attachment_delivery'] ) );
  181. return $post_data;
  182. }
  183. /**
  184. * Update an attachments delivery.
  185. *
  186. * @param int $attachment_id The attachment ID to update.
  187. * @param bool $bypass True to bypass and deliver from WordPress, false deliver from Cloudinary.
  188. */
  189. public function set_attachment_delivery( $attachment_id, $bypass ) {
  190. $this->media->update_post_meta( $attachment_id, Sync::META_KEYS['bypass'], $bypass );
  191. $this->media->sync->set_signature_item( $attachment_id, 'delivery' );
  192. }
  193. /**
  194. * Add bulk actions.
  195. *
  196. * @param array $actions Current actions to add to.
  197. *
  198. * @return array
  199. */
  200. public function add_bulk_actions( $actions ) {
  201. $cloudinary_actions = $this->get_actions();
  202. return array_merge( $cloudinary_actions, $actions );
  203. }
  204. /**
  205. * Filter states to indicate delivery when bypassed.
  206. *
  207. * @param array $status The current status.
  208. * @param int $attachment_id The attachment ID.
  209. *
  210. * @return array
  211. */
  212. public function filter_status( $status, $attachment_id ) {
  213. if ( ! empty( $status ) && $this->is_bypassed( $attachment_id ) ) {
  214. $actions = $this->get_actions( $attachment_id );
  215. $status = array(
  216. 'state' => 'info',
  217. 'note' => $actions[ self::BYPASS_KEYS['wp'] ],
  218. );
  219. }
  220. return $status;
  221. }
  222. /**
  223. * Adds the deliver checkbox on the single image edit screen.
  224. *
  225. * @param WP_Post $attachment The attachment post object.
  226. */
  227. public function delivery_actions( $attachment ) {
  228. $actions = $this->get_actions( $attachment->ID );
  229. if ( ! empty( $actions[ self::BYPASS_KEYS['wp'] ] ) ) :
  230. ?>
  231. <div class="misc-pub-section misc-pub-delivery">
  232. <label><input type="checkbox" name="attachment_delivery" value="true" <?php checked( true, $this->is_bypassed( $attachment->ID ) ); ?> />
  233. <?php echo esc_html( $actions[ self::BYPASS_KEYS['wp'] ] ); ?>
  234. </label>
  235. </div>
  236. <?php
  237. endif;
  238. }
  239. /**
  240. * Filter if the asset can be synced if it's bypassed.
  241. *
  242. * @param bool $can The current flag to sync.
  243. * @param int $attachment_id The attachment ID.
  244. *
  245. * @return bool
  246. */
  247. public function can_sync( $can, $attachment_id ) {
  248. if ( $this->is_bypassed( $attachment_id ) ) {
  249. $can = false;
  250. }
  251. return $can;
  252. }
  253. /**
  254. * Check if an attachment is bypassing Cloudinary.
  255. *
  256. * @param int $attachment_id The attachment ID.
  257. *
  258. * @return bool
  259. */
  260. public function is_bypassed( $attachment_id ) {
  261. return (bool) $this->media->get_post_meta( $attachment_id, Sync::META_KEYS['bypass'], true );
  262. }
  263. }