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 array $post_data 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 ( !isset($post_data['user_ID']) )
35 $post_data['user_ID'] = $GLOBALS['user_ID'];
37 if (!empty ( $post_data['post_author_override'] ) ) {
38 $post_data['post_author'] = (int) $post_data['post_author_override'];
40 if (!empty ( $post_data['post_author'] ) ) {
41 $post_data['post_author'] = (int) $post_data['post_author'];
43 $post_data['post_author'] = (int) $post_data['user_ID'];
47 $ptype = get_post_type_object( $post_data['post_type'] );
48 if ( isset($post_data['user_ID']) && ($post_data['post_author'] != $post_data['user_ID']) ) {
49 if ( !current_user_can( $ptype->cap->edit_others_posts ) ) {
50 if ( 'page' == $post_data['post_type'] ) {
51 return new WP_Error( 'edit_others_pages', $update ?
52 __( 'You are not allowed to edit pages as this user.' ) :
53 __( 'You are not allowed to create pages as this user.' )
56 return new WP_Error( 'edit_others_posts', $update ?
57 __( 'You are not allowed to edit posts as this user.' ) :
58 __( 'You are not allowed to post as this user.' )
64 // What to do based on which button they pressed
65 if ( isset($post_data['saveasdraft']) && '' != $post_data['saveasdraft'] )
66 $post_data['post_status'] = 'draft';
67 if ( isset($post_data['saveasprivate']) && '' != $post_data['saveasprivate'] )
68 $post_data['post_status'] = 'private';
69 if ( isset($post_data['publish']) && ( '' != $post_data['publish'] ) && ( !isset($post_data['post_status']) || $post_data['post_status'] != 'private' ) )
70 $post_data['post_status'] = 'publish';
71 if ( isset($post_data['advanced']) && '' != $post_data['advanced'] )
72 $post_data['post_status'] = 'draft';
73 if ( isset($post_data['pending']) && '' != $post_data['pending'] )
74 $post_data['post_status'] = 'pending';
76 if ( isset( $post_data['ID'] ) )
77 $post_id = $post_data['ID'];
80 $previous_status = $post_id ? get_post_field( 'post_status', $post_id ) : false;
82 // Posts 'submitted for approval' present are submitted to $_POST the same as if they were being published.
83 // Change status from 'publish' to 'pending' if user lacks permissions to publish or to resave published posts.
84 if ( isset($post_data['post_status']) && ('publish' == $post_data['post_status'] && !current_user_can( $ptype->cap->publish_posts )) )
85 if ( $previous_status != 'publish' || !current_user_can( 'edit_post', $post_id ) )
86 $post_data['post_status'] = 'pending';
88 if ( ! isset($post_data['post_status']) )
89 $post_data['post_status'] = $previous_status;
91 if (!isset( $post_data['comment_status'] ))
92 $post_data['comment_status'] = 'closed';
94 if (!isset( $post_data['ping_status'] ))
95 $post_data['ping_status'] = 'closed';
97 foreach ( array('aa', 'mm', 'jj', 'hh', 'mn') as $timeunit ) {
98 if ( !empty( $post_data['hidden_' . $timeunit] ) && $post_data['hidden_' . $timeunit] != $post_data[$timeunit] ) {
99 $post_data['edit_date'] = '1';
104 if ( !empty( $post_data['edit_date'] ) ) {
105 $aa = $post_data['aa'];
106 $mm = $post_data['mm'];
107 $jj = $post_data['jj'];
108 $hh = $post_data['hh'];
109 $mn = $post_data['mn'];
110 $ss = $post_data['ss'];
111 $aa = ($aa <= 0 ) ? date('Y') : $aa;
112 $mm = ($mm <= 0 ) ? date('n') : $mm;
113 $jj = ($jj > 31 ) ? 31 : $jj;
114 $jj = ($jj <= 0 ) ? date('j') : $jj;
115 $hh = ($hh > 23 ) ? $hh -24 : $hh;
116 $mn = ($mn > 59 ) ? $mn -60 : $mn;
117 $ss = ($ss > 59 ) ? $ss -60 : $ss;
118 $post_data['post_date'] = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss );
119 $post_data['post_date_gmt'] = get_gmt_from_date( $post_data['post_date'] );
126 * Update an existing post with values provided in $_POST.
130 * @param array $post_data Optional.
131 * @return int Post ID.
133 function edit_post( $post_data = null ) {
135 if ( empty($post_data) )
136 $post_data = &$_POST;
138 // Clear out any data in internal vars.
139 unset( $post_data['filter'] );
141 $post_ID = (int) $post_data['post_ID'];
142 $post = get_post( $post_ID );
143 $post_data['post_type'] = $post->post_type;
144 $post_data['post_mime_type'] = $post->post_mime_type;
146 $ptype = get_post_type_object($post_data['post_type']);
147 if ( !current_user_can( $ptype->cap->edit_post, $post_ID ) ) {
148 if ( 'page' == $post_data['post_type'] )
149 wp_die( __('You are not allowed to edit this page.' ));
151 wp_die( __('You are not allowed to edit this post.' ));
154 // Autosave shouldn't save too soon after a real save
155 if ( 'autosave' == $post_data['action'] ) {
156 $post =& get_post( $post_ID );
158 $then = strtotime($post->post_date_gmt . ' +0000');
159 $delta = AUTOSAVE_INTERVAL / 2;
160 if ( ($now - $then) < $delta )
164 $post_data = _wp_translate_postdata( true, $post_data );
165 if ( is_wp_error($post_data) )
166 wp_die( $post_data->get_error_message() );
167 if ( 'autosave' != $post_data['action'] && 'auto-draft' == $post_data['post_status'] )
168 $post_data['post_status'] = 'draft';
170 if ( isset($post_data['visibility']) ) {
171 switch ( $post_data['visibility'] ) {
173 $post_data['post_password'] = '';
176 unset( $post_data['sticky'] );
179 $post_data['post_status'] = 'private';
180 $post_data['post_password'] = '';
181 unset( $post_data['sticky'] );
187 if ( current_theme_supports( 'post-formats' ) && isset( $post_data['post_format'] ) ) {
188 $formats = get_theme_support( 'post-formats' );
189 if ( is_array( $formats ) ) {
190 $formats = $formats[0];
191 if ( in_array( $post_data['post_format'], $formats ) ) {
192 set_post_format( $post_ID, $post_data['post_format'] );
193 } elseif ( '0' == $post_data['post_format'] ) {
194 set_post_format( $post_ID, false );
200 if ( isset($post_data['meta']) && $post_data['meta'] ) {
201 foreach ( $post_data['meta'] as $key => $value ) {
202 if ( !$meta = get_post_meta_by_id( $key ) )
204 if ( $meta->post_id != $post_ID )
206 if ( is_protected_meta( $value['key'] ) )
208 update_meta( $key, $value['key'], $value['value'] );
212 if ( isset($post_data['deletemeta']) && $post_data['deletemeta'] ) {
213 foreach ( $post_data['deletemeta'] as $key => $value ) {
214 if ( !$meta = get_post_meta_by_id( $key ) )
216 if ( $meta->post_id != $post_ID )
218 if ( is_protected_meta( $meta->meta_key ) )
224 add_meta( $post_ID );
226 update_post_meta( $post_ID, '_edit_last', $GLOBALS['current_user']->ID );
228 wp_update_post( $post_data );
230 // Reunite any orphaned attachments with their parent
231 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
232 $draft_ids = array();
233 if ( $draft_temp_id = (int) array_search( $post_ID, $draft_ids ) )
234 _relocate_children( $draft_temp_id, $post_ID );
236 // Now that we have an ID we can fix any attachment anchor hrefs
237 _fix_attachment_links( $post_ID );
239 wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
241 if ( current_user_can( $ptype->cap->edit_others_posts ) ) {
242 if ( ! empty( $post_data['sticky'] ) )
243 stick_post( $post_ID );
245 unstick_post( $post_ID );
252 * Process the post data for the bulk editing of posts.
254 * Updates all bulk edited posts/pages, adding (but not removing) tags and
255 * categories. Skips pages when they would be their own parent or child.
259 * @param array $post_data Optional, the array of post data to process if not provided will use $_POST superglobal.
262 function bulk_edit_posts( $post_data = null ) {
265 if ( empty($post_data) )
266 $post_data = &$_POST;
268 if ( isset($post_data['post_type']) )
269 $ptype = get_post_type_object($post_data['post_type']);
271 $ptype = get_post_type_object('post');
273 if ( !current_user_can( $ptype->cap->edit_posts ) ) {
274 if ( 'page' == $ptype->name )
275 wp_die( __('You are not allowed to edit pages.'));
277 wp_die( __('You are not allowed to edit posts.'));
280 if ( -1 == $post_data['_status'] ) {
281 $post_data['post_status'] = null;
282 unset($post_data['post_status']);
284 $post_data['post_status'] = $post_data['_status'];
286 unset($post_data['_status']);
288 $post_IDs = array_map( 'intval', (array) $post_data['post'] );
290 $reset = array( 'post_author', 'post_status', 'post_password', 'post_parent', 'page_template', 'comment_status', 'ping_status', 'keep_private', 'tax_input', 'post_category', 'sticky' );
291 foreach ( $reset as $field ) {
292 if ( isset($post_data[$field]) && ( '' == $post_data[$field] || -1 == $post_data[$field] ) )
293 unset($post_data[$field]);
296 if ( isset($post_data['post_category']) ) {
297 if ( is_array($post_data['post_category']) && ! empty($post_data['post_category']) )
298 $new_cats = array_map( 'absint', $post_data['post_category'] );
300 unset($post_data['post_category']);
303 $tax_input = array();
304 if ( isset($post_data['tax_input'])) {
305 foreach ( $post_data['tax_input'] as $tax_name => $terms ) {
308 if ( is_taxonomy_hierarchical( $tax_name ) )
309 $tax_input[$tax_name] = array_map( 'absint', $terms );
311 $tax_input[$tax_name] = preg_replace( '/\s*,\s*/', ',', rtrim( trim($terms), ' ,' ) );
312 $tax_input[$tax_name] = explode(',', $tax_input[$tax_name]);
317 if ( isset($post_data['post_parent']) && ($parent = (int) $post_data['post_parent']) ) {
318 $pages = $wpdb->get_results("SELECT ID, post_parent FROM $wpdb->posts WHERE post_type = 'page'");
321 for ( $i = 0; $i < 50 && $parent > 0; $i++ ) {
322 $children[] = $parent;
324 foreach ( $pages as $page ) {
325 if ( $page->ID == $parent ) {
326 $parent = $page->post_parent;
333 $updated = $skipped = $locked = array();
334 foreach ( $post_IDs as $post_ID ) {
335 $post_type_object = get_post_type_object( get_post_type( $post_ID ) );
337 if ( !isset( $post_type_object ) || ( isset($children) && in_array($post_ID, $children) ) || !current_user_can( $post_type_object->cap->edit_post, $post_ID ) ) {
338 $skipped[] = $post_ID;
342 if ( wp_check_post_lock( $post_ID ) ) {
343 $locked[] = $post_ID;
347 $post = get_post( $post_ID );
348 $tax_names = get_object_taxonomies( $post );
349 foreach ( $tax_names as $tax_name ) {
350 $taxonomy_obj = get_taxonomy($tax_name);
351 if ( isset( $tax_input[$tax_name]) && current_user_can( $taxonomy_obj->cap->assign_terms ) )
352 $new_terms = $tax_input[$tax_name];
354 $new_terms = array();
356 if ( $taxonomy_obj->hierarchical )
357 $current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array('fields' => 'ids') );
359 $current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array('fields' => 'names') );
361 $post_data['tax_input'][$tax_name] = array_merge( $current_terms, $new_terms );
364 if ( isset($new_cats) && in_array( 'category', $tax_names ) ) {
365 $cats = (array) wp_get_post_categories($post_ID);
366 $post_data['post_category'] = array_unique( array_merge($cats, $new_cats) );
367 unset( $post_data['tax_input']['category'] );
370 $post_data['post_mime_type'] = $post->post_mime_type;
371 $post_data['guid'] = $post->guid;
373 $post_data['ID'] = $post_ID;
374 $updated[] = wp_update_post( $post_data );
376 if ( isset( $post_data['sticky'] ) && current_user_can( $ptype->cap->edit_others_posts ) ) {
377 if ( 'sticky' == $post_data['sticky'] )
378 stick_post( $post_ID );
380 unstick_post( $post_ID );
385 return array( 'updated' => $updated, 'skipped' => $skipped, 'locked' => $locked );
389 * Default post information to use when populating the "Write Post" form.
393 * @param string $post_type A post type string, defaults to 'post'.
394 * @return object stdClass object containing all the default post data as attributes
396 function get_default_post_to_edit( $post_type = 'post', $create_in_db = false ) {
400 if ( !empty( $_REQUEST['post_title'] ) )
401 $post_title = esc_html( stripslashes( $_REQUEST['post_title'] ));
404 if ( !empty( $_REQUEST['content'] ) )
405 $post_content = esc_html( stripslashes( $_REQUEST['content'] ));
408 if ( !empty( $_REQUEST['excerpt'] ) )
409 $post_excerpt = esc_html( stripslashes( $_REQUEST['excerpt'] ));
411 if ( $create_in_db ) {
412 // Cleanup old auto-drafts more than 7 days old
413 $old_posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_status = 'auto-draft' AND DATE_SUB( NOW(), INTERVAL 7 DAY ) > post_date" );
414 foreach ( (array) $old_posts as $delete )
415 wp_delete_post( $delete, true ); // Force delete
416 $post_id = wp_insert_post( array( 'post_title' => __( 'Auto Draft' ), 'post_type' => $post_type, 'post_status' => 'auto-draft' ) );
417 $post = get_post( $post_id );
418 if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post->post_type, 'post-formats' ) && get_option( 'default_post_format' ) )
419 set_post_format( $post, get_option( 'default_post_format' ) );
422 $post->post_author = '';
423 $post->post_date = '';
424 $post->post_date_gmt = '';
425 $post->post_password = '';
426 $post->post_type = $post_type;
427 $post->post_status = 'draft';
430 $post->comment_status = get_option( 'default_comment_status' );
431 $post->ping_status = get_option( 'default_ping_status' );
432 $post->post_pingback = get_option( 'default_pingback_flag' );
433 $post->post_category = get_option( 'default_category' );
434 $post->page_template = 'default';
435 $post->post_parent = 0;
436 $post->menu_order = 0;
439 $post->post_content = apply_filters( 'default_content', $post_content, $post );
440 $post->post_title = apply_filters( 'default_title', $post_title, $post );
441 $post->post_excerpt = apply_filters( 'default_excerpt', $post_excerpt, $post );
442 $post->post_name = '';
448 * Get the default page information to use.
452 * @return object stdClass object containing all the default post data as attributes
454 function get_default_page_to_edit() {
455 $page = get_default_post_to_edit();
456 $page->post_type = 'page';
461 * Get an existing post and format it for editing.
465 * @param unknown_type $id
468 function get_post_to_edit( $id ) {
470 $post = get_post( $id, OBJECT, 'edit' );
472 if ( $post->post_type == 'page' )
473 $post->page_template = get_post_meta( $id, '_wp_page_template', true );
479 * Determine if a post exists based on title, content, and date
483 * @param string $title Post title
484 * @param string $content Optional post content
485 * @param string $date Optional post date
486 * @return int Post ID if post exists, 0 otherwise.
488 function post_exists($title, $content = '', $date = '') {
491 $post_title = stripslashes( sanitize_post_field( 'post_title', $title, 0, 'db' ) );
492 $post_content = stripslashes( sanitize_post_field( 'post_content', $content, 0, 'db' ) );
493 $post_date = stripslashes( sanitize_post_field( 'post_date', $date, 0, 'db' ) );
495 $query = "SELECT ID FROM $wpdb->posts WHERE 1=1";
498 if ( !empty ( $date ) ) {
499 $query .= ' AND post_date = %s';
500 $args[] = $post_date;
503 if ( !empty ( $title ) ) {
504 $query .= ' AND post_title = %s';
505 $args[] = $post_title;
508 if ( !empty ( $content ) ) {
509 $query .= 'AND post_content = %s';
510 $args[] = $post_content;
513 if ( !empty ( $args ) )
514 return $wpdb->get_var( $wpdb->prepare($query, $args) );
520 * Creates a new post from the "Write Post" form using $_POST information.
526 function wp_write_post() {
530 if ( isset($_POST['post_type']) )
531 $ptype = get_post_type_object($_POST['post_type']);
533 $ptype = get_post_type_object('post');
535 if ( !current_user_can( $ptype->cap->edit_posts ) ) {
536 if ( 'page' == $ptype->name )
537 return new WP_Error( 'edit_pages', __( 'You are not allowed to create pages on this site.' ) );
539 return new WP_Error( 'edit_posts', __( 'You are not allowed to create posts or drafts on this site.' ) );
542 $_POST['post_mime_type'] = '';
544 // Clear out any data in internal vars.
545 unset( $_POST['filter'] );
547 // Check for autosave collisions
548 // Does this need to be updated? ~ Mark
550 if ( isset($_POST['temp_ID']) ) {
551 $temp_id = (int) $_POST['temp_ID'];
552 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
553 $draft_ids = array();
554 foreach ( $draft_ids as $temp => $real )
555 if ( time() + $temp > 86400 ) // 1 day: $temp is equal to -1 * time( then )
556 unset($draft_ids[$temp]);
558 if ( isset($draft_ids[$temp_id]) ) { // Edit, don't write
559 $_POST['post_ID'] = $draft_ids[$temp_id];
560 unset($_POST['temp_ID']);
561 update_user_option( $user_ID, 'autosave_draft_ids', $draft_ids );
566 // Edit don't write if we have a post id.
567 if ( isset( $_POST['ID'] ) ) {
568 $_POST['post_ID'] = $_POST['ID'];
569 unset ( $_POST['ID'] );
571 if ( isset( $_POST['post_ID'] ) ) {
575 $translated = _wp_translate_postdata( false );
576 if ( is_wp_error($translated) )
579 if ( isset($_POST['visibility']) ) {
580 switch ( $_POST['visibility'] ) {
582 $_POST['post_password'] = '';
585 unset( $_POST['sticky'] );
588 $_POST['post_status'] = 'private';
589 $_POST['post_password'] = '';
590 unset( $_POST['sticky'] );
596 $post_ID = wp_insert_post( $_POST );
597 if ( is_wp_error( $post_ID ) )
600 if ( empty($post_ID) )
603 add_meta( $post_ID );
605 add_post_meta( $post_ID, '_edit_last', $GLOBALS['current_user']->ID );
607 // Reunite any orphaned attachments with their parent
608 // Does this need to be udpated? ~ Mark
609 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
610 $draft_ids = array();
611 if ( $draft_temp_id = (int) array_search( $post_ID, $draft_ids ) )
612 _relocate_children( $draft_temp_id, $post_ID );
613 if ( $temp_id && $temp_id != $draft_temp_id )
614 _relocate_children( $temp_id, $post_ID );
616 // Update autosave collision detection
618 $draft_ids[$temp_id] = $post_ID;
619 update_user_option( $user_ID, 'autosave_draft_ids', $draft_ids );
622 // Now that we have an ID we can fix any attachment anchor hrefs
623 _fix_attachment_links( $post_ID );
625 wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
631 * Calls wp_write_post() and handles the errors.
637 function write_post() {
638 $result = wp_write_post();
639 if ( is_wp_error( $result ) )
640 wp_die( $result->get_error_message() );
650 * {@internal Missing Short Description}}
654 * @param unknown_type $post_ID
657 function add_meta( $post_ID ) {
659 $post_ID = (int) $post_ID;
661 $metakeyselect = isset($_POST['metakeyselect']) ? stripslashes( trim( $_POST['metakeyselect'] ) ) : '';
662 $metakeyinput = isset($_POST['metakeyinput']) ? stripslashes( trim( $_POST['metakeyinput'] ) ) : '';
663 $metavalue = isset($_POST['metavalue']) ? maybe_serialize( stripslashes_deep( $_POST['metavalue'] ) ) : '';
664 if ( is_string($metavalue) )
665 $metavalue = trim( $metavalue );
667 if ( ('0' === $metavalue || !empty ( $metavalue ) ) && ((('#NONE#' != $metakeyselect) && !empty ( $metakeyselect) ) || !empty ( $metakeyinput) ) ) {
668 // We have a key/value pair. If both the select and the
669 // input for the key have data, the input takes precedence:
671 if ('#NONE#' != $metakeyselect)
672 $metakey = $metakeyselect;
675 $metakey = $metakeyinput; // default
677 if ( is_protected_meta( $metakey ) )
680 wp_cache_delete($post_ID, 'post_meta');
681 $wpdb->insert( $wpdb->postmeta, array( 'post_id' => $post_ID, 'meta_key' => $metakey, 'meta_value' => $metavalue ) );
682 $meta_id = $wpdb->insert_id;
683 do_action( 'added_postmeta', $meta_id, $post_ID, $metakey, $metavalue );
691 * {@internal Missing Short Description}}
695 * @param unknown_type $mid
698 function delete_meta( $mid ) {
702 $post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
704 do_action( 'delete_postmeta', $mid );
705 wp_cache_delete($post_id, 'post_meta');
706 $rval = $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
707 do_action( 'deleted_postmeta', $mid );
713 * Get a list of previously defined keys.
719 function get_meta_keys() {
722 $keys = $wpdb->get_col( "
726 ORDER BY meta_key" );
732 * {@internal Missing Short Description}}
736 * @param unknown_type $mid
739 function get_post_meta_by_id( $mid ) {
743 $meta = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
746 if ( is_serialized_string( $meta->meta_value ) )
747 $meta->meta_value = maybe_unserialize( $meta->meta_value );
752 * {@internal Missing Short Description}}
754 * Some postmeta stuff.
758 * @param unknown_type $postid
761 function has_meta( $postid ) {
764 return $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value, meta_id, post_id
765 FROM $wpdb->postmeta WHERE post_id = %d
766 ORDER BY meta_key,meta_id", $postid), ARRAY_A );
771 * {@internal Missing Short Description}}
775 * @param unknown_type $meta_id
776 * @param unknown_type $meta_key Expect Slashed
777 * @param unknown_type $meta_value Expect Slashed
780 function update_meta( $meta_id, $meta_key, $meta_value ) {
783 $meta_key = stripslashes($meta_key);
785 if ( is_protected_meta( $meta_key ) )
788 if ( '' === trim( $meta_value ) )
791 $post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_id = %d", $meta_id) );
793 $meta_value = maybe_serialize( stripslashes_deep( $meta_value ) );
794 $meta_id = (int) $meta_id;
796 $data = compact( 'meta_key', 'meta_value' );
797 $where = compact( 'meta_id' );
799 do_action( 'update_postmeta', $meta_id, $post_id, $meta_key, $meta_value );
800 $rval = $wpdb->update( $wpdb->postmeta, $data, $where );
801 wp_cache_delete($post_id, 'post_meta');
802 do_action( 'updated_postmeta', $meta_id, $post_id, $meta_key, $meta_value );
812 * Replace hrefs of attachment anchors with up-to-date permalinks.
817 * @param unknown_type $post_ID
820 function _fix_attachment_links( $post_ID ) {
821 global $_fix_attachment_link_id;
823 $post = & get_post( $post_ID, ARRAY_A );
825 $search = "#<a[^>]+rel=('|\")[^'\"]*attachment[^>]*>#ie";
827 // See if we have any rel="attachment" links
828 if ( 0 == preg_match_all( $search, $post['post_content'], $anchor_matches, PREG_PATTERN_ORDER ) )
832 $search = "#[\s]+rel=(\"|')(.*?)wp-att-(\d+)\\1#i";
833 foreach ( $anchor_matches[0] as $anchor ) {
834 if ( 0 == preg_match( $search, $anchor, $id_matches ) )
837 $id = (int) $id_matches[3];
839 // While we have the attachment ID, let's adopt any orphans.
840 $attachment = & get_post( $id, ARRAY_A );
841 if ( ! empty( $attachment) && ! is_object( get_post( $attachment['post_parent'] ) ) ) {
842 $attachment['post_parent'] = $post_ID;
843 // Escape data pulled from DB.
844 $attachment = add_magic_quotes( $attachment );
845 wp_update_post( $attachment );
848 $post_search[$i] = $anchor;
849 $_fix_attachment_link_id = $id;
850 $post_replace[$i] = preg_replace_callback( "#href=(\"|')[^'\"]*\\1#", '_fix_attachment_links_replace_cb', $anchor );
854 $post['post_content'] = str_replace( $post_search, $post_replace, $post['post_content'] );
856 // Escape data pulled from DB.
857 $post = add_magic_quotes( $post);
859 return wp_update_post( $post);
862 function _fix_attachment_links_replace_cb($match) {
863 global $_fix_attachment_link_id;
864 return stripslashes( 'href='.$match[1] ).get_attachment_link( $_fix_attachment_link_id ).stripslashes( $match[1] );
868 * Move child posts to a new parent.
873 * @param unknown_type $old_ID
874 * @param unknown_type $new_ID
877 function _relocate_children( $old_ID, $new_ID ) {
879 $old_ID = (int) $old_ID;
880 $new_ID = (int) $new_ID;
882 $children = $wpdb->get_col( $wpdb->prepare("
885 WHERE meta_key = '_wp_attachment_temp_parent'
886 AND meta_value = %d", $old_ID) );
888 foreach ( $children as $child_id ) {
889 $wpdb->update($wpdb->posts, array('post_parent' => $new_ID), array('ID' => $child_id) );
890 delete_post_meta($child_id, '_wp_attachment_temp_parent');
895 * Get all the possible statuses for a post_type
899 * @param string $type The post_type you want the statuses for
900 * @return array As array of all the statuses for the supplied post type
902 function get_available_post_statuses($type = 'post') {
903 $stati = wp_count_posts($type);
905 return array_keys(get_object_vars($stati));
909 * Run the wp query to fetch the posts for listing on the edit posts page
913 * @param array|bool $q Array of query variables to use to build the query or false to use $_GET superglobal.
916 function wp_edit_posts_query( $q = false ) {
919 $q['m'] = isset($q['m']) ? (int) $q['m'] : 0;
920 $q['cat'] = isset($q['cat']) ? (int) $q['cat'] : 0;
921 $post_stati = get_post_stati();
923 if ( isset($q['post_type']) && in_array( $q['post_type'], get_post_types() ) )
924 $post_type = $q['post_type'];
928 $avail_post_stati = get_available_post_statuses($post_type);
930 if ( isset($q['post_status']) && in_array( $q['post_status'], $post_stati ) ) {
931 $post_status = $q['post_status'];
935 if ( isset($q['orderby']) )
936 $orderby = $q['orderby'];
937 elseif ( isset($q['post_status']) && in_array($q['post_status'], array('pending', 'draft')) )
938 $orderby = 'modified';
940 if ( isset($q['order']) )
941 $order = $q['order'];
942 elseif ( isset($q['post_status']) && 'pending' == $q['post_status'] )
945 $per_page = 'edit_' . $post_type . '_per_page';
946 $posts_per_page = (int) get_user_option( $per_page );
947 if ( empty( $posts_per_page ) || $posts_per_page < 1 )
948 $posts_per_page = 20;
950 $posts_per_page = apply_filters( $per_page, $posts_per_page );
951 $posts_per_page = apply_filters( 'edit_posts_per_page', $posts_per_page, $post_type );
953 $query = compact('post_type', 'post_status', 'perm', 'order', 'orderby', 'posts_per_page');
955 // Hierarchical types require special args.
956 if ( is_post_type_hierarchical( $post_type ) && !isset($orderby) ) {
957 $query['orderby'] = 'menu_order title';
958 $query['order'] = 'asc';
959 $query['posts_per_page'] = -1;
960 $query['posts_per_archive_page'] = -1;
963 if ( ! empty( $q['show_sticky'] ) )
964 $query['post__in'] = (array) get_option( 'sticky_posts' );
968 return $avail_post_stati;
972 * Get default post mime types
978 function get_post_mime_types() {
979 $post_mime_types = array( // array( adj, noun )
980 'image' => array(__('Images'), __('Manage Images'), _n_noop('Image <span class="count">(%s)</span>', 'Images <span class="count">(%s)</span>')),
981 'audio' => array(__('Audio'), __('Manage Audio'), _n_noop('Audio <span class="count">(%s)</span>', 'Audio <span class="count">(%s)</span>')),
982 'video' => array(__('Video'), __('Manage Video'), _n_noop('Video <span class="count">(%s)</span>', 'Video <span class="count">(%s)</span>')),
985 return apply_filters('post_mime_types', $post_mime_types);
989 * {@internal Missing Short Description}}
993 * @param unknown_type $type
996 function get_available_post_mime_types($type = 'attachment') {
999 $types = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT post_mime_type FROM $wpdb->posts WHERE post_type = %s", $type));
1004 * {@internal Missing Short Description}}
1008 * @param unknown_type $q
1011 function wp_edit_attachments_query( $q = false ) {
1015 $q['m'] = isset( $q['m'] ) ? (int) $q['m'] : 0;
1016 $q['cat'] = isset( $q['cat'] ) ? (int) $q['cat'] : 0;
1017 $q['post_type'] = 'attachment';
1018 $post_type = get_post_type_object( 'attachment' );
1019 $states = 'inherit';
1020 if ( current_user_can( $post_type->cap->read_private_posts ) )
1021 $states .= ',private';
1023 $q['post_status'] = isset( $q['status'] ) && 'trash' == $q['status'] ? 'trash' : $states;
1024 $media_per_page = (int) get_user_option( 'upload_per_page' );
1025 if ( empty( $media_per_page ) || $media_per_page < 1 )
1026 $media_per_page = 20;
1027 $q['posts_per_page'] = apply_filters( 'upload_per_page', $media_per_page );
1029 $post_mime_types = get_post_mime_types();
1030 $avail_post_mime_types = get_available_post_mime_types('attachment');
1032 if ( isset($q['post_mime_type']) && !array_intersect( (array) $q['post_mime_type'], array_keys($post_mime_types) ) )
1033 unset($q['post_mime_type']);
1035 if ( isset($q['detached']) )
1036 add_filter('posts_where', '_edit_attachments_query_helper');
1040 if ( isset($q['detached']) )
1041 remove_filter('posts_where', '_edit_attachments_query_helper');
1043 return array($post_mime_types, $avail_post_mime_types);
1046 function _edit_attachments_query_helper($where) {
1047 return $where .= ' AND post_parent < 1';
1051 * {@internal Missing Short Description}}
1053 * @uses get_user_option()
1056 * @param unknown_type $id
1057 * @param unknown_type $page
1060 function postbox_classes( $id, $page ) {
1061 if ( isset( $_GET['edit'] ) && $_GET['edit'] == $id )
1064 if ( $closed = get_user_option('closedpostboxes_'.$page ) ) {
1065 if ( !is_array( $closed ) ) {
1068 return in_array( $id, $closed )? 'closed' : '';
1075 * {@internal Missing Short Description}}
1079 * @param int|object $id Post ID or post object.
1080 * @param string $title (optional) Title
1081 * @param string $name (optional) Name
1082 * @return array With two entries of type string
1084 function get_sample_permalink($id, $title = null, $name = null) {
1085 $post = &get_post($id);
1087 return array('', '');
1089 $ptype = get_post_type_object($post->post_type);
1091 $original_status = $post->post_status;
1092 $original_date = $post->post_date;
1093 $original_name = $post->post_name;
1095 // Hack: get_permalink would return ugly permalink for
1096 // drafts, so we will fake, that our post is published
1097 if ( in_array($post->post_status, array('draft', 'pending')) ) {
1098 $post->post_status = 'publish';
1099 $post->post_name = sanitize_title($post->post_name ? $post->post_name : $post->post_title, $post->ID);
1102 // If the user wants to set a new name -- override the current one
1103 // Note: if empty name is supplied -- use the title instead, see #6072
1104 if ( !is_null($name) )
1105 $post->post_name = sanitize_title($name ? $name : $title, $post->ID);
1107 $post->post_name = wp_unique_post_slug($post->post_name, $post->ID, $post->post_status, $post->post_type, $post->post_parent);
1109 $post->filter = 'sample';
1111 $permalink = get_permalink($post, true);
1113 // Replace custom post_type Token with generic pagename token for ease of use.
1114 $permalink = str_replace("%$post->post_type%", '%pagename%', $permalink);
1116 // Handle page hierarchy
1117 if ( $ptype->hierarchical ) {
1118 $uri = get_page_uri($post);
1119 $uri = untrailingslashit($uri);
1120 $uri = strrev( stristr( strrev( $uri ), '/' ) );
1121 $uri = untrailingslashit($uri);
1124 $permalink = str_replace('%pagename%', "{$uri}%pagename%", $permalink);
1127 $permalink = array($permalink, apply_filters('editable_slug', $post->post_name));
1128 $post->post_status = $original_status;
1129 $post->post_date = $original_date;
1130 $post->post_name = $original_name;
1131 unset($post->filter);
1137 * sample permalink html
1139 * intended to be used for the inplace editor of the permalink post slug on in the post (and page?) editor.
1143 * @param int|object $id Post ID or post object.
1144 * @param string $new_title (optional) New title
1145 * @param string $new_slug (optional) New slug
1146 * @return string intended to be used for the inplace editor of the permalink post slug on in the post (and page?) editor.
1148 function get_sample_permalink_html( $id, $new_title = null, $new_slug = null ) {
1150 $post = &get_post($id);
1152 list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug);
1154 if ( 'publish' == $post->post_status ) {
1155 $ptype = get_post_type_object($post->post_type);
1156 $view_post = $ptype->labels->view_item;
1157 $title = __('Click to edit this part of the permalink');
1159 $title = __('Temporary permalink. Click to edit this part.');
1162 if ( false === strpos($permalink, '%postname%') && false === strpos($permalink, '%pagename%') ) {
1163 $return = '<strong>' . __('Permalink:') . "</strong>\n" . '<span id="sample-permalink">' . $permalink . "</span>\n";
1164 if ( '' == get_option( 'permalink_structure' ) && current_user_can( 'manage_options' ) && !( 'page' == get_option('show_on_front') && $id == get_option('page_on_front') ) )
1165 $return .= '<span id="change-permalinks"><a href="options-permalink.php" class="button" target="_blank">' . __('Change Permalinks') . "</a></span>\n";
1166 if ( isset($view_post) )
1167 $return .= "<span id='view-post-btn'><a href='$permalink' class='button' target='_blank'>$view_post</a></span>\n";
1169 $return = apply_filters('get_sample_permalink_html', $return, $id, $new_title, $new_slug);
1174 if ( function_exists('mb_strlen') ) {
1175 if ( mb_strlen($post_name) > 30 ) {
1176 $post_name_abridged = mb_substr($post_name, 0, 14). '…' . mb_substr($post_name, -14);
1178 $post_name_abridged = $post_name;
1181 if ( strlen($post_name) > 30 ) {
1182 $post_name_abridged = substr($post_name, 0, 14). '…' . substr($post_name, -14);
1184 $post_name_abridged = $post_name;
1188 $post_name_html = '<span id="editable-post-name" title="' . $title . '">' . $post_name_abridged . '</span>';
1189 $display_link = str_replace(array('%pagename%','%postname%'), $post_name_html, $permalink);
1190 $view_link = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
1191 $return = '<strong>' . __('Permalink:') . "</strong>\n";
1192 $return .= '<span id="sample-permalink">' . $display_link . "</span>\n";
1193 $return .= '‎'; // Fix bi-directional text display defect in RTL languages.
1194 $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";
1195 $return .= '<span id="editable-post-name-full">' . $post_name . "</span>\n";
1196 if ( isset($view_post) )
1197 $return .= "<span id='view-post-btn'><a href='$view_link' class='button' target='_blank'>$view_post</a></span>\n";
1199 $return = apply_filters('get_sample_permalink_html', $return, $id, $new_title, $new_slug);
1205 * Output HTML for the post thumbnail meta-box.
1209 * @param int $thumbnail_id ID of the attachment used for thumbnail
1210 * @return string html
1212 function _wp_post_thumbnail_html( $thumbnail_id = NULL ) {
1213 global $content_width, $_wp_additional_image_sizes, $post_ID;
1214 $set_thumbnail_link = '<p class="hide-if-no-js"><a title="' . esc_attr__( 'Set featured image' ) . '" href="' . esc_url( get_upload_iframe_src('image') ) . '" id="set-post-thumbnail" class="thickbox">%s</a></p>';
1215 $content = sprintf($set_thumbnail_link, esc_html__( 'Set featured image' ));
1217 if ( $thumbnail_id && get_post( $thumbnail_id ) ) {
1218 $old_content_width = $content_width;
1219 $content_width = 266;
1220 if ( !isset( $_wp_additional_image_sizes['post-thumbnail'] ) )
1221 $thumbnail_html = wp_get_attachment_image( $thumbnail_id, array( $content_width, $content_width ) );
1223 $thumbnail_html = wp_get_attachment_image( $thumbnail_id, 'post-thumbnail' );
1224 if ( !empty( $thumbnail_html ) ) {
1225 $ajax_nonce = wp_create_nonce( "set_post_thumbnail-$post_ID" );
1226 $content = sprintf($set_thumbnail_link, $thumbnail_html);
1227 $content .= '<p class="hide-if-no-js"><a href="#" id="remove-post-thumbnail" onclick="WPRemoveThumbnail(\'' . $ajax_nonce . '\');return false;">' . esc_html__( 'Remove featured image' ) . '</a></p>';
1229 $content_width = $old_content_width;
1232 return apply_filters( 'admin_post_thumbnail_html', $content );
1236 * Check to see if the post is currently being edited by another user.
1240 * @param int $post_id ID of the post to check for editing
1241 * @return bool|int False: not locked or locked by current user. Int: user ID of user with lock.
1243 function wp_check_post_lock( $post_id ) {
1244 if ( !$post = get_post( $post_id ) )
1247 if ( !$lock = get_post_meta( $post->ID, '_edit_lock', true ) )
1250 $lock = explode( ':', $lock );
1252 $user = isset( $lock[1] ) ? $lock[1] : get_post_meta( $post->ID, '_edit_last', true );
1254 $time_window = apply_filters( 'wp_check_post_lock_window', AUTOSAVE_INTERVAL * 2 );
1256 if ( $time && $time > time() - $time_window && $user != get_current_user_id() )
1262 * Mark the post as currently being edited by the current user
1266 * @param int $post_id ID of the post to being edited
1267 * @return bool Returns false if the post doesn't exist of there is no current user
1269 function wp_set_post_lock( $post_id ) {
1270 if ( !$post = get_post( $post_id ) )
1272 if ( 0 == ($user_id = get_current_user_id()) )
1276 $lock = "$now:$user_id";
1278 update_post_meta( $post->ID, '_edit_lock', $lock );
1282 * Outputs the notice message to say that someone else is editing this post at the moment.
1287 function _admin_notice_post_locked() {
1290 $lock = explode( ':', get_post_meta( $post->ID, '_edit_lock', true ) );
1291 $user = isset( $lock[1] ) ? $lock[1] : get_post_meta( $post->ID, '_edit_last', true );
1292 $last_user = get_userdata( $user );
1293 $last_user_name = $last_user ? $last_user->display_name : __('Somebody');
1295 switch ($post->post_type) {
1297 $message = __( 'Warning: %s is currently editing this post' );
1300 $message = __( 'Warning: %s is currently editing this page' );
1303 $message = __( 'Warning: %s is currently editing this.' );
1306 $message = sprintf( $message, esc_html( $last_user_name ) );
1307 echo "<div class='error'><p>$message</p></div>";
1311 * Creates autosave data for the specified post from $_POST data.
1313 * @package WordPress
1314 * @subpackage Post_Revisions
1317 * @uses _wp_translate_postdata()
1318 * @uses _wp_post_revision_fields()
1322 function wp_create_post_autosave( $post_id ) {
1323 $translated = _wp_translate_postdata( true );
1324 if ( is_wp_error( $translated ) )
1327 // Only store one autosave. If there is already an autosave, overwrite it.
1328 if ( $old_autosave = wp_get_post_autosave( $post_id ) ) {
1329 $new_autosave = _wp_post_revision_fields( $_POST, true );
1330 $new_autosave['ID'] = $old_autosave->ID;
1331 $new_autosave['post_author'] = get_current_user_id();
1332 return wp_update_post( $new_autosave );
1335 // _wp_put_post_revision() expects unescaped.
1336 $_POST = stripslashes_deep($_POST);
1338 // Otherwise create the new autosave as a special post revision
1339 return _wp_put_post_revision( $_POST, true );
1343 * Save draft or manually autosave for showing preview.
1345 * @package WordPress
1348 * @uses wp_write_post()
1351 * @uses current_user_can()
1352 * @uses wp_create_post_autosave()
1354 * @return str URL to redirect to show the preview
1356 function post_preview() {
1358 $post_ID = (int) $_POST['post_ID'];
1359 $status = get_post_status( $post_ID );
1360 if ( 'auto-draft' == $status )
1361 wp_die( __('Preview not available. Please save as a draft first.') );
1363 if ( isset($_POST['catslist']) )
1364 $_POST['post_category'] = explode(",", $_POST['catslist']);
1366 if ( isset($_POST['tags_input']) )
1367 $_POST['tags_input'] = explode(",", $_POST['tags_input']);
1369 if ( $_POST['post_type'] == 'page' || empty($_POST['post_category']) )
1370 unset($_POST['post_category']);
1372 $_POST['ID'] = $post_ID;
1373 $post = get_post($post_ID);
1375 if ( 'page' == $post->post_type ) {
1376 if ( !current_user_can('edit_page', $post_ID) )
1377 wp_die(__('You are not allowed to edit this page.'));
1379 if ( !current_user_can('edit_post', $post_ID) )
1380 wp_die(__('You are not allowed to edit this post.'));
1383 if ( 'draft' == $post->post_status ) {
1385 } else { // Non drafts are not overwritten. The autosave is stored in a special post revision.
1386 $id = wp_create_post_autosave( $post->ID );
1387 if ( ! is_wp_error($id) )
1391 if ( is_wp_error($id) )
1392 wp_die( $id->get_error_message() );
1394 if ( $_POST['post_status'] == 'draft' ) {
1395 $url = add_query_arg( 'preview', 'true', get_permalink($id) );
1397 $nonce = wp_create_nonce('post_preview_' . $id);
1398 $url = add_query_arg( array( 'preview' => 'true', 'preview_id' => $id, 'preview_nonce' => $nonce ), get_permalink($id) );
1405 * Adds the TinyMCE editor used on the Write and Edit screens.
1407 * @package WordPress
1410 * TinyMCE is loaded separately from other Javascript by using wp-tinymce.php. It outputs concatenated
1411 * and optionaly pre-compressed version of the core and all default plugins. Additional plugins are loaded
1412 * directly by TinyMCE using non-blocking method. Custom plugins can be refreshed by adding a query string
1413 * to the URL when queueing them with the mce_external_plugins filter.
1415 * @param bool $teeny optional Output a trimmed down version used in Press This.
1416 * @param mixed $settings optional An array that can add to or overwrite the default TinyMCE settings.
1418 function wp_tiny_mce( $teeny = false, $settings = false ) {
1419 global $concatenate_scripts, $compress_scripts, $tinymce_version, $editor_styles;
1421 if ( ! user_can_richedit() )
1424 $baseurl = includes_url('js/tinymce');
1426 $mce_locale = ( '' == get_locale() ) ? 'en' : strtolower( substr(get_locale(), 0, 2) ); // only ISO 639-1
1429 The following filter allows localization scripts to change the languages displayed in the spellchecker's drop-down menu.
1430 By default it uses Google's spellchecker API, but can be configured to use PSpell/ASpell if installed on the server.
1431 The + sign marks the default language. More information:
1432 http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker
1434 $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');
1437 $plugins = apply_filters( 'teeny_mce_plugins', array('inlinepopups', 'fullscreen', 'wordpress', 'wplink', 'wpdialogs') );
1440 $plugins = array( 'inlinepopups', 'spellchecker', 'paste', 'wordpress', 'fullscreen', 'wpeditimage', 'wpgallery', 'tabfocus', 'wplink', 'wpdialogs' );
1443 The following filter takes an associative array of external plugins for TinyMCE in the form 'plugin_name' => 'url'.
1444 It adds the plugin's name to TinyMCE's plugins init and the call to PluginManager to load the plugin.
1445 The url should be absolute and should include the js file name to be loaded. Example:
1446 array( 'myplugin' => 'http://my-site.com/wp-content/plugins/myfolder/mce_plugin.js' )
1447 If the plugin uses a button, it should be added with one of the "$mce_buttons" filters.
1449 $mce_external_plugins = apply_filters('mce_external_plugins', array());
1452 if ( ! empty($mce_external_plugins) ) {
1455 The following filter loads external language files for TinyMCE plugins.
1456 It takes an associative array 'plugin_name' => 'path', where path is the
1457 include path to the file. The language file should follow the same format as
1458 /tinymce/langs/wp-langs.php and should define a variable $strings that
1459 holds all translated strings.
1460 When this filter is not used, the function will try to load {mce_locale}.js.
1461 If that is not found, en.js will be tried next.
1463 $mce_external_languages = apply_filters('mce_external_languages', array());
1465 $loaded_langs = array();
1468 if ( ! empty($mce_external_languages) ) {
1469 foreach ( $mce_external_languages as $name => $path ) {
1470 if ( @is_file($path) && @is_readable($path) ) {
1471 include_once($path);
1472 $ext_plugins .= $strings . "\n";
1473 $loaded_langs[] = $name;
1478 foreach ( $mce_external_plugins as $name => $url ) {
1480 if ( is_ssl() ) $url = str_replace('http://', 'https://', $url);
1482 $plugins[] = '-' . $name;
1484 $plugurl = dirname($url);
1485 $strings = $str1 = $str2 = '';
1486 if ( ! in_array($name, $loaded_langs) ) {
1487 $path = str_replace( WP_PLUGIN_URL, '', $plugurl );
1488 $path = WP_PLUGIN_DIR . $path . '/langs/';
1490 if ( function_exists('realpath') )
1491 $path = trailingslashit( realpath($path) );
1493 if ( @is_file($path . $mce_locale . '.js') )
1494 $strings .= @file_get_contents($path . $mce_locale . '.js') . "\n";
1496 if ( @is_file($path . $mce_locale . '_dlg.js') )
1497 $strings .= @file_get_contents($path . $mce_locale . '_dlg.js') . "\n";
1499 if ( 'en' != $mce_locale && empty($strings) ) {
1500 if ( @is_file($path . 'en.js') ) {
1501 $str1 = @file_get_contents($path . 'en.js');
1502 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str1, 1 ) . "\n";
1505 if ( @is_file($path . 'en_dlg.js') ) {
1506 $str2 = @file_get_contents($path . 'en_dlg.js');
1507 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str2, 1 ) . "\n";
1511 if ( ! empty($strings) )
1512 $ext_plugins .= "\n" . $strings . "\n";
1515 $ext_plugins .= 'tinyMCEPreInit.load_ext("' . $plugurl . '", "' . $mce_locale . '");' . "\n";
1516 $ext_plugins .= 'tinymce.PluginManager.load("' . $name . '", "' . $url . '");' . "\n";
1522 $mce_buttons = apply_filters( 'teeny_mce_buttons', array('bold, italic, underline, blockquote, separator, strikethrough, bullist, numlist,justifyleft, justifycenter, justifyright, undo, redo, link, unlink, fullscreen') );
1523 $mce_buttons = implode($mce_buttons, ',');
1524 $mce_buttons_2 = $mce_buttons_3 = $mce_buttons_4 = '';
1526 $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', '|', 'bullist', 'numlist', 'blockquote', '|', 'justifyleft', 'justifycenter', 'justifyright', '|', 'link', 'unlink', 'wp_more', '|', 'spellchecker', 'fullscreen', 'wp_adv' ));
1527 $mce_buttons = implode($mce_buttons, ',');
1529 $mce_buttons_2 = array( 'formatselect', 'underline', 'justifyfull', 'forecolor', '|', 'pastetext', 'pasteword', 'removeformat', '|', 'charmap', '|', 'outdent', 'indent', '|', 'undo', 'redo', 'wp_help' );
1530 $mce_buttons_2 = apply_filters('mce_buttons_2', $mce_buttons_2);
1531 $mce_buttons_2 = implode($mce_buttons_2, ',');
1533 $mce_buttons_3 = apply_filters('mce_buttons_3', array());
1534 $mce_buttons_3 = implode($mce_buttons_3, ',');
1536 $mce_buttons_4 = apply_filters('mce_buttons_4', array());
1537 $mce_buttons_4 = implode($mce_buttons_4, ',');
1539 $no_captions = (bool) apply_filters( 'disable_captions', '' );
1541 // TinyMCE init settings
1542 $initArray = array (
1543 'mode' => 'specific_textareas',
1544 'editor_selector' => 'theEditor',
1546 'theme' => 'advanced',
1547 'skin' => 'wp_theme',
1548 'theme_advanced_buttons1' => $mce_buttons,
1549 'theme_advanced_buttons2' => $mce_buttons_2,
1550 'theme_advanced_buttons3' => $mce_buttons_3,
1551 'theme_advanced_buttons4' => $mce_buttons_4,
1552 'language' => $mce_locale,
1553 'spellchecker_languages' => $mce_spellchecker_languages,
1554 'theme_advanced_toolbar_location' => 'top',
1555 'theme_advanced_toolbar_align' => 'left',
1556 'theme_advanced_statusbar_location' => 'bottom',
1557 'theme_advanced_resizing' => true,
1558 'theme_advanced_resize_horizontal' => false,
1559 'dialog_type' => 'modal',
1562 {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'left'}},
1563 {selector : 'img,table', classes : 'alignleft'}
1566 {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'center'}},
1567 {selector : 'img,table', classes : 'aligncenter'}
1570 {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'right'}},
1571 {selector : 'img,table', classes : 'alignright'}
1573 strikethrough : {inline : 'del'}
1575 'relative_urls' => false,
1576 'remove_script_host' => false,
1577 'convert_urls' => false,
1578 'apply_source_formatting' => false,
1579 'remove_linebreaks' => true,
1580 'gecko_spellcheck' => true,
1581 'entities' => '38,amp,60,lt,62,gt',
1582 'accessibility_focus' => true,
1583 'tabfocus_elements' => 'major-publishing-actions',
1584 'media_strict' => false,
1585 'paste_remove_styles' => true,
1586 'paste_remove_spans' => true,
1587 'paste_strip_class_attributes' => 'all',
1588 'paste_text_use_dialog' => true,
1589 'wpeditimage_disable_captions' => $no_captions,
1590 'plugins' => implode( ',', $plugins ),
1593 if ( ! empty( $editor_styles ) && is_array( $editor_styles ) ) {
1595 $style_uri = get_stylesheet_directory_uri();
1596 if ( ! is_child_theme() ) {
1597 foreach ( $editor_styles as $file )
1598 $mce_css[] = "$style_uri/$file";
1600 $style_dir = get_stylesheet_directory();
1601 $template_uri = get_template_directory_uri();
1602 $template_dir = get_template_directory();
1603 foreach ( $editor_styles as $file ) {
1604 if ( file_exists( "$template_dir/$file" ) )
1605 $mce_css[] = "$template_uri/$file";
1606 if ( file_exists( "$style_dir/$file" ) )
1607 $mce_css[] = "$style_uri/$file";
1610 $mce_css = implode( ',', $mce_css );
1615 $mce_css = trim( apply_filters( 'mce_css', $mce_css ), ' ,' );
1617 if ( ! empty($mce_css) )
1618 $initArray['content_css'] = $mce_css;
1620 if ( is_array($settings) )
1621 $initArray = array_merge($initArray, $settings);
1623 // For people who really REALLY know what they're doing with TinyMCE
1624 // You can modify initArray to add, remove, change elements of the config before tinyMCE.init
1625 // Setting "valid_elements", "invalid_elements" and "extended_valid_elements" can be done through "tiny_mce_before_init".
1626 // Best is to use the default cleanup by not specifying valid_elements, as TinyMCE contains full set of XHTML 1.0.
1628 $initArray = apply_filters('teeny_mce_before_init', $initArray);
1630 $initArray = apply_filters('tiny_mce_before_init', $initArray);
1633 if ( empty($initArray['theme_advanced_buttons3']) && !empty($initArray['theme_advanced_buttons4']) ) {
1634 $initArray['theme_advanced_buttons3'] = $initArray['theme_advanced_buttons4'];
1635 $initArray['theme_advanced_buttons4'] = '';
1638 if ( ! isset($concatenate_scripts) )
1639 script_concat_settings();
1641 $language = $initArray['language'];
1643 $compressed = $compress_scripts && $concatenate_scripts && isset($_SERVER['HTTP_ACCEPT_ENCODING'])
1644 && false !== strpos( strtolower($_SERVER['HTTP_ACCEPT_ENCODING']), 'gzip');
1649 * The tiny_mce_version filter is not needed since external plugins are loaded directly by TinyMCE.
1650 * These plugins can be refreshed by appending query string to the URL passed to mce_external_plugins filter.
1651 * 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).
1653 $version = apply_filters('tiny_mce_version', '');
1654 $version = 'ver=' . $tinymce_version . $version;
1656 if ( 'en' != $language )
1657 include_once(ABSPATH . WPINC . '/js/tinymce/langs/wp-langs.php');
1660 foreach ( $initArray as $k => $v ) {
1661 if ( is_bool($v) ) {
1662 $val = $v ? 'true' : 'false';
1663 $mce_options .= $k . ':' . $val . ', ';
1665 } elseif ( !empty($v) && is_string($v) && ( '{' == $v{0} || '[' == $v{0} ) ) {
1666 $mce_options .= $k . ':' . $v . ', ';
1670 $mce_options .= $k . ':"' . $v . '", ';
1673 $mce_options = rtrim( trim($mce_options), '\n\r,' ); ?>
1675 <script type="text/javascript">
1678 base : "<?php echo $baseurl; ?>",
1680 query : "<?php echo $version; ?>",
1681 mceInit : {<?php echo $mce_options; ?>},
1682 load_ext : function(url,lang){var sl=tinymce.ScriptLoader;sl.markDone(url+'/langs/'+lang+'.js');sl.markDone(url+'/langs/'+lang+'_dlg.js');}
1689 echo "<script type='text/javascript' src='$baseurl/wp-tinymce.php?c=1&$version'></script>\n";
1691 echo "<script type='text/javascript' src='$baseurl/tiny_mce.js?$version'></script>\n";
1693 if ( 'en' != $language && isset($lang) )
1694 echo "<script type='text/javascript'>\n$lang\n</script>\n";
1696 echo "<script type='text/javascript' src='$baseurl/langs/wp-langs-en.js?$version'></script>\n";
1699 <script type="text/javascript">
1703 echo "$ext_plugins\n";
1705 if ( ! $compressed ) {
1707 (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');}});})();
1709 tinyMCE.init(tinyMCEPreInit.mceInit);
1714 // Load additional inline scripts based on active plugins.
1715 if ( in_array( 'wpdialogs', $plugins ) ) {
1716 wp_print_scripts( array( 'wpdialogs-popup' ) );
1717 wp_print_styles('wp-jquery-ui-dialog');
1719 if ( in_array( 'wplink', $plugins ) ) {
1720 require_once ABSPATH . 'wp-admin/includes/internal-linking.php';
1721 add_action('tiny_mce_preload_dialogs', 'wp_link_dialog');
1722 wp_print_scripts('wplink');
1723 wp_print_styles('wplink');
1726 function wp_tiny_mce_preload_dialogs() { ?>
1727 <div id="preloaded-dialogs" style="display:none;">
1728 <?php do_action('tiny_mce_preload_dialogs'); ?>