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(); ?>
+
+
+
>