Wordpress 2.6.2
[autoinstalls/wordpress.git] / wp-admin / includes / post.php
1 <?php
2
3 /**
4  * _wp_translate_postdata() - Rename $_POST data from form names to DB post columns.
5  *
6  * Manipulates $_POST directly.
7  *
8  * @package WordPress
9  * @since 2.6
10  *
11  * @param bool $update Are we updating a pre-existing post?
12  * @return object|bool WP_Error on failure, true on success.
13  */
14 function _wp_translate_postdata( $update = false ) {
15         if ( $update )
16                 $_POST['ID'] = (int) $_POST['post_ID'];
17         $_POST['post_content'] = $_POST['content'];
18         $_POST['post_excerpt'] = $_POST['excerpt'];
19         $_POST['post_parent'] = isset($_POST['parent_id'])? $_POST['parent_id'] : '';
20         $_POST['to_ping'] = $_POST['trackback_url'];
21
22         if (!empty ( $_POST['post_author_override'] ) ) {
23                 $_POST['post_author'] = (int) $_POST['post_author_override'];
24         } else {
25                 if (!empty ( $_POST['post_author'] ) ) {
26                         $_POST['post_author'] = (int) $_POST['post_author'];
27                 } else {
28                         $_POST['post_author'] = (int) $_POST['user_ID'];
29                 }
30         }
31
32         if ( $_POST['post_author'] != $_POST['user_ID'] ) {
33                 if ( 'page' == $_POST['post_type'] ) {
34                         if ( !current_user_can( 'edit_others_pages' ) ) {
35                                 return new WP_Error( 'edit_others_pages', $update ?
36                                         __( 'You are not allowed to edit pages as this user.' ) :
37                                         __( 'You are not allowed to create pages as this user.' )
38                                 );
39                         }
40                 } else {
41                         if ( !current_user_can( 'edit_others_posts' ) ) {
42                                 return new WP_Error( 'edit_others_posts', $update ?
43                                         __( 'You are not allowed to edit posts as this user.' ) :
44                                         __( 'You are not allowed to post as this user.' )
45                                 );
46                         }
47                 }
48         }
49
50         // What to do based on which button they pressed
51         if ( isset($_POST['saveasdraft']) && '' != $_POST['saveasdraft'] )
52                 $_POST['post_status'] = 'draft';
53         if ( isset($_POST['saveasprivate']) && '' != $_POST['saveasprivate'] )
54                 $_POST['post_status'] = 'private';
55         if ( isset($_POST['publish']) && ( '' != $_POST['publish'] ) && ( $_POST['post_status'] != 'private' ) )
56                 $_POST['post_status'] = 'publish';
57         if ( isset($_POST['advanced']) && '' != $_POST['advanced'] )
58                 $_POST['post_status'] = 'draft';
59
60         $previous_status = get_post_field('post_status',  $_POST['ID']);
61
62         // Posts 'submitted for approval' present are submitted to $_POST the same as if they were being published. 
63         // Change status from 'publish' to 'pending' if user lacks permissions to publish or to resave published posts.
64         if ( 'page' == $_POST['post_type'] ) {
65                 if ( 'publish' == $_POST['post_status'] && !current_user_can( 'publish_pages' ) )
66                         if ( $previous_status != 'publish' OR !current_user_can( 'edit_published_pages') )
67                                 $_POST['post_status'] = 'pending';
68         } else {
69                 if ( 'publish' == $_POST['post_status'] && !current_user_can( 'publish_posts' ) ) :
70                         // Stop attempts to publish new posts, but allow already published posts to be saved if appropriate.
71                         if ( $previous_status != 'publish' OR !current_user_can( 'edit_published_posts') )
72                                 $_POST['post_status'] = 'pending';
73                 endif;
74         }
75
76         if (!isset( $_POST['comment_status'] ))
77                 $_POST['comment_status'] = 'closed';
78
79         if (!isset( $_POST['ping_status'] ))
80                 $_POST['ping_status'] = 'closed';
81
82         foreach ( array('aa', 'mm', 'jj', 'hh', 'mn') as $timeunit ) {
83                 if ( !empty( $_POST['hidden_' . $timeunit] ) && $_POST['hidden_' . $timeunit] != $_POST[$timeunit] ) {
84                         $_POST['edit_date'] = '1';
85                         break;
86                 }
87         }
88
89         if ( !empty( $_POST['edit_date'] ) ) {
90                 $aa = $_POST['aa'];
91                 $mm = $_POST['mm'];
92                 $jj = $_POST['jj'];
93                 $hh = $_POST['hh'];
94                 $mn = $_POST['mn'];
95                 $ss = $_POST['ss'];
96                 $aa = ($aa <= 0 ) ? date('Y') : $aa;
97                 $mm = ($mm <= 0 ) ? date('n') : $mm;
98                 $jj = ($jj > 31 ) ? 31 : $jj;
99                 $jj = ($jj <= 0 ) ? date('j') : $jj;
100                 $hh = ($hh > 23 ) ? $hh -24 : $hh;
101                 $mn = ($mn > 59 ) ? $mn -60 : $mn;
102                 $ss = ($ss > 59 ) ? $ss -60 : $ss;
103                 $_POST['post_date'] = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss );
104                 $_POST['post_date_gmt'] = get_gmt_from_date( $_POST['post_date'] );
105         }
106
107         return true;
108 }
109
110
111 // Update an existing post with values provided in $_POST.
112 function edit_post() {
113
114         $post_ID = (int) $_POST['post_ID'];
115
116         if ( 'page' == $_POST['post_type'] ) {
117                 if ( !current_user_can( 'edit_page', $post_ID ) )
118                         wp_die( __('You are not allowed to edit this page.' ));
119         } else {
120                 if ( !current_user_can( 'edit_post', $post_ID ) )
121                         wp_die( __('You are not allowed to edit this post.' ));
122         }
123
124         // Autosave shouldn't save too soon after a real save
125         if ( 'autosave' == $_POST['action'] ) {
126                 $post =& get_post( $post_ID );
127                 $now = time();
128                 $then = strtotime($post->post_date_gmt . ' +0000');
129                 $delta = AUTOSAVE_INTERVAL / 2;
130                 if ( ($now - $then) < $delta )
131                         return $post_ID;
132         }
133
134         $translated = _wp_translate_postdata( true );
135         if ( is_wp_error($translated) )
136                 wp_die( $translated->get_error_message() );
137
138         // Meta Stuff
139         if ( isset($_POST['meta']) && $_POST['meta'] ) {
140                 foreach ( $_POST['meta'] as $key => $value )
141                         update_meta( $key, $value['key'], $value['value'] );
142         }
143
144         if ( isset($_POST['deletemeta']) && $_POST['deletemeta'] ) {
145                 foreach ( $_POST['deletemeta'] as $key => $value )
146                         delete_meta( $key );
147         }
148
149         add_meta( $post_ID );
150
151         wp_update_post( $_POST );
152
153         // Reunite any orphaned attachments with their parent
154         if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
155                 $draft_ids = array();
156         if ( $draft_temp_id = (int) array_search( $post_ID, $draft_ids ) )
157                 _relocate_children( $draft_temp_id, $post_ID );
158
159         // Now that we have an ID we can fix any attachment anchor hrefs
160         _fix_attachment_links( $post_ID );
161
162         wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
163
164         return $post_ID;
165 }
166
167 // Default post information to use when populating the "Write Post" form.
168 function get_default_post_to_edit() {
169         if ( !empty( $_REQUEST['post_title'] ) )
170                 $post_title = wp_specialchars( stripslashes( $_REQUEST['post_title'] ));
171         else if ( !empty( $_REQUEST['popuptitle'] ) ) {
172                 $post_title = wp_specialchars( stripslashes( $_REQUEST['popuptitle'] ));
173                 $post_title = funky_javascript_fix( $post_title );
174         } else {
175                 $post_title = '';
176         }
177
178         $post_content = '';
179         if ( !empty( $_REQUEST['content'] ) )
180                 $post_content = wp_specialchars( stripslashes( $_REQUEST['content'] ));
181         else if ( !empty( $post_title ) ) {
182                 $text       = wp_specialchars( stripslashes( urldecode( $_REQUEST['text'] ) ) );
183                 $text       = funky_javascript_fix( $text);
184                 $popupurl   = clean_url($_REQUEST['popupurl']);
185         $post_content = '<a href="'.$popupurl.'">'.$post_title.'</a>'."\n$text";
186     }
187
188         if ( !empty( $_REQUEST['excerpt'] ) )
189                 $post_excerpt = wp_specialchars( stripslashes( $_REQUEST['excerpt'] ));
190         else
191                 $post_excerpt = '';
192
193         $post->ID = 0;
194         $post->post_name = '';
195         $post->post_author = '';
196         $post->post_date = '';
197         $post->post_status = 'draft';
198         $post->post_type = 'post';
199         $post->to_ping = '';
200         $post->pinged = '';
201         $post->comment_status = get_option( 'default_comment_status' );
202         $post->ping_status = get_option( 'default_ping_status' );
203         $post->post_pingback = get_option( 'default_pingback_flag' );
204         $post->post_category = get_option( 'default_category' );
205         $post->post_content = apply_filters( 'default_content', $post_content);
206         $post->post_title = apply_filters( 'default_title', $post_title );
207         $post->post_excerpt = apply_filters( 'default_excerpt', $post_excerpt);
208         $post->page_template = 'default';
209         $post->post_parent = 0;
210         $post->menu_order = 0;
211
212         return $post;
213 }
214
215 function get_default_page_to_edit() {
216         $page = get_default_post_to_edit();
217         $page->post_type = 'page';
218         return $page;
219 }
220
221 // Get an existing post and format it for editing.
222 function get_post_to_edit( $id ) {
223
224         $post = get_post( $id, OBJECT, 'edit' );
225
226         if ( $post->post_type == 'page' )
227                 $post->page_template = get_post_meta( $id, '_wp_page_template', true );
228
229         return $post;
230 }
231
232 function post_exists($title, $content = '', $post_date = '') {
233         global $wpdb;
234
235         if (!empty ($post_date))
236                 $post_date = $wpdb->prepare("AND post_date = %s", $post_date);
237
238         if (!empty ($title))
239                 return $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_title = %s $post_date", $title) );
240         else
241                 if (!empty ($content))
242                         return $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_content = %s $post_date", $content) );
243
244         return 0;
245 }
246
247 // Creates a new post from the "Write Post" form using $_POST information.
248 function wp_write_post() {
249         global $user_ID;
250
251         if ( 'page' == $_POST['post_type'] ) {
252                 if ( !current_user_can( 'edit_pages' ) )
253                         return new WP_Error( 'edit_pages', __( 'You are not allowed to create pages on this blog.' ) );
254         } else {
255                 if ( !current_user_can( 'edit_posts' ) )
256                         return new WP_Error( 'edit_posts', __( 'You are not allowed to create posts or drafts on this blog.' ) );
257         }
258
259
260         // Check for autosave collisions
261         $temp_id = false;
262         if ( isset($_POST['temp_ID']) ) {
263                 $temp_id = (int) $_POST['temp_ID'];
264                 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
265                         $draft_ids = array();
266                 foreach ( $draft_ids as $temp => $real )
267                         if ( time() + $temp > 86400 ) // 1 day: $temp is equal to -1 * time( then )
268                                 unset($draft_ids[$temp]);
269
270                 if ( isset($draft_ids[$temp_id]) ) { // Edit, don't write
271                         $_POST['post_ID'] = $draft_ids[$temp_id];
272                         unset($_POST['temp_ID']);
273                         update_user_option( $user_ID, 'autosave_draft_ids', $draft_ids );
274                         return edit_post();
275                 }
276         }
277
278         $translated = _wp_translate_postdata( false );
279         if ( is_wp_error($translated) )
280                 return $translated;
281
282         // Create the post.
283         $post_ID = wp_insert_post( $_POST );
284         if ( is_wp_error( $post_ID ) )
285                 return $post_ID;
286
287         if ( empty($post_ID) )
288                 return 0;
289
290         add_meta( $post_ID );
291
292         // Reunite any orphaned attachments with their parent
293         if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
294                 $draft_ids = array();
295         if ( $draft_temp_id = (int) array_search( $post_ID, $draft_ids ) )
296                 _relocate_children( $draft_temp_id, $post_ID );
297         if ( $temp_id && $temp_id != $draft_temp_id )
298                 _relocate_children( $temp_id, $post_ID );
299
300         // Update autosave collision detection
301         if ( $temp_id ) {
302                 $draft_ids[$temp_id] = $post_ID;
303                 update_user_option( $user_ID, 'autosave_draft_ids', $draft_ids );
304         }
305
306         // Now that we have an ID we can fix any attachment anchor hrefs
307         _fix_attachment_links( $post_ID );
308
309         wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
310
311         return $post_ID;
312 }
313
314 function write_post() {
315         $result = wp_write_post();
316         if( is_wp_error( $result ) )
317                 wp_die( $result->get_error_message() );
318         else
319                 return $result;
320 }
321
322 //
323 // Post Meta
324 //
325
326 function add_meta( $post_ID ) {
327         global $wpdb;
328         $post_ID = (int) $post_ID;
329
330         $protected = array( '_wp_attached_file', '_wp_attachment_metadata', '_wp_old_slug', '_wp_page_template' );
331
332         $metakeyselect = $wpdb->escape( stripslashes( trim( $_POST['metakeyselect'] ) ) );
333         $metakeyinput = $wpdb->escape( stripslashes( trim( $_POST['metakeyinput'] ) ) );
334         $metavalue = maybe_serialize( stripslashes( (trim( $_POST['metavalue'] ) ) ));
335         $metavalue = $wpdb->escape( $metavalue );
336
337         if ( ('0' === $metavalue || !empty ( $metavalue ) ) && ((('#NONE#' != $metakeyselect) && !empty ( $metakeyselect) ) || !empty ( $metakeyinput) ) ) {
338                 // We have a key/value pair. If both the select and the
339                 // input for the key have data, the input takes precedence:
340
341                 if ('#NONE#' != $metakeyselect)
342                         $metakey = $metakeyselect;
343
344                 if ( $metakeyinput)
345                         $metakey = $metakeyinput; // default
346
347                 if ( in_array($metakey, $protected) )
348                         return false;
349
350                 wp_cache_delete($post_ID, 'post_meta');
351
352                 $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->postmeta 
353                         (post_id,meta_key,meta_value ) VALUES (%s, %s, %s)",
354                         $post_ID, $metakey, $metavalue) );
355                 return $wpdb->insert_id;
356         }
357         return false;
358 } // add_meta
359
360 function delete_meta( $mid ) {
361         global $wpdb;
362         $mid = (int) $mid;
363
364         $post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
365         wp_cache_delete($post_id, 'post_meta');
366
367         return $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
368 }
369
370 // Get a list of previously defined keys
371 function get_meta_keys() {
372         global $wpdb;
373
374         $keys = $wpdb->get_col( "
375                         SELECT meta_key
376                         FROM $wpdb->postmeta
377                         GROUP BY meta_key
378                         ORDER BY meta_key" );
379
380         return $keys;
381 }
382
383 function get_post_meta_by_id( $mid ) {
384         global $wpdb;
385         $mid = (int) $mid;
386
387         $meta = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
388         if ( is_serialized_string( $meta->meta_value ) )
389                 $meta->meta_value = maybe_unserialize( $meta->meta_value );
390         return $meta;
391 }
392
393 // Some postmeta stuff
394 function has_meta( $postid ) {
395         global $wpdb;
396
397         return $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value, meta_id, post_id
398                         FROM $wpdb->postmeta WHERE post_id = %d
399                         ORDER BY meta_key,meta_id", $postid), ARRAY_A );
400
401 }
402
403 function update_meta( $meta_id, $meta_key, $meta_value ) {
404         global $wpdb;
405
406         $protected = array( '_wp_attached_file', '_wp_attachment_metadata', '_wp_old_slug', '_wp_page_template' );
407
408         if ( in_array($meta_key, $protected) )
409                 return false;
410
411         $post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_id = %d", $meta_id) );
412         wp_cache_delete($post_id, 'post_meta');
413
414         $meta_value = maybe_serialize( stripslashes( $meta_value ));
415         $meta_id = (int) $meta_id;
416         
417         $data  = compact( 'meta_key', 'meta_value' );
418         $where = compact( 'meta_id' );
419
420         return $wpdb->update( $wpdb->postmeta, $data, $where );
421 }
422
423 //
424 // Private
425 //
426
427 // Replace hrefs of attachment anchors with up-to-date permalinks.
428 function _fix_attachment_links( $post_ID ) {
429
430         $post = & get_post( $post_ID, ARRAY_A );
431
432         $search = "#<a[^>]+rel=('|\")[^'\"]*attachment[^>]*>#ie";
433
434         // See if we have any rel="attachment" links
435         if ( 0 == preg_match_all( $search, $post['post_content'], $anchor_matches, PREG_PATTERN_ORDER ) )
436                 return;
437
438         $i = 0;
439         $search = "#[\s]+rel=(\"|')(.*?)wp-att-(\d+)\\1#i";
440         foreach ( $anchor_matches[0] as $anchor ) {
441                 if ( 0 == preg_match( $search, $anchor, $id_matches ) )
442                         continue;
443
444                 $id = (int) $id_matches[3];
445
446                 // While we have the attachment ID, let's adopt any orphans.
447                 $attachment = & get_post( $id, ARRAY_A );
448                 if ( ! empty( $attachment) && ! is_object( get_post( $attachment['post_parent'] ) ) ) {
449                         $attachment['post_parent'] = $post_ID;
450                         // Escape data pulled from DB.
451                         $attachment = add_magic_quotes( $attachment);
452                         wp_update_post( $attachment);
453                 }
454
455                 $post_search[$i] = $anchor;
456                 $post_replace[$i] = preg_replace( "#href=(\"|')[^'\"]*\\1#e", "stripslashes( 'href=\\1' ).get_attachment_link( $id ).stripslashes( '\\1' )", $anchor );
457                 ++$i;
458         }
459
460         $post['post_content'] = str_replace( $post_search, $post_replace, $post['post_content'] );
461
462         // Escape data pulled from DB.
463         $post = add_magic_quotes( $post);
464
465         return wp_update_post( $post);
466 }
467
468 // Move child posts to a new parent
469 function _relocate_children( $old_ID, $new_ID ) {
470         global $wpdb;
471         $old_ID = (int) $old_ID;
472         $new_ID = (int) $new_ID;
473         return $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET post_parent = %d WHERE post_parent = %d", $new_ID, $old_ID) );
474 }
475
476 function get_available_post_statuses($type = 'post') {
477         $stati = wp_count_posts($type);
478
479         return array_keys(get_object_vars($stati));
480 }
481
482 function wp_edit_posts_query( $q = false ) {
483         global $wpdb;
484         if ( false === $q )
485                 $q = $_GET;
486         $q['m']   = (int) $q['m'];
487         $q['cat'] = (int) $q['cat'];
488         $post_stati  = array(   //      array( adj, noun )
489                                 'publish' => array(__('Published'), __('Published posts'), __ngettext_noop('Published (%s)', 'Published (%s)')),
490                                 'future' => array(__('Scheduled'), __('Scheduled posts'), __ngettext_noop('Scheduled (%s)', 'Scheduled (%s)')),
491                                 'pending' => array(__('Pending Review'), __('Pending posts'), __ngettext_noop('Pending Review (%s)', 'Pending Review (%s)')),
492                                 'draft' => array(__('Draft'), _c('Drafts|manage posts header'), __ngettext_noop('Draft (%s)', 'Drafts (%s)')),
493                                 'private' => array(__('Private'), __('Private posts'), __ngettext_noop('Private (%s)', 'Private (%s)')),
494                         );
495
496         $post_stati = apply_filters('post_stati', $post_stati);
497
498         $avail_post_stati = get_available_post_statuses('post');
499
500         $post_status_q = '';
501         if ( isset($q['post_status']) && in_array( $q['post_status'], array_keys($post_stati) ) ) {
502                 $post_status_q = '&post_status=' . $q['post_status'];
503                 $post_status_q .= '&perm=readable';
504         }
505
506         if ( 'pending' === $q['post_status'] ) {
507                 $order = 'ASC';
508                 $orderby = 'modified';
509         } elseif ( 'draft' === $q['post_status'] ) {
510                 $order = 'DESC';
511                 $orderby = 'modified';
512         } else {
513                 $order = 'DESC';
514                 $orderby = 'date';
515         }
516
517         wp("post_type=post&what_to_show=posts$post_status_q&posts_per_page=15&order=$order&orderby=$orderby");
518
519         return array($post_stati, $avail_post_stati);
520 }
521
522 function get_available_post_mime_types($type = 'attachment') {
523         global $wpdb;
524
525         $types = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT post_mime_type FROM $wpdb->posts WHERE post_type = %s", $type));
526         return $types;
527 }
528
529 function wp_edit_attachments_query( $q = false ) {
530         global $wpdb;
531         if ( false === $q )
532                 $q = $_GET;
533         $q['m']   = (int) $q['m'];
534         $q['cat'] = (int) $q['cat'];
535         $q['post_type'] = 'attachment';
536         $q['post_status'] = 'any';
537         $q['posts_per_page'] = 15;
538         $post_mime_types = array(       //      array( adj, noun )
539                                 'image' => array(__('Images'), __('Manage Images'), __ngettext_noop('Image (%s)', 'Images (%s)')),
540                                 'audio' => array(__('Audio'), __('Manage Audio'), __ngettext_noop('Audio (%s)', 'Audio (%s)')),
541                                 'video' => array(__('Video'), __('Manage Video'), __ngettext_noop('Video (%s)', 'Video (%s)')),
542                         );
543         $post_mime_types = apply_filters('post_mime_types', $post_mime_types);
544
545         $avail_post_mime_types = get_available_post_mime_types('attachment');
546
547         if ( isset($q['post_mime_type']) && !array_intersect( (array) $q['post_mime_type'], array_keys($post_mime_types) ) )
548                 unset($q['post_mime_type']);
549
550         wp($q);
551
552         return array($post_mime_types, $avail_post_mime_types);
553 }
554
555 function postbox_classes( $id, $page ) {
556         $current_user = wp_get_current_user();
557         if ( $closed = get_usermeta( $current_user->ID, 'closedpostboxes_'.$page ) ) {
558                 if ( !is_array( $closed ) ) return '';
559                 return in_array( $id, $closed )? 'if-js-closed' : '';
560         } else {
561                 if ( 'tagsdiv' == $id || 'categorydiv' == $id ) return '';
562                 else return 'if-js-closed';
563         }
564 }
565
566 function get_sample_permalink($id, $title=null, $name = null) {
567         $post = &get_post($id);
568         if (!$post->ID) {
569                 return array('', '');
570         }
571         $original_status = $post->post_status;
572         $original_date = $post->post_date;
573         $original_name = $post->post_name;
574
575         // Hack: get_permalink would return ugly permalink for
576         // drafts, so we will fake, that our post is published
577         if (in_array($post->post_status, array('draft', 'pending'))) {
578                 $post->post_status = 'publish';
579                 $post->post_date = date('Y-m-d H:i:s');
580                 $post->post_name = sanitize_title($post->post_name? $post->post_name : $post->post_title, $post->ID); 
581         }
582
583         // If the user wants to set a new name -- override the current one
584         // Note: if empty name is supplied -- use the title instead, see #6072
585         if (!is_null($name)) {
586                 $post->post_name = sanitize_title($name? $name : $title, $post->ID);
587         }
588
589         $permalink = get_permalink($post, true);
590
591         // Handle page hierarchy
592         if ( 'page' == $post->post_type ) {
593                 $uri = get_page_uri($post->ID);
594                 $uri = untrailingslashit($uri);
595                 $uri = strrev( stristr( strrev( $uri ), '/' ) );
596                 $uri = untrailingslashit($uri);
597                 if ( !empty($uri) )
598                         $uri .='/';
599                 $permalink = str_replace('%pagename%', "${uri}%pagename%", $permalink);
600         }
601
602         $permalink = array($permalink, apply_filters('editable_slug', $post->post_name));
603         $post->post_status = $original_status;
604         $post->post_date = $original_date;
605         $post->post_name = $original_name;
606         return $permalink;
607 }
608
609 function get_sample_permalink_html($id, $new_title=null, $new_slug=null) {
610         $post = &get_post($id);
611         list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug);
612         if (false === strpos($permalink, '%postname%') && false === strpos($permalink, '%pagename%')) {
613                 return '';
614         }
615         $title = __('Click to edit this part of the permalink');
616         if (strlen($post_name) > 30) {
617                 $post_name_abridged = substr($post_name, 0, 14). '&hellip;' . substr($post_name, -14);
618         } else {
619                 $post_name_abridged = $post_name;
620         }
621         $post_name_html = '<span id="editable-post-name" title="'.$title.'">'.$post_name_abridged.'</span><span id="editable-post-name-full">'.$post_name.'</span>';
622         $display_link = str_replace(array('%pagename%','%postname%'), $post_name_html, $permalink);
623         $return = '<strong>' . __('Permalink:') . "</strong>\n" . '<span id="sample-permalink">' . $display_link . "</span>\n";
624         $return .= '<span id="edit-slug-buttons"><a href="#post_name" class="edit-slug" onclick="edit_permalink(' . $id . '); return false;">' . __('Edit') . "</a></span>\n";
625         return $return;
626 }
627
628 // false: not locked or locked by current user
629 // int: user ID of user with lock
630 function wp_check_post_lock( $post_id ) {
631         global $current_user;
632
633         if ( !$post = get_post( $post_id ) )
634                 return false;
635
636         $lock = get_post_meta( $post->ID, '_edit_lock', true );
637         $last = get_post_meta( $post->ID, '_edit_last', true );
638
639         $time_window = apply_filters( 'wp_check_post_lock_window', AUTOSAVE_INTERVAL * 2 );
640
641         if ( $lock && $lock > time() - $time_window && $last != $current_user->ID )
642                 return $last;
643         return false;
644 }
645
646 function wp_set_post_lock( $post_id ) {
647         global $current_user;
648         if ( !$post = get_post( $post_id ) )
649                 return false;
650         if ( !$current_user || !$current_user->ID )
651                 return false;
652
653         $now = time();
654
655         if ( !add_post_meta( $post->ID, '_edit_lock', $now, true ) )
656                 update_post_meta( $post->ID, '_edit_lock', $now );
657         if ( !add_post_meta( $post->ID, '_edit_last', $current_user->ID, true ) )
658                 update_post_meta( $post->ID, '_edit_last', $current_user->ID );
659 }
660
661 /**
662  * wp_create_post_autosave() - creates autosave data for the specified post from $_POST data
663  *
664  * @package WordPress
665  * @subpackage Post Revisions
666  * @since 2.6
667  *
668  * @uses _wp_translate_postdata()
669  * @uses _wp_post_revision_fields()
670  */
671 function wp_create_post_autosave( $post_id ) {
672         $translated = _wp_translate_postdata( true );
673         if ( is_wp_error( $translated ) )
674                 return $translated;
675
676         // Only store one autosave.  If there is already an autosave, overwrite it.
677         if ( $old_autosave = wp_get_post_autosave( $post_id ) ) {
678                 $new_autosave = _wp_post_revision_fields( $_POST, true );
679                 $new_autosave['ID'] = $old_autosave->ID;
680                 return wp_update_post( $new_autosave );
681         }
682
683         // Otherwise create the new autosave as a special post revision
684         return _wp_put_post_revision( $_POST, true );
685 }