Advertisement
Guest User

Untitled

a guest
Sep 6th, 2016
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 18.42 KB | None | 0 0
  1. <?php
  2.  
  3. /**
  4.  * Plugin Name: Manage WordPress Posts Using Bulk Edit and Quick Edit
  5.  * Description: This is the code for a tutorial WP Dreamer wrote about managing WordPress posts using bulk and quick edit.
  6.  * Author: WP Dreamer
  7.  * Author URI: http://wpdreamer.com/2012/03/manage-wordpress-posts-using-bulk-edit-and-quick-edit/
  8.  */
  9.  
  10. /**
  11.  * I decided to convert the tutorial to a plugin format
  12.  * so I could easily monitor it on my development environment
  13.  * and store it on GitHub.
  14.  *
  15.  * With that said, you could easily take this code and paste it
  16.  * into your theme's functions.php file. There is, however,
  17.  * an included javascript file so be sure to check the
  18.  * manage_wp_posts_be_qe_enqueue_admin_scripts()
  19.  * function to confirm you're enqueueing the right javascript file.
  20.  *
  21.  * Also, after a few requests for custom field examples other than
  22.  * text boxes, I updated the tutorial to include a select dropdown
  23.  * and a radio button.
  24.  *
  25.  * Custom Fields:
  26.  * 'Release Date - input text
  27.  * 'Coming Soon' - input radio
  28.  * 'Film Rating' - select dropdown
  29.  *
  30.  * If you find any issues with the tutorial, or code, please let me know. Thanks!
  31.  */
  32.  
  33. /**
  34.  * Since Bulk Edit and Quick Edit hooks are triggered by custom columns,
  35.  * you must first add custom columns for the fields you wish to add, which are setup by
  36.  * 'filtering' the column information.
  37.  *
  38.  * There are 3 different column filters: 'manage_pages_columns' for pages,
  39.  * 'manage_posts_columns' which covers ALL post types (including custom post types),
  40.  * and 'manage_{$post_type_name}_posts_columns' which only covers, you guessed it,
  41.  * the columns for the defined $post_type_name.
  42.  *
  43.  * The 'manage_pages_columns' and 'manage_{$post_type_name}_posts_columns' filters only
  44.  * pass $columns (an array), which is the column info, as an argument, but 'manage_posts_columns'
  45.  * passes $columns and $post_type (a string).
  46.  *
  47.  * Note: Don't forget that it's a WordPress filter so you HAVE to return the first argument that's
  48.  * passed to the function, in this case $columns. And for filters that pass more than 1 argument,
  49.  * you have to specify the number of accepted arguments in your add_filter() declaration,
  50.  * following the priority argument.
  51.  *
  52.  */
  53. add_filter( 'manage_posts_columns', 'manage_wp_posts_be_qe_manage_posts_columns', 10, 2 );
  54. function manage_wp_posts_be_qe_manage_posts_columns( $columns, $post_type ) {
  55.  
  56.     /**
  57.      * The first example adds our new columns at the end.
  58.      * Notice that we're specifying a post type because our function covers ALL post types.
  59.      *
  60.      * Uncomment this code if you want to add your column at the end
  61.      */
  62.     if ( $post_type == 'products' ) {
  63.         $columns[ 'field_products_sale' ] = 'Sale Icon';
  64.         $columns[ 'field_products_description_under_button' ] = 'Sale Description';
  65.     }
  66.  
  67.     return $columns;
  68.  
  69.     /**
  70.      * The second example adds our new column after the �Title� column.
  71.      * Notice that we're specifying a post type because our function covers ALL post types.
  72.      */
  73.     switch ( $post_type ) {
  74.  
  75.         case 'products':
  76.  
  77.             // building a new array of column data
  78.             $new_columns = array();
  79.  
  80.             foreach( $columns as $key => $value ) {
  81.  
  82.                 // default-ly add every original column
  83.                 $new_columns[ $key ] = $value;
  84.  
  85.                 /**
  86.                  * If currently adding the title column,
  87.                  * follow immediately with our custom columns.
  88.                  */
  89.                 if ( $key == 'title' ) {
  90.                     $new_columns[ 'field_products_sale_column' ] = 'Sale Icon';
  91.                     $new_columns[ 'field_products_description_under_button_column' ] = 'Description';
  92.                 }
  93.  
  94.             }
  95.  
  96.             return $new_columns;
  97.  
  98.     }
  99.  
  100.     return $columns;
  101.  
  102. }
  103.  
  104. /**
  105.  * The following filter allows you to make your column(s) sortable.
  106.  *
  107.  * The 'edit-products' section of the filter name is the custom part
  108.  * of the filter name, which tells WordPress you want this to run
  109.  * on the main 'products' custom post type edit screen. So, e.g., if
  110.  * your custom post type's name was 'books', then the filter name
  111.  * would be 'manage_edit-books_sortable_columns'.
  112.  *
  113.  * Don't forget that filters must ALWAYS return a value.
  114.  */
  115. add_filter( 'manage_edit-products_sortable_columns', 'manage_wp_posts_be_qe_manage_sortable_columns' );
  116. function manage_wp_posts_be_qe_manage_sortable_columns( $sortable_columns ) {
  117.  
  118.     /**
  119.      * In order to make a column sortable, add the
  120.      * column data to the $sortable_columns array.
  121.      *
  122.      * I want to make my 'Release Date' column
  123.      * sortable so the array indexes (the 'field_products_sale_column'
  124.      * value between the []) need to match from
  125.      * where we added the column in the
  126.      * manage_wp_posts_be_qe_manage_posts_columns()
  127.      * function.
  128.      *
  129.      * The array value (after the =) should be set to
  130.      * identify the data that is going to be sorted,
  131.      * i.e. what will be placed in the URL when it's sorted.
  132.      * Since my release date is a custom field, I just
  133.      * use the custom field name, 'field_products_sale'.
  134.      *
  135.      * When the column is clicked, the URL will look like this:
  136.      * http://mywebsite.com/wp-admin/edit.php?post_type=products&orderby=field_products_sale&order=asc
  137.      */
  138.     $sortable_columns[ 'field_products_sale' ] = 'field_products_sale';
  139.     $sortable_columns[ 'field_products_description_under_button' ] = 'field_products_description_under_button';
  140.  
  141.     return $sortable_columns;
  142.  
  143. }
  144.  
  145. /**
  146.  * Now that we have a column, we need to fill our column with data.
  147.  * The filters to populate your custom column are pretty similar to the ones
  148.  * that added your column: 'manage_pages_custom_column', 'manage_posts_custom_column',
  149.  * and 'manage_{$post_type_name}_posts_custom_column'. All three pass the same
  150.  * 2 arguments: $column_name (a string) and the $post_id (an integer).
  151.  *
  152.  * Our custom column data is post meta so it will be a pretty simple case of retrieving
  153.  * the post meta with the meta key 'field_products_sale'.
  154.  *
  155.  * Note that we are wrapping our post meta in a div with an id of �field_products_sale-� plus the post id.
  156.  * This will come in handy when we are populating our �Quick Edit� row.
  157.  */
  158. add_action( 'manage_posts_custom_column', 'manage_wp_posts_be_qe_manage_posts_custom_column', 10, 2 );
  159. function manage_wp_posts_be_qe_manage_posts_custom_column( $column_name, $post_id ) {
  160.  
  161.     switch( $column_name ) {
  162.  
  163.         case 'field_products_sale_column':
  164.  
  165.             echo '<span class="produce-sale ' . get_post_meta( $post_id, 'products_sale', true ) . '"></span><div id="field_products_sale-' . $post_id . '">' . get_post_meta( $post_id, 'products_sale', true ) . '</div>';
  166.             break;
  167.  
  168.         case 'field_products_description_under_button_column':
  169.  
  170.             echo '<div id="products_description_under_button-' . $post_id . '">' . get_post_meta( $post_id, 'products_description_under_button', true ) . '</div>';
  171.             break;
  172.  
  173.     }
  174.  
  175. }
  176.  
  177. /**
  178.  * Just because we've made the column sortable doesn't
  179.  * mean the posts will sort by our column data. That's where
  180.  * this next 2 filters come into play.
  181.  *
  182.  * If your sort data is simple, i.e. alphabetically or numerically,
  183.  * then 'pre_get_posts' is the filter to use. This filter lets you
  184.  * change up the query before it's run.
  185.  *
  186.  * If your orderby data is more complicated, like our release date
  187.  * which is a date string stored in a custom field, then check out
  188.  * the 'posts_clauses' filter example used below.
  189.  *
  190.  * In the example below, when the main query is trying to order by
  191.  * the 'film_rating', it's a simple alphabetical sorting by a custom
  192.  * field so we're telling the query to set our 'meta_key' which is
  193.  * 'film_rating' and that we want to order by the query by the
  194.  * custom field's meta_value, e.g. PG, PG-13, R, etc.
  195.  *
  196.  * Check out http://codex.wordpress.org/Class_Reference/WP_Query
  197.  * for more info on WP Query parameters.
  198.  */
  199. add_action( 'pre_get_posts', 'manage_wp_posts_be_qe_pre_get_posts', 1 );
  200. function manage_wp_posts_be_qe_pre_get_posts( $query ) {
  201.  
  202.     /**
  203.      * We only want our code to run in the main WP query
  204.      * AND if an orderby query variable is designated.
  205.      */
  206.     if ( $query->is_main_query() && ( $orderby = $query->get( 'orderby' ) ) ) {
  207.  
  208.         switch( $orderby ) {
  209.  
  210.             // If we're ordering by 'film_rating'
  211.             case 'field_products_sale':
  212.  
  213.                 // set our query's meta_key, which is used for custom fields
  214.                 $query->set( 'meta_key', 'products_sale' );
  215.  
  216.                 /**
  217.                  * Tell the query to order by our custom field/meta_key's
  218.                  * value, in this case: PG, PG-13, R, etc.
  219.                  *
  220.                  * If your meta value are numbers, change
  221.                  * 'meta_value' to 'meta_value_num'.
  222.                  */
  223.                 $query->set( 'orderby', 'meta_value' );
  224.  
  225.                 break;
  226.  
  227.             // If we're ordering by 'film_rating'
  228.             case 'field_products_description_under_button':
  229.  
  230.                 // set our query's meta_key, which is used for custom fields
  231.                 $query->set( 'meta_key', 'products_description_under_button' );
  232.  
  233.                 /**
  234.                  * Tell the query to order by our custom field/meta_key's
  235.                  * value, in this case: PG, PG-13, R, etc.
  236.                  *
  237.                  * If your meta value are numbers, change
  238.                  * 'meta_value' to 'meta_value_num'.
  239.                  */
  240.                 $query->set( 'orderby', 'meta_value' );
  241.  
  242.                 break;
  243.  
  244.         }
  245.  
  246.     }
  247.  
  248. }
  249.  
  250. /**
  251.  * Just because we've made the column sortable doesn't
  252.  * mean the posts will sort by our column data. That's where
  253.  * the filter above, 'pre_get_posts', and the filter below,
  254.  * 'posts_clauses', come into play.
  255.  *
  256.  * If your sort data is simple, i.e. alphabetically or numerically,
  257.  * then check out the 'pre_get_posts' filter used above.
  258.  *
  259.  * If your orderby data is more complicated, like combining
  260.  * several values or a date string stored in a custom field,
  261.  * then the 'posts_clauses' filter used below is for you.
  262.  * The 'posts_clauses' filter allows you to manually tweak
  263.  * the query clauses in order to sort the posts by your
  264.  * custom column data.
  265.  *
  266.  * The reason more complicated sorts will not with the
  267.  * "out of the box" WP Query is because the WP Query orderby
  268.  * parameter will only order alphabetically and numerically.
  269.  *
  270.  * Usually I would recommend simply using the 'pre_get_posts'
  271.  * and altering the WP Query itself but because our custom
  272.  * field is a date, we have to manually set the query to
  273.  * order our posts by a date.
  274.  */
  275. add_filter( 'posts_clauses', 'manage_wp_posts_be_qe_posts_clauses', 1, 2 );
  276. function manage_wp_posts_be_qe_posts_clauses( $pieces, $query ) {
  277.     global $wpdb;
  278.  
  279.     /**
  280.      * We only want our code to run in the main WP query
  281.      * AND if an orderby query variable is designated.
  282.      */
  283.     if ( $query->is_main_query() && ( $orderby = $query->get( 'orderby' ) ) ) {
  284.  
  285.         // Get the order query variable - ASC or DESC
  286.         $order = strtoupper( $query->get( 'order' ) );
  287.  
  288.         // Make sure the order setting qualifies. If not, set default as ASC
  289.         if ( ! in_array( $order, array( 'ASC', 'DESC' ) ) )
  290.             $order = 'ASC';
  291.  
  292.         switch( $orderby ) {
  293.  
  294.             // If we're ordering by field_products_sale
  295.             case 'field_products_sale':
  296.  
  297.                 /**
  298.                  * We have to join the postmeta table to include
  299.                  * our release date in the query.
  300.                  */
  301.                 $pieces[ 'join' ] .= " LEFT JOIN $wpdb->postmeta wp_rd ON wp_rd.post_id = {$wpdb->posts}.ID AND wp_rd.meta_key = 'field_products_sale'";
  302.  
  303.                 // Then tell the query to order by our date
  304.                 $pieces[ 'orderby' ] = "STR_TO_DATE( wp_rd.meta_value,'%m/%d/%Y' ) $order, " . $pieces[ 'orderby' ];
  305.  
  306.                 break;
  307.  
  308.             // If we're ordering by field_products_sale
  309.             case 'field_products_description_under_button':
  310.  
  311.                 /**
  312.                  * We have to join the postmeta table to include
  313.                  * our release date in the query.
  314.                  */
  315.                 $pieces[ 'join' ] .= " LEFT JOIN $wpdb->postmeta wp_rd ON wp_rd.post_id = {$wpdb->posts}.ID AND wp_rd.meta_key = 'field_products_description_under_button'";
  316.  
  317.                 // Then tell the query to order by our date
  318.                 $pieces[ 'orderby' ] = "STR_TO_DATE( wp_rd.meta_value,'%m/%d/%Y' ) $order, " . $pieces[ 'orderby' ];
  319.  
  320.                 break;
  321.  
  322.         }
  323.  
  324.     }
  325.  
  326.     return $pieces;
  327.  
  328. }
  329.  
  330. /**
  331.  * Now that you have your custom column, it's bulk/quick edit showtime!
  332.  * The filters are 'bulk_edit_custom_box' and 'quick_edit_custom_box'. Both filters
  333.  * pass the same 2 arguments: the $column_name (a string) and the $post_type (a string).
  334.  *
  335.  * Your data's form fields will obviously vary so customize at will. For this example,
  336.  * we're using an input. Also take note of the css classes on the <fieldset> and <div>.
  337.  * There are a few other options like 'inline-edit-col-left' and 'inline-edit-col-center'
  338.  * for the fieldset and 'inline-edit-col' for the div. I recommend studying the WordPress
  339.  * bulk and quick edit HTML to see the best way to layout your custom fields.
  340.  */
  341.  add_action( 'bulk_edit_custom_box', 'manage_wp_posts_be_qe_bulk_quick_edit_custom_box', 10, 2 );
  342.  add_action( 'quick_edit_custom_box', 'manage_wp_posts_be_qe_bulk_quick_edit_custom_box', 10, 2 );
  343.  function manage_wp_posts_be_qe_bulk_quick_edit_custom_box( $column_name, $post_type ) {
  344.  
  345.     switch ( $post_type ) {
  346.  
  347.         case 'products':
  348.  
  349.             switch( $column_name ) {
  350.  
  351.                 case 'field_products_sale_column':
  352.  
  353.                     ?><fieldset class="inline-edit-col-left">
  354.                         <div class="inline-edit-col">
  355.                             <label>
  356.                                 <span class="title">Products Sale</span>
  357.                                 <span class="input-text-wrap">
  358.                                     <input type="text" value="" name="field_products_sale">
  359.                                 </span>
  360.                             </label>
  361.                         </div>
  362.                     </fieldset><?php
  363.                     break;
  364.  
  365.                 case 'field_products_description_under_button_column':
  366.  
  367.                     ?><fieldset class="inline-edit-col-left">
  368.                         <div class="inline-edit-col">
  369.                             <label>
  370.                                 <span class="title">Sale Description</span>
  371.                                 <span class="input-text-wrap">
  372.                                     <input type="text" value="" name="field_products_description_under_button">
  373.                                 </span>
  374.                             </label>
  375.                         </div>
  376.                     </fieldset><?php
  377.                     break;
  378.  
  379.             }
  380.  
  381.             break;
  382.  
  383.     }
  384.  
  385.  }
  386.  
  387. /**
  388.  * When you click 'Quick Edit', you may have noticed that your form fields are not populated.
  389.  * WordPress adds one 'Quick Edit' row which moves around for each post so the information cannot
  390.  * be pre-populated. It has to be populated with JavaScript on a per-post 'click Quick Edit' basis.
  391.  *
  392.  * WordPress has an inline edit post function that populates all of their default quick edit fields
  393.  * so we want to hook into this function, in a sense, to make sure our JavaScript code is run when
  394.  * needed. We will 'copy' the WP function, 'overwrite' the WP function so we're hooked in, 'call'
  395.  * the original WP function (via our copy) so WordPress is not left hanging, and then run our code.
  396.  *
  397.  * Remember where we wrapped our column data in a <div> in Step 2? This is where it comes in handy,
  398.  * allowing our Javascript to retrieve the data by the <div>'s element ID to populate our form field.
  399.  * There are other methods to retrieve your data that involve AJAX but this route is the simplest.
  400.  *
  401.  * Don't forget to enqueue your script and make sure it's dependent on WordPress's 'inline-edit-post' file.
  402.  * Since we'll be using the jQuery library, we need to make sure 'jquery' is loaded as well.
  403.  *
  404.  * I have provided several scenarios for where you've placed this code. Simply uncomment the scenario
  405.  * you're using. For all scenarios, make sure your javascript file is in the same folder as your code.
  406.  */
  407. add_action( 'admin_print_scripts-edit.php', 'manage_wp_posts_be_qe_enqueue_admin_scripts' );
  408. function manage_wp_posts_be_qe_enqueue_admin_scripts() {
  409.  
  410.     // if code is in theme functions.php file
  411.     //wp_enqueue_script( 'manage-wp-posts-using-bulk-quick-edit', trailingslashit( get_bloginfo( 'stylesheet_directory' ) ) . 'bulk_quick_edit.js', array( 'jquery', 'inline-edit-post' ), '', true );
  412.  
  413.     // if using code as plugin
  414.     wp_enqueue_script( 'manage-wp-posts-using-bulk-quick-edit', trailingslashit( plugin_dir_url( __FILE__ ) ) . 'bulk_quick_edit.js', array( 'jquery', 'inline-edit-post' ), '', true );
  415.  
  416. }
  417.  
  418. /**
  419.  * Saving your 'Quick Edit' data is exactly like saving custom data
  420.  * when editing a post, using the 'save_post' hook. With that said,
  421.  * you may have already set this up. If you're not sure, and your
  422.  * 'Quick Edit' data is not saving, odds are you need to hook into
  423.  * the 'save_post' action.
  424.  *
  425.  * The 'save_post' action passes 2 arguments: the $post_id (an integer)
  426.  * and the $post information (an object).
  427.  */
  428. add_action( 'save_post', 'save_quick_edit_custom_fields', 10, 2 );
  429. function save_quick_edit_custom_fields( $post_id, $post ) {
  430.  
  431.     // pointless if $_POST is empty (this happens on bulk edit)
  432.     if ( empty( $_POST ) )
  433.         return $post_id;
  434.  
  435.     // verify quick edit nonce
  436.     if ( isset( $_POST[ '_inline_edit' ] ) && ! wp_verify_nonce( $_POST[ '_inline_edit' ], 'inlineeditnonce' ) )
  437.         return $post_id;
  438.  
  439.     // don't save for autosave
  440.     if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
  441.         return $post_id;
  442.  
  443.     // dont save for revisions
  444.     if ( isset( $post->post_type ) && $post->post_type == 'revision' )
  445.         return $post_id;
  446.  
  447.     switch( $post->post_type ) {
  448.  
  449.         case 'products':
  450.  
  451.             /**
  452.              * Because this action is run in several places, checking for the array key
  453.              * keeps WordPress from editing data that wasn't in the form, i.e. if you had
  454.              * this post meta on your "Quick Edit" but didn't have it on the "Edit Post" screen.
  455.              */
  456.             $custom_fields = array( 'products_sale', 'products_description_under_button' );
  457.  
  458.             foreach( $custom_fields as $field ) {
  459.  
  460.                 if ( array_key_exists( $field, $_POST ) )
  461.                     update_post_meta( $post_id, $field, $_POST[ $field ] );
  462.  
  463.             }
  464.  
  465.             break;
  466.  
  467.     }
  468.  
  469. }
  470.  
  471. /**
  472.  * Saving the 'Bulk Edit' data is a little trickier because we have
  473.  * to get JavaScript involved. WordPress saves their bulk edit data
  474.  * via AJAX so, guess what, so do we.
  475.  *
  476.  * Your javascript will run an AJAX function to save your data.
  477.  * This is the WordPress AJAX function that will handle and save your data.
  478.  */
  479. add_action( 'wp_ajax_manage_wp_posts_using_bulk_quick_save_bulk_edit', 'manage_wp_posts_using_bulk_quick_save_bulk_edit' );
  480. function manage_wp_posts_using_bulk_quick_save_bulk_edit() {
  481.  
  482.     // we need the post IDs
  483.     $post_ids = ( isset( $_POST[ 'post_ids' ] ) && !empty( $_POST[ 'post_ids' ] ) ) ? $_POST[ 'post_ids' ] : NULL;
  484.  
  485.     // if we have post IDs
  486.     if ( ! empty( $post_ids ) && is_array( $post_ids ) ) {
  487.  
  488.         // get the custom fields
  489.         $custom_fields = array( 'products_sale', 'products_description_under_button' );
  490.  
  491.         foreach( $custom_fields as $field ) {
  492.  
  493.             // if it has a value, doesn't update if empty on bulk
  494.             if ( isset( $_POST[ $field ] ) && !empty( $_POST[ $field ] ) ) {
  495.  
  496.                 // update for each post ID
  497.                 foreach( $post_ids as $post_id ) {
  498.                     update_post_meta( $post_id, $field, $_POST[ $field ] );
  499.                 }
  500.  
  501.             }
  502.  
  503.         }
  504.  
  505.     }
  506.  
  507. }
  508.  
  509. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement