media.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. <?php
  2. if ( ! defined( 'ABSPATH' ) ) {
  3. exit; // Exit if accessed directly
  4. }
  5. if ( ! class_exists( 'ACF_Media' ) ) :
  6. class ACF_Media {
  7. /**
  8. * Constructor.
  9. *
  10. * @date 23/06/12
  11. * @since 5.0.0
  12. *
  13. * @param void
  14. * @return void
  15. */
  16. public function __construct() {
  17. // Localize media strings.
  18. add_action( 'acf/enqueue_scripts', array( $this, 'enqueue_scripts' ) );
  19. // Save files uploaded from basic `$_FILE` field.
  20. add_action( 'acf/save_post', array( $this, 'save_files' ), 5, 1 );
  21. // Hook into Media Upload to run additional logic.
  22. add_filter( 'wp_handle_upload_prefilter', array( $this, 'handle_upload_prefilter' ), 10, 1 );
  23. // Hook into Media Modal Query to run additional logic.
  24. add_action( 'wp_ajax_query-attachments', array( $this, 'wp_ajax_query_attachments' ), -1 );
  25. }
  26. /**
  27. * Fires when ACF scrtips are enqueued.
  28. *
  29. * @date 27/4/18
  30. * @since 5.6.9
  31. *
  32. * @param void
  33. * @return void
  34. */
  35. public function enqueue_scripts() {
  36. if ( wp_script_is( 'acf-input' ) ) {
  37. acf_localize_text(
  38. array(
  39. 'Select.verb' => _x( 'Select', 'verb', 'acf' ),
  40. 'Edit.verb' => _x( 'Edit', 'verb', 'acf' ),
  41. 'Update.verb' => _x( 'Update', 'verb', 'acf' ),
  42. 'Uploaded to this post' => __( 'Uploaded to this post', 'acf' ),
  43. 'Expand Details' => __( 'Expand Details', 'acf' ),
  44. 'Collapse Details' => __( 'Collapse Details', 'acf' ),
  45. 'Restricted' => __( 'Restricted', 'acf' ),
  46. 'All images' => __( 'All images', 'acf' ),
  47. )
  48. );
  49. acf_localize_data(
  50. array(
  51. 'mimeTypeIcon' => wp_mime_type_icon(),
  52. 'mimeTypes' => get_allowed_mime_types(),
  53. )
  54. );
  55. }
  56. }
  57. /**
  58. * Uploads attachments found in the basic `$_FILES` array.
  59. *
  60. * @date 24/10/2014
  61. * @since 5.0.9
  62. *
  63. * @param string|int $post_id The post ID being saved.
  64. * @return void
  65. */
  66. public function save_files( $post_id = 0 ) {
  67. if ( isset( $_FILES['acf']['name'] ) ) {
  68. acf_upload_files();
  69. }
  70. }
  71. /**
  72. * Filters data for the current file being uploaded.
  73. *
  74. * @date 16/02/2015
  75. * @since 5.1.5
  76. *
  77. * @param array $file An array of data for a single file.
  78. * @return array
  79. */
  80. public function handle_upload_prefilter( $file ) {
  81. $field = $this->get_source_field();
  82. if ( ! $field ) {
  83. return $file;
  84. }
  85. // Validate the attachment and append any errors.
  86. $errors = acf_validate_attachment( $file, $field, 'upload' );
  87. /**
  88. * Filters the errors for a file before it is uploaded to WordPress.
  89. *
  90. * @date 16/02/2015
  91. * @since 5.1.5
  92. *
  93. * @param array $errors An array of errors.
  94. * @param array $file An array of data for a single file.
  95. * @param array $field The field array.
  96. */
  97. $errors = apply_filters( "acf/upload_prefilter/type={$field['type']}", $errors, $file, $field );
  98. $errors = apply_filters( "acf/upload_prefilter/name={$field['_name']}", $errors, $file, $field );
  99. $errors = apply_filters( "acf/upload_prefilter/key={$field['key']}", $errors, $file, $field );
  100. $errors = apply_filters( 'acf/upload_prefilter', $errors, $file, $field );
  101. // Append errors.
  102. if ( ! empty( $errors ) ) {
  103. $file['error'] = implode( "\n", $errors );
  104. }
  105. // Ensure newly uploaded image contains "preview_size" within the "size" data.
  106. add_filter( 'image_size_names_choose', array( $this, 'image_size_names_choose' ), 10, 1 );
  107. // Return.
  108. return $file;
  109. }
  110. /**
  111. * Returns the field responsible for the current Media query or upload context.
  112. *
  113. * @date 21/5/21
  114. * @since 5.9.7
  115. *
  116. * @param void
  117. * @return array| false.
  118. */
  119. private function get_source_field() {
  120. $field = false;
  121. // phpcs:disable WordPress.Security.NonceVerification.Missing -- Verified elsewhere.
  122. // Search for field key within available data.
  123. // Case 1) Media modal query.
  124. if ( isset( $_POST['query']['_acfuploader'] ) ) {
  125. $field_key = sanitize_text_field( $_POST['query']['_acfuploader'] );
  126. // Case 2) Media modal upload.
  127. } elseif ( isset( $_POST['_acfuploader'] ) ) {
  128. $field_key = sanitize_text_field( $_POST['_acfuploader'] );
  129. }
  130. // phpcs:enable WordPress.Security.NonceVerification.Missing
  131. // Attempt to load field.
  132. // Note the `acf_get_field()` function will return false if not found.
  133. if ( isset( $field_key ) ) {
  134. $field = acf_get_field( $field_key );
  135. }
  136. return $field;
  137. }
  138. /**
  139. * Fires during the WP Modal Query AJAX call.
  140. *
  141. * @date 26/06/2015
  142. * @since 5.2.3
  143. *
  144. * @param void
  145. * @return void
  146. */
  147. function wp_ajax_query_attachments() {
  148. if ( $this->get_source_field() ) {
  149. add_filter( 'wp_prepare_attachment_for_js', array( $this, 'wp_prepare_attachment_for_js' ), 10, 3 );
  150. add_filter( 'image_size_names_choose', array( $this, 'image_size_names_choose' ), 10, 1 );
  151. } else {
  152. add_filter( 'wp_prepare_attachment_for_js', array( $this, 'clear_acf_errors_for_core_requests' ), 5, 3 );
  153. }
  154. }
  155. /**
  156. * Append acf_errors false for non-acf media library calls to prevent media library caching.
  157. *
  158. * @date 31/8/21
  159. * @since 5.10.2
  160. *
  161. * @param array $response Array of prepared attachment data.
  162. * @param WP_Post $attachment Attachment object.
  163. * @param array|false $meta Array of attachment meta data, or false if there is none.
  164. * @return array
  165. */
  166. function clear_acf_errors_for_core_requests( $response, $attachment, $meta ) {
  167. $response['acf_errors'] = false;
  168. return $response;
  169. }
  170. /**
  171. * Filters attachment data as it is being prepared for JS.
  172. *
  173. * @date 21/5/21
  174. * @since 5.9.7
  175. *
  176. * @param array $response Array of prepared attachment data.
  177. * @param WP_Post $attachment Attachment object.
  178. * @param array|false $meta Array of attachment meta data, or false if there is none.
  179. * @return array
  180. */
  181. function wp_prepare_attachment_for_js( $response, $attachment, $meta ) {
  182. $field = $this->get_source_field();
  183. // Validate the attachment and append any errors.
  184. $errors = acf_validate_attachment( $response, $field, 'prepare' );
  185. $response['acf_errors'] = false;
  186. if ( ! empty( $errors ) ) {
  187. $response['acf_errors'] = implode( '<br />', $errors );
  188. }
  189. // Return.
  190. return $response;
  191. }
  192. /**
  193. * Filters the names and labels of the default image sizes.
  194. *
  195. * @date 21/5/21
  196. * @since 5.9.7
  197. *
  198. * @param array $size_names Array of image size labels keyed by their name.
  199. * @return array
  200. */
  201. function image_size_names_choose( $size_names ) {
  202. $field = $this->get_source_field();
  203. // Append "preview_size" setting to array of image sizes so WP will include in prepared JS data.
  204. if ( isset( $field['preview_size'] ) ) {
  205. $name = (string) $field['preview_size'];
  206. $size_names[ $name ] = $name; // Don't worry about size label, it is never used.
  207. }
  208. return $size_names;
  209. }
  210. }
  211. // Instantiate.
  212. acf_new_instance( 'ACF_Media' );
  213. endif; // class_exists check