Make WordPress Core

Ticket #18150: post.php

File post.php, 60.4 KB (added by kaptinlin, 15 years ago)

wp-admin\includes\post.php

Line 
1<?php
2/**
3 * WordPress Post Administration API.
4 *
5 * @package WordPress
6 * @subpackage Administration
7 */
8
9/**
10 * Rename $_POST data from form names to DB post columns.
11 *
12 * Manipulates $_POST directly.
13 *
14 * @package WordPress
15 * @since 2.6.0
16 *
17 * @param bool $update Are we updating a pre-existing post?
18 * @param array $post_data Array of post data. Defaults to the contents of $_POST.
19 * @return object|bool WP_Error on failure, true on success.
20 */
21function _wp_translate_postdata( $update = false, $post_data = null ) {
22
23 if ( empty($post_data) )
24 $post_data = &$_POST;
25
26 if ( $update )
27 $post_data['ID'] = (int) $post_data['post_ID'];
28
29 if ( isset( $post_data['content'] ) )
30 $post_data['post_content'] = $post_data['content'];
31
32 if ( isset( $post_data['excerpt'] ) )
33 $post_data['post_excerpt'] = $post_data['excerpt'];
34
35 if ( isset( $post_data['parent_id'] ) )
36 $post_data['post_parent'] = (int) $post_data['parent_id'];
37
38 if ( isset($post_data['trackback_url']) )
39 $post_data['to_ping'] = $post_data['trackback_url'];
40
41 if ( !isset($post_data['user_ID']) )
42 $post_data['user_ID'] = $GLOBALS['user_ID'];
43
44 if (!empty ( $post_data['post_author_override'] ) ) {
45 $post_data['post_author'] = (int) $post_data['post_author_override'];
46 } else {
47 if (!empty ( $post_data['post_author'] ) ) {
48 $post_data['post_author'] = (int) $post_data['post_author'];
49 } else {
50 $post_data['post_author'] = (int) $post_data['user_ID'];
51 }
52 }
53
54 $ptype = get_post_type_object( $post_data['post_type'] );
55 if ( isset($post_data['user_ID']) && ($post_data['post_author'] != $post_data['user_ID']) ) {
56 if ( !current_user_can( $ptype->cap->edit_others_posts ) ) {
57 if ( 'page' == $post_data['post_type'] ) {
58 return new WP_Error( 'edit_others_pages', $update ?
59 __( 'You are not allowed to edit pages as this user.' ) :
60 __( 'You are not allowed to create pages as this user.' )
61 );
62 } else {
63 return new WP_Error( 'edit_others_posts', $update ?
64 __( 'You are not allowed to edit posts as this user.' ) :
65 __( 'You are not allowed to post as this user.' )
66 );
67 }
68 }
69 }
70
71 // What to do based on which button they pressed
72 if ( isset($post_data['saveasdraft']) && '' != $post_data['saveasdraft'] )
73 $post_data['post_status'] = 'draft';
74 if ( isset($post_data['saveasprivate']) && '' != $post_data['saveasprivate'] )
75 $post_data['post_status'] = 'private';
76 if ( isset($post_data['publish']) && ( '' != $post_data['publish'] ) && ( !isset($post_data['post_status']) || $post_data['post_status'] != 'private' ) )
77 $post_data['post_status'] = 'publish';
78 if ( isset($post_data['advanced']) && '' != $post_data['advanced'] )
79 $post_data['post_status'] = 'draft';
80 if ( isset($post_data['pending']) && '' != $post_data['pending'] )
81 $post_data['post_status'] = 'pending';
82
83 if ( isset( $post_data['ID'] ) )
84 $post_id = $post_data['ID'];
85 else
86 $post_id = false;
87 $previous_status = $post_id ? get_post_field( 'post_status', $post_id ) : false;
88
89 // Posts 'submitted for approval' present are submitted to $_POST the same as if they were being published.
90 // Change status from 'publish' to 'pending' if user lacks permissions to publish or to resave published posts.
91 if ( isset($post_data['post_status']) && ('publish' == $post_data['post_status'] && !current_user_can( $ptype->cap->publish_posts )) )
92 if ( $previous_status != 'publish' || !current_user_can( 'edit_post', $post_id ) )
93 $post_data['post_status'] = 'pending';
94
95 if ( ! isset($post_data['post_status']) )
96 $post_data['post_status'] = $previous_status;
97
98 if (!isset( $post_data['comment_status'] ))
99 $post_data['comment_status'] = 'closed';
100
101 if (!isset( $post_data['ping_status'] ))
102 $post_data['ping_status'] = 'closed';
103
104 foreach ( array('aa', 'mm', 'jj', 'hh', 'mn') as $timeunit ) {
105 if ( !empty( $post_data['hidden_' . $timeunit] ) && $post_data['hidden_' . $timeunit] != $post_data[$timeunit] ) {
106 $post_data['edit_date'] = '1';
107 break;
108 }
109 }
110
111 if ( !empty( $post_data['edit_date'] ) ) {
112 $aa = $post_data['aa'];
113 $mm = $post_data['mm'];
114 $jj = $post_data['jj'];
115 $hh = $post_data['hh'];
116 $mn = $post_data['mn'];
117 $ss = $post_data['ss'];
118 $aa = ($aa <= 0 ) ? date('Y') : $aa;
119 $mm = ($mm <= 0 ) ? date('n') : $mm;
120 $jj = ($jj > 31 ) ? 31 : $jj;
121 $jj = ($jj <= 0 ) ? date('j') : $jj;
122 $hh = ($hh > 23 ) ? $hh -24 : $hh;
123 $mn = ($mn > 59 ) ? $mn -60 : $mn;
124 $ss = ($ss > 59 ) ? $ss -60 : $ss;
125 $post_data['post_date'] = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss );
126 $post_data['post_date_gmt'] = get_gmt_from_date( $post_data['post_date'] );
127 }
128
129 return $post_data;
130}
131
132/**
133 * Update an existing post with values provided in $_POST.
134 *
135 * @since 1.5.0
136 *
137 * @param array $post_data Optional.
138 * @return int Post ID.
139 */
140function edit_post( $post_data = null ) {
141
142 if ( empty($post_data) )
143 $post_data = &$_POST;
144
145 // Clear out any data in internal vars.
146 unset( $post_data['filter'] );
147
148 $post_ID = (int) $post_data['post_ID'];
149 $post = get_post( $post_ID );
150 $post_data['post_type'] = $post->post_type;
151 $post_data['post_mime_type'] = $post->post_mime_type;
152
153 $ptype = get_post_type_object($post_data['post_type']);
154 if ( !current_user_can( $ptype->cap->edit_post, $post_ID ) ) {
155 if ( 'page' == $post_data['post_type'] )
156 wp_die( __('You are not allowed to edit this page.' ));
157 else
158 wp_die( __('You are not allowed to edit this post.' ));
159 }
160
161 // Autosave shouldn't save too soon after a real save
162 if ( 'autosave' == $post_data['action'] ) {
163 $post =& get_post( $post_ID );
164 $now = time();
165 $then = strtotime($post->post_date_gmt . ' +0000');
166 $delta = AUTOSAVE_INTERVAL / 2;
167 if ( ($now - $then) < $delta )
168 return $post_ID;
169 }
170
171 $post_data = _wp_translate_postdata( true, $post_data );
172 if ( is_wp_error($post_data) )
173 wp_die( $post_data->get_error_message() );
174 if ( 'autosave' != $post_data['action'] && 'auto-draft' == $post_data['post_status'] )
175 $post_data['post_status'] = 'draft';
176
177 if ( isset($post_data['visibility']) ) {
178 switch ( $post_data['visibility'] ) {
179 case 'public' :
180 $post_data['post_password'] = '';
181 break;
182 case 'password' :
183 unset( $post_data['sticky'] );
184 break;
185 case 'private' :
186 $post_data['post_status'] = 'private';
187 $post_data['post_password'] = '';
188 unset( $post_data['sticky'] );
189 break;
190 }
191 }
192
193 // Post Formats
194 if ( current_theme_supports( 'post-formats' ) && isset( $post_data['post_format'] ) ) {
195 $formats = get_theme_support( 'post-formats' );
196 if ( is_array( $formats ) ) {
197 $formats = $formats[0];
198 if ( in_array( $post_data['post_format'], $formats ) ) {
199 set_post_format( $post_ID, $post_data['post_format'] );
200 } elseif ( '0' == $post_data['post_format'] ) {
201 set_post_format( $post_ID, false );
202 }
203 }
204 }
205
206 // Meta Stuff
207 if ( isset($post_data['meta']) && $post_data['meta'] ) {
208 foreach ( $post_data['meta'] as $key => $value ) {
209 if ( !$meta = get_post_meta_by_id( $key ) )
210 continue;
211 if ( $meta->post_id != $post_ID )
212 continue;
213 if ( is_protected_meta( $value['key'] ) )
214 continue;
215 update_meta( $key, $value['key'], $value['value'] );
216 }
217 }
218
219 if ( isset($post_data['deletemeta']) && $post_data['deletemeta'] ) {
220 foreach ( $post_data['deletemeta'] as $key => $value ) {
221 if ( !$meta = get_post_meta_by_id( $key ) )
222 continue;
223 if ( $meta->post_id != $post_ID )
224 continue;
225 if ( is_protected_meta( $meta->meta_key ) )
226 continue;
227 delete_meta( $key );
228 }
229 }
230
231 add_meta( $post_ID );
232
233 update_post_meta( $post_ID, '_edit_last', $GLOBALS['current_user']->ID );
234
235 wp_update_post( $post_data );
236
237 // Reunite any orphaned attachments with their parent
238 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
239 $draft_ids = array();
240 if ( $draft_temp_id = (int) array_search( $post_ID, $draft_ids ) )
241 _relocate_children( $draft_temp_id, $post_ID );
242
243 // Now that we have an ID we can fix any attachment anchor hrefs
244 _fix_attachment_links( $post_ID );
245
246 wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
247
248 if ( current_user_can( $ptype->cap->edit_others_posts ) ) {
249 if ( ! empty( $post_data['sticky'] ) )
250 stick_post( $post_ID );
251 else
252 unstick_post( $post_ID );
253 }
254
255 return $post_ID;
256}
257
258/**
259 * Process the post data for the bulk editing of posts.
260 *
261 * Updates all bulk edited posts/pages, adding (but not removing) tags and
262 * categories. Skips pages when they would be their own parent or child.
263 *
264 * @since 2.7.0
265 *
266 * @param array $post_data Optional, the array of post data to process if not provided will use $_POST superglobal.
267 * @return array
268 */
269function bulk_edit_posts( $post_data = null ) {
270 global $wpdb;
271
272 if ( empty($post_data) )
273 $post_data = &$_POST;
274
275 if ( isset($post_data['post_type']) )
276 $ptype = get_post_type_object($post_data['post_type']);
277 else
278 $ptype = get_post_type_object('post');
279
280 if ( !current_user_can( $ptype->cap->edit_posts ) ) {
281 if ( 'page' == $ptype->name )
282 wp_die( __('You are not allowed to edit pages.'));
283 else
284 wp_die( __('You are not allowed to edit posts.'));
285 }
286
287 if ( -1 == $post_data['_status'] ) {
288 $post_data['post_status'] = null;
289 unset($post_data['post_status']);
290 } else {
291 $post_data['post_status'] = $post_data['_status'];
292 }
293 unset($post_data['_status']);
294
295 $post_IDs = array_map( 'intval', (array) $post_data['post'] );
296
297 $reset = array( 'post_author', 'post_status', 'post_password', 'post_parent', 'page_template', 'comment_status', 'ping_status', 'keep_private', 'tax_input', 'post_category', 'sticky' );
298 foreach ( $reset as $field ) {
299 if ( isset($post_data[$field]) && ( '' == $post_data[$field] || -1 == $post_data[$field] ) )
300 unset($post_data[$field]);
301 }
302
303 if ( isset($post_data['post_category']) ) {
304 if ( is_array($post_data['post_category']) && ! empty($post_data['post_category']) )
305 $new_cats = array_map( 'absint', $post_data['post_category'] );
306 else
307 unset($post_data['post_category']);
308 }
309
310 $tax_input = array();
311 if ( isset($post_data['tax_input'])) {
312 foreach ( $post_data['tax_input'] as $tax_name => $terms ) {
313 if ( empty($terms) )
314 continue;
315 if ( is_taxonomy_hierarchical( $tax_name ) )
316 $tax_input[$tax_name] = array_map( 'absint', $terms );
317 else {
318 $tax_input[$tax_name] = preg_replace( '/\s*,\s*/', ',', rtrim( trim($terms), ' ,' ) );
319 $tax_input[$tax_name] = explode(',', $tax_input[$tax_name]);
320 }
321 }
322 }
323
324 if ( isset($post_data['post_parent']) && ($parent = (int) $post_data['post_parent']) ) {
325 $pages = $wpdb->get_results("SELECT ID, post_parent FROM $wpdb->posts WHERE post_type = 'page'");
326 $children = array();
327
328 for ( $i = 0; $i < 50 && $parent > 0; $i++ ) {
329 $children[] = $parent;
330
331 foreach ( $pages as $page ) {
332 if ( $page->ID == $parent ) {
333 $parent = $page->post_parent;
334 break;
335 }
336 }
337 }
338 }
339
340 $updated = $skipped = $locked = array();
341 foreach ( $post_IDs as $post_ID ) {
342 $post_type_object = get_post_type_object( get_post_type( $post_ID ) );
343
344 if ( !isset( $post_type_object ) || ( isset($children) && in_array($post_ID, $children) ) || !current_user_can( $post_type_object->cap->edit_post, $post_ID ) ) {
345 $skipped[] = $post_ID;
346 continue;
347 }
348
349 if ( wp_check_post_lock( $post_ID ) ) {
350 $locked[] = $post_ID;
351 continue;
352 }
353
354 $post = get_post( $post_ID );
355 $tax_names = get_object_taxonomies( $post );
356 foreach ( $tax_names as $tax_name ) {
357 $taxonomy_obj = get_taxonomy($tax_name);
358 if ( isset( $tax_input[$tax_name]) && current_user_can( $taxonomy_obj->cap->assign_terms ) )
359 $new_terms = $tax_input[$tax_name];
360 else
361 $new_terms = array();
362
363 if ( $taxonomy_obj->hierarchical )
364 $current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array('fields' => 'ids') );
365 else
366 $current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array('fields' => 'names') );
367
368 $post_data['tax_input'][$tax_name] = array_merge( $current_terms, $new_terms );
369 }
370
371 if ( isset($new_cats) && in_array( 'category', $tax_names ) ) {
372 $cats = (array) wp_get_post_categories($post_ID);
373 $post_data['post_category'] = array_unique( array_merge($cats, $new_cats) );
374 unset( $post_data['tax_input']['category'] );
375 }
376
377 $post_data['post_mime_type'] = $post->post_mime_type;
378 $post_data['guid'] = $post->guid;
379
380 $post_data['ID'] = $post_ID;
381 $updated[] = wp_update_post( $post_data );
382
383 if ( isset( $post_data['sticky'] ) && current_user_can( $ptype->cap->edit_others_posts ) ) {
384 if ( 'sticky' == $post_data['sticky'] )
385 stick_post( $post_ID );
386 else
387 unstick_post( $post_ID );
388 }
389
390 }
391
392 return array( 'updated' => $updated, 'skipped' => $skipped, 'locked' => $locked );
393}
394
395/**
396 * Default post information to use when populating the "Write Post" form.
397 *
398 * @since 2.0.0
399 *
400 * @param string $post_type A post type string, defaults to 'post'.
401 * @return object stdClass object containing all the default post data as attributes
402 */
403function get_default_post_to_edit( $post_type = 'post', $create_in_db = false ) {
404 global $wpdb;
405
406 $post_title = '';
407 if ( !empty( $_REQUEST['post_title'] ) )
408 $post_title = esc_html( stripslashes( $_REQUEST['post_title'] ));
409
410 $post_content = '';
411 if ( !empty( $_REQUEST['content'] ) )
412 $post_content = esc_html( stripslashes( $_REQUEST['content'] ));
413
414 $post_excerpt = '';
415 if ( !empty( $_REQUEST['excerpt'] ) )
416 $post_excerpt = esc_html( stripslashes( $_REQUEST['excerpt'] ));
417
418 if ( $create_in_db ) {
419 // Cleanup old auto-drafts more than 7 days old
420 $old_posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_status = 'auto-draft' AND DATE_SUB( NOW(), INTERVAL 7 DAY ) > post_date" );
421 foreach ( (array) $old_posts as $delete )
422 wp_delete_post( $delete, true ); // Force delete
423 $post_id = wp_insert_post( array( 'post_title' => __( 'Auto Draft' ), 'post_type' => $post_type, 'post_status' => 'auto-draft' ) );
424 $post = get_post( $post_id );
425 if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post->post_type, 'post-formats' ) && get_option( 'default_post_format' ) )
426 set_post_format( $post, get_option( 'default_post_format' ) );
427 } else {
428 $post->ID = 0;
429 $post->post_author = '';
430 $post->post_date = '';
431 $post->post_date_gmt = '';
432 $post->post_password = '';
433 $post->post_type = $post_type;
434 $post->post_status = 'draft';
435 $post->to_ping = '';
436 $post->pinged = '';
437 $post->comment_status = get_option( 'default_comment_status' );
438 $post->ping_status = get_option( 'default_ping_status' );
439 $post->post_pingback = get_option( 'default_pingback_flag' );
440 $post->post_category = get_option( 'default_category' );
441 $post->page_template = 'default';
442 $post->post_parent = 0;
443 $post->menu_order = 0;
444 }
445
446 $post->post_content = apply_filters( 'default_content', $post_content, $post );
447 $post->post_title = apply_filters( 'default_title', $post_title, $post );
448 $post->post_excerpt = apply_filters( 'default_excerpt', $post_excerpt, $post );
449 $post->post_name = '';
450
451 return $post;
452}
453
454/**
455 * Get the default page information to use.
456 *
457 * @since 2.5.0
458 *
459 * @return object stdClass object containing all the default post data as attributes
460 */
461function get_default_page_to_edit() {
462 $page = get_default_post_to_edit();
463 $page->post_type = 'page';
464 return $page;
465}
466
467/**
468 * Get an existing post and format it for editing.
469 *
470 * @since 2.0.0
471 *
472 * @param unknown_type $id
473 * @return unknown
474 */
475function get_post_to_edit( $id ) {
476
477 $post = get_post( $id, OBJECT, 'edit' );
478
479 if ( $post->post_type == 'page' )
480 $post->page_template = get_post_meta( $id, '_wp_page_template', true );
481
482 return $post;
483}
484
485/**
486 * Determine if a post exists based on title, content, and date
487 *
488 * @since 2.0.0
489 *
490 * @param string $title Post title
491 * @param string $content Optional post content
492 * @param string $date Optional post date
493 * @return int Post ID if post exists, 0 otherwise.
494 */
495function post_exists($title, $content = '', $date = '') {
496 global $wpdb;
497
498 $post_title = stripslashes( sanitize_post_field( 'post_title', $title, 0, 'db' ) );
499 $post_content = stripslashes( sanitize_post_field( 'post_content', $content, 0, 'db' ) );
500 $post_date = stripslashes( sanitize_post_field( 'post_date', $date, 0, 'db' ) );
501
502 $query = "SELECT ID FROM $wpdb->posts WHERE 1=1";
503 $args = array();
504
505 if ( !empty ( $date ) ) {
506 $query .= ' AND post_date = %s';
507 $args[] = $post_date;
508 }
509
510 if ( !empty ( $title ) ) {
511 $query .= ' AND post_title = %s';
512 $args[] = $post_title;
513 }
514
515 if ( !empty ( $content ) ) {
516 $query .= 'AND post_content = %s';
517 $args[] = $post_content;
518 }
519
520 if ( !empty ( $args ) )
521 return $wpdb->get_var( $wpdb->prepare($query, $args) );
522
523 return 0;
524}
525
526/**
527 * Creates a new post from the "Write Post" form using $_POST information.
528 *
529 * @since 2.1.0
530 *
531 * @return unknown
532 */
533function wp_write_post() {
534 global $user_ID;
535
536
537 if ( isset($_POST['post_type']) )
538 $ptype = get_post_type_object($_POST['post_type']);
539 else
540 $ptype = get_post_type_object('post');
541
542 if ( !current_user_can( $ptype->cap->edit_posts ) ) {
543 if ( 'page' == $ptype->name )
544 return new WP_Error( 'edit_pages', __( 'You are not allowed to create pages on this site.' ) );
545 else
546 return new WP_Error( 'edit_posts', __( 'You are not allowed to create posts or drafts on this site.' ) );
547 }
548
549 $_POST['post_mime_type'] = '';
550
551 // Clear out any data in internal vars.
552 unset( $_POST['filter'] );
553
554 // Check for autosave collisions
555 // Does this need to be updated? ~ Mark
556 $temp_id = false;
557 if ( isset($_POST['temp_ID']) ) {
558 $temp_id = (int) $_POST['temp_ID'];
559 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
560 $draft_ids = array();
561 foreach ( $draft_ids as $temp => $real )
562 if ( time() + $temp > 86400 ) // 1 day: $temp is equal to -1 * time( then )
563 unset($draft_ids[$temp]);
564
565 if ( isset($draft_ids[$temp_id]) ) { // Edit, don't write
566 $_POST['post_ID'] = $draft_ids[$temp_id];
567 unset($_POST['temp_ID']);
568 update_user_option( $user_ID, 'autosave_draft_ids', $draft_ids );
569 return edit_post();
570 }
571 }
572
573 // Edit don't write if we have a post id.
574 if ( isset( $_POST['ID'] ) ) {
575 $_POST['post_ID'] = $_POST['ID'];
576 unset ( $_POST['ID'] );
577 }
578 if ( isset( $_POST['post_ID'] ) ) {
579 return edit_post();
580 }
581
582 $translated = _wp_translate_postdata( false );
583 if ( is_wp_error($translated) )
584 return $translated;
585
586 if ( isset($_POST['visibility']) ) {
587 switch ( $_POST['visibility'] ) {
588 case 'public' :
589 $_POST['post_password'] = '';
590 break;
591 case 'password' :
592 unset( $_POST['sticky'] );
593 break;
594 case 'private' :
595 $_POST['post_status'] = 'private';
596 $_POST['post_password'] = '';
597 unset( $_POST['sticky'] );
598 break;
599 }
600 }
601
602 // Create the post.
603 $post_ID = wp_insert_post( $_POST );
604 if ( is_wp_error( $post_ID ) )
605 return $post_ID;
606
607 if ( empty($post_ID) )
608 return 0;
609
610 add_meta( $post_ID );
611
612 add_post_meta( $post_ID, '_edit_last', $GLOBALS['current_user']->ID );
613
614 // Reunite any orphaned attachments with their parent
615 // Does this need to be udpated? ~ Mark
616 if ( !$draft_ids = get_user_option( 'autosave_draft_ids' ) )
617 $draft_ids = array();
618 if ( $draft_temp_id = (int) array_search( $post_ID, $draft_ids ) )
619 _relocate_children( $draft_temp_id, $post_ID );
620 if ( $temp_id && $temp_id != $draft_temp_id )
621 _relocate_children( $temp_id, $post_ID );
622
623 // Update autosave collision detection
624 if ( $temp_id ) {
625 $draft_ids[$temp_id] = $post_ID;
626 update_user_option( $user_ID, 'autosave_draft_ids', $draft_ids );
627 }
628
629 // Now that we have an ID we can fix any attachment anchor hrefs
630 _fix_attachment_links( $post_ID );
631
632 wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
633
634 return $post_ID;
635}
636
637/**
638 * Calls wp_write_post() and handles the errors.
639 *
640 * @since 2.0.0
641 *
642 * @return unknown
643 */
644function write_post() {
645 $result = wp_write_post();
646 if ( is_wp_error( $result ) )
647 wp_die( $result->get_error_message() );
648 else
649 return $result;
650}
651
652//
653// Post Meta
654//
655
656/**
657 * {@internal Missing Short Description}}
658 *
659 * @since 1.2.0
660 *
661 * @param unknown_type $post_ID
662 * @return unknown
663 */
664function add_meta( $post_ID ) {
665 global $wpdb;
666 $post_ID = (int) $post_ID;
667
668 $metakeyselect = isset($_POST['metakeyselect']) ? stripslashes( trim( $_POST['metakeyselect'] ) ) : '';
669 $metakeyinput = isset($_POST['metakeyinput']) ? stripslashes( trim( $_POST['metakeyinput'] ) ) : '';
670 $metavalue = isset($_POST['metavalue']) ? maybe_serialize( stripslashes_deep( $_POST['metavalue'] ) ) : '';
671 if ( is_string($metavalue) )
672 $metavalue = trim( $metavalue );
673
674 if ( ('0' === $metavalue || !empty ( $metavalue ) ) && ((('#NONE#' != $metakeyselect) && !empty ( $metakeyselect) ) || !empty ( $metakeyinput) ) ) {
675 // We have a key/value pair. If both the select and the
676 // input for the key have data, the input takes precedence:
677
678 if ('#NONE#' != $metakeyselect)
679 $metakey = $metakeyselect;
680
681 if ( $metakeyinput)
682 $metakey = $metakeyinput; // default
683
684 if ( is_protected_meta( $metakey ) )
685 return false;
686
687 wp_cache_delete($post_ID, 'post_meta');
688 $wpdb->insert( $wpdb->postmeta, array( 'post_id' => $post_ID, 'meta_key' => $metakey, 'meta_value' => $metavalue ) );
689 $meta_id = $wpdb->insert_id;
690 do_action( 'added_postmeta', $meta_id, $post_ID, $metakey, $metavalue );
691
692 return $meta_id;
693 }
694 return false;
695} // add_meta
696
697/**
698 * {@internal Missing Short Description}}
699 *
700 * @since 1.2.0
701 *
702 * @param unknown_type $mid
703 * @return unknown
704 */
705function delete_meta( $mid ) {
706 global $wpdb;
707 $mid = (int) $mid;
708
709 $post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
710
711 do_action( 'delete_postmeta', $mid );
712 wp_cache_delete($post_id, 'post_meta');
713 $rval = $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
714 do_action( 'deleted_postmeta', $mid );
715
716 return $rval;
717}
718
719/**
720 * Get a list of previously defined keys.
721 *
722 * @since 1.2.0
723 *
724 * @return unknown
725 */
726function get_meta_keys() {
727 global $wpdb;
728
729 $keys = $wpdb->get_col( "
730 SELECT meta_key
731 FROM $wpdb->postmeta
732 GROUP BY meta_key
733 ORDER BY meta_key" );
734
735 return $keys;
736}
737
738/**
739 * {@internal Missing Short Description}}
740 *
741 * @since 2.1.0
742 *
743 * @param unknown_type $mid
744 * @return unknown
745 */
746function get_post_meta_by_id( $mid ) {
747 global $wpdb;
748 $mid = (int) $mid;
749
750 $meta = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE meta_id = %d", $mid) );
751 if ( empty($meta) )
752 return false;
753 if ( is_serialized_string( $meta->meta_value ) )
754 $meta->meta_value = maybe_unserialize( $meta->meta_value );
755 return $meta;
756}
757
758/**
759 * {@internal Missing Short Description}}
760 *
761 * Some postmeta stuff.
762 *
763 * @since 1.2.0
764 *
765 * @param unknown_type $postid
766 * @return unknown
767 */
768function has_meta( $postid ) {
769 global $wpdb;
770
771 return $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value, meta_id, post_id
772 FROM $wpdb->postmeta WHERE post_id = %d
773 ORDER BY meta_key,meta_id", $postid), ARRAY_A );
774
775}
776
777/**
778 * {@internal Missing Short Description}}
779 *
780 * @since 1.2.0
781 *
782 * @param unknown_type $meta_id
783 * @param unknown_type $meta_key Expect Slashed
784 * @param unknown_type $meta_value Expect Slashed
785 * @return unknown
786 */
787function update_meta( $meta_id, $meta_key, $meta_value ) {
788 global $wpdb;
789
790 $meta_key = stripslashes($meta_key);
791
792 if ( is_protected_meta( $meta_key ) )
793 return false;
794
795 if ( '' === trim( $meta_value ) )
796 return false;
797
798 $post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_id = %d", $meta_id) );
799
800 $meta_value = maybe_serialize( stripslashes_deep( $meta_value ) );
801 $meta_id = (int) $meta_id;
802
803 $data = compact( 'meta_key', 'meta_value' );
804 $where = compact( 'meta_id' );
805
806 do_action( 'update_postmeta', $meta_id, $post_id, $meta_key, $meta_value );
807 $rval = $wpdb->update( $wpdb->postmeta, $data, $where );
808 wp_cache_delete($post_id, 'post_meta');
809 do_action( 'updated_postmeta', $meta_id, $post_id, $meta_key, $meta_value );
810
811 return $rval;
812}
813
814//
815// Private
816//
817
818/**
819 * Replace hrefs of attachment anchors with up-to-date permalinks.
820 *
821 * @since 2.3.0
822 * @access private
823 *
824 * @param unknown_type $post_ID
825 * @return unknown
826 */
827function _fix_attachment_links( $post_ID ) {
828 global $_fix_attachment_link_id;
829
830 $post = & get_post( $post_ID, ARRAY_A );
831
832 $search = "#<a[^>]+rel=('|\")[^'\"]*attachment[^>]*>#ie";
833
834 // See if we have any rel="attachment" links
835 if ( 0 == preg_match_all( $search, $post['post_content'], $anchor_matches, PREG_PATTERN_ORDER ) )
836 return;
837
838 $i = 0;
839 $search = "#[\s]+rel=(\"|')(.*?)wp-att-(\d+)\\1#i";
840 foreach ( $anchor_matches[0] as $anchor ) {
841 if ( 0 == preg_match( $search, $anchor, $id_matches ) )
842 continue;
843
844 $id = (int) $id_matches[3];
845
846 // While we have the attachment ID, let's adopt any orphans.
847 $attachment = & get_post( $id, ARRAY_A );
848 if ( ! empty( $attachment) && ! is_object( get_post( $attachment['post_parent'] ) ) ) {
849 $attachment['post_parent'] = $post_ID;
850 // Escape data pulled from DB.
851 $attachment = add_magic_quotes( $attachment );
852 wp_update_post( $attachment );
853 }
854
855 $post_search[$i] = $anchor;
856 $_fix_attachment_link_id = $id;
857 $post_replace[$i] = preg_replace_callback( "#href=(\"|')[^'\"]*\\1#", '_fix_attachment_links_replace_cb', $anchor );
858 ++$i;
859 }
860
861 $post['post_content'] = str_replace( $post_search, $post_replace, $post['post_content'] );
862
863 // Escape data pulled from DB.
864 $post = add_magic_quotes( $post);
865
866 return wp_update_post( $post);
867}
868
869function _fix_attachment_links_replace_cb($match) {
870 global $_fix_attachment_link_id;
871 return stripslashes( 'href='.$match[1] ).get_attachment_link( $_fix_attachment_link_id ).stripslashes( $match[1] );
872}
873
874/**
875 * Move child posts to a new parent.
876 *
877 * @since 2.3.0
878 * @access private
879 *
880 * @param unknown_type $old_ID
881 * @param unknown_type $new_ID
882 * @return unknown
883 */
884function _relocate_children( $old_ID, $new_ID ) {
885 global $wpdb;
886 $old_ID = (int) $old_ID;
887 $new_ID = (int) $new_ID;
888
889 $children = $wpdb->get_col( $wpdb->prepare("
890 SELECT post_id
891 FROM $wpdb->postmeta
892 WHERE meta_key = '_wp_attachment_temp_parent'
893 AND meta_value = %d", $old_ID) );
894
895 foreach ( $children as $child_id ) {
896 $wpdb->update($wpdb->posts, array('post_parent' => $new_ID), array('ID' => $child_id) );
897 delete_post_meta($child_id, '_wp_attachment_temp_parent');
898 }
899}
900
901/**
902 * Get all the possible statuses for a post_type
903 *
904 * @since 2.5.0
905 *
906 * @param string $type The post_type you want the statuses for
907 * @return array As array of all the statuses for the supplied post type
908 */
909function get_available_post_statuses($type = 'post') {
910 $stati = wp_count_posts($type);
911
912 return array_keys(get_object_vars($stati));
913}
914
915/**
916 * Run the wp query to fetch the posts for listing on the edit posts page
917 *
918 * @since 2.5.0
919 *
920 * @param array|bool $q Array of query variables to use to build the query or false to use $_GET superglobal.
921 * @return array
922 */
923function wp_edit_posts_query( $q = false ) {
924 if ( false === $q )
925 $q = $_GET;
926 $q['m'] = isset($q['m']) ? (int) $q['m'] : 0;
927 $q['cat'] = isset($q['cat']) ? (int) $q['cat'] : 0;
928 $post_stati = get_post_stati();
929
930 if ( isset($q['post_type']) && in_array( $q['post_type'], get_post_types() ) )
931 $post_type = $q['post_type'];
932 else
933 $post_type = 'post';
934
935 $avail_post_stati = get_available_post_statuses($post_type);
936
937 if ( isset($q['post_status']) && in_array( $q['post_status'], $post_stati ) ) {
938 $post_status = $q['post_status'];
939 $perm = 'readable';
940 }
941
942 if ( isset($q['orderby']) )
943 $orderby = $q['orderby'];
944 elseif ( isset($q['post_status']) && in_array($q['post_status'], array('pending', 'draft')) )
945 $orderby = 'modified';
946
947 if ( isset($q['order']) )
948 $order = $q['order'];
949 elseif ( isset($q['post_status']) && 'pending' == $q['post_status'] )
950 $order = 'ASC';
951
952 $per_page = 'edit_' . $post_type . '_per_page';
953 $posts_per_page = (int) get_user_option( $per_page );
954 if ( empty( $posts_per_page ) || $posts_per_page < 1 )
955 $posts_per_page = 20;
956
957 $posts_per_page = apply_filters( $per_page, $posts_per_page );
958 $posts_per_page = apply_filters( 'edit_posts_per_page', $posts_per_page, $post_type );
959
960 $query = compact('post_type', 'post_status', 'perm', 'order', 'orderby', 'posts_per_page');
961
962 // Hierarchical types require special args.
963 if ( is_post_type_hierarchical( $post_type ) && !isset($orderby) ) {
964 $query['orderby'] = 'menu_order title';
965 $query['order'] = 'asc';
966 $query['posts_per_page'] = -1;
967 $query['posts_per_archive_page'] = -1;
968 }
969
970 if ( ! empty( $q['show_sticky'] ) )
971 $query['post__in'] = (array) get_option( 'sticky_posts' );
972
973 wp( $query );
974
975 return $avail_post_stati;
976}
977
978/**
979 * Get default post mime types
980 *
981 * @since 2.9.0
982 *
983 * @return array
984 */
985function get_post_mime_types() {
986 $post_mime_types = array( // array( adj, noun )
987 'image' => array(__('Images'), __('Manage Images'), _n_noop('Image <span class="count">(%s)</span>', 'Images <span class="count">(%s)</span>')),
988 'audio' => array(__('Audio'), __('Manage Audio'), _n_noop('Audio <span class="count">(%s)</span>', 'Audio <span class="count">(%s)</span>')),
989 'video' => array(__('Video'), __('Manage Video'), _n_noop('Video <span class="count">(%s)</span>', 'Video <span class="count">(%s)</span>')),
990 );
991
992 return apply_filters('post_mime_types', $post_mime_types);
993}
994
995/**
996 * {@internal Missing Short Description}}
997 *
998 * @since 2.5.0
999 *
1000 * @param unknown_type $type
1001 * @return unknown
1002 */
1003function get_available_post_mime_types($type = 'attachment') {
1004 global $wpdb;
1005
1006 $types = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT post_mime_type FROM $wpdb->posts WHERE post_type = %s", $type));
1007 return $types;
1008}
1009
1010/**
1011 * {@internal Missing Short Description}}
1012 *
1013 * @since 2.5.0
1014 *
1015 * @param unknown_type $q
1016 * @return unknown
1017 */
1018function wp_edit_attachments_query( $q = false ) {
1019 if ( false === $q )
1020 $q = $_GET;
1021
1022 $q['m'] = isset( $q['m'] ) ? (int) $q['m'] : 0;
1023 $q['cat'] = isset( $q['cat'] ) ? (int) $q['cat'] : 0;
1024 $q['post_type'] = 'attachment';
1025 $post_type = get_post_type_object( 'attachment' );
1026 $states = 'inherit';
1027 if ( current_user_can( $post_type->cap->read_private_posts ) )
1028 $states .= ',private';
1029
1030 $q['post_status'] = isset( $q['status'] ) && 'trash' == $q['status'] ? 'trash' : $states;
1031 $media_per_page = (int) get_user_option( 'upload_per_page' );
1032 if ( empty( $media_per_page ) || $media_per_page < 1 )
1033 $media_per_page = 20;
1034 $q['posts_per_page'] = apply_filters( 'upload_per_page', $media_per_page );
1035
1036 $post_mime_types = get_post_mime_types();
1037 $avail_post_mime_types = get_available_post_mime_types('attachment');
1038
1039 if ( isset($q['post_mime_type']) && !array_intersect( (array) $q['post_mime_type'], array_keys($post_mime_types) ) )
1040 unset($q['post_mime_type']);
1041
1042 if ( isset($q['detached']) )
1043 add_filter('posts_where', '_edit_attachments_query_helper');
1044
1045 wp( $q );
1046
1047 if ( isset($q['detached']) )
1048 remove_filter('posts_where', '_edit_attachments_query_helper');
1049
1050 return array($post_mime_types, $avail_post_mime_types);
1051}
1052
1053function _edit_attachments_query_helper($where) {
1054 return $where .= ' AND post_parent < 1';
1055}
1056
1057/**
1058 * Returns the list of classes to be used by a metabox
1059 *
1060 * @uses get_user_option()
1061 * @since 2.5.0
1062 *
1063 * @param unknown_type $id
1064 * @param unknown_type $page
1065 * @return unknown
1066 */
1067function postbox_classes( $id, $page ) {
1068 if ( isset( $_GET['edit'] ) && $_GET['edit'] == $id ) {
1069 $classes = array( '' );
1070 } elseif ( $closed = get_user_option('closedpostboxes_'.$page ) ) {
1071 if ( !is_array( $closed ) ) {
1072 $classes = array( '' );
1073 } else {
1074 $classes = in_array( $id, $closed ) ? array( 'closed' ) : array( '' );
1075 }
1076 } else {
1077 $classes = array( '' );
1078 }
1079
1080 $classes = apply_filters( "postbox_classes_{$page}_{$id}", $classes );
1081 return implode( ' ', $classes );
1082}
1083
1084/**
1085 * {@internal Missing Short Description}}
1086 *
1087 * @since 2.5.0
1088 *
1089 * @param int|object $id Post ID or post object.
1090 * @param string $title (optional) Title
1091 * @param string $name (optional) Name
1092 * @return array With two entries of type string
1093 */
1094function get_sample_permalink($id, $title = null, $name = null) {
1095 $post = &get_post($id);
1096 if ( !$post->ID )
1097 return array('', '');
1098
1099 $ptype = get_post_type_object($post->post_type);
1100
1101 $original_status = $post->post_status;
1102 $original_date = $post->post_date;
1103 $original_name = $post->post_name;
1104
1105 // Hack: get_permalink would return ugly permalink for
1106 // drafts, so we will fake, that our post is published
1107 if ( in_array($post->post_status, array('draft', 'pending')) ) {
1108 $post->post_status = 'publish';
1109 $post->post_name = sanitize_title($post->post_name ? $post->post_name : $post->post_title, $post->ID);
1110 }
1111
1112 // If the user wants to set a new name -- override the current one
1113 // Note: if empty name is supplied -- use the title instead, see #6072
1114 if ( !is_null($name) )
1115 $post->post_name = sanitize_title($name ? $name : $title, $post->ID);
1116
1117 $post->post_name = wp_unique_post_slug($post->post_name, $post->ID, $post->post_status, $post->post_type, $post->post_parent);
1118
1119 $post->filter = 'sample';
1120
1121 $permalink = get_permalink($post, true);
1122
1123 // Replace custom post_type Token with generic pagename token for ease of use.
1124 $permalink = str_replace("%$post->post_type%", '%pagename%', $permalink);
1125
1126 // Handle page hierarchy
1127 if ( $ptype->hierarchical ) {
1128 $uri = get_page_uri($post);
1129 $uri = untrailingslashit($uri);
1130 $uri = strrev( stristr( strrev( $uri ), '/' ) );
1131 $uri = untrailingslashit($uri);
1132 $uri = apply_filters( 'editable_slug', $uri );
1133 if ( !empty($uri) )
1134 $uri .= '/';
1135 $permalink = str_replace('%pagename%', "{$uri}%pagename%", $permalink);
1136 }
1137
1138 $permalink = array($permalink, apply_filters('editable_slug', $post->post_name));
1139 $post->post_status = $original_status;
1140 $post->post_date = $original_date;
1141 $post->post_name = $original_name;
1142 unset($post->filter);
1143
1144 return $permalink;
1145}
1146
1147/**
1148 * sample permalink html
1149 *
1150 * intended to be used for the inplace editor of the permalink post slug on in the post (and page?) editor.
1151 *
1152 * @since 2.5.0
1153 *
1154 * @param int|object $id Post ID or post object.
1155 * @param string $new_title (optional) New title
1156 * @param string $new_slug (optional) New slug
1157 * @return string intended to be used for the inplace editor of the permalink post slug on in the post (and page?) editor.
1158 */
1159function get_sample_permalink_html( $id, $new_title = null, $new_slug = null ) {
1160 global $wpdb;
1161 $post = &get_post($id);
1162
1163 list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug);
1164
1165 if ( 'publish' == $post->post_status ) {
1166 $ptype = get_post_type_object($post->post_type);
1167 $view_post = $ptype->labels->view_item;
1168 $title = __('Click to edit this part of the permalink');
1169 } else {
1170 $title = __('Temporary permalink. Click to edit this part.');
1171 }
1172
1173 if ( false === strpos($permalink, '%postname%') && false === strpos($permalink, '%pagename%') ) {
1174 $return = '<strong>' . __('Permalink:') . "</strong>\n" . '<span id="sample-permalink">' . $permalink . "</span>\n";
1175 if ( '' == get_option( 'permalink_structure' ) && current_user_can( 'manage_options' ) && !( 'page' == get_option('show_on_front') && $id == get_option('page_on_front') ) )
1176 $return .= '<span id="change-permalinks"><a href="options-permalink.php" class="button" target="_blank">' . __('Change Permalinks') . "</a></span>\n";
1177 if ( isset($view_post) )
1178 $return .= "<span id='view-post-btn'><a href='$permalink' class='button' target='_blank'>$view_post</a></span>\n";
1179
1180 $return = apply_filters('get_sample_permalink_html', $return, $id, $new_title, $new_slug);
1181
1182 return $return;
1183 }
1184
1185 if ( function_exists('mb_strlen') ) {
1186 if ( mb_strlen($post_name) > 30 ) {
1187 $post_name_abridged = mb_substr($post_name, 0, 14). '&hellip;' . mb_substr($post_name, -14);
1188 } else {
1189 $post_name_abridged = $post_name;
1190 }
1191 } else {
1192 if ( strlen($post_name) > 30 ) {
1193 $post_name_abridged = substr($post_name, 0, 14). '&hellip;' . substr($post_name, -14);
1194 } else {
1195 $post_name_abridged = $post_name;
1196 }
1197 }
1198
1199 $post_name_html = '<span id="editable-post-name" title="' . $title . '">' . $post_name_abridged . '</span>';
1200 $display_link = str_replace(array('%pagename%','%postname%'), $post_name_html, $permalink);
1201 $view_link = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
1202 $return = '<strong>' . __('Permalink:') . "</strong>\n";
1203 $return .= '<span id="sample-permalink">' . $display_link . "</span>\n";
1204 $return .= '&lrm;'; // Fix bi-directional text display defect in RTL languages.
1205 $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";
1206 $return .= '<span id="editable-post-name-full">' . $post_name . "</span>\n";
1207 if ( isset($view_post) )
1208 $return .= "<span id='view-post-btn'><a href='$view_link' class='button' target='_blank'>$view_post</a></span>\n";
1209
1210 $return = apply_filters('get_sample_permalink_html', $return, $id, $new_title, $new_slug);
1211
1212 return $return;
1213}
1214
1215/**
1216 * Output HTML for the post thumbnail meta-box.
1217 *
1218 * @since 2.9.0
1219 *
1220 * @param int $thumbnail_id ID of the attachment used for thumbnail
1221 * @return string html
1222 */
1223function _wp_post_thumbnail_html( $thumbnail_id = NULL ) {
1224 global $content_width, $_wp_additional_image_sizes, $post_ID;
1225 $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>';
1226 $content = sprintf($set_thumbnail_link, esc_html__( 'Set featured image' ));
1227
1228 if ( $thumbnail_id && get_post( $thumbnail_id ) ) {
1229 $old_content_width = $content_width;
1230 $content_width = 266;
1231 if ( !isset( $_wp_additional_image_sizes['post-thumbnail'] ) )
1232 $thumbnail_html = wp_get_attachment_image( $thumbnail_id, array( $content_width, $content_width ) );
1233 else
1234 $thumbnail_html = wp_get_attachment_image( $thumbnail_id, 'post-thumbnail' );
1235 if ( !empty( $thumbnail_html ) ) {
1236 $ajax_nonce = wp_create_nonce( "set_post_thumbnail-$post_ID" );
1237 $content = sprintf($set_thumbnail_link, $thumbnail_html);
1238 $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>';
1239 }
1240 $content_width = $old_content_width;
1241 }
1242
1243 return apply_filters( 'admin_post_thumbnail_html', $content );
1244}
1245
1246/**
1247 * Check to see if the post is currently being edited by another user.
1248 *
1249 * @since 2.5.0
1250 *
1251 * @param int $post_id ID of the post to check for editing
1252 * @return bool|int False: not locked or locked by current user. Int: user ID of user with lock.
1253 */
1254function wp_check_post_lock( $post_id ) {
1255 if ( !$post = get_post( $post_id ) )
1256 return false;
1257
1258 if ( !$lock = get_post_meta( $post->ID, '_edit_lock', true ) )
1259 return false;
1260
1261 $lock = explode( ':', $lock );
1262 $time = $lock[0];
1263 $user = isset( $lock[1] ) ? $lock[1] : get_post_meta( $post->ID, '_edit_last', true );
1264
1265 $time_window = apply_filters( 'wp_check_post_lock_window', AUTOSAVE_INTERVAL * 2 );
1266
1267 if ( $time && $time > time() - $time_window && $user != get_current_user_id() )
1268 return $user;
1269 return false;
1270}
1271
1272/**
1273 * Mark the post as currently being edited by the current user
1274 *
1275 * @since 2.5.0
1276 *
1277 * @param int $post_id ID of the post to being edited
1278 * @return bool Returns false if the post doesn't exist of there is no current user
1279 */
1280function wp_set_post_lock( $post_id ) {
1281 if ( !$post = get_post( $post_id ) )
1282 return false;
1283 if ( 0 == ($user_id = get_current_user_id()) )
1284 return false;
1285
1286 $now = time();
1287 $lock = "$now:$user_id";
1288
1289 update_post_meta( $post->ID, '_edit_lock', $lock );
1290}
1291
1292/**
1293 * Outputs the notice message to say that someone else is editing this post at the moment.
1294 *
1295 * @since 2.8.5
1296 * @return none
1297 */
1298function _admin_notice_post_locked() {
1299 global $post;
1300
1301 $lock = explode( ':', get_post_meta( $post->ID, '_edit_lock', true ) );
1302 $user = isset( $lock[1] ) ? $lock[1] : get_post_meta( $post->ID, '_edit_last', true );
1303 $last_user = get_userdata( $user );
1304 $last_user_name = $last_user ? $last_user->display_name : __('Somebody');
1305
1306 switch ($post->post_type) {
1307 case 'post':
1308 $message = __( 'Warning: %s is currently editing this post' );
1309 break;
1310 case 'page':
1311 $message = __( 'Warning: %s is currently editing this page' );
1312 break;
1313 default:
1314 $message = __( 'Warning: %s is currently editing this.' );
1315 }
1316
1317 $message = sprintf( $message, esc_html( $last_user_name ) );
1318 echo "<div class='error'><p>$message</p></div>";
1319}
1320
1321/**
1322 * Creates autosave data for the specified post from $_POST data.
1323 *
1324 * @package WordPress
1325 * @subpackage Post_Revisions
1326 * @since 2.6.0
1327 *
1328 * @uses _wp_translate_postdata()
1329 * @uses _wp_post_revision_fields()
1330 *
1331 * @return unknown
1332 */
1333function wp_create_post_autosave( $post_id ) {
1334 $translated = _wp_translate_postdata( true );
1335 if ( is_wp_error( $translated ) )
1336 return $translated;
1337
1338 // Only store one autosave. If there is already an autosave, overwrite it.
1339 if ( $old_autosave = wp_get_post_autosave( $post_id ) ) {
1340 $new_autosave = _wp_post_revision_fields( $_POST, true );
1341 $new_autosave['ID'] = $old_autosave->ID;
1342 $new_autosave['post_author'] = get_current_user_id();
1343 return wp_update_post( $new_autosave );
1344 }
1345
1346 // _wp_put_post_revision() expects unescaped.
1347 $_POST = stripslashes_deep($_POST);
1348
1349 // Otherwise create the new autosave as a special post revision
1350 return _wp_put_post_revision( $_POST, true );
1351}
1352
1353/**
1354 * Save draft or manually autosave for showing preview.
1355 *
1356 * @package WordPress
1357 * @since 2.7.0
1358 *
1359 * @uses wp_write_post()
1360 * @uses edit_post()
1361 * @uses get_post()
1362 * @uses current_user_can()
1363 * @uses wp_create_post_autosave()
1364 *
1365 * @return str URL to redirect to show the preview
1366 */
1367function post_preview() {
1368
1369 $post_ID = (int) $_POST['post_ID'];
1370 $status = get_post_status( $post_ID );
1371 if ( 'auto-draft' == $status )
1372 wp_die( __('Preview not available. Please save as a draft first.') );
1373
1374 if ( isset($_POST['catslist']) )
1375 $_POST['post_category'] = explode(",", $_POST['catslist']);
1376
1377 if ( isset($_POST['tags_input']) )
1378 $_POST['tags_input'] = explode(",", $_POST['tags_input']);
1379
1380 if ( $_POST['post_type'] == 'page' || empty($_POST['post_category']) )
1381 unset($_POST['post_category']);
1382
1383 $_POST['ID'] = $post_ID;
1384 $post = get_post($post_ID);
1385
1386 if ( 'page' == $post->post_type ) {
1387 if ( !current_user_can('edit_page', $post_ID) )
1388 wp_die(__('You are not allowed to edit this page.'));
1389 } else {
1390 if ( !current_user_can('edit_post', $post_ID) )
1391 wp_die(__('You are not allowed to edit this post.'));
1392 }
1393
1394 if ( 'draft' == $post->post_status ) {
1395 $id = edit_post();
1396 } else { // Non drafts are not overwritten. The autosave is stored in a special post revision.
1397 $id = wp_create_post_autosave( $post->ID );
1398 if ( ! is_wp_error($id) )
1399 $id = $post->ID;
1400 }
1401
1402 if ( is_wp_error($id) )
1403 wp_die( $id->get_error_message() );
1404
1405 if ( $_POST['post_status'] == 'draft' ) {
1406 $url = add_query_arg( 'preview', 'true', get_permalink($id) );
1407 } else {
1408 $nonce = wp_create_nonce('post_preview_' . $id);
1409 $url = add_query_arg( array( 'preview' => 'true', 'preview_id' => $id, 'preview_nonce' => $nonce ), get_permalink($id) );
1410 }
1411
1412 return $url;
1413}
1414
1415/**
1416 * Adds the TinyMCE editor used on the Write and Edit screens.
1417 *
1418 * @package WordPress
1419 * @since 2.7.0
1420 *
1421 * TinyMCE is loaded separately from other Javascript by using wp-tinymce.php. It outputs concatenated
1422 * and optionaly pre-compressed version of the core and all default plugins. Additional plugins are loaded
1423 * directly by TinyMCE using non-blocking method. Custom plugins can be refreshed by adding a query string
1424 * to the URL when queueing them with the mce_external_plugins filter.
1425 *
1426 * @param bool $teeny optional Output a trimmed down version used in Press This.
1427 * @param mixed $settings optional An array that can add to or overwrite the default TinyMCE settings.
1428 */
1429function wp_tiny_mce( $teeny = false, $settings = false ) {
1430 global $concatenate_scripts, $compress_scripts, $tinymce_version, $editor_styles;
1431
1432 if ( ! user_can_richedit() )
1433 return;
1434
1435 $baseurl = includes_url('js/tinymce');
1436
1437 $mce_locale = ( '' == get_locale() ) ? 'en' : strtolower( substr(get_locale(), 0, 2) ); // only ISO 639-1
1438
1439 /*
1440 The following filter allows localization scripts to change the languages displayed in the spellchecker's drop-down menu.
1441 By default it uses Google's spellchecker API, but can be configured to use PSpell/ASpell if installed on the server.
1442 The + sign marks the default language. More information:
1443 http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker
1444 */
1445 $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');
1446
1447 if ( $teeny ) {
1448 $plugins = apply_filters( 'teeny_mce_plugins', array('inlinepopups', 'fullscreen', 'wordpress', 'wplink', 'wpdialogs') );
1449 $ext_plugins = '';
1450 } else {
1451 $plugins = array( 'inlinepopups', 'spellchecker', 'tabfocus', 'paste', 'media', 'wordpress', 'wpfullscreen', 'wpeditimage', 'wpgallery', 'wplink', 'wpdialogs' );
1452
1453 /*
1454 The following filter takes an associative array of external plugins for TinyMCE in the form 'plugin_name' => 'url'.
1455 It adds the plugin's name to TinyMCE's plugins init and the call to PluginManager to load the plugin.
1456 The url should be absolute and should include the js file name to be loaded. Example:
1457 array( 'myplugin' => 'http://my-site.com/wp-content/plugins/myfolder/mce_plugin.js' )
1458 If the plugin uses a button, it should be added with one of the "$mce_buttons" filters.
1459 */
1460 $mce_external_plugins = apply_filters('mce_external_plugins', array());
1461
1462 $ext_plugins = '';
1463 if ( ! empty($mce_external_plugins) ) {
1464
1465 /*
1466 The following filter loads external language files for TinyMCE plugins.
1467 It takes an associative array 'plugin_name' => 'path', where path is the
1468 include path to the file. The language file should follow the same format as
1469 /tinymce/langs/wp-langs.php and should define a variable $strings that
1470 holds all translated strings.
1471 When this filter is not used, the function will try to load {mce_locale}.js.
1472 If that is not found, en.js will be tried next.
1473 */
1474 $mce_external_languages = apply_filters('mce_external_languages', array());
1475
1476 $loaded_langs = array();
1477 $strings = '';
1478
1479 if ( ! empty($mce_external_languages) ) {
1480 foreach ( $mce_external_languages as $name => $path ) {
1481 if ( @is_file($path) && @is_readable($path) ) {
1482 include_once($path);
1483 $ext_plugins .= $strings . "\n";
1484 $loaded_langs[] = $name;
1485 }
1486 }
1487 }
1488
1489 foreach ( $mce_external_plugins as $name => $url ) {
1490
1491 if ( is_ssl() ) $url = str_replace('http://', 'https://', $url);
1492
1493 $plugins[] = '-' . $name;
1494
1495 $plugurl = dirname($url);
1496 $strings = $str1 = $str2 = '';
1497 if ( ! in_array($name, $loaded_langs) ) {
1498 if(false !== strpos($plugurl, WP_PLUGIN_URL)){
1499 $path = str_replace( WP_PLUGIN_URL, '', $plugurl );
1500 $path = WP_PLUGIN_DIR . $path . '/langs/';
1501 }else{
1502 $path = str_replace( get_template_directory_uri(), '', $plugurl );
1503 $path = get_template_directory(). $path . '/langs/';
1504 }
1505
1506 if ( function_exists('realpath') )
1507 $path = trailingslashit( realpath($path) );
1508
1509 if ( @is_file($path . $mce_locale . '.js') )
1510 $strings .= @file_get_contents($path . $mce_locale . '.js') . "\n";
1511
1512 if ( @is_file($path . $mce_locale . '_dlg.js') )
1513 $strings .= @file_get_contents($path . $mce_locale . '_dlg.js') . "\n";
1514
1515 if ( 'en' != $mce_locale && empty($strings) ) {
1516 if ( @is_file($path . 'en.js') ) {
1517 $str1 = @file_get_contents($path . 'en.js');
1518 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str1, 1 ) . "\n";
1519 }
1520
1521 if ( @is_file($path . 'en_dlg.js') ) {
1522 $str2 = @file_get_contents($path . 'en_dlg.js');
1523 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str2, 1 ) . "\n";
1524 }
1525 }
1526
1527 if ( ! empty($strings) )
1528 $ext_plugins .= "\n" . $strings . "\n";
1529 }
1530
1531 $ext_plugins .= 'tinyMCEPreInit.load_ext("' . $plugurl . '", "' . $mce_locale . '");' . "\n";
1532 $ext_plugins .= 'tinymce.PluginManager.load("' . $name . '", "' . $url . '");' . "\n";
1533 }
1534 }
1535 }
1536
1537 if ( $teeny ) {
1538 $mce_buttons = apply_filters( 'teeny_mce_buttons', array('bold, italic, underline, blockquote, separator, strikethrough, bullist, numlist,justifyleft, justifycenter, justifyright, undo, redo, link, unlink, fullscreen') );
1539 $mce_buttons = implode($mce_buttons, ',');
1540 $mce_buttons_2 = $mce_buttons_3 = $mce_buttons_4 = '';
1541 } else {
1542 $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', '|', 'bullist', 'numlist', 'blockquote', '|', 'justifyleft', 'justifycenter', 'justifyright', '|', 'link', 'unlink', 'wp_more', '|', 'spellchecker', 'fullscreen', 'wp_adv' ));
1543 $mce_buttons = implode($mce_buttons, ',');
1544
1545 $mce_buttons_2 = array( 'formatselect', 'underline', 'justifyfull', 'forecolor', '|', 'pastetext', 'pasteword', 'removeformat', '|', 'charmap', '|', 'outdent', 'indent', '|', 'undo', 'redo', 'wp_help' );
1546 $mce_buttons_2 = apply_filters('mce_buttons_2', $mce_buttons_2);
1547 $mce_buttons_2 = implode($mce_buttons_2, ',');
1548
1549 $mce_buttons_3 = apply_filters('mce_buttons_3', array());
1550 $mce_buttons_3 = implode($mce_buttons_3, ',');
1551
1552 $mce_buttons_4 = apply_filters('mce_buttons_4', array());
1553 $mce_buttons_4 = implode($mce_buttons_4, ',');
1554 }
1555 $no_captions = (bool) apply_filters( 'disable_captions', '' );
1556
1557 // TinyMCE init settings
1558 $initArray = array (
1559 'mode' => 'specific_textareas',
1560 'editor_selector' => 'theEditor',
1561 'width' => '100%',
1562 'theme' => 'advanced',
1563 'skin' => 'wp_theme',
1564 'theme_advanced_buttons1' => $mce_buttons,
1565 'theme_advanced_buttons2' => $mce_buttons_2,
1566 'theme_advanced_buttons3' => $mce_buttons_3,
1567 'theme_advanced_buttons4' => $mce_buttons_4,
1568 'language' => $mce_locale,
1569 'spellchecker_languages' => $mce_spellchecker_languages,
1570 'theme_advanced_toolbar_location' => 'top',
1571 'theme_advanced_toolbar_align' => 'left',
1572 'theme_advanced_statusbar_location' => 'bottom',
1573 'theme_advanced_resizing' => true,
1574 'theme_advanced_resize_horizontal' => false,
1575 'dialog_type' => 'modal',
1576 'formats' => "{
1577 alignleft : [
1578 {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'left'}},
1579 {selector : 'img,table', classes : 'alignleft'}
1580 ],
1581 aligncenter : [
1582 {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'center'}},
1583 {selector : 'img,table', classes : 'aligncenter'}
1584 ],
1585 alignright : [
1586 {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'right'}},
1587 {selector : 'img,table', classes : 'alignright'}
1588 ],
1589 strikethrough : {inline : 'del'}
1590 }",
1591 'relative_urls' => false,
1592 'remove_script_host' => false,
1593 'convert_urls' => false,
1594 'apply_source_formatting' => false,
1595 'remove_linebreaks' => true,
1596 'gecko_spellcheck' => true,
1597 'keep_styles' => false,
1598 'entities' => '38,amp,60,lt,62,gt',
1599 'accessibility_focus' => true,
1600 'tabfocus_elements' => 'major-publishing-actions',
1601 'media_strict' => false,
1602 'paste_remove_styles' => true,
1603 'paste_remove_spans' => true,
1604 'paste_strip_class_attributes' => 'all',
1605 'paste_text_use_dialog' => true,
1606 'extended_valid_elements' => 'article[*],aside[*],audio[*],canvas[*],command[*],datalist[*],details[*],embed[*],figcaption[*],figure[*],footer[*],header[*],hgroup[*],keygen[*],mark[*],meter[*],nav[*],output[*],progress[*],section[*],source[*],summary,time[*],video[*],wbr',
1607 'wpeditimage_disable_captions' => $no_captions,
1608 'wp_fullscreen_content_css' => "$baseurl/plugins/wpfullscreen/css/wp-fullscreen.css",
1609 'plugins' => implode( ',', $plugins ),
1610 );
1611
1612 if ( ! empty( $editor_styles ) && is_array( $editor_styles ) ) {
1613 $mce_css = array();
1614 $style_uri = get_stylesheet_directory_uri();
1615 if ( ! is_child_theme() ) {
1616 foreach ( $editor_styles as $file )
1617 $mce_css[] = "$style_uri/$file";
1618 } else {
1619 $style_dir = get_stylesheet_directory();
1620 $template_uri = get_template_directory_uri();
1621 $template_dir = get_template_directory();
1622 foreach ( $editor_styles as $file ) {
1623 if ( file_exists( "$template_dir/$file" ) )
1624 $mce_css[] = "$template_uri/$file";
1625 if ( file_exists( "$style_dir/$file" ) )
1626 $mce_css[] = "$style_uri/$file";
1627 }
1628 }
1629 $mce_css = implode( ',', $mce_css );
1630 } else {
1631 $mce_css = '';
1632 }
1633
1634 $mce_css = trim( apply_filters( 'mce_css', $mce_css ), ' ,' );
1635
1636 if ( ! empty($mce_css) )
1637 $initArray['content_css'] = $mce_css;
1638
1639 if ( is_array($settings) )
1640 $initArray = array_merge($initArray, $settings);
1641
1642 // For people who really REALLY know what they're doing with TinyMCE
1643 // You can modify initArray to add, remove, change elements of the config before tinyMCE.init
1644 // Setting "valid_elements", "invalid_elements" and "extended_valid_elements" can be done through "tiny_mce_before_init".
1645 // Best is to use the default cleanup by not specifying valid_elements, as TinyMCE contains full set of XHTML 1.0.
1646 if ( $teeny ) {
1647 $initArray = apply_filters('teeny_mce_before_init', $initArray);
1648 } else {
1649 $initArray = apply_filters('tiny_mce_before_init', $initArray);
1650 }
1651
1652 if ( empty($initArray['theme_advanced_buttons3']) && !empty($initArray['theme_advanced_buttons4']) ) {
1653 $initArray['theme_advanced_buttons3'] = $initArray['theme_advanced_buttons4'];
1654 $initArray['theme_advanced_buttons4'] = '';
1655 }
1656
1657 if ( ! isset($concatenate_scripts) )
1658 script_concat_settings();
1659
1660 $language = $initArray['language'];
1661
1662 $compressed = $compress_scripts && $concatenate_scripts && isset($_SERVER['HTTP_ACCEPT_ENCODING'])
1663 && false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
1664
1665 /**
1666 * Deprecated
1667 *
1668 * The tiny_mce_version filter is not needed since external plugins are loaded directly by TinyMCE.
1669 * These plugins can be refreshed by appending query string to the URL passed to mce_external_plugins filter.
1670 * 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).
1671 */
1672 $version = apply_filters('tiny_mce_version', '');
1673 $version = 'ver=' . $tinymce_version . $version;
1674
1675 if ( 'en' != $language )
1676 include_once(ABSPATH . WPINC . '/js/tinymce/langs/wp-langs.php');
1677
1678 $mce_options = '';
1679 foreach ( $initArray as $k => $v ) {
1680 if ( is_bool($v) ) {
1681 $val = $v ? 'true' : 'false';
1682 $mce_options .= $k . ':' . $val . ', ';
1683 continue;
1684 } elseif ( !empty($v) && is_string($v) && ( ('{' == $v{0} && '}' == $v{strlen($v) - 1}) || ('[' == $v{0} && ']' == $v{strlen($v) - 1}) || preg_match('/^\(?function ?\(/', $v) ) ) {
1685 $mce_options .= $k . ':' . $v . ', ';
1686 continue;
1687 }
1688
1689 $mce_options .= $k . ':"' . $v . '", ';
1690 }
1691
1692 $mce_options = rtrim( trim($mce_options), '\n\r,' );
1693
1694 do_action('before_wp_tiny_mce', $initArray); ?>
1695
1696<script type="text/javascript">
1697/* <![CDATA[ */
1698tinyMCEPreInit = {
1699 base : "<?php echo $baseurl; ?>",
1700 suffix : "",
1701 query : "<?php echo $version; ?>",
1702 mceInit : {<?php echo $mce_options; ?>},
1703 load_ext : function(url,lang){var sl=tinymce.ScriptLoader;sl.markDone(url+'/langs/'+lang+'.js');sl.markDone(url+'/langs/'+lang+'_dlg.js');}
1704};
1705/* ]]> */
1706</script>
1707
1708<?php
1709 if ( $compressed )
1710 echo "<script type='text/javascript' src='$baseurl/wp-tinymce.php?c=1&amp;$version'></script>\n";
1711 else
1712 echo "<script type='text/javascript' src='$baseurl/tiny_mce.js?$version'></script>\n";
1713
1714 if ( 'en' != $language && isset($lang) )
1715 echo "<script type='text/javascript'>\n$lang\n</script>\n";
1716 else
1717 echo "<script type='text/javascript' src='$baseurl/langs/wp-langs-en.js?$version'></script>\n";
1718?>
1719
1720<script type="text/javascript">
1721/* <![CDATA[ */
1722<?php
1723 if ( $ext_plugins )
1724 echo "$ext_plugins\n";
1725
1726 if ( ! $compressed ) {
1727?>
1728(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');}});})();
1729<?php } ?>
1730tinyMCE.init(tinyMCEPreInit.mceInit);
1731/* ]]> */
1732</script>
1733<?php
1734
1735do_action('after_wp_tiny_mce', $initArray);
1736}
1737
1738// Load additional inline scripts based on active plugins.
1739function wp_preload_dialogs($init) {
1740 $plugins = preg_split('/[ ,-]+/', $init['plugins']);
1741
1742 if ( in_array( 'wpdialogs', $plugins, true ) ) {
1743 wp_print_scripts('wpdialogs-popup');
1744 wp_print_styles('wp-jquery-ui-dialog');
1745 }
1746
1747 if ( in_array( 'wplink', $plugins, true ) ) {
1748 require_once ABSPATH . 'wp-admin/includes/internal-linking.php';
1749 ?><div style="display:none;"><?php wp_link_dialog(); ?></div><?php
1750 wp_print_scripts('wplink');
1751 wp_print_styles('wplink');
1752 }
1753
1754 // Distraction Free Writing mode
1755 if ( in_array( 'wpfullscreen', $plugins, true ) ) {
1756 wp_fullscreen_html();
1757 wp_print_scripts('wp-fullscreen');
1758 }
1759
1760 wp_print_scripts('word-count');
1761}
1762
1763function wp_quicktags() {
1764 global $tinymce_version;
1765
1766 wp_preload_dialogs( array( 'plugins' => 'wpdialogs,wplink,wpfullscreen' ) );
1767
1768 if ( !user_can_richedit() ) {
1769 wp_enqueue_style( 'tinymce-buttons', includes_url('js/tinymce/themes/advanced/skins/wp_theme/ui.css'), array(), $tinymce_version );
1770 wp_print_styles('tinymce-buttons');
1771 }
1772}
1773
1774function wp_print_editor_js() {
1775 wp_print_scripts('editor');
1776}
1777
1778function wp_fullscreen_html() {
1779 global $content_width, $post;
1780
1781 $width = isset($content_width) && 800 > $content_width ? $content_width : 800;
1782 $width = $width + 10; // compensate for the padding
1783 $dfw_width = get_user_setting( 'dfw_width', $width );
1784 $save = isset($post->post_status) && $post->post_status == 'publish' ? __('Update') : __('Save');
1785?>
1786<div id="wp-fullscreen-body">
1787<div id="fullscreen-topbar">
1788 <div id="wp-fullscreen-toolbar">
1789 <div id="wp-fullscreen-close"><a href="#" onclick="fullscreen.off();return false;"><?php _e('Exit fullscreen'); ?></a></div>
1790 <div id="wp-fullscreen-central-toolbar" style="width:<?php echo $width; ?>px;">
1791
1792 <div id="wp-fullscreen-mode-bar"><div id="wp-fullscreen-modes">
1793 <a href="#" onclick="fullscreen.switchmode('tinymce');return false;"><?php _e('Visual'); ?></a>
1794 <a href="#" onclick="fullscreen.switchmode('html');return false;"><?php _e('HTML'); ?></a>
1795 </div></div>
1796
1797 <div id="wp-fullscreen-button-bar"><div id="wp-fullscreen-buttons" class="wp_themeSkin">
1798<?php
1799
1800 $media_link_type = 'image';
1801 if ( is_multisite() && ( ( ! $mu_media_buttons = get_site_option( 'mu_media_buttons' ) ) || empty( $mu_media_buttons['image'] ) ) )
1802 $media_link_type = 'media';
1803
1804 $buttons = array(
1805 // format: title, onclick, show in both editors
1806 'bold' => array( 'title' => __('Bold (Ctrl + B)'), 'onclick' => 'fullscreen.b();', 'both' => false ),
1807 'italic' => array( 'title' => __('Italic (Ctrl + I)'), 'onclick' => 'fullscreen.i();', 'both' => false ),
1808 '0' => 'separator',
1809 'bullist' => array( 'title' => __('Unordered list (Alt + Shift + U)'), 'onclick' => 'fullscreen.ul();', 'both' => false ),
1810 'numlist' => array( 'title' => __('Ordered list (Alt + Shift + O)'), 'onclick' => 'fullscreen.ol();', 'both' => false ),
1811 '1' => 'separator',
1812 'blockquote' => array( 'title' => __('Blockquote (Alt+Shift+Q)'), 'onclick' => 'fullscreen.blockquote();', 'both' => false ),
1813 'image' => array( 'title' => __('Insert/edit image (Alt + Shift + M)'), 'onclick' => "jQuery('#add_{$media_link_type}').click();", 'both' => true ),
1814 '2' => 'separator',
1815 'link' => array( 'title' => __('Insert/edit link (Alt + Shift + A)'), 'onclick' => 'fullscreen.link();', 'both' => true ),
1816 'unlink' => array( 'title' => __('Unlink (Alt + Shift + S)'), 'onclick' => 'fullscreen.unlink();', 'both' => false ),
1817 '3' => 'separator',
1818 'help' => array( 'title' => __('Help (Alt + Shift + H)'), 'onclick' => 'fullscreen.help();', 'both' => false )
1819 );
1820
1821 $buttons = apply_filters( 'wp_fullscreen_buttons', $buttons );
1822
1823 foreach ( $buttons as $button => $args ) {
1824 if ( 'separator' == $args ) { ?>
1825 <div><span aria-orientation="vertical" role="separator" class="mceSeparator"></span></div>
1826<?php continue;
1827 } ?>
1828
1829 <div<?php if ( $args['both'] ) { ?> class="wp-fullscreen-both"<?php } ?>>
1830 <a title="<?php echo $args['title']; ?>" onclick="<?php echo $args['onclick']; ?>return false;" class="mceButton mceButtonEnabled mce_<?php echo $button; ?>" href="#" id="wp_fs_<?php echo $button; ?>" role="button" aria-pressed="false">
1831 <span class="mceIcon mce_<?php echo $button; ?>"></span>
1832 </a>
1833 </div>
1834<?php
1835 } ?>
1836
1837 </div></div>
1838
1839 <div id="wp-fullscreen-save">
1840 <span><?php if ( $post->post_status == 'publish' ) _e('Updated.'); else _e('Saved.'); ?></span>
1841 <img src="images/wpspin_light.gif" alt="" />
1842 <input type="button" class="button-primary" value="<?php echo $save; ?>" onclick="fullscreen.save();" />
1843 </div>
1844
1845 </div>
1846 </div>
1847</div>
1848
1849<div id="wp-fullscreen-wrap" style="width:<?php echo $dfw_width; ?>px;">
1850 <label id="wp-fullscreen-title-prompt-text" for="wp-fullscreen-title"><?php echo apply_filters( 'enter_title_here', __( 'Enter title here' ), $post ); ?></label>
1851 <input type="text" id="wp-fullscreen-title" value="" autocomplete="off" />
1852
1853 <div id="wp-fullscreen-container">
1854 <textarea id="wp_mce_fullscreen"></textarea>
1855 </div>
1856
1857 <div id="wp-fullscreen-status">
1858 <div id="wp-fullscreen-count"><?php printf( __( 'Word count: %s' ), '<span class="word-count">0</span>' ); ?></div>
1859 <div id="wp-fullscreen-tagline"><?php _e('Just write.'); ?></div>
1860 </div>
1861</div>
1862</div>
1863
1864<div class="fullscreen-overlay" id="fullscreen-overlay"></div>
1865<div class="fullscreen-overlay fullscreen-fader fade-600" id="fullscreen-fader"></div>
1866<?php
1867}
1868
1869