[ Root ] [ Search ] [ Index ]

PHP Cross Reference of WordPress 3.0.1

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


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