From 2c14110cfd19cc9c5e6f057dc5d11f71937b3bdb Mon Sep 17 00:00:00 2001 From: Philip Hestermann Date: Fri, 5 Feb 2016 09:21:46 +0100 Subject: [PATCH] add menu change and option implementation --- assets/js/content-staging.js | 22 ++- classes/class-setup.php | 53 +++--- classes/controllers/class-batch-ctrl.php | 38 +++- classes/controllers/class-options-ctrl.php | 15 ++ classes/db/class-option-dao.php | 64 ++++++- classes/db/class-post-dao.php | 44 ++++- classes/db/class-post-taxonomy-dao.php | 25 +++ classes/importers/class-batch-importer.php | 54 +++++- classes/listeners/class-delete-listener.php | 29 +++ classes/managers/class-batch-mgr.php | 193 ++++++++++++++++++-- classes/models/class-post-taxonomy.php | 8 +- classes/view/class-menu-table.php | 103 +++++++++++ content-staging.php | 3 +- templates/edit-batch.php | 10 + 14 files changed, 583 insertions(+), 78 deletions(-) create mode 100644 classes/view/class-menu-table.php diff --git a/assets/js/content-staging.js b/assets/js/content-staging.js index 470c7cc..4b19c8c 100644 --- a/assets/js/content-staging.js +++ b/assets/js/content-staging.js @@ -48,13 +48,14 @@ jQuery( document ).ready(function($) { * cleared. */ editBatch: function() { - var self = this; - var batchId = $('#sme-batch-id').html(); - var titleObj = $('input[name="batch_title"]'); - var posts = $('.sme-select-post'); - var postIdsObj = $('input[name="post_ids"]'); - var postIds = []; - var selectAll = $('[id^=cb-select-all-]'); + var self = this; + var batchId = $('#sme-batch-id').html(); + var titleObj = $('input[name="batch_title"]'); + var posts = $('.sme-select-post'); + var postIdsObj = $('input[name="post_ids"]'); + var postIds = []; + var selectAll = $('[id^=cb-select-all-]'); + var selectAllPosts = $('.posts [id^=cb-select-all-]'); var cookie; var batch; @@ -118,17 +119,20 @@ jQuery( document ).ready(function($) { self.updateSelectedPosts(batchId, postIds, postIdsObj, titleObj.val()); }); - // User has selected/unselected all posts. + // User has selected/unselected all pages or menu items. selectAll.click(function() { var isChecked = $(this).prop('checked'); - posts.each(function() { self.selectPost(postIds, parseInt($(this).val()), isChecked); }); + }); + // User has selected/unselected all posts. + selectAllPosts.click(function() { // Update selected posts. self.updateSelectedPosts(batchId, postIds, postIdsObj, titleObj.val()); }); + }, /** diff --git a/classes/class-setup.php b/classes/class-setup.php index 09a50a0..4d77005 100644 --- a/classes/class-setup.php +++ b/classes/class-setup.php @@ -79,35 +79,28 @@ public function register_post_types() { } public function register_menu_pages() { - add_menu_page( 'Content Staging', 'Content Staging', apply_filters( 'sme-list-batches-capability', 'manage_options' ), 'sme-list-batches', array( $this->batch_ctrl, 'list_batches' ) ); - add_submenu_page( 'sme-list-batches', 'History', 'History', apply_filters( 'sme-batch-history-capability', 'manage_options' ), 'sme-batch-history', array( $this->batch_history_ctrl, 'init' ) ); - add_submenu_page( 'sme-list-batches', 'Settings', 'Settings', apply_filters( 'sme-settings-capability', 'manage_options' ), 'sme-settings', array( $this->settings_ctrl, 'init' ) ); - add_submenu_page( 'sme-list-batches', 'WordPress Options', 'WordPress Options', apply_filters( 'sme-wp-options-capability', 'manage_options' ), 'sme-wp-options', array( $this->options_ctrl, 'init' ) ); - add_submenu_page( null, 'Edit Batch', 'Edit', apply_filters( 'sme-edit-batch-capability', 'manage_options' ), 'sme-edit-batch', array( $this->batch_ctrl, 'edit_batch' ) ); - add_submenu_page( null, 'Delete Batch', 'Delete', apply_filters( 'sme-delete-batch-capability', 'manage_options' ), 'sme-delete-batch', array( $this->batch_ctrl, 'confirm_delete_batch' ) ); - add_submenu_page( null, 'Pre-Flight Batch', 'Pre-Flight', apply_filters( 'sme-preflight-batch-capability', 'manage_options' ), 'sme-preflight-batch', array( $this->batch_ctrl, 'prepare' ) ); - add_submenu_page( null, 'Quick Deploy Batch', 'Quick Deploy', apply_filters( 'sme-quick-deploy-batch-capability', 'manage_options' ), 'sme-quick-deploy-batch', array( $this->batch_ctrl, 'quick_deploy' ) ); - add_submenu_page( null, 'Deploy Batch', 'Deploy', apply_filters( 'sme-send-batch-capability', 'manage_options' ), 'sme-send-batch', array( $this->batch_ctrl, 'deploy' ) ); + add_menu_page( 'Content Staging', 'Content Staging', 'manage_options', 'sme-list-batches', array( $this->batch_ctrl, 'list_batches' ) ); + add_submenu_page( 'sme-list-batches', 'History', 'History', 'manage_options', 'sme-batch-history', array( $this->batch_history_ctrl, 'init' ) ); + add_submenu_page( 'sme-list-batches', 'Settings', 'Settings', 'manage_options', 'sme-settings', array( $this->settings_ctrl, 'init' ) ); + add_submenu_page( 'sme-list-batches', 'WordPress Options', 'WordPress Options', 'manage_options', 'sme-wp-options', array( $this->options_ctrl, 'init' ) ); + add_submenu_page( null, 'Edit Batch', 'Edit', 'manage_options', 'sme-edit-batch', array( $this->batch_ctrl, 'edit_batch' ) ); + add_submenu_page( null, 'Delete Batch', 'Delete', 'manage_options', 'sme-delete-batch', array( $this->batch_ctrl, 'confirm_delete_batch' ) ); + add_submenu_page( null, 'Pre-Flight Batch', 'Pre-Flight', 'manage_options', 'sme-preflight-batch', array( $this->batch_ctrl, 'prepare' ) ); + add_submenu_page( null, 'Quick Deploy Batch', 'Quick Deploy', 'manage_options', 'sme-quick-deploy-batch', array( $this->batch_ctrl, 'quick_deploy' ) ); + add_submenu_page( null, 'Deploy Batch', 'Deploy', 'manage_options', 'sme-send-batch', array( $this->batch_ctrl, 'deploy' ) ); } /** * Display a "Deploy To Production" button whenever a post is updated. */ - - public function quick_deploy_batch( $messages ) { - global $post; - - $post_ID = $post->ID; - $post_type = get_post_type( $post_ID ); - - $obj = get_post_type_object( $post_type ); - $singular = $obj->labels->singular_name; - - foreach ( $messages[$post_type] as $key => $message ) { - $messages[$post_type][$key] = $message . ' or Deploy To Production'; + public function quick_deploy_batch() { + if ( isset( $_GET['post'] ) && isset( $_GET['action'] ) && isset( $_GET['message'] ) && $_GET['action'] == 'edit' ) { + ?> +
+

Deploy To Production'; ?>

+
+ prepare_items(); + $menu_table = $this->get_menu_table( $batch ); + $type = get_post_type_object( 'sme_content_batch' ); if ( ! $batch->get_id() ) { $label = $type->labels->new_item; @@ -216,6 +217,7 @@ public function edit_batch() { 'label' => $label, 'filters' => $filters, 'table' => $table, + 'menu_table' => $menu_table, 'post_ids' => implode( ',', $post_ids ), 'wp_options' => $wp_options, ); @@ -852,6 +854,8 @@ private function handle_edit_batch_form_data( Batch $batch, $request_data ) { $selected_post_ids = array_map( 'intval', explode( ',', $request_data['post_ids'] ) ); } + $this->save_selected_menus( $batch, $request_data ); + // Set whether WordPress options should be included in batch or not. $this->should_include_wp_options( $batch, $request_data ); @@ -965,4 +969,34 @@ private function verify_by_type( Batch $batch, $type ) { } } + private function get_menu_table( Batch $batch ) { + + $menus = wp_get_nav_menus(); + $selected = get_post_meta( $batch->get_id(), '_sme_selected_menus', true ); + + if ( ! is_array( $selected ) ) { + $selected = array(); + } + + $table = new Menu_Table( $selected ); + $table->items = $menus; + + $table->prepare_items(); + + return $table; + } + + private function save_selected_menus( Batch $batch, array $request_data ) { + + // IDs of menus user has selected to include in this batch. + $selected_menu_ids = array(); + + // Check if any menus to include in batch has been selected. + if ( isset( $request_data['menus'] ) && $request_data['menus'] ) { + $selected_menu_ids = array_map( 'intval', $request_data['menus'] ); + } + + update_post_meta( $batch->get_id(), '_sme_selected_menus', $selected_menu_ids ); + } + } \ No newline at end of file diff --git a/classes/controllers/class-options-ctrl.php b/classes/controllers/class-options-ctrl.php index bc723d6..8b08dfd 100644 --- a/classes/controllers/class-options-ctrl.php +++ b/classes/controllers/class-options-ctrl.php @@ -180,6 +180,21 @@ private function get_blacklist( $options ) { return array_diff_key( $options, array_flip( $blacklist ) ); } + /** + * Options that should not be possible to sync to production. + * + * @return array + */ + private function get_default_blacklist() { + return array( + 'siteurl', + 'home', + 'fileupload_url', + 'sme_wp_options', + 'rewrite_rules', + ); + } + /** * Options as presented in the view. Includes presentation specific data * such as table row classes, input values etc. diff --git a/classes/db/class-option-dao.php b/classes/db/class-option-dao.php index ed3af2d..a4b7494 100644 --- a/classes/db/class-option-dao.php +++ b/classes/db/class-option-dao.php @@ -76,24 +76,72 @@ public function get_option_names_to_sync() { } /** - * Insert options. + * Get options by pattern. * - * Using the WordPress method 'update_option()' to insert/update options - * one by one. - * - * @todo Consider changing the implementation so that all options are - * imported in one query. + * @param string $pattern + * @return array + */ + public function get_option_names_by_pattern( $pattern ) { + + $options = array(); + $stmt = 'SELECT option_name FROM ' . $this->get_table() . ' WHERE option_name LIKE %s'; + $query = $this->wpdb->prepare( $stmt, $pattern ); + $result = $this->wpdb->get_results( $query, ARRAY_A ); + + foreach ( $result as $option ) { + $options[] = $option['option_name']; + } + + return $options; + } + + /** + * Update options. * * @param array $options */ - public function insert_options( array $options ) { + public function update_options( array $options ) { foreach ( $options as $option ) { if ( $option instanceof Option ) { - update_option( $option->get_name(), $option->get_value(), $option->get_autoload() ); + $old_value = get_option( $option->get_name() ); + + if ( $old_value === false ) { + $this->insert( $option ); + } else { + $this->do_update( $option ); + } } } } + /** + * Update option. Create option if it does not already exist. + * + * @param Option $option + */ + public function update_option( Option $option) { + $old_value = get_option( $option->get_name() ); + + if ( $old_value === false ) { + $this->insert( $option ); + } else { + $this->do_update( $option ); + } + } + + /** + * Update option. + * + * @param Option $option + */ + public function do_update( Option $option ) { + $data = $this->create_array( $option ); + $where = array( 'option_name' => $option->get_name() ); + $format = $this->format(); + $where_format = array( '%s' ); + $this->update( $data, $where, $format, $where_format ); + } + /** * @return string */ diff --git a/classes/db/class-post-dao.php b/classes/db/class-post-dao.php index dcca40e..046d00b 100644 --- a/classes/db/class-post-dao.php +++ b/classes/db/class-post-dao.php @@ -134,6 +134,7 @@ public function get_posts( $statuses = array(), $order_by = null, $order = 'asc' $nbr_of_selected = count( $selected ); $limit = $per_page; $values = array(); + $where = array(); if ( ( $offset = ( ( $paged - 1 ) * $per_page ) - $nbr_of_selected ) < 0 ) { $offset = 0; @@ -152,18 +153,36 @@ public function get_posts( $statuses = array(), $order_by = null, $order = 'asc' $order = 'desc'; } - $where = 'post_type != "sme_content_batch" AND post_type != "sme_batch_import_job"'; - $where = $this->where_statuses( $where, $statuses, $values ); - $where = apply_filters( 'sme_query_posts_where', $where ); - $values = apply_filters( 'sme_values_posts_where', $values ); - $stmt = 'SELECT * FROM ' . $this->wpdb->posts . ' WHERE ' . $where; + // Post type. + $blacklisted_post_types = $this->get_blacklisted_post_types(); + + if ( ( $nbr_of_blacklisted_post_types = count( $blacklisted_post_types ) ) > 0 ) { + $blacklist_placeholders = implode( ',', array_fill( 0, $nbr_of_blacklisted_post_types, '%s' ) ); + $where[] = 'post_type NOT IN (' . $blacklist_placeholders . ')'; + $values = array_merge( $values, $blacklisted_post_types ); + } + + // Post status. + if ( ( $nbr_of_post_statuses = count( $statuses ) ) > 0 ) { + $post_status_placeholders = implode( ',', array_fill( 0, $nbr_of_post_statuses, '%s' ) ); + $where[] = 'post_status IN (' . $post_status_placeholders . ')'; + $values = array_merge( $values, $statuses ); + } + // Post ID. if ( ( $nbr_of_selected = count( $selected ) ) > 0 ) { - $placeholders = implode( ',', array_fill( 0, $nbr_of_selected, '%d' ) ); - $values = array_merge( $values, $selected ); - $stmt .= ' AND ID NOT IN (' . $placeholders . ')'; + $id_placeholders = implode( ',', array_fill( 0, $nbr_of_selected, '%d' ) ); + $where[] = 'ID NOT IN (' . $id_placeholders . ')'; + $values = array_merge( $values, $selected ); } + // Implode where clauses into single where clause. + $where_clause = implode( ' AND ', $where ); + + $where_clause = apply_filters( 'sme_query_posts_where', $where_clause ); + $values = apply_filters( 'sme_values_posts_where', $values ); + $stmt = 'SELECT * FROM ' . $this->wpdb->posts . ' WHERE ' . $where_clause; + if ( ! is_null( $order_by ) ) { $stmt .= ' ORDER BY ' . $order_by . ' ' . $order; } @@ -536,4 +555,13 @@ protected function format() { ); } + private function get_blacklisted_post_types() { + + $blacklist = array( + 'sme_content_batch', 'sme_batch_import_job', 'nav_menu_item', + ); + + return apply_filters( 'sme_blacklisted_post_types', $blacklist ); + } + } diff --git a/classes/db/class-post-taxonomy-dao.php b/classes/db/class-post-taxonomy-dao.php index e9d049b..a907e46 100644 --- a/classes/db/class-post-taxonomy-dao.php +++ b/classes/db/class-post-taxonomy-dao.php @@ -38,6 +38,31 @@ public function get_post_taxonomy_relationships( Post $post ) { } } + /** + * Get IDs of all object IDs that are connected to one of the provided + * taxonomy IDs. + * + * @param array $taxonomy_ids + * @return array + */ + public function get_object_ids_by_taxonomy_ids( $taxonomy_ids ) { + + $placeholders = $this->in_clause_placeholders( $taxonomy_ids, '%d' ); + + $query = $this->wpdb->prepare( + 'SELECT object_id FROM ' . $this->get_table() . ' WHERE term_taxonomy_id in (' . $placeholders . ')', + $taxonomy_ids + ); + + $object_ids = array_map( + function( $record ) { + return (int) $record['object_id']; + }, $this->wpdb->get_results( $query, ARRAY_A ) + ); + + return $object_ids; + } + /** * Clear the Post_Taxonomy relationships informations. * diff --git a/classes/importers/class-batch-importer.php b/classes/importers/class-batch-importer.php index b1d1da8..1568c13 100644 --- a/classes/importers/class-batch-importer.php +++ b/classes/importers/class-batch-importer.php @@ -14,6 +14,7 @@ use Me\Stenberg\Content\Staging\DB\User_DAO; use Me\Stenberg\Content\Staging\Helper_Factory; use Me\Stenberg\Content\Staging\Models\Batch; +use Me\Stenberg\Content\Staging\Models\Option; use Me\Stenberg\Content\Staging\Models\Post; use Me\Stenberg\Content\Staging\Models\Post_Env_Diff; use Me\Stenberg\Content\Staging\Models\Relationships\Post_Taxonomy; @@ -358,7 +359,19 @@ public function import_post_meta( Post $post ) { * @param array $options */ public function import_options( array $options ) { - $this->option_dao->insert_options( $options ); + foreach ( $options as $option ) { + $this->import_option( $option ); + } + } + + /** + * Import option. + * + * @param Option $option + */ + public function import_option( Option $option ) { + $this->update_menu_locations( $option ); + $this->option_dao->update_option( $option ); } /** @@ -595,4 +608,43 @@ private function add_post_diff( Post_Env_Diff $diff ) { $this->post_diffs[$diff->get_stage_id()] = $diff; } } + + /** + * Update location of menus for a theme so it gets a menu ID (term ID) + * set on production instead of the slug provided from stage. + * + * @param Option $option + */ + private function update_menu_locations( Option $option ) { + + if ( 0 !== strpos( $option->get_name(), 'theme_mods_' ) ) { + return; + } + + if ( ! is_serialized( $option->get_value() ) ) { + return; + } + + $value = unserialize( $option->get_value() ); + + if ( ! is_array( $value['nav_menu_locations'] ) ) { + return; + } + + foreach ( $value['nav_menu_locations'] as &$location ) { + + if ( ! is_string( $location ) ) { + continue; + } + + $term = $this->term_dao->get_term_by_slug( $location ); + + if ( $term instanceof Term ) { + $location = $term->get_id(); + } + } + + $value['nav_menu_locations'] = array_filter( $value['nav_menu_locations'], 'is_int' ); + $option->set_value( serialize( $value ) ); + } } \ No newline at end of file diff --git a/classes/listeners/class-delete-listener.php b/classes/listeners/class-delete-listener.php index d7107cf..d55e661 100644 --- a/classes/listeners/class-delete-listener.php +++ b/classes/listeners/class-delete-listener.php @@ -59,6 +59,9 @@ public function __construct( Template $template, Common_API $api ) { // Hook in to Content Staging preparation of batch. add_action( 'sme_save_batch', array( $this, 'prepare' ) ); + // Add deleted menu items to batch. + add_action( 'sme_prepare_menu_options', array( $this, 'prepare_delete_menu_items') ); + // Hook in to Content Staging import of extension data. add_action( 'sme_import_' . $this->extension, array( $this, 'import' ), 10, 2 ); @@ -167,6 +170,32 @@ public function prepare( Batch $batch ) { $batch->add_custom_data( $this->extension, $deleted_posts ); } + /** + * Add deleted menu items to batch. + * + * @param Batch $batch + */ + public function prepare_delete_menu_items( Batch $batch ) { + + /** + * @var Custom_DAO $custom_dao + */ + $custom_dao = Helper_Factory::get_instance()->get_dao( 'Custom' ); + $deleted_posts = $custom_dao->get_deleted_posts(); + + $deleted_menu_posts = array_filter( + $deleted_posts, + function( $post ) { + return $post['title'] === ' (nav_menu_item)'; + } + ); + + $deleted_posts_in_batch = $batch->get_custom_data( $this->extension ); + $deleted_posts_in_batch = array_merge( $deleted_posts_in_batch, $deleted_menu_posts ); + + $batch->add_custom_data( $this->extension, $deleted_posts_in_batch ); + } + /** * Remove posts that has been deleted on content stage. * diff --git a/classes/managers/class-batch-mgr.php b/classes/managers/class-batch-mgr.php index 96b58fb..65186f7 100644 --- a/classes/managers/class-batch-mgr.php +++ b/classes/managers/class-batch-mgr.php @@ -9,11 +9,14 @@ use Me\Stenberg\Content\Staging\DB\Post_DAO; use Me\Stenberg\Content\Staging\DB\Post_Taxonomy_DAO; use Me\Stenberg\Content\Staging\DB\Postmeta_DAO; +use Me\Stenberg\Content\Staging\DB\Term_DAO; use Me\Stenberg\Content\Staging\DB\User_DAO; use Me\Stenberg\Content\Staging\Factories\DAO_Factory; use Me\Stenberg\Content\Staging\Helper_Factory; use Me\Stenberg\Content\Staging\Models\Batch; +use Me\Stenberg\Content\Staging\Models\Option; use Me\Stenberg\Content\Staging\Models\Post; +use Me\Stenberg\Content\Staging\Models\Term; /** * Class Batch_Mgr @@ -25,6 +28,15 @@ */ class Batch_Mgr { + /** + * Post meta field keys that holds a reference to another post. + * + * @var array + */ + private $post_relationship_keys = array( + '_menu_item_menu_item_parent' + ); + /** * @var Batch_DAO */ @@ -55,6 +67,11 @@ class Batch_Mgr { */ private $postmeta_dao; + /** + * @var Term_DAO + */ + private $term_dao; + /** * @var User_DAO */ @@ -79,6 +96,7 @@ public function __construct( Common_API $api, DAO_Factory $dao_factory ) { $this->post_dao = $dao_factory->create( 'Post' ); $this->post_taxonomy_dao = $dao_factory->create( 'Post_Taxonomy' ); $this->postmeta_dao = $dao_factory->create( 'Postmeta' ); + $this->term_dao = $dao_factory->create( 'Term' ); $this->user_dao = $dao_factory->create( 'User' ); } @@ -116,25 +134,15 @@ public function prepare( Batch $batch ) { return; } - $post_ids = array(); - $batch->set_post_rel_keys( apply_filters( 'sme_post_relationship_keys', array() ) ); - // Clean batch from any old content. $batch->set_attachments( array() ); $batch->set_users( array() ); $batch->set_posts( array() ); $batch->set_options( array() ); - // Get IDs of posts user has selected to include in this batch. - $meta = $this->batch_dao->get_post_meta( $batch->get_id(), 'sme_selected_post' ); - - // Ensure that we got an array back when looking for posts IDs in DB. - if ( is_array( $meta ) ) { - $post_ids = $meta; - } - + $this->add_post_relationship_keys( $batch ); $this->add_table_prefix( $batch ); - $this->add_posts( $batch, $post_ids ); + $this->add_posts( $batch ); $this->add_users( $batch ); $this->add_options( $batch ); @@ -146,9 +154,11 @@ public function prepare( Batch $batch ) { * Provide IDs of posts you want to add to the current batch. * * @param Batch $batch - * @param array $post_ids */ - private function add_posts( Batch $batch, $post_ids ) { + private function add_posts( Batch $batch ) { + + // Get IDs of posts user has selected to include in this batch. + $post_ids = $this->get_post_ids( $batch->get_id() ); $post_ids = apply_filters( 'sme_prepare_post_ids', $post_ids ); $post_ids = array_unique( $post_ids ); @@ -224,15 +234,23 @@ private function add_users( Batch $batch ) { */ private function add_options( Batch $batch ) { + $wp_options = array(); + // Check if options should be included with this batch. $include_options = get_post_meta( $batch->get_id(), '_sme_include_wp_options', true ); - if ( $include_options !== 'yes' ) { - return; + + if ( $include_options === 'yes' ) { + $option_names = $this->option_dao->get_option_names_to_sync(); + + $wp_options = $this->option_dao->get_options_by_names( $option_names ); + } - $options = $this->option_dao->get_options_to_sync(); - $batch->set_options( $options ); + $menu_options = $this->get_menu_options( $batch ); + $all_options = array_merge( $wp_options, $menu_options ); + + $batch->set_options( $all_options ); } /** @@ -312,6 +330,15 @@ private function add_related_posts( Batch $batch, $postmeta ) { return $postmeta; } + /** + * Set keys of post meta fields that holds a reference to another post. + * + * @param Batch $batch + */ + private function add_post_relationship_keys( Batch $batch ) { + $batch->set_post_rel_keys( apply_filters( 'sme_post_relationship_keys', $this->post_relationship_keys ) ); + } + /** * Add database table base prefix to batch. * @@ -321,4 +348,132 @@ private function add_table_prefix( Batch $batch ) { $batch->add_custom_data( 'sme_table_base_prefix', $this->custom_dao->get_table_base_prefix() ); } -} \ No newline at end of file + /** + * Get IDs of posts user has selected to include in a batch. + * + * @param int $batch_id + * @return array + */ + private function get_post_ids( $batch_id ) { + + $post_ids = $this->batch_dao->get_post_meta( $batch_id, 'sme_selected_post' ); + $menu_ids = $this->get_menu_post_ids( $batch_id ); + + $post_ids = array_merge( $post_ids, $menu_ids ); + + // Make sure we got an array back when looking for post IDs in DB. + return is_array( $post_ids ) ? $post_ids : array(); + } + + /** + * Get options related to menu. + * + * @param Batch $batch + * @return array + */ + private function get_menu_options( Batch $batch ) { + + // IDs of menu items to include in batch. + $menu_ids = $this->get_menu_post_ids( $batch->get_id() ); + + // Abort if no menus should be included in batch. + if ( empty( $menu_ids ) ) { + return array(); + } + + do_action( 'sme_prepare_menu_options', $batch ); + + $option_names = $this->get_menu_option_names(); + $wp_options = $this->option_dao->get_options_by_names( $option_names ); + + // Include custom menu information in batch. + $this->add_custom_menu_info( $batch, $wp_options ); + + return $wp_options; + } + + /** + * Get menu options to include with this batch. + * + * @return array + */ + private function get_menu_option_names() { + $names = $this->option_dao->get_option_names_by_pattern( 'theme_mods_%' ); + + array_push( $names, 'nav_menu_options' ); + return $names; + } + + /** + * Get post IDs of menu items user has selected to include in batch. + * + * @param int $batch_id + * @return array + */ + private function get_menu_post_ids( $batch_id ) { + $menu_ids = get_post_meta( $batch_id, '_sme_selected_menus', true ); + + if ( ! is_array( $menu_ids ) || empty( $menu_ids ) ) { + return array(); + } + + return $this->post_taxonomy_dao->get_object_ids_by_taxonomy_ids( $menu_ids ); + } + + /** + * Include custom menu information in batch. + * + * @param Batch $batch + * @param $options + */ + private function add_custom_menu_info( Batch $batch, $options ) { + foreach ( $options as $option ) { + $this->add_menu_position_info( $batch, $option ); + } + } + + /** + * Include information about what menus are places where in the themes. + * + * @param Batch $batch + * @param Option $option + */ + private function add_menu_position_info( Batch $batch, Option $option ) { + + if ( 0 !== strpos( $option->get_name(), 'theme_mods_' ) ) { + return; + } + + $value = $option->get_value(); + + if ( ! is_serialized( $value ) ) { + return; + } + + $value = unserialize( $value ); + + if ( empty( $value['nav_menu_locations'] ) ) { + return; + } + + if ( ! is_array( $value['nav_menu_locations'] ) ) { + return; + } + + foreach ( $value['nav_menu_locations'] as &$location ) { + + if ( ! is_int( $location ) ) { + continue; + } + + $term = $this->term_dao->find( $location ); + + if ( $term instanceof Term ) { + $location = $term->get_slug(); + } + } + + $option->set_value( serialize( $value ) ); + } + +} diff --git a/classes/models/class-post-taxonomy.php b/classes/models/class-post-taxonomy.php index af39c39..de5f8c3 100644 --- a/classes/models/class-post-taxonomy.php +++ b/classes/models/class-post-taxonomy.php @@ -62,8 +62,8 @@ public function set_term_order( $term_order ) { /** * @return int */ - public function get_term_order() { - return ( $this->term_order !== null ) ? $this->term_order : 0; - } + public function get_term_order() { + return $this->term_order; + } -} +} \ No newline at end of file diff --git a/classes/view/class-menu-table.php b/classes/view/class-menu-table.php new file mode 100644 index 0000000..b4e896b --- /dev/null +++ b/classes/view/class-menu-table.php @@ -0,0 +1,103 @@ + 'menu', + 'plural' => 'menus', + 'ajax' => false, + ) + ); + + $this->selected_items = $selected_items; + } + + /** + * Called if a column does not have a method that provides logic for + * rendering of that column. + * + * @param stdClass $menu + * @param array $column_name + * @return string Text or HTML to be placed inside the column. + */ + public function column_default( $menu, $column_name ) { + return ''; + } + + /** + * Render the menu name column. + * + * @param stdClass $menu + * @return string HTML to be rendered inside column. + */ + public function column_menu_name( $menu ){ + return sprintf( + '', + $menu->term_taxonomy_id, + $menu->name + ); + } + + /** + * Display checkbox (e.g. for bulk actions). The checkbox should have the + * value of the menu ID. + * + * @param stdClass $menu + * @return string Text to be placed inside the column. + */ + public function column_cb( $menu ) { + + $checked = in_array( $menu->term_taxonomy_id, $this->selected_items ) ? 'checked="checked"' : ''; + + return sprintf( + '', + $menu->term_taxonomy_id, + $this->_args['plural'], + $menu->term_taxonomy_id, + $checked + ); + } + + /** + * Set the table's columns and titles. + * + * The column named 'cb' will display checkboxes. Make sure to create a + * column_cb method for setting up the checkbox column. + * + * @return array An associative array: + * Key = Column name + * Value = Column title (except for key 'cb') + */ + public function get_columns() { + return array( + 'cb' => '', + 'menu_name' => 'Menu', + ); + } + + /** + * Prepare sites for display. + */ + public function prepare_items() { + + $columns = $this->get_columns(); + $hidden = array(); + $sortable = array(); + + $this->_column_headers = array( $columns, $hidden, $sortable ); + } + +} \ No newline at end of file diff --git a/content-staging.php b/content-staging.php index 4048bfa..013f2d7 100644 --- a/content-staging.php +++ b/content-staging.php @@ -70,6 +70,7 @@ require_once( 'classes/models/class-post-taxonomy.php' ); require_once( 'classes/view/class-batch-table.php' ); require_once( 'classes/view/class-batch-history-table.php' ); +require_once( 'classes/view/class-menu-table.php' ); require_once( 'classes/view/class-post-table.php' ); require_once( 'classes/xmlrpc/class-client.php' ); require_once( 'classes/class-background-process.php' ); @@ -185,6 +186,7 @@ public static function init() { add_action( 'init', array( $setup, 'register_post_types' ) ); add_action( 'init', array( $importer_factory, 'run_background_import' ) ); add_action( 'admin_menu', array( $setup, 'register_menu_pages' ) ); + add_action( 'admin_notices', array( $setup, 'quick_deploy_batch' ) ); add_action( 'admin_enqueue_scripts', array( $setup, 'load_assets' ) ); // Routing. @@ -198,7 +200,6 @@ public static function init() { // Filters. add_filter( 'xmlrpc_methods', array( $setup, 'register_xmlrpc_methods' ) ); add_filter( 'sme_post_relationship_keys', array( $setup, 'set_postmeta_post_relation_keys' ) ); - add_filter( 'post_updated_messages', array( $setup, 'quick_deploy_batch' ) ); // Content Staging loaded. do_action( 'content_staging_loaded' ); diff --git a/templates/edit-batch.php b/templates/edit-batch.php index f8d10a8..9a74130 100644 --- a/templates/edit-batch.php +++ b/templates/edit-batch.php @@ -22,6 +22,16 @@ display(); ?> + + +

+

+ +

+ display(); ?> + + +

>