3 * WordPress Post Administration API.
6 * @subpackage Administration
10 * Rename $_POST data from form names to DB post columns.
12 * Manipulates $_POST directly.
17 * @param bool $update Are we updating a pre-existing post?
18 * @param post_data array Array of post data. Defaults to the contents of $_POST.
19 * @return object|bool WP_Error on failure, true on success.
21 function _wp_translate_postdata( $update = false, $post_data = null ) {
23 if ( empty($post_data) )
27 $post_data['ID'] = (int) $post_data['post_ID'];
28 $post_data['post_content'] = isset($post_data['content']) ? $post_data['content'] : '';
29 $post_data['post_excerpt'] = isset($post_data['excerpt']) ? $post_data['excerpt'] : '';
30 $post_data['post_parent'] = isset($post_data['parent_id'])? $post_data['parent_id'] : '';
31 if ( isset($post_data['trackback_url']) )
32 $post_data['to_ping'] = $post_data['trackback_url'];
34 if (!empty ( $post_data['post_author_override'] ) ) {
35 $post_data['post_author'] = (int) $post_data['post_author_override'];
37 if (!empty ( $post_data['post_author'] ) ) {
38 $post_data['post_author'] = (int) $post_data['post_author'];
40 $post_data['post_author'] = (int) $post_data['user_ID'];
44 if ( isset($post_data['user_ID']) && ($post_data['post_author'] != $post_data['user_ID']) ) {
45 if ( 'page' == $post_data['post_type'] ) {
46 if ( !current_user_can( 'edit_others_pages' ) ) {
47 return new WP_Error( 'edit_others_pages', $update ?
48 __( 'You are not allowed to edit pages as this user.' ) :
49 __( 'You are not allowed to create pages as this user.' )
53 if ( !current_user_can( 'edit_others_posts' ) ) {
54 return new WP_Error( 'edit_others_posts', $update ?
55 __( 'You are not allowed to edit posts as this user.' ) :
56 __( 'You are not allowed to post as this user.' )
62 // What to do based on which button they pressed
63 if ( isset($post_data['saveasdraft']) && '' != $post_data['saveasdraft'] )
64 $post_data['post_status'] = 'draft';
65 if ( isset($post_data['saveasprivate']) && '' != $post_data['saveasprivate'] )
66 $post_data['post_status'] = 'private';
67 if ( isset($post_data['publish']) && ( '' != $post_data['publish'] ) && ( $post_data['post_status'] != 'private' ) )
68 $post_data['post_status'] = 'publish';
69 if ( isset($post_data['advanced']) && '' != $post_data['advanced'] )
70 $post_data['post_status'] = 'draft';
71 if ( isset($post_data['pending']) && '' != $post_data['pending'] )
72 $post_data['post_status'] = 'pending';
74 $previous_status = get_post_field('post_status', isset($post_data['ID']) ? $post_data['ID'] : $post_data['temp_ID']);
76 // Posts 'submitted for approval' present are submitted to $_POST the same as if they were being published.
77 // Change status from 'publish' to 'pending' if user lacks permissions to publish or to resave published posts.
78 if ( 'page' == $post_data['post_type'] ) {
79 $publish_cap = 'publish_pages';
80 $edit_cap = 'edit_published_pages';
82 $publish_cap = 'publish_posts';
83 $edit_cap = 'edit_published_posts';
85 if ( isset($post_data['post_status']) && ('publish' == $post_data['post_status'] && !current_user_can( $publish_cap )) )
86 if ( $previous_status != 'publish' || !current_user_can( $edit_cap ) )
87 $post_data['post_status'] = 'pending';
89 if ( ! isset($post_data['post_status']) )
90 $post_data['post_status'] = $previous_status;
92 if (!isset( $post_data['comment_status'] ))
93 $post_data['comment_status'] = 'closed';
95 if (!isset( $post_data['ping_status'] ))
96 $post_data['ping_status'] = 'closed';
98 foreach ( array('aa', 'mm', 'jj', 'hh', 'mn') as $timeunit ) {
99 if ( !empty( $post_data['hidden_' . $timeunit] ) && $post_data['hidden_' . $timeunit] != $post_data[$timeunit] ) {
100 $post_data['edit_date'] = '1';
105 if ( !empty( $post_data['edit_date'] ) ) {
106 $aa = $post_data['aa'];
107 $mm = $post_data['mm'];
108 $jj = $post_data['jj'];
109 $hh = $post_data['hh'];
110 $mn = $post_data['mn'];
111 $ss = $post_data['ss'];
112 $aa = ($aa <= 0 ) ? date('Y') : $aa;
113 $mm = ($mm <= 0 ) ? date('n') : $mm;
114 $jj = ($jj > 31 ) ? 31 : $jj;
115 $jj = ($jj <= 0 ) ? date('j') : $jj;
116 $hh = ($hh > 23 ) ? $hh -24 : $hh;
117 $mn = ($mn > 59 ) ? $mn -60 : $mn;
118 $ss = ($ss > 59 ) ? $ss -60 : $ss;
119 $post_data['post_date'] = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss );
120 $post_data['post_date_gmt'] = get_gmt_from_date( $post_data['post_date'] );
127 * Update an existing post with values provided in $_POST.
131 * @param array $post_data Optional.
132 * @return int Post ID.
134 function edit_post( $post_data = null ) {
136 if ( empty($post_data) )
137 $post_data = &$_POST;
139 $post_ID = (int) $post_data['post_ID'];
141 if ( 'page' == $post_data['post_type'] ) {
142 if ( !current_user_can( 'edit_page', $post_ID ) )
143 wp_die( __('You are not allowed to edit this page.' ));
145 if ( !current_user_can( 'edit_post', $post_ID ) )
146 wp_die( __('You are not allowed to edit this post.' ));
149 // Autosave shouldn't save too soon after a real save
150 if ( 'autosave' == $post_data['action'] ) {
151 $post =& get_post( $post_ID );
153 $then = strtotime($post->post_date_gmt . ' +0000');
154 $delta = AUTOSAVE_INTERVAL / 2;
155 if ( ($now - $then) < $delta )
159 $post_data = _wp_translate_postdata( true, $post_data );
160 if ( is_wp_error($post_data) )
161 wp_die( $post_data->get_error_message() );
163 if ( isset($post_data['visibility']) ) {
164 switch ( $post_data['visibility'] ) {
166 $post_data['post_password'] = '';
169 unset( $post_data['sticky'] );
172 $post_data['post_status'] = 'private';
173 $post_data['post_password'] = '';
174 unset( $post_data['sticky'] );
180 if ( isset($post_data['meta']) && $post_data['meta'] ) {
181 foreach ( $post_data['meta'] as $key => $value )
182 update_meta( $key, $value['key'], $value['value'] );
185 if ( isset($post_data['deletemeta']) && $post_data['deletemeta'] ) {
186 foreach ( $post_data['deletemeta'] as $key => $value )
190 add_meta( $post_ID );
192 wp_update_post( $post_data );
194 // Reunite any orphaned attachments with their parent
195 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
196 $draft_ids = array();
197 if ( $draft_temp_id = (int) array_search( $post_ID, $draft_ids ) )
198 _relocate_children( $draft_temp_id, $post_ID );
200 // Now that we have an ID we can fix any attachment anchor hrefs
201 _fix_attachment_links( $post_ID );
203 wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
205 if ( current_user_can( 'edit_others_posts' ) ) {
206 if ( !empty($post_data['sticky']) )
207 stick_post($post_ID);
209 unstick_post($post_ID);
216 * {@internal Missing Short Description}}
218 * Updates all bulk edited posts/pages, adding (but not removing) tags and
219 * categories. Skips pages when they would be their own parent or child.
225 function bulk_edit_posts( $post_data = null ) {
228 if ( empty($post_data) )
229 $post_data = &$_POST;
231 if ( isset($post_data['post_type']) && 'page' == $post_data['post_type'] ) {
232 if ( ! current_user_can( 'edit_pages' ) )
233 wp_die( __('You are not allowed to edit pages.') );
235 if ( ! current_user_can( 'edit_posts' ) )
236 wp_die( __('You are not allowed to edit posts.') );
239 $post_IDs = array_map( 'intval', (array) $post_data['post'] );
241 $reset = array( 'post_author', 'post_status', 'post_password', 'post_parent', 'page_template', 'comment_status', 'ping_status', 'keep_private', 'tags_input', 'post_category', 'sticky' );
242 foreach ( $reset as $field ) {
243 if ( isset($post_data[$field]) && ( '' == $post_data[$field] || -1 == $post_data[$field] ) )
244 unset($post_data[$field]);
247 if ( isset($post_data['post_category']) ) {
248 if ( is_array($post_data['post_category']) && ! empty($post_data['post_category']) )
249 $new_cats = array_map( absint, $post_data['post_category'] );
251 unset($post_data['post_category']);
254 if ( isset($post_data['tags_input']) ) {
255 $new_tags = preg_replace( '/\s*,\s*/', ',', rtrim( trim($post_data['tags_input']), ' ,' ) );
256 $new_tags = explode(',', $new_tags);
259 if ( isset($post_data['post_parent']) && ($parent = (int) $post_data['post_parent']) ) {
260 $pages = $wpdb->get_results("SELECT ID, post_parent FROM $wpdb->posts WHERE post_type = 'page'");
263 for ( $i = 0; $i < 50 && $parent > 0; $i++ ) {
264 $children[] = $parent;
266 foreach ( $pages as $page ) {
267 if ( $page->ID == $parent ) {
268 $parent = $page->post_parent;
275 $updated = $skipped = $locked = array();
276 foreach ( $post_IDs as $post_ID ) {
278 if ( isset($children) && in_array($post_ID, $children) ) {
279 $skipped[] = $post_ID;
283 if ( wp_check_post_lock( $post_ID ) ) {
284 $locked[] = $post_ID;
288 if ( isset($new_cats) ) {
289 $cats = (array) wp_get_post_categories($post_ID);
290 $post_data['post_category'] = array_unique( array_merge($cats, $new_cats) );
293 if ( isset($new_tags) ) {
294 $tags = wp_get_post_tags($post_ID, array('fields' => 'names'));
295 $post_data['tags_input'] = array_unique( array_merge($tags, $new_tags) );
298 $post_data['ID'] = $post_ID;
299 $updated[] = wp_update_post( $post_data );
301 if ( current_user_can( 'edit_others_posts' ) && isset( $post_data['sticky'] ) ) {
302 if ( 'sticky' == $post_data['sticky'] )
303 stick_post( $post_ID );
305 unstick_post( $post_ID );
310 return array( 'updated' => $updated, 'skipped' => $skipped, 'locked' => $locked );
314 * Default post information to use when populating the "Write Post" form.
320 function get_default_post_to_edit() {
321 if ( !empty( $_REQUEST['post_title'] ) )
322 $post_title = wp_specialchars( stripslashes( $_REQUEST['post_title'] ));
323 else if ( !empty( $_REQUEST['popuptitle'] ) ) {
324 $post_title = wp_specialchars( stripslashes( $_REQUEST['popuptitle'] ));
325 $post_title = funky_javascript_fix( $post_title );
331 if ( !empty( $_REQUEST['content'] ) )
332 $post_content = wp_specialchars( stripslashes( $_REQUEST['content'] ));
333 else if ( !empty( $post_title ) ) {
334 $text = wp_specialchars( stripslashes( urldecode( $_REQUEST['text'] ) ) );
335 $text = funky_javascript_fix( $text);
336 $popupurl = clean_url($_REQUEST['popupurl']);
337 $post_content = '<a href="'.$popupurl.'">'.$post_title.'</a>'."\n$text";
340 if ( !empty( $_REQUEST['excerpt'] ) )
341 $post_excerpt = wp_specialchars( stripslashes( $_REQUEST['excerpt'] ));
346 $post->post_name = '';
347 $post->post_author = '';
348 $post->post_date = '';
349 $post->post_password = '';
350 $post->post_status = 'draft';
351 $post->post_type = 'post';
354 $post->comment_status = get_option( 'default_comment_status' );
355 $post->ping_status = get_option( 'default_ping_status' );
356 $post->post_pingback = get_option( 'default_pingback_flag' );
357 $post->post_category = get_option( 'default_category' );
358 $post->post_content = apply_filters( 'default_content', $post_content);
359 $post->post_title = apply_filters( 'default_title', $post_title );
360 $post->post_excerpt = apply_filters( 'default_excerpt', $post_excerpt);
361 $post->page_template = 'default';
362 $post->post_parent = 0;
363 $post->menu_order = 0;
369 * {@internal Missing Short Description}}
375 function get_default_page_to_edit() {
376 $page = get_default_post_to_edit();
377 $page->post_type = 'page';
382 * Get an existing post and format it for editing.
386 * @param unknown_type $id
389 function get_post_to_edit( $id ) {
391 $post = get_post( $id, OBJECT, 'edit' );
393 if ( $post->post_type == 'page' )
394 $post->page_template = get_post_meta( $id, '_wp_page_template', true );
400 * {@internal Missing Short Description}}
404 * @param unknown_type $title
405 * @param unknown_type $content
406 * @param unknown_type $post_date
409 function post_exists($title, $content = '', $post_date = '') {
412 $title = stripslashes($title);
413 $content = stripslashes($content);
414 $post_date = stripslashes($post_date);
416 if (!empty ($post_date))
417 $post_date = $wpdb->prepare("AND post_date = %s", $post_date);
420 return $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_title = %s $post_date", $title) );
422 if (!empty ($content))
423 return $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_content = %s $post_date", $content) );
429 * Creates a new post from the "Write Post" form using $_POST information.
435 function wp_write_post() {
438 if ( 'page' == $_POST['post_type'] ) {
439 if ( !current_user_can( 'edit_pages' ) )
440 return new WP_Error( 'edit_pages', __( 'You are not allowed to create pages on this blog.' ) );
442 if ( !current_user_can( 'edit_posts' ) )
443 return new WP_Error( 'edit_posts', __( 'You are not allowed to create posts or drafts on this blog.' ) );
447 // Check for autosave collisions
449 if ( isset($_POST['temp_ID']) ) {
450 $temp_id = (int) $_POST['temp_ID'];
451 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
452 $draft_ids = array();
453 foreach ( $draft_ids as $temp => $real )
454 if ( time() + $temp > 86400 ) // 1 day: $temp is equal to -1 * time( then )
455 unset($draft_ids[$temp]);
457 if ( isset($draft_ids[$temp_id]) ) { // Edit, don't write
458 $_POST['post_ID'] = $draft_ids[$temp_id];
459 unset($_POST['temp_ID']);
460 update_user_option( $user_ID, 'autosave_draft_ids', $draft_ids );
465 $translated = _wp_translate_postdata( false );
466 if ( is_wp_error($translated) )
469 if ( isset($_POST['visibility']) ) {
470 switch ( $_POST['visibility'] ) {
472 $_POST['post_password'] = '';
475 unset( $_POST['sticky'] );
478 $_POST['post_status'] = 'private';
479 $_POST['post_password'] = '';
480 unset( $_POST['sticky'] );
486 $post_ID = wp_insert_post( $_POST );
487 if ( is_wp_error( $post_ID ) )
490 if ( empty($post_ID) )
493 add_meta( $post_ID );
495 // Reunite any orphaned attachments with their parent
496 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
497 $draft_ids = array();
498 if ( $draft_temp_id = (int) array_search( $post_ID, $draft_ids ) )
499 _relocate_children( $draft_temp_id, $post_ID );
500 if ( $temp_id && $temp_id != $draft_temp_id )
501 _relocate_children( $temp_id, $post_ID );
503 // Update autosave collision detection
505 $draft_ids[$temp_id] = $post_ID;
506 update_user_option( $user_ID, 'autosave_draft_ids', $draft_ids );
509 // Now that we have an ID we can fix any attachment anchor hrefs
510 _fix_attachment_links( $post_ID );
512 wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
518 * Calls wp_write_post() and handles the errors.
524 function write_post() {
525 $result = wp_write_post();
526 if( is_wp_error( $result ) )
527 wp_die( $result->get_error_message() );
537 * {@internal Missing Short Description}}
541 * @param unknown_type $post_ID
544 function add_meta( $post_ID ) {
546 $post_ID = (int) $post_ID;
548 $protected = array( '_wp_attached_file', '_wp_attachment_metadata', '_wp_old_slug', '_wp_page_template' );
550 $metakeyselect = isset($_POST['metakeyselect']) ? stripslashes( trim( $_POST['metakeyselect'] ) ) : '';
551 $metakeyinput = isset($_POST['metakeyinput']) ? stripslashes( trim( $_POST['metakeyinput'] ) ) : '';
552 $metavalue = isset($_POST['metavalue']) ? maybe_serialize( stripslashes( trim( $_POST['metavalue'] ) ) ) : '';
554 if ( ('0' === $metavalue || !empty ( $metavalue ) ) && ((('#NONE#' != $metakeyselect) && !empty ( $metakeyselect) ) || !empty ( $metakeyinput) ) ) {
555 // We have a key/value pair. If both the select and the
556 // input for the key have data, the input takes precedence:
558 if ('#NONE#' != $metakeyselect)
559 $metakey = $metakeyselect;
562 $metakey = $metakeyinput; // default
564 if ( in_array($metakey, $protected) )
567 wp_cache_delete($post_ID, 'post_meta');
569 $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->postmeta (post_id,meta_key,meta_value ) VALUES (%s, %s, %s)", $post_ID, $metakey, $metavalue) );
570 return $wpdb->insert_id;
576 * {@internal Missing Short Description}}
580 * @param unknown_type $mid
583 function delete_meta( $mid ) {
587 $post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
588 wp_cache_delete($post_id, 'post_meta');
590 return $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
594 * Get a list of previously defined keys.
600 function get_meta_keys() {
603 $keys = $wpdb->get_col( "
607 ORDER BY meta_key" );
613 * {@internal Missing Short Description}}
617 * @param unknown_type $mid
620 function get_post_meta_by_id( $mid ) {
624 $meta = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
625 if ( is_serialized_string( $meta->meta_value ) )
626 $meta->meta_value = maybe_unserialize( $meta->meta_value );
631 * {@internal Missing Short Description}}
633 * Some postmeta stuff.
637 * @param unknown_type $postid
640 function has_meta( $postid ) {
643 return $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value, meta_id, post_id
644 FROM $wpdb->postmeta WHERE post_id = %d
645 ORDER BY meta_key,meta_id", $postid), ARRAY_A );
650 * {@internal Missing Short Description}}
654 * @param unknown_type $meta_id
655 * @param unknown_type $meta_key
656 * @param unknown_type $meta_value
659 function update_meta( $meta_id, $meta_key, $meta_value ) {
662 $protected = array( '_wp_attached_file', '_wp_attachment_metadata', '_wp_old_slug', '_wp_page_template' );
664 if ( in_array($meta_key, $protected) )
667 $post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_id = %d", $meta_id) );
668 wp_cache_delete($post_id, 'post_meta');
670 $meta_value = maybe_serialize( stripslashes( $meta_value ));
671 $meta_id = (int) $meta_id;
673 $data = compact( 'meta_key', 'meta_value' );
674 $where = compact( 'meta_id' );
676 return $wpdb->update( $wpdb->postmeta, $data, $where );
684 * Replace hrefs of attachment anchors with up-to-date permalinks.
689 * @param unknown_type $post_ID
692 function _fix_attachment_links( $post_ID ) {
694 $post = & get_post( $post_ID, ARRAY_A );
696 $search = "#<a[^>]+rel=('|\")[^'\"]*attachment[^>]*>#ie";
698 // See if we have any rel="attachment" links
699 if ( 0 == preg_match_all( $search, $post['post_content'], $anchor_matches, PREG_PATTERN_ORDER ) )
703 $search = "#[\s]+rel=(\"|')(.*?)wp-att-(\d+)\\1#i";
704 foreach ( $anchor_matches[0] as $anchor ) {
705 if ( 0 == preg_match( $search, $anchor, $id_matches ) )
708 $id = (int) $id_matches[3];
710 // While we have the attachment ID, let's adopt any orphans.
711 $attachment = & get_post( $id, ARRAY_A );
712 if ( ! empty( $attachment) && ! is_object( get_post( $attachment['post_parent'] ) ) ) {
713 $attachment['post_parent'] = $post_ID;
714 // Escape data pulled from DB.
715 $attachment = add_magic_quotes( $attachment);
716 wp_update_post( $attachment);
719 $post_search[$i] = $anchor;
720 $post_replace[$i] = preg_replace( "#href=(\"|')[^'\"]*\\1#e", "stripslashes( 'href=\\1' ).get_attachment_link( $id ).stripslashes( '\\1' )", $anchor );
724 $post['post_content'] = str_replace( $post_search, $post_replace, $post['post_content'] );
726 // Escape data pulled from DB.
727 $post = add_magic_quotes( $post);
729 return wp_update_post( $post);
733 * Move child posts to a new parent.
738 * @param unknown_type $old_ID
739 * @param unknown_type $new_ID
742 function _relocate_children( $old_ID, $new_ID ) {
744 $old_ID = (int) $old_ID;
745 $new_ID = (int) $new_ID;
746 return $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET post_parent = %d WHERE post_parent = %d", $new_ID, $old_ID) );
750 * {@internal Missing Short Description}}
754 * @param unknown_type $type
757 function get_available_post_statuses($type = 'post') {
758 $stati = wp_count_posts($type);
760 return array_keys(get_object_vars($stati));
764 * {@internal Missing Short Description}}
768 * @param unknown_type $q
771 function wp_edit_posts_query( $q = false ) {
774 $q['m'] = isset($q['m']) ? (int) $q['m'] : 0;
775 $q['cat'] = isset($q['cat']) ? (int) $q['cat'] : 0;
776 $post_stati = array( // array( adj, noun )
777 'publish' => array(__('Published'), __('Published posts'), __ngettext_noop('Published <span class="count">(%s)</span>', 'Published <span class="count">(%s)</span>')),
778 'future' => array(__('Scheduled'), __('Scheduled posts'), __ngettext_noop('Scheduled <span class="count">(%s)</span>', 'Scheduled <span class="count">(%s)</span>')),
779 'pending' => array(__('Pending Review'), __('Pending posts'), __ngettext_noop('Pending Review <span class="count">(%s)</span>', 'Pending Review <span class="count">(%s)</span>')),
780 'draft' => array(__('Draft'), _c('Drafts|manage posts header'), __ngettext_noop('Draft <span class="count">(%s)</span>', 'Drafts <span class="count">(%s)</span>')),
781 'private' => array(__('Private'), __('Private posts'), __ngettext_noop('Private <span class="count">(%s)</span>', 'Private <span class="count">(%s)</span>')),
784 $post_stati = apply_filters('post_stati', $post_stati);
786 $avail_post_stati = get_available_post_statuses('post');
789 if ( isset($q['post_status']) && in_array( $q['post_status'], array_keys($post_stati) ) ) {
790 $post_status_q = '&post_status=' . $q['post_status'];
791 $post_status_q .= '&perm=readable';
794 if ( isset($q['post_status']) && 'pending' === $q['post_status'] ) {
796 $orderby = 'modified';
797 } elseif ( isset($q['post_status']) && 'draft' === $q['post_status'] ) {
799 $orderby = 'modified';
805 wp("post_type=post&what_to_show=posts$post_status_q&posts_per_page=15&order=$order&orderby=$orderby");
807 return array($post_stati, $avail_post_stati);
811 * {@internal Missing Short Description}}
815 * @param unknown_type $type
818 function get_available_post_mime_types($type = 'attachment') {
821 $types = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT post_mime_type FROM $wpdb->posts WHERE post_type = %s", $type));
826 * {@internal Missing Short Description}}
830 * @param unknown_type $q
833 function wp_edit_attachments_query( $q = false ) {
837 $q['m'] = isset( $q['m'] ) ? (int) $q['m'] : 0;
838 $q['cat'] = isset( $q['cat'] ) ? (int) $q['cat'] : 0;
839 $q['post_type'] = 'attachment';
840 $q['post_status'] = 'any';
841 $q['posts_per_page'] = 15;
842 $post_mime_types = array( // array( adj, noun )
843 'image' => array(__('Images'), __('Manage Images'), __ngettext_noop('Image <span class="count">(%s)</span>', 'Images <span class="count">(%s)</span>')),
844 'audio' => array(__('Audio'), __('Manage Audio'), __ngettext_noop('Audio <span class="count">(%s)</span>', 'Audio <span class="count">(%s)</span>')),
845 'video' => array(__('Video'), __('Manage Video'), __ngettext_noop('Video <span class="count">(%s)</span>', 'Video <span class="count">(%s)</span>')),
847 $post_mime_types = apply_filters('post_mime_types', $post_mime_types);
849 $avail_post_mime_types = get_available_post_mime_types('attachment');
851 if ( isset($q['post_mime_type']) && !array_intersect( (array) $q['post_mime_type'], array_keys($post_mime_types) ) )
852 unset($q['post_mime_type']);
856 return array($post_mime_types, $avail_post_mime_types);
860 * {@internal Missing Short Description}}
864 * @param unknown_type $id
865 * @param unknown_type $page
868 function postbox_classes( $id, $page ) {
869 if ( isset( $_GET['edit'] ) && $_GET['edit'] == $id )
871 $current_user = wp_get_current_user();
872 if ( $closed = get_user_option('closedpostboxes_'.$page, 0, false ) ) {
873 if ( !is_array( $closed ) ) return '';
874 return in_array( $id, $closed )? 'if-js-closed' : '';
881 * {@internal Missing Short Description}}
885 * @param unknown_type $id
886 * @param unknown_type $title
887 * @param unknown_type $name
890 function get_sample_permalink($id, $title=null, $name = null) {
891 $post = &get_post($id);
893 return array('', '');
895 $original_status = $post->post_status;
896 $original_date = $post->post_date;
897 $original_name = $post->post_name;
899 // Hack: get_permalink would return ugly permalink for
900 // drafts, so we will fake, that our post is published
901 if (in_array($post->post_status, array('draft', 'pending'))) {
902 $post->post_status = 'publish';
903 $post->post_name = sanitize_title($post->post_name? $post->post_name : $post->post_title, $post->ID);
906 // If the user wants to set a new name -- override the current one
907 // Note: if empty name is supplied -- use the title instead, see #6072
908 if (!is_null($name)) {
909 $post->post_name = sanitize_title($name? $name : $title, $post->ID);
912 $post->filter = 'sample';
914 $permalink = get_permalink($post, true);
916 // Handle page hierarchy
917 if ( 'page' == $post->post_type ) {
918 $uri = get_page_uri($post->ID);
919 $uri = untrailingslashit($uri);
920 $uri = strrev( stristr( strrev( $uri ), '/' ) );
921 $uri = untrailingslashit($uri);
924 $permalink = str_replace('%pagename%', "${uri}%pagename%", $permalink);
927 $permalink = array($permalink, apply_filters('editable_slug', $post->post_name));
928 $post->post_status = $original_status;
929 $post->post_date = $original_date;
930 $post->post_name = $original_name;
931 unset($post->filter);
937 * {@internal Missing Short Description}}
941 * @param unknown_type $id
942 * @param unknown_type $new_title
943 * @param unknown_type $new_slug
946 function get_sample_permalink_html($id, $new_title=null, $new_slug=null) {
947 $post = &get_post($id);
948 list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug);
949 if (false === strpos($permalink, '%postname%') && false === strpos($permalink, '%pagename%')) {
952 $title = __('Click to edit this part of the permalink');
953 if (function_exists('mb_strlen')) {
954 if (mb_strlen($post_name) > 30) {
955 $post_name_abridged = mb_substr($post_name, 0, 14). '…' . mb_substr($post_name, -14);
957 $post_name_abridged = $post_name;
960 if (strlen($post_name) > 30) {
961 $post_name_abridged = substr($post_name, 0, 14). '…' . substr($post_name, -14);
963 $post_name_abridged = $post_name;
966 $post_name_html = '<span id="editable-post-name" title="'.$title.'">'.$post_name_abridged.'</span><span id="editable-post-name-full">'.$post_name.'</span>';
967 $display_link = str_replace(array('%pagename%','%postname%'), $post_name_html, $permalink);
968 $return = '<strong>' . __('Permalink:') . "</strong>\n" . '<span id="sample-permalink">' . $display_link . "</span>\n";
969 $return .= '<span id="edit-slug-buttons"><a href="#post_name" class="edit-slug button" onclick="edit_permalink(' . $id . '); return false;">' . __('Edit') . "</a></span>\n";
974 * {@internal Missing Short Description}}
978 * @param unknown_type $post_id
979 * @return bool|int False: not locked or locked by current user. Int: user ID of user with lock.
981 function wp_check_post_lock( $post_id ) {
982 global $current_user;
984 if ( !$post = get_post( $post_id ) )
987 $lock = get_post_meta( $post->ID, '_edit_lock', true );
988 $last = get_post_meta( $post->ID, '_edit_last', true );
990 $time_window = apply_filters( 'wp_check_post_lock_window', AUTOSAVE_INTERVAL * 2 );
992 if ( $lock && $lock > time() - $time_window && $last != $current_user->ID )
998 * {@internal Missing Short Description}}
1002 * @param unknown_type $post_id
1005 function wp_set_post_lock( $post_id ) {
1006 global $current_user;
1007 if ( !$post = get_post( $post_id ) )
1009 if ( !$current_user || !$current_user->ID )
1014 if ( !add_post_meta( $post->ID, '_edit_lock', $now, true ) )
1015 update_post_meta( $post->ID, '_edit_lock', $now );
1016 if ( !add_post_meta( $post->ID, '_edit_last', $current_user->ID, true ) )
1017 update_post_meta( $post->ID, '_edit_last', $current_user->ID );
1021 * Creates autosave data for the specified post from $_POST data.
1023 * @package WordPress
1024 * @subpackage Post_Revisions
1027 * @uses _wp_translate_postdata()
1028 * @uses _wp_post_revision_fields()
1030 function wp_create_post_autosave( $post_id ) {
1031 $translated = _wp_translate_postdata( true );
1032 if ( is_wp_error( $translated ) )
1035 // Only store one autosave. If there is already an autosave, overwrite it.
1036 if ( $old_autosave = wp_get_post_autosave( $post_id ) ) {
1037 $new_autosave = _wp_post_revision_fields( $_POST, true );
1038 $new_autosave['ID'] = $old_autosave->ID;
1039 return wp_update_post( $new_autosave );
1042 // Otherwise create the new autosave as a special post revision
1043 return _wp_put_post_revision( $_POST, true );
1047 * Save draft or manually autosave for showing preview.
1049 * @package WordPress
1052 * @uses wp_write_post()
1055 * @uses current_user_can()
1056 * @uses wp_create_post_autosave()
1058 * @return str URL to redirect to show the preview
1060 function post_preview() {
1062 $post_ID = (int) $_POST['post_ID'];
1064 wp_die( __('Preview not available. Please save as a draft first.') );
1066 if ( isset($_POST['catslist']) )
1067 $_POST['post_category'] = explode(",", $_POST['catslist']);
1069 if ( isset($_POST['tags_input']) )
1070 $_POST['tags_input'] = explode(",", $_POST['tags_input']);
1072 if ( $_POST['post_type'] == 'page' || empty($_POST['post_category']) )
1073 unset($_POST['post_category']);
1075 $_POST['ID'] = $post_ID;
1076 $post = get_post($post_ID);
1078 if ( 'page' == $post->post_type ) {
1079 if ( !current_user_can('edit_page', $post_ID) )
1080 wp_die(__('You are not allowed to edit this page.'));
1082 if ( !current_user_can('edit_post', $post_ID) )
1083 wp_die(__('You are not allowed to edit this post.'));
1086 if ( 'draft' == $post->post_status ) {
1088 } else { // Non drafts are not overwritten. The autosave is stored in a special post revision.
1089 $id = wp_create_post_autosave( $post->ID );
1090 if ( ! is_wp_error($id) )
1094 if ( is_wp_error($id) )
1095 wp_die( $id->get_error_message() );
1097 if ( $_POST['post_status'] == 'draft' ) {
1098 $url = add_query_arg( 'preview', 'true', get_permalink($id) );
1100 $nonce = wp_create_nonce('post_preview_' . $id);
1101 $url = add_query_arg( array( 'preview' => 'true', 'preview_id' => $id, 'preview_nonce' => $nonce ), get_permalink($id) );
1108 * Adds the TinyMCE editor used on the Write and Edit screens.
1110 * Has option to output a trimmed down version used in Press This.
1112 * @package WordPress
1115 function wp_tiny_mce( $teeny = false ) {
1116 if ( ! user_can_richedit() )
1119 $baseurl = includes_url('js/tinymce');
1121 $mce_css = $baseurl . '/wordpress.css';
1122 $mce_css = apply_filters('mce_css', $mce_css);
1124 $mce_locale = ( '' == get_locale() ) ? 'en' : strtolower( substr(get_locale(), 0, 2) ); // only ISO 639-1
1127 The following filter allows localization scripts to change the languages displayed in the spellchecker's drop-down menu.
1128 By default it uses Google's spellchecker API, but can be configured to use PSpell/ASpell if installed on the server.
1129 The + sign marks the default language. More information:
1130 http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker
1132 $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');
1135 $plugins = apply_filters( 'teeny_mce_plugins', array('safari', 'inlinepopups', 'media', 'autosave', 'fullscreen') );
1138 $plugins = array( 'safari', 'inlinepopups', 'autosave', 'spellchecker', 'paste', 'wordpress', 'media', 'fullscreen', 'wpeditimage', 'wpgallery' );
1141 The following filter takes an associative array of external plugins for TinyMCE in the form 'plugin_name' => 'url'.
1142 It adds the plugin's name to TinyMCE's plugins init and the call to PluginManager to load the plugin.
1143 The url should be absolute and should include the js file name to be loaded. Example:
1144 array( 'myplugin' => 'http://my-site.com/wp-content/plugins/myfolder/mce_plugin.js' )
1145 If the plugin uses a button, it should be added with one of the "$mce_buttons" filters.
1147 $mce_external_plugins = apply_filters('mce_external_plugins', array());
1149 $ext_plugins = "\n";
1150 if ( ! empty($mce_external_plugins) ) {
1153 The following filter loads external language files for TinyMCE plugins.
1154 It takes an associative array 'plugin_name' => 'path', where path is the
1155 include path to the file. The language file should follow the same format as
1156 /tinymce/langs/wp-langs.php and should define a variable $strings that
1157 holds all translated strings.
1158 When this filter is not used, the function will try to load {mce_locale}.js.
1159 If that is not found, en.js will be tried next.
1161 $mce_external_languages = apply_filters('mce_external_languages', array());
1163 $loaded_langs = array();
1166 if ( ! empty($mce_external_languages) ) {
1167 foreach ( $mce_external_languages as $name => $path ) {
1168 if ( @is_file($path) && @is_readable($path) ) {
1169 include_once($path);
1170 $ext_plugins .= $strings . "\n";
1171 $loaded_langs[] = $name;
1176 foreach ( $mce_external_plugins as $name => $url ) {
1178 if ( is_ssl() ) $url = str_replace('http://', 'https://', $url);
1180 $plugins[] = '-' . $name;
1182 $plugurl = dirname($url);
1183 $strings = $str1 = $str2 = '';
1184 if ( ! in_array($name, $loaded_langs) ) {
1185 $path = str_replace( WP_PLUGIN_URL, '', $plugurl );
1186 $path = WP_PLUGIN_DIR . $path . '/langs/';
1188 if ( function_exists('realpath') )
1189 $path = trailingslashit( realpath($path) );
1191 if ( @is_file($path . $mce_locale . '.js') )
1192 $strings .= @file_get_contents($path . $mce_locale . '.js') . "\n";
1194 if ( @is_file($path . $mce_locale . '_dlg.js') )
1195 $strings .= @file_get_contents($path . $mce_locale . '_dlg.js') . "\n";
1197 if ( 'en' != $mce_locale && empty($strings) ) {
1198 if ( @is_file($path . 'en.js') ) {
1199 $str1 = @file_get_contents($path . 'en.js');
1200 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str1, 1 ) . "\n";
1203 if ( @is_file($path . 'en_dlg.js') ) {
1204 $str2 = @file_get_contents($path . 'en_dlg.js');
1205 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str2, 1 ) . "\n";
1209 if ( ! empty($strings) )
1210 $ext_plugins .= "\n" . $strings . "\n";
1213 $ext_plugins .= 'tinyMCEPreInit.load_ext("' . $plugurl . '", "' . $mce_locale . '");' . "\n";
1214 $ext_plugins .= 'tinymce.PluginManager.load("' . $name . '", "' . $url . '");' . "\n";
1219 $plugins = implode($plugins, ',');
1222 $mce_buttons = apply_filters( 'teeny_mce_buttons', array('bold, italic, underline, blockquote, separator, strikethrough, bullist, numlist,justifyleft, justifycenter, justifyright, undo, redo, link, unlink, fullscreen') );
1223 $mce_buttons = implode($mce_buttons, ',');
1224 $mce_buttons_2 = $mce_buttons_3 = $mce_buttons_4 = '';
1226 $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', '|', 'bullist', 'numlist', 'blockquote', '|', 'justifyleft', 'justifycenter', 'justifyright', '|', 'link', 'unlink', 'wp_more', '|', 'spellchecker', 'fullscreen', 'wp_adv' ));
1227 $mce_buttons = implode($mce_buttons, ',');
1229 $mce_buttons_2 = apply_filters('mce_buttons_2', array('formatselect', 'underline', 'justifyfull', 'forecolor', '|', 'pastetext', 'pasteword', 'removeformat', '|', 'media', 'charmap', '|', 'outdent', 'indent', '|', 'undo', 'redo', 'wp_help' ));
1230 $mce_buttons_2 = implode($mce_buttons_2, ',');
1232 $mce_buttons_3 = apply_filters('mce_buttons_3', array());
1233 $mce_buttons_3 = implode($mce_buttons_3, ',');
1235 $mce_buttons_4 = apply_filters('mce_buttons_4', array());
1236 $mce_buttons_4 = implode($mce_buttons_4, ',');
1238 $no_captions = ( apply_filters( 'disable_captions', '' ) ) ? true : false;
1240 // TinyMCE init settings
1241 $initArray = array (
1243 'onpageload' => 'switchEditors.edInit',
1245 'theme' => 'advanced',
1246 'skin' => 'wp_theme',
1247 'theme_advanced_buttons1' => "$mce_buttons",
1248 'theme_advanced_buttons2' => "$mce_buttons_2",
1249 'theme_advanced_buttons3' => "$mce_buttons_3",
1250 'theme_advanced_buttons4' => "$mce_buttons_4",
1251 'language' => "$mce_locale",
1252 'spellchecker_languages' => "$mce_spellchecker_languages",
1253 'theme_advanced_toolbar_location' => 'top',
1254 'theme_advanced_toolbar_align' => 'left',
1255 'theme_advanced_statusbar_location' => 'bottom',
1256 'theme_advanced_resizing' => true,
1257 'theme_advanced_resize_horizontal' => false,
1258 'dialog_type' => 'modal',
1259 'relative_urls' => false,
1260 'remove_script_host' => false,
1261 'convert_urls' => false,
1262 'apply_source_formatting' => false,
1263 'remove_linebreaks' => true,
1264 'paste_convert_middot_lists' => true,
1265 'paste_remove_spans' => true,
1266 'paste_remove_styles' => true,
1267 'gecko_spellcheck' => true,
1268 'entities' => '38,amp,60,lt,62,gt',
1269 'accessibility_focus' => true,
1270 'tab_focus' => ':prev,:next',
1271 'content_css' => "$mce_css",
1272 'save_callback' => 'switchEditors.saveCallback',
1273 'wpeditimage_disable_captions' => $no_captions,
1274 'plugins' => "$plugins"
1277 // For people who really REALLY know what they're doing with TinyMCE
1278 // You can modify initArray to add, remove, change elements of the config before tinyMCE.init
1279 // Setting "valid_elements", "invalid_elements" and "extended_valid_elements" can be done through "tiny_mce_before_init".
1280 // Best is to use the default cleanup by not specifying valid_elements, as TinyMCE contains full set of XHTML 1.0.
1282 $initArray = apply_filters('teeny_mce_before_init', $initArray);
1284 $initArray = apply_filters('tiny_mce_before_init', $initArray);
1287 $language = $initArray['language'];
1289 $ver = apply_filters('tiny_mce_version', '3101');
1291 if ( 'en' != $language )
1292 include_once(ABSPATH . WPINC . '/js/tinymce/langs/wp-langs.php');
1295 foreach ( $initArray as $k => $v )
1296 $mce_options .= $k . ':"' . $v . '", ';
1298 $mce_options = rtrim( trim($mce_options), '\n\r,' ); ?>
1300 <script type="text/javascript">
1303 base : "<?php echo $baseurl; ?>",
1305 query : "ver=<?php echo $ver; ?>",
1306 mceInit : {<?php echo $mce_options; ?>},
1309 var t = this, sl = tinymce.ScriptLoader, ln = t.mceInit.language, th = t.mceInit.theme, pl = t.mceInit.plugins;
1311 sl.markDone(t.base + '/langs/' + ln + '.js');
1313 sl.markDone(t.base + '/themes/' + th + '/langs/' + ln + '.js');
1314 sl.markDone(t.base + '/themes/' + th + '/langs/' + ln + '_dlg.js');
1316 tinymce.each(pl.split(','), function(n) {
1317 if (n && n.charAt(0) != '-') {
1318 sl.markDone(t.base + '/plugins/' + n + '/langs/' + ln + '.js');
1319 sl.markDone(t.base + '/plugins/' + n + '/langs/' + ln + '_dlg.js');
1324 load_ext : function(url,lang) {
1325 var sl = tinymce.ScriptLoader;
1327 sl.markDone(url + '/langs/' + lang + '.js');
1328 sl.markDone(url + '/langs/' + lang + '_dlg.js');
1333 <script type="text/javascript" src="<?php echo $baseurl; ?>/tiny_mce.js?ver=<?php echo $ver; ?>"></script>
1334 <?php if ( 'en' != $language && isset($lang) ) { ?>
1335 <script type="text/javascript">
1336 <?php echo $lang; ?>
1339 <script type="text/javascript" src="<?php echo $baseurl; ?>/langs/wp-langs-en.js?ver=<?php echo $ver; ?>"></script>
1341 <script type="text/javascript">
1342 <?php if ( $ext_plugins ) echo $ext_plugins; ?>
1344 // Mark translations as done
1345 tinyMCEPreInit.go();
1348 tinyMCE.init(tinyMCEPreInit.mceInit);