Advertisement
Guest User

Untitled

a guest
Jan 18th, 2016
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 53.31 KB | None | 0 0
  1. <?php
  2. /**
  3.  * WordPress Post Administration API.
  4.  *
  5.  * @package WordPress
  6.  * @subpackage Administration
  7.  */
  8.  
  9. /**
  10.  * Rename $_POST data from form names to DB post columns.
  11.  *
  12.  * Manipulates $_POST directly.
  13.  *
  14.  * @package WordPress
  15.  * @since 2.6.0
  16.  *
  17.  * @param bool $update Are we updating a pre-existing post?
  18.  * @param array $post_data Array of post data. Defaults to the contents of $_POST.
  19.  * @return object|bool WP_Error on failure, true on success.
  20.  */
  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.  
  29.     $ptype = get_post_type_object( $post_data['post_type'] );
  30.  
  31.     if ( $update && ! current_user_can( 'edit_post', $post_data['ID'] ) ) {
  32.         if ( 'page' == $post_data['post_type'] )
  33.             return new WP_Error( 'edit_others_pages', __( 'You are not allowed to edit pages as this user.' ) );
  34.         else
  35.             return new WP_Error( 'edit_others_posts', __( 'You are not allowed to edit posts as this user.' ) );
  36.     } elseif ( ! $update && ! current_user_can( $ptype->cap->create_posts ) ) {
  37.         if ( 'page' == $post_data['post_type'] )
  38.             return new WP_Error( 'edit_others_pages', __( 'You are not allowed to create pages as this user.' ) );
  39.         else
  40.             return new WP_Error( 'edit_others_posts', __( 'You are not allowed to create posts as this user.' ) );
  41.     }
  42.  
  43.     if ( isset( $post_data['content'] ) )
  44.         $post_data['post_content'] = $post_data['content'];
  45.  
  46.     if ( isset( $post_data['excerpt'] ) )
  47.         $post_data['post_excerpt'] = $post_data['excerpt'];
  48.  
  49.     if ( isset( $post_data['parent_id'] ) )
  50.         $post_data['post_parent'] = (int) $post_data['parent_id'];
  51.  
  52.     if ( isset($post_data['trackback_url']) )
  53.         $post_data['to_ping'] = $post_data['trackback_url'];
  54.  
  55.     $post_data['user_ID'] = get_current_user_id();
  56.  
  57.     if (!empty ( $post_data['post_author_override'] ) ) {
  58.         $post_data['post_author'] = (int) $post_data['post_author_override'];
  59.     } else {
  60.         if (!empty ( $post_data['post_author'] ) ) {
  61.             $post_data['post_author'] = (int) $post_data['post_author'];
  62.         } else {
  63.             $post_data['post_author'] = (int) $post_data['user_ID'];
  64.         }
  65.     }
  66.  
  67.     if ( isset( $post_data['user_ID'] ) && ( $post_data['post_author'] != $post_data['user_ID'] )
  68.          && ! current_user_can( $ptype->cap->edit_others_posts ) ) {
  69.         if ( $update ) {
  70.             if ( 'page' == $post_data['post_type'] )
  71.                 return new WP_Error( 'edit_others_pages', __( 'You are not allowed to edit pages as this user.' ) );
  72.             else
  73.                 return new WP_Error( 'edit_others_posts', __( 'You are not allowed to edit posts as this user.' ) );
  74.         } else {
  75.             if ( 'page' == $post_data['post_type'] )
  76.                 return new WP_Error( 'edit_others_pages', __( 'You are not allowed to create pages as this user.' ) );
  77.             else
  78.                 return new WP_Error( 'edit_others_posts', __( 'You are not allowed to create posts as this user.' ) );
  79.         }
  80.     }
  81.  
  82.     if ( ! empty( $post_data['post_status'] ) ) {
  83.         $post_data['post_status'] = sanitize_key( $post_data['post_status'] );
  84.  
  85.         // No longer an auto-draft
  86.         if ( 'auto-draft' === $post_data['post_status'] ) {
  87.             $post_data['post_status'] = 'draft';
  88.         }
  89.  
  90.         if ( ! get_post_status_object( $post_data['post_status'] ) ) {
  91.             unset( $post_data['post_status'] );
  92.         }
  93.     }
  94.  
  95.     // What to do based on which button they pressed
  96.     if ( isset($post_data['saveasdraft']) && '' != $post_data['saveasdraft'] )
  97.         $post_data['post_status'] = 'draft';
  98.     if ( isset($post_data['saveasprivate']) && '' != $post_data['saveasprivate'] )
  99.         $post_data['post_status'] = 'private';
  100.     if ( isset($post_data['publish']) && ( '' != $post_data['publish'] ) && ( !isset($post_data['post_status']) || $post_data['post_status'] != 'private' ) )
  101.         $post_data['post_status'] = 'publish';
  102.     if ( isset($post_data['advanced']) && '' != $post_data['advanced'] )
  103.         $post_data['post_status'] = 'draft';
  104.     if ( isset($post_data['pending']) && '' != $post_data['pending'] )
  105.         $post_data['post_status'] = 'pending';
  106.  
  107.     if ( isset( $post_data['ID'] ) )
  108.         $post_id = $post_data['ID'];
  109.     else
  110.         $post_id = false;
  111.     $previous_status = $post_id ? get_post_field( 'post_status', $post_id ) : false;
  112.  
  113.     if ( isset( $post_data['post_status'] ) && 'private' == $post_data['post_status'] && ! current_user_can( $ptype->cap->publish_posts ) ) {
  114.         $post_data['post_status'] = $previous_status ? $previous_status : 'pending';
  115.     }
  116.  
  117.     $published_statuses = array( 'publish', 'future' );
  118.  
  119.     // Posts 'submitted for approval' present are submitted to $_POST the same as if they were being published.
  120.     // Change status from 'publish' to 'pending' if user lacks permissions to publish or to resave published posts.
  121.     if ( isset($post_data['post_status']) && (in_array( $post_data['post_status'], $published_statuses ) && !current_user_can( $ptype->cap->publish_posts )) )
  122.         if ( ! in_array( $previous_status, $published_statuses ) || !current_user_can( 'edit_post', $post_id ) )
  123.             $post_data['post_status'] = 'pending';
  124.  
  125.     if ( ! isset( $post_data['post_status'] ) ) {
  126.         $post_data['post_status'] = 'auto-draft' === $previous_status ? 'draft' : $previous_status;
  127.     }
  128.  
  129.     if ( isset( $post_data['post_password'] ) && ! current_user_can( $ptype->cap->publish_posts ) ) {
  130.         unset( $post_data['post_password'] );
  131.     }
  132.  
  133.     if (!isset( $post_data['comment_status'] ))
  134.         $post_data['comment_status'] = 'closed';
  135.  
  136.     if (!isset( $post_data['ping_status'] ))
  137.         $post_data['ping_status'] = 'closed';
  138.  
  139.     foreach ( array('aa', 'mm', 'jj', 'hh', 'mn') as $timeunit ) {
  140.         if ( !empty( $post_data['hidden_' . $timeunit] ) && $post_data['hidden_' . $timeunit] != $post_data[$timeunit] ) {
  141.             $post_data['edit_date'] = '1';
  142.             break;
  143.         }
  144.     }
  145.  
  146.     if ( !empty( $post_data['edit_date'] ) ) {
  147.         $aa = $post_data['aa'];
  148.         $mm = $post_data['mm'];
  149.         $jj = $post_data['jj'];
  150.         $hh = $post_data['hh'];
  151.         $mn = $post_data['mn'];
  152.         $ss = $post_data['ss'];
  153.         $aa = ($aa <= 0 ) ? date('Y') : $aa;
  154.         $mm = ($mm <= 0 ) ? date('n') : $mm;
  155.         $jj = ($jj > 31 ) ? 31 : $jj;
  156.         $jj = ($jj <= 0 ) ? date('j') : $jj;
  157.         $hh = ($hh > 23 ) ? $hh -24 : $hh;
  158.         $mn = ($mn > 59 ) ? $mn -60 : $mn;
  159.         $ss = ($ss > 59 ) ? $ss -60 : $ss;
  160.         $post_data['post_date'] = sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $aa, $mm, $jj, $hh, $mn, $ss );
  161.         $valid_date = wp_checkdate( $mm, $jj, $aa, $post_data['post_date'] );
  162.         if ( !$valid_date ) {
  163.             return new WP_Error( 'invalid_date', __( 'Whoops, the provided date is invalid.' ) );
  164.         }
  165.         $post_data['post_date_gmt'] = get_gmt_from_date( $post_data['post_date'] );
  166.     }
  167.  
  168.     return $post_data;
  169. }
  170.  
  171. /**
  172.  * Update an existing post with values provided in $_POST.
  173.  *
  174.  * @since 1.5.0
  175.  *
  176.  * @param array $post_data Optional.
  177.  * @return int Post ID.
  178.  */
  179. function edit_post( $post_data = null ) {
  180.     global $wpdb;
  181.  
  182.     if ( empty($post_data) )
  183.         $post_data = &$_POST;
  184.  
  185.     // Clear out any data in internal vars.
  186.     unset( $post_data['filter'] );
  187.  
  188.     $post_ID = (int) $post_data['post_ID'];
  189.     $post = get_post( $post_ID );
  190.     $post_data['post_type'] = $post->post_type;
  191.     $post_data['post_mime_type'] = $post->post_mime_type;
  192.  
  193.     if ( ! empty( $post_data['post_status'] ) ) {
  194.         $post_data['post_status'] = sanitize_key( $post_data['post_status'] );
  195.  
  196.         if ( 'inherit' == $post_data['post_status'] ) {
  197.             unset( $post_data['post_status'] );
  198.         }
  199.     }
  200.  
  201.     $ptype = get_post_type_object($post_data['post_type']);
  202.     if ( !current_user_can( 'edit_post', $post_ID ) ) {
  203.         if ( 'page' == $post_data['post_type'] )
  204.             wp_die( __('You are not allowed to edit this page.' ));
  205.         else
  206.             wp_die( __('You are not allowed to edit this post.' ));
  207.     }
  208.  
  209.     if ( post_type_supports( $ptype->name, 'revisions' ) ) {
  210.         $revisions = wp_get_post_revisions( $post_ID, array( 'order' => 'ASC', 'posts_per_page' => 1 ) );
  211.         $revision = current( $revisions );
  212.  
  213.         // Check if the revisions have been upgraded
  214.         if ( $revisions && _wp_get_post_revision_version( $revision ) < 1 )
  215.             _wp_upgrade_revisions_of_post( $post, wp_get_post_revisions( $post_ID ) );
  216.     }
  217.  
  218.     if ( isset($post_data['visibility']) ) {
  219.         switch ( $post_data['visibility'] ) {
  220.             case 'public' :
  221.                 $post_data['post_password'] = '';
  222.                 break;
  223.             case 'password' :
  224.                 unset( $post_data['sticky'] );
  225.                 break;
  226.             case 'private' :
  227.                 $post_data['post_status'] = 'private';
  228.                 $post_data['post_password'] = '';
  229.                 unset( $post_data['sticky'] );
  230.                 break;
  231.         }
  232.     }
  233.  
  234.     $post_data = _wp_translate_postdata( true, $post_data );
  235.     if ( is_wp_error($post_data) )
  236.         wp_die( $post_data->get_error_message() );
  237.  
  238.     // Post Formats
  239.     if ( isset( $post_data['post_format'] ) )
  240.         set_post_format( $post_ID, $post_data['post_format'] );
  241.  
  242.     $format_meta_urls = array( 'url', 'link_url', 'quote_source_url' );
  243.     foreach ( $format_meta_urls as $format_meta_url ) {
  244.         $keyed = '_format_' . $format_meta_url;
  245.         if ( isset( $post_data[ $keyed ] ) )
  246.             update_post_meta( $post_ID, $keyed, wp_slash( esc_url_raw( wp_unslash( $post_data[ $keyed ] ) ) ) );
  247.     }
  248.  
  249.     $format_keys = array( 'quote', 'quote_source_name', 'image', 'gallery', 'audio_embed', 'video_embed' );
  250.  
  251.     foreach ( $format_keys as $key ) {
  252.         $keyed = '_format_' . $key;
  253.         if ( isset( $post_data[ $keyed ] ) ) {
  254.             if ( current_user_can( 'unfiltered_html' ) )
  255.                 update_post_meta( $post_ID, $keyed, $post_data[ $keyed ] );
  256.             else
  257.                 update_post_meta( $post_ID, $keyed, wp_filter_post_kses( $post_data[ $keyed ] ) );
  258.         }
  259.     }
  260.  
  261.     if ( 'attachment' === $post_data['post_type'] && preg_match( '#^(audio|video)/#', $post_data['post_mime_type'] ) ) {
  262.         $id3data = wp_get_attachment_metadata( $post_ID );
  263.         if ( ! is_array( $id3data ) ) {
  264.             $id3data = array();
  265.         }
  266.  
  267.         foreach ( wp_get_attachment_id3_keys( $post, 'edit' ) as $key => $label ) {
  268.             if ( isset( $post_data[ 'id3_' . $key ] ) ) {
  269.                 $id3data[ $key ] = sanitize_text_field( wp_unslash( $post_data[ 'id3_' . $key ] ) );
  270.             }
  271.         }
  272.         wp_update_attachment_metadata( $post_ID, $id3data );
  273.     }
  274.  
  275.     // Meta Stuff
  276.     if ( isset($post_data['meta']) && $post_data['meta'] ) {
  277.         foreach ( $post_data['meta'] as $key => $value ) {
  278.             if ( !$meta = get_post_meta_by_id( $key ) )
  279.                 continue;
  280.             if ( $meta->post_id != $post_ID )
  281.                 continue;
  282.             if ( is_protected_meta( $value['key'], 'post' ) || ! current_user_can( 'edit_post_meta', $post_ID, $value['key'] ) )
  283.                 continue;
  284.             update_meta( $key, $value['key'], $value['value'] );
  285.         }
  286.     }
  287.  
  288.     if ( isset($post_data['deletemeta']) && $post_data['deletemeta'] ) {
  289.         foreach ( $post_data['deletemeta'] as $key => $value ) {
  290.             if ( !$meta = get_post_meta_by_id( $key ) )
  291.                 continue;
  292.             if ( $meta->post_id != $post_ID )
  293.                 continue;
  294.             if ( is_protected_meta( $meta->meta_key, 'post' ) || ! current_user_can( 'delete_post_meta', $post_ID, $meta->meta_key ) )
  295.                 continue;
  296.             delete_meta( $key );
  297.         }
  298.     }
  299.  
  300.     // Attachment stuff
  301.     if ( 'attachment' == $post_data['post_type'] ) {
  302.         if ( isset( $post_data[ '_wp_attachment_image_alt' ] ) ) {
  303.             $image_alt = wp_unslash( $post_data['_wp_attachment_image_alt'] );
  304.             if ( $image_alt != get_post_meta( $post_ID, '_wp_attachment_image_alt', true ) ) {
  305.                 $image_alt = wp_strip_all_tags( $image_alt, true );
  306.                 // update_meta expects slashed
  307.                 update_post_meta( $post_ID, '_wp_attachment_image_alt', wp_slash( $image_alt ) );
  308.             }
  309.         }
  310.  
  311.         $attachment_data = isset( $post_data['attachments'][ $post_ID ] ) ? $post_data['attachments'][ $post_ID ] : array();
  312.  
  313.         /** This filter is documented in wp-admin/includes/media.php */
  314.         $post_data = apply_filters( 'attachment_fields_to_save', $post_data, $attachment_data );
  315.     }
  316.  
  317.     add_meta( $post_ID );
  318.  
  319.     update_post_meta( $post_ID, '_edit_last', get_current_user_id() );
  320.  
  321.     $success = wp_update_post( $post_data );
  322.     // If the save failed, see if we can sanity check the main fields and try again
  323.     if ( ! $success && is_callable( array( $wpdb, 'strip_invalid_text_for_column' ) ) ) {
  324.         $fields = array( 'post_title', 'post_content', 'post_excerpt' );
  325.  
  326.         foreach( $fields as $field ) {
  327.             if ( isset( $post_data[ $field ] ) ) {
  328.                 $post_data[ $field ] = $wpdb->strip_invalid_text_for_column( $wpdb->posts, $field, $post_data[ $field ] );
  329.             }
  330.         }
  331.  
  332.         wp_update_post( $post_data );
  333.     }
  334.  
  335.     // Now that we have an ID we can fix any attachment anchor hrefs
  336.     _fix_attachment_links( $post_ID );
  337.  
  338.     wp_set_post_lock( $post_ID );
  339.  
  340.     if ( current_user_can( $ptype->cap->edit_others_posts ) ) {
  341.         if ( ! empty( $post_data['sticky'] ) )
  342.             stick_post( $post_ID );
  343.         else
  344.             unstick_post( $post_ID );
  345.     }
  346.  
  347.     return $post_ID;
  348. }
  349.  
  350. /**
  351.  * Process the post data for the bulk editing of posts.
  352.  *
  353.  * Updates all bulk edited posts/pages, adding (but not removing) tags and
  354.  * categories. Skips pages when they would be their own parent or child.
  355.  *
  356.  * @since 2.7.0
  357.  *
  358.  * @param array $post_data Optional, the array of post data to process if not provided will use $_POST superglobal.
  359.  * @return array
  360.  */
  361. function bulk_edit_posts( $post_data = null ) {
  362.     global $wpdb;
  363.  
  364.     if ( empty($post_data) )
  365.         $post_data = &$_POST;
  366.  
  367.     if ( isset($post_data['post_type']) )
  368.         $ptype = get_post_type_object($post_data['post_type']);
  369.     else
  370.         $ptype = get_post_type_object('post');
  371.  
  372.     if ( !current_user_can( $ptype->cap->edit_posts ) ) {
  373.         if ( 'page' == $ptype->name )
  374.             wp_die( __('You are not allowed to edit pages.'));
  375.         else
  376.             wp_die( __('You are not allowed to edit posts.'));
  377.     }
  378.  
  379.     if ( -1 == $post_data['_status'] ) {
  380.         $post_data['post_status'] = null;
  381.         unset($post_data['post_status']);
  382.     } else {
  383.         $post_data['post_status'] = $post_data['_status'];
  384.     }
  385.     unset($post_data['_status']);
  386.  
  387.     if ( ! empty( $post_data['post_status'] ) ) {
  388.         $post_data['post_status'] = sanitize_key( $post_data['post_status'] );
  389.  
  390.         if ( 'inherit' == $post_data['post_status'] ) {
  391.             unset( $post_data['post_status'] );
  392.         }
  393.     }
  394.  
  395.     $post_IDs = array_map( 'intval', (array) $post_data['post'] );
  396.  
  397.     $reset = array(
  398.         'post_author', 'post_status', 'post_password',
  399.         'post_parent', 'page_template', 'comment_status',
  400.         'ping_status', 'keep_private', 'tax_input',
  401.         'post_category', 'sticky', 'post_format',
  402.     );
  403.  
  404.     foreach ( $reset as $field ) {
  405.         if ( isset($post_data[$field]) && ( '' == $post_data[$field] || -1 == $post_data[$field] ) )
  406.             unset($post_data[$field]);
  407.     }
  408.  
  409.     if ( isset($post_data['post_category']) ) {
  410.         if ( is_array($post_data['post_category']) && ! empty($post_data['post_category']) )
  411.             $new_cats = array_map( 'absint', $post_data['post_category'] );
  412.         else
  413.             unset($post_data['post_category']);
  414.     }
  415.  
  416.     $tax_input = array();
  417.     if ( isset($post_data['tax_input'])) {
  418.         foreach ( $post_data['tax_input'] as $tax_name => $terms ) {
  419.             if ( empty($terms) )
  420.                 continue;
  421.             if ( is_taxonomy_hierarchical( $tax_name ) ) {
  422.                 $tax_input[ $tax_name ] = array_map( 'absint', $terms );
  423.             } else {
  424.                 $comma = _x( ',', 'tag delimiter' );
  425.                 if ( ',' !== $comma )
  426.                     $terms = str_replace( $comma, ',', $terms );
  427.                 $tax_input[ $tax_name ] = explode( ',', trim( $terms, " \n\t\r\0\x0B," ) );
  428.             }
  429.         }
  430.     }
  431.  
  432.     if ( isset($post_data['post_parent']) && ($parent = (int) $post_data['post_parent']) ) {
  433.         $pages = $wpdb->get_results("SELECT ID, post_parent FROM $wpdb->posts WHERE post_type = 'page'");
  434.         $children = array();
  435.  
  436.         for ( $i = 0; $i < 50 && $parent > 0; $i++ ) {
  437.             $children[] = $parent;
  438.  
  439.             foreach ( $pages as $page ) {
  440.                 if ( $page->ID == $parent ) {
  441.                     $parent = $page->post_parent;
  442.                     break;
  443.                 }
  444.             }
  445.         }
  446.     }
  447.  
  448.     $updated = $skipped = $locked = array();
  449.     $shared_post_data = $post_data;
  450.  
  451.     foreach ( $post_IDs as $post_ID ) {
  452.         // Start with fresh post data with each iteration.
  453.         $post_data = $shared_post_data;
  454.  
  455.         $post_type_object = get_post_type_object( get_post_type( $post_ID ) );
  456.  
  457.         if ( !isset( $post_type_object ) || ( isset($children) && in_array($post_ID, $children) ) || !current_user_can( 'edit_post', $post_ID ) ) {
  458.             $skipped[] = $post_ID;
  459.             continue;
  460.         }
  461.  
  462.         if ( wp_check_post_lock( $post_ID ) ) {
  463.             $locked[] = $post_ID;
  464.             continue;
  465.         }
  466.  
  467.         $post = get_post( $post_ID );
  468.         $tax_names = get_object_taxonomies( $post );
  469.         foreach ( $tax_names as $tax_name ) {
  470.             $taxonomy_obj = get_taxonomy($tax_name);
  471.             if ( isset( $tax_input[$tax_name]) && current_user_can( $taxonomy_obj->cap->assign_terms ) )
  472.                 $new_terms = $tax_input[$tax_name];
  473.             else
  474.                 $new_terms = array();
  475.  
  476.             if ( $taxonomy_obj->hierarchical )
  477.                 $current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array('fields' => 'ids') );
  478.             else
  479.                 $current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array('fields' => 'names') );
  480.  
  481.             $post_data['tax_input'][$tax_name] = array_merge( $current_terms, $new_terms );
  482.         }
  483.  
  484.         if ( isset($new_cats) && in_array( 'category', $tax_names ) ) {
  485.             $cats = (array) wp_get_post_categories($post_ID);
  486.             $post_data['post_category'] = array_unique( array_merge($cats, $new_cats) );
  487.             unset( $post_data['tax_input']['category'] );
  488.         }
  489.  
  490.         $post_data['post_type'] = $post->post_type;
  491.         $post_data['post_mime_type'] = $post->post_mime_type;
  492.         $post_data['guid'] = $post->guid;
  493.  
  494.         foreach ( array( 'comment_status', 'ping_status', 'post_author' ) as $field ) {
  495.             if ( ! isset( $post_data[ $field ] ) ) {
  496.                 $post_data[ $field ] = $post->$field;
  497.             }
  498.         }
  499.  
  500.         $post_data['ID'] = $post_ID;
  501.         $post_data['post_ID'] = $post_ID;
  502.  
  503.         $post_data = _wp_translate_postdata( true, $post_data );
  504.         if ( is_wp_error( $post_data ) ) {
  505.             $skipped[] = $post_ID;
  506.             continue;
  507.         }
  508.  
  509.         $updated[] = wp_update_post( $post_data );
  510.  
  511.         if ( isset( $post_data['sticky'] ) && current_user_can( $ptype->cap->edit_others_posts ) ) {
  512.             if ( 'sticky' == $post_data['sticky'] )
  513.                 stick_post( $post_ID );
  514.             else
  515.                 unstick_post( $post_ID );
  516.         }
  517.  
  518.         if ( isset( $post_data['post_format'] ) )
  519.             set_post_format( $post_ID, $post_data['post_format'] );
  520.     }
  521.  
  522.     return array( 'updated' => $updated, 'skipped' => $skipped, 'locked' => $locked );
  523. }
  524.  
  525. /**
  526.  * Default post information to use when populating the "Write Post" form.
  527.  *
  528.  * @since 2.0.0
  529.  *
  530.  * @param string $post_type A post type string, defaults to 'post'.
  531.  * @return WP_Post Post object containing all the default post data as attributes
  532.  */
  533. function get_default_post_to_edit( $post_type = 'post', $create_in_db = false ) {
  534.     global $wpdb;
  535.  
  536.     $post_title = '';
  537.     if ( !empty( $_REQUEST['post_title'] ) )
  538.         $post_title = esc_html( wp_unslash( $_REQUEST['post_title'] ));
  539.  
  540.     $post_content = '';
  541.     if ( !empty( $_REQUEST['content'] ) )
  542.         $post_content = esc_html( wp_unslash( $_REQUEST['content'] ));
  543.  
  544.     $post_excerpt = '';
  545.     if ( !empty( $_REQUEST['excerpt'] ) )
  546.         $post_excerpt = esc_html( wp_unslash( $_REQUEST['excerpt'] ));
  547.  
  548.     if ( $create_in_db ) {
  549.         $post_id = wp_insert_post( array( 'post_title' => __( 'Auto Draft' ), 'post_type' => $post_type, 'post_status' => 'auto-draft' ) );
  550.         $post = get_post( $post_id );
  551.         if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post->post_type, 'post-formats' ) && get_option( 'default_post_format' ) )
  552.             set_post_format( $post, get_option( 'default_post_format' ) );
  553.     } else {
  554.         $post = new stdClass;
  555.         $post->ID = 0;
  556.         $post->post_author = '';
  557.         $post->post_date = '';
  558.         $post->post_date_gmt = '';
  559.         $post->post_password = '';
  560.         $post->post_type = $post_type;
  561.         $post->post_status = 'draft';
  562.         $post->to_ping = '';
  563.         $post->pinged = '';
  564.         $post->comment_status = get_option( 'default_comment_status' );
  565.         $post->ping_status = get_option( 'default_ping_status' );
  566.         $post->post_pingback = get_option( 'default_pingback_flag' );
  567.         $post->post_category = get_option( 'default_category' );
  568.         $post->page_template = 'default';
  569.         $post->post_parent = 0;
  570.         $post->menu_order = 0;
  571.         $post = new WP_Post( $post );
  572.     }
  573.  
  574.     /**
  575.      * Filter the default post content initially used in the "Write Post" form.
  576.      *
  577.      * @since 1.5.0
  578.      *
  579.      * @param string  $post_content Default post content.
  580.      * @param WP_Post $post         Post object.
  581.      */
  582.     $post->post_content = apply_filters( 'default_content', $post_content, $post );
  583.  
  584.     /**
  585.      * Filter the default post title initially used in the "Write Post" form.
  586.      *
  587.      * @since 1.5.0
  588.      *
  589.      * @param string  $post_title Default post title.
  590.      * @param WP_Post $post       Post object.
  591.      */
  592.     $post->post_title = apply_filters( 'default_title', $post_title, $post );
  593.  
  594.     /**
  595.      * Filter the default post excerpt initially used in the "Write Post" form.
  596.      *
  597.      * @since 1.5.0
  598.      *
  599.      * @param string  $post_excerpt Default post excerpt.
  600.      * @param WP_Post $post         Post object.
  601.      */
  602.     $post->post_excerpt = apply_filters( 'default_excerpt', $post_excerpt, $post );
  603.     $post->post_name = '';
  604.  
  605.     return $post;
  606. }
  607.  
  608. /**
  609.  * Determine if a post exists based on title, content, and date
  610.  *
  611.  * @since 2.0.0
  612.  *
  613.  * @param string $title Post title
  614.  * @param string $content Optional post content
  615.  * @param string $date Optional post date
  616.  * @return int Post ID if post exists, 0 otherwise.
  617.  */
  618. function post_exists($title, $content = '', $date = '') {
  619.     global $wpdb;
  620.  
  621.     $post_title = wp_unslash( sanitize_post_field( 'post_title', $title, 0, 'db' ) );
  622.     $post_content = wp_unslash( sanitize_post_field( 'post_content', $content, 0, 'db' ) );
  623.     $post_date = wp_unslash( sanitize_post_field( 'post_date', $date, 0, 'db' ) );
  624.  
  625.     $query = "SELECT ID FROM $wpdb->posts WHERE 1=1";
  626.     $args = array();
  627.  
  628.     if ( !empty ( $date ) ) {
  629.         $query .= ' AND post_date = %s';
  630.         $args[] = $post_date;
  631.     }
  632.  
  633.     if ( !empty ( $title ) ) {
  634.         $query .= ' AND post_title = %s';
  635.         $args[] = $post_title;
  636.     }
  637.  
  638.     if ( !empty ( $content ) ) {
  639.         $query .= 'AND post_content = %s';
  640.         $args[] = $post_content;
  641.     }
  642.  
  643.     if ( !empty ( $args ) )
  644.         return (int) $wpdb->get_var( $wpdb->prepare($query, $args) );
  645.  
  646.     return 0;
  647. }
  648.  
  649. /**
  650.  * Creates a new post from the "Write Post" form using $_POST information.
  651.  *
  652.  * @since 2.1.0
  653.  *
  654.  * @return unknown
  655.  */
  656. function wp_write_post() {
  657.     if ( isset($_POST['post_type']) )
  658.         $ptype = get_post_type_object($_POST['post_type']);
  659.     else
  660.         $ptype = get_post_type_object('post');
  661.  
  662.     if ( !current_user_can( $ptype->cap->edit_posts ) ) {
  663.         if ( 'page' == $ptype->name )
  664.             return new WP_Error( 'edit_pages', __( 'You are not allowed to create pages on this site.' ) );
  665.         else
  666.             return new WP_Error( 'edit_posts', __( 'You are not allowed to create posts or drafts on this site.' ) );
  667.     }
  668.  
  669.     $_POST['post_mime_type'] = '';
  670.  
  671.     // Clear out any data in internal vars.
  672.     unset( $_POST['filter'] );
  673.  
  674.     // Edit don't write if we have a post id.
  675.     if ( isset( $_POST['post_ID'] ) )
  676.         return edit_post();
  677.  
  678.     if ( isset($_POST['visibility']) ) {
  679.         switch ( $_POST['visibility'] ) {
  680.             case 'public' :
  681.                 $_POST['post_password'] = '';
  682.                 break;
  683.             case 'password' :
  684.                 unset( $_POST['sticky'] );
  685.                 break;
  686.             case 'private' :
  687.                 $_POST['post_status'] = 'private';
  688.                 $_POST['post_password'] = '';
  689.                 unset( $_POST['sticky'] );
  690.                 break;
  691.         }
  692.     }
  693.  
  694.     $translated = _wp_translate_postdata( false );
  695.     if ( is_wp_error($translated) )
  696.         return $translated;
  697.  
  698.     // Create the post.
  699.     $post_ID = wp_insert_post( $_POST );
  700.     if ( is_wp_error( $post_ID ) )
  701.         return $post_ID;
  702.  
  703.     if ( empty($post_ID) )
  704.         return 0;
  705.  
  706.     add_meta( $post_ID );
  707.  
  708.     add_post_meta( $post_ID, '_edit_last', $GLOBALS['current_user']->ID );
  709.  
  710.     // Now that we have an ID we can fix any attachment anchor hrefs
  711.     _fix_attachment_links( $post_ID );
  712.  
  713.     wp_set_post_lock( $post_ID );
  714.  
  715.     return $post_ID;
  716. }
  717.  
  718. /**
  719.  * Calls wp_write_post() and handles the errors.
  720.  *
  721.  * @since 2.0.0
  722.  
  723.  * @uses wp_write_post()
  724.  * @uses is_wp_error()
  725.  * @uses wp_die()
  726.  * @return unknown
  727.  */
  728. function write_post() {
  729.     $result = wp_write_post();
  730.     if ( is_wp_error( $result ) )
  731.         wp_die( $result->get_error_message() );
  732.     else
  733.         return $result;
  734. }
  735.  
  736. //
  737. // Post Meta
  738. //
  739.  
  740. /**
  741.  * {@internal Missing Short Description}}
  742.  *
  743.  * @since 1.2.0
  744.  *
  745.  * @param unknown_type $post_ID
  746.  * @return unknown
  747.  */
  748. function add_meta( $post_ID ) {
  749.     global $wpdb;
  750.     $post_ID = (int) $post_ID;
  751.  
  752.     $metakeyselect = isset($_POST['metakeyselect']) ? wp_unslash( trim( $_POST['metakeyselect'] ) ) : '';
  753.     $metakeyinput = isset($_POST['metakeyinput']) ? wp_unslash( trim( $_POST['metakeyinput'] ) ) : '';
  754.     $metavalue = isset($_POST['metavalue']) ? $_POST['metavalue'] : '';
  755.     if ( is_string( $metavalue ) )
  756.         $metavalue = trim( $metavalue );
  757.  
  758.     if ( ('0' === $metavalue || ! empty ( $metavalue ) ) && ( ( ( '#NONE#' != $metakeyselect ) && !empty ( $metakeyselect) ) || !empty ( $metakeyinput ) ) ) {
  759.         // We have a key/value pair. If both the select and the
  760.         // input for the key have data, the input takes precedence:
  761.  
  762.         if ( '#NONE#' != $metakeyselect )
  763.             $metakey = $metakeyselect;
  764.  
  765.         if ( $metakeyinput )
  766.             $metakey = $metakeyinput; // default
  767.  
  768.         if ( is_protected_meta( $metakey, 'post' ) || ! current_user_can( 'add_post_meta', $post_ID, $metakey ) )
  769.             return false;
  770.  
  771.         $metakey = wp_slash( $metakey );
  772.  
  773.         return add_post_meta( $post_ID, $metakey, $metavalue );
  774.     }
  775.  
  776.     return false;
  777. } // add_meta
  778.  
  779. /**
  780.  * {@internal Missing Short Description}}
  781.  *
  782.  * @since 1.2.0
  783.  *
  784.  * @param unknown_type $mid
  785.  * @return unknown
  786.  */
  787. function delete_meta( $mid ) {
  788.     return delete_metadata_by_mid( 'post' , $mid );
  789. }
  790.  
  791. /**
  792.  * Get a list of previously defined keys.
  793.  *
  794.  * @since 1.2.0
  795.  *
  796.  * @return unknown
  797.  */
  798. function get_meta_keys() {
  799.     global $wpdb;
  800.  
  801.     $keys = $wpdb->get_col( "
  802.             SELECT meta_key
  803.             FROM $wpdb->postmeta
  804.             GROUP BY meta_key
  805.             ORDER BY meta_key" );
  806.  
  807.     return $keys;
  808. }
  809.  
  810. /**
  811.  * {@internal Missing Short Description}}
  812.  *
  813.  * @since 2.1.0
  814.  *
  815.  * @param unknown_type $mid
  816.  * @return unknown
  817.  */
  818. function get_post_meta_by_id( $mid ) {
  819.     return get_metadata_by_mid( 'post', $mid );
  820. }
  821.  
  822. /**
  823.  * {@internal Missing Short Description}}
  824.  *
  825.  * Some postmeta stuff.
  826.  *
  827.  * @since 1.2.0
  828.  *
  829.  * @param unknown_type $postid
  830.  * @return unknown
  831.  */
  832. function has_meta( $postid ) {
  833.     global $wpdb;
  834.  
  835.     return $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value, meta_id, post_id
  836.             FROM $wpdb->postmeta WHERE post_id = %d
  837.             ORDER BY meta_key,meta_id", $postid), ARRAY_A );
  838. }
  839.  
  840. /**
  841.  * {@internal Missing Short Description}}
  842.  *
  843.  * @since 1.2.0
  844.  *
  845.  * @param unknown_type $meta_id
  846.  * @param unknown_type $meta_key Expect Slashed
  847.  * @param unknown_type $meta_value Expect Slashed
  848.  * @return unknown
  849.  */
  850. function update_meta( $meta_id, $meta_key, $meta_value ) {
  851.     $meta_key = wp_unslash( $meta_key );
  852.     $meta_value = wp_unslash( $meta_value );
  853.  
  854.     return update_metadata_by_mid( 'post', $meta_id, $meta_value, $meta_key );
  855. }
  856.  
  857. //
  858. // Private
  859. //
  860.  
  861. /**
  862.  * Replace hrefs of attachment anchors with up-to-date permalinks.
  863.  *
  864.  * @since 2.3.0
  865.  * @access private
  866.  *
  867.  * @param int|object $post Post ID or post object.
  868.  * @return void|int|WP_Error Void if nothing fixed. 0 or WP_Error on update failure. The post ID on update success.
  869.  */
  870. function _fix_attachment_links( $post ) {
  871.     $post = get_post( $post, ARRAY_A );
  872.     $content = $post['post_content'];
  873.  
  874.     // Don't run if no pretty permalinks or post is not published, scheduled, or privately published.
  875.     if ( ! get_option( 'permalink_structure' ) || ! in_array( $post['post_status'], array( 'publish', 'future', 'private' ) ) )
  876.         return;
  877.  
  878.     // Short if there aren't any links or no '?attachment_id=' strings (strpos cannot be zero)
  879.     if ( !strpos($content, '?attachment_id=') || !preg_match_all( '/<a ([^>]+)>[\s\S]+?<\/a>/', $content, $link_matches ) )
  880.         return;
  881.  
  882.     $site_url = get_bloginfo('url');
  883.     $site_url = substr( $site_url, (int) strpos($site_url, '://') ); // remove the http(s)
  884.     $replace = '';
  885.  
  886.     foreach ( $link_matches[1] as $key => $value ) {
  887.         if ( !strpos($value, '?attachment_id=') || !strpos($value, 'wp-att-')
  888.             || !preg_match( '/href=(["\'])[^"\']*\?attachment_id=(\d+)[^"\']*\\1/', $value, $url_match )
  889.             || !preg_match( '/rel=["\'][^"\']*wp-att-(\d+)/', $value, $rel_match ) )
  890.                 continue;
  891.  
  892.         $quote = $url_match[1]; // the quote (single or double)
  893.         $url_id = (int) $url_match[2];
  894.         $rel_id = (int) $rel_match[1];
  895.  
  896.         if ( !$url_id || !$rel_id || $url_id != $rel_id || strpos($url_match[0], $site_url) === false )
  897.             continue;
  898.  
  899.         $link = $link_matches[0][$key];
  900.         $replace = str_replace( $url_match[0], 'href=' . $quote . get_attachment_link( $url_id ) . $quote, $link );
  901.  
  902.         $content = str_replace( $link, $replace, $content );
  903.     }
  904.  
  905.     if ( $replace ) {
  906.         $post['post_content'] = $content;
  907.         // Escape data pulled from DB.
  908.         $post = add_magic_quotes($post);
  909.  
  910.         return wp_update_post($post);
  911.     }
  912. }
  913.  
  914. /**
  915.  * Get all the possible statuses for a post_type
  916.  *
  917.  * @since 2.5.0
  918.  *
  919.  * @param string $type The post_type you want the statuses for
  920.  * @return array As array of all the statuses for the supplied post type
  921.  */
  922. function get_available_post_statuses($type = 'post') {
  923.     $stati = wp_count_posts($type);
  924.  
  925.     return array_keys(get_object_vars($stati));
  926. }
  927.  
  928. /**
  929.  * Run the wp query to fetch the posts for listing on the edit posts page
  930.  *
  931.  * @since 2.5.0
  932.  *
  933.  * @param array|bool $q Array of query variables to use to build the query or false to use $_GET superglobal.
  934.  * @return array
  935.  */
  936. function wp_edit_posts_query( $q = false ) {
  937.     if ( false === $q )
  938.         $q = $_GET;
  939.     $q['m'] = isset($q['m']) ? (int) $q['m'] : 0;
  940.     $q['cat'] = isset($q['cat']) ? (int) $q['cat'] : 0;
  941.     $post_stati  = get_post_stati();
  942.  
  943.     if ( isset($q['post_type']) && in_array( $q['post_type'], get_post_types() ) )
  944.         $post_type = $q['post_type'];
  945.     else
  946.         $post_type = 'post';
  947.  
  948.     $avail_post_stati = get_available_post_statuses($post_type);
  949.  
  950.     if ( isset($q['post_status']) && in_array( $q['post_status'], $post_stati ) ) {
  951.         $post_status = $q['post_status'];
  952.         $perm = 'readable';
  953.     }
  954.  
  955.     if ( isset($q['orderby']) )
  956.         $orderby = $q['orderby'];
  957.     elseif ( isset($q['post_status']) && in_array($q['post_status'], array('pending', 'draft')) )
  958.         $orderby = 'modified';
  959.  
  960.     if ( isset($q['order']) )
  961.         $order = $q['order'];
  962.     elseif ( isset($q['post_status']) && 'pending' == $q['post_status'] )
  963.         $order = 'ASC';
  964.  
  965.     $per_page = 'edit_' . $post_type . '_per_page';
  966.     $posts_per_page = (int) get_user_option( $per_page );
  967.     if ( empty( $posts_per_page ) || $posts_per_page < 1 )
  968.         $posts_per_page = 20;
  969.  
  970.     /**
  971.      * Filter the number of items per page to show for a specific 'per_page' type.
  972.      *
  973.      * The dynamic hook name, $per_page, refers to a hook name comprised of the post type,
  974.      * preceded by 'edit_', and succeeded by '_per_page', e.g. 'edit_$post_type_per_page'.
  975.      *
  976.      * Some examples of filter hooks generated here include: 'edit_attachment_per_page',
  977.      * 'edit_post_per_page', 'edit_page_per_page', etc.
  978.      *
  979.      * @since 3.0.0
  980.      *
  981.      * @param int $posts_per_page Number of posts to display per page for the given 'per_page'
  982.      *                            type. Default 20.
  983.      */
  984.     $posts_per_page = apply_filters( $per_page, $posts_per_page );
  985.  
  986.     /**
  987.      * Filter the number of posts displayed per page when specifically listing "posts".
  988.      *
  989.      * @since 2.8.0
  990.      *
  991.      * @param int    $per_page  Number of posts to be displayed. Default 20.
  992.      * @param string $post_type The post type.
  993.      */
  994.     $posts_per_page = apply_filters( 'edit_posts_per_page', $posts_per_page, $post_type );
  995.  
  996.     $query = compact('post_type', 'post_status', 'perm', 'order', 'orderby', 'posts_per_page');
  997.  
  998.     // Hierarchical types require special args.
  999.     if ( is_post_type_hierarchical( $post_type ) && !isset($orderby) ) {
  1000.         $query['orderby'] = 'menu_order title';
  1001.         $query['order'] = 'asc';
  1002.         $query['posts_per_page'] = -1;
  1003.         $query['posts_per_archive_page'] = -1;
  1004.     }
  1005.  
  1006.     if ( ! empty( $q['show_sticky'] ) )
  1007.         $query['post__in'] = (array) get_option( 'sticky_posts' );
  1008.  
  1009.     wp( $query );
  1010.  
  1011.     return $avail_post_stati;
  1012. }
  1013.  
  1014. /**
  1015.  * {@internal Missing Short Description}}
  1016.  *
  1017.  * @since 2.5.0
  1018.  *
  1019.  * @param unknown_type $type
  1020.  * @return unknown
  1021.  */
  1022. function get_available_post_mime_types($type = 'attachment') {
  1023.     global $wpdb;
  1024.  
  1025.     $types = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT post_mime_type FROM $wpdb->posts WHERE post_type = %s", $type));
  1026.     return $types;
  1027. }
  1028.  
  1029. /**
  1030.  * Executes a query for attachments. An array of WP_Query arguments
  1031.  * can be passed in, which will override the arguments set by this function.
  1032.  *
  1033.  * @since 2.5.0
  1034.  *
  1035.  * @param array|bool $q Array of query variables to use to build the query or false to use $_GET superglobal.
  1036.  * @return array
  1037.  */
  1038. function wp_edit_attachments_query( $q = false ) {
  1039.     if ( false === $q )
  1040.         $q = $_GET;
  1041.  
  1042.     $q['m']   = isset( $q['m'] ) ? (int) $q['m'] : 0;
  1043.     $q['cat'] = isset( $q['cat'] ) ? (int) $q['cat'] : 0;
  1044.     $q['post_type'] = 'attachment';
  1045.     $post_type = get_post_type_object( 'attachment' );
  1046.     $states = 'inherit';
  1047.     if ( current_user_can( $post_type->cap->read_private_posts ) )
  1048.         $states .= ',private';
  1049.  
  1050.     $q['post_status'] = isset( $q['status'] ) && 'trash' == $q['status'] ? 'trash' : $states;
  1051.     $media_per_page = (int) get_user_option( 'upload_per_page' );
  1052.     if ( empty( $media_per_page ) || $media_per_page < 1 )
  1053.         $media_per_page = 20;
  1054.  
  1055.     /**
  1056.      * Filter the number of items to list per page when listing media items.
  1057.      *
  1058.      * @since 2.9.0
  1059.      *
  1060.      * @param int $media_per_page Number of media to list. Default 20.
  1061.      */
  1062.     $q['posts_per_page'] = apply_filters( 'upload_per_page', $media_per_page );
  1063.  
  1064.     $post_mime_types = get_post_mime_types();
  1065.     $avail_post_mime_types = get_available_post_mime_types('attachment');
  1066.  
  1067.     if ( isset($q['post_mime_type']) && !array_intersect( (array) $q['post_mime_type'], array_keys($post_mime_types) ) )
  1068.         unset($q['post_mime_type']);
  1069.  
  1070.     if ( isset($q['detached']) )
  1071.         $q['post_parent'] = 0;
  1072.  
  1073.     wp( $q );
  1074.  
  1075.     return array($post_mime_types, $avail_post_mime_types);
  1076. }
  1077.  
  1078. /**
  1079.  * Returns the list of classes to be used by a metabox
  1080.  *
  1081.  * @uses get_user_option()
  1082.  * @since 2.5.0
  1083.  *
  1084.  * @param unknown_type $id
  1085.  * @param unknown_type $page
  1086.  * @return unknown
  1087.  */
  1088. function postbox_classes( $id, $page ) {
  1089.     if ( isset( $_GET['edit'] ) && $_GET['edit'] == $id ) {
  1090.         $classes = array( '' );
  1091.     } elseif ( $closed = get_user_option('closedpostboxes_'.$page ) ) {
  1092.         if ( !is_array( $closed ) ) {
  1093.             $classes = array( '' );
  1094.         } else {
  1095.             $classes = in_array( $id, $closed ) ? array( 'closed' ) : array( '' );
  1096.         }
  1097.     } else {
  1098.         $classes = array( '' );
  1099.     }
  1100.  
  1101.     /**
  1102.      * Filter the postbox classes for a specific screen and screen ID combo.
  1103.      *
  1104.      * The dynamic portions of the hook name, $page, and $id, refer to
  1105.      * the screen, and screen ID, respectively.
  1106.      *
  1107.      * @since 3.2.0
  1108.      *
  1109.      * @param array $classes An array of postbox classes.
  1110.      */
  1111.     $classes = apply_filters( "postbox_classes_{$page}_{$id}", $classes );
  1112.     return implode( ' ', $classes );
  1113. }
  1114.  
  1115. /**
  1116.  * {@internal Missing Short Description}}
  1117.  *
  1118.  * @since 2.5.0
  1119.  *
  1120.  * @param int|object $id    Post ID or post object.
  1121.  * @param string $title (optional) Title
  1122.  * @param string $name (optional) Name
  1123.  * @return array With two entries of type string
  1124.  */
  1125. function get_sample_permalink($id, $title = null, $name = null) {
  1126.     $post = get_post( $id );
  1127.     if ( ! $post )
  1128.         return array( '', '' );
  1129.  
  1130.     $ptype = get_post_type_object($post->post_type);
  1131.  
  1132.     $original_status = $post->post_status;
  1133.     $original_date = $post->post_date;
  1134.     $original_name = $post->post_name;
  1135.  
  1136.     // Hack: get_permalink() would return ugly permalink for drafts, so we will fake that our post is published.
  1137.     if ( in_array( $post->post_status, array( 'draft', 'pending' ) ) ) {
  1138.         $post->post_status = 'publish';
  1139.         $post->post_name = sanitize_title($post->post_name ? $post->post_name : $post->post_title, $post->ID);
  1140.     }
  1141.  
  1142.     // If the user wants to set a new name -- override the current one
  1143.     // Note: if empty name is supplied -- use the title instead, see #6072
  1144.     if ( !is_null($name) )
  1145.         $post->post_name = sanitize_title($name ? $name : $title, $post->ID);
  1146.  
  1147.     $post->post_name = wp_unique_post_slug($post->post_name, $post->ID, $post->post_status, $post->post_type, $post->post_parent);
  1148.  
  1149.     $post->filter = 'sample';
  1150.  
  1151.     $permalink = get_permalink($post, true);
  1152.  
  1153.     // Replace custom post_type Token with generic pagename token for ease of use.
  1154.     $permalink = str_replace("%$post->post_type%", '%pagename%', $permalink);
  1155.  
  1156.     // Handle page hierarchy
  1157.     if ( $ptype->hierarchical ) {
  1158.         $uri = get_page_uri($post);
  1159.         $uri = untrailingslashit($uri);
  1160.         $uri = strrev( stristr( strrev( $uri ), '/' ) );
  1161.         $uri = untrailingslashit($uri);
  1162.  
  1163.         /** This filter is documented in wp-admin/edit-tag-form.php */
  1164.         $uri = apply_filters( 'editable_slug', $uri );
  1165.         if ( !empty($uri) )
  1166.             $uri .= '/';
  1167.         $permalink = str_replace('%pagename%', "{$uri}%pagename%", $permalink);
  1168.     }
  1169.  
  1170.     /** This filter is documented in wp-admin/edit-tag-form.php */
  1171.     $permalink = array( $permalink, apply_filters( 'editable_slug', $post->post_name ) );
  1172.     $post->post_status = $original_status;
  1173.     $post->post_date = $original_date;
  1174.     $post->post_name = $original_name;
  1175.     unset($post->filter);
  1176.  
  1177.     return $permalink;
  1178. }
  1179.  
  1180. /**
  1181.  * Returns the HTML of the sample permalink slug editor.
  1182.  *
  1183.  * @since 2.5.0
  1184.  *
  1185.  * @param int|object $id Post ID or post object.
  1186.  * @param string $new_title Optional. New title.
  1187.  * @param string $new_slug Optional. New slug.
  1188.  * @return string The HTML of the sample permalink slug editor.
  1189.  */
  1190. function get_sample_permalink_html( $id, $new_title = null, $new_slug = null ) {
  1191.     $post = get_post( $id );
  1192.     if ( ! $post )
  1193.         return '';
  1194.  
  1195.     list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug);
  1196.  
  1197.     if ( current_user_can( 'read_post', $post->ID ) ) {
  1198.         $ptype = get_post_type_object( $post->post_type );
  1199.         $view_post = $ptype->labels->view_item;
  1200.     }
  1201.  
  1202.     if ( 'publish' == get_post_status( $post ) ) {
  1203.         $title = __('Click to edit this part of the permalink');
  1204.     } else {
  1205.         $title = __('Temporary permalink. Click to edit this part.');
  1206.     }
  1207.  
  1208.     if ( false === strpos($permalink, '%postname%') && false === strpos($permalink, '%pagename%') ) {
  1209.         $return = '<strong>' . __('Permalink:') . "</strong>\n" . '<span id="sample-permalink" tabindex="-1">' . $permalink . "</span>\n";
  1210.         if ( '' == get_option( 'permalink_structure' ) && current_user_can( 'manage_options' ) && !( 'page' == get_option('show_on_front') && $id == get_option('page_on_front') ) )
  1211.             $return .= '<span id="change-permalinks"><a href="options-permalink.php" class="button button-small" target="_blank">' . __('Change Permalinks') . "</a></span>\n";
  1212.         if ( isset( $view_post ) )
  1213.             $return .= "<span id='view-post-btn'><a href='$permalink' class='button button-small'>$view_post</a></span>\n";
  1214.  
  1215.         /**
  1216.          * Filter the sample permalink HTML markup.
  1217.          *
  1218.          * @since 2.9.0
  1219.          *
  1220.          * @param string      $return    Sample permalink HTML markup.
  1221.          * @param int|WP_Post $id        Post object or ID.
  1222.          * @param string      $new_title New sample permalink title.
  1223.          * @param string      $new_slug  New sample permalink slug.
  1224.          */
  1225.         $return = apply_filters( 'get_sample_permalink_html', $return, $id, $new_title, $new_slug );
  1226.  
  1227.         return $return;
  1228.     }
  1229.  
  1230.     if ( function_exists('mb_strlen') ) {
  1231.         if ( mb_strlen($post_name) > 30 ) {
  1232.             $post_name_abridged = mb_substr($post_name, 0, 14). '&hellip;' . mb_substr($post_name, -14);
  1233.         } else {
  1234.             $post_name_abridged = $post_name;
  1235.         }
  1236.     } else {
  1237.         if ( strlen($post_name) > 30 ) {
  1238.             $post_name_abridged = substr($post_name, 0, 14). '&hellip;' . substr($post_name, -14);
  1239.         } else {
  1240.             $post_name_abridged = $post_name;
  1241.         }
  1242.     }
  1243.  
  1244.     $post_name_html = '<span id="editable-post-name" title="' . $title . '">' . $post_name_abridged . '</span>';
  1245.     $display_link = str_replace(array('%pagename%','%postname%'), $post_name_html, $permalink);
  1246.     $view_link = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
  1247.     $return =  '<strong>' . __('Permalink:') . "</strong>\n";
  1248.     $return .= '<span id="sample-permalink" tabindex="-1">' . $display_link . "</span>\n";
  1249.     $return .= '&lrm;'; // Fix bi-directional text display defect in RTL languages.
  1250.     $return .= '<span id="edit-slug-buttons"><a href="#post_name" class="edit-slug button button-small hide-if-no-js" onclick="editPermalink(' . $id . '); return false;">' . __('Edit') . "</a></span>\n";
  1251.     $return .= '<span id="editable-post-name-full">' . $post_name . "</span>\n";
  1252.  
  1253.     if ( isset( $view_post ) ) {
  1254.         $return .= "<span id='view-post-btn'><a href='" . get_permalink( $post ) . "' class='button button-small'>$view_post</a></span>\n";
  1255.     }
  1256.  
  1257.     /** This filter is documented in wp-admin/includes/post.php */
  1258.     $return = apply_filters( 'get_sample_permalink_html', $return, $id, $new_title, $new_slug );
  1259.  
  1260.     return $return;
  1261. }
  1262.  
  1263. /**
  1264.  * Output HTML for the post thumbnail meta-box.
  1265.  *
  1266.  * @since 2.9.0
  1267.  *
  1268.  * @param int $thumbnail_id ID of the attachment used for thumbnail
  1269.  * @param mixed $post The post ID or object associated with the thumbnail, defaults to global $post.
  1270.  * @return string html
  1271.  */
  1272. function _wp_post_thumbnail_html( $thumbnail_id = null, $post = null ) {
  1273.     global $content_width, $_wp_additional_image_sizes;
  1274.  
  1275.     $post = get_post( $post );
  1276.  
  1277.     $upload_iframe_src = esc_url( get_upload_iframe_src('image', $post->ID ) );
  1278.     $set_thumbnail_link = '<p class="hide-if-no-js"><a title="' . esc_attr__( 'Set featured image' ) . '" href="%s" id="set-post-thumbnail" class="thickbox">%s</a></p>';
  1279.     $content = sprintf( $set_thumbnail_link, $upload_iframe_src, esc_html__( 'Set featured image' ) );
  1280.  
  1281.     if ( $thumbnail_id && get_post( $thumbnail_id ) ) {
  1282.         $old_content_width = $content_width;
  1283.         $content_width = 266;
  1284.         if ( !isset( $_wp_additional_image_sizes['post-thumbnail'] ) )
  1285.             $thumbnail_html = wp_get_attachment_image( $thumbnail_id, array( $content_width, $content_width ) );
  1286.         else
  1287.             $thumbnail_html = wp_get_attachment_image( $thumbnail_id, 'post-thumbnail' );
  1288.         if ( !empty( $thumbnail_html ) ) {
  1289.             $ajax_nonce = wp_create_nonce( 'set_post_thumbnail-' . $post->ID );
  1290.             $content = sprintf( $set_thumbnail_link, $upload_iframe_src, $thumbnail_html );
  1291.             $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>';
  1292.         }
  1293.         $content_width = $old_content_width;
  1294.     }
  1295.  
  1296.     /**
  1297.      * Filter the admin post thumbnail HTML markup to return.
  1298.      *
  1299.      * @since 2.9.0
  1300.      *
  1301.      * @param string $content Admin post thumbnail HTML markup.
  1302.      * @param int    $post_id Post ID.
  1303.      */
  1304.     return apply_filters( 'admin_post_thumbnail_html', $content, $post->ID );
  1305. }
  1306.  
  1307. /**
  1308.  * Check to see if the post is currently being edited by another user.
  1309.  *
  1310.  * @since 2.5.0
  1311.  *
  1312.  * @param int $post_id ID of the post to check for editing
  1313.  * @return bool|int False: not locked or locked by current user. Int: user ID of user with lock.
  1314.  */
  1315. function wp_check_post_lock( $post_id ) {
  1316.     if ( !$post = get_post( $post_id ) )
  1317.         return false;
  1318.  
  1319.     if ( !$lock = get_post_meta( $post->ID, '_edit_lock', true ) )
  1320.         return false;
  1321.  
  1322.     $lock = explode( ':', $lock );
  1323.     $time = $lock[0];
  1324.     $user = isset( $lock[1] ) ? $lock[1] : get_post_meta( $post->ID, '_edit_last', true );
  1325.  
  1326.     /** This filter is documented in wp-admin/includes/ajax-actions.php */
  1327.     $time_window = apply_filters( 'wp_check_post_lock_window', 150 );
  1328.  
  1329.     if ( $time && $time > time() - $time_window && $user != get_current_user_id() )
  1330.         return $user;
  1331.     return false;
  1332. }
  1333.  
  1334. /**
  1335.  * Mark the post as currently being edited by the current user
  1336.  *
  1337.  * @since 2.5.0
  1338.  *
  1339.  * @param int $post_id ID of the post to being edited
  1340.  * @return bool|array Returns false if the post doesn't exist of there is no current user, or
  1341.  *  an array of the lock time and the user ID.
  1342.  */
  1343. function wp_set_post_lock( $post_id ) {
  1344.     if ( !$post = get_post( $post_id ) )
  1345.         return false;
  1346.     if ( 0 == ($user_id = get_current_user_id()) )
  1347.         return false;
  1348.  
  1349.     $now = time();
  1350.     $lock = "$now:$user_id";
  1351.  
  1352.     update_post_meta( $post->ID, '_edit_lock', $lock );
  1353.     return array( $now, $user_id );
  1354. }
  1355.  
  1356. /**
  1357.  * Outputs the HTML for the notice to say that someone else is editing or has taken over editing of this post.
  1358.  *
  1359.  * @since 2.8.5
  1360.  * @return none
  1361.  */
  1362. function _admin_notice_post_locked() {
  1363.     if ( ! $post = get_post() )
  1364.         return;
  1365.  
  1366.     $user = null;
  1367.     if (  $user_id = wp_check_post_lock( $post->ID ) )
  1368.         $user = get_userdata( $user_id );
  1369.  
  1370.     if ( $user ) {
  1371.  
  1372.         /**
  1373.          * Filter whether to show the post locked dialog.
  1374.          *
  1375.          * Returning a falsey value to the filter will short-circuit displaying the dialog.
  1376.          *
  1377.          * @since 3.6.0
  1378.          *
  1379.          * @param bool         $display Whether to display the dialog. Default true.
  1380.          * @param WP_User|bool $user    WP_User object on success, false otherwise.
  1381.          */
  1382.         if ( ! apply_filters( 'show_post_locked_dialog', true, $post, $user ) )
  1383.             return;
  1384.  
  1385.         $locked = true;
  1386.     } else {
  1387.         $locked = false;
  1388.     }
  1389.  
  1390.     if ( $locked && ( $sendback = wp_get_referer() ) &&
  1391.         false === strpos( $sendback, 'post.php' ) && false === strpos( $sendback, 'post-new.php' ) ) {
  1392.  
  1393.         $sendback_text = __('Go back');
  1394.     } else {
  1395.         $sendback = admin_url( 'edit.php' );
  1396.  
  1397.         if ( 'post' != $post->post_type )
  1398.             $sendback = add_query_arg( 'post_type', $post->post_type, $sendback );
  1399.  
  1400.         $sendback_text = get_post_type_object( $post->post_type )->labels->all_items;
  1401.     }
  1402.  
  1403.     $hidden = $locked ? '' : ' hidden';
  1404.  
  1405.     ?>
  1406.     <div id="post-lock-dialog" class="notification-dialog-wrap<?php echo $hidden; ?>">
  1407.     <div class="notification-dialog-background"></div>
  1408.     <div class="notification-dialog">
  1409.     <?php
  1410.  
  1411.     if ( $locked ) {
  1412.         if ( get_post_type_object( $post->post_type )->public ) {
  1413.             $preview_link = set_url_scheme( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) );
  1414.  
  1415.             if ( 'publish' == $post->post_status || $user->ID != $post->post_author ) {
  1416.                 // Latest content is in autosave
  1417.                 $nonce = wp_create_nonce( 'post_preview_' . $post->ID );
  1418.                 $preview_link = add_query_arg( array( 'preview_id' => $post->ID, 'preview_nonce' => $nonce ), $preview_link );
  1419.             }
  1420.         } else {
  1421.             $preview_link = '';
  1422.         }
  1423.  
  1424.         /** This filter is documented in wp-admin/includes/meta-boxes.php */
  1425.         $preview_link = apply_filters( 'preview_post_link', $preview_link );
  1426.  
  1427.         /**
  1428.          * Filter whether to allow the post lock to be overridden.
  1429.          *
  1430.          * Returning a falsey value to the filter will disable the ability
  1431.          * to override the post lock.
  1432.          *
  1433.          * @since 3.6.0
  1434.          *
  1435.          * @param bool    $override Whether to allow overriding post locks. Default true.
  1436.          * @param WP_Post $post     Post object.
  1437.          * @param WP_User $user     User object.
  1438.          */
  1439.         $override = apply_filters( 'override_post_lock', true, $post, $user );
  1440.         $tab_last = $override ? '' : ' wp-tab-last';
  1441.  
  1442.         ?>
  1443.         <div class="post-locked-message">
  1444.         <div class="post-locked-avatar"><?php echo get_avatar( $user->ID, 64 ); ?></div>
  1445.         <p class="currently-editing wp-tab-first" tabindex="0">
  1446.         <?php
  1447.             _e( 'This content is currently locked.' );
  1448.             if ( $override )
  1449.                 printf( ' ' . __( 'If you take over, %s will be blocked from continuing to edit.' ), esc_html( $user->display_name ) );
  1450.         ?>
  1451.         </p>
  1452.         <?php
  1453.         /**
  1454.          * Fires inside the post locked dialog before the buttons are displayed.
  1455.          *
  1456.          * @since 3.6.0
  1457.          *
  1458.          * @param WP_Post $post Post object.
  1459.          */
  1460.         do_action( 'post_locked_dialog', $post );
  1461.         ?>
  1462.         <p>
  1463.         <a class="button" href="<?php echo esc_url( $sendback ); ?>"><?php echo $sendback_text; ?></a>
  1464.         <?php if ( $preview_link ) { ?>
  1465.         <a class="button<?php echo $tab_last; ?>" href="<?php echo esc_url( $preview_link ); ?>"><?php _e('Preview'); ?></a>
  1466.         <?php
  1467.         }
  1468.  
  1469.         // Allow plugins to prevent some users overriding the post lock
  1470.         if ( $override ) {
  1471.             ?>
  1472.             <a class="button button-primary wp-tab-last" href="<?php echo esc_url( add_query_arg( 'get-post-lock', '1', wp_nonce_url( get_edit_post_link( $post->ID, 'url' ), 'lock-post_' . $post->ID ) ) ); ?>"><?php _e('Take over'); ?></a>
  1473.             <?php
  1474.         }
  1475.  
  1476.         ?>
  1477.         </p>
  1478.         </div>
  1479.         <?php
  1480.     } else {
  1481.         ?>
  1482.         <div class="post-taken-over">
  1483.             <div class="post-locked-avatar"></div>
  1484.             <p class="wp-tab-first" tabindex="0">
  1485.             <span class="currently-editing"></span><br>
  1486.             <span class="locked-saving hidden"><img src="images/wpspin_light-2x.gif" width="16" height="16" /> <?php _e('Saving revision...'); ?></span>
  1487.             <span class="locked-saved hidden"><?php _e('Your latest changes were saved as a revision.'); ?></span>
  1488.             </p>
  1489.             <?php
  1490.             /**
  1491.              * Fires inside the dialog displayed when a user has lost the post lock.
  1492.              *
  1493.              * @since 3.6.0
  1494.              *
  1495.              * @param WP_Post $post Post object.
  1496.              */
  1497.             do_action( 'post_lock_lost_dialog', $post );
  1498.             ?>
  1499.             <p><a class="button button-primary wp-tab-last" href="<?php echo esc_url( $sendback ); ?>"><?php echo $sendback_text; ?></a></p>
  1500.         </div>
  1501.         <?php
  1502.     }
  1503.  
  1504.     ?>
  1505.     </div>
  1506.     </div>
  1507.     <?php
  1508. }
  1509.  
  1510. /**
  1511.  * Creates autosave data for the specified post from $_POST data.
  1512.  *
  1513.  * @package WordPress
  1514.  * @subpackage Post_Revisions
  1515.  * @since 2.6.0
  1516.  *
  1517.  * @uses _wp_translate_postdata()
  1518.  * @uses _wp_post_revision_fields()
  1519.  *
  1520.  * @param mixed $post_data Associative array containing the post data or int post ID.
  1521.  * @return mixed The autosave revision ID. WP_Error or 0 on error.
  1522.  */
  1523. function wp_create_post_autosave( $post_data ) {
  1524.     if ( is_numeric( $post_data ) ) {
  1525.         $post_id = $post_data;
  1526.         $post_data = &$_POST;
  1527.     } else {
  1528.         $post_id = (int) $post_data['post_ID'];
  1529.     }
  1530.  
  1531.     $post_data = _wp_translate_postdata( true, $post_data );
  1532.     if ( is_wp_error( $post_data ) )
  1533.         return $post_data;
  1534.  
  1535.     $post_author = get_current_user_id();
  1536.  
  1537.     // Store one autosave per author. If there is already an autosave, overwrite it.
  1538.     if ( $old_autosave = wp_get_post_autosave( $post_id, $post_author ) ) {
  1539.         $new_autosave = _wp_post_revision_fields( $post_data, true );
  1540.         $new_autosave['ID'] = $old_autosave->ID;
  1541.         $new_autosave['post_author'] = $post_author;
  1542.  
  1543.         // If the new autosave has the same content as the post, delete the autosave.
  1544.         $post = get_post( $post_id );
  1545.         $autosave_is_different = false;
  1546.         foreach ( array_intersect( array_keys( $new_autosave ), array_keys( _wp_post_revision_fields() ) ) as $field ) {
  1547.             if ( normalize_whitespace( $new_autosave[ $field ] ) != normalize_whitespace( $post->$field ) ) {
  1548.                 $autosave_is_different = true;
  1549.                 break;
  1550.             }
  1551.         }
  1552.  
  1553.         if ( ! $autosave_is_different ) {
  1554.             wp_delete_post_revision( $old_autosave->ID );
  1555.             return 0;
  1556.         }
  1557.  
  1558.         return wp_update_post( $new_autosave );
  1559.     }
  1560.  
  1561.     // _wp_put_post_revision() expects unescaped.
  1562.     $post_data = wp_unslash( $post_data );
  1563.  
  1564.     // Otherwise create the new autosave as a special post revision
  1565.     return _wp_put_post_revision( $post_data, true );
  1566. }
  1567.  
  1568. /**
  1569.  * Save draft or manually autosave for showing preview.
  1570.  *
  1571.  * @package WordPress
  1572.  * @since 2.7.0
  1573.  *
  1574.  * @uses get_post_status()
  1575.  * @uses edit_post()
  1576.  * @uses get_post()
  1577.  * @uses current_user_can()
  1578.  * @uses wp_die()
  1579.  * @uses wp_create_post_autosave()
  1580.  * @uses add_query_arg()
  1581.  * @uses wp_create_nonce()
  1582.  *
  1583.  * @return str URL to redirect to show the preview
  1584.  */
  1585. function post_preview() {
  1586.  
  1587.     $post_ID = (int) $_POST['post_ID'];
  1588.     $_POST['ID'] = $post_ID;
  1589.  
  1590.     if ( ! $post = get_post( $post_ID ) ) {
  1591.         wp_die( __( 'You are not allowed to edit this post.' ) );
  1592.     }
  1593.  
  1594.     if ( ! current_user_can( 'edit_post', $post->ID ) ) {
  1595.         wp_die( __( 'You are not allowed to edit this post.' ) );
  1596.     }
  1597.  
  1598.     $is_autosave = false;
  1599.  
  1600.     if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() == $post->post_author && ( 'draft' == $post->post_status || 'auto-draft' == $post->post_status ) ) {
  1601.         $saved_post_id = edit_post();
  1602.     } else {
  1603.         $is_autosave = true;
  1604.  
  1605.         if ( 'auto-draft' == $_POST['post_status'] )
  1606.             $_POST['post_status'] = 'draft';
  1607.  
  1608.         $saved_post_id = wp_create_post_autosave( $post->ID );
  1609.     }
  1610.  
  1611.     if ( is_wp_error( $saved_post_id ) )
  1612.         wp_die( $saved_post_id->get_error_message() );
  1613.  
  1614.     $query_args = array( 'preview' => 'true' );
  1615.  
  1616.     if ( $is_autosave && $saved_post_id ) {
  1617.         $query_args['preview_id'] = $post->ID;
  1618.         $query_args['preview_nonce'] = wp_create_nonce( 'post_preview_' . $post->ID );
  1619.  
  1620.         if ( isset( $_POST['post_format'] ) )
  1621.             $query_args['post_format'] = empty( $_POST['post_format'] ) ? 'standard' : sanitize_key( $_POST['post_format'] );
  1622.     }
  1623.  
  1624.     $url = add_query_arg( $query_args, get_permalink( $post->ID ) );
  1625.  
  1626.     /** This filter is documented in wp-admin/includes/meta-boxes.php */
  1627.     return apply_filters( 'preview_post_link', $url );
  1628. }
  1629.  
  1630. /**
  1631.  * Save a post submitted with XHR
  1632.  *
  1633.  * Intended for use with heartbeat and autosave.js
  1634.  *
  1635.  * @since 3.9
  1636.  *
  1637.  * @param $post_data Associative array of the submitted post data.
  1638.  * @return mixed The value 0 or WP_Error on failure. The saved post ID on success.
  1639.  *               Te ID can be the draft post_id or the autosave revision post_id.
  1640.  */
  1641. function wp_autosave( $post_data ) {
  1642.     // Back-compat
  1643.     if ( ! defined( 'DOING_AUTOSAVE' ) )
  1644.         define( 'DOING_AUTOSAVE', true );
  1645.  
  1646.     $post_id = (int) $post_data['post_id'];
  1647.     $post_data['ID'] = $post_data['post_ID'] = $post_id;
  1648.  
  1649.     if ( false === wp_verify_nonce( $post_data['_wpnonce'], 'update-post_' . $post_id ) ) {
  1650.         return new WP_Error( 'invalid_nonce', __( 'Error while saving.' ) );
  1651.     }
  1652.  
  1653.     $post = get_post( $post_id );
  1654.  
  1655.     if ( ! current_user_can( 'edit_post', $post->ID ) ) {
  1656.         return new WP_Error( 'edit_posts', __( 'You are not allowed to edit this item.' ) );
  1657.     }
  1658.  
  1659.     if ( 'auto-draft' == $post->post_status )
  1660.         $post_data['post_status'] = 'draft';
  1661.  
  1662.     if ( $post_data['post_type'] != 'page' && ! empty( $post_data['catslist'] ) )
  1663.         $post_data['post_category'] = explode( ',', $post_data['catslist'] );
  1664.  
  1665.     if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() == $post->post_author && ( 'auto-draft' == $post->post_status || 'draft' == $post->post_status ) ) {
  1666.         // Drafts and auto-drafts are just overwritten by autosave for the same user if the post is not locked
  1667.         return edit_post( wp_slash( $post_data ) );
  1668.     } else {
  1669.         // Non drafts or other users drafts are not overwritten. The autosave is stored in a special post revision for each user.
  1670.         return wp_create_post_autosave( wp_slash( $post_data ) );
  1671.     }
  1672. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement