3 * WordPress Post Administration API.
6 * @subpackage Administration
10 * Rename $_POST data from form names to DB post columns.
12 * Manipulates $_POST directly.
17 * @param bool $update Are we updating a pre-existing post?
18 * @param post_data array Array of post data. Defaults to the contents of $_POST.
19 * @return object|bool WP_Error on failure, true on success.
21 function _wp_translate_postdata( $update = false, $post_data = null ) {
23 if ( empty($post_data) )
27 $post_data['ID'] = (int) $post_data['post_ID'];
28 $post_data['post_content'] = isset($post_data['content']) ? $post_data['content'] : '';
29 $post_data['post_excerpt'] = isset($post_data['excerpt']) ? $post_data['excerpt'] : '';
30 $post_data['post_parent'] = isset($post_data['parent_id'])? $post_data['parent_id'] : '';
31 if ( isset($post_data['trackback_url']) )
32 $post_data['to_ping'] = $post_data['trackback_url'];
34 if (!empty ( $post_data['post_author_override'] ) ) {
35 $post_data['post_author'] = (int) $post_data['post_author_override'];
37 if (!empty ( $post_data['post_author'] ) ) {
38 $post_data['post_author'] = (int) $post_data['post_author'];
40 $post_data['post_author'] = (int) $post_data['user_ID'];
44 if ( isset($post_data['user_ID']) && ($post_data['post_author'] != $post_data['user_ID']) ) {
45 if ( 'page' == $post_data['post_type'] ) {
46 if ( !current_user_can( 'edit_others_pages' ) ) {
47 return new WP_Error( 'edit_others_pages', $update ?
48 __( 'You are not allowed to edit pages as this user.' ) :
49 __( 'You are not allowed to create pages as this user.' )
53 if ( !current_user_can( 'edit_others_posts' ) ) {
54 return new WP_Error( 'edit_others_posts', $update ?
55 __( 'You are not allowed to edit posts as this user.' ) :
56 __( 'You are not allowed to post as this user.' )
62 // What to do based on which button they pressed
63 if ( isset($post_data['saveasdraft']) && '' != $post_data['saveasdraft'] )
64 $post_data['post_status'] = 'draft';
65 if ( isset($post_data['saveasprivate']) && '' != $post_data['saveasprivate'] )
66 $post_data['post_status'] = 'private';
67 if ( isset($post_data['publish']) && ( '' != $post_data['publish'] ) && ( $post_data['post_status'] != 'private' ) )
68 $post_data['post_status'] = 'publish';
69 if ( isset($post_data['advanced']) && '' != $post_data['advanced'] )
70 $post_data['post_status'] = 'draft';
71 if ( isset($post_data['pending']) && '' != $post_data['pending'] )
72 $post_data['post_status'] = 'pending';
74 $previous_status = get_post_field('post_status', isset($post_data['ID']) ? $post_data['ID'] : $post_data['temp_ID']);
76 // Posts 'submitted for approval' present are submitted to $_POST the same as if they were being published.
77 // Change status from 'publish' to 'pending' if user lacks permissions to publish or to resave published posts.
78 if ( 'page' == $post_data['post_type'] ) {
79 $publish_cap = 'publish_pages';
80 $edit_cap = 'edit_published_pages';
82 $publish_cap = 'publish_posts';
83 $edit_cap = 'edit_published_posts';
85 if ( isset($post_data['post_status']) && ('publish' == $post_data['post_status'] && !current_user_can( $publish_cap )) )
86 if ( $previous_status != 'publish' || !current_user_can( $edit_cap ) )
87 $post_data['post_status'] = 'pending';
89 if ( ! isset($post_data['post_status']) )
90 $post_data['post_status'] = $previous_status;
92 if (!isset( $post_data['comment_status'] ))
93 $post_data['comment_status'] = 'closed';
95 if (!isset( $post_data['ping_status'] ))
96 $post_data['ping_status'] = 'closed';
98 foreach ( array('aa', 'mm', 'jj', 'hh', 'mn') as $timeunit ) {
99 if ( !empty( $post_data['hidden_' . $timeunit] ) && $post_data['hidden_' . $timeunit] != $post_data[$timeunit] ) {
100 $post_data['edit_date'] = '1';
105 if ( !empty( $post_data['edit_date'] ) ) {
106 $aa = $post_data['aa'];
107 $mm = $post_data['mm'];
108 $jj = $post_data['jj'];
109 $hh = $post_data['hh'];
110 $mn = $post_data['mn'];
111 $ss = $post_data['ss'];
112 $aa = ($aa <= 0 ) ? date('Y') : $aa;
113 $mm = ($mm <= 0 ) ? date('n') : $mm;
114 $jj = ($jj > 31 ) ? 31 : $jj;
115 $jj = ($jj <= 0 ) ? date('j') : $jj;
116 $hh = ($hh > 23 ) ? $hh -24 : $hh;
117 $mn = ($mn > 59 ) ? $mn -60 : $mn;
118 $ss = ($ss > 59 ) ? $ss -60 : $ss;
119 $post_data['post_date'] = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss );
120 $post_data['post_date_gmt'] = get_gmt_from_date( $post_data['post_date'] );
127 * Update an existing post with values provided in $_POST.
131 * @param array $post_data Optional.
132 * @return int Post ID.
134 function edit_post( $post_data = null ) {
136 if ( empty($post_data) )
137 $post_data = &$_POST;
139 $post_ID = (int) $post_data['post_ID'];
141 if ( 'page' == $post_data['post_type'] ) {
142 if ( !current_user_can( 'edit_page', $post_ID ) )
143 wp_die( __('You are not allowed to edit this page.' ));
145 if ( !current_user_can( 'edit_post', $post_ID ) )
146 wp_die( __('You are not allowed to edit this post.' ));
149 // Autosave shouldn't save too soon after a real save
150 if ( 'autosave' == $post_data['action'] ) {
151 $post =& get_post( $post_ID );
153 $then = strtotime($post->post_date_gmt . ' +0000');
154 $delta = AUTOSAVE_INTERVAL / 2;
155 if ( ($now - $then) < $delta )
159 $post_data = _wp_translate_postdata( true, $post_data );
160 if ( is_wp_error($post_data) )
161 wp_die( $post_data->get_error_message() );
163 if ( isset($post_data['visibility']) ) {
164 switch ( $post_data['visibility'] ) {
166 $post_data['post_password'] = '';
169 unset( $post_data['sticky'] );
172 $post_data['post_status'] = 'private';
173 $post_data['post_password'] = '';
174 unset( $post_data['sticky'] );
180 if ( isset($post_data['meta']) && $post_data['meta'] ) {
181 foreach ( $post_data['meta'] as $key => $value )
182 update_meta( $key, $value['key'], $value['value'] );
185 if ( isset($post_data['deletemeta']) && $post_data['deletemeta'] ) {
186 foreach ( $post_data['deletemeta'] as $key => $value )
190 add_meta( $post_ID );
192 wp_update_post( $post_data );
194 // Reunite any orphaned attachments with their parent
195 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
196 $draft_ids = array();
197 if ( $draft_temp_id = (int) array_search( $post_ID, $draft_ids ) )
198 _relocate_children( $draft_temp_id, $post_ID );
200 // Now that we have an ID we can fix any attachment anchor hrefs
201 _fix_attachment_links( $post_ID );
203 wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
205 if ( current_user_can( 'edit_others_posts' ) ) {
206 if ( !empty($post_data['sticky']) )
207 stick_post($post_ID);
209 unstick_post($post_ID);
216 * {@internal Missing Short Description}}
218 * Updates all bulk edited posts/pages, adding (but not removing) tags and
219 * categories. Skips pages when they would be their own parent or child.
225 function bulk_edit_posts( $post_data = null ) {
228 if ( empty($post_data) )
229 $post_data = &$_POST;
231 if ( isset($post_data['post_type']) && 'page' == $post_data['post_type'] ) {
232 if ( ! current_user_can( 'edit_pages' ) )
233 wp_die( __('You are not allowed to edit pages.') );
235 if ( ! current_user_can( 'edit_posts' ) )
236 wp_die( __('You are not allowed to edit posts.') );
239 if ( -1 == $post_data['_status'] ) {
240 $post_data['post_status'] = null;
241 unset($post_data['post_status']);
243 $post_data['post_status'] = $post_data['_status'];
245 unset($post_data['_status']);
247 $post_IDs = array_map( 'intval', (array) $post_data['post'] );
249 $reset = array( 'post_author', 'post_status', 'post_password', 'post_parent', 'page_template', 'comment_status', 'ping_status', 'keep_private', 'tags_input', 'post_category', 'sticky' );
250 foreach ( $reset as $field ) {
251 if ( isset($post_data[$field]) && ( '' == $post_data[$field] || -1 == $post_data[$field] ) )
252 unset($post_data[$field]);
255 if ( isset($post_data['post_category']) ) {
256 if ( is_array($post_data['post_category']) && ! empty($post_data['post_category']) )
257 $new_cats = array_map( 'absint', $post_data['post_category'] );
259 unset($post_data['post_category']);
262 if ( isset($post_data['tags_input']) ) {
263 $new_tags = preg_replace( '/\s*,\s*/', ',', rtrim( trim($post_data['tags_input']), ' ,' ) );
264 $new_tags = explode(',', $new_tags);
267 if ( isset($post_data['post_parent']) && ($parent = (int) $post_data['post_parent']) ) {
268 $pages = $wpdb->get_results("SELECT ID, post_parent FROM $wpdb->posts WHERE post_type = 'page'");
271 for ( $i = 0; $i < 50 && $parent > 0; $i++ ) {
272 $children[] = $parent;
274 foreach ( $pages as $page ) {
275 if ( $page->ID == $parent ) {
276 $parent = $page->post_parent;
283 $updated = $skipped = $locked = array();
284 foreach ( $post_IDs as $post_ID ) {
286 if ( isset($children) && in_array($post_ID, $children) ) {
287 $skipped[] = $post_ID;
291 if ( wp_check_post_lock( $post_ID ) ) {
292 $locked[] = $post_ID;
296 if ( isset($new_cats) ) {
297 $cats = (array) wp_get_post_categories($post_ID);
298 $post_data['post_category'] = array_unique( array_merge($cats, $new_cats) );
301 if ( isset($new_tags) ) {
302 $tags = wp_get_post_tags($post_ID, array('fields' => 'names'));
303 $post_data['tags_input'] = array_unique( array_merge($tags, $new_tags) );
306 $post_data['ID'] = $post_ID;
307 $updated[] = wp_update_post( $post_data );
309 if ( isset( $post_data['sticky'] ) && current_user_can( 'edit_others_posts' ) ) {
310 if ( 'sticky' == $post_data['sticky'] )
311 stick_post( $post_ID );
313 unstick_post( $post_ID );
318 return array( 'updated' => $updated, 'skipped' => $skipped, 'locked' => $locked );
322 * Default post information to use when populating the "Write Post" form.
328 function get_default_post_to_edit() {
331 if ( !empty( $_REQUEST['post_title'] ) )
332 $post_title = esc_html( stripslashes( $_REQUEST['post_title'] ));
335 if ( !empty( $_REQUEST['content'] ) )
336 $post_content = esc_html( stripslashes( $_REQUEST['content'] ));
339 if ( !empty( $_REQUEST['excerpt'] ) )
340 $post_excerpt = esc_html( stripslashes( $_REQUEST['excerpt'] ));
343 $post->post_name = '';
344 $post->post_author = '';
345 $post->post_date = '';
346 $post->post_date_gmt = '';
347 $post->post_password = '';
348 $post->post_status = 'draft';
349 $post->post_type = 'post';
352 $post->comment_status = get_option( 'default_comment_status' );
353 $post->ping_status = get_option( 'default_ping_status' );
354 $post->post_pingback = get_option( 'default_pingback_flag' );
355 $post->post_category = get_option( 'default_category' );
356 $post->post_content = apply_filters( 'default_content', $post_content);
357 $post->post_title = apply_filters( 'default_title', $post_title );
358 $post->post_excerpt = apply_filters( 'default_excerpt', $post_excerpt);
359 $post->page_template = 'default';
360 $post->post_parent = 0;
361 $post->menu_order = 0;
367 * {@internal Missing Short Description}}
373 function get_default_page_to_edit() {
374 $page = get_default_post_to_edit();
375 $page->post_type = 'page';
380 * Get an existing post and format it for editing.
384 * @param unknown_type $id
387 function get_post_to_edit( $id ) {
389 $post = get_post( $id, OBJECT, 'edit' );
391 if ( $post->post_type == 'page' )
392 $post->page_template = get_post_meta( $id, '_wp_page_template', true );
398 * Determine if a post exists based on title, content, and date
402 * @param string $title Post title
403 * @param string $content Optional post content
404 * @param string $date Optional post date
405 * @return int Post ID if post exists, 0 otherwise.
407 function post_exists($title, $content = '', $date = '') {
410 $post_title = stripslashes( sanitize_post_field( 'post_title', $title, 0, 'db' ) );
411 $post_content = stripslashes( sanitize_post_field( 'post_content', $content, 0, 'db' ) );
412 $post_date = stripslashes( sanitize_post_field( 'post_date', $date, 0, 'db' ) );
414 $query = "SELECT ID FROM $wpdb->posts WHERE 1=1";
417 if ( !empty ( $date ) ) {
418 $query .= ' AND post_date = %s';
419 $args[] = $post_date;
422 if ( !empty ( $title ) ) {
423 $query .= ' AND post_title = %s';
424 $args[] = $post_title;
427 if ( !empty ( $content ) ) {
428 $query .= 'AND post_content = %s';
429 $args[] = $post_content;
432 if ( !empty ( $args ) )
433 return $wpdb->get_var( $wpdb->prepare($query, $args) );
439 * Creates a new post from the "Write Post" form using $_POST information.
445 function wp_write_post() {
448 if ( 'page' == $_POST['post_type'] ) {
449 if ( !current_user_can( 'edit_pages' ) )
450 return new WP_Error( 'edit_pages', __( 'You are not allowed to create pages on this blog.' ) );
452 if ( !current_user_can( 'edit_posts' ) )
453 return new WP_Error( 'edit_posts', __( 'You are not allowed to create posts or drafts on this blog.' ) );
457 // Check for autosave collisions
459 if ( isset($_POST['temp_ID']) ) {
460 $temp_id = (int) $_POST['temp_ID'];
461 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
462 $draft_ids = array();
463 foreach ( $draft_ids as $temp => $real )
464 if ( time() + $temp > 86400 ) // 1 day: $temp is equal to -1 * time( then )
465 unset($draft_ids[$temp]);
467 if ( isset($draft_ids[$temp_id]) ) { // Edit, don't write
468 $_POST['post_ID'] = $draft_ids[$temp_id];
469 unset($_POST['temp_ID']);
470 update_user_option( $user_ID, 'autosave_draft_ids', $draft_ids );
475 $translated = _wp_translate_postdata( false );
476 if ( is_wp_error($translated) )
479 if ( isset($_POST['visibility']) ) {
480 switch ( $_POST['visibility'] ) {
482 $_POST['post_password'] = '';
485 unset( $_POST['sticky'] );
488 $_POST['post_status'] = 'private';
489 $_POST['post_password'] = '';
490 unset( $_POST['sticky'] );
496 $post_ID = wp_insert_post( $_POST );
497 if ( is_wp_error( $post_ID ) )
500 if ( empty($post_ID) )
503 add_meta( $post_ID );
505 // Reunite any orphaned attachments with their parent
506 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
507 $draft_ids = array();
508 if ( $draft_temp_id = (int) array_search( $post_ID, $draft_ids ) )
509 _relocate_children( $draft_temp_id, $post_ID );
510 if ( $temp_id && $temp_id != $draft_temp_id )
511 _relocate_children( $temp_id, $post_ID );
513 // Update autosave collision detection
515 $draft_ids[$temp_id] = $post_ID;
516 update_user_option( $user_ID, 'autosave_draft_ids', $draft_ids );
519 // Now that we have an ID we can fix any attachment anchor hrefs
520 _fix_attachment_links( $post_ID );
522 wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
528 * Calls wp_write_post() and handles the errors.
534 function write_post() {
535 $result = wp_write_post();
536 if( is_wp_error( $result ) )
537 wp_die( $result->get_error_message() );
547 * {@internal Missing Short Description}}
551 * @param unknown_type $post_ID
554 function add_meta( $post_ID ) {
556 $post_ID = (int) $post_ID;
558 $protected = array( '_wp_attached_file', '_wp_attachment_metadata', '_wp_old_slug', '_wp_page_template' );
560 $metakeyselect = isset($_POST['metakeyselect']) ? stripslashes( trim( $_POST['metakeyselect'] ) ) : '';
561 $metakeyinput = isset($_POST['metakeyinput']) ? stripslashes( trim( $_POST['metakeyinput'] ) ) : '';
562 $metavalue = isset($_POST['metavalue']) ? maybe_serialize( stripslashes_deep( $_POST['metavalue'] ) ) : '';
563 if ( is_string($metavalue) )
564 $metavalue = trim( $metavalue );
566 if ( ('0' === $metavalue || !empty ( $metavalue ) ) && ((('#NONE#' != $metakeyselect) && !empty ( $metakeyselect) ) || !empty ( $metakeyinput) ) ) {
567 // We have a key/value pair. If both the select and the
568 // input for the key have data, the input takes precedence:
570 if ('#NONE#' != $metakeyselect)
571 $metakey = $metakeyselect;
574 $metakey = $metakeyinput; // default
576 if ( in_array($metakey, $protected) )
579 wp_cache_delete($post_ID, 'post_meta');
581 $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->postmeta (post_id,meta_key,meta_value ) VALUES (%s, %s, %s)", $post_ID, $metakey, $metavalue) );
582 do_action( 'added_postmeta', $wpdb->insert_id, $post_ID, $metakey, $metavalue );
584 return $wpdb->insert_id;
590 * {@internal Missing Short Description}}
594 * @param unknown_type $mid
597 function delete_meta( $mid ) {
601 $post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
603 do_action( 'delete_postmeta', $mid );
604 wp_cache_delete($post_id, 'post_meta');
605 $rval = $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
606 do_action( 'deleted_postmeta', $mid );
612 * Get a list of previously defined keys.
618 function get_meta_keys() {
621 $keys = $wpdb->get_col( "
625 ORDER BY meta_key" );
631 * {@internal Missing Short Description}}
635 * @param unknown_type $mid
638 function get_post_meta_by_id( $mid ) {
642 $meta = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
643 if ( is_serialized_string( $meta->meta_value ) )
644 $meta->meta_value = maybe_unserialize( $meta->meta_value );
649 * {@internal Missing Short Description}}
651 * Some postmeta stuff.
655 * @param unknown_type $postid
658 function has_meta( $postid ) {
661 return $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value, meta_id, post_id
662 FROM $wpdb->postmeta WHERE post_id = %d
663 ORDER BY meta_key,meta_id", $postid), ARRAY_A );
668 * {@internal Missing Short Description}}
672 * @param unknown_type $meta_id
673 * @param unknown_type $meta_key
674 * @param unknown_type $meta_value
677 function update_meta( $meta_id, $meta_key, $meta_value ) {
680 $protected = array( '_wp_attached_file', '_wp_attachment_metadata', '_wp_old_slug', '_wp_page_template' );
682 if ( in_array($meta_key, $protected) )
685 if ( '' === trim( $meta_value ) )
688 $post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_id = %d", $meta_id) );
690 $meta_value = maybe_serialize( stripslashes_deep( $meta_value ) );
691 $meta_id = (int) $meta_id;
693 $data = compact( 'meta_key', 'meta_value' );
694 $where = compact( 'meta_id' );
696 do_action( 'update_postmeta', $meta_id, $post_id, $meta_key, $meta_value );
697 $rval = $wpdb->update( $wpdb->postmeta, $data, $where );
698 wp_cache_delete($post_id, 'post_meta');
699 do_action( 'updated_postmeta', $meta_id, $post_id, $meta_key, $meta_value );
709 * Replace hrefs of attachment anchors with up-to-date permalinks.
714 * @param unknown_type $post_ID
717 function _fix_attachment_links( $post_ID ) {
718 global $_fix_attachment_link_id;
720 $post = & get_post( $post_ID, ARRAY_A );
722 $search = "#<a[^>]+rel=('|\")[^'\"]*attachment[^>]*>#ie";
724 // See if we have any rel="attachment" links
725 if ( 0 == preg_match_all( $search, $post['post_content'], $anchor_matches, PREG_PATTERN_ORDER ) )
729 $search = "#[\s]+rel=(\"|')(.*?)wp-att-(\d+)\\1#i";
730 foreach ( $anchor_matches[0] as $anchor ) {
731 if ( 0 == preg_match( $search, $anchor, $id_matches ) )
734 $id = (int) $id_matches[3];
736 // While we have the attachment ID, let's adopt any orphans.
737 $attachment = & get_post( $id, ARRAY_A );
738 if ( ! empty( $attachment) && ! is_object( get_post( $attachment['post_parent'] ) ) ) {
739 $attachment['post_parent'] = $post_ID;
740 // Escape data pulled from DB.
741 $attachment = add_magic_quotes( $attachment);
742 wp_update_post( $attachment);
745 $post_search[$i] = $anchor;
746 $_fix_attachment_link_id = $id;
747 $post_replace[$i] = preg_replace_callback( "#href=(\"|')[^'\"]*\\1#", '_fix_attachment_links_replace_cb', $anchor );
751 $post['post_content'] = str_replace( $post_search, $post_replace, $post['post_content'] );
753 // Escape data pulled from DB.
754 $post = add_magic_quotes( $post);
756 return wp_update_post( $post);
759 function _fix_attachment_links_replace_cb($match) {
760 global $_fix_attachment_link_id;
761 return stripslashes( 'href='.$match[1] ).get_attachment_link( $_fix_attachment_link_id ).stripslashes( $match[1] );
765 * Move child posts to a new parent.
770 * @param unknown_type $old_ID
771 * @param unknown_type $new_ID
774 function _relocate_children( $old_ID, $new_ID ) {
776 $old_ID = (int) $old_ID;
777 $new_ID = (int) $new_ID;
779 $children = $wpdb->get_col( $wpdb->prepare("
782 WHERE meta_key = '_wp_attachment_temp_parent'
783 AND meta_value = %d", $old_ID) );
785 foreach ( $children as $child_id ) {
786 $wpdb->update($wpdb->posts, array('post_parent' => $new_ID), array('ID' => $child_id) );
787 delete_post_meta($child_id, '_wp_attachment_temp_parent');
792 * {@internal Missing Short Description}}
796 * @param unknown_type $type
799 function get_available_post_statuses($type = 'post') {
800 $stati = wp_count_posts($type);
802 return array_keys(get_object_vars($stati));
806 * {@internal Missing Short Description}}
810 * @param unknown_type $q
813 function wp_edit_posts_query( $q = false ) {
816 $q['m'] = isset($q['m']) ? (int) $q['m'] : 0;
817 $q['cat'] = isset($q['cat']) ? (int) $q['cat'] : 0;
818 $post_stati = array( // array( adj, noun )
819 'publish' => array(_x('Published', 'post'), __('Published posts'), _n_noop('Published <span class="count">(%s)</span>', 'Published <span class="count">(%s)</span>')),
820 'future' => array(_x('Scheduled', 'post'), __('Scheduled posts'), _n_noop('Scheduled <span class="count">(%s)</span>', 'Scheduled <span class="count">(%s)</span>')),
821 'pending' => array(_x('Pending Review', 'post'), __('Pending posts'), _n_noop('Pending Review <span class="count">(%s)</span>', 'Pending Review <span class="count">(%s)</span>')),
822 'draft' => array(_x('Draft', 'post'), _x('Drafts', 'manage posts header'), _n_noop('Draft <span class="count">(%s)</span>', 'Drafts <span class="count">(%s)</span>')),
823 'private' => array(_x('Private', 'post'), __('Private posts'), _n_noop('Private <span class="count">(%s)</span>', 'Private <span class="count">(%s)</span>')),
824 'trash' => array(_x('Trash', 'post'), __('Trash posts'), _n_noop('Trash <span class="count">(%s)</span>', 'Trash <span class="count">(%s)</span>')),
827 $post_stati = apply_filters('post_stati', $post_stati);
829 $avail_post_stati = get_available_post_statuses('post');
832 if ( isset($q['post_status']) && in_array( $q['post_status'], array_keys($post_stati) ) ) {
833 $post_status_q = '&post_status=' . $q['post_status'];
834 $post_status_q .= '&perm=readable';
837 if ( isset($q['post_status']) && 'pending' === $q['post_status'] ) {
839 $orderby = 'modified';
840 } elseif ( isset($q['post_status']) && 'draft' === $q['post_status'] ) {
842 $orderby = 'modified';
848 $posts_per_page = (int) get_user_option( 'edit_per_page', 0, false );
849 if ( empty( $posts_per_page ) || $posts_per_page < 1 )
850 $posts_per_page = 15;
851 $posts_per_page = apply_filters( 'edit_posts_per_page', $posts_per_page );
853 wp("post_type=post&$post_status_q&posts_per_page=$posts_per_page&order=$order&orderby=$orderby");
855 return array($post_stati, $avail_post_stati);
859 * Get default post mime types
865 function get_post_mime_types() {
866 $post_mime_types = array( // array( adj, noun )
867 'image' => array(__('Images'), __('Manage Images'), _n_noop('Image <span class="count">(%s)</span>', 'Images <span class="count">(%s)</span>')),
868 'audio' => array(__('Audio'), __('Manage Audio'), _n_noop('Audio <span class="count">(%s)</span>', 'Audio <span class="count">(%s)</span>')),
869 'video' => array(__('Video'), __('Manage Video'), _n_noop('Video <span class="count">(%s)</span>', 'Video <span class="count">(%s)</span>')),
872 return apply_filters('post_mime_types', $post_mime_types);
876 * {@internal Missing Short Description}}
880 * @param unknown_type $type
883 function get_available_post_mime_types($type = 'attachment') {
886 $types = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT post_mime_type FROM $wpdb->posts WHERE post_type = %s", $type));
891 * {@internal Missing Short Description}}
895 * @param unknown_type $q
898 function wp_edit_attachments_query( $q = false ) {
902 $q['m'] = isset( $q['m'] ) ? (int) $q['m'] : 0;
903 $q['cat'] = isset( $q['cat'] ) ? (int) $q['cat'] : 0;
904 $q['post_type'] = 'attachment';
905 $q['post_status'] = isset( $q['status'] ) && 'trash' == $q['status'] ? 'trash' : 'inherit';
906 $media_per_page = (int) get_user_option( 'upload_per_page', 0, false );
907 if ( empty( $media_per_page ) || $media_per_page < 1 )
908 $media_per_page = 20;
909 $q['posts_per_page'] = apply_filters( 'upload_per_page', $media_per_page );
911 $post_mime_types = get_post_mime_types();
912 $avail_post_mime_types = get_available_post_mime_types('attachment');
914 if ( isset($q['post_mime_type']) && !array_intersect( (array) $q['post_mime_type'], array_keys($post_mime_types) ) )
915 unset($q['post_mime_type']);
919 return array($post_mime_types, $avail_post_mime_types);
923 * {@internal Missing Short Description}}
927 * @param unknown_type $id
928 * @param unknown_type $page
931 function postbox_classes( $id, $page ) {
932 if ( isset( $_GET['edit'] ) && $_GET['edit'] == $id )
934 $current_user = wp_get_current_user();
935 if ( $closed = get_user_option('closedpostboxes_'.$page, 0, false ) ) {
936 if ( !is_array( $closed ) ) return '';
937 return in_array( $id, $closed )? 'closed' : '';
944 * {@internal Missing Short Description}}
948 * @param int|object $id Post ID or post object.
949 * @param string $title (optional) Title
950 * @param string $name (optional) Name
951 * @return array With two entries of type string
953 function get_sample_permalink($id, $title = null, $name = null) {
954 $post = &get_post($id);
956 return array('', '');
958 $original_status = $post->post_status;
959 $original_date = $post->post_date;
960 $original_name = $post->post_name;
962 // Hack: get_permalink would return ugly permalink for
963 // drafts, so we will fake, that our post is published
964 if (in_array($post->post_status, array('draft', 'pending'))) {
965 $post->post_status = 'publish';
966 $post->post_name = sanitize_title($post->post_name ? $post->post_name : $post->post_title, $post->ID);
969 $post->post_name = wp_unique_post_slug($post->post_name, $post->ID, $post->post_status, $post->post_type, $post->post_parent);
971 // If the user wants to set a new name -- override the current one
972 // Note: if empty name is supplied -- use the title instead, see #6072
973 if (!is_null($name)) {
974 $post->post_name = sanitize_title($name ? $name : $title, $post->ID);
977 $post->filter = 'sample';
979 $permalink = get_permalink($post, true);
981 // Handle page hierarchy
982 if ( 'page' == $post->post_type ) {
983 $uri = get_page_uri($post->ID);
984 $uri = untrailingslashit($uri);
985 $uri = strrev( stristr( strrev( $uri ), '/' ) );
986 $uri = untrailingslashit($uri);
989 $permalink = str_replace('%pagename%', "${uri}%pagename%", $permalink);
992 $permalink = array($permalink, apply_filters('editable_slug', $post->post_name));
993 $post->post_status = $original_status;
994 $post->post_date = $original_date;
995 $post->post_name = $original_name;
996 unset($post->filter);
1002 * sample permalink html
1004 * intended to be used for the inplace editor of the permalink post slug on in the post (and page?) editor.
1008 * @param int|object $id Post ID or post object.
1009 * @param string $new_title (optional) New title
1010 * @param string $new_slug (optional) New slug
1011 * @return string intended to be used for the inplace editor of the permalink post slug on in the post (and page?) editor.
1013 function get_sample_permalink_html( $id, $new_title = null, $new_slug = null ) {
1014 $post = &get_post($id);
1015 list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug);
1017 if ( 'publish' == $post->post_status ) {
1018 $view_post = 'post' == $post->post_type ? __('View Post') : __('View Page');
1019 $title = __('Click to edit this part of the permalink');
1021 $title = __('Temporary permalink. Click to edit this part.');
1024 if ( false === strpos($permalink, '%postname%') && false === strpos($permalink, '%pagename%') ) {
1025 $return = '<strong>' . __('Permalink:') . "</strong>\n" . '<span id="sample-permalink">' . $permalink . "</span>\n";
1026 if ( current_user_can( 'manage_options' ) && !( 'page' == get_option('show_on_front') && $id == get_option('page_on_front') ) )
1027 $return .= '<span id="change-permalinks"><a href="options-permalink.php" class="button" target="_blank">' . __('Change Permalinks') . "</a></span>\n";
1028 if ( isset($view_post) )
1029 $return .= "<span id='view-post-btn'><a href='$permalink' class='button' target='_blank'>$view_post</a></span>\n";
1031 $return = apply_filters('get_sample_permalink_html', $return, $id, $new_title, $new_slug);
1036 if ( function_exists('mb_strlen') ) {
1037 if ( mb_strlen($post_name) > 30 ) {
1038 $post_name_abridged = mb_substr($post_name, 0, 14). '…' . mb_substr($post_name, -14);
1040 $post_name_abridged = $post_name;
1043 if ( strlen($post_name) > 30 ) {
1044 $post_name_abridged = substr($post_name, 0, 14). '…' . substr($post_name, -14);
1046 $post_name_abridged = $post_name;
1050 $post_name_html = '<span id="editable-post-name" title="' . $title . '">' . $post_name_abridged . '</span>';
1051 $display_link = str_replace(array('%pagename%','%postname%'), $post_name_html, $permalink);
1052 $view_link = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
1053 $return = '<strong>' . __('Permalink:') . "</strong>\n" . '<span id="sample-permalink">' . $display_link . "</span>\n";
1054 $return .= '<span id="edit-slug-buttons"><a href="#post_name" class="edit-slug button hide-if-no-js" onclick="editPermalink(' . $id . '); return false;">' . __('Edit') . "</a></span>\n";
1055 $return .= '<span id="editable-post-name-full">' . $post_name . "</span>\n";
1056 if ( isset($view_post) )
1057 $return .= "<span id='view-post-btn'><a href='$view_link' class='button' target='_blank'>$view_post</a></span>\n";
1059 $return = apply_filters('get_sample_permalink_html', $return, $id, $new_title, $new_slug);
1065 * Output HTML for the post thumbnail meta-box.
1069 * @param int $thumbnail_id ID of the attachment used for thumbnail
1070 * @return string html
1072 function _wp_post_thumbnail_html( $thumbnail_id = NULL ) {
1073 global $content_width, $_wp_additional_image_sizes;
1074 $content = '<p class="hide-if-no-js"><a href="#" id="set-post-thumbnail" onclick="jQuery(\'#add_image\').click();return false;">' . esc_html__( 'Set thumbnail' ) . '</a></p>';
1076 if ( $thumbnail_id && get_post( $thumbnail_id ) ) {
1077 $old_content_width = $content_width;
1078 $content_width = 266;
1079 if ( !isset( $_wp_additional_image_sizes['post-thumbnail'] ) )
1080 $thumbnail_html = wp_get_attachment_image( $thumbnail_id, array( $content_width, $content_width ) );
1082 $thumbnail_html = wp_get_attachment_image( $thumbnail_id, 'post-thumbnail' );
1083 if ( !empty( $thumbnail_html ) ) {
1084 $content = '<a href="#" id="set-post-thumbnail" onclick="jQuery(\'#add_image\').click();return false;">' . $thumbnail_html . '</a>';
1085 $content .= '<p class="hide-if-no-js"><a href="#" id="remove-post-thumbnail" onclick="WPRemoveThumbnail();return false;">' . esc_html__( 'Remove thumbnail' ) . '</a></p>';
1087 $content_width = $old_content_width;
1090 return apply_filters( 'admin_post_thumbnail_html', $content );
1094 * Check to see if the post is currently being edited by another user.
1098 * @param int $post_id ID of the post to check for editing
1099 * @return bool|int False: not locked or locked by current user. Int: user ID of user with lock.
1101 function wp_check_post_lock( $post_id ) {
1102 global $current_user;
1104 if ( !$post = get_post( $post_id ) )
1107 $lock = get_post_meta( $post->ID, '_edit_lock', true );
1108 $last = get_post_meta( $post->ID, '_edit_last', true );
1110 $time_window = apply_filters( 'wp_check_post_lock_window', AUTOSAVE_INTERVAL * 2 );
1112 if ( $lock && $lock > time() - $time_window && $last != $current_user->ID )
1118 * Mark the post as currently being edited by the current user
1122 * @param int $post_id ID of the post to being edited
1123 * @return bool Returns false if the post doesn't exist of there is no current user
1125 function wp_set_post_lock( $post_id ) {
1126 global $current_user;
1127 if ( !$post = get_post( $post_id ) )
1129 if ( !$current_user || !$current_user->ID )
1134 if ( !add_post_meta( $post->ID, '_edit_lock', $now, true ) )
1135 update_post_meta( $post->ID, '_edit_lock', $now );
1136 if ( !add_post_meta( $post->ID, '_edit_last', $current_user->ID, true ) )
1137 update_post_meta( $post->ID, '_edit_last', $current_user->ID );
1141 * Outputs the notice message to say that someone else is editing this post at the moment.
1146 function _admin_notice_post_locked() {
1148 $last_user = get_userdata( get_post_meta( $post->ID, '_edit_last', true ) );
1149 $last_user_name = $last_user ? $last_user->display_name : __('Somebody');
1151 switch ($post->post_type) {
1153 $message = __( 'Warning: %s is currently editing this post' );
1156 $message = __( 'Warning: %s is currently editing this page' );
1159 $message = __( 'Warning: %s is currently editing this.' );
1162 $message = sprintf( $message, esc_html( $last_user_name ) );
1163 echo "<div class='error'><p>$message</p></div>";
1167 * Creates autosave data for the specified post from $_POST data.
1169 * @package WordPress
1170 * @subpackage Post_Revisions
1173 * @uses _wp_translate_postdata()
1174 * @uses _wp_post_revision_fields()
1176 function wp_create_post_autosave( $post_id ) {
1177 $translated = _wp_translate_postdata( true );
1178 if ( is_wp_error( $translated ) )
1181 // Only store one autosave. If there is already an autosave, overwrite it.
1182 if ( $old_autosave = wp_get_post_autosave( $post_id ) ) {
1183 $new_autosave = _wp_post_revision_fields( $_POST, true );
1184 $new_autosave['ID'] = $old_autosave->ID;
1185 $current_user = wp_get_current_user();
1186 $new_autosave['post_author'] = $current_user->ID;
1187 return wp_update_post( $new_autosave );
1190 // _wp_put_post_revision() expects unescaped.
1191 $_POST = stripslashes_deep($_POST);
1193 // Otherwise create the new autosave as a special post revision
1194 return _wp_put_post_revision( $_POST, true );
1198 * Save draft or manually autosave for showing preview.
1200 * @package WordPress
1203 * @uses wp_write_post()
1206 * @uses current_user_can()
1207 * @uses wp_create_post_autosave()
1209 * @return str URL to redirect to show the preview
1211 function post_preview() {
1213 $post_ID = (int) $_POST['post_ID'];
1215 wp_die( __('Preview not available. Please save as a draft first.') );
1217 if ( isset($_POST['catslist']) )
1218 $_POST['post_category'] = explode(",", $_POST['catslist']);
1220 if ( isset($_POST['tags_input']) )
1221 $_POST['tags_input'] = explode(",", $_POST['tags_input']);
1223 if ( $_POST['post_type'] == 'page' || empty($_POST['post_category']) )
1224 unset($_POST['post_category']);
1226 $_POST['ID'] = $post_ID;
1227 $post = get_post($post_ID);
1229 if ( 'page' == $post->post_type ) {
1230 if ( !current_user_can('edit_page', $post_ID) )
1231 wp_die(__('You are not allowed to edit this page.'));
1233 if ( !current_user_can('edit_post', $post_ID) )
1234 wp_die(__('You are not allowed to edit this post.'));
1237 if ( 'draft' == $post->post_status ) {
1239 } else { // Non drafts are not overwritten. The autosave is stored in a special post revision.
1240 $id = wp_create_post_autosave( $post->ID );
1241 if ( ! is_wp_error($id) )
1245 if ( is_wp_error($id) )
1246 wp_die( $id->get_error_message() );
1248 if ( $_POST['post_status'] == 'draft' ) {
1249 $url = add_query_arg( 'preview', 'true', get_permalink($id) );
1251 $nonce = wp_create_nonce('post_preview_' . $id);
1252 $url = add_query_arg( array( 'preview' => 'true', 'preview_id' => $id, 'preview_nonce' => $nonce ), get_permalink($id) );
1259 * Adds the TinyMCE editor used on the Write and Edit screens.
1261 * @package WordPress
1264 * TinyMCE is loaded separately from other Javascript by using wp-tinymce.php. It outputs concatenated
1265 * and optionaly pre-compressed version of the core and all default plugins. Additional plugins are loaded
1266 * directly by TinyMCE using non-blocking method. Custom plugins can be refreshed by adding a query string
1267 * to the URL when queueing them with the mce_external_plugins filter.
1269 * @param bool $teeny optional Output a trimmed down version used in Press This.
1270 * @param mixed $settings optional An array that can add to or overwrite the default TinyMCE settings.
1272 function wp_tiny_mce( $teeny = false, $settings = false ) {
1273 global $concatenate_scripts, $compress_scripts, $tinymce_version;
1275 if ( ! user_can_richedit() )
1278 $baseurl = includes_url('js/tinymce');
1280 $mce_locale = ( '' == get_locale() ) ? 'en' : strtolower( substr(get_locale(), 0, 2) ); // only ISO 639-1
1283 The following filter allows localization scripts to change the languages displayed in the spellchecker's drop-down menu.
1284 By default it uses Google's spellchecker API, but can be configured to use PSpell/ASpell if installed on the server.
1285 The + sign marks the default language. More information:
1286 http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker
1288 $mce_spellchecker_languages = apply_filters('mce_spellchecker_languages', '+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv');
1291 $plugins = apply_filters( 'teeny_mce_plugins', array('safari', 'inlinepopups', 'media', 'fullscreen', 'wordpress') );
1294 $plugins = array( 'safari', 'inlinepopups', 'spellchecker', 'paste', 'wordpress', 'media', 'fullscreen', 'wpeditimage', 'wpgallery', 'tabfocus' );
1297 The following filter takes an associative array of external plugins for TinyMCE in the form 'plugin_name' => 'url'.
1298 It adds the plugin's name to TinyMCE's plugins init and the call to PluginManager to load the plugin.
1299 The url should be absolute and should include the js file name to be loaded. Example:
1300 array( 'myplugin' => 'http://my-site.com/wp-content/plugins/myfolder/mce_plugin.js' )
1301 If the plugin uses a button, it should be added with one of the "$mce_buttons" filters.
1303 $mce_external_plugins = apply_filters('mce_external_plugins', array());
1306 if ( ! empty($mce_external_plugins) ) {
1309 The following filter loads external language files for TinyMCE plugins.
1310 It takes an associative array 'plugin_name' => 'path', where path is the
1311 include path to the file. The language file should follow the same format as
1312 /tinymce/langs/wp-langs.php and should define a variable $strings that
1313 holds all translated strings.
1314 When this filter is not used, the function will try to load {mce_locale}.js.
1315 If that is not found, en.js will be tried next.
1317 $mce_external_languages = apply_filters('mce_external_languages', array());
1319 $loaded_langs = array();
1322 if ( ! empty($mce_external_languages) ) {
1323 foreach ( $mce_external_languages as $name => $path ) {
1324 if ( @is_file($path) && @is_readable($path) ) {
1325 include_once($path);
1326 $ext_plugins .= $strings . "\n";
1327 $loaded_langs[] = $name;
1332 foreach ( $mce_external_plugins as $name => $url ) {
1334 if ( is_ssl() ) $url = str_replace('http://', 'https://', $url);
1336 $plugins[] = '-' . $name;
1338 $plugurl = dirname($url);
1339 $strings = $str1 = $str2 = '';
1340 if ( ! in_array($name, $loaded_langs) ) {
1341 $path = str_replace( WP_PLUGIN_URL, '', $plugurl );
1342 $path = WP_PLUGIN_DIR . $path . '/langs/';
1344 if ( function_exists('realpath') )
1345 $path = trailingslashit( realpath($path) );
1347 if ( @is_file($path . $mce_locale . '.js') )
1348 $strings .= @file_get_contents($path . $mce_locale . '.js') . "\n";
1350 if ( @is_file($path . $mce_locale . '_dlg.js') )
1351 $strings .= @file_get_contents($path . $mce_locale . '_dlg.js') . "\n";
1353 if ( 'en' != $mce_locale && empty($strings) ) {
1354 if ( @is_file($path . 'en.js') ) {
1355 $str1 = @file_get_contents($path . 'en.js');
1356 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str1, 1 ) . "\n";
1359 if ( @is_file($path . 'en_dlg.js') ) {
1360 $str2 = @file_get_contents($path . 'en_dlg.js');
1361 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str2, 1 ) . "\n";
1365 if ( ! empty($strings) )
1366 $ext_plugins .= "\n" . $strings . "\n";
1369 $ext_plugins .= 'tinyMCEPreInit.load_ext("' . $plugurl . '", "' . $mce_locale . '");' . "\n";
1370 $ext_plugins .= 'tinymce.PluginManager.load("' . $name . '", "' . $url . '");' . "\n";
1375 $plugins = implode($plugins, ',');
1378 $mce_buttons = apply_filters( 'teeny_mce_buttons', array('bold, italic, underline, blockquote, separator, strikethrough, bullist, numlist,justifyleft, justifycenter, justifyright, undo, redo, link, unlink, fullscreen') );
1379 $mce_buttons = implode($mce_buttons, ',');
1380 $mce_buttons_2 = $mce_buttons_3 = $mce_buttons_4 = '';
1382 $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', '|', 'bullist', 'numlist', 'blockquote', '|', 'justifyleft', 'justifycenter', 'justifyright', '|', 'link', 'unlink', 'wp_more', '|', 'spellchecker', 'fullscreen', 'wp_adv' ));
1383 $mce_buttons = implode($mce_buttons, ',');
1385 $mce_buttons_2 = apply_filters('mce_buttons_2', array('formatselect', 'underline', 'justifyfull', 'forecolor', '|', 'pastetext', 'pasteword', 'removeformat', '|', 'media', 'charmap', '|', 'outdent', 'indent', '|', 'undo', 'redo', 'wp_help' ));
1386 $mce_buttons_2 = implode($mce_buttons_2, ',');
1388 $mce_buttons_3 = apply_filters('mce_buttons_3', array());
1389 $mce_buttons_3 = implode($mce_buttons_3, ',');
1391 $mce_buttons_4 = apply_filters('mce_buttons_4', array());
1392 $mce_buttons_4 = implode($mce_buttons_4, ',');
1394 $no_captions = ( apply_filters( 'disable_captions', '' ) ) ? true : false;
1396 // TinyMCE init settings
1397 $initArray = array (
1398 'mode' => 'specific_textareas',
1399 'editor_selector' => 'theEditor',
1401 'theme' => 'advanced',
1402 'skin' => 'wp_theme',
1403 'theme_advanced_buttons1' => "$mce_buttons",
1404 'theme_advanced_buttons2' => "$mce_buttons_2",
1405 'theme_advanced_buttons3' => "$mce_buttons_3",
1406 'theme_advanced_buttons4' => "$mce_buttons_4",
1407 'language' => "$mce_locale",
1408 'spellchecker_languages' => "$mce_spellchecker_languages",
1409 'theme_advanced_toolbar_location' => 'top',
1410 'theme_advanced_toolbar_align' => 'left',
1411 'theme_advanced_statusbar_location' => 'bottom',
1412 'theme_advanced_resizing' => true,
1413 'theme_advanced_resize_horizontal' => false,
1414 'dialog_type' => 'modal',
1415 'relative_urls' => false,
1416 'remove_script_host' => false,
1417 'convert_urls' => false,
1418 'apply_source_formatting' => false,
1419 'remove_linebreaks' => true,
1420 'gecko_spellcheck' => true,
1421 'entities' => '38,amp,60,lt,62,gt',
1422 'accessibility_focus' => true,
1423 'tabfocus_elements' => 'major-publishing-actions',
1424 'media_strict' => false,
1425 'paste_remove_styles' => true,
1426 'paste_remove_spans' => true,
1427 'paste_strip_class_attributes' => 'all',
1428 'wpeditimage_disable_captions' => $no_captions,
1429 'plugins' => "$plugins"
1432 $mce_css = trim(apply_filters('mce_css', ''), ' ,');
1434 if ( ! empty($mce_css) )
1435 $initArray['content_css'] = "$mce_css";
1437 if ( is_array($settings) )
1438 $initArray = array_merge($initArray, $settings);
1440 // For people who really REALLY know what they're doing with TinyMCE
1441 // You can modify initArray to add, remove, change elements of the config before tinyMCE.init
1442 // Setting "valid_elements", "invalid_elements" and "extended_valid_elements" can be done through "tiny_mce_before_init".
1443 // Best is to use the default cleanup by not specifying valid_elements, as TinyMCE contains full set of XHTML 1.0.
1445 $initArray = apply_filters('teeny_mce_before_init', $initArray);
1447 $initArray = apply_filters('tiny_mce_before_init', $initArray);
1450 if ( empty($initArray['theme_advanced_buttons3']) && !empty($initArray['theme_advanced_buttons4']) ) {
1451 $initArray['theme_advanced_buttons3'] = $initArray['theme_advanced_buttons4'];
1452 $initArray['theme_advanced_buttons4'] = '';
1455 if ( ! isset($concatenate_scripts) )
1456 script_concat_settings();
1458 $language = $initArray['language'];
1459 $zip = $compress_scripts ? 1 : 0;
1464 * The tiny_mce_version filter is not needed since external plugins are loaded directly by TinyMCE.
1465 * These plugins can be refreshed by appending query string to the URL passed to mce_external_plugins filter.
1466 * If the plugin has a popup dialog, a query string can be added to the button action that opens it (in the plugin's code).
1468 $version = apply_filters('tiny_mce_version', '');
1469 $version = 'ver=' . $tinymce_version . $version;
1471 if ( 'en' != $language )
1472 include_once(ABSPATH . WPINC . '/js/tinymce/langs/wp-langs.php');
1475 foreach ( $initArray as $k => $v )
1476 $mce_options .= $k . ':"' . $v . '", ';
1478 $mce_options = rtrim( trim($mce_options), '\n\r,' ); ?>
1480 <script type="text/javascript">
1483 base : "<?php echo $baseurl; ?>",
1485 query : "<?php echo $version; ?>",
1486 mceInit : {<?php echo $mce_options; ?>},
1487 load_ext : function(url,lang){var sl=tinymce.ScriptLoader;sl.markDone(url+'/langs/'+lang+'.js');sl.markDone(url+'/langs/'+lang+'_dlg.js');}
1493 if ( $concatenate_scripts )
1494 echo "<script type='text/javascript' src='$baseurl/wp-tinymce.php?c=$zip&$version'></script>\n";
1496 echo "<script type='text/javascript' src='$baseurl/tiny_mce.js?$version'></script>\n";
1498 if ( 'en' != $language && isset($lang) )
1499 echo "<script type='text/javascript'>\n$lang\n</script>\n";
1501 echo "<script type='text/javascript' src='$baseurl/langs/wp-langs-en.js?$version'></script>\n";
1504 <script type="text/javascript">
1506 <?php if ( $ext_plugins ) echo "$ext_plugins\n"; ?>
1507 <?php if ( $concatenate_scripts ) { ?>
1508 tinyMCEPreInit.go();
1510 (function(){var t=tinyMCEPreInit,sl=tinymce.ScriptLoader,ln=t.mceInit.language,th=t.mceInit.theme,pl=t.mceInit.plugins;sl.markDone(t.base+'/langs/'+ln+'.js');sl.markDone(t.base+'/themes/'+th+'/langs/'+ln+'.js');sl.markDone(t.base+'/themes/'+th+'/langs/'+ln+'_dlg.js');tinymce.each(pl.split(','),function(n){if(n&&n.charAt(0)!='-'){sl.markDone(t.base+'/plugins/'+n+'/langs/'+ln+'.js');sl.markDone(t.base+'/plugins/'+n+'/langs/'+ln+'_dlg.js');}});})();
1512 tinyMCE.init(tinyMCEPreInit.mceInit);