[ Root ] [ Search ] [ Index ]

PHP Cross Reference of WordPress 3.0

Provided by Yoast

title

Body

[close]

/wp-admin/includes/ -> post.php (source)

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


Generated: Thu Oct 14 05:11:12 2010 Cross-referenced by PHPXref 0.7