/wp-admin/includes/media.php

  1. <?php 
  2. /** 
  3. * WordPress Administration Media API. 
  4. * 
  5. * @package WordPress 
  6. * @subpackage Administration 
  7. */ 
  8.  
  9. /** 
  10. * Defines the default media upload tabs 
  11. * 
  12. * @since 2.5.0 
  13. * 
  14. * @return array default tabs 
  15. */ 
  16. function media_upload_tabs() { 
  17. $_default_tabs = array( 
  18. 'type' => __('From Computer'), // handler action suffix => tab text 
  19. 'type_url' => __('From URL'),  
  20. 'gallery' => __('Gallery'),  
  21. 'library' => __('Media Library') 
  22. ); 
  23.  
  24. /** 
  25. * Filters the available tabs in the legacy (pre-3.5.0) media popup. 
  26. * 
  27. * @since 2.5.0 
  28. * 
  29. * @param array $_default_tabs An array of media tabs. 
  30. */ 
  31. return apply_filters( 'media_upload_tabs', $_default_tabs ); 
  32.  
  33. /** 
  34. * Adds the gallery tab back to the tabs array if post has image attachments 
  35. * 
  36. * @since 2.5.0 
  37. * 
  38. * @global wpdb $wpdb WordPress database abstraction object. 
  39. * 
  40. * @param array $tabs 
  41. * @return array $tabs with gallery if post has image attachment 
  42. */ 
  43. function update_gallery_tab($tabs) { 
  44. global $wpdb; 
  45.  
  46. if ( !isset($_REQUEST['post_id']) ) { 
  47. unset($tabs['gallery']); 
  48. return $tabs; 
  49.  
  50. $post_id = intval($_REQUEST['post_id']); 
  51.  
  52. if ( $post_id ) 
  53. $attachments = intval( $wpdb->get_var( $wpdb->prepare( "SELECT count(*) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' AND post_parent = %d", $post_id ) ) ); 
  54.  
  55. if ( empty($attachments) ) { 
  56. unset($tabs['gallery']); 
  57. return $tabs; 
  58.  
  59. $tabs['gallery'] = sprintf(__('Gallery (%s)'), "<span id='attachments-count'>$attachments</span>"); 
  60.  
  61. return $tabs; 
  62.  
  63. /** 
  64. * Outputs the legacy media upload tabs UI. 
  65. * 
  66. * @since 2.5.0 
  67. * 
  68. * @global string $redir_tab 
  69. */ 
  70. function the_media_upload_tabs() { 
  71. global $redir_tab; 
  72. $tabs = media_upload_tabs(); 
  73. $default = 'type'; 
  74.  
  75. if ( !empty($tabs) ) { 
  76. echo "<ul id='sidemenu'>\n"; 
  77. if ( isset($redir_tab) && array_key_exists($redir_tab, $tabs) ) { 
  78. $current = $redir_tab; 
  79. } elseif ( isset($_GET['tab']) && array_key_exists($_GET['tab'], $tabs) ) { 
  80. $current = $_GET['tab']; 
  81. } else { 
  82. /** This filter is documented in wp-admin/media-upload.php */ 
  83. $current = apply_filters( 'media_upload_default_tab', $default ); 
  84.  
  85. foreach ( $tabs as $callback => $text ) { 
  86. $class = ''; 
  87.  
  88. if ( $current == $callback ) 
  89. $class = " class='current'"; 
  90.  
  91. $href = add_query_arg(array('tab' => $callback, 's' => false, 'paged' => false, 'post_mime_type' => false, 'm' => false)); 
  92. $link = "<a href='" . esc_url($href) . "'$class>$text</a>"; 
  93. echo "\t<li id='" . esc_attr("tab-$callback") . "'>$link</li>\n"; 
  94. echo "</ul>\n"; 
  95.  
  96. /** 
  97. * Retrieves the image HTML to send to the editor. 
  98. * 
  99. * @since 2.5.0 
  100. * 
  101. * @param int $id Image attachment id. 
  102. * @param string $caption Image caption. 
  103. * @param string $title Image title attribute. 
  104. * @param string $align Image CSS alignment property. 
  105. * @param string $url Optional. Image src URL. Default empty. 
  106. * @param bool|string $rel Optional. Value for rel attribute or whether to add a default value. Default false. 
  107. * @param string|array $size Optional. Image size. Accepts any valid image size, or an array of width 
  108. * and height values in pixels (in that order). Default 'medium'. 
  109. * @param string $alt Optional. Image alt attribute. Default empty. 
  110. * @return string The HTML output to insert into the editor. 
  111. */ 
  112. function get_image_send_to_editor( $id, $caption, $title, $align, $url = '', $rel = false, $size = 'medium', $alt = '' ) { 
  113.  
  114. $html = get_image_tag( $id, $alt, '', $align, $size ); 
  115.  
  116. if ( $rel ) { 
  117. if ( is_string( $rel ) ) { 
  118. $rel = ' rel="' . esc_attr( $rel ) . '"'; 
  119. } else { 
  120. $rel = ' rel="attachment wp-att-' . intval( $id ) . '"'; 
  121. } else { 
  122. $rel = ''; 
  123.  
  124. if ( $url ) 
  125. $html = '<a href="' . esc_attr( $url ) . '"' . $rel . '>' . $html . '</a>'; 
  126.  
  127. /** 
  128. * Filters the image HTML markup to send to the editor when inserting an image. 
  129. * 
  130. * @since 2.5.0 
  131. * 
  132. * @param string $html The image HTML markup to send. 
  133. * @param int $id The attachment id. 
  134. * @param string $caption The image caption. 
  135. * @param string $title The image title. 
  136. * @param string $align The image alignment. 
  137. * @param string $url The image source URL. 
  138. * @param string|array $size Size of image. Image size or array of width and height values 
  139. * (in that order). Default 'medium'. 
  140. * @param string $alt The image alternative, or alt, text. 
  141. */ 
  142. $html = apply_filters( 'image_send_to_editor', $html, $id, $caption, $title, $align, $url, $size, $alt ); 
  143.  
  144. return $html; 
  145.  
  146. /** 
  147. * Adds image shortcode with caption to editor 
  148. * 
  149. * @since 2.6.0 
  150. * 
  151. * @param string $html 
  152. * @param integer $id 
  153. * @param string $caption image caption 
  154. * @param string $title image title attribute 
  155. * @param string $align image css alignment property 
  156. * @param string $url image src url 
  157. * @param string $size image size (thumbnail, medium, large, full or added with add_image_size() ) 
  158. * @param string $alt image alt attribute 
  159. * @return string 
  160. */ 
  161. function image_add_caption( $html, $id, $caption, $title, $align, $url, $size, $alt = '' ) { 
  162.  
  163. /** 
  164. * Filters the caption text. 
  165. * 
  166. * Note: If the caption text is empty, the caption shortcode will not be appended 
  167. * to the image HTML when inserted into the editor. 
  168. * 
  169. * Passing an empty value also prevents the {@see 'image_add_caption_shortcode'} 
  170. * Filters from being evaluated at the end of image_add_caption(). 
  171. * 
  172. * @since 4.1.0 
  173. * 
  174. * @param string $caption The original caption text. 
  175. * @param int $id The attachment ID. 
  176. */ 
  177. $caption = apply_filters( 'image_add_caption_text', $caption, $id ); 
  178.  
  179. /** 
  180. * Filters whether to disable captions. 
  181. * 
  182. * Prevents image captions from being appended to image HTML when inserted into the editor. 
  183. * 
  184. * @since 2.6.0 
  185. * 
  186. * @param bool $bool Whether to disable appending captions. Returning true to the filter 
  187. * will disable captions. Default empty string. 
  188. */ 
  189. if ( empty($caption) || apply_filters( 'disable_captions', '' ) ) 
  190. return $html; 
  191.  
  192. $id = ( 0 < (int) $id ) ? 'attachment_' . $id : ''; 
  193.  
  194. if ( ! preg_match( '/width=["\']([0-9]+)/', $html, $matches ) ) 
  195. return $html; 
  196.  
  197. $width = $matches[1]; 
  198.  
  199. $caption = str_replace( array("\r\n", "\r"), "\n", $caption); 
  200. $caption = preg_replace_callback( '/<[a-zA-Z0-9]+(?: [^<>]+>)*/', '_cleanup_image_add_caption', $caption ); 
  201.  
  202. // Convert any remaining line breaks to <br>. 
  203. $caption = preg_replace( '/[ \n\t]*\n[ \t]*/', '<br />', $caption ); 
  204.  
  205. $html = preg_replace( '/(class=["\'][^\'"]*)align(none|left|right|center)\s?/', '$1', $html ); 
  206. if ( empty($align) ) 
  207. $align = 'none'; 
  208.  
  209. $shcode = '' . $html . ' ' . $caption . ''; 
  210.  
  211. /** 
  212. * Filters the image HTML markup including the caption shortcode. 
  213. * 
  214. * @since 2.6.0 
  215. * 
  216. * @param string $shcode The image HTML markup with caption shortcode. 
  217. * @param string $html The image HTML markup. 
  218. */ 
  219. return apply_filters( 'image_add_caption_shortcode', $shcode, $html ); 
  220.  
  221. /** 
  222. * Private preg_replace callback used in image_add_caption() 
  223. * 
  224. * @access private 
  225. * @since 3.4.0 
  226. */ 
  227. function _cleanup_image_add_caption( $matches ) { 
  228. // Remove any line breaks from inside the tags. 
  229. return preg_replace( '/[\r\n\t]+/', ' ', $matches[0] ); 
  230.  
  231. /** 
  232. * Adds image html to editor 
  233. * 
  234. * @since 2.5.0 
  235. * 
  236. * @param string $html 
  237. */ 
  238. function media_send_to_editor($html) { 
  239. ?> 
  240. <script type="text/javascript"> 
  241. var win = window.dialogArguments || opener || parent || top; 
  242. win.send_to_editor( <?php echo wp_json_encode( $html ); ?> ); 
  243. </script> 
  244. <?php 
  245. exit; 
  246.  
  247. /** 
  248. * Save a file submitted from a POST request and create an attachment post for it. 
  249. * 
  250. * @since 2.5.0 
  251. * 
  252. * @param string $file_id Index of the `$_FILES` array that the file was sent. Required. 
  253. * @param int $post_id The post ID of a post to attach the media item to. Required, but can 
  254. * be set to 0, creating a media item that has no relationship to a post. 
  255. * @param array $post_data Overwrite some of the attachment. Optional. 
  256. * @param array $overrides Override the wp_handle_upload() behavior. Optional. 
  257. * @return int|WP_Error ID of the attachment or a WP_Error object on failure. 
  258. */ 
  259. function media_handle_upload($file_id, $post_id, $post_data = array(), $overrides = array( 'test_form' => false )) { 
  260.  
  261. $time = current_time('mysql'); 
  262. if ( $post = get_post($post_id) ) { 
  263. if ( substr( $post->post_date, 0, 4 ) > 0 ) 
  264. $time = $post->post_date; 
  265.  
  266. $file = wp_handle_upload($_FILES[$file_id], $overrides, $time); 
  267.  
  268. if ( isset($file['error']) ) 
  269. return new WP_Error( 'upload_error', $file['error'] ); 
  270.  
  271. $name = $_FILES[$file_id]['name']; 
  272. $ext = pathinfo( $name, PATHINFO_EXTENSION ); 
  273. $name = wp_basename( $name, ".$ext" ); 
  274.  
  275. $url = $file['url']; 
  276. $type = $file['type']; 
  277. $file = $file['file']; 
  278. $title = sanitize_text_field( $name ); 
  279. $content = ''; 
  280. $excerpt = ''; 
  281.  
  282. if ( preg_match( '#^audio#', $type ) ) { 
  283. $meta = wp_read_audio_metadata( $file ); 
  284.  
  285. if ( ! empty( $meta['title'] ) ) { 
  286. $title = $meta['title']; 
  287.  
  288. if ( ! empty( $title ) ) { 
  289.  
  290. if ( ! empty( $meta['album'] ) && ! empty( $meta['artist'] ) ) { 
  291. /** translators: 1: audio track title, 2: album title, 3: artist name */ 
  292. $content .= sprintf( __( '"%1$s" from %2$s by %3$s.' ), $title, $meta['album'], $meta['artist'] ); 
  293. } elseif ( ! empty( $meta['album'] ) ) { 
  294. /** translators: 1: audio track title, 2: album title */ 
  295. $content .= sprintf( __( '"%1$s" from %2$s.' ), $title, $meta['album'] ); 
  296. } elseif ( ! empty( $meta['artist'] ) ) { 
  297. /** translators: 1: audio track title, 2: artist name */ 
  298. $content .= sprintf( __( '"%1$s" by %2$s.' ), $title, $meta['artist'] ); 
  299. } else { 
  300. /** translators: 1: audio track title */ 
  301. $content .= sprintf( __( '"%s".' ), $title ); 
  302.  
  303. } elseif ( ! empty( $meta['album'] ) ) { 
  304.  
  305. if ( ! empty( $meta['artist'] ) ) { 
  306. /** translators: 1: audio album title, 2: artist name */ 
  307. $content .= sprintf( __( '%1$s by %2$s.' ), $meta['album'], $meta['artist'] ); 
  308. } else { 
  309. $content .= $meta['album'] . '.'; 
  310.  
  311. } elseif ( ! empty( $meta['artist'] ) ) { 
  312.  
  313. $content .= $meta['artist'] . '.'; 
  314.  
  315.  
  316. if ( ! empty( $meta['year'] ) ) { 
  317. /** translators: Audio file track information. 1: Year of audio track release */ 
  318. $content .= ' ' . sprintf( __( 'Released: %d.' ), $meta['year'] ); 
  319.  
  320. if ( ! empty( $meta['track_number'] ) ) { 
  321. $track_number = explode( '/', $meta['track_number'] ); 
  322. if ( isset( $track_number[1] ) ) { 
  323. /** translators: Audio file track information. 1: Audio track number, 2: Total audio tracks */ 
  324. $content .= ' ' . sprintf( __( 'Track %1$s of %2$s.' ), number_format_i18n( $track_number[0] ), number_format_i18n( $track_number[1] ) ); 
  325. } else { 
  326. /** translators: Audio file track information. 1: Audio track number */ 
  327. $content .= ' ' . sprintf( __( 'Track %1$s.' ), number_format_i18n( $track_number[0] ) ); 
  328.  
  329. if ( ! empty( $meta['genre'] ) ) { 
  330. /** translators: Audio file genre information. 1: Audio genre name */ 
  331. $content .= ' ' . sprintf( __( 'Genre: %s.' ), $meta['genre'] ); 
  332.  
  333. // Use image exif/iptc data for title and caption defaults if possible. 
  334. } elseif ( 0 === strpos( $type, 'image/' ) && $image_meta = @wp_read_image_metadata( $file ) ) { 
  335. if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) { 
  336. $title = $image_meta['title']; 
  337.  
  338. if ( trim( $image_meta['caption'] ) ) { 
  339. $excerpt = $image_meta['caption']; 
  340.  
  341. // Construct the attachment array 
  342. $attachment = array_merge( array( 
  343. 'post_mime_type' => $type,  
  344. 'guid' => $url,  
  345. 'post_parent' => $post_id,  
  346. 'post_title' => $title,  
  347. 'post_content' => $content,  
  348. 'post_excerpt' => $excerpt,  
  349. ), $post_data ); 
  350.  
  351. // This should never be set as it would then overwrite an existing attachment. 
  352. unset( $attachment['ID'] ); 
  353.  
  354. // Save the data 
  355. $id = wp_insert_attachment($attachment, $file, $post_id); 
  356. if ( !is_wp_error($id) ) { 
  357. wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $file ) ); 
  358.  
  359. return $id; 
  360.  
  361.  
  362. /** 
  363. * Handles a side-loaded file in the same way as an uploaded file is handled by media_handle_upload(). 
  364. * 
  365. * @since 2.6.0 
  366. * 
  367. * @param array $file_array Array similar to a `$_FILES` upload array. 
  368. * @param int $post_id The post ID the media is associated with. 
  369. * @param string $desc Optional. Description of the side-loaded file. Default null. 
  370. * @param array $post_data Optional. Post data to override. Default empty array. 
  371. * @return int|object The ID of the attachment or a WP_Error on failure. 
  372. */ 
  373. function media_handle_sideload( $file_array, $post_id, $desc = null, $post_data = array() ) { 
  374. $overrides = array('test_form'=>false); 
  375.  
  376. $time = current_time( 'mysql' ); 
  377. if ( $post = get_post( $post_id ) ) { 
  378. if ( substr( $post->post_date, 0, 4 ) > 0 ) 
  379. $time = $post->post_date; 
  380.  
  381. $file = wp_handle_sideload( $file_array, $overrides, $time ); 
  382. if ( isset($file['error']) ) 
  383. return new WP_Error( 'upload_error', $file['error'] ); 
  384.  
  385. $url = $file['url']; 
  386. $type = $file['type']; 
  387. $file = $file['file']; 
  388. $title = preg_replace('/\.[^.]+$/', '', basename($file)); 
  389. $content = ''; 
  390.  
  391. // Use image exif/iptc data for title and caption defaults if possible. 
  392. if ( $image_meta = @wp_read_image_metadata($file) ) { 
  393. if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) 
  394. $title = $image_meta['title']; 
  395. if ( trim( $image_meta['caption'] ) ) 
  396. $content = $image_meta['caption']; 
  397.  
  398. if ( isset( $desc ) ) 
  399. $title = $desc; 
  400.  
  401. // Construct the attachment array
  402. $attachment = array_merge( array( 
  403. 'post_mime_type' => $type,  
  404. 'guid' => $url,  
  405. 'post_parent' => $post_id,  
  406. 'post_title' => $title,  
  407. 'post_content' => $content,  
  408. ), $post_data ); 
  409.  
  410. // This should never be set as it would then overwrite an existing attachment. 
  411. unset( $attachment['ID'] ); 
  412.  
  413. // Save the attachment metadata 
  414. $id = wp_insert_attachment($attachment, $file, $post_id); 
  415. if ( !is_wp_error($id) ) 
  416. wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $file ) ); 
  417.  
  418. return $id; 
  419.  
  420. /** 
  421. * Adds the iframe to display content for the media upload page 
  422. * 
  423. * @since 2.5.0 
  424. * 
  425. * @global int $body_id 
  426. * 
  427. * @param string|callable $content_func 
  428. */ 
  429. function wp_iframe($content_func /** ... */) { 
  430. _wp_admin_html_begin(); 
  431. ?> 
  432. <title><?php bloginfo('name') ?> › <?php _e('Uploads'); ?> — <?php _e('WordPress'); ?></title> 
  433. <?php 
  434.  
  435. wp_enqueue_style( 'colors' ); 
  436. // Check callback name for 'media' 
  437. if ( ( is_array( $content_func ) && ! empty( $content_func[1] ) && 0 === strpos( (string) $content_func[1], 'media' ) ) 
  438. || ( ! is_array( $content_func ) && 0 === strpos( $content_func, 'media' ) ) ) 
  439. wp_enqueue_style( 'deprecated-media' ); 
  440. wp_enqueue_style( 'ie' ); 
  441. ?> 
  442. <script type="text/javascript"> 
  443. addLoadEvent = function(func) {if(typeof jQuery!="undefined")jQuery(document).ready(func);else if(typeof wpOnload!='function') {wpOnload=func;}else{var oldonload=wpOnload;wpOnload=function() {oldonload();func();}}}; 
  444. var ajaxurl = '<?php echo admin_url( 'admin-ajax.php', 'relative' ); ?>', pagenow = 'media-upload-popup', adminpage = 'media-upload-popup',  
  445. isRtl = <?php echo (int) is_rtl(); ?>; 
  446. </script> 
  447. <?php 
  448. /** This action is documented in wp-admin/admin-header.php */ 
  449. do_action( 'admin_enqueue_scripts', 'media-upload-popup' ); 
  450.  
  451. /** 
  452. * Fires when admin styles enqueued for the legacy (pre-3.5.0) media upload popup are printed. 
  453. * 
  454. * @since 2.9.0 
  455. */ 
  456. do_action( 'admin_print_styles-media-upload-popup' ); 
  457.  
  458. /** This action is documented in wp-admin/admin-header.php */ 
  459. do_action( 'admin_print_styles' ); 
  460.  
  461. /** 
  462. * Fires when admin scripts enqueued for the legacy (pre-3.5.0) media upload popup are printed. 
  463. * 
  464. * @since 2.9.0 
  465. */ 
  466. do_action( 'admin_print_scripts-media-upload-popup' ); 
  467.  
  468. /** This action is documented in wp-admin/admin-header.php */ 
  469. do_action( 'admin_print_scripts' ); 
  470.  
  471. /** 
  472. * Fires when scripts enqueued for the admin header for the legacy (pre-3.5.0) 
  473. * media upload popup are printed. 
  474. * 
  475. * @since 2.9.0 
  476. */ 
  477. do_action( 'admin_head-media-upload-popup' ); 
  478.  
  479. /** This action is documented in wp-admin/admin-header.php */ 
  480. do_action( 'admin_head' ); 
  481.  
  482. if ( is_string( $content_func ) ) { 
  483. /** 
  484. * Fires in the admin header for each specific form tab in the legacy 
  485. * (pre-3.5.0) media upload popup. 
  486. * 
  487. * The dynamic portion of the hook, `$content_func`, refers to the form 
  488. * callback for the media upload type. Possible values include 
  489. * 'media_upload_type_form', 'media_upload_type_url_form', and 
  490. * 'media_upload_library_form'. 
  491. * 
  492. * @since 2.5.0 
  493. */ 
  494. do_action( "admin_head_{$content_func}" ); 
  495. ?> 
  496. </head> 
  497. <body<?php if ( isset($GLOBALS['body_id']) ) echo ' id="' . $GLOBALS['body_id'] . '"'; ?> class="wp-core-ui no-js"> 
  498. <script type="text/javascript"> 
  499. document.body.className = document.body.className.replace('no-js', 'js'); 
  500. </script> 
  501. <?php 
  502. $args = func_get_args(); 
  503. $args = array_slice($args, 1); 
  504. call_user_func_array($content_func, $args); 
  505.  
  506. /** This action is documented in wp-admin/admin-footer.php */ 
  507. do_action( 'admin_print_footer_scripts' ); 
  508. ?> 
  509. <script type="text/javascript">if(typeof wpOnload=='function')wpOnload();</script> 
  510. </body> 
  511. </html> 
  512. <?php 
  513.  
  514. /** 
  515. * Adds the media button to the editor 
  516. * 
  517. * @since 2.5.0 
  518. * 
  519. * @global int $post_ID 
  520. * 
  521. * @staticvar int $instance 
  522. * 
  523. * @param string $editor_id 
  524. */ 
  525. function media_buttons($editor_id = 'content') { 
  526. static $instance = 0; 
  527. $instance++; 
  528.  
  529. $post = get_post(); 
  530. if ( ! $post && ! empty( $GLOBALS['post_ID'] ) ) 
  531. $post = $GLOBALS['post_ID']; 
  532.  
  533. wp_enqueue_media( array( 
  534. 'post' => $post 
  535. ) ); 
  536.  
  537. $img = '<span class="wp-media-buttons-icon"></span> '; 
  538.  
  539. $id_attribute = $instance === 1 ? ' id="insert-media-button"' : ''; 
  540. printf( '<button type="button"%s class="button insert-media add_media" data-editor="%s">%s</button>',  
  541. $id_attribute,  
  542. esc_attr( $editor_id ),  
  543. $img . __( 'Add Media' ) 
  544. ); 
  545. /** 
  546. * Filters the legacy (pre-3.5.0) media buttons. 
  547. * 
  548. * Use {@see 'media_buttons'} action instead. 
  549. * 
  550. * @since 2.5.0 
  551. * @deprecated 3.5.0 Use {@see 'media_buttons'} action instead. 
  552. * 
  553. * @param string $string Media buttons context. Default empty. 
  554. */ 
  555. $legacy_filter = apply_filters( 'media_buttons_context', '' ); 
  556.  
  557. if ( $legacy_filter ) { 
  558. // #WP22559. Close <a> if a plugin started by closing <a> to open their own <a> tag. 
  559. if ( 0 === stripos( trim( $legacy_filter ), '</a>' ) ) 
  560. $legacy_filter .= '</a>'; 
  561. echo $legacy_filter; 
  562.  
  563. /** 
  564. * 
  565. * @global int $post_ID 
  566. * @param string $type 
  567. * @param int $post_id 
  568. * @param string $tab 
  569. * @return string 
  570. */ 
  571. function get_upload_iframe_src( $type = null, $post_id = null, $tab = null ) { 
  572. global $post_ID; 
  573.  
  574. if ( empty( $post_id ) ) 
  575. $post_id = $post_ID; 
  576.  
  577. $upload_iframe_src = add_query_arg( 'post_id', (int) $post_id, admin_url('media-upload.php') ); 
  578.  
  579. if ( $type && 'media' != $type ) 
  580. $upload_iframe_src = add_query_arg('type', $type, $upload_iframe_src); 
  581.  
  582. if ( ! empty( $tab ) ) 
  583. $upload_iframe_src = add_query_arg('tab', $tab, $upload_iframe_src); 
  584.  
  585. /** 
  586. * Filters the upload iframe source URL for a specific media type. 
  587. * 
  588. * The dynamic portion of the hook name, `$type`, refers to the type 
  589. * of media uploaded. 
  590. * 
  591. * @since 3.0.0 
  592. * 
  593. * @param string $upload_iframe_src The upload iframe source URL by type. 
  594. */ 
  595. $upload_iframe_src = apply_filters( "{$type}_upload_iframe_src", $upload_iframe_src ); 
  596.  
  597. return add_query_arg('TB_iframe', true, $upload_iframe_src); 
  598.  
  599. /** 
  600. * Handles form submissions for the legacy media uploader. 
  601. * 
  602. * @since 2.5.0 
  603. * 
  604. * @return mixed void|object WP_Error on failure 
  605. */ 
  606. function media_upload_form_handler() { 
  607. check_admin_referer('media-form'); 
  608.  
  609. $errors = null; 
  610.  
  611. if ( isset($_POST['send']) ) { 
  612. $keys = array_keys( $_POST['send'] ); 
  613. $send_id = (int) reset( $keys ); 
  614.  
  615. if ( !empty($_POST['attachments']) ) foreach ( $_POST['attachments'] as $attachment_id => $attachment ) { 
  616. $post = $_post = get_post($attachment_id, ARRAY_A); 
  617.  
  618. if ( !current_user_can( 'edit_post', $attachment_id ) ) 
  619. continue; 
  620.  
  621. if ( isset($attachment['post_content']) ) 
  622. $post['post_content'] = $attachment['post_content']; 
  623. if ( isset($attachment['post_title']) ) 
  624. $post['post_title'] = $attachment['post_title']; 
  625. if ( isset($attachment['post_excerpt']) ) 
  626. $post['post_excerpt'] = $attachment['post_excerpt']; 
  627. if ( isset($attachment['menu_order']) ) 
  628. $post['menu_order'] = $attachment['menu_order']; 
  629.  
  630. if ( isset($send_id) && $attachment_id == $send_id ) { 
  631. if ( isset($attachment['post_parent']) ) 
  632. $post['post_parent'] = $attachment['post_parent']; 
  633.  
  634. /** 
  635. * Filters the attachment fields to be saved. 
  636. * 
  637. * @since 2.5.0 
  638. * 
  639. * @see wp_get_attachment_metadata() 
  640. * 
  641. * @param array $post An array of post data. 
  642. * @param array $attachment An array of attachment metadata. 
  643. */ 
  644. $post = apply_filters( 'attachment_fields_to_save', $post, $attachment ); 
  645.  
  646. if ( isset($attachment['image_alt']) ) { 
  647. $image_alt = wp_unslash( $attachment['image_alt'] ); 
  648. if ( $image_alt != get_post_meta($attachment_id, '_wp_attachment_image_alt', true) ) { 
  649. $image_alt = wp_strip_all_tags( $image_alt, true ); 
  650.  
  651. // Update_meta expects slashed. 
  652. update_post_meta( $attachment_id, '_wp_attachment_image_alt', wp_slash( $image_alt ) ); 
  653.  
  654. if ( isset($post['errors']) ) { 
  655. $errors[$attachment_id] = $post['errors']; 
  656. unset($post['errors']); 
  657.  
  658. if ( $post != $_post ) 
  659. wp_update_post($post); 
  660.  
  661. foreach ( get_attachment_taxonomies($post) as $t ) { 
  662. if ( isset($attachment[$t]) ) 
  663. wp_set_object_terms($attachment_id, array_map('trim', preg_split('/, +/', $attachment[$t])), $t, false); 
  664.  
  665. if ( isset($_POST['insert-gallery']) || isset($_POST['update-gallery']) ) { ?> 
  666. <script type="text/javascript"> 
  667. var win = window.dialogArguments || opener || parent || top; 
  668. win.tb_remove(); 
  669. </script> 
  670. <?php 
  671. exit; 
  672.  
  673. if ( isset($send_id) ) { 
  674. $attachment = wp_unslash( $_POST['attachments'][$send_id] ); 
  675.  
  676. $html = isset( $attachment['post_title'] ) ? $attachment['post_title'] : ''; 
  677. if ( !empty($attachment['url']) ) { 
  678. $rel = ''; 
  679. if ( strpos($attachment['url'], 'attachment_id') || get_attachment_link($send_id) == $attachment['url'] ) 
  680. $rel = " rel='attachment wp-att-" . esc_attr($send_id) . "'"; 
  681. $html = "<a href='{$attachment['url']}'$rel>$html</a>"; 
  682.  
  683. /** 
  684. * Filters the HTML markup for a media item sent to the editor. 
  685. * 
  686. * @since 2.5.0 
  687. * 
  688. * @see wp_get_attachment_metadata() 
  689. * 
  690. * @param string $html HTML markup for a media item sent to the editor. 
  691. * @param int $send_id The first key from the $_POST['send'] data. 
  692. * @param array $attachment Array of attachment metadata. 
  693. */ 
  694. $html = apply_filters( 'media_send_to_editor', $html, $send_id, $attachment ); 
  695. return media_send_to_editor($html); 
  696.  
  697. return $errors; 
  698.  
  699. /** 
  700. * Handles the process of uploading media. 
  701. * 
  702. * @since 2.5.0 
  703. * 
  704. * @return null|string 
  705. */ 
  706. function wp_media_upload_handler() { 
  707. $errors = array(); 
  708. $id = 0; 
  709.  
  710. if ( isset($_POST['html-upload']) && !empty($_FILES) ) { 
  711. check_admin_referer('media-form'); 
  712. // Upload File button was clicked 
  713. $id = media_handle_upload('async-upload', $_REQUEST['post_id']); 
  714. unset($_FILES); 
  715. if ( is_wp_error($id) ) { 
  716. $errors['upload_error'] = $id; 
  717. $id = false; 
  718.  
  719. if ( !empty($_POST['insertonlybutton']) ) { 
  720. $src = $_POST['src']; 
  721. if ( !empty($src) && !strpos($src, '://') ) 
  722. $src = "http://$src"; 
  723.  
  724. if ( isset( $_POST['media_type'] ) && 'image' != $_POST['media_type'] ) { 
  725. $title = esc_html( wp_unslash( $_POST['title'] ) ); 
  726. if ( empty( $title ) ) 
  727. $title = esc_html( basename( $src ) ); 
  728.  
  729. if ( $title && $src ) 
  730. $html = "<a href='" . esc_url($src) . "'>$title</a>"; 
  731.  
  732. $type = 'file'; 
  733. if ( ( $ext = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src ) ) && ( $ext_type = wp_ext2type( $ext ) ) 
  734. && ( 'audio' == $ext_type || 'video' == $ext_type ) ) 
  735. $type = $ext_type; 
  736.  
  737. /** 
  738. * Filters the URL sent to the editor for a specific media type. 
  739. * 
  740. * The dynamic portion of the hook name, `$type`, refers to the type 
  741. * of media being sent. 
  742. * 
  743. * @since 3.3.0 
  744. * 
  745. * @param string $html HTML markup sent to the editor. 
  746. * @param string $src Media source URL. 
  747. * @param string $title Media title. 
  748. */ 
  749. $html = apply_filters( "{$type}_send_to_editor_url", $html, esc_url_raw( $src ), $title ); 
  750. } else { 
  751. $align = ''; 
  752. $alt = esc_attr( wp_unslash( $_POST['alt'] ) ); 
  753. if ( isset($_POST['align']) ) { 
  754. $align = esc_attr( wp_unslash( $_POST['align'] ) ); 
  755. $class = " class='align$align'"; 
  756. if ( !empty($src) ) 
  757. $html = "<img src='" . esc_url($src) . "' alt='$alt'$class />"; 
  758.  
  759. /** 
  760. * Filters the image URL sent to the editor. 
  761. * 
  762. * @since 2.8.0 
  763. * 
  764. * @param string $html HTML markup sent to the editor for an image. 
  765. * @param string $src Image source URL. 
  766. * @param string $alt Image alternate, or alt, text. 
  767. * @param string $align The image alignment. Default 'alignnone'. Possible values include 
  768. * 'alignleft', 'aligncenter', 'alignright', 'alignnone'. 
  769. */ 
  770. $html = apply_filters( 'image_send_to_editor_url', $html, esc_url_raw( $src ), $alt, $align ); 
  771.  
  772. return media_send_to_editor($html); 
  773.  
  774. if ( isset( $_POST['save'] ) ) { 
  775. $errors['upload_notice'] = __('Saved.'); 
  776. wp_enqueue_script( 'admin-gallery' ); 
  777. return wp_iframe( 'media_upload_gallery_form', $errors ); 
  778.  
  779. } elseif ( ! empty( $_POST ) ) { 
  780. $return = media_upload_form_handler(); 
  781.  
  782. if ( is_string($return) ) 
  783. return $return; 
  784. if ( is_array($return) ) 
  785. $errors = $return; 
  786.  
  787. if ( isset($_GET['tab']) && $_GET['tab'] == 'type_url' ) { 
  788. $type = 'image'; 
  789. if ( isset( $_GET['type'] ) && in_array( $_GET['type'], array( 'video', 'audio', 'file' ) ) ) 
  790. $type = $_GET['type']; 
  791. return wp_iframe( 'media_upload_type_url_form', $type, $errors, $id ); 
  792.  
  793. return wp_iframe( 'media_upload_type_form', 'image', $errors, $id ); 
  794.  
  795. /** 
  796. * Downloads an image from the specified URL and attaches it to a post. 
  797. * 
  798. * @since 2.6.0 
  799. * @since 4.2.0 Introduced the `$return` parameter. 
  800. * 
  801. * @param string $file The URL of the image to download. 
  802. * @param int $post_id The post ID the media is to be associated with. 
  803. * @param string $desc Optional. Description of the image. 
  804. * @param string $return Optional. Accepts 'html' (image tag html) or 'src' (URL). Default 'html'. 
  805. * @return string|WP_Error Populated HTML img tag on success, WP_Error object otherwise. 
  806. */ 
  807. function media_sideload_image( $file, $post_id, $desc = null, $return = 'html' ) { 
  808. if ( ! empty( $file ) ) { 
  809.  
  810. // Set variables for storage, fix file filename for query strings. 
  811. preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $file, $matches ); 
  812. if ( ! $matches ) { 
  813. return new WP_Error( 'image_sideload_failed', __( 'Invalid image URL' ) ); 
  814.  
  815. $file_array = array(); 
  816. $file_array['name'] = basename( $matches[0] ); 
  817.  
  818. // Download file to temp location. 
  819. $file_array['tmp_name'] = download_url( $file ); 
  820.  
  821. // If error storing temporarily, return the error. 
  822. if ( is_wp_error( $file_array['tmp_name'] ) ) { 
  823. return $file_array['tmp_name']; 
  824.  
  825. // Do the validation and storage stuff. 
  826. $id = media_handle_sideload( $file_array, $post_id, $desc ); 
  827.  
  828. // If error storing permanently, unlink. 
  829. if ( is_wp_error( $id ) ) { 
  830. @unlink( $file_array['tmp_name'] ); 
  831. return $id; 
  832.  
  833. $src = wp_get_attachment_url( $id ); 
  834.  
  835. // Finally, check to make sure the file has been saved, then return the HTML. 
  836. if ( ! empty( $src ) ) { 
  837. if ( $return === 'src' ) { 
  838. return $src; 
  839.  
  840. $alt = isset( $desc ) ? esc_attr( $desc ) : ''; 
  841. $html = "<img src='$src' alt='$alt' />"; 
  842. return $html; 
  843. } else { 
  844. return new WP_Error( 'image_sideload_failed' ); 
  845.  
  846. /** 
  847. * Retrieves the legacy media uploader form in an iframe. 
  848. * 
  849. * @since 2.5.0 
  850. * 
  851. * @return string|null 
  852. */ 
  853. function media_upload_gallery() { 
  854. $errors = array(); 
  855.  
  856. if ( !empty($_POST) ) { 
  857. $return = media_upload_form_handler(); 
  858.  
  859. if ( is_string($return) ) 
  860. return $return; 
  861. if ( is_array($return) ) 
  862. $errors = $return; 
  863.  
  864. wp_enqueue_script('admin-gallery'); 
  865. return wp_iframe( 'media_upload_gallery_form', $errors ); 
  866.  
  867. /** 
  868. * Retrieves the legacy media library form in an iframe. 
  869. * 
  870. * @since 2.5.0 
  871. * 
  872. * @return string|null 
  873. */ 
  874. function media_upload_library() { 
  875. $errors = array(); 
  876. if ( !empty($_POST) ) { 
  877. $return = media_upload_form_handler(); 
  878.  
  879. if ( is_string($return) ) 
  880. return $return; 
  881. if ( is_array($return) ) 
  882. $errors = $return; 
  883.  
  884. return wp_iframe( 'media_upload_library_form', $errors ); 
  885.  
  886. /** 
  887. * Retrieve HTML for the image alignment radio buttons with the specified one checked. 
  888. * 
  889. * @since 2.7.0 
  890. * 
  891. * @param WP_Post $post 
  892. * @param string $checked 
  893. * @return string 
  894. */ 
  895. function image_align_input_fields( $post, $checked = '' ) { 
  896.  
  897. if ( empty($checked) ) 
  898. $checked = get_user_setting('align', 'none'); 
  899.  
  900. $alignments = array('none' => __('None'), 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right')); 
  901. if ( !array_key_exists( (string) $checked, $alignments ) ) 
  902. $checked = 'none'; 
  903.  
  904. $out = array(); 
  905. foreach ( $alignments as $name => $label ) { 
  906. $name = esc_attr($name); 
  907. $out[] = "<input type='radio' name='attachments[{$post->ID}][align]' id='image-align-{$name}-{$post->ID}' value='$name'". 
  908. ( $checked == $name ? " checked='checked'" : "" ) . 
  909. " /><label for='image-align-{$name}-{$post->ID}' class='align image-align-{$name}-label'>$label</label>"; 
  910. return join("\n", $out); 
  911.  
  912. /** 
  913. * Retrieve HTML for the size radio buttons with the specified one checked. 
  914. * 
  915. * @since 2.7.0 
  916. * 
  917. * @param WP_Post $post 
  918. * @param bool|string $check 
  919. * @return array 
  920. */ 
  921. function image_size_input_fields( $post, $check = '' ) { 
  922. /** 
  923. * Filters the names and labels of the default image sizes. 
  924. * 
  925. * @since 3.3.0 
  926. * 
  927. * @param array $size_names Array of image sizes and their names. Default values 
  928. * include 'Thumbnail', 'Medium', 'Large', 'Full Size'. 
  929. */ 
  930. $size_names = apply_filters( 'image_size_names_choose', array( 
  931. 'thumbnail' => __( 'Thumbnail' ),  
  932. 'medium' => __( 'Medium' ),  
  933. 'large' => __( 'Large' ),  
  934. 'full' => __( 'Full Size' ) 
  935. ) ); 
  936.  
  937. if ( empty( $check ) ) { 
  938. $check = get_user_setting('imgsize', 'medium'); 
  939. $out = array(); 
  940.  
  941. foreach ( $size_names as $size => $label ) { 
  942. $downsize = image_downsize( $post->ID, $size ); 
  943. $checked = ''; 
  944.  
  945. // Is this size selectable? 
  946. $enabled = ( $downsize[3] || 'full' == $size ); 
  947. $css_id = "image-size-{$size}-{$post->ID}"; 
  948.  
  949. // If this size is the default but that's not available, don't select it. 
  950. if ( $size == $check ) { 
  951. if ( $enabled ) { 
  952. $checked = " checked='checked'"; 
  953. } else { 
  954. $check = ''; 
  955. } elseif ( ! $check && $enabled && 'thumbnail' != $size ) { 
  956. /** 
  957. * If $check is not enabled, default to the first available size 
  958. * that's bigger than a thumbnail. 
  959. */ 
  960. $check = $size; 
  961. $checked = " checked='checked'"; 
  962.  
  963. $html = "<div class='image-size-item'><input type='radio' " . disabled( $enabled, false, false ) . "name='attachments[$post->ID][image-size]' id='{$css_id}' value='{$size}'$checked />"; 
  964.  
  965. $html .= "<label for='{$css_id}'>$label</label>"; 
  966.  
  967. // Only show the dimensions if that choice is available. 
  968. if ( $enabled ) { 
  969. $html .= " <label for='{$css_id}' class='help'>" . sprintf( "(%d × %d)", $downsize[1], $downsize[2] ). "</label>"; 
  970. $html .= '</div>'; 
  971.  
  972. $out[] = $html; 
  973.  
  974. return array( 
  975. 'label' => __( 'Size' ),  
  976. 'input' => 'html',  
  977. 'html' => join( "\n", $out ),  
  978. ); 
  979.  
  980. /** 
  981. * Retrieve HTML for the Link URL buttons with the default link type as specified. 
  982. * 
  983. * @since 2.7.0 
  984. * 
  985. * @param WP_Post $post 
  986. * @param string $url_type 
  987. * @return string 
  988. */ 
  989. function image_link_input_fields($post, $url_type = '') { 
  990.  
  991. $file = wp_get_attachment_url($post->ID); 
  992. $link = get_attachment_link($post->ID); 
  993.  
  994. if ( empty($url_type) ) 
  995. $url_type = get_user_setting('urlbutton', 'post'); 
  996.  
  997. $url = ''; 
  998. if ( $url_type == 'file' ) 
  999. $url = $file; 
  1000. elseif ( $url_type == 'post' ) 
  1001. $url = $link; 
  1002.  
  1003. return " 
  1004. <input type='text' class='text urlfield' name='attachments[$post->ID][url]' value='" . esc_attr($url) . "' /><br /> 
  1005. <button type='button' class='button urlnone' data-link-url=''>" . __('None') . "</button> 
  1006. <button type='button' class='button urlfile' data-link-url='" . esc_attr($file) . "'>" . __('File URL') . "</button> 
  1007. <button type='button' class='button urlpost' data-link-url='" . esc_attr($link) . "'>" . __('Attachment Post URL') . "</button> 
  1008. "; 
  1009.  
  1010. /** 
  1011. * Output a textarea element for inputting an attachment caption. 
  1012. * 
  1013. * @since 3.4.0 
  1014. * 
  1015. * @param WP_Post $edit_post Attachment WP_Post object. 
  1016. * @return string HTML markup for the textarea element. 
  1017. */ 
  1018. function wp_caption_input_textarea($edit_post) { 
  1019. // Post data is already escaped. 
  1020. $name = "attachments[{$edit_post->ID}][post_excerpt]"; 
  1021.  
  1022. return '<textarea name="' . $name . '" id="' . $name . '">' . $edit_post->post_excerpt . '</textarea>'; 
  1023.  
  1024. /** 
  1025. * Retrieves the image attachment fields to edit form fields. 
  1026. * 
  1027. * @since 2.5.0 
  1028. * 
  1029. * @param array $form_fields 
  1030. * @param object $post 
  1031. * @return array 
  1032. */ 
  1033. function image_attachment_fields_to_edit($form_fields, $post) { 
  1034. return $form_fields; 
  1035.  
  1036. /** 
  1037. * Retrieves the single non-image attachment fields to edit form fields. 
  1038. * 
  1039. * @since 2.5.0 
  1040. * 
  1041. * @param array $form_fields An array of attachment form fields. 
  1042. * @param WP_Post $post The WP_Post attachment object. 
  1043. * @return array Filtered attachment form fields. 
  1044. */ 
  1045. function media_single_attachment_fields_to_edit( $form_fields, $post ) { 
  1046. unset($form_fields['url'], $form_fields['align'], $form_fields['image-size']); 
  1047. return $form_fields; 
  1048.  
  1049. /** 
  1050. * Retrieves the post non-image attachment fields to edito form fields. 
  1051. * 
  1052. * @since 2.8.0 
  1053. * 
  1054. * @param array $form_fields An array of attachment form fields. 
  1055. * @param WP_Post $post The WP_Post attachment object. 
  1056. * @return array Filtered attachment form fields. 
  1057. */ 
  1058. function media_post_single_attachment_fields_to_edit( $form_fields, $post ) { 
  1059. unset($form_fields['image_url']); 
  1060. return $form_fields; 
  1061.  
  1062. /** 
  1063. * Filters input from media_upload_form_handler() and assigns a default 
  1064. * post_title from the file name if none supplied. 
  1065. * 
  1066. * Illustrates the use of the {@see 'attachment_fields_to_save'} filter 
  1067. * which can be used to add default values to any field before saving to DB. 
  1068. * 
  1069. * @since 2.5.0 
  1070. * 
  1071. * @param array $post The WP_Post attachment object converted to an array. 
  1072. * @param array $attachment An array of attachment metadata. 
  1073. * @return array Filtered attachment post object. 
  1074. */ 
  1075. function image_attachment_fields_to_save( $post, $attachment ) { 
  1076. if ( substr( $post['post_mime_type'], 0, 5 ) == 'image' ) { 
  1077. if ( strlen( trim( $post['post_title'] ) ) == 0 ) { 
  1078. $attachment_url = ( isset( $post['attachment_url'] ) ) ? $post['attachment_url'] : $post['guid']; 
  1079. $post['post_title'] = preg_replace( '/\.\w+$/', '', wp_basename( $attachment_url ) ); 
  1080. $post['errors']['post_title']['errors'][] = __( 'Empty Title filled from filename.' ); 
  1081.  
  1082. return $post; 
  1083.  
  1084. /** 
  1085. * Retrieves the media element HTML to send to the editor. 
  1086. * 
  1087. * @since 2.5.0 
  1088. * 
  1089. * @param string $html 
  1090. * @param integer $attachment_id 
  1091. * @param array $attachment 
  1092. * @return string 
  1093. */ 
  1094. function image_media_send_to_editor($html, $attachment_id, $attachment) { 
  1095. $post = get_post($attachment_id); 
  1096. if ( substr($post->post_mime_type, 0, 5) == 'image' ) { 
  1097. $url = $attachment['url']; 
  1098. $align = !empty($attachment['align']) ? $attachment['align'] : 'none'; 
  1099. $size = !empty($attachment['image-size']) ? $attachment['image-size'] : 'medium'; 
  1100. $alt = !empty($attachment['image_alt']) ? $attachment['image_alt'] : ''; 
  1101. $rel = ( strpos( $url, 'attachment_id') || $url === get_attachment_link( $attachment_id ) ); 
  1102.  
  1103. return get_image_send_to_editor($attachment_id, $attachment['post_excerpt'], $attachment['post_title'], $align, $url, $rel, $size, $alt); 
  1104.  
  1105. return $html; 
  1106.  
  1107. /** 
  1108. * Retrieves the attachment fields to edit form fields. 
  1109. * 
  1110. * @since 2.5.0 
  1111. * 
  1112. * @param WP_Post $post 
  1113. * @param array $errors 
  1114. * @return array 
  1115. */ 
  1116. function get_attachment_fields_to_edit($post, $errors = null) { 
  1117. if ( is_int($post) ) 
  1118. $post = get_post($post); 
  1119. if ( is_array($post) ) 
  1120. $post = new WP_Post( (object) $post ); 
  1121.  
  1122. $image_url = wp_get_attachment_url($post->ID); 
  1123.  
  1124. $edit_post = sanitize_post($post, 'edit'); 
  1125.  
  1126. $form_fields = array( 
  1127. 'post_title' => array( 
  1128. 'label' => __('Title'),  
  1129. 'value' => $edit_post->post_title 
  1130. ),  
  1131. 'image_alt' => array(),  
  1132. 'post_excerpt' => array( 
  1133. 'label' => __('Caption'),  
  1134. 'input' => 'html',  
  1135. 'html' => wp_caption_input_textarea($edit_post) 
  1136. ),  
  1137. 'post_content' => array( 
  1138. 'label' => __('Description'),  
  1139. 'value' => $edit_post->post_content,  
  1140. 'input' => 'textarea' 
  1141. ),  
  1142. 'url' => array( 
  1143. 'label' => __('Link URL'),  
  1144. 'input' => 'html',  
  1145. 'html' => image_link_input_fields($post, get_option('image_default_link_type')),  
  1146. 'helps' => __('Enter a link URL or click above for presets.') 
  1147. ),  
  1148. 'menu_order' => array( 
  1149. 'label' => __('Order'),  
  1150. 'value' => $edit_post->menu_order 
  1151. ),  
  1152. 'image_url' => array( 
  1153. 'label' => __('File URL'),  
  1154. 'input' => 'html',  
  1155. 'html' => "<input type='text' class='text urlfield' readonly='readonly' name='attachments[$post->ID][url]' value='" . esc_attr($image_url) . "' /><br />",  
  1156. 'value' => wp_get_attachment_url($post->ID),  
  1157. 'helps' => __('Location of the uploaded file.') 
  1158. ); 
  1159.  
  1160. foreach ( get_attachment_taxonomies($post) as $taxonomy ) { 
  1161. $t = (array) get_taxonomy($taxonomy); 
  1162. if ( ! $t['public'] || ! $t['show_ui'] ) 
  1163. continue; 
  1164. if ( empty($t['label']) ) 
  1165. $t['label'] = $taxonomy; 
  1166. if ( empty($t['args']) ) 
  1167. $t['args'] = array(); 
  1168.  
  1169. $terms = get_object_term_cache($post->ID, $taxonomy); 
  1170. if ( false === $terms ) 
  1171. $terms = wp_get_object_terms($post->ID, $taxonomy, $t['args']); 
  1172.  
  1173. $values = array(); 
  1174.  
  1175. foreach ( $terms as $term ) 
  1176. $values[] = $term->slug; 
  1177. $t['value'] = join(', ', $values); 
  1178.  
  1179. $form_fields[$taxonomy] = $t; 
  1180.  
  1181. // Merge default fields with their errors, so any key passed with the error (e.g. 'error', 'helps', 'value') will replace the default 
  1182. // The recursive merge is easily traversed with array casting: foreach ( (array) $things as $thing ) 
  1183. $form_fields = array_merge_recursive($form_fields, (array) $errors); 
  1184.  
  1185. // This was formerly in image_attachment_fields_to_edit(). 
  1186. if ( substr($post->post_mime_type, 0, 5) == 'image' ) { 
  1187. $alt = get_post_meta($post->ID, '_wp_attachment_image_alt', true); 
  1188. if ( empty($alt) ) 
  1189. $alt = ''; 
  1190.  
  1191. $form_fields['post_title']['required'] = true; 
  1192.  
  1193. $form_fields['image_alt'] = array( 
  1194. 'value' => $alt,  
  1195. 'label' => __('Alternative Text'),  
  1196. 'helps' => __('Alt text for the image, e.g. “The Mona Lisa”') 
  1197. ); 
  1198.  
  1199. $form_fields['align'] = array( 
  1200. 'label' => __('Alignment'),  
  1201. 'input' => 'html',  
  1202. 'html' => image_align_input_fields($post, get_option('image_default_align')),  
  1203. ); 
  1204.  
  1205. $form_fields['image-size'] = image_size_input_fields( $post, get_option('image_default_size', 'medium') ); 
  1206.  
  1207. } else { 
  1208. unset( $form_fields['image_alt'] ); 
  1209.  
  1210. /** 
  1211. * Filters the attachment fields to edit. 
  1212. * 
  1213. * @since 2.5.0 
  1214. * 
  1215. * @param array $form_fields An array of attachment form fields. 
  1216. * @param WP_Post $post The WP_Post attachment object. 
  1217. */ 
  1218. $form_fields = apply_filters( 'attachment_fields_to_edit', $form_fields, $post ); 
  1219.  
  1220. return $form_fields; 
  1221.  
  1222. /** 
  1223. * Retrieve HTML for media items of post gallery. 
  1224. * 
  1225. * The HTML markup retrieved will be created for the progress of SWF Upload 
  1226. * component. Will also create link for showing and hiding the form to modify 
  1227. * the image attachment. 
  1228. * 
  1229. * @since 2.5.0 
  1230. * 
  1231. * @global WP_Query $wp_the_query 
  1232. * 
  1233. * @param int $post_id Optional. Post ID. 
  1234. * @param array $errors Errors for attachment, if any. 
  1235. * @return string 
  1236. */ 
  1237. function get_media_items( $post_id, $errors ) { 
  1238. $attachments = array(); 
  1239. if ( $post_id ) { 
  1240. $post = get_post($post_id); 
  1241. if ( $post && $post->post_type == 'attachment' ) 
  1242. $attachments = array($post->ID => $post); 
  1243. else 
  1244. $attachments = get_children( array( 'post_parent' => $post_id, 'post_type' => 'attachment', 'orderby' => 'menu_order ASC, ID', 'order' => 'DESC') ); 
  1245. } else { 
  1246. if ( is_array($GLOBALS['wp_the_query']->posts) ) 
  1247. foreach ( $GLOBALS['wp_the_query']->posts as $attachment ) 
  1248. $attachments[$attachment->ID] = $attachment; 
  1249.  
  1250. $output = ''; 
  1251. foreach ( (array) $attachments as $id => $attachment ) { 
  1252. if ( $attachment->post_status == 'trash' ) 
  1253. continue; 
  1254. if ( $item = get_media_item( $id, array( 'errors' => isset($errors[$id]) ? $errors[$id] : null) ) ) 
  1255. $output .= "\n<div id='media-item-$id' class='media-item child-of-$attachment->post_parent preloaded'><div class='progress hidden'><div class='bar'></div></div><div id='media-upload-error-$id' class='hidden'></div><div class='filename hidden'></div>$item\n</div>"; 
  1256.  
  1257. return $output; 
  1258.  
  1259. /** 
  1260. * Retrieve HTML form for modifying the image attachment. 
  1261. * 
  1262. * @since 2.5.0 
  1263. * 
  1264. * @global string $redir_tab 
  1265. * 
  1266. * @param int $attachment_id Attachment ID for modification. 
  1267. * @param string|array $args Optional. Override defaults. 
  1268. * @return string HTML form for attachment. 
  1269. */ 
  1270. function get_media_item( $attachment_id, $args = null ) { 
  1271. global $redir_tab; 
  1272.  
  1273. if ( ( $attachment_id = intval( $attachment_id ) ) && $thumb_url = wp_get_attachment_image_src( $attachment_id, 'thumbnail', true ) ) 
  1274. $thumb_url = $thumb_url[0]; 
  1275. else 
  1276. $thumb_url = false; 
  1277.  
  1278. $post = get_post( $attachment_id ); 
  1279. $current_post_id = !empty( $_GET['post_id'] ) ? (int) $_GET['post_id'] : 0; 
  1280.  
  1281. $default_args = array( 
  1282. 'errors' => null,  
  1283. 'send' => $current_post_id ? post_type_supports( get_post_type( $current_post_id ), 'editor' ) : true,  
  1284. 'delete' => true,  
  1285. 'toggle' => true,  
  1286. 'show_title' => true 
  1287. ); 
  1288. $args = wp_parse_args( $args, $default_args ); 
  1289.  
  1290. /** 
  1291. * Filters the arguments used to retrieve an image for the edit image form. 
  1292. * 
  1293. * @since 3.1.0 
  1294. * 
  1295. * @see get_media_item 
  1296. * 
  1297. * @param array $args An array of arguments. 
  1298. */ 
  1299. $r = apply_filters( 'get_media_item_args', $args ); 
  1300.  
  1301. $toggle_on = __( 'Show' ); 
  1302. $toggle_off = __( 'Hide' ); 
  1303.  
  1304. $file = get_attached_file( $post->ID ); 
  1305. $filename = esc_html( wp_basename( $file ) ); 
  1306. $title = esc_attr( $post->post_title ); 
  1307.  
  1308. $post_mime_types = get_post_mime_types(); 
  1309. $keys = array_keys( wp_match_mime_types( array_keys( $post_mime_types ), $post->post_mime_type ) ); 
  1310. $type = reset( $keys ); 
  1311. $type_html = "<input type='hidden' id='type-of-$attachment_id' value='" . esc_attr( $type ) . "' />"; 
  1312.  
  1313. $form_fields = get_attachment_fields_to_edit( $post, $r['errors'] ); 
  1314.  
  1315. if ( $r['toggle'] ) { 
  1316. $class = empty( $r['errors'] ) ? 'startclosed' : 'startopen'; 
  1317. $toggle_links = " 
  1318. <a class='toggle describe-toggle-on' href='#'>$toggle_on</a> 
  1319. <a class='toggle describe-toggle-off' href='#'>$toggle_off</a>"; 
  1320. } else { 
  1321. $class = ''; 
  1322. $toggle_links = ''; 
  1323.  
  1324. $display_title = ( !empty( $title ) ) ? $title : $filename; // $title shouldn't ever be empty, but just in case 
  1325. $display_title = $r['show_title'] ? "<div class='filename new'><span class='title'>" . wp_html_excerpt( $display_title, 60, '…' ) . "</span></div>" : ''; 
  1326.  
  1327. $gallery = ( ( isset( $_REQUEST['tab'] ) && 'gallery' == $_REQUEST['tab'] ) || ( isset( $redir_tab ) && 'gallery' == $redir_tab ) ); 
  1328. $order = ''; 
  1329.  
  1330. foreach ( $form_fields as $key => $val ) { 
  1331. if ( 'menu_order' == $key ) { 
  1332. if ( $gallery ) 
  1333. $order = "<div class='menu_order'> <input class='menu_order_input' type='text' id='attachments[$attachment_id][menu_order]' name='attachments[$attachment_id][menu_order]' value='" . esc_attr( $val['value'] ). "' /></div>"; 
  1334. else 
  1335. $order = "<input type='hidden' name='attachments[$attachment_id][menu_order]' value='" . esc_attr( $val['value'] ) . "' />"; 
  1336.  
  1337. unset( $form_fields['menu_order'] ); 
  1338. break; 
  1339.  
  1340. $media_dims = ''; 
  1341. $meta = wp_get_attachment_metadata( $post->ID ); 
  1342. if ( isset( $meta['width'], $meta['height'] ) ) 
  1343. $media_dims .= "<span id='media-dims-$post->ID'>{$meta['width']} × {$meta['height']}</span> "; 
  1344.  
  1345. /** 
  1346. * Filters the media metadata. 
  1347. * 
  1348. * @since 2.5.0 
  1349. * 
  1350. * @param string $media_dims The HTML markup containing the media dimensions. 
  1351. * @param WP_Post $post The WP_Post attachment object. 
  1352. */ 
  1353. $media_dims = apply_filters( 'media_meta', $media_dims, $post ); 
  1354.  
  1355. $image_edit_button = ''; 
  1356. if ( wp_attachment_is_image( $post->ID ) && wp_image_editor_supports( array( 'mime_type' => $post->post_mime_type ) ) ) { 
  1357. $nonce = wp_create_nonce( "image_editor-$post->ID" ); 
  1358. $image_edit_button = "<input type='button' id='imgedit-open-btn-$post->ID' onclick='imageEdit.open( $post->ID, \"$nonce\" )' class='button' value='" . esc_attr__( 'Edit Image' ) . "' /> <span class='spinner'></span>"; 
  1359.  
  1360. $attachment_url = get_permalink( $attachment_id ); 
  1361.  
  1362. $item = " 
  1363. $type_html 
  1364. $toggle_links 
  1365. $order 
  1366. $display_title 
  1367. <table class='slidetoggle describe $class'> 
  1368. <thead class='media-item-info' id='media-head-$post->ID'> 
  1369. <tr> 
  1370. <td class='A1B1' id='thumbnail-head-$post->ID'> 
  1371. <p><a href='$attachment_url' target='_blank'><img class='thumbnail' src='$thumb_url' alt='' /></a></p> 
  1372. <p>$image_edit_button</p> 
  1373. </td> 
  1374. <td> 
  1375. <p><strong>" . __('File name:') . "</strong> $filename</p> 
  1376. <p><strong>" . __('File type:') . "</strong> $post->post_mime_type</p> 
  1377. <p><strong>" . __('Upload date:') . "</strong> " . mysql2date( __( 'F j, Y' ), $post->post_date ). '</p>'; 
  1378. if ( !empty( $media_dims ) ) 
  1379. $item .= "<p><strong>" . __('Dimensions:') . "</strong> $media_dims</p>\n"; 
  1380.  
  1381. $item .= "</td></tr>\n"; 
  1382.  
  1383. $item .= " 
  1384. </thead> 
  1385. <tbody> 
  1386. <tr><td colspan='2' class='imgedit-response' id='imgedit-response-$post->ID'></td></tr>\n 
  1387. <tr><td style='display:none' colspan='2' class='image-editor' id='image-editor-$post->ID'></td></tr>\n 
  1388. <tr><td colspan='2'><p class='media-types media-types-required-info'>" . sprintf( __( 'Required fields are marked %s' ), '<span class="required">*</span>' ) . "</p></td></tr>\n"; 
  1389.  
  1390. $defaults = array( 
  1391. 'input' => 'text',  
  1392. 'required' => false,  
  1393. 'value' => '',  
  1394. 'extra_rows' => array(),  
  1395. ); 
  1396.  
  1397. if ( $r['send'] ) { 
  1398. $r['send'] = get_submit_button( __( 'Insert into Post' ), '', "send[$attachment_id]", false ); 
  1399.  
  1400. $delete = empty( $r['delete'] ) ? '' : $r['delete']; 
  1401. if ( $delete && current_user_can( 'delete_post', $attachment_id ) ) { 
  1402. if ( !EMPTY_TRASH_DAYS ) { 
  1403. $delete = "<a href='" . wp_nonce_url( "post.php?action=delete&post=$attachment_id", 'delete-post_' . $attachment_id ) . "' id='del[$attachment_id]' class='delete-permanently'>" . __( 'Delete Permanently' ) . '</a>'; 
  1404. } elseif ( !MEDIA_TRASH ) { 
  1405. $delete = "<a href='#' class='del-link' onclick=\"document.getElementById('del_attachment_$attachment_id').style.display='block';return false;\">" . __( 'Delete' ) . "</a> 
  1406. <div id='del_attachment_$attachment_id' class='del-attachment' style='display:none;'>" . 
  1407. /** translators: %s: file name */ 
  1408. '<p>' . sprintf( __( 'You are about to delete %s.' ), '<strong>' . $filename . '</strong>' ) . "</p> 
  1409. <a href='" . wp_nonce_url( "post.php?action=delete&post=$attachment_id", 'delete-post_' . $attachment_id ) . "' id='del[$attachment_id]' class='button'>" . __( 'Continue' ) . "</a> 
  1410. <a href='#' class='button' onclick=\"this.parentNode.style.display='none';return false;\">" . __( 'Cancel' ) . "</a> 
  1411. </div>"; 
  1412. } else { 
  1413. $delete = "<a href='" . wp_nonce_url( "post.php?action=trash&post=$attachment_id", 'trash-post_' . $attachment_id ) . "' id='del[$attachment_id]' class='delete'>" . __( 'Move to Trash' ) . "</a> 
  1414. <a href='" . wp_nonce_url( "post.php?action=untrash&post=$attachment_id", 'untrash-post_' . $attachment_id ) . "' id='undo[$attachment_id]' class='undo hidden'>" . __( 'Undo' ) . "</a>"; 
  1415. } else { 
  1416. $delete = ''; 
  1417.  
  1418. $thumbnail = ''; 
  1419. $calling_post_id = 0; 
  1420. if ( isset( $_GET['post_id'] ) ) { 
  1421. $calling_post_id = absint( $_GET['post_id'] ); 
  1422. } elseif ( isset( $_POST ) && count( $_POST ) ) {// Like for async-upload where $_GET['post_id'] isn't set 
  1423. $calling_post_id = $post->post_parent; 
  1424. if ( 'image' == $type && $calling_post_id && current_theme_supports( 'post-thumbnails', get_post_type( $calling_post_id ) ) 
  1425. && post_type_supports( get_post_type( $calling_post_id ), 'thumbnail' ) && get_post_thumbnail_id( $calling_post_id ) != $attachment_id ) { 
  1426.  
  1427. $calling_post = get_post( $calling_post_id ); 
  1428. $calling_post_type_object = get_post_type_object( $calling_post->post_type ); 
  1429.  
  1430. $ajax_nonce = wp_create_nonce( "set_post_thumbnail-$calling_post_id" ); 
  1431. $thumbnail = "<a class='wp-post-thumbnail' id='wp-post-thumbnail-" . $attachment_id . "' href='#' onclick='WPSetAsThumbnail(\"$attachment_id\", \"$ajax_nonce\");return false;'>" . esc_html( $calling_post_type_object->labels->use_featured_image ) . "</a>"; 
  1432.  
  1433. if ( ( $r['send'] || $thumbnail || $delete ) && !isset( $form_fields['buttons'] ) ) { 
  1434. $form_fields['buttons'] = array( 'tr' => "\t\t<tr class='submit'><td></td><td class='savesend'>" . $r['send'] . " $thumbnail $delete</td></tr>\n" ); 
  1435. $hidden_fields = array(); 
  1436.  
  1437. foreach ( $form_fields as $id => $field ) { 
  1438. if ( $id[0] == '_' ) 
  1439. continue; 
  1440.  
  1441. if ( !empty( $field['tr'] ) ) { 
  1442. $item .= $field['tr']; 
  1443. continue; 
  1444.  
  1445. $field = array_merge( $defaults, $field ); 
  1446. $name = "attachments[$attachment_id][$id]"; 
  1447.  
  1448. if ( $field['input'] == 'hidden' ) { 
  1449. $hidden_fields[$name] = $field['value']; 
  1450. continue; 
  1451.  
  1452. $required = $field['required'] ? '<span class="required">*</span>' : ''; 
  1453. $required_attr = $field['required'] ? ' required' : ''; 
  1454. $aria_required = $field['required'] ? " aria-required='true'" : ''; 
  1455. $class = $id; 
  1456. $class .= $field['required'] ? ' form-required' : ''; 
  1457.  
  1458. $item .= "\t\t<tr class='$class'>\n\t\t\t<th scope='row' class='label'><label for='$name'><span class='alignleft'>{$field['label']}{$required}</span><br class='clear' /></label></th>\n\t\t\t<td class='field'>"; 
  1459. if ( !empty( $field[ $field['input'] ] ) ) 
  1460. $item .= $field[ $field['input'] ]; 
  1461. elseif ( $field['input'] == 'textarea' ) { 
  1462. if ( 'post_content' == $id && user_can_richedit() ) { 
  1463. // Sanitize_post() skips the post_content when user_can_richedit. 
  1464. $field['value'] = htmlspecialchars( $field['value'], ENT_QUOTES ); 
  1465. // Post_excerpt is already escaped by sanitize_post() in get_attachment_fields_to_edit(). 
  1466. $item .= "<textarea id='$name' name='$name'{$required_attr}{$aria_required}>" . $field['value'] . '</textarea>'; 
  1467. } else { 
  1468. $item .= "<input type='text' class='text' id='$name' name='$name' value='" . esc_attr( $field['value'] ) . "'{$required_attr}{$aria_required} />"; 
  1469. if ( !empty( $field['helps'] ) ) 
  1470. $item .= "<p class='help'>" . join( "</p>\n<p class='help'>", array_unique( (array) $field['helps'] ) ) . '</p>'; 
  1471. $item .= "</td>\n\t\t</tr>\n"; 
  1472.  
  1473. $extra_rows = array(); 
  1474.  
  1475. if ( !empty( $field['errors'] ) ) 
  1476. foreach ( array_unique( (array) $field['errors'] ) as $error ) 
  1477. $extra_rows['error'][] = $error; 
  1478.  
  1479. if ( !empty( $field['extra_rows'] ) ) 
  1480. foreach ( $field['extra_rows'] as $class => $rows ) 
  1481. foreach ( (array) $rows as $html ) 
  1482. $extra_rows[$class][] = $html; 
  1483.  
  1484. foreach ( $extra_rows as $class => $rows ) 
  1485. foreach ( $rows as $html ) 
  1486. $item .= "\t\t<tr><td></td><td class='$class'>$html</td></tr>\n"; 
  1487.  
  1488. if ( !empty( $form_fields['_final'] ) ) 
  1489. $item .= "\t\t<tr class='final'><td colspan='2'>{$form_fields['_final']}</td></tr>\n"; 
  1490. $item .= "\t</tbody>\n"; 
  1491. $item .= "\t</table>\n"; 
  1492.  
  1493. foreach ( $hidden_fields as $name => $value ) 
  1494. $item .= "\t<input type='hidden' name='$name' id='$name' value='" . esc_attr( $value ) . "' />\n"; 
  1495.  
  1496. if ( $post->post_parent < 1 && isset( $_REQUEST['post_id'] ) ) { 
  1497. $parent = (int) $_REQUEST['post_id']; 
  1498. $parent_name = "attachments[$attachment_id][post_parent]"; 
  1499. $item .= "\t<input type='hidden' name='$parent_name' id='$parent_name' value='$parent' />\n"; 
  1500.  
  1501. return $item; 
  1502.  
  1503. /** 
  1504. * @since 3.5.0 
  1505. * 
  1506. * @param int $attachment_id 
  1507. * @param array $args 
  1508. * @return array 
  1509. */ 
  1510. function get_compat_media_markup( $attachment_id, $args = null ) { 
  1511. $post = get_post( $attachment_id ); 
  1512.  
  1513. $default_args = array( 
  1514. 'errors' => null,  
  1515. 'in_modal' => false,  
  1516. ); 
  1517.  
  1518. $user_can_edit = current_user_can( 'edit_post', $attachment_id ); 
  1519.  
  1520. $args = wp_parse_args( $args, $default_args ); 
  1521.  
  1522. /** This filter is documented in wp-admin/includes/media.php */ 
  1523. $args = apply_filters( 'get_media_item_args', $args ); 
  1524.  
  1525. $form_fields = array(); 
  1526.  
  1527. if ( $args['in_modal'] ) { 
  1528. foreach ( get_attachment_taxonomies($post) as $taxonomy ) { 
  1529. $t = (array) get_taxonomy($taxonomy); 
  1530. if ( ! $t['public'] || ! $t['show_ui'] ) 
  1531. continue; 
  1532. if ( empty($t['label']) ) 
  1533. $t['label'] = $taxonomy; 
  1534. if ( empty($t['args']) ) 
  1535. $t['args'] = array(); 
  1536.  
  1537. $terms = get_object_term_cache($post->ID, $taxonomy); 
  1538. if ( false === $terms ) 
  1539. $terms = wp_get_object_terms($post->ID, $taxonomy, $t['args']); 
  1540.  
  1541. $values = array(); 
  1542.  
  1543. foreach ( $terms as $term ) 
  1544. $values[] = $term->slug; 
  1545. $t['value'] = join(', ', $values); 
  1546. $t['taxonomy'] = true; 
  1547.  
  1548. $form_fields[$taxonomy] = $t; 
  1549.  
  1550. // Merge default fields with their errors, so any key passed with the error (e.g. 'error', 'helps', 'value') will replace the default 
  1551. // The recursive merge is easily traversed with array casting: foreach ( (array) $things as $thing ) 
  1552. $form_fields = array_merge_recursive($form_fields, (array) $args['errors'] ); 
  1553.  
  1554. /** This filter is documented in wp-admin/includes/media.php */ 
  1555. $form_fields = apply_filters( 'attachment_fields_to_edit', $form_fields, $post ); 
  1556.  
  1557. unset( $form_fields['image-size'], $form_fields['align'], $form_fields['image_alt'],  
  1558. $form_fields['post_title'], $form_fields['post_excerpt'], $form_fields['post_content'],  
  1559. $form_fields['url'], $form_fields['menu_order'], $form_fields['image_url'] ); 
  1560.  
  1561. /** This filter is documented in wp-admin/includes/media.php */ 
  1562. $media_meta = apply_filters( 'media_meta', '', $post ); 
  1563.  
  1564. $defaults = array( 
  1565. 'input' => 'text',  
  1566. 'required' => false,  
  1567. 'value' => '',  
  1568. 'extra_rows' => array(),  
  1569. 'show_in_edit' => true,  
  1570. 'show_in_modal' => true,  
  1571. ); 
  1572.  
  1573. $hidden_fields = array(); 
  1574.  
  1575. $item = ''; 
  1576. foreach ( $form_fields as $id => $field ) { 
  1577. if ( $id[0] == '_' ) 
  1578. continue; 
  1579.  
  1580. $name = "attachments[$attachment_id][$id]"; 
  1581. $id_attr = "attachments-$attachment_id-$id"; 
  1582.  
  1583. if ( !empty( $field['tr'] ) ) { 
  1584. $item .= $field['tr']; 
  1585. continue; 
  1586.  
  1587. $field = array_merge( $defaults, $field ); 
  1588.  
  1589. if ( ( ! $field['show_in_edit'] && ! $args['in_modal'] ) || ( ! $field['show_in_modal'] && $args['in_modal'] ) ) 
  1590. continue; 
  1591.  
  1592. if ( $field['input'] == 'hidden' ) { 
  1593. $hidden_fields[$name] = $field['value']; 
  1594. continue; 
  1595.  
  1596. $readonly = ! $user_can_edit && ! empty( $field['taxonomy'] ) ? " readonly='readonly' " : ''; 
  1597. $required = $field['required'] ? '<span class="required">*</span>' : ''; 
  1598. $required_attr = $field['required'] ? ' required' : ''; 
  1599. $aria_required = $field['required'] ? " aria-required='true'" : ''; 
  1600. $class = 'compat-field-' . $id; 
  1601. $class .= $field['required'] ? ' form-required' : ''; 
  1602.  
  1603. $item .= "\t\t<tr class='$class'>"; 
  1604. $item .= "\t\t\t<th scope='row' class='label'><label for='$id_attr'><span class='alignleft'>{$field['label']}</span>$required<br class='clear' /></label>"; 
  1605. $item .= "</th>\n\t\t\t<td class='field'>"; 
  1606.  
  1607. if ( !empty( $field[ $field['input'] ] ) ) 
  1608. $item .= $field[ $field['input'] ]; 
  1609. elseif ( $field['input'] == 'textarea' ) { 
  1610. if ( 'post_content' == $id && user_can_richedit() ) { 
  1611. // sanitize_post() skips the post_content when user_can_richedit. 
  1612. $field['value'] = htmlspecialchars( $field['value'], ENT_QUOTES ); 
  1613. $item .= "<textarea id='$id_attr' name='$name'{$required_attr}{$aria_required}>" . $field['value'] . '</textarea>'; 
  1614. } else { 
  1615. $item .= "<input type='text' class='text' id='$id_attr' name='$name' value='" . esc_attr( $field['value'] ) . "' $readonly{$required_attr}{$aria_required} />"; 
  1616. if ( !empty( $field['helps'] ) ) 
  1617. $item .= "<p class='help'>" . join( "</p>\n<p class='help'>", array_unique( (array) $field['helps'] ) ) . '</p>'; 
  1618. $item .= "</td>\n\t\t</tr>\n"; 
  1619.  
  1620. $extra_rows = array(); 
  1621.  
  1622. if ( !empty( $field['errors'] ) ) 
  1623. foreach ( array_unique( (array) $field['errors'] ) as $error ) 
  1624. $extra_rows['error'][] = $error; 
  1625.  
  1626. if ( !empty( $field['extra_rows'] ) ) 
  1627. foreach ( $field['extra_rows'] as $class => $rows ) 
  1628. foreach ( (array) $rows as $html ) 
  1629. $extra_rows[$class][] = $html; 
  1630.  
  1631. foreach ( $extra_rows as $class => $rows ) 
  1632. foreach ( $rows as $html ) 
  1633. $item .= "\t\t<tr><td></td><td class='$class'>$html</td></tr>\n"; 
  1634.  
  1635. if ( !empty( $form_fields['_final'] ) ) 
  1636. $item .= "\t\t<tr class='final'><td colspan='2'>{$form_fields['_final']}</td></tr>\n"; 
  1637.  
  1638. if ( $item ) { 
  1639. $item = '<p class="media-types media-types-required-info">' . 
  1640. sprintf( __( 'Required fields are marked %s' ), '<span class="required">*</span>' ) . '</p> 
  1641. <table class="compat-attachment-fields">' . $item . '</table>'; 
  1642.  
  1643. foreach ( $hidden_fields as $hidden_field => $value ) { 
  1644. $item .= '<input type="hidden" name="' . esc_attr( $hidden_field ) . '" value="' . esc_attr( $value ) . '" />' . "\n"; 
  1645.  
  1646. if ( $item ) 
  1647. $item = '<input type="hidden" name="attachments[' . $attachment_id . '][menu_order]" value="' . esc_attr( $post->menu_order ) . '" />' . $item; 
  1648.  
  1649. return array( 
  1650. 'item' => $item,  
  1651. 'meta' => $media_meta,  
  1652. ); 
  1653.  
  1654. /** 
  1655. * Outputs the legacy media upload header. 
  1656. * 
  1657. * @since 2.5.0 
  1658. */ 
  1659. function media_upload_header() { 
  1660. $post_id = isset( $_REQUEST['post_id'] ) ? intval( $_REQUEST['post_id'] ) : 0; 
  1661.  
  1662. echo '<script type="text/javascript">post_id = ' . $post_id . ';</script>'; 
  1663. if ( empty( $_GET['chromeless'] ) ) { 
  1664. echo '<div id="media-upload-header">'; 
  1665. the_media_upload_tabs(); 
  1666. echo '</div>'; 
  1667.  
  1668. /** 
  1669. * Outputs the legacy media upload form. 
  1670. * 
  1671. * @since 2.5.0 
  1672. * 
  1673. * @global string $type 
  1674. * @global string $tab 
  1675. * @global bool $is_IE 
  1676. * @global bool $is_opera 
  1677. * 
  1678. * @param array $errors 
  1679. */ 
  1680. function media_upload_form( $errors = null ) { 
  1681. global $type, $tab, $is_IE, $is_opera; 
  1682.  
  1683. if ( ! _device_can_upload() ) { 
  1684. echo '<p>' . sprintf( __('The web browser on your device cannot be used to upload files. You may be able to use the <a href="%s">native app for your device</a> instead.'), 'https://apps.wordpress.org/' ) . '</p>'; 
  1685. return; 
  1686.  
  1687. $upload_action_url = admin_url('async-upload.php'); 
  1688. $post_id = isset($_REQUEST['post_id']) ? intval($_REQUEST['post_id']) : 0; 
  1689. $_type = isset($type) ? $type : ''; 
  1690. $_tab = isset($tab) ? $tab : ''; 
  1691.  
  1692. $max_upload_size = wp_max_upload_size(); 
  1693. if ( ! $max_upload_size ) { 
  1694. $max_upload_size = 0; 
  1695. ?> 
  1696.  
  1697. <div id="media-upload-notice"><?php 
  1698.  
  1699. if (isset($errors['upload_notice']) ) 
  1700. echo $errors['upload_notice']; 
  1701.  
  1702. ?></div> 
  1703. <div id="media-upload-error"><?php 
  1704.  
  1705. if (isset($errors['upload_error']) && is_wp_error($errors['upload_error'])) 
  1706. echo $errors['upload_error']->get_error_message(); 
  1707.  
  1708. ?></div> 
  1709. <?php 
  1710. if ( is_multisite() && !is_upload_space_available() ) { 
  1711. /** 
  1712. * Fires when an upload will exceed the defined upload space quota for a network site. 
  1713. * 
  1714. * @since 3.5.0 
  1715. */ 
  1716. do_action( 'upload_ui_over_quota' ); 
  1717. return; 
  1718.  
  1719. /** 
  1720. * Fires just before the legacy (pre-3.5.0) upload interface is loaded. 
  1721. * 
  1722. * @since 2.6.0 
  1723. */ 
  1724. do_action( 'pre-upload-ui' ); 
  1725.  
  1726. $post_params = array( 
  1727. "post_id" => $post_id,  
  1728. "_wpnonce" => wp_create_nonce('media-form'),  
  1729. "type" => $_type,  
  1730. "tab" => $_tab,  
  1731. "short" => "1",  
  1732. ); 
  1733.  
  1734. /** 
  1735. * Filters the media upload post parameters. 
  1736. * 
  1737. * @since 3.1.0 As 'swfupload_post_params' 
  1738. * @since 3.3.0 
  1739. * 
  1740. * @param array $post_params An array of media upload parameters used by Plupload. 
  1741. */ 
  1742. $post_params = apply_filters( 'upload_post_params', $post_params ); 
  1743.  
  1744. $plupload_init = array( 
  1745. 'runtimes' => 'html5, flash, silverlight, html4',  
  1746. 'browse_button' => 'plupload-browse-button',  
  1747. 'container' => 'plupload-upload-ui',  
  1748. 'drop_element' => 'drag-drop-area',  
  1749. 'file_data_name' => 'async-upload',  
  1750. 'url' => $upload_action_url,  
  1751. 'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),  
  1752. 'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),  
  1753. 'filters' => array( 
  1754. 'max_file_size' => $max_upload_size . 'b',  
  1755. ),  
  1756. 'multipart_params' => $post_params,  
  1757. ); 
  1758.  
  1759. // Currently only iOS Safari supports multiple files uploading but iOS 7.x has a bug that prevents uploading of videos 
  1760. // when enabled. See #29602. 
  1761. if ( wp_is_mobile() && strpos( $_SERVER['HTTP_USER_AGENT'], 'OS 7_' ) !== false && 
  1762. strpos( $_SERVER['HTTP_USER_AGENT'], 'like Mac OS X' ) !== false ) { 
  1763.  
  1764. $plupload_init['multi_selection'] = false; 
  1765.  
  1766. /** 
  1767. * Filters the default Plupload settings. 
  1768. * 
  1769. * @since 3.3.0 
  1770. * 
  1771. * @param array $plupload_init An array of default settings used by Plupload. 
  1772. */ 
  1773. $plupload_init = apply_filters( 'plupload_init', $plupload_init ); 
  1774.  
  1775. ?> 
  1776.  
  1777. <script type="text/javascript"> 
  1778. <?php 
  1779. // Verify size is an int. If not return default value. 
  1780. $large_size_h = absint( get_option('large_size_h') ); 
  1781. if( !$large_size_h ) 
  1782. $large_size_h = 1024; 
  1783. $large_size_w = absint( get_option('large_size_w') ); 
  1784. if( !$large_size_w ) 
  1785. $large_size_w = 1024; 
  1786. ?> 
  1787. var resize_height = <?php echo $large_size_h; ?>, resize_width = <?php echo $large_size_w; ?>,  
  1788. wpUploaderInit = <?php echo wp_json_encode( $plupload_init ); ?>; 
  1789. </script> 
  1790.  
  1791. <div id="plupload-upload-ui" class="hide-if-no-js"> 
  1792. <?php 
  1793. /** 
  1794. * Fires before the upload interface loads. 
  1795. * 
  1796. * @since 2.6.0 As 'pre-flash-upload-ui' 
  1797. * @since 3.3.0 
  1798. */ 
  1799. do_action( 'pre-plupload-upload-ui' ); ?> 
  1800. <div id="drag-drop-area"> 
  1801. <div class="drag-drop-inside"> 
  1802. <p class="drag-drop-info"><?php _e('Drop files here'); ?></p> 
  1803. <p><?php _ex('or', 'Uploader: Drop files here - or - Select Files'); ?></p> 
  1804. <p class="drag-drop-buttons"><input id="plupload-browse-button" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p> 
  1805. </div> 
  1806. </div> 
  1807. <?php 
  1808. /** 
  1809. * Fires after the upload interface loads. 
  1810. * 
  1811. * @since 2.6.0 As 'post-flash-upload-ui' 
  1812. * @since 3.3.0 
  1813. */ 
  1814. do_action( 'post-plupload-upload-ui' ); ?> 
  1815. </div> 
  1816.  
  1817. <div id="html-upload-ui" class="hide-if-js"> 
  1818. <?php 
  1819. /** 
  1820. * Fires before the upload button in the media upload interface. 
  1821. * 
  1822. * @since 2.6.0 
  1823. */ 
  1824. do_action( 'pre-html-upload-ui' ); 
  1825. ?> 
  1826. <p id="async-upload-wrap"> 
  1827. <label class="screen-reader-text" for="async-upload"><?php _e('Upload'); ?></label> 
  1828. <input type="file" name="async-upload" id="async-upload" /> 
  1829. <?php submit_button( __( 'Upload' ), 'primary', 'html-upload', false ); ?> 
  1830. <a href="#" onclick="try{top.tb_remove();}catch(e) {}; return false;"><?php _e('Cancel'); ?></a> 
  1831. </p> 
  1832. <div class="clear"></div> 
  1833. <?php 
  1834. /** 
  1835. * Fires after the upload button in the media upload interface. 
  1836. * 
  1837. * @since 2.6.0 
  1838. */ 
  1839. do_action( 'post-html-upload-ui' ); 
  1840. ?> 
  1841. </div> 
  1842.  
  1843. <p class="max-upload-size"><?php printf( __( 'Maximum upload file size: %s.' ), esc_html( size_format( $max_upload_size ) ) ); ?></p> 
  1844. <?php 
  1845.  
  1846. /** 
  1847. * Fires on the post upload UI screen. 
  1848. * 
  1849. * Legacy (pre-3.5.0) media workflow hook. 
  1850. * 
  1851. * @since 2.6.0 
  1852. */ 
  1853. do_action( 'post-upload-ui' ); 
  1854.  
  1855. /** 
  1856. * Outputs the legacy media upload form for a given media type. 
  1857. * 
  1858. * @since 2.5.0 
  1859. * 
  1860. * @param string $type 
  1861. * @param object $errors 
  1862. * @param integer $id 
  1863. */ 
  1864. function media_upload_type_form($type = 'file', $errors = null, $id = null) { 
  1865.  
  1866. media_upload_header(); 
  1867.  
  1868. $post_id = isset( $_REQUEST['post_id'] )? intval( $_REQUEST['post_id'] ) : 0; 
  1869.  
  1870. $form_action_url = admin_url("media-upload.php?type=$type&tab=type&post_id=$post_id"); 
  1871.  
  1872. /** 
  1873. * Filters the media upload form action URL. 
  1874. * 
  1875. * @since 2.6.0 
  1876. * 
  1877. * @param string $form_action_url The media upload form action URL. 
  1878. * @param string $type The type of media. Default 'file'. 
  1879. */ 
  1880. $form_action_url = apply_filters( 'media_upload_form_url', $form_action_url, $type ); 
  1881. $form_class = 'media-upload-form type-form validate'; 
  1882.  
  1883. if ( get_user_setting('uploader') ) 
  1884. $form_class .= ' html-uploader'; 
  1885. ?> 
  1886.  
  1887. <form enctype="multipart/form-data" method="post" action="<?php echo esc_url( $form_action_url ); ?>" class="<?php echo $form_class; ?>" id="<?php echo $type; ?>-form"> 
  1888. <?php submit_button( '', 'hidden', 'save', false ); ?> 
  1889. <input type="hidden" name="post_id" id="post_id" value="<?php echo (int) $post_id; ?>" /> 
  1890. <?php wp_nonce_field('media-form'); ?> 
  1891.  
  1892. <h3 class="media-title"><?php _e('Add media files from your computer'); ?></h3> 
  1893.  
  1894. <?php media_upload_form( $errors ); ?> 
  1895.  
  1896. <script type="text/javascript"> 
  1897. jQuery(function($) { 
  1898. var preloaded = $(".media-item.preloaded"); 
  1899. if ( preloaded.length > 0 ) { 
  1900. preloaded.each(function() {prepareMediaItem({id:this.id.replace(/[^0-9]/g, '')}, '');}); 
  1901. updateMediaForm(); 
  1902. }); 
  1903. </script> 
  1904. <div id="media-items"><?php 
  1905.  
  1906. if ( $id ) { 
  1907. if ( !is_wp_error($id) ) { 
  1908. add_filter('attachment_fields_to_edit', 'media_post_single_attachment_fields_to_edit', 10, 2); 
  1909. echo get_media_items( $id, $errors ); 
  1910. } else { 
  1911. echo '<div id="media-upload-error">'.esc_html($id->get_error_message()).'</div></div>'; 
  1912. exit; 
  1913. ?></div> 
  1914.  
  1915. <p class="savebutton ml-submit"> 
  1916. <?php submit_button( __( 'Save all changes' ), '', 'save', false ); ?> 
  1917. </p> 
  1918. </form> 
  1919. <?php 
  1920.  
  1921. /** 
  1922. * Outputs the legacy media upload form for external media. 
  1923. * 
  1924. * @since 2.7.0 
  1925. * 
  1926. * @param string $type 
  1927. * @param object $errors 
  1928. * @param integer $id 
  1929. */ 
  1930. function media_upload_type_url_form($type = null, $errors = null, $id = null) { 
  1931. if ( null === $type ) 
  1932. $type = 'image'; 
  1933.  
  1934. media_upload_header(); 
  1935.  
  1936. $post_id = isset( $_REQUEST['post_id'] ) ? intval( $_REQUEST['post_id'] ) : 0; 
  1937.  
  1938. $form_action_url = admin_url("media-upload.php?type=$type&tab=type&post_id=$post_id"); 
  1939. /** This filter is documented in wp-admin/includes/media.php */ 
  1940. $form_action_url = apply_filters( 'media_upload_form_url', $form_action_url, $type ); 
  1941. $form_class = 'media-upload-form type-form validate'; 
  1942.  
  1943. if ( get_user_setting('uploader') ) 
  1944. $form_class .= ' html-uploader'; 
  1945. ?> 
  1946.  
  1947. <form enctype="multipart/form-data" method="post" action="<?php echo esc_url( $form_action_url ); ?>" class="<?php echo $form_class; ?>" id="<?php echo $type; ?>-form"> 
  1948. <input type="hidden" name="post_id" id="post_id" value="<?php echo (int) $post_id; ?>" /> 
  1949. <?php wp_nonce_field('media-form'); ?> 
  1950.  
  1951. <h3 class="media-title"><?php _e('Insert media from another website'); ?></h3> 
  1952.  
  1953. <script type="text/javascript"> 
  1954. var addExtImage = { 
  1955.  
  1956. width : '',  
  1957. height : '',  
  1958. align : 'alignnone',  
  1959.  
  1960. insert : function() { 
  1961. var t = this, html, f = document.forms[0], cls, title = '', alt = '', caption = ''; 
  1962.  
  1963. if ( '' == f.src.value || '' == t.width ) 
  1964. return false; 
  1965.  
  1966. if ( f.alt.value ) 
  1967. alt = f.alt.value.replace(/'/g, ''').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>'); 
  1968.  
  1969. <?php 
  1970. /** This filter is documented in wp-admin/includes/media.php */ 
  1971. if ( ! apply_filters( 'disable_captions', '' ) ) { 
  1972. ?> 
  1973. if ( f.caption.value ) { 
  1974. caption = f.caption.value.replace(/\r\n|\r/g, '\n'); 
  1975. caption = caption.replace(/<[a-zA-Z0-9]+( [^<>]+)?>/g, function(a) { 
  1976. return a.replace(/[\r\n\t]+/, ' '); 
  1977. }); 
  1978.  
  1979. caption = caption.replace(/\s*\n\s*/g, '<br />'); 
  1980. <?php } ?> 
  1981.  
  1982. cls = caption ? '' : ' class="'+t.align+'"'; 
  1983.  
  1984. html = '<img alt="'+alt+'" src="'+f.src.value+'"'+cls+' width="'+t.width+'" height="'+t.height+'" />'; 
  1985.  
  1986. if ( f.url.value ) { 
  1987. url = f.url.value.replace(/'/g, ''').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>'); 
  1988. html = '<a href="'+url+'">'+html+'</a>'; 
  1989.  
  1990. if ( caption ) 
  1991. html = ''+html+caption+''; 
  1992.  
  1993. var win = window.dialogArguments || opener || parent || top; 
  1994. win.send_to_editor(html); 
  1995. return false; 
  1996. },  
  1997.  
  1998. resetImageData : function() { 
  1999. var t = addExtImage; 
  2000.  
  2001. t.width = t.height = ''; 
  2002. document.getElementById('go_button').style.color = '#bbb'; 
  2003. if ( ! document.forms[0].src.value ) 
  2004. document.getElementById('status_img').innerHTML = ''; 
  2005. else document.getElementById('status_img').innerHTML = '<img src="<?php echo esc_url( admin_url( 'images/no.png' ) ); ?>" alt="" />'; 
  2006. },  
  2007.  
  2008. updateImageData : function() { 
  2009. var t = addExtImage; 
  2010.  
  2011. t.width = t.preloadImg.width; 
  2012. t.height = t.preloadImg.height; 
  2013. document.getElementById('go_button').style.color = '#333'; 
  2014. document.getElementById('status_img').innerHTML = '<img src="<?php echo esc_url( admin_url( 'images/yes.png' ) ); ?>" alt="" />'; 
  2015. },  
  2016.  
  2017. getImageData : function() { 
  2018. if ( jQuery('table.describe').hasClass('not-image') ) 
  2019. return; 
  2020.  
  2021. var t = addExtImage, src = document.forms[0].src.value; 
  2022.  
  2023. if ( ! src ) { 
  2024. t.resetImageData(); 
  2025. return false; 
  2026.  
  2027. document.getElementById('status_img').innerHTML = '<img src="<?php echo esc_url( admin_url( 'images/spinner-2x.gif' ) ); ?>" alt="" width="16" height="16" />'; 
  2028. t.preloadImg = new Image(); 
  2029. t.preloadImg.onload = t.updateImageData; 
  2030. t.preloadImg.onerror = t.resetImageData; 
  2031. t.preloadImg.src = src; 
  2032. }; 
  2033.  
  2034. jQuery(document).ready( function($) { 
  2035. $('.media-types input').click( function() { 
  2036. $('table.describe').toggleClass('not-image', $('#not-image').prop('checked') ); 
  2037. }); 
  2038. }); 
  2039. </script> 
  2040.  
  2041. <div id="media-items"> 
  2042. <div class="media-item media-blank"> 
  2043. <?php 
  2044. /** 
  2045. * Filters the insert media from URL form HTML. 
  2046. * 
  2047. * @since 3.3.0 
  2048. * 
  2049. * @param string $form_html The insert from URL form HTML. 
  2050. */ 
  2051. echo apply_filters( 'type_url_form_media', wp_media_insert_url_form( $type ) ); 
  2052. ?> 
  2053. </div> 
  2054. </div> 
  2055. </form> 
  2056. <?php 
  2057.  
  2058. /** 
  2059. * Adds gallery form to upload iframe 
  2060. * 
  2061. * @since 2.5.0 
  2062. * 
  2063. * @global string $redir_tab 
  2064. * @global string $type 
  2065. * @global string $tab 
  2066. * 
  2067. * @param array $errors 
  2068. */ 
  2069. function media_upload_gallery_form($errors) { 
  2070. global $redir_tab, $type; 
  2071.  
  2072. $redir_tab = 'gallery'; 
  2073. media_upload_header(); 
  2074.  
  2075. $post_id = intval($_REQUEST['post_id']); 
  2076. $form_action_url = admin_url("media-upload.php?type=$type&tab=gallery&post_id=$post_id"); 
  2077. /** This filter is documented in wp-admin/includes/media.php */ 
  2078. $form_action_url = apply_filters( 'media_upload_form_url', $form_action_url, $type ); 
  2079. $form_class = 'media-upload-form validate'; 
  2080.  
  2081. if ( get_user_setting('uploader') ) 
  2082. $form_class .= ' html-uploader'; 
  2083. ?> 
  2084.  
  2085. <script type="text/javascript"> 
  2086. jQuery(function($) { 
  2087. var preloaded = $(".media-item.preloaded"); 
  2088. if ( preloaded.length > 0 ) { 
  2089. preloaded.each(function() {prepareMediaItem({id:this.id.replace(/[^0-9]/g, '')}, '');}); 
  2090. updateMediaForm(); 
  2091. }); 
  2092. </script> 
  2093. <div id="sort-buttons" class="hide-if-no-js"> 
  2094. <span> 
  2095. <?php _e('All Tabs:'); ?> 
  2096. <a href="#" id="showall"><?php _e('Show'); ?></a> 
  2097. <a href="#" id="hideall" style="display:none;"><?php _e('Hide'); ?></a> 
  2098. </span> 
  2099. <?php _e('Sort Order:'); ?> 
  2100. <a href="#" id="asc"><?php _e('Ascending'); ?></a> | 
  2101. <a href="#" id="desc"><?php _e('Descending'); ?></a> | 
  2102. <a href="#" id="clear"><?php _ex('Clear', 'verb'); ?></a> 
  2103. </div> 
  2104. <form enctype="multipart/form-data" method="post" action="<?php echo esc_url( $form_action_url ); ?>" class="<?php echo $form_class; ?>" id="gallery-form"> 
  2105. <?php wp_nonce_field('media-form'); ?> 
  2106. <?php //media_upload_form( $errors ); ?> 
  2107. <table class="widefat"> 
  2108. <thead><tr> 
  2109. <th><?php _e('Media'); ?></th> 
  2110. <th class="order-head"><?php _e('Order'); ?></th> 
  2111. <th class="actions-head"><?php _e('Actions'); ?></th> 
  2112. </tr></thead> 
  2113. </table> 
  2114. <div id="media-items"> 
  2115. <?php add_filter('attachment_fields_to_edit', 'media_post_single_attachment_fields_to_edit', 10, 2); ?> 
  2116. <?php echo get_media_items($post_id, $errors); ?> 
  2117. </div> 
  2118.  
  2119. <p class="ml-submit"> 
  2120. <?php submit_button( __( 'Save all changes' ), 'savebutton', 'save', false, array( 'id' => 'save-all', 'style' => 'display: none;' ) ); ?> 
  2121. <input type="hidden" name="post_id" id="post_id" value="<?php echo (int) $post_id; ?>" /> 
  2122. <input type="hidden" name="type" value="<?php echo esc_attr( $GLOBALS['type'] ); ?>" /> 
  2123. <input type="hidden" name="tab" value="<?php echo esc_attr( $GLOBALS['tab'] ); ?>" /> 
  2124. </p> 
  2125.  
  2126. <div id="gallery-settings" style="display:none;"> 
  2127. <div class="title"><?php _e('Gallery Settings'); ?></div> 
  2128. <table id="basic" class="describe"><tbody> 
  2129. <tr> 
  2130. <th scope="row" class="label"> 
  2131. <label> 
  2132. <span class="alignleft"><?php _e('Link thumbnails to:'); ?></span> 
  2133. </label> 
  2134. </th> 
  2135. <td class="field"> 
  2136. <input type="radio" name="linkto" id="linkto-file" value="file" /> 
  2137. <label for="linkto-file" class="radio"><?php _e('Image File'); ?></label> 
  2138.  
  2139. <input type="radio" checked="checked" name="linkto" id="linkto-post" value="post" /> 
  2140. <label for="linkto-post" class="radio"><?php _e('Attachment Page'); ?></label> 
  2141. </td> 
  2142. </tr> 
  2143.  
  2144. <tr> 
  2145. <th scope="row" class="label"> 
  2146. <label> 
  2147. <span class="alignleft"><?php _e('Order images by:'); ?></span> 
  2148. </label> 
  2149. </th> 
  2150. <td class="field"> 
  2151. <select id="orderby" name="orderby"> 
  2152. <option value="menu_order" selected="selected"><?php _e('Menu order'); ?></option> 
  2153. <option value="title"><?php _e('Title'); ?></option> 
  2154. <option value="post_date"><?php _e('Date/Time'); ?></option> 
  2155. <option value="rand"><?php _e('Random'); ?></option> 
  2156. </select> 
  2157. </td> 
  2158. </tr> 
  2159.  
  2160. <tr> 
  2161. <th scope="row" class="label"> 
  2162. <label> 
  2163. <span class="alignleft"><?php _e('Order:'); ?></span> 
  2164. </label> 
  2165. </th> 
  2166. <td class="field"> 
  2167. <input type="radio" checked="checked" name="order" id="order-asc" value="asc" /> 
  2168. <label for="order-asc" class="radio"><?php _e('Ascending'); ?></label> 
  2169.  
  2170. <input type="radio" name="order" id="order-desc" value="desc" /> 
  2171. <label for="order-desc" class="radio"><?php _e('Descending'); ?></label> 
  2172. </td> 
  2173. </tr> 
  2174.  
  2175. <tr> 
  2176. <th scope="row" class="label"> 
  2177. <label> 
  2178. <span class="alignleft"><?php _e('Gallery columns:'); ?></span> 
  2179. </label> 
  2180. </th> 
  2181. <td class="field"> 
  2182. <select id="columns" name="columns"> 
  2183. <option value="1">1</option> 
  2184. <option value="2">2</option> 
  2185. <option value="3" selected="selected">3</option> 
  2186. <option value="4">4</option> 
  2187. <option value="5">5</option> 
  2188. <option value="6">6</option> 
  2189. <option value="7">7</option> 
  2190. <option value="8">8</option> 
  2191. <option value="9">9</option> 
  2192. </select> 
  2193. </td> 
  2194. </tr> 
  2195. </tbody></table> 
  2196.  
  2197. <p class="ml-submit"> 
  2198. <input type="button" class="button" style="display:none;" onMouseDown="wpgallery.update();" name="insert-gallery" id="insert-gallery" value="<?php esc_attr_e( 'Insert gallery' ); ?>" /> 
  2199. <input type="button" class="button" style="display:none;" onMouseDown="wpgallery.update();" name="update-gallery" id="update-gallery" value="<?php esc_attr_e( 'Update gallery settings' ); ?>" /> 
  2200. </p> 
  2201. </div> 
  2202. </form> 
  2203. <?php 
  2204.  
  2205. /** 
  2206. * Outputs the legacy media upload form for the media library. 
  2207. * 
  2208. * @since 2.5.0 
  2209. * 
  2210. * @global wpdb $wpdb 
  2211. * @global WP_Query $wp_query 
  2212. * @global WP_Locale $wp_locale 
  2213. * @global string $type 
  2214. * @global string $tab 
  2215. * @global array $post_mime_types 
  2216. * 
  2217. * @param array $errors 
  2218. */ 
  2219. function media_upload_library_form($errors) { 
  2220. global $wpdb, $wp_query, $wp_locale, $type, $tab, $post_mime_types; 
  2221.  
  2222. media_upload_header(); 
  2223.  
  2224. $post_id = isset( $_REQUEST['post_id'] ) ? intval( $_REQUEST['post_id'] ) : 0; 
  2225.  
  2226. $form_action_url = admin_url("media-upload.php?type=$type&tab=library&post_id=$post_id"); 
  2227. /** This filter is documented in wp-admin/includes/media.php */ 
  2228. $form_action_url = apply_filters( 'media_upload_form_url', $form_action_url, $type ); 
  2229. $form_class = 'media-upload-form validate'; 
  2230.  
  2231. if ( get_user_setting('uploader') ) 
  2232. $form_class .= ' html-uploader'; 
  2233.  
  2234. $q = $_GET; 
  2235. $q['posts_per_page'] = 10; 
  2236. $q['paged'] = isset( $q['paged'] ) ? intval( $q['paged'] ) : 0; 
  2237. if ( $q['paged'] < 1 ) { 
  2238. $q['paged'] = 1; 
  2239. $q['offset'] = ( $q['paged'] - 1 ) * 10; 
  2240. if ( $q['offset'] < 1 ) { 
  2241. $q['offset'] = 0; 
  2242.  
  2243. list($post_mime_types, $avail_post_mime_types) = wp_edit_attachments_query( $q ); 
  2244.  
  2245. ?> 
  2246.  
  2247. <form id="filter" method="get"> 
  2248. <input type="hidden" name="type" value="<?php echo esc_attr( $type ); ?>" /> 
  2249. <input type="hidden" name="tab" value="<?php echo esc_attr( $tab ); ?>" /> 
  2250. <input type="hidden" name="post_id" value="<?php echo (int) $post_id; ?>" /> 
  2251. <input type="hidden" name="post_mime_type" value="<?php echo isset( $_GET['post_mime_type'] ) ? esc_attr( $_GET['post_mime_type'] ) : ''; ?>" /> 
  2252. <input type="hidden" name="context" value="<?php echo isset( $_GET['context'] ) ? esc_attr( $_GET['context'] ) : ''; ?>" /> 
  2253.  
  2254. <p id="media-search" class="search-box"> 
  2255. <label class="screen-reader-text" for="media-search-input"><?php _e('Search Media');?>:</label> 
  2256. <input type="search" id="media-search-input" name="s" value="<?php the_search_query(); ?>" /> 
  2257. <?php submit_button( __( 'Search Media' ), '', '', false ); ?> 
  2258. </p> 
  2259.  
  2260. <ul class="subsubsub"> 
  2261. <?php 
  2262. $type_links = array(); 
  2263. $_num_posts = (array) wp_count_attachments(); 
  2264. $matches = wp_match_mime_types(array_keys($post_mime_types), array_keys($_num_posts)); 
  2265. foreach ( $matches as $_type => $reals ) 
  2266. foreach ( $reals as $real ) 
  2267. if ( isset($num_posts[$_type]) ) 
  2268. $num_posts[$_type] += $_num_posts[$real]; 
  2269. else 
  2270. $num_posts[$_type] = $_num_posts[$real]; 
  2271. // If available type specified by media button clicked, filter by that type 
  2272. if ( empty($_GET['post_mime_type']) && !empty($num_posts[$type]) ) { 
  2273. $_GET['post_mime_type'] = $type; 
  2274. list($post_mime_types, $avail_post_mime_types) = wp_edit_attachments_query(); 
  2275. if ( empty($_GET['post_mime_type']) || $_GET['post_mime_type'] == 'all' ) 
  2276. $class = ' class="current"'; 
  2277. else 
  2278. $class = ''; 
  2279. $type_links[] = '<li><a href="' . esc_url(add_query_arg(array('post_mime_type'=>'all', 'paged'=>false, 'm'=>false))) . '"' . $class . '>' . __('All Types') . '</a>'; 
  2280. foreach ( $post_mime_types as $mime_type => $label ) { 
  2281. $class = ''; 
  2282.  
  2283. if ( !wp_match_mime_types($mime_type, $avail_post_mime_types) ) 
  2284. continue; 
  2285.  
  2286. if ( isset($_GET['post_mime_type']) && wp_match_mime_types($mime_type, $_GET['post_mime_type']) ) 
  2287. $class = ' class="current"'; 
  2288.  
  2289. $type_links[] = '<li><a href="' . esc_url(add_query_arg(array('post_mime_type'=>$mime_type, 'paged'=>false))) . '"' . $class . '>' . sprintf( translate_nooped_plural( $label[2], $num_posts[$mime_type] ), '<span id="' . $mime_type . '-counter">' . number_format_i18n( $num_posts[$mime_type] ) . '</span>') . '</a>'; 
  2290. /** 
  2291. * Filters the media upload mime type list items. 
  2292. * 
  2293. * Returned values should begin with an `<li>` tag. 
  2294. * 
  2295. * @since 3.1.0 
  2296. * 
  2297. * @param array $type_links An array of list items containing mime type link HTML. 
  2298. */ 
  2299. echo implode(' | </li>', apply_filters( 'media_upload_mime_type_links', $type_links ) ) . '</li>'; 
  2300. unset($type_links); 
  2301. ?> 
  2302. </ul> 
  2303.  
  2304. <div class="tablenav"> 
  2305.  
  2306. <?php 
  2307. $page_links = paginate_links( array( 
  2308. 'base' => add_query_arg( 'paged', '%#%' ),  
  2309. 'format' => '',  
  2310. 'prev_text' => __('«'),  
  2311. 'next_text' => __('»'),  
  2312. 'total' => ceil($wp_query->found_posts / 10),  
  2313. 'current' => $q['paged'],  
  2314. )); 
  2315.  
  2316. if ( $page_links ) 
  2317. echo "<div class='tablenav-pages'>$page_links</div>"; 
  2318. ?> 
  2319.  
  2320. <div class="alignleft actions"> 
  2321. <?php 
  2322.  
  2323. $arc_query = "SELECT DISTINCT YEAR(post_date) AS yyear, MONTH(post_date) AS mmonth FROM $wpdb->posts WHERE post_type = 'attachment' ORDER BY post_date DESC"; 
  2324.  
  2325. $arc_result = $wpdb->get_results( $arc_query ); 
  2326.  
  2327. $month_count = count($arc_result); 
  2328. $selected_month = isset( $_GET['m'] ) ? $_GET['m'] : 0; 
  2329.  
  2330. if ( $month_count && !( 1 == $month_count && 0 == $arc_result[0]->mmonth ) ) { ?> 
  2331. <select name='m'> 
  2332. <option<?php selected( $selected_month, 0 ); ?> value='0'><?php _e( 'All dates' ); ?></option> 
  2333. <?php 
  2334. foreach ($arc_result as $arc_row) { 
  2335. if ( $arc_row->yyear == 0 ) 
  2336. continue; 
  2337. $arc_row->mmonth = zeroise( $arc_row->mmonth, 2 ); 
  2338.  
  2339. if ( $arc_row->yyear . $arc_row->mmonth == $selected_month ) 
  2340. $default = ' selected="selected"'; 
  2341. else 
  2342. $default = ''; 
  2343.  
  2344. echo "<option$default value='" . esc_attr( $arc_row->yyear . $arc_row->mmonth ) . "'>"; 
  2345. echo esc_html( $wp_locale->get_month($arc_row->mmonth) . " $arc_row->yyear" ); 
  2346. echo "</option>\n"; 
  2347. ?> 
  2348. </select> 
  2349. <?php } ?> 
  2350.  
  2351. <?php submit_button( __( 'Filter »' ), '', 'post-query-submit', false ); ?> 
  2352.  
  2353. </div> 
  2354.  
  2355. <br class="clear" /> 
  2356. </div> 
  2357. </form> 
  2358.  
  2359. <form enctype="multipart/form-data" method="post" action="<?php echo esc_url( $form_action_url ); ?>" class="<?php echo $form_class; ?>" id="library-form"> 
  2360.  
  2361. <?php wp_nonce_field('media-form'); ?> 
  2362. <?php //media_upload_form( $errors ); ?> 
  2363.  
  2364. <script type="text/javascript"> 
  2365. <!-- 
  2366. jQuery(function($) { 
  2367. var preloaded = $(".media-item.preloaded"); 
  2368. if ( preloaded.length > 0 ) { 
  2369. preloaded.each(function() {prepareMediaItem({id:this.id.replace(/[^0-9]/g, '')}, '');}); 
  2370. updateMediaForm(); 
  2371. }); 
  2372. --> 
  2373. </script> 
  2374.  
  2375. <div id="media-items"> 
  2376. <?php add_filter('attachment_fields_to_edit', 'media_post_single_attachment_fields_to_edit', 10, 2); ?> 
  2377. <?php echo get_media_items(null, $errors); ?> 
  2378. </div> 
  2379. <p class="ml-submit"> 
  2380. <?php submit_button( __( 'Save all changes' ), 'savebutton', 'save', false ); ?> 
  2381. <input type="hidden" name="post_id" id="post_id" value="<?php echo (int) $post_id; ?>" /> 
  2382. </p> 
  2383. </form> 
  2384. <?php 
  2385.  
  2386. /** 
  2387. * Creates the form for external url 
  2388. * 
  2389. * @since 2.7.0 
  2390. * 
  2391. * @param string $default_view 
  2392. * @return string the form html 
  2393. */ 
  2394. function wp_media_insert_url_form( $default_view = 'image' ) { 
  2395. /** This filter is documented in wp-admin/includes/media.php */ 
  2396. if ( ! apply_filters( 'disable_captions', '' ) ) { 
  2397. $caption = ' 
  2398. <tr class="image-only"> 
  2399. <th scope="row" class="label"> 
  2400. <label for="caption"><span class="alignleft">' . __('Image Caption') . '</span></label> 
  2401. </th> 
  2402. <td class="field"><textarea id="caption" name="caption"></textarea></td> 
  2403. </tr> 
  2404. '; 
  2405. } else { 
  2406. $caption = ''; 
  2407.  
  2408. $default_align = get_option('image_default_align'); 
  2409. if ( empty($default_align) ) 
  2410. $default_align = 'none'; 
  2411.  
  2412. if ( 'image' == $default_view ) { 
  2413. $view = 'image-only'; 
  2414. $table_class = ''; 
  2415. } else { 
  2416. $view = $table_class = 'not-image'; 
  2417.  
  2418. return ' 
  2419. <p class="media-types"><label><input type="radio" name="media_type" value="image" id="image-only"' . checked( 'image-only', $view, false ) . ' /> ' . __( 'Image' ) . '</label>     <label><input type="radio" name="media_type" value="generic" id="not-image"' . checked( 'not-image', $view, false ) . ' /> ' . __( 'Audio, Video, or Other File' ) . '</label></p> 
  2420. <p class="media-types media-types-required-info">' . sprintf( __( 'Required fields are marked %s' ), '<span class="required">*</span>' ) . '</p> 
  2421. <table class="describe ' . $table_class . '"><tbody> 
  2422. <tr> 
  2423. <th scope="row" class="label" style="width:130px;"> 
  2424. <label for="src"><span class="alignleft">' . __( 'URL' ) . '</span> <span class="required">*</span></label> 
  2425. <span class="alignright" id="status_img"></span> 
  2426. </th> 
  2427. <td class="field"><input id="src" name="src" value="" type="text" required aria-required="true" onblur="addExtImage.getImageData()" /></td> 
  2428. </tr> 
  2429.  
  2430. <tr> 
  2431. <th scope="row" class="label"> 
  2432. <label for="title"><span class="alignleft">' . __( 'Title' ) . '</span> <span class="required">*</span></label> 
  2433. </th> 
  2434. <td class="field"><input id="title" name="title" value="" type="text" required aria-required="true" /></td> 
  2435. </tr> 
  2436.  
  2437. <tr class="not-image"><td></td><td><p class="help">' . __('Link text, e.g. “Ransom Demands (PDF)”') . '</p></td></tr> 
  2438.  
  2439. <tr class="image-only"> 
  2440. <th scope="row" class="label"> 
  2441. <label for="alt"><span class="alignleft">' . __('Alternative Text') . '</span></label> 
  2442. </th> 
  2443. <td class="field"><input id="alt" name="alt" value="" type="text" aria-required="true" /> 
  2444. <p class="help">' . __('Alt text for the image, e.g. “The Mona Lisa”') . '</p></td> 
  2445. </tr> 
  2446. ' . $caption . ' 
  2447. <tr class="align image-only"> 
  2448. <th scope="row" class="label"><p><label for="align">' . __('Alignment') . '</label></p></th> 
  2449. <td class="field"> 
  2450. <input name="align" id="align-none" value="none" onclick="addExtImage.align=\'align\'+this.value" type="radio"' . ($default_align == 'none' ? ' checked="checked"' : '').' /> 
  2451. <label for="align-none" class="align image-align-none-label">' . __('None') . '</label> 
  2452. <input name="align" id="align-left" value="left" onclick="addExtImage.align=\'align\'+this.value" type="radio"' . ($default_align == 'left' ? ' checked="checked"' : '').' /> 
  2453. <label for="align-left" class="align image-align-left-label">' . __('Left') . '</label> 
  2454. <input name="align" id="align-center" value="center" onclick="addExtImage.align=\'align\'+this.value" type="radio"' . ($default_align == 'center' ? ' checked="checked"' : '').' /> 
  2455. <label for="align-center" class="align image-align-center-label">' . __('Center') . '</label> 
  2456. <input name="align" id="align-right" value="right" onclick="addExtImage.align=\'align\'+this.value" type="radio"' . ($default_align == 'right' ? ' checked="checked"' : '').' /> 
  2457. <label for="align-right" class="align image-align-right-label">' . __('Right') . '</label> 
  2458. </td> 
  2459. </tr> 
  2460.  
  2461. <tr class="image-only"> 
  2462. <th scope="row" class="label"> 
  2463. <label for="url"><span class="alignleft">' . __('Link Image To:') . '</span></label> 
  2464. </th> 
  2465. <td class="field"><input id="url" name="url" value="" type="text" /><br /> 
  2466.  
  2467. <button type="button" class="button" value="" onclick="document.forms[0].url.value=null">' . __('None') . '</button> 
  2468. <button type="button" class="button" value="" onclick="document.forms[0].url.value=document.forms[0].src.value">' . __('Link to image') . '</button> 
  2469. <p class="help">' . __('Enter a link URL or click above for presets.') . '</p></td> 
  2470. </tr> 
  2471. <tr class="image-only"> 
  2472. <td></td> 
  2473. <td> 
  2474. <input type="button" class="button" id="go_button" style="color:#bbb;" onclick="addExtImage.insert()" value="' . esc_attr__('Insert into Post') . '" /> 
  2475. </td> 
  2476. </tr> 
  2477. <tr class="not-image"> 
  2478. <td></td> 
  2479. <td> 
  2480. ' . get_submit_button( __( 'Insert into Post' ), '', 'insertonlybutton', false ) . ' 
  2481. </td> 
  2482. </tr> 
  2483. </tbody></table> 
  2484. '; 
  2485.  
  2486.  
  2487. /** 
  2488. * Displays the multi-file uploader message. 
  2489. * 
  2490. * @since 2.6.0 
  2491. * 
  2492. * @global int $post_ID 
  2493. */ 
  2494. function media_upload_flash_bypass() { 
  2495. $browser_uploader = admin_url( 'media-new.php?browser-uploader' ); 
  2496.  
  2497. if ( $post = get_post() ) 
  2498. $browser_uploader .= '&post_id=' . intval( $post->ID ); 
  2499. elseif ( ! empty( $GLOBALS['post_ID'] ) ) 
  2500. $browser_uploader .= '&post_id=' . intval( $GLOBALS['post_ID'] ); 
  2501.  
  2502. ?> 
  2503. <p class="upload-flash-bypass"> 
  2504. <?php printf( __( 'You are using the multi-file uploader. Problems? Try the <a href="%1$s" target="%2$s">browser uploader</a> instead.' ), $browser_uploader, '_blank' ); ?> 
  2505. </p> 
  2506. <?php 
  2507.  
  2508. /** 
  2509. * Displays the browser's built-in uploader message. 
  2510. * 
  2511. * @since 2.6.0 
  2512. */ 
  2513. function media_upload_html_bypass() { 
  2514. ?> 
  2515. <p class="upload-html-bypass hide-if-no-js"> 
  2516. <?php _e('You are using the browser’s built-in file uploader. The WordPress uploader includes multiple file selection and drag and drop capability. <a href="#">Switch to the multi-file uploader</a>.'); ?> 
  2517. </p> 
  2518. <?php 
  2519.  
  2520. /** 
  2521. * Used to display a "After a file has been uploaded..." help message. 
  2522. * 
  2523. * @since 3.3.0 
  2524. */ 
  2525. function media_upload_text_after() {} 
  2526.  
  2527. /** 
  2528. * Displays the checkbox to scale images. 
  2529. * 
  2530. * @since 3.3.0 
  2531. */ 
  2532. function media_upload_max_image_resize() { 
  2533. $checked = get_user_setting('upload_resize') ? ' checked="true"' : ''; 
  2534. $a = $end = ''; 
  2535.  
  2536. if ( current_user_can( 'manage_options' ) ) { 
  2537. $a = '<a href="' . esc_url( admin_url( 'options-media.php' ) ) . '" target="_blank">'; 
  2538. $end = '</a>'; 
  2539. ?> 
  2540. <p class="hide-if-no-js"><label> 
  2541. <input name="image_resize" type="checkbox" id="image_resize" value="true"<?php echo $checked; ?> /> 
  2542. <?php 
  2543. /** translators: %1$s is link start tag, %2$s is link end tag, %3$d is width, %4$d is height*/ 
  2544. printf( __( 'Scale images to match the large size selected in %1$simage options%2$s (%3$d × %4$d).' ), $a, $end, (int) get_option( 'large_size_w', '1024' ), (int) get_option( 'large_size_h', '1024' ) ); 
  2545. ?> 
  2546. </label></p> 
  2547. <?php 
  2548.  
  2549. /** 
  2550. * Displays the out of storage quota message in Multisite. 
  2551. * 
  2552. * @since 3.5.0 
  2553. */ 
  2554. function multisite_over_quota_message() { 
  2555. echo '<p>' . sprintf( __( 'Sorry, you have used all of your storage quota of %s MB.' ), get_space_allowed() ) . '</p>'; 
  2556.  
  2557. /** 
  2558. * Displays the image and editor in the post editor 
  2559. * 
  2560. * @since 3.5.0 
  2561. * 
  2562. * @param WP_Post $post A post object. 
  2563. */ 
  2564. function edit_form_image_editor( $post ) { 
  2565. $open = isset( $_GET['image-editor'] ); 
  2566. if ( $open ) 
  2567. require_once ABSPATH . 'wp-admin/includes/image-edit.php'; 
  2568.  
  2569. $thumb_url = false; 
  2570. if ( $attachment_id = intval( $post->ID ) ) 
  2571. $thumb_url = wp_get_attachment_image_src( $attachment_id, array( 900, 450 ), true ); 
  2572.  
  2573. $alt_text = get_post_meta( $post->ID, '_wp_attachment_image_alt', true ); 
  2574.  
  2575. $att_url = wp_get_attachment_url( $post->ID ); ?> 
  2576. <div class="wp_attachment_holder wp-clearfix"> 
  2577. <?php 
  2578. if ( wp_attachment_is_image( $post->ID ) ) : 
  2579. $image_edit_button = ''; 
  2580. if ( wp_image_editor_supports( array( 'mime_type' => $post->post_mime_type ) ) ) { 
  2581. $nonce = wp_create_nonce( "image_editor-$post->ID" ); 
  2582. $image_edit_button = "<input type='button' id='imgedit-open-btn-$post->ID' onclick='imageEdit.open( $post->ID, \"$nonce\" )' class='button' value='" . esc_attr__( 'Edit Image' ) . "' /> <span class='spinner'></span>"; 
  2583. ?> 
  2584.  
  2585. <div class="imgedit-response" id="imgedit-response-<?php echo $attachment_id; ?>"></div> 
  2586.  
  2587. <div<?php if ( $open ) echo ' style="display:none"'; ?> class="wp_attachment_image wp-clearfix" id="media-head-<?php echo $attachment_id; ?>"> 
  2588. <p id="thumbnail-head-<?php echo $attachment_id; ?>"><img class="thumbnail" src="<?php echo set_url_scheme( $thumb_url[0] ); ?>" style="max-width:100%" alt="" /></p> 
  2589. <p><?php echo $image_edit_button; ?></p> 
  2590. </div> 
  2591. <div<?php if ( ! $open ) echo ' style="display:none"'; ?> class="image-editor" id="image-editor-<?php echo $attachment_id; ?>"> 
  2592. <?php if ( $open ) wp_image_editor( $attachment_id ); ?> 
  2593. </div> 
  2594. <?php 
  2595. elseif ( $attachment_id && wp_attachment_is( 'audio', $post ) ): 
  2596.  
  2597. wp_maybe_generate_attachment_metadata( $post ); 
  2598.  
  2599. echo wp_audio_shortcode( array( 'src' => $att_url ) ); 
  2600.  
  2601. elseif ( $attachment_id && wp_attachment_is( 'video', $post ) ): 
  2602.  
  2603. wp_maybe_generate_attachment_metadata( $post ); 
  2604.  
  2605. $meta = wp_get_attachment_metadata( $attachment_id ); 
  2606. $w = ! empty( $meta['width'] ) ? min( $meta['width'], 640 ) : 0; 
  2607. $h = ! empty( $meta['height'] ) ? $meta['height'] : 0; 
  2608. if ( $h && $w < $meta['width'] ) { 
  2609. $h = round( ( $meta['height'] * $w ) / $meta['width'] ); 
  2610.  
  2611. $attr = array( 'src' => $att_url ); 
  2612. if ( ! empty( $w ) && ! empty( $h ) ) { 
  2613. $attr['width'] = $w; 
  2614. $attr['height'] = $h; 
  2615.  
  2616. $thumb_id = get_post_thumbnail_id( $attachment_id ); 
  2617. if ( ! empty( $thumb_id ) ) { 
  2618. $attr['poster'] = wp_get_attachment_url( $thumb_id ); 
  2619.  
  2620. echo wp_video_shortcode( $attr ); 
  2621.  
  2622. elseif ( isset( $thumb_url[0] ) ): 
  2623.  
  2624. ?> 
  2625. <div class="wp_attachment_image wp-clearfix" id="media-head-<?php echo $attachment_id; ?>"> 
  2626. <p id="thumbnail-head-<?php echo $attachment_id; ?>"> 
  2627. <img class="thumbnail" src="<?php echo set_url_scheme( $thumb_url[0] ); ?>" style="max-width:100%" alt="" /> 
  2628. </p> 
  2629. </div> 
  2630. <?php 
  2631.  
  2632. else: 
  2633.  
  2634. /** 
  2635. * Fires when an attachment type can't be rendered in the edit form. 
  2636. * 
  2637. * @since 4.6.0 
  2638. * 
  2639. * @param WP_Post $post A post object. 
  2640. */ 
  2641. do_action( 'wp_edit_form_attachment_display', $post ); 
  2642.  
  2643. endif; ?> 
  2644. </div> 
  2645. <div class="wp_attachment_details edit-form-section"> 
  2646. <p> 
  2647. <label for="attachment_caption"><strong><?php _e( 'Caption' ); ?></strong></label><br /> 
  2648. <textarea class="widefat" name="excerpt" id="attachment_caption"><?php echo $post->post_excerpt; ?></textarea> 
  2649. </p> 
  2650.  
  2651.  
  2652. <?php if ( 'image' === substr( $post->post_mime_type, 0, 5 ) ) : ?> 
  2653. <p> 
  2654. <label for="attachment_alt"><strong><?php _e( 'Alternative Text' ); ?></strong></label><br /> 
  2655. <input type="text" class="widefat" name="_wp_attachment_image_alt" id="attachment_alt" value="<?php echo esc_attr( $alt_text ); ?>" /> 
  2656. </p> 
  2657. <?php endif; ?> 
  2658.  
  2659. <?php 
  2660. $quicktags_settings = array( 'buttons' => 'strong, em, link, block, del, ins, img, ul, ol, li, code, close' ); 
  2661. $editor_args = array( 
  2662. 'textarea_name' => 'content',  
  2663. 'textarea_rows' => 5,  
  2664. 'media_buttons' => false,  
  2665. 'tinymce' => false,  
  2666. 'quicktags' => $quicktags_settings,  
  2667. ); 
  2668. ?> 
  2669.  
  2670. <label for="attachment_content"><strong><?php _e( 'Description' ); ?></strong><?php 
  2671. if ( preg_match( '#^(audio|video)/#', $post->post_mime_type ) ) { 
  2672. echo ': ' . __( 'Displayed on attachment pages.' ); 
  2673. } ?></label> 
  2674. <?php wp_editor( $post->post_content, 'attachment_content', $editor_args ); ?> 
  2675.  
  2676. </div> 
  2677. <?php 
  2678. $extras = get_compat_media_markup( $post->ID ); 
  2679. echo $extras['item']; 
  2680. echo '<input type="hidden" id="image-edit-context" value="edit-attachment" />' . "\n"; 
  2681.  
  2682. /** 
  2683. * Displays non-editable attachment metadata in the publish meta box. 
  2684. * 
  2685. * @since 3.5.0 
  2686. */ 
  2687. function attachment_submitbox_metadata() { 
  2688. $post = get_post(); 
  2689.  
  2690. $file = get_attached_file( $post->ID ); 
  2691. $filename = esc_html( wp_basename( $file ) ); 
  2692.  
  2693. $media_dims = ''; 
  2694. $meta = wp_get_attachment_metadata( $post->ID ); 
  2695. if ( isset( $meta['width'], $meta['height'] ) ) 
  2696. $media_dims .= "<span id='media-dims-$post->ID'>{$meta['width']} × {$meta['height']}</span> "; 
  2697. /** This filter is documented in wp-admin/includes/media.php */ 
  2698. $media_dims = apply_filters( 'media_meta', $media_dims, $post ); 
  2699.  
  2700. $att_url = wp_get_attachment_url( $post->ID ); 
  2701. ?> 
  2702. <div class="misc-pub-section misc-pub-attachment"> 
  2703. <label for="attachment_url"><?php _e( 'File URL:' ); ?></label> 
  2704. <input type="text" class="widefat urlfield" readonly="readonly" name="attachment_url" id="attachment_url" value="<?php echo esc_attr( $att_url ); ?>" /> 
  2705. </div> 
  2706. <div class="misc-pub-section misc-pub-filename"> 
  2707. <?php _e( 'File name:' ); ?> <strong><?php echo $filename; ?></strong> 
  2708. </div> 
  2709. <div class="misc-pub-section misc-pub-filetype"> 
  2710. <?php _e( 'File type:' ); ?> <strong><?php 
  2711. if ( preg_match( '/^.*?\.(\w+)$/', get_attached_file( $post->ID ), $matches ) ) { 
  2712. echo esc_html( strtoupper( $matches[1] ) ); 
  2713. list( $mime_type ) = explode( '/', $post->post_mime_type ); 
  2714. if ( $mime_type !== 'image' && ! empty( $meta['mime_type'] ) ) { 
  2715. if ( $meta['mime_type'] !== "$mime_type/" . strtolower( $matches[1] ) ) { 
  2716. echo ' (' . $meta['mime_type'] . ')'; 
  2717. } else { 
  2718. echo strtoupper( str_replace( 'image/', '', $post->post_mime_type ) ); 
  2719. ?></strong> 
  2720. </div> 
  2721.  
  2722. <?php 
  2723. $file_size = false; 
  2724.  
  2725. if ( isset( $meta['filesize'] ) ) 
  2726. $file_size = $meta['filesize']; 
  2727. elseif ( file_exists( $file ) ) 
  2728. $file_size = filesize( $file ); 
  2729.  
  2730. if ( ! empty( $file_size ) ) : ?> 
  2731. <div class="misc-pub-section misc-pub-filesize"> 
  2732. <?php _e( 'File size:' ); ?> <strong><?php echo size_format( $file_size ); ?></strong> 
  2733. </div> 
  2734. <?php 
  2735. endif; 
  2736.  
  2737. if ( preg_match( '#^(audio|video)/#', $post->post_mime_type ) ) { 
  2738.  
  2739. /** 
  2740. * Filters the audio and video metadata fields to be shown in the publish meta box. 
  2741. * 
  2742. * The key for each item in the array should correspond to an attachment 
  2743. * metadata key, and the value should be the desired label. 
  2744. * 
  2745. * @since 3.7.0 
  2746. * 
  2747. * @param array $fields An array of the attachment metadata keys and labels. 
  2748. */ 
  2749. $fields = apply_filters( 'media_submitbox_misc_sections', array( 
  2750. 'length_formatted' => __( 'Length:' ),  
  2751. 'bitrate' => __( 'Bitrate:' ),  
  2752. ) ); 
  2753.  
  2754. foreach ( $fields as $key => $label ) { 
  2755. if ( empty( $meta[ $key ] ) ) { 
  2756. continue; 
  2757. ?> 
  2758. <div class="misc-pub-section misc-pub-mime-meta misc-pub-<?php echo sanitize_html_class( $key ); ?>"> 
  2759. <?php echo $label ?> <strong><?php 
  2760. switch ( $key ) { 
  2761. case 'bitrate' : 
  2762. echo round( $meta['bitrate'] / 1000 ) . 'kb/s'; 
  2763. if ( ! empty( $meta['bitrate_mode'] ) ) { 
  2764. echo ' ' . strtoupper( esc_html( $meta['bitrate_mode'] ) ); 
  2765. break; 
  2766. default: 
  2767. echo esc_html( $meta[ $key ] ); 
  2768. break; 
  2769. ?></strong> 
  2770. </div> 
  2771. <?php 
  2772.  
  2773. /** 
  2774. * Filters the audio attachment metadata fields to be shown in the publish meta box. 
  2775. * 
  2776. * The key for each item in the array should correspond to an attachment 
  2777. * metadata key, and the value should be the desired label. 
  2778. * 
  2779. * @since 3.7.0 
  2780. * 
  2781. * @param array $fields An array of the attachment metadata keys and labels. 
  2782. */ 
  2783. $audio_fields = apply_filters( 'audio_submitbox_misc_sections', array( 
  2784. 'dataformat' => __( 'Audio Format:' ),  
  2785. 'codec' => __( 'Audio Codec:' ) 
  2786. ) ); 
  2787.  
  2788. foreach ( $audio_fields as $key => $label ) { 
  2789. if ( empty( $meta['audio'][ $key ] ) ) { 
  2790. continue; 
  2791. ?> 
  2792. <div class="misc-pub-section misc-pub-audio misc-pub-<?php echo sanitize_html_class( $key ); ?>"> 
  2793. <?php echo $label; ?> <strong><?php echo esc_html( $meta['audio'][$key] ); ?></strong> 
  2794. </div> 
  2795. <?php 
  2796.  
  2797.  
  2798. if ( $media_dims ) : ?> 
  2799. <div class="misc-pub-section misc-pub-dimensions"> 
  2800. <?php _e( 'Dimensions:' ); ?> <strong><?php echo $media_dims; ?></strong> 
  2801. </div> 
  2802. <?php 
  2803. endif; 
  2804.  
  2805. /** 
  2806. * Parse ID3v2, ID3v1, and getID3 comments to extract usable data 
  2807. * 
  2808. * @since 3.6.0 
  2809. * 
  2810. * @param array $metadata An existing array with data 
  2811. * @param array $data Data supplied by ID3 tags 
  2812. */ 
  2813. function wp_add_id3_tag_data( &$metadata, $data ) { 
  2814. foreach ( array( 'id3v2', 'id3v1' ) as $version ) { 
  2815. if ( ! empty( $data[$version]['comments'] ) ) { 
  2816. foreach ( $data[$version]['comments'] as $key => $list ) { 
  2817. if ( 'length' !== $key && ! empty( $list ) ) { 
  2818. $metadata[$key] = wp_kses_post( reset( $list ) ); 
  2819. // Fix bug in byte stream analysis. 
  2820. if ( 'terms_of_use' === $key && 0 === strpos( $metadata[$key], 'yright notice.' ) ) 
  2821. $metadata[$key] = 'Cop' . $metadata[$key]; 
  2822. break; 
  2823.  
  2824. if ( ! empty( $data['id3v2']['APIC'] ) ) { 
  2825. $image = reset( $data['id3v2']['APIC']); 
  2826. if ( ! empty( $image['data'] ) ) { 
  2827. $metadata['image'] = array( 
  2828. 'data' => $image['data'],  
  2829. 'mime' => $image['image_mime'],  
  2830. 'width' => $image['image_width'],  
  2831. 'height' => $image['image_height'] 
  2832. ); 
  2833. } elseif ( ! empty( $data['comments']['picture'] ) ) { 
  2834. $image = reset( $data['comments']['picture'] ); 
  2835. if ( ! empty( $image['data'] ) ) { 
  2836. $metadata['image'] = array( 
  2837. 'data' => $image['data'],  
  2838. 'mime' => $image['image_mime'] 
  2839. ); 
  2840.  
  2841. /** 
  2842. * Retrieve metadata from a video file's ID3 tags 
  2843. * 
  2844. * @since 3.6.0 
  2845. * 
  2846. * @param string $file Path to file. 
  2847. * @return array|bool Returns array of metadata, if found. 
  2848. */ 
  2849. function wp_read_video_metadata( $file ) { 
  2850. if ( ! file_exists( $file ) ) { 
  2851. return false; 
  2852.  
  2853. $metadata = array(); 
  2854.  
  2855. if ( ! defined( 'GETID3_TEMP_DIR' ) ) { 
  2856. define( 'GETID3_TEMP_DIR', get_temp_dir() ); 
  2857.  
  2858. if ( ! class_exists( 'getID3', false ) ) { 
  2859. require( ABSPATH . WPINC . '/ID3/getid3.php' ); 
  2860. $id3 = new getID3(); 
  2861. $data = $id3->analyze( $file ); 
  2862.  
  2863. if ( isset( $data['video']['lossless'] ) ) 
  2864. $metadata['lossless'] = $data['video']['lossless']; 
  2865. if ( ! empty( $data['video']['bitrate'] ) ) 
  2866. $metadata['bitrate'] = (int) $data['video']['bitrate']; 
  2867. if ( ! empty( $data['video']['bitrate_mode'] ) ) 
  2868. $metadata['bitrate_mode'] = $data['video']['bitrate_mode']; 
  2869. if ( ! empty( $data['filesize'] ) ) 
  2870. $metadata['filesize'] = (int) $data['filesize']; 
  2871. if ( ! empty( $data['mime_type'] ) ) 
  2872. $metadata['mime_type'] = $data['mime_type']; 
  2873. if ( ! empty( $data['playtime_seconds'] ) ) 
  2874. $metadata['length'] = (int) round( $data['playtime_seconds'] ); 
  2875. if ( ! empty( $data['playtime_string'] ) ) 
  2876. $metadata['length_formatted'] = $data['playtime_string']; 
  2877. if ( ! empty( $data['video']['resolution_x'] ) ) 
  2878. $metadata['width'] = (int) $data['video']['resolution_x']; 
  2879. if ( ! empty( $data['video']['resolution_y'] ) ) 
  2880. $metadata['height'] = (int) $data['video']['resolution_y']; 
  2881. if ( ! empty( $data['fileformat'] ) ) 
  2882. $metadata['fileformat'] = $data['fileformat']; 
  2883. if ( ! empty( $data['video']['dataformat'] ) ) 
  2884. $metadata['dataformat'] = $data['video']['dataformat']; 
  2885. if ( ! empty( $data['video']['encoder'] ) ) 
  2886. $metadata['encoder'] = $data['video']['encoder']; 
  2887. if ( ! empty( $data['video']['codec'] ) ) 
  2888. $metadata['codec'] = $data['video']['codec']; 
  2889.  
  2890. if ( ! empty( $data['audio'] ) ) { 
  2891. unset( $data['audio']['streams'] ); 
  2892. $metadata['audio'] = $data['audio']; 
  2893.  
  2894. wp_add_id3_tag_data( $metadata, $data ); 
  2895.  
  2896. return $metadata; 
  2897.  
  2898. /** 
  2899. * Retrieve metadata from a audio file's ID3 tags 
  2900. * 
  2901. * @since 3.6.0 
  2902. * 
  2903. * @param string $file Path to file. 
  2904. * @return array|bool Returns array of metadata, if found. 
  2905. */ 
  2906. function wp_read_audio_metadata( $file ) { 
  2907. if ( ! file_exists( $file ) ) { 
  2908. return false; 
  2909. $metadata = array(); 
  2910.  
  2911. if ( ! defined( 'GETID3_TEMP_DIR' ) ) { 
  2912. define( 'GETID3_TEMP_DIR', get_temp_dir() ); 
  2913.  
  2914. if ( ! class_exists( 'getID3', false ) ) { 
  2915. require( ABSPATH . WPINC . '/ID3/getid3.php' ); 
  2916. $id3 = new getID3(); 
  2917. $data = $id3->analyze( $file ); 
  2918.  
  2919. if ( ! empty( $data['audio'] ) ) { 
  2920. unset( $data['audio']['streams'] ); 
  2921. $metadata = $data['audio']; 
  2922.  
  2923. if ( ! empty( $data['fileformat'] ) ) 
  2924. $metadata['fileformat'] = $data['fileformat']; 
  2925. if ( ! empty( $data['filesize'] ) ) 
  2926. $metadata['filesize'] = (int) $data['filesize']; 
  2927. if ( ! empty( $data['mime_type'] ) ) 
  2928. $metadata['mime_type'] = $data['mime_type']; 
  2929. if ( ! empty( $data['playtime_seconds'] ) ) 
  2930. $metadata['length'] = (int) round( $data['playtime_seconds'] ); 
  2931. if ( ! empty( $data['playtime_string'] ) ) 
  2932. $metadata['length_formatted'] = $data['playtime_string']; 
  2933.  
  2934. wp_add_id3_tag_data( $metadata, $data ); 
  2935.  
  2936. return $metadata; 
  2937.  
  2938. /** 
  2939. * Encapsulate logic for Attach/Detach actions 
  2940. * 
  2941. * @since 4.2.0 
  2942. * 
  2943. * @global wpdb $wpdb WordPress database abstraction object. 
  2944. * 
  2945. * @param int $parent_id Attachment parent ID. 
  2946. * @param string $action Optional. Attach/detach action. Accepts 'attach' or 'detach'. 
  2947. * Default 'attach'. 
  2948. */ 
  2949. function wp_media_attach_action( $parent_id, $action = 'attach' ) { 
  2950. global $wpdb; 
  2951.  
  2952. if ( ! $parent_id ) { 
  2953. return; 
  2954.  
  2955. if ( ! current_user_can( 'edit_post', $parent_id ) ) { 
  2956. wp_die( __( 'Sorry, you are not allowed to edit this post.' ) ); 
  2957. $ids = array(); 
  2958. foreach ( (array) $_REQUEST['media'] as $att_id ) { 
  2959. $att_id = (int) $att_id; 
  2960.  
  2961. if ( ! current_user_can( 'edit_post', $att_id ) ) { 
  2962. continue; 
  2963.  
  2964. $ids[] = $att_id; 
  2965.  
  2966. if ( ! empty( $ids ) ) { 
  2967. $ids_string = implode( ', ', $ids ); 
  2968. if ( 'attach' === $action ) { 
  2969. $result = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_parent = %d WHERE post_type = 'attachment' AND ID IN ( $ids_string )", $parent_id ) ); 
  2970. } else { 
  2971. $result = $wpdb->query( "UPDATE $wpdb->posts SET post_parent = 0 WHERE post_type = 'attachment' AND ID IN ( $ids_string )" ); 
  2972.  
  2973. foreach ( $ids as $att_id ) { 
  2974. clean_attachment_cache( $att_id ); 
  2975.  
  2976. if ( isset( $result ) ) { 
  2977. $location = 'upload.php'; 
  2978. if ( $referer = wp_get_referer() ) { 
  2979. if ( false !== strpos( $referer, 'upload.php' ) ) { 
  2980. $location = remove_query_arg( array( 'attached', 'detach' ), $referer ); 
  2981.  
  2982. $key = 'attach' === $action ? 'attached' : 'detach'; 
  2983. $location = add_query_arg( array( $key => $result ), $location ); 
  2984. wp_redirect( $location ); 
  2985. exit; 
.