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 ( !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 $post_ID = (int) $post_data['post_ID'];
140 $ptype = get_post_type_object($post_data['post_type']);
141 if ( !current_user_can( $ptype->cap->edit_post, $post_ID ) ) {
142 if ( 'page' == $post_data['post_type'] )
143 wp_die( __('You are not allowed to edit this page.' ));
145 wp_die( __('You are not allowed to edit this post.' ));
148 // Autosave shouldn't save too soon after a real save
149 if ( 'autosave' == $post_data['action'] ) {
150 $post =& get_post( $post_ID );
152 $then = strtotime($post->post_date_gmt . ' +0000');
153 $delta = AUTOSAVE_INTERVAL / 2;
154 if ( ($now - $then) < $delta )
158 $post_data = _wp_translate_postdata( true, $post_data );
159 if ( 'autosave' != $post_data['action'] && 'auto-draft' == $post_data['post_status'] )
160 $post_data['post_status'] = 'draft';
161 if ( is_wp_error($post_data) )
162 wp_die( $post_data->get_error_message() );
164 if ( isset($post_data['visibility']) ) {
165 switch ( $post_data['visibility'] ) {
167 $post_data['post_password'] = '';
170 unset( $post_data['sticky'] );
173 $post_data['post_status'] = 'private';
174 $post_data['post_password'] = '';
175 unset( $post_data['sticky'] );
181 if ( isset($post_data['meta']) && $post_data['meta'] ) {
182 foreach ( $post_data['meta'] as $key => $value )
183 update_meta( $key, $value['key'], $value['value'] );
186 if ( isset($post_data['deletemeta']) && $post_data['deletemeta'] ) {
187 foreach ( $post_data['deletemeta'] as $key => $value )
191 add_meta( $post_ID );
193 update_post_meta( $post_ID, '_edit_last', $GLOBALS['current_user']->ID );
195 wp_update_post( $post_data );
197 // Reunite any orphaned attachments with their parent
198 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
199 $draft_ids = array();
200 if ( $draft_temp_id = (int) array_search( $post_ID, $draft_ids ) )
201 _relocate_children( $draft_temp_id, $post_ID );
203 // Now that we have an ID we can fix any attachment anchor hrefs
204 _fix_attachment_links( $post_ID );
206 wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
208 if ( current_user_can( 'edit_others_posts' ) ) {
209 if ( !empty($post_data['sticky']) )
210 stick_post($post_ID);
212 unstick_post($post_ID);
219 * Process the post data for the bulk editing of posts.
221 * Updates all bulk edited posts/pages, adding (but not removing) tags and
222 * categories. Skips pages when they would be their own parent or child.
226 * @param array $post_data Optional, the array of post data to process if not provided will use $_POST superglobal.
229 function bulk_edit_posts( $post_data = null ) {
232 if ( empty($post_data) )
233 $post_data = &$_POST;
235 if ( isset($post_data['post_type']) )
236 $ptype = get_post_type_object($post_data['post_type']);
238 $ptype = get_post_type_object('post');
240 if ( !current_user_can( $ptype->cap->edit_posts ) ) {
241 if ( 'page' == $ptype->name )
242 wp_die( __('You are not allowed to edit pages.'));
244 wp_die( __('You are not allowed to edit posts.'));
247 if ( -1 == $post_data['_status'] ) {
248 $post_data['post_status'] = null;
249 unset($post_data['post_status']);
251 $post_data['post_status'] = $post_data['_status'];
253 unset($post_data['_status']);
255 $post_IDs = array_map( 'intval', (array) $post_data['post'] );
257 $reset = array( 'post_author', 'post_status', 'post_password', 'post_parent', 'page_template', 'comment_status', 'ping_status', 'keep_private', 'tax_input', 'post_category', 'sticky' );
258 foreach ( $reset as $field ) {
259 if ( isset($post_data[$field]) && ( '' == $post_data[$field] || -1 == $post_data[$field] ) )
260 unset($post_data[$field]);
263 if ( isset($post_data['post_category']) ) {
264 if ( is_array($post_data['post_category']) && ! empty($post_data['post_category']) )
265 $new_cats = array_map( 'absint', $post_data['post_category'] );
267 unset($post_data['post_category']);
270 $tax_input = array();
271 if ( isset($post_data['tax_input'])) {
272 foreach ( $post_data['tax_input'] as $tax_name => $terms ) {
275 if ( is_taxonomy_hierarchical( $tax_name ) )
276 $tax_input[$tax_name] = array_map( 'absint', $terms );
278 $tax_input[$tax_name] = preg_replace( '/\s*,\s*/', ',', rtrim( trim($terms), ' ,' ) );
279 $tax_input[$tax_name] = explode(',', $tax_input[$tax_name]);
284 if ( isset($post_data['post_parent']) && ($parent = (int) $post_data['post_parent']) ) {
285 $pages = $wpdb->get_results("SELECT ID, post_parent FROM $wpdb->posts WHERE post_type = 'page'");
288 for ( $i = 0; $i < 50 && $parent > 0; $i++ ) {
289 $children[] = $parent;
291 foreach ( $pages as $page ) {
292 if ( $page->ID == $parent ) {
293 $parent = $page->post_parent;
300 $updated = $skipped = $locked = array();
301 foreach ( $post_IDs as $post_ID ) {
302 $post_type_object = get_post_type_object( get_post_type( $post_ID ) );
304 if ( !isset( $post_type_object ) || ( isset($children) && in_array($post_ID, $children) ) || !current_user_can( $post_type_object->cap->edit_post, $post_ID ) ) {
305 $skipped[] = $post_ID;
309 if ( wp_check_post_lock( $post_ID ) ) {
310 $locked[] = $post_ID;
314 $tax_names = get_object_taxonomies( get_post($post_ID) );
315 foreach ( $tax_names as $tax_name ) {
316 $taxonomy_obj = get_taxonomy($tax_name);
317 if ( isset( $tax_input[$tax_name]) && current_user_can( $taxonomy_obj->cap->assign_terms ) )
318 $new_terms = $tax_input[$tax_name];
320 $new_terms = array();
322 if ( $taxonomy_obj->hierarchical )
323 $current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array('fields' => 'ids') );
325 $current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array('fields' => 'names') );
327 $post_data['tax_input'][$tax_name] = array_merge( $current_terms, $new_terms );
330 if ( isset($new_cats) && in_array( 'category', $tax_names ) ) {
331 $cats = (array) wp_get_post_categories($post_ID);
332 $post_data['post_category'] = array_unique( array_merge($cats, $new_cats) );
333 unset( $post_data['tax_input']['category'] );
336 $post_data['ID'] = $post_ID;
337 $updated[] = wp_update_post( $post_data );
339 if ( isset( $post_data['sticky'] ) && current_user_can( 'edit_others_posts' ) ) {
340 if ( 'sticky' == $post_data['sticky'] )
341 stick_post( $post_ID );
343 unstick_post( $post_ID );
348 return array( 'updated' => $updated, 'skipped' => $skipped, 'locked' => $locked );
352 * Default post information to use when populating the "Write Post" form.
356 *@param string A post type string, defaults to 'post'.
357 * @return object stdClass object containing all the default post data as attributes
359 function get_default_post_to_edit( $post_type = 'post', $create_in_db = false ) {
363 if ( !empty( $_REQUEST['post_title'] ) )
364 $post_title = esc_html( stripslashes( $_REQUEST['post_title'] ));
367 if ( !empty( $_REQUEST['content'] ) )
368 $post_content = esc_html( stripslashes( $_REQUEST['content'] ));
371 if ( !empty( $_REQUEST['excerpt'] ) )
372 $post_excerpt = esc_html( stripslashes( $_REQUEST['excerpt'] ));
374 if ( $create_in_db ) {
375 // Cleanup old auto-drafts more than 7 days old
376 $old_posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_status = 'auto-draft' AND DATE_SUB( NOW(), INTERVAL 7 DAY ) > post_date" );
377 foreach ( (array) $old_posts as $delete )
378 wp_delete_post( $delete, true ); // Force delete
379 $post_id = wp_insert_post( array( 'post_title' => __( 'Auto Draft' ), 'post_type' => $post_type, 'post_status' => 'auto-draft' ) );
380 $post = get_post( $post_id );
383 $post->post_author = '';
384 $post->post_date = '';
385 $post->post_date_gmt = '';
386 $post->post_password = '';
387 $post->post_type = $post_type;
388 $post->post_status = 'draft';
391 $post->comment_status = get_option( 'default_comment_status' );
392 $post->ping_status = get_option( 'default_ping_status' );
393 $post->post_pingback = get_option( 'default_pingback_flag' );
394 $post->post_category = get_option( 'default_category' );
395 $post->page_template = 'default';
396 $post->post_parent = 0;
397 $post->menu_order = 0;
400 $post->post_content = apply_filters( 'default_content', $post_content, $post );
401 $post->post_title = apply_filters( 'default_title', $post_title, $post );
402 $post->post_excerpt = apply_filters( 'default_excerpt', $post_excerpt, $post );
403 $post->post_name = '';
409 * Get the default page information to use.
413 * @return object stdClass object containing all the default post data as attributes
415 function get_default_page_to_edit() {
416 $page = get_default_post_to_edit();
417 $page->post_type = 'page';
422 * Get an existing post and format it for editing.
426 * @param unknown_type $id
429 function get_post_to_edit( $id ) {
431 $post = get_post( $id, OBJECT, 'edit' );
433 if ( $post->post_type == 'page' )
434 $post->page_template = get_post_meta( $id, '_wp_page_template', true );
440 * Determine if a post exists based on title, content, and date
444 * @param string $title Post title
445 * @param string $content Optional post content
446 * @param string $date Optional post date
447 * @return int Post ID if post exists, 0 otherwise.
449 function post_exists($title, $content = '', $date = '') {
452 $post_title = stripslashes( sanitize_post_field( 'post_title', $title, 0, 'db' ) );
453 $post_content = stripslashes( sanitize_post_field( 'post_content', $content, 0, 'db' ) );
454 $post_date = stripslashes( sanitize_post_field( 'post_date', $date, 0, 'db' ) );
456 $query = "SELECT ID FROM $wpdb->posts WHERE 1=1";
459 if ( !empty ( $date ) ) {
460 $query .= ' AND post_date = %s';
461 $args[] = $post_date;
464 if ( !empty ( $title ) ) {
465 $query .= ' AND post_title = %s';
466 $args[] = $post_title;
469 if ( !empty ( $content ) ) {
470 $query .= 'AND post_content = %s';
471 $args[] = $post_content;
474 if ( !empty ( $args ) )
475 return $wpdb->get_var( $wpdb->prepare($query, $args) );
481 * Creates a new post from the "Write Post" form using $_POST information.
487 function wp_write_post() {
491 if ( isset($_POST['post_type']) )
492 $ptype = get_post_type_object($_POST['post_type']);
494 $ptype = get_post_type_object('post');
496 if ( !current_user_can( $ptype->cap->edit_posts ) ) {
497 if ( 'page' == $ptype->name )
498 return new WP_Error( 'edit_pages', __( 'You are not allowed to create pages on this site.' ) );
500 return new WP_Error( 'edit_posts', __( 'You are not allowed to create posts or drafts on this site.' ) );
503 // Check for autosave collisions
504 // Does this need to be updated? ~ Mark
506 if ( isset($_POST['temp_ID']) ) {
507 $temp_id = (int) $_POST['temp_ID'];
508 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
509 $draft_ids = array();
510 foreach ( $draft_ids as $temp => $real )
511 if ( time() + $temp > 86400 ) // 1 day: $temp is equal to -1 * time( then )
512 unset($draft_ids[$temp]);
514 if ( isset($draft_ids[$temp_id]) ) { // Edit, don't write
515 $_POST['post_ID'] = $draft_ids[$temp_id];
516 unset($_POST['temp_ID']);
517 update_user_option( $user_ID, 'autosave_draft_ids', $draft_ids );
522 $translated = _wp_translate_postdata( false );
523 if ( is_wp_error($translated) )
526 if ( isset($_POST['visibility']) ) {
527 switch ( $_POST['visibility'] ) {
529 $_POST['post_password'] = '';
532 unset( $_POST['sticky'] );
535 $_POST['post_status'] = 'private';
536 $_POST['post_password'] = '';
537 unset( $_POST['sticky'] );
543 $post_ID = wp_insert_post( $_POST );
544 if ( is_wp_error( $post_ID ) )
547 if ( empty($post_ID) )
550 add_meta( $post_ID );
552 add_post_meta( $post_ID, '_edit_last', $GLOBALS['current_user']->ID );
554 // Reunite any orphaned attachments with their parent
555 // Does this need to be udpated? ~ Mark
556 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
557 $draft_ids = array();
558 if ( $draft_temp_id = (int) array_search( $post_ID, $draft_ids ) )
559 _relocate_children( $draft_temp_id, $post_ID );
560 if ( $temp_id && $temp_id != $draft_temp_id )
561 _relocate_children( $temp_id, $post_ID );
563 // Update autosave collision detection
565 $draft_ids[$temp_id] = $post_ID;
566 update_user_option( $user_ID, 'autosave_draft_ids', $draft_ids );
569 // Now that we have an ID we can fix any attachment anchor hrefs
570 _fix_attachment_links( $post_ID );
572 wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
578 * Calls wp_write_post() and handles the errors.
584 function write_post() {
585 $result = wp_write_post();
586 if ( is_wp_error( $result ) )
587 wp_die( $result->get_error_message() );
597 * {@internal Missing Short Description}}
601 * @param unknown_type $post_ID
604 function add_meta( $post_ID ) {
606 $post_ID = (int) $post_ID;
608 $protected = array( '_wp_attached_file', '_wp_attachment_metadata', '_wp_old_slug', '_wp_page_template' );
610 $metakeyselect = isset($_POST['metakeyselect']) ? stripslashes( trim( $_POST['metakeyselect'] ) ) : '';
611 $metakeyinput = isset($_POST['metakeyinput']) ? stripslashes( trim( $_POST['metakeyinput'] ) ) : '';
612 $metavalue = isset($_POST['metavalue']) ? maybe_serialize( stripslashes_deep( $_POST['metavalue'] ) ) : '';
613 if ( is_string($metavalue) )
614 $metavalue = trim( $metavalue );
616 if ( ('0' === $metavalue || !empty ( $metavalue ) ) && ((('#NONE#' != $metakeyselect) && !empty ( $metakeyselect) ) || !empty ( $metakeyinput) ) ) {
617 // We have a key/value pair. If both the select and the
618 // input for the key have data, the input takes precedence:
620 if ('#NONE#' != $metakeyselect)
621 $metakey = $metakeyselect;
624 $metakey = $metakeyinput; // default
626 if ( in_array($metakey, $protected) )
629 wp_cache_delete($post_ID, 'post_meta');
630 $wpdb->insert( $wpdb->postmeta, array( 'post_id' => $post_ID, 'meta_key' => $metakey, 'meta_value' => $metavalue ) );
631 do_action( 'added_postmeta', $wpdb->insert_id, $post_ID, $metakey, $metavalue );
633 return $wpdb->insert_id;
639 * {@internal Missing Short Description}}
643 * @param unknown_type $mid
646 function delete_meta( $mid ) {
650 $post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
652 do_action( 'delete_postmeta', $mid );
653 wp_cache_delete($post_id, 'post_meta');
654 $rval = $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
655 do_action( 'deleted_postmeta', $mid );
661 * Get a list of previously defined keys.
667 function get_meta_keys() {
670 $keys = $wpdb->get_col( "
674 ORDER BY meta_key" );
680 * {@internal Missing Short Description}}
684 * @param unknown_type $mid
687 function get_post_meta_by_id( $mid ) {
691 $meta = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
694 if ( is_serialized_string( $meta->meta_value ) )
695 $meta->meta_value = maybe_unserialize( $meta->meta_value );
700 * {@internal Missing Short Description}}
702 * Some postmeta stuff.
706 * @param unknown_type $postid
709 function has_meta( $postid ) {
712 return $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value, meta_id, post_id
713 FROM $wpdb->postmeta WHERE post_id = %d
714 ORDER BY meta_key,meta_id", $postid), ARRAY_A );
719 * {@internal Missing Short Description}}
723 * @param unknown_type $meta_id
724 * @param unknown_type $meta_key Expect Slashed
725 * @param unknown_type $meta_value Expect Slashed
728 function update_meta( $meta_id, $meta_key, $meta_value ) {
731 $protected = array( '_wp_attached_file', '_wp_attachment_metadata', '_wp_old_slug', '_wp_page_template' );
733 $meta_key = stripslashes($meta_key);
735 if ( in_array($meta_key, $protected) )
738 if ( '' === trim( $meta_value ) )
741 $post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_id = %d", $meta_id) );
743 $meta_value = maybe_serialize( stripslashes_deep( $meta_value ) );
744 $meta_id = (int) $meta_id;
746 $data = compact( 'meta_key', 'meta_value' );
747 $where = compact( 'meta_id' );
749 do_action( 'update_postmeta', $meta_id, $post_id, $meta_key, $meta_value );
750 $rval = $wpdb->update( $wpdb->postmeta, $data, $where );
751 wp_cache_delete($post_id, 'post_meta');
752 do_action( 'updated_postmeta', $meta_id, $post_id, $meta_key, $meta_value );
762 * Replace hrefs of attachment anchors with up-to-date permalinks.
767 * @param unknown_type $post_ID
770 function _fix_attachment_links( $post_ID ) {
771 global $_fix_attachment_link_id;
773 $post = & get_post( $post_ID, ARRAY_A );
775 $search = "#<a[^>]+rel=('|\")[^'\"]*attachment[^>]*>#ie";
777 // See if we have any rel="attachment" links
778 if ( 0 == preg_match_all( $search, $post['post_content'], $anchor_matches, PREG_PATTERN_ORDER ) )
782 $search = "#[\s]+rel=(\"|')(.*?)wp-att-(\d+)\\1#i";
783 foreach ( $anchor_matches[0] as $anchor ) {
784 if ( 0 == preg_match( $search, $anchor, $id_matches ) )
787 $id = (int) $id_matches[3];
789 // While we have the attachment ID, let's adopt any orphans.
790 $attachment = & get_post( $id, ARRAY_A );
791 if ( ! empty( $attachment) && ! is_object( get_post( $attachment['post_parent'] ) ) ) {
792 $attachment['post_parent'] = $post_ID;
793 // Escape data pulled from DB.
794 $attachment = add_magic_quotes( $attachment );
795 wp_update_post( $attachment );
798 $post_search[$i] = $anchor;
799 $_fix_attachment_link_id = $id;
800 $post_replace[$i] = preg_replace_callback( "#href=(\"|')[^'\"]*\\1#", '_fix_attachment_links_replace_cb', $anchor );
804 $post['post_content'] = str_replace( $post_search, $post_replace, $post['post_content'] );
806 // Escape data pulled from DB.
807 $post = add_magic_quotes( $post);
809 return wp_update_post( $post);
812 function _fix_attachment_links_replace_cb($match) {
813 global $_fix_attachment_link_id;
814 return stripslashes( 'href='.$match[1] ).get_attachment_link( $_fix_attachment_link_id ).stripslashes( $match[1] );
818 * Move child posts to a new parent.
823 * @param unknown_type $old_ID
824 * @param unknown_type $new_ID
827 function _relocate_children( $old_ID, $new_ID ) {
829 $old_ID = (int) $old_ID;
830 $new_ID = (int) $new_ID;
832 $children = $wpdb->get_col( $wpdb->prepare("
835 WHERE meta_key = '_wp_attachment_temp_parent'
836 AND meta_value = %d", $old_ID) );
838 foreach ( $children as $child_id ) {
839 $wpdb->update($wpdb->posts, array('post_parent' => $new_ID), array('ID' => $child_id) );
840 delete_post_meta($child_id, '_wp_attachment_temp_parent');
845 * Get all the possible statuses for a post_type
849 * @param string $type The post_type you want the statuses for
850 * @return array As array of all the statuses for the supplied post type
852 function get_available_post_statuses($type = 'post') {
853 $stati = wp_count_posts($type);
855 return array_keys(get_object_vars($stati));
859 * Run the wp query to fetch the posts for listing on the edit posts page
863 * @param array|bool $q Array of query variables to use to build the query or false to use $_GET superglobal.
866 function wp_edit_posts_query( $q = false ) {
869 $q['m'] = isset($q['m']) ? (int) $q['m'] : 0;
870 $q['cat'] = isset($q['cat']) ? (int) $q['cat'] : 0;
871 $post_stati = get_post_stati();
873 if ( isset($q['post_type']) && in_array( $q['post_type'], get_post_types() ) )
874 $post_type = $q['post_type'];
878 $avail_post_stati = get_available_post_statuses($post_type);
880 if ( isset($q['post_status']) && in_array( $q['post_status'], $post_stati ) ) {
881 $post_status = $q['post_status'];
885 if ( isset($q['post_status']) && 'pending' === $q['post_status'] ) {
887 $orderby = 'modified';
888 } elseif ( isset($q['post_status']) && 'draft' === $q['post_status'] ) {
890 $orderby = 'modified';
896 $per_page = 'edit_' . $post_type . '_per_page';
897 $posts_per_page = (int) get_user_option( $per_page );
898 if ( empty( $posts_per_page ) || $posts_per_page < 1 )
899 $posts_per_page = 20;
901 $posts_per_page = apply_filters( $per_page, $posts_per_page );
902 $posts_per_page = apply_filters( 'edit_posts_per_page', $posts_per_page, $post_type );
904 $query = compact('post_type', 'post_status', 'perm', 'order', 'orderby', 'posts_per_page');
906 // Hierarchical types require special args.
907 if ( is_post_type_hierarchical( $post_type ) ) {
908 $query['orderby'] = 'menu_order title';
909 $query['order'] = 'asc';
910 $query['posts_per_page'] = -1;
911 $query['posts_per_archive_page'] = -1;
916 return $avail_post_stati;
920 * Get default post mime types
926 function get_post_mime_types() {
927 $post_mime_types = array( // array( adj, noun )
928 'image' => array(__('Images'), __('Manage Images'), _n_noop('Image <span class="count">(%s)</span>', 'Images <span class="count">(%s)</span>')),
929 'audio' => array(__('Audio'), __('Manage Audio'), _n_noop('Audio <span class="count">(%s)</span>', 'Audio <span class="count">(%s)</span>')),
930 'video' => array(__('Video'), __('Manage Video'), _n_noop('Video <span class="count">(%s)</span>', 'Video <span class="count">(%s)</span>')),
933 return apply_filters('post_mime_types', $post_mime_types);
937 * {@internal Missing Short Description}}
941 * @param unknown_type $type
944 function get_available_post_mime_types($type = 'attachment') {
947 $types = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT post_mime_type FROM $wpdb->posts WHERE post_type = %s", $type));
952 * {@internal Missing Short Description}}
956 * @param unknown_type $q
959 function wp_edit_attachments_query( $q = false ) {
963 $q['m'] = isset( $q['m'] ) ? (int) $q['m'] : 0;
964 $q['cat'] = isset( $q['cat'] ) ? (int) $q['cat'] : 0;
965 $q['post_type'] = 'attachment';
966 $q['post_status'] = isset( $q['status'] ) && 'trash' == $q['status'] ? 'trash' : 'inherit';
967 $media_per_page = (int) get_user_option( 'upload_per_page' );
968 if ( empty( $media_per_page ) || $media_per_page < 1 )
969 $media_per_page = 20;
970 $q['posts_per_page'] = apply_filters( 'upload_per_page', $media_per_page );
972 $post_mime_types = get_post_mime_types();
973 $avail_post_mime_types = get_available_post_mime_types('attachment');
975 if ( isset($q['post_mime_type']) && !array_intersect( (array) $q['post_mime_type'], array_keys($post_mime_types) ) )
976 unset($q['post_mime_type']);
980 return array($post_mime_types, $avail_post_mime_types);
984 * {@internal Missing Short Description}}
986 * @uses get_user_option()
989 * @param unknown_type $id
990 * @param unknown_type $page
993 function postbox_classes( $id, $page ) {
994 if ( isset( $_GET['edit'] ) && $_GET['edit'] == $id )
997 if ( $closed = get_user_option('closedpostboxes_'.$page ) ) {
998 if ( !is_array( $closed ) ) {
1001 return in_array( $id, $closed )? 'closed' : '';
1008 * {@internal Missing Short Description}}
1012 * @param int|object $id Post ID or post object.
1013 * @param string $title (optional) Title
1014 * @param string $name (optional) Name
1015 * @return array With two entries of type string
1017 function get_sample_permalink($id, $title = null, $name = null) {
1018 $post = &get_post($id);
1020 return array('', '');
1022 $ptype = get_post_type_object($post->post_type);
1024 $original_status = $post->post_status;
1025 $original_date = $post->post_date;
1026 $original_name = $post->post_name;
1028 // Hack: get_permalink would return ugly permalink for
1029 // drafts, so we will fake, that our post is published
1030 if ( in_array($post->post_status, array('draft', 'pending')) ) {
1031 $post->post_status = 'publish';
1032 $post->post_name = sanitize_title($post->post_name ? $post->post_name : $post->post_title, $post->ID);
1035 // If the user wants to set a new name -- override the current one
1036 // Note: if empty name is supplied -- use the title instead, see #6072
1037 if ( !is_null($name) )
1038 $post->post_name = sanitize_title($name ? $name : $title, $post->ID);
1040 $post->post_name = wp_unique_post_slug($post->post_name, $post->ID, $post->post_status, $post->post_type, $post->post_parent);
1042 $post->filter = 'sample';
1044 $permalink = get_permalink($post, true);
1046 // Replace custom post_type Token with generic pagename token for ease of use.
1047 $permalink = str_replace("%$post->post_type%", '%pagename%', $permalink);
1049 // Handle page hierarchy
1050 if ( $ptype->hierarchical ) {
1051 $uri = get_page_uri($post);
1052 $uri = untrailingslashit($uri);
1053 $uri = strrev( stristr( strrev( $uri ), '/' ) );
1054 $uri = untrailingslashit($uri);
1057 $permalink = str_replace('%pagename%', "${uri}%pagename%", $permalink);
1060 $permalink = array($permalink, apply_filters('editable_slug', $post->post_name));
1061 $post->post_status = $original_status;
1062 $post->post_date = $original_date;
1063 $post->post_name = $original_name;
1064 unset($post->filter);
1070 * sample permalink html
1072 * intended to be used for the inplace editor of the permalink post slug on in the post (and page?) editor.
1076 * @param int|object $id Post ID or post object.
1077 * @param string $new_title (optional) New title
1078 * @param string $new_slug (optional) New slug
1079 * @return string intended to be used for the inplace editor of the permalink post slug on in the post (and page?) editor.
1081 function get_sample_permalink_html( $id, $new_title = null, $new_slug = null ) {
1083 $post = &get_post($id);
1085 list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug);
1087 if ( 'publish' == $post->post_status ) {
1088 $ptype = get_post_type_object($post->post_type);
1089 $view_post = $ptype->labels->view_item;
1090 $title = __('Click to edit this part of the permalink');
1092 $title = __('Temporary permalink. Click to edit this part.');
1095 if ( false === strpos($permalink, '%postname%') && false === strpos($permalink, '%pagename%') ) {
1096 $return = '<strong>' . __('Permalink:') . "</strong>\n" . '<span id="sample-permalink">' . $permalink . "</span>\n";
1097 if ( current_user_can( 'manage_options' ) && !( 'page' == get_option('show_on_front') && $id == get_option('page_on_front') ) )
1098 $return .= '<span id="change-permalinks"><a href="options-permalink.php" class="button" target="_blank">' . __('Change Permalinks') . "</a></span>\n";
1099 if ( isset($view_post) )
1100 $return .= "<span id='view-post-btn'><a href='$permalink' class='button' target='_blank'>$view_post</a></span>\n";
1102 $return = apply_filters('get_sample_permalink_html', $return, $id, $new_title, $new_slug);
1107 if ( function_exists('mb_strlen') ) {
1108 if ( mb_strlen($post_name) > 30 ) {
1109 $post_name_abridged = mb_substr($post_name, 0, 14). '…' . mb_substr($post_name, -14);
1111 $post_name_abridged = $post_name;
1114 if ( strlen($post_name) > 30 ) {
1115 $post_name_abridged = substr($post_name, 0, 14). '…' . substr($post_name, -14);
1117 $post_name_abridged = $post_name;
1121 $post_name_html = '<span id="editable-post-name" title="' . $title . '">' . $post_name_abridged . '</span>';
1122 $display_link = str_replace(array('%pagename%','%postname%'), $post_name_html, $permalink);
1123 $view_link = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
1124 $return = '<strong>' . __('Permalink:') . "</strong>\n";
1125 $return .= '<span id="sample-permalink">' . $display_link . "</span>\n";
1126 $return .= '‎'; // Fix bi-directional text display defect in RTL languages.
1127 $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";
1128 $return .= '<span id="editable-post-name-full">' . $post_name . "</span>\n";
1129 if ( isset($view_post) )
1130 $return .= "<span id='view-post-btn'><a href='$view_link' class='button' target='_blank'>$view_post</a></span>\n";
1132 $return = apply_filters('get_sample_permalink_html', $return, $id, $new_title, $new_slug);
1138 * Output HTML for the post thumbnail meta-box.
1142 * @param int $thumbnail_id ID of the attachment used for thumbnail
1143 * @return string html
1145 function _wp_post_thumbnail_html( $thumbnail_id = NULL ) {
1146 global $content_width, $_wp_additional_image_sizes, $post_ID;
1147 $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>';
1148 $content = sprintf($set_thumbnail_link, esc_html__( 'Set featured image' ));
1150 if ( $thumbnail_id && get_post( $thumbnail_id ) ) {
1151 $old_content_width = $content_width;
1152 $content_width = 266;
1153 if ( !isset( $_wp_additional_image_sizes['post-thumbnail'] ) )
1154 $thumbnail_html = wp_get_attachment_image( $thumbnail_id, array( $content_width, $content_width ) );
1156 $thumbnail_html = wp_get_attachment_image( $thumbnail_id, 'post-thumbnail' );
1157 if ( !empty( $thumbnail_html ) ) {
1158 $ajax_nonce = wp_create_nonce( "set_post_thumbnail-$post_ID" );
1159 $content = sprintf($set_thumbnail_link, $thumbnail_html);
1160 $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>';
1162 $content_width = $old_content_width;
1165 return apply_filters( 'admin_post_thumbnail_html', $content );
1169 * Check to see if the post is currently being edited by another user.
1173 * @param int $post_id ID of the post to check for editing
1174 * @return bool|int False: not locked or locked by current user. Int: user ID of user with lock.
1176 function wp_check_post_lock( $post_id ) {
1177 if ( !$post = get_post( $post_id ) )
1180 $lock = get_post_meta( $post->ID, '_edit_lock', true );
1181 $last = get_post_meta( $post->ID, '_edit_last', true );
1183 $time_window = apply_filters( 'wp_check_post_lock_window', AUTOSAVE_INTERVAL * 2 );
1185 if ( $lock && $lock > time() - $time_window && $last != get_current_user_id() )
1191 * Mark the post as currently being edited by the current user
1195 * @param int $post_id ID of the post to being edited
1196 * @return bool Returns false if the post doesn't exist of there is no current user
1198 function wp_set_post_lock( $post_id ) {
1199 if ( !$post = get_post( $post_id ) )
1201 if ( 0 == get_current_user_id() )
1206 update_post_meta( $post->ID, '_edit_lock', $now );
1210 * Outputs the notice message to say that someone else is editing this post at the moment.
1215 function _admin_notice_post_locked() {
1217 $last_user = get_userdata( get_post_meta( $post->ID, '_edit_last', true ) );
1218 $last_user_name = $last_user ? $last_user->display_name : __('Somebody');
1220 switch ($post->post_type) {
1222 $message = __( 'Warning: %s is currently editing this post' );
1225 $message = __( 'Warning: %s is currently editing this page' );
1228 $message = __( 'Warning: %s is currently editing this.' );
1231 $message = sprintf( $message, esc_html( $last_user_name ) );
1232 echo "<div class='error'><p>$message</p></div>";
1236 * Creates autosave data for the specified post from $_POST data.
1238 * @package WordPress
1239 * @subpackage Post_Revisions
1242 * @uses _wp_translate_postdata()
1243 * @uses _wp_post_revision_fields()
1247 function wp_create_post_autosave( $post_id ) {
1248 $translated = _wp_translate_postdata( true );
1249 if ( is_wp_error( $translated ) )
1252 // Only store one autosave. If there is already an autosave, overwrite it.
1253 if ( $old_autosave = wp_get_post_autosave( $post_id ) ) {
1254 $new_autosave = _wp_post_revision_fields( $_POST, true );
1255 $new_autosave['ID'] = $old_autosave->ID;
1256 $new_autosave['post_author'] = get_current_user_id();
1257 return wp_update_post( $new_autosave );
1260 // _wp_put_post_revision() expects unescaped.
1261 $_POST = stripslashes_deep($_POST);
1263 // Otherwise create the new autosave as a special post revision
1264 return _wp_put_post_revision( $_POST, true );
1268 * Save draft or manually autosave for showing preview.
1270 * @package WordPress
1273 * @uses wp_write_post()
1276 * @uses current_user_can()
1277 * @uses wp_create_post_autosave()
1279 * @return str URL to redirect to show the preview
1281 function post_preview() {
1283 $post_ID = (int) $_POST['post_ID'];
1284 $status = get_post_status( $post_ID );
1285 if ( 'auto-draft' == $status )
1286 wp_die( __('Preview not available. Please save as a draft first.') );
1288 if ( isset($_POST['catslist']) )
1289 $_POST['post_category'] = explode(",", $_POST['catslist']);
1291 if ( isset($_POST['tags_input']) )
1292 $_POST['tags_input'] = explode(",", $_POST['tags_input']);
1294 if ( $_POST['post_type'] == 'page' || empty($_POST['post_category']) )
1295 unset($_POST['post_category']);
1297 $_POST['ID'] = $post_ID;
1298 $post = get_post($post_ID);
1300 if ( 'page' == $post->post_type ) {
1301 if ( !current_user_can('edit_page', $post_ID) )
1302 wp_die(__('You are not allowed to edit this page.'));
1304 if ( !current_user_can('edit_post', $post_ID) )
1305 wp_die(__('You are not allowed to edit this post.'));
1308 if ( 'draft' == $post->post_status ) {
1310 } else { // Non drafts are not overwritten. The autosave is stored in a special post revision.
1311 $id = wp_create_post_autosave( $post->ID );
1312 if ( ! is_wp_error($id) )
1316 if ( is_wp_error($id) )
1317 wp_die( $id->get_error_message() );
1319 if ( $_POST['post_status'] == 'draft' ) {
1320 $url = add_query_arg( 'preview', 'true', get_permalink($id) );
1322 $nonce = wp_create_nonce('post_preview_' . $id);
1323 $url = add_query_arg( array( 'preview' => 'true', 'preview_id' => $id, 'preview_nonce' => $nonce ), get_permalink($id) );
1330 * Adds the TinyMCE editor used on the Write and Edit screens.
1332 * @package WordPress
1335 * TinyMCE is loaded separately from other Javascript by using wp-tinymce.php. It outputs concatenated
1336 * and optionaly pre-compressed version of the core and all default plugins. Additional plugins are loaded
1337 * directly by TinyMCE using non-blocking method. Custom plugins can be refreshed by adding a query string
1338 * to the URL when queueing them with the mce_external_plugins filter.
1340 * @param bool $teeny optional Output a trimmed down version used in Press This.
1341 * @param mixed $settings optional An array that can add to or overwrite the default TinyMCE settings.
1343 function wp_tiny_mce( $teeny = false, $settings = false ) {
1344 global $concatenate_scripts, $compress_scripts, $tinymce_version, $editor_styles;
1346 if ( ! user_can_richedit() )
1349 $baseurl = includes_url('js/tinymce');
1351 $mce_locale = ( '' == get_locale() ) ? 'en' : strtolower( substr(get_locale(), 0, 2) ); // only ISO 639-1
1354 The following filter allows localization scripts to change the languages displayed in the spellchecker's drop-down menu.
1355 By default it uses Google's spellchecker API, but can be configured to use PSpell/ASpell if installed on the server.
1356 The + sign marks the default language. More information:
1357 http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker
1359 $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');
1362 $plugins = apply_filters( 'teeny_mce_plugins', array('safari', 'inlinepopups', 'media', 'fullscreen', 'wordpress') );
1365 $plugins = array( 'safari', 'inlinepopups', 'spellchecker', 'paste', 'wordpress', 'media', 'fullscreen', 'wpeditimage', 'wpgallery', 'tabfocus' );
1368 The following filter takes an associative array of external plugins for TinyMCE in the form 'plugin_name' => 'url'.
1369 It adds the plugin's name to TinyMCE's plugins init and the call to PluginManager to load the plugin.
1370 The url should be absolute and should include the js file name to be loaded. Example:
1371 array( 'myplugin' => 'http://my-site.com/wp-content/plugins/myfolder/mce_plugin.js' )
1372 If the plugin uses a button, it should be added with one of the "$mce_buttons" filters.
1374 $mce_external_plugins = apply_filters('mce_external_plugins', array());
1377 if ( ! empty($mce_external_plugins) ) {
1380 The following filter loads external language files for TinyMCE plugins.
1381 It takes an associative array 'plugin_name' => 'path', where path is the
1382 include path to the file. The language file should follow the same format as
1383 /tinymce/langs/wp-langs.php and should define a variable $strings that
1384 holds all translated strings.
1385 When this filter is not used, the function will try to load {mce_locale}.js.
1386 If that is not found, en.js will be tried next.
1388 $mce_external_languages = apply_filters('mce_external_languages', array());
1390 $loaded_langs = array();
1393 if ( ! empty($mce_external_languages) ) {
1394 foreach ( $mce_external_languages as $name => $path ) {
1395 if ( @is_file($path) && @is_readable($path) ) {
1396 include_once($path);
1397 $ext_plugins .= $strings . "\n";
1398 $loaded_langs[] = $name;
1403 foreach ( $mce_external_plugins as $name => $url ) {
1405 if ( is_ssl() ) $url = str_replace('http://', 'https://', $url);
1407 $plugins[] = '-' . $name;
1409 $plugurl = dirname($url);
1410 $strings = $str1 = $str2 = '';
1411 if ( ! in_array($name, $loaded_langs) ) {
1412 $path = str_replace( WP_PLUGIN_URL, '', $plugurl );
1413 $path = WP_PLUGIN_DIR . $path . '/langs/';
1415 if ( function_exists('realpath') )
1416 $path = trailingslashit( realpath($path) );
1418 if ( @is_file($path . $mce_locale . '.js') )
1419 $strings .= @file_get_contents($path . $mce_locale . '.js') . "\n";
1421 if ( @is_file($path . $mce_locale . '_dlg.js') )
1422 $strings .= @file_get_contents($path . $mce_locale . '_dlg.js') . "\n";
1424 if ( 'en' != $mce_locale && empty($strings) ) {
1425 if ( @is_file($path . 'en.js') ) {
1426 $str1 = @file_get_contents($path . 'en.js');
1427 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str1, 1 ) . "\n";
1430 if ( @is_file($path . 'en_dlg.js') ) {
1431 $str2 = @file_get_contents($path . 'en_dlg.js');
1432 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str2, 1 ) . "\n";
1436 if ( ! empty($strings) )
1437 $ext_plugins .= "\n" . $strings . "\n";
1440 $ext_plugins .= 'tinyMCEPreInit.load_ext("' . $plugurl . '", "' . $mce_locale . '");' . "\n";
1441 $ext_plugins .= 'tinymce.PluginManager.load("' . $name . '", "' . $url . '");' . "\n";
1446 $plugins = implode($plugins, ',');
1449 $mce_buttons = apply_filters( 'teeny_mce_buttons', array('bold, italic, underline, blockquote, separator, strikethrough, bullist, numlist,justifyleft, justifycenter, justifyright, undo, redo, link, unlink, fullscreen') );
1450 $mce_buttons = implode($mce_buttons, ',');
1451 $mce_buttons_2 = $mce_buttons_3 = $mce_buttons_4 = '';
1453 $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', '|', 'bullist', 'numlist', 'blockquote', '|', 'justifyleft', 'justifycenter', 'justifyright', '|', 'link', 'unlink', 'wp_more', '|', 'spellchecker', 'fullscreen', 'wp_adv' ));
1454 $mce_buttons = implode($mce_buttons, ',');
1456 $mce_buttons_2 = array('formatselect', 'underline', 'justifyfull', 'forecolor', '|', 'pastetext', 'pasteword', 'removeformat', '|', 'media', 'charmap', '|', 'outdent', 'indent', '|', 'undo', 'redo', 'wp_help' );
1457 if ( is_multisite() )
1458 unset( $mce_buttons_2[ array_search( 'media', $mce_buttons_2 ) ] );
1459 $mce_buttons_2 = apply_filters('mce_buttons_2', $mce_buttons_2);
1460 $mce_buttons_2 = implode($mce_buttons_2, ',');
1462 $mce_buttons_3 = apply_filters('mce_buttons_3', array());
1463 $mce_buttons_3 = implode($mce_buttons_3, ',');
1465 $mce_buttons_4 = apply_filters('mce_buttons_4', array());
1466 $mce_buttons_4 = implode($mce_buttons_4, ',');
1468 $no_captions = (bool) apply_filters( 'disable_captions', '' );
1470 // TinyMCE init settings
1471 $initArray = array (
1472 'mode' => 'specific_textareas',
1473 'editor_selector' => 'theEditor',
1475 'theme' => 'advanced',
1476 'skin' => 'wp_theme',
1477 'theme_advanced_buttons1' => $mce_buttons,
1478 'theme_advanced_buttons2' => $mce_buttons_2,
1479 'theme_advanced_buttons3' => $mce_buttons_3,
1480 'theme_advanced_buttons4' => $mce_buttons_4,
1481 'language' => $mce_locale,
1482 'spellchecker_languages' => $mce_spellchecker_languages,
1483 'theme_advanced_toolbar_location' => 'top',
1484 'theme_advanced_toolbar_align' => 'left',
1485 'theme_advanced_statusbar_location' => 'bottom',
1486 'theme_advanced_resizing' => true,
1487 'theme_advanced_resize_horizontal' => false,
1488 'dialog_type' => 'modal',
1489 'relative_urls' => false,
1490 'remove_script_host' => false,
1491 'convert_urls' => false,
1492 'apply_source_formatting' => false,
1493 'remove_linebreaks' => true,
1494 'gecko_spellcheck' => true,
1495 'entities' => '38,amp,60,lt,62,gt',
1496 'accessibility_focus' => true,
1497 'tabfocus_elements' => 'major-publishing-actions',
1498 'media_strict' => false,
1499 'paste_remove_styles' => true,
1500 'paste_remove_spans' => true,
1501 'paste_strip_class_attributes' => 'all',
1502 'wpeditimage_disable_captions' => $no_captions,
1503 'plugins' => $plugins
1506 if ( ! empty( $editor_styles ) && is_array( $editor_styles ) ) {
1508 $style_uri = get_stylesheet_directory_uri();
1509 if ( TEMPLATEPATH == STYLESHEETPATH ) {
1510 foreach ( $editor_styles as $file )
1511 $mce_css[] = "$style_uri/$file";
1513 $style_dir = get_stylesheet_directory();
1514 $template_uri = get_template_directory_uri();
1515 $template_dir = get_template_directory();
1516 foreach ( $editor_styles as $file ) {
1517 if ( file_exists( "$style_dir/$file" ) )
1518 $mce_css[] = "$style_uri/$file";
1519 if ( file_exists( "$template_dir/$file" ) )
1520 $mce_css[] = "$template_uri/$file";
1523 $mce_css = implode( ',', $mce_css );
1528 $mce_css = trim( apply_filters( 'mce_css', $mce_css ), ' ,' );
1530 if ( ! empty($mce_css) )
1531 $initArray['content_css'] = $mce_css;
1533 if ( is_array($settings) )
1534 $initArray = array_merge($initArray, $settings);
1536 // For people who really REALLY know what they're doing with TinyMCE
1537 // You can modify initArray to add, remove, change elements of the config before tinyMCE.init
1538 // Setting "valid_elements", "invalid_elements" and "extended_valid_elements" can be done through "tiny_mce_before_init".
1539 // Best is to use the default cleanup by not specifying valid_elements, as TinyMCE contains full set of XHTML 1.0.
1541 $initArray = apply_filters('teeny_mce_before_init', $initArray);
1543 $initArray = apply_filters('tiny_mce_before_init', $initArray);
1546 if ( empty($initArray['theme_advanced_buttons3']) && !empty($initArray['theme_advanced_buttons4']) ) {
1547 $initArray['theme_advanced_buttons3'] = $initArray['theme_advanced_buttons4'];
1548 $initArray['theme_advanced_buttons4'] = '';
1551 if ( ! isset($concatenate_scripts) )
1552 script_concat_settings();
1554 $language = $initArray['language'];
1556 $compressed = $compress_scripts && $concatenate_scripts && isset($_SERVER['HTTP_ACCEPT_ENCODING'])
1557 && false !== strpos( strtolower($_SERVER['HTTP_ACCEPT_ENCODING']), 'gzip');
1562 * The tiny_mce_version filter is not needed since external plugins are loaded directly by TinyMCE.
1563 * These plugins can be refreshed by appending query string to the URL passed to mce_external_plugins filter.
1564 * 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).
1566 $version = apply_filters('tiny_mce_version', '');
1567 $version = 'ver=' . $tinymce_version . $version;
1569 if ( 'en' != $language )
1570 include_once(ABSPATH . WPINC . '/js/tinymce/langs/wp-langs.php');
1573 foreach ( $initArray as $k => $v )
1574 $mce_options .= $k . ':"' . $v . '", ';
1576 $mce_options = rtrim( trim($mce_options), '\n\r,' ); ?>
1578 <script type="text/javascript">
1581 base : "<?php echo $baseurl; ?>",
1583 query : "<?php echo $version; ?>",
1584 mceInit : {<?php echo $mce_options; ?>},
1585 load_ext : function(url,lang){var sl=tinymce.ScriptLoader;sl.markDone(url+'/langs/'+lang+'.js');sl.markDone(url+'/langs/'+lang+'_dlg.js');}
1592 echo "<script type='text/javascript' src='$baseurl/wp-tinymce.php?c=1&$version'></script>\n";
1594 echo "<script type='text/javascript' src='$baseurl/tiny_mce.js?$version'></script>\n";
1596 if ( 'en' != $language && isset($lang) )
1597 echo "<script type='text/javascript'>\n$lang\n</script>\n";
1599 echo "<script type='text/javascript' src='$baseurl/langs/wp-langs-en.js?$version'></script>\n";
1602 <script type="text/javascript">
1604 <?php if ( $ext_plugins ) echo "$ext_plugins\n"; ?>
1605 <?php if ( $compressed ) { ?>
1606 tinyMCEPreInit.go();
1608 (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');}});})();
1610 tinyMCE.init(tinyMCEPreInit.mceInit);