From 2d4004bb79fbcc4b8628dc0e99df5cefc46aa902 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Thu, 1 Aug 2019 20:37:00 +0200 Subject: [PATCH 01/61] Add link to plugin to theme description --- themes/labbook/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/labbook/style.css b/themes/labbook/style.css index c8fad87..d360afb 100644 --- a/themes/labbook/style.css +++ b/themes/labbook/style.css @@ -3,7 +3,7 @@ Theme Name: Labbook Theme URI: https://alp.attackllama.com/documentation/themes/labbook/ Author: Sean Leavey Author URI: https://attackllama.com/ -Description: Laboratory notebook theme, intended to be used in combination with Academic Labbook Plugin. +Description: Laboratory notebook theme, intended to be used in combination with Academic Labbook Plugin (ALP). ALP adds a whole bunch of features to WordPress to convert it into an electronic laboratory notebook. The Labbook theme enables the display of the front-end features provided by ALP. ALP is currently in beta and can be installed using the instructions here: https://alp.attackllama.com/documentation/installation/. Version: 1.1.9 License: GNU General Public License v3 or later License URI: LICENSE From 326539e600941c316dfebba05373be8f5af5c2ac Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sat, 3 Aug 2019 11:28:31 +0200 Subject: [PATCH 02/61] Initial working inventory system --- ssl-alp/includes/class-ssl-alp-inventory.php | 497 ++++++++++++++++++ ssl-alp/includes/class-ssl-alp.php | 9 + .../site/inventory-settings-display.php | 5 + 3 files changed, 511 insertions(+) create mode 100644 ssl-alp/includes/class-ssl-alp-inventory.php create mode 100644 ssl-alp/partials/admin/settings/site/inventory-settings-display.php diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php new file mode 100644 index 0000000..4a975ca --- /dev/null +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -0,0 +1,497 @@ +get_loader(); + + /** + * Inventory post type. + */ + + // Register inventory post type. + $loader->add_action( 'init', $this, 'register_post_type' ); + + // Remove month dropdown filter on admin page list. + $loader->add_action( 'months_dropdown_results', $this, 'disable_months_dropdown_results', 10, 2 ); + + // Remove date column from admin post list. + $loader->add_filter( 'manage_edit-ssl_alp_inventory_columns', $this, 'manage_edit_columns' ); + + // Sort inventory posts alphabetically by default. + $loader->add_filter( 'manage_edit-ssl_alp_inventory_sortable_columns', $this, 'manage_edit_sortable_columns' ); + + // Create/delete corresponding inventory item terms whenever posts are created/deleted. + $loader->add_action( 'save_post', $this, 'associate_inventory_post_with_term', 10, 2 ); + $loader->add_action( 'before_delete_post', $this, 'delete_associated_inventory_post_term' ); + + // Delete any invalid inventory items when post terms are set. + $loader->add_action( 'added_term_relationship', $this, 'reject_invalid_inventory_terms', 10, 3 ); + + // Filter to stop users from editing or deleting inventory terms directly. + $loader->add_filter( 'user_has_cap', $this, 'filter_user_has_cap', 10, 4 ); + + // Stop super admins deleting inventory terms. + $loader->add_filter( 'map_meta_cap', $this, 'filter_capabilities', 10, 4 ); + + /** + * Inventory taxonomy. + */ + + $loader->add_action( 'init', $this, 'register_taxonomy' ); + } + + /** + * Register settings. + */ + public function register_settings() { + register_setting( + SSL_ALP_SITE_SETTINGS_PAGE, + 'ssl_alp_enable_inventory', + array( + 'type' => 'boolean', + ) + ); + } + + /** + * Register settings fields. + */ + public function register_settings_fields() { + /** + * Post multiple author settings field. + */ + add_settings_field( + 'ssl_alp_inventory_settings', + __( 'Inventory', 'ssl-alp' ), + array( $this, 'inventory_settings_callback' ), + SSL_ALP_SITE_SETTINGS_PAGE, + 'ssl_alp_site_settings_section' + ); + } + + /** + * Inventory settings partial. + */ + public function inventory_settings_callback() { + require_once SSL_ALP_BASE_DIR . 'partials/admin/settings/site/inventory-settings-display.php'; + } + + /** + * Register the inventory post type. + */ + public function register_post_type() { + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return; + } + + $labels = array( + 'name' => __( 'Inventory', 'ssl-alp' ), + 'singular_name' => __( 'Inventory', 'ssl-alp' ), + 'add_new_item' => __( 'Add New Item', 'ssl-alp' ), + 'edit_item' => __( 'Edit Item', 'ssl-alp' ), + 'new_item' => __( 'New Item', 'ssl-alp' ), + 'view_item' => __( 'View Item', 'ssl-alp' ), + 'view_items' => __( 'View Items', 'ssl-alp' ), + 'search_items' => __( 'Search Items', 'ssl-alp' ), + 'not_found' => __( 'No items found.', 'ssl-alp' ), + 'not_found_in_trash' => __( 'No items found in Trash.', 'ssl-alp' ), + 'all_items' => __( 'All Items', 'ssl-alp' ), + 'attributes' => __( 'Item Attributes', 'ssl-alp' ), + 'insert_into_item' => __( 'Insert into item', 'ssl-alp' ), + 'uploaded_to_this_item' => __( 'Uploaded to this item', 'ssl-alp' ), + 'featured_image' => __( 'Item Image', 'ssl-alp' ), + 'set_featured_image' => __( 'Set item image', 'ssl-alp' ), + 'remove_featured_image' => __( 'Remove item image', 'ssl-alp' ), + 'use_featured_image' => __( 'Use as item image', 'ssl-alp' ), + 'filter_items_list' => __( 'Filter items list', 'ssl-alp' ), + 'items_list_navigation' => __( 'Items list navigation', 'ssl-alp' ), + 'items_list' => __( 'Items list', 'ssl-alp' ), + 'item_published' => __( 'Item created.', 'ssl-alp' ), + 'item_published_privately' => __( 'Item created privately.', 'ssl-alp' ), + 'item_reverted_to_draft' => __( 'Item reverted to draft.', 'ssl-alp' ), + 'item_updated' => __( 'Item updated.', 'ssl-alp' ), + ); + + // Register new post type to represent inventory items. + $args = array( + 'labels' => $labels, + 'description' => __( 'Inventory items.', 'ssl-alp' ), + 'public' => true, + 'hierarchical' => false, + 'show_in_rest' => true, + 'menu_icon' => 'dashicons-tag', + 'supports' => array( + 'title', + 'editor', + 'revisions', + 'page-attributes', + 'thumbnail', + ), + 'rewrite' => array( + 'slug' => 'inventory', + ), + ); + + register_post_type( 'ssl_alp_inventory', $args ); + } + + /** + * Disable months dropdown box in admin inventory posts list. + * + * @param array $months Months. + * @param string $post_type Post type being shown. + * @return array Empty array if post type is page, otherwise $months. + */ + public function disable_months_dropdown_results( $months, $post_type ) { + if ( 'ssl_alp_inventory' === $post_type ) { + // Return empty array to force it to hide (see months_dropdown() in class-wp-list-table.php). + return array(); + } + + return $months; + } + + /** + * Filter columns shown on list of inventory posts in admin panel. + * + * @param array $columns Columns to show by default. + * @return array Columns with date column removed. + */ + public function manage_edit_columns( $columns ) { + if ( array_key_exists( 'date', $columns ) ) { + // Remove date column. + unset( $columns['date'] ); + } + + return $columns; + } + + /** + * Remove date column and sort columns alphabetically by name on list of + * inventory posts in admin panel. + * + * @param array $columns Sortable columns. + * @return array Columns with title column set as default sort. + */ + public function manage_edit_sortable_columns( $columns ) { + if ( array_key_exists( 'date', $columns ) ) { + // Remove date column. + unset( $columns['date'] ); + } + + // Make title the default sort. + $columns['title'] = array( $columns['title'], true ); + + return $columns; + } + + /** + * Add or update inventory item taxonomy term using the specified inventory + * custom post type post. + * + * @param WP_Post $post The inventory post. + */ + private function update_inventory_item_term( $post ) { + $post = get_post( $post ); + + if ( is_null( $post ) ) { + // Invalid post. + return; + } + + // Get inventory item term, if present. + $term = $this->get_inventory_term( $post ); + + if ( ! $term ) { + // Term doesn't yet exist. + $args = array( + 'slug' => $this->get_inventory_term_slug( $post ), + ); + + wp_insert_term( $post->post_title, 'ssl_alp_inventory_item', $args ); + } else { + // Update term. + $args = array( + 'name' => $post->post_title, + 'slug' => $this->get_inventory_term_slug( $post ), + ); + + wp_update_term( $term->term_id, 'ssl_alp_inventory_item', $args ); + } + } + + private function get_inventory_term( $post ) { + $post = get_post( $post ); + + if ( is_null( $post ) ) { + // Invalid post. + return; + } + + $slug = $this->get_inventory_term_slug( $post ); + return get_term_by( 'slug', $slug, 'ssl_alp_inventory_item' ); + } + + /** + * Get unique slug for the inventory term. This uses the associated + * inventory post's ID since this doesn't change even if e.g. its slug does. + * + * @param WP_Post $post The inventory post. + */ + private function get_inventory_term_slug( $post ) { + $post = get_post( $post ); + + if ( is_null( $post ) ) { + // Invalid post. + return; + } + + return $post->ID; + } + + /** + * Get post from inventory term. + * + * @param WP_Term $term The inventory term. + * + * @return WP_Post|null The inventory post, or null if the term is invalid. + */ + private function get_post_from_inventory_term( $term ) { + // The term's slug is the post ID. + return get_post( $term->slug ); + } + + /** + * Associate a post in the ssl_alp_inventory custom post type with a corresponding + * ssl_alp_inventory_item term when created or saved. + * + * @param int $post_id The post ID. + * @param WP_Post $post The post object. + */ + public function associate_inventory_post_with_term( $post_id, $post ) { + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return; + } + + if ( 'ssl_alp_inventory' !== $post->post_type ) { + return; + } + + if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { + // Don't create term for autosaves. + return; + } + + if ( 'publish' !== $post->post_status ) { + // Don't create a term unless the post is being published. + return; + } + + // Add or update the associated term. + $this->update_inventory_item_term( $post ); + } + + /** + * Delete associated inventory post term before an inventory post is deleted. + * + * @param int $post_id The post ID. + */ + public function delete_associated_inventory_post_term( $post_id ) { + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return; + } + + $post = get_post( $post_id ); + + if ( is_null( $post ) ) { + // Invalid post. + return; + } + + if ( 'ssl_alp_inventory' !== $post->post_type ) { + return; + } + + if ( 'trash' !== $post->post_status ) { + // Don't create a term unless the post is being published. + return; + } + + $term = $this->get_inventory_term( $post ); + + if ( ! $term ) { + // No term to delete. + return; + } + + wp_delete_term( $term->term_id, 'ssl_alp_inventory_item' ); + } + + /** + * Delete invalid inventory when a post is saved. + * + * Unfortunately there is no way to filter terms before they are set on a post, so this function + * deletes them afterwards instead. + * + * @param int $object_id Object ID. + * @param int $tt_id Term taxonomy ID. + * @param string $taxonomy Taxonomy slug. + */ + public function reject_invalid_inventory_terms( $object_id, $tt_id, $taxonomy ) { + if ( 'ssl_alp_inventory_item' !== $taxonomy ) { + return; + } + + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return; + } + + $term = get_term_by( 'term_taxonomy_id', $tt_id, 'ssl_alp_inventory_item' ); + + if ( ! $term ) { + // Nothing to do here. + return; + } + + // Check term is valid. + $inventory_post = $this->get_post_from_inventory_term( $term ); + + if ( ! $inventory_post ) { + // This is not a valid inventory term - delete it. + wp_delete_term( $term->term_id, 'ssl_alp_inventory_item' ); + } + } + + /** + * Stop users editing or deleting inventory terms. + * + * @param array $all_capabilities All user capabilities. + * @param mixed $unused Unused. + * @param array $args Capability arguments. + * @param WP_User $user User object. + */ + public function filter_user_has_cap( $all_capabilities, $unused, $args, $user ) { + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return $all_capabilities; + } + + $requested_capability = $args[0]; + + if ( in_array( $requested_capability, array( 'edit_term', 'delete_term' ), true ) ) { + // Disallow in all circumstances. + $all_capabilities['edit_term'] = false; + $all_capabilities['delete_term'] = false; + } + + return $all_capabilities; + } + + /** + * Filter capabilities of super admins to stop them editing or deleting inventory terms. + * + * Inventory terms are essential to the correct operation of the inventory system and are + * managed only by the inventory custom post type. + * + * @param array $caps All capabilities. + * @param string $cap Capability being checked. + * @param int $user_id User ID. + * @param array $args Capability arguments. + */ + public function filter_capabilities( $caps, $cap, $user_id, $args ) { + // Construct list of capabilities based on post type. + $filtered_caps = array( + // Terms. + 'edit_term', + 'delete_term', + ); + + if ( ! in_array( $cap, $filtered_caps, true ) ) { + // this is not a capability we need to filter. + return $caps; + } + + // Get term. + $term = get_term( $args[0] ); + + if ( is_null( $term ) ) { + return $caps; + } + + $taxonomy = get_taxonomy( $term->taxonomy ); + + if ( 'ssl_alp_inventory_item' === $taxonomy->name ) { + // Disallow. + $caps[] = 'do_not_allow'; + } + + return $caps; + } + + /** + * Register the inventory taxonomy and add post type support. + */ + public function register_taxonomy() { + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return; + } + + // Register new taxonomy so that we can store inventory item and post relationships. + $args = array( + 'hierarchical' => false, + 'labels' => array( + 'name' => __( 'Inventory', 'ssl-alp' ), + 'singular_name' => __( 'Item', 'ssl-alp' ), + 'search_items' => __( 'Search Items', 'ssl-alp' ), + 'popular_items' => __( 'Popular Items', 'ssl-alp' ), + 'all_items' => __( 'All Items', 'ssl-alp' ), + 'edit_item' => __( 'Edit Item', 'ssl-alp' ), + 'update_item' => __( 'Update Item', 'ssl-alp' ), + 'add_new_item' => __( 'Add New Item', 'ssl-alp' ), + 'new_item_name' => __( 'New Item Name', 'ssl-alp' ), + 'separate_items_with_commas' => __( 'Separate items with commas', 'ssl-alp' ), + 'add_or_remove_items' => __( 'Add or remove items', 'ssl-alp' ), + 'choose_from_most_used' => __( 'Choose from the most used items', 'ssl-alp' ), + 'not_found' => __( 'No items found.', 'ssl-alp' ), + 'no_terms' => __( 'No items', 'ssl-alp' ), + ), + 'public' => true, + 'show_in_menu' => false, // Disable term edit page. + 'show_in_rest' => true, // Needed for block editor support. + 'show_admin_column' => true, // Show associated terms in admin edit screen. + ); + + // Create inventory taxonomy. + register_taxonomy( 'ssl_alp_inventory_item', $this->supported_post_types, $args ); + } +} diff --git a/ssl-alp/includes/class-ssl-alp.php b/ssl-alp/includes/class-ssl-alp.php index 4f34098..30bc5e9 100644 --- a/ssl-alp/includes/class-ssl-alp.php +++ b/ssl-alp/includes/class-ssl-alp.php @@ -135,6 +135,14 @@ private function load_modules() { $this->terms = new SSL_ALP_Terms( $this ); + /** + * Inventory. + */ + + require_once SSL_ALP_BASE_DIR . 'includes/class-ssl-alp-inventory.php'; + + $this->inventory = new SSL_ALP_Inventory( $this ); + /** * Page functionality. */ @@ -204,6 +212,7 @@ private function register() { $this->auth->register(); $this->search->register(); $this->terms->register(); + $this->inventory->register(); $this->pages->register(); $this->coauthors->register(); $this->revisions->register(); diff --git a/ssl-alp/partials/admin/settings/site/inventory-settings-display.php b/ssl-alp/partials/admin/settings/site/inventory-settings-display.php new file mode 100644 index 0000000..cb2c0bb --- /dev/null +++ b/ssl-alp/partials/admin/settings/site/inventory-settings-display.php @@ -0,0 +1,5 @@ + From 8919e5b17c4b47027b6e3779d160320b7da9d551 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sat, 3 Aug 2019 22:32:26 +0200 Subject: [PATCH 03/61] Disallow creation of inventory terms directly --- ssl-alp/includes/class-ssl-alp-inventory.php | 155 ++++++++++++------- 1 file changed, 99 insertions(+), 56 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index 4a975ca..a3b4ed2 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -47,7 +47,21 @@ public function register_hooks() { // Create/delete corresponding inventory item terms whenever posts are created/deleted. $loader->add_action( 'save_post', $this, 'associate_inventory_post_with_term', 10, 2 ); - $loader->add_action( 'before_delete_post', $this, 'delete_associated_inventory_post_term' ); + $loader->add_action( 'deleted_post', $this, 'delete_associated_inventory_post_term' ); + + /** + * Inventory taxonomy. + */ + + // Register inventory item taxonomy. + $loader->add_action( 'init', $this, 'register_taxonomy' ); + + // Disallow creation of new terms directly (this is temporarily disabled + // by `associate_inventory_post_with_term`). + // NOTE: if this line is changed, the enable_disallow_insert_term_filter + // and disable_disallow_insert_term_filter functions must also be + // updated. + $loader->add_filter( 'pre_insert_term', $this, 'disallow_insert_term', 10, 2 ); // Delete any invalid inventory items when post terms are set. $loader->add_action( 'added_term_relationship', $this, 'reject_invalid_inventory_terms', 10, 3 ); @@ -57,12 +71,6 @@ public function register_hooks() { // Stop super admins deleting inventory terms. $loader->add_filter( 'map_meta_cap', $this, 'filter_capabilities', 10, 4 ); - - /** - * Inventory taxonomy. - */ - - $loader->add_action( 'init', $this, 'register_taxonomy' ); } /** @@ -101,6 +109,14 @@ public function inventory_settings_callback() { require_once SSL_ALP_BASE_DIR . 'partials/admin/settings/site/inventory-settings-display.php'; } + private function enable_disallow_insert_term_filter() { + add_filter( 'pre_insert_term', array( $this, 'disallow_insert_term', 10, 2 ) ); + } + + private function disable_disallow_insert_term_filter() { + remove_filter( 'pre_insert_term', array( $this, 'disallow_insert_term', 10, 2 ) ); + } + /** * Register the inventory post type. */ @@ -228,6 +244,10 @@ private function update_inventory_item_term( $post ) { // Get inventory item term, if present. $term = $this->get_inventory_term( $post ); + // Temporarily disable the filter that blocks creation of terms in the + // ssl_alp_inventory_item taxonomy. + $this->disable_disallow_insert_term_filter(); + if ( ! $term ) { // Term doesn't yet exist. $args = array( @@ -244,9 +264,12 @@ private function update_inventory_item_term( $post ) { wp_update_term( $term->term_id, 'ssl_alp_inventory_item', $args ); } + + // Re-enable the filter. + $this->enable_disallow_insert_term_filter(); } - private function get_inventory_term( $post ) { + public function get_inventory_term( $post ) { $post = get_post( $post ); if ( is_null( $post ) ) { @@ -327,34 +350,92 @@ public function delete_associated_inventory_post_term( $post_id ) { if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { // Inventory disabled. return; - } + } $post = get_post( $post_id ); if ( is_null( $post ) ) { // Invalid post. return; - } + } if ( 'ssl_alp_inventory' !== $post->post_type ) { return; - } - - if ( 'trash' !== $post->post_status ) { - // Don't create a term unless the post is being published. - return; - } + } $term = $this->get_inventory_term( $post ); if ( ! $term ) { // No term to delete. return; - } + } - wp_delete_term( $term->term_id, 'ssl_alp_inventory_item' ); + wp_delete_term( $term->term_id, 'ssl_alp_inventory_item' ); + clean_term_cache( array( $term->term_id ), 'ssl_alp_inventory_item' ); } + /** + * Register the inventory taxonomy and add post type support. + */ + public function register_taxonomy() { + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return; + } + + // Register new taxonomy so that we can store inventory item and post relationships. + $args = array( + 'hierarchical' => false, + 'labels' => array( + 'name' => __( 'Inventory', 'ssl-alp' ), + 'singular_name' => __( 'Item', 'ssl-alp' ), + 'search_items' => __( 'Search Items', 'ssl-alp' ), + 'popular_items' => __( 'Popular Items', 'ssl-alp' ), + 'all_items' => __( 'All Items', 'ssl-alp' ), + 'edit_item' => __( 'Edit Item', 'ssl-alp' ), + 'update_item' => __( 'Update Item', 'ssl-alp' ), + 'add_new_item' => __( 'Add New Item', 'ssl-alp' ), + 'new_item_name' => __( 'New Item Name', 'ssl-alp' ), + 'separate_items_with_commas' => __( 'Separate items with commas', 'ssl-alp' ), + 'add_or_remove_items' => __( 'Add or remove items', 'ssl-alp' ), + 'choose_from_most_used' => __( 'Choose from the most used items', 'ssl-alp' ), + 'not_found' => __( 'No items found.', 'ssl-alp' ), + 'no_terms' => __( 'No items', 'ssl-alp' ), + ), + 'public' => true, + 'show_in_menu' => false, // Disable term edit page. + 'show_in_rest' => true, // Needed for block editor support. + 'show_admin_column' => true, // Show associated terms in admin edit screen. + ); + + // Create inventory taxonomy. + register_taxonomy( 'ssl_alp_inventory_item', $this->supported_post_types, $args ); + } + + /** + * Disallow the creation of new terms under normal circumstances. + * + * This is to avoid users being able to create terms in the inventory + * taxonomy directly; terms should only be created when a new inventory post + * is created. + * + * @param string $term The term. + * @param string $taxonomy The taxonomy. + * + * @return string|WP_Error $term The term, or error. + */ + public function disallow_insert_term( $term, $taxonomy ) { + if ( 'ssl_alp_inventory_item' !== $taxonomy ) { + return; + } + + // Return an error in all circumstances. + return new WP_Error( + 'disallow_insert_term', + __( 'Your role does not have permission to add terms to this taxonomy', 'ssl-alp' ) + ); + } + /** * Delete invalid inventory when a post is saved. * @@ -456,42 +537,4 @@ public function filter_capabilities( $caps, $cap, $user_id, $args ) { return $caps; } - - /** - * Register the inventory taxonomy and add post type support. - */ - public function register_taxonomy() { - if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { - // Inventory disabled. - return; - } - - // Register new taxonomy so that we can store inventory item and post relationships. - $args = array( - 'hierarchical' => false, - 'labels' => array( - 'name' => __( 'Inventory', 'ssl-alp' ), - 'singular_name' => __( 'Item', 'ssl-alp' ), - 'search_items' => __( 'Search Items', 'ssl-alp' ), - 'popular_items' => __( 'Popular Items', 'ssl-alp' ), - 'all_items' => __( 'All Items', 'ssl-alp' ), - 'edit_item' => __( 'Edit Item', 'ssl-alp' ), - 'update_item' => __( 'Update Item', 'ssl-alp' ), - 'add_new_item' => __( 'Add New Item', 'ssl-alp' ), - 'new_item_name' => __( 'New Item Name', 'ssl-alp' ), - 'separate_items_with_commas' => __( 'Separate items with commas', 'ssl-alp' ), - 'add_or_remove_items' => __( 'Add or remove items', 'ssl-alp' ), - 'choose_from_most_used' => __( 'Choose from the most used items', 'ssl-alp' ), - 'not_found' => __( 'No items found.', 'ssl-alp' ), - 'no_terms' => __( 'No items', 'ssl-alp' ), - ), - 'public' => true, - 'show_in_menu' => false, // Disable term edit page. - 'show_in_rest' => true, // Needed for block editor support. - 'show_admin_column' => true, // Show associated terms in admin edit screen. - ); - - // Create inventory taxonomy. - register_taxonomy( 'ssl_alp_inventory_item', $this->supported_post_types, $args ); - } } From f91a9ca01c675f8f955805b8c7203f56db8dd056 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sat, 3 Aug 2019 22:33:17 +0200 Subject: [PATCH 04/61] Add activator and uninstaller functions for inventory --- ssl-alp/includes/class-ssl-alp-activator.php | 1 + .../includes/class-ssl-alp-uninstaller.php | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/ssl-alp/includes/class-ssl-alp-activator.php b/ssl-alp/includes/class-ssl-alp-activator.php index c90710b..0ce6525 100644 --- a/ssl-alp/includes/class-ssl-alp-activator.php +++ b/ssl-alp/includes/class-ssl-alp-activator.php @@ -119,6 +119,7 @@ private static function add_options() { add_option( 'ssl_alp_require_login', true ); add_option( 'ssl_alp_enable_applications', false ); add_option( 'ssl_alp_disallow_public_advanced_search', true ); + add_option( 'ssl_alp_enable_inventory', true ); add_option( 'ssl_alp_allow_multiple_authors', true ); add_option( 'ssl_alp_disable_post_trackbacks', true ); add_option( 'ssl_alp_enable_crossreferences', true ); diff --git a/ssl-alp/includes/class-ssl-alp-uninstaller.php b/ssl-alp/includes/class-ssl-alp-uninstaller.php index 7239e7f..6b812b8 100644 --- a/ssl-alp/includes/class-ssl-alp-uninstaller.php +++ b/ssl-alp/includes/class-ssl-alp-uninstaller.php @@ -113,6 +113,7 @@ public static function delete_data() { self::delete_taxonomies(); self::delete_post_metas(); self::delete_user_metas(); + self::delete_custom_post_types(); } /** @@ -123,6 +124,7 @@ private static function delete_options() { delete_option( 'ssl_alp_require_login' ); delete_option( 'ssl_alp_enable_applications' ); delete_option( 'ssl_alp_disallow_public_advanced_search' ); + delete_option( 'ssl_alp_enable_inventory' ); delete_option( 'ssl_alp_allow_multiple_authors' ); delete_option( 'ssl_alp_disable_post_trackbacks' ); delete_option( 'ssl_alp_enable_crossreferences' ); @@ -146,6 +148,7 @@ private static function delete_taxonomies() { self::delete_taxonomy( 'ssl_alp_coauthor' ); self::delete_taxonomy( 'ssl_alp_crossreference' ); self::delete_taxonomy( 'ssl_alp_read_flag' ); + self::delete_taxonomy( 'ssl_alp_inventory_item' ); } /** @@ -292,4 +295,30 @@ private static function delete_user_meta( $meta_key ) { ) ); } + + /** + * Delete custom post types. + */ + private static function delete_custom_post_types() { + // Inventory. + self::delete_custom_post_type_posts( 'ssl_alp_inventory' ); + } + + /** + * Delete custom post type posts. + * + * @global $wpdb + */ + private static function delete_custom_post_type_posts( $post_type ) { + // Note: this doesn't delete the post type's revision posts. + $wpdb->delete( + $wpdb->posts, + array( + 'post_type' => $post_type, + ), + array( + '%s', + ) + ); + } } From 417a0eb26dd59fa6bb8ccebaa8f786711b8d0dfa Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sat, 3 Aug 2019 22:42:10 +0200 Subject: [PATCH 05/61] Add inventory tests --- ssl-alp/tests/unit/test-inventory.php | 130 ++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 ssl-alp/tests/unit/test-inventory.php diff --git a/ssl-alp/tests/unit/test-inventory.php b/ssl-alp/tests/unit/test-inventory.php new file mode 100644 index 0000000..d22bf67 --- /dev/null +++ b/ssl-alp/tests/unit/test-inventory.php @@ -0,0 +1,130 @@ +admin = $this->factory->user->create_and_get( + array( + 'role' => 'administrator' + ) + ); + + $this->editor = $this->factory->user->create_and_get( + array( + 'role' => 'editor' + ) + ); + + $this->author = $this->factory->user->create_and_get( + array( + 'role' => 'author' + ) + ); + + $this->contributor = $this->factory->user->create_and_get( + array( + 'role' => 'contributor' + ) + ); + + $this->subscriber = $this->factory->user->create_and_get( + array( + 'role' => 'subscriber' + ) + ); + } + + public function test_creating_inventory_post_creates_corresponding_term() { + global $ssl_alp; + + $post = $this->factory->post->create_and_get( + array( + 'post_type' => 'ssl_alp_inventory', + ) + ); + + $this->assertEquals( $post->post_type, 'ssl_alp_inventory' ); + // A corresponding term should have been created. + $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); + $this->assertNotFalse( $term ); + $this->assertEquals( $term->slug, $post->ID ); + } + + public function test_deleting_inventory_post_deletes_corresponding_term() { + global $ssl_alp; + + $post = $this->factory->post->create_and_get( + array( + 'post_type' => 'ssl_alp_inventory', + ) + ); + + $this->assertEquals( $post->post_type, 'ssl_alp_inventory' ); + $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); + $this->assertNotFalse( $term ); + $this->assertEquals( $term->slug, $post->ID ); + + // Force delete post. + wp_delete_post( $post->ID, true ); + + // The term should be deleted too. + $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); + $this->assertFalse( $term ); + } + + public function test_trashing_inventory_post_does_not_delete_corresponding_term() { + global $ssl_alp; + + $post = $this->factory->post->create_and_get( + array( + 'post_type' => 'ssl_alp_inventory', + ) + ); + + $this->assertEquals( $post->post_type, 'ssl_alp_inventory' ); + $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); + $this->assertNotFalse( $term ); + $this->assertEquals( $term->slug, $post->ID ); + + // Trash the post. + wp_trash_post( $post->ID ); + + // The term should still be present. + $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); + $this->assertNotFalse( $term ); + $this->assertEquals( $term->slug, $post->ID ); + + // Now delete the post. + wp_delete_post( $post->ID ); + + // The term should be deleted too. + $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); + $this->assertFalse( $term ); + } + + public function test_user_cannot_create_inventory_item_terms_manually() { + $users = array( + $this->admin, + $this->editor, + $this->author, + $this->contributor, + $this->subscriber, + ); + + foreach ( $users as $user ) { + wp_set_current_user( $user->ID ); + $term = wp_insert_term( 'Test', 'ssl_alp_inventory_item' ); + $this->assertTrue( is_wp_error( $term ) ); + } + } +} From 4999b6b43d94c018856905fc22256d5ea8b725f9 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 10:46:59 +0200 Subject: [PATCH 06/61] Support revisions for inventory posts (fix capability check) --- ssl-alp/includes/class-ssl-alp-revisions.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ssl-alp/includes/class-ssl-alp-revisions.php b/ssl-alp/includes/class-ssl-alp-revisions.php index f6f5fce..e5d2b59 100644 --- a/ssl-alp/includes/class-ssl-alp-revisions.php +++ b/ssl-alp/includes/class-ssl-alp-revisions.php @@ -44,6 +44,7 @@ class SSL_ALP_Revisions extends SSL_ALP_Module { */ protected static $supported_unread_flag_post_types = array( 'post', + 'ssl_alp_inventory', ); /** @@ -209,7 +210,8 @@ public function edit_summary_allowed( $post = null, $check_edit_permission = tru } // Check if user has permission to edit the post, if we are to check this. - if ( $check_edit_permission && ! current_user_can( "edit_{$post->post_type}", $post->ID ) ) { + $post_type = get_post_type_object( $post->post_type ); + if ( $check_edit_permission && ! current_user_can( "edit_{$post_type->capability_type}", $post->ID ) ) { // No permission. return false; } From 07b66c6e618f95a3a98b1078b634ba4de93840be Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 10:49:43 +0200 Subject: [PATCH 07/61] Add default inventory post template --- ssl-alp/includes/class-ssl-alp-inventory.php | 30 ++++++++++++++------ 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index a3b4ed2..3b443e4 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -156,20 +156,34 @@ public function register_post_type() { // Register new post type to represent inventory items. $args = array( - 'labels' => $labels, - 'description' => __( 'Inventory items.', 'ssl-alp' ), - 'public' => true, - 'hierarchical' => false, - 'show_in_rest' => true, - 'menu_icon' => 'dashicons-tag', - 'supports' => array( + 'labels' => $labels, + 'description' => __( 'Inventory items.', 'ssl-alp' ), + 'public' => true, + 'hierarchical' => false, + 'show_in_rest' => true, + 'template' => array( + array( + 'core/heading', + array( + 'content' => 'Location', + ) + ), + array( + 'core/paragraph', + array( + 'placeholder' => 'Location...', + ) + ), + ), + 'menu_icon' => 'dashicons-tag', + 'supports' => array( 'title', 'editor', 'revisions', 'page-attributes', 'thumbnail', ), - 'rewrite' => array( + 'rewrite' => array( 'slug' => 'inventory', ), ); From ab51f06f7022a24c249cc4536a0356e69e594a90 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 10:49:58 +0200 Subject: [PATCH 08/61] Fix permission bug --- ssl-alp/includes/class-ssl-alp-inventory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index 3b443e4..d1e5225 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -440,7 +440,7 @@ public function register_taxonomy() { */ public function disallow_insert_term( $term, $taxonomy ) { if ( 'ssl_alp_inventory_item' !== $taxonomy ) { - return; + return $term; } // Return an error in all circumstances. From 67710f7ee6fb87f4ffb2d15fe816406e911173ce Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 10:50:22 +0200 Subject: [PATCH 09/61] Add cross-reference support for inventory posts --- ssl-alp/includes/class-ssl-alp-references.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-references.php b/ssl-alp/includes/class-ssl-alp-references.php index 0255d32..5ba4445 100644 --- a/ssl-alp/includes/class-ssl-alp-references.php +++ b/ssl-alp/includes/class-ssl-alp-references.php @@ -21,8 +21,9 @@ class SSL_ALP_References extends SSL_ALP_Module { * @var array */ protected $supported_reference_post_types = array( - 'post' => true, - 'page' => false, + 'post' => true, + 'page' => false, + 'ssl_alp_inventory' => false, ); /** From a31a60a0097649db97f8448191407462f4b3da5f Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 10:50:59 +0200 Subject: [PATCH 10/61] Fix incorrectly named variable --- ssl-alp/includes/class-ssl-alp-coauthors.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-coauthors.php b/ssl-alp/includes/class-ssl-alp-coauthors.php index 67533bb..e3da6e9 100644 --- a/ssl-alp/includes/class-ssl-alp-coauthors.php +++ b/ssl-alp/includes/class-ssl-alp-coauthors.php @@ -1017,9 +1017,9 @@ public function reject_invalid_coauthor_terms( $object_id, $tt_id, $taxonomy ) { } // Check term is valid. - $author_term = $this->get_user_from_coauthor_term( $term ); + $coauthor = $this->get_user_from_coauthor_term( $term ); - if ( ! $author_term ) { + if ( ! $coauthor ) { // This is not a valid coauthor term - delete it. wp_delete_term( $term->term_id, 'ssl_alp_coauthor' ); } From f11d45427692ea970966920a8122aa8e4c8d1ce0 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 11:26:27 +0200 Subject: [PATCH 11/61] Update uninstaller --- .../includes/class-ssl-alp-uninstaller.php | 76 +++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-uninstaller.php b/ssl-alp/includes/class-ssl-alp-uninstaller.php index 6b812b8..d51e18b 100644 --- a/ssl-alp/includes/class-ssl-alp-uninstaller.php +++ b/ssl-alp/includes/class-ssl-alp-uninstaller.php @@ -300,25 +300,73 @@ private static function delete_user_meta( $meta_key ) { * Delete custom post types. */ private static function delete_custom_post_types() { - // Inventory. - self::delete_custom_post_type_posts( 'ssl_alp_inventory' ); + // Change inventory posts to pages. + self::delete_custom_post_type_posts( 'ssl_alp_inventory', 'page' ); } /** - * Delete custom post type posts. + * Delete or reassign custom post type posts and their revisions. + * + * @param string $post_type The post type to remove. + * @param string $new_post_type The replacement post type. If specified, the post type is + * changed to this, and revisions are left untouched. If null, the + * posts are deleted. * * @global $wpdb */ - private static function delete_custom_post_type_posts( $post_type ) { - // Note: this doesn't delete the post type's revision posts. - $wpdb->delete( - $wpdb->posts, - array( - 'post_type' => $post_type, - ), - array( - '%s', - ) - ); + private static function delete_custom_post_type_posts( $post_type, $new_post_type = null ) { + if ( is_null( $new_post_type ) ) { + $post_ids = $wpdb->get_col( + $wpdb->prepare( + " + SELECT post_id + FROM $wpdb->posts + WHERE post_type = %s + " + ), + $post_type + ); + + foreach ( $post_ids as $post_id ) { + // Delete children. + $wpdb->delete( + $wpdb->posts, + array( + 'post_parent' => $post_id + ), + array( + '%d' + ) + ); + + // Delete post. + $wpdb->delete( + $wpdb->posts, + array( + 'ID' => $post_id + ), + array( + '%d' + ) + ); + } + } else { + // Reassign to new post type. + $wpdb->update( + $wpdb->posts, + array( + 'post_type' => $new_post_type, + ), + array( + 'post_type' => $post_type, + ), + array( + '%s', + ), + array( + '%s', + ) + ); + } } } From 362ef60a4fba9f383f15d611f25ec3794beb5167 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 11:38:14 +0200 Subject: [PATCH 12/61] Remove inventory post type unread flag support --- ssl-alp/includes/class-ssl-alp-revisions.php | 1 - 1 file changed, 1 deletion(-) diff --git a/ssl-alp/includes/class-ssl-alp-revisions.php b/ssl-alp/includes/class-ssl-alp-revisions.php index e5d2b59..3d80066 100644 --- a/ssl-alp/includes/class-ssl-alp-revisions.php +++ b/ssl-alp/includes/class-ssl-alp-revisions.php @@ -44,7 +44,6 @@ class SSL_ALP_Revisions extends SSL_ALP_Module { */ protected static $supported_unread_flag_post_types = array( 'post', - 'ssl_alp_inventory', ); /** From e1a109aeb33038551121ea89303cc1a25f7b2289 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 11:54:03 +0200 Subject: [PATCH 13/61] Fix bug with brackets --- ssl-alp/includes/class-ssl-alp-inventory.php | 26 +++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index d1e5225..c3d11e4 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -56,11 +56,10 @@ public function register_hooks() { // Register inventory item taxonomy. $loader->add_action( 'init', $this, 'register_taxonomy' ); - // Disallow creation of new terms directly (this is temporarily disabled - // by `associate_inventory_post_with_term`). - // NOTE: if this line is changed, the enable_disallow_insert_term_filter - // and disable_disallow_insert_term_filter functions must also be - // updated. + // Disallow creation of new terms directly (this is temporarily disabled by + // `associate_inventory_post_with_term`). + // NOTE: if this line is changed, the enable_disallow_insert_term_filter and + // disable_disallow_insert_term_filter functions must also be updated. $loader->add_filter( 'pre_insert_term', $this, 'disallow_insert_term', 10, 2 ); // Delete any invalid inventory items when post terms are set. @@ -109,12 +108,12 @@ public function inventory_settings_callback() { require_once SSL_ALP_BASE_DIR . 'partials/admin/settings/site/inventory-settings-display.php'; } - private function enable_disallow_insert_term_filter() { - add_filter( 'pre_insert_term', array( $this, 'disallow_insert_term', 10, 2 ) ); + public function enable_disallow_insert_term_filter() { + add_filter( 'pre_insert_term', array( $this, 'disallow_insert_term' ), 10, 2 ); } - private function disable_disallow_insert_term_filter() { - remove_filter( 'pre_insert_term', array( $this, 'disallow_insert_term', 10, 2 ) ); + public function disable_disallow_insert_term_filter() { + remove_filter( 'pre_insert_term', array( $this, 'disallow_insert_term' ), 10, 2 ); } /** @@ -429,9 +428,12 @@ public function register_taxonomy() { /** * Disallow the creation of new terms under normal circumstances. * - * This is to avoid users being able to create terms in the inventory - * taxonomy directly; terms should only be created when a new inventory post - * is created. + * This is to avoid users being able to create terms in the inventory taxonomy directly; terms + * should only be created when a new inventory post is created. + * + * This filter is disabled temporarily by `enable_disallow_insert_term_filter` to allow creation + * of new terms in acceptable circumstances, then reenabled by + * `enable_disallow_insert_term_filter`. * * @param string $term The term. * @param string $taxonomy The taxonomy. From ebfca68a052d17568874a7e816c4c0a2e43c3ea4 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 11:54:53 +0200 Subject: [PATCH 14/61] Disallow manual creation of coauthor terms --- ssl-alp/includes/class-ssl-alp-coauthors.php | 55 ++++++++++++++++++++ ssl-alp/tests/unit/test-coauthors.php | 2 + 2 files changed, 57 insertions(+) diff --git a/ssl-alp/includes/class-ssl-alp-coauthors.php b/ssl-alp/includes/class-ssl-alp-coauthors.php index e3da6e9..a88fe51 100644 --- a/ssl-alp/includes/class-ssl-alp-coauthors.php +++ b/ssl-alp/includes/class-ssl-alp-coauthors.php @@ -56,6 +56,12 @@ public function register_hooks() { // Set the current user as the default coauthor on new drafts. $loader->add_action( 'save_post', $this, 'add_user_to_draft', 10, 2 ); + // Disallow creation of new terms directly (this is temporarily disabled by + // `associate_inventory_post_with_term`). + // NOTE: if this line is changed, the enable_disallow_insert_term_filter and + // disable_disallow_insert_term_filter functions must also be updated. + $loader->add_filter( 'pre_insert_term', $this, 'disallow_insert_term', 10, 2 ); + // Delete any invalid coauthors when post terms are set. $loader->add_action( 'added_term_relationship', $this, 'reject_invalid_coauthor_terms', 10, 3 ); @@ -174,6 +180,14 @@ public function author_settings_callback() { require_once SSL_ALP_BASE_DIR . 'partials/admin/settings/post/author-settings-display.php'; } + public function enable_disallow_insert_term_filter() { + add_filter( 'pre_insert_term', array( $this, 'disallow_insert_term' ), 10, 2 ); + } + + public function disable_disallow_insert_term_filter() { + remove_filter( 'pre_insert_term', array( $this, 'disallow_insert_term' ), 10, 2 ); + } + /** * Register users widget. */ @@ -313,7 +327,14 @@ public function add_coauthor_term( $coauthor ) { 'slug' => $this->get_coauthor_term_slug( $coauthor ), ); + // Temporarily disable the filter that blocks creation of terms in the ssl_alp_coauthor + // taxonomy. + $this->disable_disallow_insert_term_filter(); + wp_insert_term( $coauthor->display_name, 'ssl_alp_coauthor', $args ); + + // Re-enable the filter. + $this->enable_disallow_insert_term_filter(); } else { // Update term. $this->update_coauthor_term( $coauthor->ID, $coauthor ); @@ -342,8 +363,15 @@ public function update_coauthor_term( $user_id, $old_user_object ) { 'slug' => $this->get_coauthor_term_slug( $user ), ); + // Temporarily disable the filter that blocks creation of terms in the ssl_alp_coauthor + // taxonomy. + $this->disable_disallow_insert_term_filter(); + // Set term name. wp_update_term( $term->term_id, 'ssl_alp_coauthor', $args ); + + // Re-enable the filter. + $this->enable_disallow_insert_term_filter(); } /** @@ -989,6 +1017,33 @@ public function add_user_to_draft( $post_id, $post ) { $this->set_coauthors( $post, $coauthors ); } + /** + * Disallow the creation of new terms under normal circumstances. + * + * This is to avoid users being able to create terms in the coauthor taxonomy directly; terms + * should only be created when a new user is created. + * + * This filter is disabled temporarily by `enable_disallow_insert_term_filter` to allow creation + * of new terms in acceptable circumstances, then reenabled by + * `enable_disallow_insert_term_filter`. + * + * @param string $term The term. + * @param string $taxonomy The taxonomy. + * + * @return string|WP_Error $term The term, or error. + */ + public function disallow_insert_term( $term, $taxonomy ) { + if ( 'ssl_alp_coauthor' !== $taxonomy ) { + return $term; + } + + // Return an error in all circumstances. + return new WP_Error( + 'disallow_insert_term', + __( 'Your role does not have permission to add terms to this taxonomy', 'ssl-alp' ) + ); + } + /** * Delete invalid coauthors when a post is saved. * diff --git a/ssl-alp/tests/unit/test-coauthors.php b/ssl-alp/tests/unit/test-coauthors.php index a630c4b..50f2a87 100644 --- a/ssl-alp/tests/unit/test-coauthors.php +++ b/ssl-alp/tests/unit/test-coauthors.php @@ -1398,6 +1398,7 @@ function test_invalid_coauthor_terms_are_removed() { ); // Create junk terms. + $ssl_alp->coauthors->disable_disallow_insert_term_filter(); $junk1 = wp_insert_term( 'junk_term', 'ssl_alp_coauthor', @@ -1412,6 +1413,7 @@ function test_invalid_coauthor_terms_are_removed() { 'slug' => 'ssl-alp-coauthor-nonexistent-user', ) ); + $ssl_alp->coauthors->enable_disallow_insert_term_filter(); // Add junk terms to the submission. $set_terms = $required_term_ids; From 68a90461a97e1609d2cabf6c80e40ed958f9df4c Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 16:58:57 +0200 Subject: [PATCH 15/61] Change icon --- ssl-alp/includes/class-ssl-alp-inventory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index c3d11e4..773f4fd 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -174,7 +174,7 @@ public function register_post_type() { ) ), ), - 'menu_icon' => 'dashicons-tag', + 'menu_icon' => 'dashicons-book-alt', 'supports' => array( 'title', 'editor', From 21e0f439ac19d12a7e0e3f2c7aa9099c505deced Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 21:06:25 +0200 Subject: [PATCH 16/61] Move sanitize querystring function to core --- ssl-alp/includes/class-ssl-alp-coauthors.php | 32 +++++--------------- ssl-alp/includes/class-ssl-alp-core.php | 16 ++++++++++ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-coauthors.php b/ssl-alp/includes/class-ssl-alp-coauthors.php index a88fe51..2906846 100644 --- a/ssl-alp/includes/class-ssl-alp-coauthors.php +++ b/ssl-alp/includes/class-ssl-alp-coauthors.php @@ -74,10 +74,10 @@ public function register_hooks() { $loader->add_filter( 'posts_groupby', $this, 'posts_groupby_filter', 10, 2 ); // Allow public coauthor query vars. - $loader->add_filter( 'query_vars', $this, 'whitelist_coauthor_search_query_vars' ); + $loader->add_filter( 'query_vars', $this, 'whitelist_search_query_vars' ); // Support coauthor querystrings in WP_Query. - $loader->add_action( 'parse_tax_query', $this, 'parse_coauthor_query_vars' ); + $loader->add_action( 'parse_tax_query', $this, 'parse_query_vars' ); // Filter to send comment notification/moderation emails to multiple authors. $loader->add_filter( 'comment_notification_recipients', $this, 'filter_comment_notification_email_recipients', 10, 2 ); @@ -1242,7 +1242,7 @@ public function set_coauthors( $post, $coauthors ) { * * @param string[] $public_query_vars Array of public query vars. */ - public function whitelist_coauthor_search_query_vars( $public_query_vars ) { + public function whitelist_search_query_vars( $public_query_vars ) { global $ssl_alp; if ( ! get_option( 'ssl_alp_allow_multiple_authors' ) ) { @@ -1256,7 +1256,7 @@ public function whitelist_coauthor_search_query_vars( $public_query_vars ) { } // Custom query vars to make public. These are sanitised and handled by - // `parse_coauthor_query_vars`. + // `parse_query_vars`. $custom_query_vars = array( 'ssl_alp_coauthor__and', 'ssl_alp_coauthor__in', @@ -1275,7 +1275,7 @@ public function whitelist_coauthor_search_query_vars( $public_query_vars ) { * * @param WP_Query $query The query. */ - public function parse_coauthor_query_vars( $query ) { + public function parse_query_vars( $query ) { global $ssl_alp; if ( ! get_option( 'ssl_alp_allow_multiple_authors' ) ) { @@ -1292,9 +1292,9 @@ public function parse_coauthor_query_vars( $query ) { $tax_query = array(); // Sanitize submitted values. - $this->sanitize_coauthor_querystring( $query, 'ssl_alp_coauthor__and' ); - $this->sanitize_coauthor_querystring( $query, 'ssl_alp_coauthor__in' ); - $this->sanitize_coauthor_querystring( $query, 'ssl_alp_coauthor__not_in' ); + $ssl_alp->core->sanitize_querystring( $query, 'ssl_alp_coauthor__and' ); + $ssl_alp->core->sanitize_querystring( $query, 'ssl_alp_coauthor__in' ); + $ssl_alp->core->sanitize_querystring( $query, 'ssl_alp_coauthor__not_in' ); // Get coauthor query vars. $coauthor_and = $query->get( 'ssl_alp_coauthor__and' ); @@ -1358,22 +1358,6 @@ public function parse_coauthor_query_vars( $query ) { $query->tax_query->queries = wp_parse_args( $tax_query, $query->tax_query->queries ); } - /** - * Sanitize coauthor querystring, returning an array of integers. - * - * Used for coauthor__in and coauthor__not_in. - * - * @param WP_Query $query Query object. - * @param string $query_var Query var whose contents to sanitize. - */ - private function sanitize_coauthor_querystring( $query, $query_var ) { - $querystring = $query->get( $query_var, array() ); - $querystring = array_map( 'absint', array_unique( (array) $querystring ) ); - - // Update querystring. - $query->set( $query_var, $querystring ); - } - /** * Action taken when user is deleted. This function does the deleting/reassigning of * posts instead of `wp_delete_user`. Since this plugin disables (single) author diff --git a/ssl-alp/includes/class-ssl-alp-core.php b/ssl-alp/includes/class-ssl-alp-core.php index 7eeb740..70fd066 100644 --- a/ssl-alp/includes/class-ssl-alp-core.php +++ b/ssl-alp/includes/class-ssl-alp-core.php @@ -168,6 +168,22 @@ public function register_hooks() { $loader->add_action( 'init', $this, 'disable_post_trackbacks' ); } + /** + * Sanitize term querystring, returning an array of integers. + * + * Used for e.g. coauthor__in, coauthor__not_in, ssl_alp_inventory_item__and, etc. + * + * @param WP_Query $query Query object. + * @param string $query_var Query var whose contents to sanitize. + */ + public function sanitize_querystring( $query, $query_var ) { + $querystring = $query->get( $query_var, array() ); + $querystring = array_map( 'absint', array_unique( (array) $querystring ) ); + + // Update querystring. + $query->set( $query_var, $querystring ); + } + /** * Filters supplied media type string into an array. * From 10cb40d3f83ff2c07d070dc2a3143a2b4be33263 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 21:08:03 +0200 Subject: [PATCH 17/61] Override inventory term archive URL to point to inventory post; add advanced search functionality for inventories; show tagged posts in inventory admin post list --- ssl-alp/includes/class-ssl-alp-inventory.php | 273 ++++++++++++++++++- 1 file changed, 267 insertions(+), 6 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index 773f4fd..8100a1f 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -40,10 +40,10 @@ public function register_hooks() { $loader->add_action( 'months_dropdown_results', $this, 'disable_months_dropdown_results', 10, 2 ); // Remove date column from admin post list. - $loader->add_filter( 'manage_edit-ssl_alp_inventory_columns', $this, 'manage_edit_columns' ); + $loader->add_filter( 'manage_edit-ssl_alp_inventory_columns', $this, 'remove_date_edit_column' ); // Sort inventory posts alphabetically by default. - $loader->add_filter( 'manage_edit-ssl_alp_inventory_sortable_columns', $this, 'manage_edit_sortable_columns' ); + $loader->add_filter( 'manage_edit-ssl_alp_inventory_sortable_columns', $this, 'remove_date_sort_edit_control' ); // Create/delete corresponding inventory item terms whenever posts are created/deleted. $loader->add_action( 'save_post', $this, 'associate_inventory_post_with_term', 10, 2 ); @@ -56,6 +56,19 @@ public function register_hooks() { // Register inventory item taxonomy. $loader->add_action( 'init', $this, 'register_taxonomy' ); + // Add posts column to admin post list and make it sortable. + $loader->add_filter( 'manage_edit-ssl_alp_inventory_columns', $this, 'add_posts_column_to_edit_table' ); + $loader->add_filter( 'manage_edit-ssl_alp_inventory_sortable_columns', $this, 'add_posts_column_to_edit_table' ); + + // Add posts to rows of the admin post list. + $loader->add_action( 'manage_ssl_alp_inventory_posts_custom_column', $this, 'add_posts_row_data', 10, 2 ); + + // Override default term links to point towards the term custom post instead of term + // archive. + // NOTE: if this line is changed, the `enable_override_term_link` and + // `disable_override_term_link` functions must also be updated. + $loader->add_filter( 'term_link', $this, 'override_term_link', 10, 3 ); + // Disallow creation of new terms directly (this is temporarily disabled by // `associate_inventory_post_with_term`). // NOTE: if this line is changed, the enable_disallow_insert_term_filter and @@ -65,6 +78,12 @@ public function register_hooks() { // Delete any invalid inventory items when post terms are set. $loader->add_action( 'added_term_relationship', $this, 'reject_invalid_inventory_terms', 10, 3 ); + // Allow public inventory item query vars. + $loader->add_filter( 'query_vars', $this, 'whitelist_search_query_vars' ); + + // Support inventory item querystrings in WP_Query. + $loader->add_action( 'parse_tax_query', $this, 'parse_query_vars' ); + // Filter to stop users from editing or deleting inventory terms directly. $loader->add_filter( 'user_has_cap', $this, 'filter_user_has_cap', 10, 4 ); @@ -108,6 +127,14 @@ public function inventory_settings_callback() { require_once SSL_ALP_BASE_DIR . 'partials/admin/settings/site/inventory-settings-display.php'; } + public function enable_override_term_link() { + add_filter( 'term_link', array( $this, 'override_term_link' ), 10, 3 ); + } + + public function disable_override_term_link() { + remove_filter( 'term_link', array( $this, 'override_term_link' ), 10, 3 ); + } + public function enable_disallow_insert_term_filter() { add_filter( 'pre_insert_term', array( $this, 'disallow_insert_term' ), 10, 2 ); } @@ -212,7 +239,7 @@ public function disable_months_dropdown_results( $months, $post_type ) { * @param array $columns Columns to show by default. * @return array Columns with date column removed. */ - public function manage_edit_columns( $columns ) { + public function remove_date_edit_column( $columns ) { if ( array_key_exists( 'date', $columns ) ) { // Remove date column. unset( $columns['date'] ); @@ -228,7 +255,7 @@ public function manage_edit_columns( $columns ) { * @param array $columns Sortable columns. * @return array Columns with title column set as default sort. */ - public function manage_edit_sortable_columns( $columns ) { + public function remove_date_sort_edit_control( $columns ) { if ( array_key_exists( 'date', $columns ) ) { // Remove date column. unset( $columns['date'] ); @@ -385,7 +412,7 @@ public function delete_associated_inventory_post_term( $post_id ) { wp_delete_term( $term->term_id, 'ssl_alp_inventory_item' ); clean_term_cache( array( $term->term_id ), 'ssl_alp_inventory_item' ); - } + } /** * Register the inventory taxonomy and add post type support. @@ -418,13 +445,124 @@ public function register_taxonomy() { 'public' => true, 'show_in_menu' => false, // Disable term edit page. 'show_in_rest' => true, // Needed for block editor support. - 'show_admin_column' => true, // Show associated terms in admin edit screen. + 'show_admin_column' => true, // Show associated terms in admin edit screen. + 'rewrite' => array( + 'slug' => 'inventory-posts', + ), ); // Create inventory taxonomy. register_taxonomy( 'ssl_alp_inventory_item', $this->supported_post_types, $args ); } + /** + * Add posts column to inventory post type post edit table. + * + * This is called twice: once for getting the columns, and once for getting the sortable + * columns. + * + * @param array $columns Columns to show by default. + * @return array Columns with new column. + */ + public function add_posts_column_to_edit_table( $columns ) { + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return $columns; + } + + $columns['posts'] = __( 'Posts', 'ssl-alp' ); + return $columns; + } + + /** + * Add post counts to inventory admin table rows. + * + * @param string $colname The column name. + * @param int $post_id The inventory post type post ID. + */ + public function add_posts_row_data( $colname, $post_id ) { + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return; + } + + if ( 'posts' !== $colname ) { + return; + } + + $term = $this->get_inventory_term( $post_id ); + + if ( is_null( $term ) ) { + return; + } + + if ( $term->count > 0 ) { + printf( + '%3$d', + esc_url( 'edit.php?taxonomy=ssl_alp_inventory_item&term=' . $this->get_inventory_term_slug( $post_id ) ), + esc_attr__( 'View posts for this inventory item', 'ssl-alp' ), + esc_html( number_format_i18n( $term->count ) ) + ); + } else { + echo number_format_i18n( 0 ); + } + } + + /** + * Override term links to point towards the inventory post page instead of the term archive. + * + * @param string $termlink Term link URL. + * @param object $term Term object. + * @param string $taxonomy Taxonomy slug. + * + * @return string The overridden term link. + */ + public function override_term_link( $link, $term, $taxonomy ) { + if ( 'ssl_alp_inventory_item' !== $taxonomy ) { + return $link; + } + + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return $link; + } + + $inventory_post = $this->get_post_from_inventory_term( $term ); + + if ( is_null( $inventory_post ) ) { + return $link; + } + + return get_permalink( $inventory_post ); + } + + /** + * Get the term archive link without overriding it to the corresponding custom post type post. + * + * @param WP_Term $term The term. + * + * @return string|null The term archive URL, or null if term not found or invalid. + */ + public function get_inventory_term_archive_url( $term ) { + if ( is_null( $term ) ) { + return; + } + + if ( 'ssl_alp_inventory_item' !== $term->taxonomy ) { + return; + } + + // Temporarily disable filter that overrides term link. + $this->disable_override_term_link(); + + $url = get_term_link( $term, 'ssl_alp_inventory_item' ); + + // Re-enable filter. + $this->enable_override_term_link(); + + return $url; + } + /** * Disallow the creation of new terms under normal circumstances. * @@ -488,6 +626,129 @@ public function reject_invalid_inventory_terms( $object_id, $tt_id, $taxonomy ) } } + /** + * Whitelist inventory item query vars. + * + * This allows inventory items to be queried publicly. + * + * @param string[] $public_query_vars Array of public query vars. + */ + public function whitelist_search_query_vars( $public_query_vars ) { + global $ssl_alp; + + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return $public_query_vars; + } + + if ( ! $ssl_alp->search->current_user_can_advanced_search() ) { + // Advanced search disabled. + return $public_query_vars; + } + + // Custom query vars to make public. These are sanitised and handled by + // `parse_query_vars`. + $custom_query_vars = array( + 'ssl_alp_inventory_item__and', + 'ssl_alp_inventory_item__in', + 'ssl_alp_inventory_item__not_in', + ); + + // Merge new query vars into existing ones. + return wp_parse_args( $custom_query_vars, $public_query_vars ); + } + + /** + * Sanitise inventory item querystrings and inject them as taxonomy filters into WP_Query. + * + * This detects values submitted through the custom search function and turns them into the + * filters expected by WP_Query. + * + * @param WP_Query $query The query. + */ + public function parse_query_vars( $query ) { + global $ssl_alp; + + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return; + } + + if ( ! $ssl_alp->search->current_user_can_advanced_search() ) { + // Advanced search disabled. + return; + } + + // Taxonomy query. + $tax_query = array(); + + // Sanitize submitted values. + $ssl_alp->core->sanitize_querystring( $query, 'ssl_alp_inventory_item__and' ); + $ssl_alp->core->sanitize_querystring( $query, 'ssl_alp_inventory_item__in' ); + $ssl_alp->core->sanitize_querystring( $query, 'ssl_alp_inventory_item__not_in' ); + + // Get inventory item query vars. + $inventory_item_and = $query->get( 'ssl_alp_inventory_item__and' ); + $inventory_item_in = $query->get( 'ssl_alp_inventory_item__in' ); + $inventory_not_in = $query->get( 'ssl_alp_inventory_item__not_in' ); + + if ( ! empty( $inventory_item_and ) && 1 === count( $inventory_item_and ) ) { + // There is only one AND term specified, so merge it into IN. + $inventory_item_in[] = absint( reset( $inventory_item_and ) ); + $inventory_item_and = array(); + + // Update querystring. This matches core behaviour for categories + // (but bizarrely not for tags: https://core.trac.wordpress.org/ticket/46459). + $query->set( 'ssl_alp_inventory_item__and', $inventory_item_and ); + $query->set( 'ssl_alp_inventory_item__in', $inventory_item_in ); + } + + if ( ! empty( $inventory_item_and ) ) { + // Inventory item AND search criterion specified. + $tax_query[] = array( + // Note, this is different from how parse_tax_query handles + // e.g. tag__and because we have to inject the tax query after + // WP_Tax_Query has already been instantiated, which normally + // applies the relation as part of its instantiation. + 'relation' => 'AND', + array( + 'taxonomy' => 'ssl_alp_inventory_item', + 'terms' => $inventory_item_and, + 'field' => 'term_id', + 'operator' => 'AND', + 'include_children' => false, + ), + ); + } + + if ( ! empty( $inventory_item_in ) ) { + // Coauthor IN search criterion specified. + $tax_query[] = array( + 'taxonomy' => 'ssl_alp_inventory_item', + 'terms' => $inventory_item_in, + 'field' => 'term_id', + 'include_children' => false, + ); + } + + if ( ! empty( $inventory_not_in ) ) { + // Coauthor NOT IN search criterion specified. + $tax_query[] = array( + 'taxonomy' => 'ssl_alp_inventory_item', + 'terms' => $inventory_not_in, + 'field' => 'term_id', + 'operator' => 'NOT IN', + 'include_children' => false, + ); + } + + // Sanitize new taxonomy filters. + $tax_query = $query->tax_query->sanitize_query( $tax_query ); + + // Merge new taxonomy filters into existing ones. + $query->tax_query->queries = wp_parse_args( $tax_query, $query->tax_query->queries ); + } + /** * Stop users editing or deleting inventory terms. * From 87ebbfb75c135b7c83ea3274cd4a508b7aacab2d Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 21:12:17 +0200 Subject: [PATCH 18/61] Add check to avoid referenced posts which cannot be read by user from showing in list --- ssl-alp/includes/class-ssl-alp-references.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ssl-alp/includes/class-ssl-alp-references.php b/ssl-alp/includes/class-ssl-alp-references.php index 0255d32..834916e 100644 --- a/ssl-alp/includes/class-ssl-alp-references.php +++ b/ssl-alp/includes/class-ssl-alp-references.php @@ -262,6 +262,16 @@ public function get_reference_to_posts( $post = null ) { continue; } + if ( ! post_type_exists( $referenced_post->post_type ) ) { + // The referenced post is some type that doesn't exist any more. + continue; + } + + // Check user permission to view. + if ( ! current_user_can( 'read', $referenced_post ) ) { + continue; + } + $posts[] = $referenced_post; } @@ -330,6 +340,16 @@ public function get_reference_from_posts( $post = null ) { continue; } + if ( ! post_type_exists( $referenced_post->post_type ) ) { + // The referenced post is some type that doesn't exist any more. + continue; + } + + // Check user permission to view. + if ( ! current_user_can( 'read', $referenced_post ) ) { + continue; + } + $posts[] = $referenced_post; } From dddab3aa736824fd0979f1517521a12c24a4431d Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 21:13:17 +0200 Subject: [PATCH 19/61] Show post type in recent revisions widget if not normal post --- .../includes/class-ssl-alp-revisions-widget.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ssl-alp/includes/class-ssl-alp-revisions-widget.php b/ssl-alp/includes/class-ssl-alp-revisions-widget.php index 741aeab..67cf18f 100644 --- a/ssl-alp/includes/class-ssl-alp-revisions-widget.php +++ b/ssl-alp/includes/class-ssl-alp-revisions-widget.php @@ -137,6 +137,22 @@ private function the_revisions( $number ) { ) ); + // Post type (only for non-posts). + if ( 'post' !== $parent->post_type ) { + $post_type = get_post_type_object( $parent->post_type ); + $post_type_label = sprintf( + /* translators: 1: referenced post type label */ + __( '(%1$s)', 'ssl-alp' ), + $post_type->labels->singular_name + ); + + echo ' '; + printf( + '%1$s', + esc_html( $post_type_label ) + ); + } + echo ''; } From 0a99a273ba21a3d10c6504e5fde8090290b74804 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 21:42:07 +0200 Subject: [PATCH 20/61] Make revisions list table more generic to post types, and add inventory revisions list table admin page --- ssl-alp/alp.php | 1 + ssl-alp/includes/class-ssl-alp-inventory.php | 37 +++++++++++++++++++ .../class-ssl-alp-revisions-list-table.php | 28 +++++++++----- ssl-alp/includes/class-ssl-alp-revisions.php | 9 +++-- .../includes/class-ssl-alp-uninstaller.php | 1 + 5 files changed, 62 insertions(+), 14 deletions(-) diff --git a/ssl-alp/alp.php b/ssl-alp/alp.php index e24dd4f..81909f0 100644 --- a/ssl-alp/alp.php +++ b/ssl-alp/alp.php @@ -48,6 +48,7 @@ define( 'SSL_ALP_SITE_TOOLS_MENU_SLUG', 'ssl-alp-admin-tools' ); define( 'SSL_ALP_POST_REVISIONS_MENU_SLUG', 'ssl-alp-admin-post-revisions' ); define( 'SSL_ALP_PAGE_REVISIONS_MENU_SLUG', 'ssl-alp-admin-page-revisions' ); +define( 'SSL_ALP_INVENTORY_REVISIONS_MENU_SLUG', 'ssl-alp-admin-inventory-revisions' ); define( 'SSL_ALP_APPLICATIONS_MENU_SLUG', 'ssl-alp-admin-applications' ); /** diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index 8100a1f..cc7921d 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -49,6 +49,9 @@ public function register_hooks() { $loader->add_action( 'save_post', $this, 'associate_inventory_post_with_term', 10, 2 ); $loader->add_action( 'deleted_post', $this, 'delete_associated_inventory_post_term' ); + // Add admin revisions tables. + $loader->add_action( 'admin_menu', $this, 'add_revisions_page' ); + /** * Inventory taxonomy. */ @@ -414,6 +417,40 @@ public function delete_associated_inventory_post_term( $post_id ) { clean_term_cache( array( $term->term_id ), 'ssl_alp_inventory_item' ); } + /** + * Add revisions pages to admin menu. + * + * @global $ssl_alp + */ + public function add_revisions_page() { + global $ssl_alp; + + $hook_suffix = add_submenu_page( + 'edit.php?post_type=ssl_alp_inventory', + __( 'Revisions', 'ssl-alp' ), + __( 'Revisions', 'ssl-alp' ), + 'read', + SSL_ALP_INVENTORY_REVISIONS_MENU_SLUG, + array( $ssl_alp->revisions, 'output_admin_revisions_page' ) + ); + + if ( $hook_suffix ) { + // Add callback for loading the page. + add_action( "load-{$hook_suffix}", array( $this, 'load_revisions_page_screen_options' ) ); + } + } + + /** + * Load revisions page screen options. + * + * @global $ssl_alp + */ + public function load_revisions_page_screen_options() { + global $ssl_alp; + + return $ssl_alp->revisions->load_revisions_page_screen_options( 'ssl_alp_inventory', SSL_ALP_INVENTORY_REVISIONS_MENU_SLUG ); + } + /** * Register the inventory taxonomy and add post type support. */ diff --git a/ssl-alp/includes/class-ssl-alp-revisions-list-table.php b/ssl-alp/includes/class-ssl-alp-revisions-list-table.php index d8cc283..7a63e0e 100644 --- a/ssl-alp/includes/class-ssl-alp-revisions-list-table.php +++ b/ssl-alp/includes/class-ssl-alp-revisions-list-table.php @@ -19,18 +19,25 @@ */ class SSL_ALP_Revisions_List_Table extends WP_List_Table { /** - * Revisions post type. Sets whether posts or pages are displayed. + * Revisions post type. Determines the post type revisions shown. * * @var string */ protected $post_type; + /** + * Menu slug. Used for links. + * + * @var string + */ + protected $menu_slug; + /** * Constructor. * * @param string $post_type Post type to show revisions for. */ - public function __construct( $post_type = 'post' ) { + public function __construct( $post_type, $menu_slug ) { parent::__construct( array( 'singular' => __( 'Revision', 'ssl-alp' ), @@ -39,11 +46,13 @@ public function __construct( $post_type = 'post' ) { ) ); - if ( ! in_array( $post_type, array( 'post', 'page' ), true ) ) { - $post_type = 'post'; + if ( ! post_type_supports( $post_type, 'revisions' ) ) { + // Post type not supported. + return; } $this->post_type = $post_type; + $this->menu_slug = $menu_slug; } /** @@ -125,13 +134,12 @@ protected function get_views() { * Get URL query arguments depending on post type. */ private function get_page_args() { - $args = array(); + $args = array( + 'page' => $this->menu_slug, + ); - if ( 'post' === $this->post_type ) { - $args['page'] = SSL_ALP_POST_REVISIONS_MENU_SLUG; - } elseif ( 'page' === $this->post_type ) { - $args['page'] = SSL_ALP_PAGE_REVISIONS_MENU_SLUG; - $args['post_type'] = 'page'; + if ( 'post' !== $this->post_type ) { + $args['post_type'] = $this->post_type; } return $args; diff --git a/ssl-alp/includes/class-ssl-alp-revisions.php b/ssl-alp/includes/class-ssl-alp-revisions.php index 3d80066..fc6e79c 100644 --- a/ssl-alp/includes/class-ssl-alp-revisions.php +++ b/ssl-alp/includes/class-ssl-alp-revisions.php @@ -787,22 +787,23 @@ public function add_revisions_page() { * Load post revisions page screen options. */ public function load_post_revisions_page_screen_options() { - return $this->load_revisions_page_screen_options( 'post' ); + return $this->load_revisions_page_screen_options( 'post', SSL_ALP_POST_REVISIONS_MENU_SLUG ); } /** * Load page revisions page screen options. */ public function load_page_revisions_page_screen_options() { - return $this->load_revisions_page_screen_options( 'page' ); + return $this->load_revisions_page_screen_options( 'page', SSL_ALP_PAGE_REVISIONS_MENU_SLUG ); } /** * Load revisions page screen options. * * @param string $post_type Post type. Either 'post' or 'page'. + * @param string $menu_slug Menu slug. */ - private function load_revisions_page_screen_options( $post_type ) { + public function load_revisions_page_screen_options( $post_type, $menu_slug ) { $arguments = array( 'label' => __( 'Revisions Per Page', 'ssl-alp' ), 'default' => 20, @@ -815,7 +816,7 @@ private function load_revisions_page_screen_options( $post_type ) { * Instantiate the revisions list table. Creating the instance here allow the core * WP_List_Table class to automatically load the table columns in the screen options panel. */ - $this->revisions_list_table = new SSL_ALP_Revisions_List_Table( $post_type ); + $this->revisions_list_table = new SSL_ALP_Revisions_List_Table( $post_type, $menu_slug ); } /** diff --git a/ssl-alp/includes/class-ssl-alp-uninstaller.php b/ssl-alp/includes/class-ssl-alp-uninstaller.php index d51e18b..7f9f674 100644 --- a/ssl-alp/includes/class-ssl-alp-uninstaller.php +++ b/ssl-alp/includes/class-ssl-alp-uninstaller.php @@ -273,6 +273,7 @@ private static function delete_user_metas() { // Screen column settings. self::delete_user_meta( 'manageposts_page_ssl-alp-admin-revisionscolumnshidden' ); self::delete_user_meta( 'manageusers_page_ssl-alp-admin-applicationscolumnshidden' ); + self::delete_user_meta( 'managessl_alp_inventory_page_ssl-alp-admin-inventory-revisionscolumnshidden' ); } /** From 86e63111a4bcd4598be626e4a13cb44cf811f326 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 21:55:09 +0200 Subject: [PATCH 21/61] Use transients instead of cache for recent revisions list --- ssl-alp/includes/class-ssl-alp-revisions.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-revisions.php b/ssl-alp/includes/class-ssl-alp-revisions.php index fc6e79c..c5c64ee 100644 --- a/ssl-alp/includes/class-ssl-alp-revisions.php +++ b/ssl-alp/includes/class-ssl-alp-revisions.php @@ -885,7 +885,7 @@ public function get_author_grouped_published_revisions( $number, $order = 'DESC' // Reference posts cache key. $cache_key = 'ssl-alp-revisions-' . $number . '-' . $order; - $object_ids = wp_cache_get( $cache_key ); + $object_ids = get_transient( $cache_key ); if ( false === $object_ids ) { /** @@ -917,7 +917,7 @@ public function get_author_grouped_published_revisions( $number, $order = 'DESC' ) ); - wp_cache_set( $cache_key, $object_ids ); + set_transient( $cache_key, $object_ids, SSL_ALP_RECENT_REVISIONS_CACHE_TIMEOUT ); } return $object_ids; @@ -1569,7 +1569,7 @@ public function mark_post_as_unread_for_users_after_update( $post_id, $post_afte * * @param WP_Post $new_revision New revision. * @param WP_Post|null $old_revision Previous revision. If not specified, the revision - * immediately prior to $post_after is used. + * immediately prior to $new_revision is used. * @return array|null Array containing lines added and removed, or null if difference can't be * determined. */ From ba638818ce44d0c2cb25257ee18d343a0a282853 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 4 Aug 2019 22:57:28 +0200 Subject: [PATCH 22/61] Change recent revision list to transient and add function to check text changes --- ssl-alp/alp.php | 4 +++ ssl-alp/includes/class-ssl-alp-revisions.php | 34 +++++++++++++------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/ssl-alp/alp.php b/ssl-alp/alp.php index 81909f0..a754f83 100644 --- a/ssl-alp/alp.php +++ b/ssl-alp/alp.php @@ -61,8 +61,12 @@ * Default settings */ +// KaTeX version. define( 'SSL_ALP_KATEX_VERSION', '0.10.1' ); +// Recent revisions widget cache timeout. +define( 'SSL_ALP_RECENT_REVISIONS_CACHE_TIMEOUT', 5 * 60 ); + /** * Code to run on plugin activation and deactivation. */ diff --git a/ssl-alp/includes/class-ssl-alp-revisions.php b/ssl-alp/includes/class-ssl-alp-revisions.php index c5c64ee..daaa28c 100644 --- a/ssl-alp/includes/class-ssl-alp-revisions.php +++ b/ssl-alp/includes/class-ssl-alp-revisions.php @@ -885,9 +885,9 @@ public function get_author_grouped_published_revisions( $number, $order = 'DESC' // Reference posts cache key. $cache_key = 'ssl-alp-revisions-' . $number . '-' . $order; - $object_ids = get_transient( $cache_key ); + $posts = get_transient( $cache_key ); - if ( false === $object_ids ) { + if ( false === $posts ) { /** * Get last $number revisions (don't need parents) grouped by author and parent id, ordered * by date descending, where number is > 1 if the revision was made by the original author @@ -896,7 +896,7 @@ public function get_author_grouped_published_revisions( $number, $order = 'DESC' * * Note: `post_date` is the most recent revision found in each group. */ - $object_ids = $wpdb->get_results( + $posts = $wpdb->get_results( $wpdb->prepare( "SELECT posts.post_author, posts.post_parent, MAX(posts.post_date) AS post_date, COUNT(1) AS number, parent_posts.post_author AS parent_author @@ -917,10 +917,10 @@ public function get_author_grouped_published_revisions( $number, $order = 'DESC' ) ); - set_transient( $cache_key, $object_ids, SSL_ALP_RECENT_REVISIONS_CACHE_TIMEOUT ); + set_transient( $cache_key, $posts, SSL_ALP_RECENT_REVISIONS_CACHE_TIMEOUT ); } - return $object_ids; + return $posts; } /** @@ -1549,13 +1549,7 @@ public function mark_post_as_unread_for_users_after_update( $post_id, $post_afte require ABSPATH . WPINC . '/wp-diff.php'; } - // Compute text difference between old and new posts. - $diff = $this->get_post_text_differences( $post_after, $post_before ); - - // Post content is deemed changed if there are new or deleted lines. - $changed = $diff['added'] > 1 || $diff['removed'] > 1; - - if ( ! $changed ) { + if ( ! $this->have_post_content_lines_changed( $post_after, $post_before ) ) { return; } } @@ -1618,6 +1612,22 @@ public function get_post_text_differences( $new_revision, $old_revision = null ) ); } + /** + * Check if post content lines changed between two revisions of a post. + * + * @param WP_Post $new_revision New revision. + * @param WP_Post|null $old_revision Previous revision. If not specified, the revision + * immediately prior to $new_revision is used. + * @return bool Whether post content lines changed. + */ + public function have_post_content_lines_changed( $new_revision, $old_revision = null ) { + // Compute text difference between old and new posts. + $diff = $this->get_post_text_differences( $new_revision, $old_revision ); + + // Post content is deemed changed if there are new or deleted lines. + return $diff['added'] > 1 || $diff['removed'] > 1; + } + /** * Get post read status for specified post and user. * From 398b3d5133e19bfcb6827365db921dc74ae5f41e Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 5 Aug 2019 20:37:29 +0200 Subject: [PATCH 23/61] Move and expand permission check --- ssl-alp/includes/class-ssl-alp-core.php | 28 +++++++++++++++++++ ssl-alp/includes/class-ssl-alp-references.php | 11 ++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-core.php b/ssl-alp/includes/class-ssl-alp-core.php index 70fd066..8d7d54b 100644 --- a/ssl-alp/includes/class-ssl-alp-core.php +++ b/ssl-alp/includes/class-ssl-alp-core.php @@ -184,6 +184,34 @@ public function sanitize_querystring( $query, $query_var ) { $query->set( $query_var, $querystring ); } + /** + * Checks if the current user (including not logged in users), can read the specified post. + * + * @param WP_Post $post The post. + * + * @return bool|null The permission, or null if the post is invalid. + */ + public function current_user_can_read_post( $post ) { + $post = get_post( $post ); + + if ( is_null( $post ) ) { + return; + } + + if ( is_user_logged_in() ) { + $post_type_obj = get_post_type_object( $post->post_type ); + + if ( is_null( $post_type_obj ) ) { + return; + } + + return current_user_can( $post_type_obj->cap->read_post, $post ); + } else { + // Anonymous user on a public site. + return 'publish' === get_post_status( $post ); + } + } + /** * Filters supplied media type string into an array. * diff --git a/ssl-alp/includes/class-ssl-alp-references.php b/ssl-alp/includes/class-ssl-alp-references.php index abd01f1..7f40a9a 100644 --- a/ssl-alp/includes/class-ssl-alp-references.php +++ b/ssl-alp/includes/class-ssl-alp-references.php @@ -226,8 +226,12 @@ public function rebuild_references() { * * @param int|WP_Post|null $post Post ID or post object. Defaults to global $post. * @return array|null Referenced posts, or null if invalid post specified. + * + * @global $ssl_alp */ public function get_reference_to_posts( $post = null ) { + global $ssl_alp; + $post = get_post( $post ); if ( is_null( $post ) ) { @@ -269,7 +273,7 @@ public function get_reference_to_posts( $post = null ) { } // Check user permission to view. - if ( ! current_user_can( 'read', $referenced_post ) ) { + if ( ! $ssl_alp->core->current_user_can_read_post( $referenced_post ) ) { continue; } @@ -285,9 +289,10 @@ public function get_reference_to_posts( $post = null ) { * @param int|WP_Post|null $post Post ID or post object. Defaults to global $post. * @return array|null Referencing posts, or null if invalid post specified. * @global $wpdb + * @global $ssl_alp; */ public function get_reference_from_posts( $post = null ) { - global $wpdb; + global $wpdb, $ssl_alp; $post = get_post( $post ); @@ -347,7 +352,7 @@ public function get_reference_from_posts( $post = null ) { } // Check user permission to view. - if ( ! current_user_can( 'read', $referenced_post ) ) { + if ( ! $ssl_alp->core->current_user_can_read_post( $referenced_post ) ) { continue; } From 891bb96d6bb97cc7b9797d5a75c06a402ff242ae Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 5 Aug 2019 20:37:43 +0200 Subject: [PATCH 24/61] Check cross-references against user roles --- ssl-alp/tests/unit/test-references.php | 182 +++++++++++++++++-------- 1 file changed, 123 insertions(+), 59 deletions(-) diff --git a/ssl-alp/tests/unit/test-references.php b/ssl-alp/tests/unit/test-references.php index 935eec2..bc6e348 100644 --- a/ssl-alp/tests/unit/test-references.php +++ b/ssl-alp/tests/unit/test-references.php @@ -4,9 +4,55 @@ * Cross-references tests */ class CrossReferencesTest extends WP_UnitTestCase { + protected $admin; + protected $editor; + protected $author; + protected $contributor; + protected $subscriber; + + protected $user_ids; + public function setUp() { parent::setUp(); + $this->admin = $this->factory->user->create_and_get( + array( + 'role' => 'administrator' + ) + ); + + $this->editor = $this->factory->user->create_and_get( + array( + 'role' => 'editor' + ) + ); + + $this->author = $this->factory->user->create_and_get( + array( + 'role' => 'author' + ) + ); + + $this->contributor = $this->factory->user->create_and_get( + array( + 'role' => 'contributor' + ) + ); + + $this->subscriber = $this->factory->user->create_and_get( + array( + 'role' => 'subscriber' + ) + ); + + $this->users = array( + $this->admin, + $this->editor, + $this->author, + $this->contributor, + $this->subscriber, + ); + $this->post_1 = $this->factory->post->create_and_get( array( 'post_content' => 'This contains no cross-references.' @@ -97,72 +143,84 @@ function test_references_to() { // rebuild references $ssl_alp->references->rebuild_references(); - // post 1 references nothing - $this->assertEquals( - $ssl_alp->references->get_reference_to_posts( $this->post_1 ), - array() - ); - - // post 2 references post 1 - $this->assertEquals( - $ssl_alp->references->get_reference_to_posts( $this->post_2 ), - array( $this->post_1 ) - ); - - // post 3 references posts 1 and 2 - $this->assertEqualSets( - $ssl_alp->references->get_reference_to_posts( $this->post_3 ), - array( $this->post_1, $this->post_2 ) - ); - - // page 1 references nothing - $this->assertEquals( - $ssl_alp->references->get_reference_to_posts( $this->page_1 ), - array() - ); - - // page 2 references post 1 - $this->assertEquals( - $ssl_alp->references->get_reference_to_posts( $this->page_2 ), - array( $this->post_1 ) - ); + foreach ( $this->users as $user ) { + wp_set_current_user( $user->ID ); + + // post 1 references nothing + $this->assertEquals( + $ssl_alp->references->get_reference_to_posts( $this->post_1 ), + array() + ); + + // post 2 references post 1 + $this->assertEquals( + $ssl_alp->references->get_reference_to_posts( $this->post_2 ), + array( $this->post_1 ) + ); + + // post 3 references posts 1 and 2 + $this->assertEqualSets( + $ssl_alp->references->get_reference_to_posts( $this->post_3 ), + array( $this->post_1, $this->post_2 ) + ); + + // page 1 references nothing + $this->assertEquals( + $ssl_alp->references->get_reference_to_posts( $this->page_1 ), + array() + ); + + // page 2 references post 1 + $this->assertEquals( + $ssl_alp->references->get_reference_to_posts( $this->page_2 ), + array( $this->post_1 ) + ); + } + + wp_set_current_user( 0 ); } function test_references_from() { global $ssl_alp; - // rebuild references + // Rebuild references. $ssl_alp->references->rebuild_references(); - // post 1 referenced by posts 2 and 3 and page 2 - $this->assertEqualSets( - $ssl_alp->references->get_reference_from_posts( $this->post_1 ), - array( $this->post_2, $this->post_3, $this->page_2 ) - ); - - // post 2 referenced by post 3 - $this->assertEquals( - $ssl_alp->references->get_reference_from_posts( $this->post_2 ), - array( $this->post_3 ) - ); - - // post 3 referenced by nothing - $this->assertEquals( - $ssl_alp->references->get_reference_from_posts( $this->post_3 ), - array() - ); - - // page 1 referenced by nothing - $this->assertEquals( - $ssl_alp->references->get_reference_from_posts( $this->page_1 ), - array() - ); - - // page 2 referenced by nothing - $this->assertEquals( - $ssl_alp->references->get_reference_from_posts( $this->page_2 ), - array() - ); + foreach ( $this->users as $user ) { + wp_set_current_user( $user->ID ); + + // post 1 referenced by posts 2 and 3 and page 2 + $this->assertEqualSets( + $ssl_alp->references->get_reference_from_posts( $this->post_1 ), + array( $this->post_2, $this->post_3, $this->page_2 ) + ); + + // post 2 referenced by post 3 + $this->assertEquals( + $ssl_alp->references->get_reference_from_posts( $this->post_2 ), + array( $this->post_3 ) + ); + + // post 3 referenced by nothing + $this->assertEquals( + $ssl_alp->references->get_reference_from_posts( $this->post_3 ), + array() + ); + + // page 1 referenced by nothing + $this->assertEquals( + $ssl_alp->references->get_reference_from_posts( $this->page_1 ), + array() + ); + + // page 2 referenced by nothing + $this->assertEquals( + $ssl_alp->references->get_reference_from_posts( $this->page_2 ), + array() + ); + } + + wp_set_current_user( 0 ); } function test_invalid_references() { @@ -272,6 +330,8 @@ function test_references_after_edit_and_revert() { $ssl_alp->references->get_reference_to_posts( $post ), array( $this->post_1 ) ); + + wp_set_current_user( 0 ); } function test_self_reference() { @@ -306,6 +366,8 @@ function test_self_reference() { $ssl_alp->references->get_reference_to_posts( $post ), array( $this->post_1 ) ); + + wp_set_current_user( 0 ); } function test_draft_reference() { @@ -345,5 +407,7 @@ function test_draft_reference() { $ssl_alp->references->get_reference_from_posts( $published ), array() ); + + wp_set_current_user( 0 ); } } From a2a53f81d61f62af59204fe247a43e36aaad813b Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 5 Aug 2019 20:45:46 +0200 Subject: [PATCH 25/61] Add test for invalid post type --- ssl-alp/tests/unit/test-references.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/ssl-alp/tests/unit/test-references.php b/ssl-alp/tests/unit/test-references.php index bc6e348..1cae818 100644 --- a/ssl-alp/tests/unit/test-references.php +++ b/ssl-alp/tests/unit/test-references.php @@ -239,6 +239,29 @@ function test_invalid_references() { ); } + public function test_references_from_invalid_post_types() { + global $ssl_alp; + + $invalid_post = $this->factory->post->create_and_get( + array( + 'post_content' => sprintf( + 'Cross reference to post 1.', + get_permalink( $this->post_1 ) + ), + 'post_type' => 'invalid', + ) + ); + + // Rebuild references. + $ssl_alp->references->rebuild_references(); + + // Post 1 references don't include the new post. + $this->assertEquals( + $ssl_alp->references->get_reference_from_posts( $this->post_1 ), + array( $this->post_2, $this->post_3, $this->page_2 ) + ); + } + function test_multi_reference() { global $ssl_alp; From 904ff12e8189ab56103424cadbdbac9b8510e586 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 5 Aug 2019 22:15:33 +0200 Subject: [PATCH 26/61] Change posts per page to nopaging --- ssl-alp/includes/class-ssl-alp-references.php | 6 +++--- ssl-alp/tests/unit/test-coauthors-search.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-references.php b/ssl-alp/includes/class-ssl-alp-references.php index 7f40a9a..6670454 100644 --- a/ssl-alp/includes/class-ssl-alp-references.php +++ b/ssl-alp/includes/class-ssl-alp-references.php @@ -209,9 +209,9 @@ public function rebuild_references() { foreach ( array_keys( $this->supported_reference_post_types ) as $post_type ) { $posts = get_posts( array( - 'post_type' => $post_type, - 'post_status' => 'published', - 'posts_per_page' => -1, // Needed to get all. + 'post_type' => $post_type, + 'post_status' => 'published', + 'nopaging' => true, ) ); diff --git a/ssl-alp/tests/unit/test-coauthors-search.php b/ssl-alp/tests/unit/test-coauthors-search.php index b5aaf06..2a14203 100644 --- a/ssl-alp/tests/unit/test-coauthors-search.php +++ b/ssl-alp/tests/unit/test-coauthors-search.php @@ -76,9 +76,9 @@ private function create_coauthor_post( $author, $coauthors = array() ) { protected function get_search_results( $search_string, $extra_args ) { $query_data = array( - 's' => $search_string, - 'post_type' => 'post', - 'posts_per_page' => -1, // Required to get all results. + 's' => $search_string, + 'post_type' => 'post', + 'nopaging' => true, // Required to get all results. ); $query_data = wp_parse_args( $extra_args, $query_data ); From 91acec70511f64c891f509070c29303a71584137 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 5 Aug 2019 22:16:17 +0200 Subject: [PATCH 27/61] Change recent revisions list generation method --- .../class-ssl-alp-revisions-widget.php | 3 + ssl-alp/includes/class-ssl-alp-revisions.php | 137 +++++++++++++----- 2 files changed, 104 insertions(+), 36 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-revisions-widget.php b/ssl-alp/includes/class-ssl-alp-revisions-widget.php index 67cf18f..530b480 100644 --- a/ssl-alp/includes/class-ssl-alp-revisions-widget.php +++ b/ssl-alp/includes/class-ssl-alp-revisions-widget.php @@ -93,6 +93,9 @@ public function update( $new_instance, $old_instance ) { $instance['title'] = ! empty( $new_instance['title'] ) ? wp_strip_all_tags( $new_instance['title'] ) : ''; $instance['number'] = absint( $new_instance['number'] ); + // Invalidate cached recent revisions. + delete_transient( 'ssl-alp-recent-revisions' ); + return $instance; } diff --git a/ssl-alp/includes/class-ssl-alp-revisions.php b/ssl-alp/includes/class-ssl-alp-revisions.php index daaa28c..ef63bc8 100644 --- a/ssl-alp/includes/class-ssl-alp-revisions.php +++ b/ssl-alp/includes/class-ssl-alp-revisions.php @@ -875,49 +875,111 @@ public function get_author_grouped_published_revisions( $number, $order = 'DESC' global $wpdb; $number = absint( $number ); - $order = esc_sql( ( 'ASC' === strtoupper( $order ) ) ? 'ASC' : 'DESC' ); - - // Get post types that support edit summaries, and filter for SQL. - $supported_post_types = get_post_types_by_support( 'revisions' ); - $supported_post_types = array_map( 'esc_sql', $supported_post_types ); - $supported_types_clause = "'" . implode( "', '", $supported_post_types ) . "'"; // Reference posts cache key. - $cache_key = 'ssl-alp-revisions-' . $number . '-' . $order; - - $posts = get_transient( $cache_key ); + $posts = get_transient( 'ssl-alp-recent-revisions' ); if ( false === $posts ) { /** - * Get last $number revisions (don't need parents) grouped by author and parent id, ordered - * by date descending, where number is > 1 if the revision was made by the original author - * (this prevents the original published post showing up as a revision), or > 0 if the - * revision was made by someone else. Ignore autosaves. - * - * Note: `post_date` is the most recent revision found in each group. + * Generate post list. */ - $posts = $wpdb->get_results( - $wpdb->prepare( - "SELECT posts.post_author, posts.post_parent, MAX(posts.post_date) AS post_date, - COUNT(1) AS number, parent_posts.post_author AS parent_author - FROM {$wpdb->posts} AS posts - INNER JOIN {$wpdb->posts} AS parent_posts ON posts.post_parent = parent_posts.ID - WHERE - posts.post_type = 'revision' - AND LOCATE(CONCAT(posts.post_parent, '-autosave'), posts.post_name) = 0 - AND posts.post_status = 'inherit' - AND posts.post_date > parent_posts.post_date - AND parent_posts.post_status = 'publish' - AND parent_posts.post_type IN ({$supported_types_clause}) - GROUP BY posts.post_author, posts.post_parent - HAVING (number > 1) OR (posts.post_author <> parent_posts.post_author) - ORDER BY post_date {$order} - LIMIT %d", - $number - ) - ); - set_transient( $cache_key, $posts, SSL_ALP_RECENT_REVISIONS_CACHE_TIMEOUT ); + $supported_post_types = get_post_types_by_support( 'revisions' ); + + $maxiter = 10 * $number; + $iter = 0; + $offset = 0; + $posts = array(); + $last_post = null; + // Array of user IDs and the post IDs they've edited contained in the $posts array. + $user_post_revisions = array(); + + while ( count( $posts ) < $number ) { + if ( ++$iter > $maxiter ) { + // Maximum iterations reached without finding $number posts. Proceed with what + // we have. + break; + } + + $post = get_posts( + array( + 'post_type' => 'revision', + 'post_status' => 'inherit', + 'orderby' => 'date', + 'order' => $order, + 'posts_per_page' => 1, + 'offset' => $offset, + ) + ); + + if ( empty( $post ) ) { + // Stop searching. + break; + } + + $offset++; + $post = $post[0]; + $parent = get_post( $post->post_parent ); + + if ( is_null( $parent ) ) { + // Invalid parent. + continue; + } + + if ( ! in_array( $parent->post_type, $supported_post_types, true ) ) { + // Unsupported post type. + continue; + } + + if ( $post->post_date <= $parent->post_date ) { + // Draft. + continue; + } + + if ( wp_is_post_autosave( $post ) ) { + // Autosave. + continue; + } + + if ( 'publish' !== $parent->post_status ) { + // Unpublished. + continue; + } + + if ( $this->revision_was_autogenerated_on_publication( $post ) ) { + // Autogenerated. + continue; + } + + if ( ! is_null( $last_post ) ) { + if ( $post->post_parent === $last_post->post_parent && $post->post_author === $last_post->post_author ) { + // This is a further edit to the same post by the same author. + continue; + } + } + + if ( ! $this->have_post_content_lines_changed( $post ) ) { + // Insufficient changes. + continue; + } + + if ( array_key_exists( $post->post_author, $user_post_revisions ) ) { + if ( in_array( $parent->ID, $user_post_revisions[ $post->post_author ] ) ) { + // User has already edited this post more recently. + continue; + } + } + + $posts[] = $post; + $last_post = $post; + + if ( ! array_key_exists( $post->post_author, $user_post_revisions ) ) { + $user_post_revisions[ $post->post_author ] = array(); + } + $user_post_revisions[ $post->post_author ][] = $parent->ID; + } + + set_transient( 'ssl-alp-recent-revisions', $posts, SSL_ALP_RECENT_REVISIONS_CACHE_TIMEOUT ); } return $posts; @@ -1556,6 +1618,9 @@ public function mark_post_as_unread_for_users_after_update( $post_id, $post_afte // Set post as unread for all users except current user. $this->set_users_post_read_status( false, $post_after, wp_get_current_user() ); + + // Invalidate cached recent revisions. + delete_transient( 'ssl-alp-recent-revisions' ); } /** From 63dfc58ecfe2c146493726d9de38e1662e418962 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 5 Aug 2019 23:02:21 +0200 Subject: [PATCH 28/61] Set default sort order --- ssl-alp/includes/class-ssl-alp-inventory.php | 31 +++++++++----------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index cc7921d..07e2e05 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -40,10 +40,10 @@ public function register_hooks() { $loader->add_action( 'months_dropdown_results', $this, 'disable_months_dropdown_results', 10, 2 ); // Remove date column from admin post list. - $loader->add_filter( 'manage_edit-ssl_alp_inventory_columns', $this, 'remove_date_edit_column' ); + $loader->add_filter( 'manage_edit-ssl_alp_inventory_columns', $this, 'remove_date_edit_column' ); - // Sort inventory posts alphabetically by default. - $loader->add_filter( 'manage_edit-ssl_alp_inventory_sortable_columns', $this, 'remove_date_sort_edit_control' ); + // Set default inventory post list sort order to alphabetical by title. + $loader->add_action( 'pre_get_posts', $this, 'sort_posts_by_title' ); // Create/delete corresponding inventory item terms whenever posts are created/deleted. $loader->add_action( 'save_post', $this, 'associate_inventory_post_with_term', 10, 2 ); @@ -61,7 +61,6 @@ public function register_hooks() { // Add posts column to admin post list and make it sortable. $loader->add_filter( 'manage_edit-ssl_alp_inventory_columns', $this, 'add_posts_column_to_edit_table' ); - $loader->add_filter( 'manage_edit-ssl_alp_inventory_sortable_columns', $this, 'add_posts_column_to_edit_table' ); // Add posts to rows of the admin post list. $loader->add_action( 'manage_ssl_alp_inventory_posts_custom_column', $this, 'add_posts_row_data', 10, 2 ); @@ -252,23 +251,21 @@ public function remove_date_edit_column( $columns ) { } /** - * Remove date column and sort columns alphabetically by name on list of - * inventory posts in admin panel. + * Set default inventory post list sort order to alphabetical by title. * - * @param array $columns Sortable columns. - * @return array Columns with title column set as default sort. + * @param WP_Query $query The query. */ - public function remove_date_sort_edit_control( $columns ) { - if ( array_key_exists( 'date', $columns ) ) { - // Remove date column. - unset( $columns['date'] ); + public function sort_posts_by_title( $query ) { + if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory disabled. + return; } - // Make title the default sort. - $columns['title'] = array( $columns['title'], true ); - - return $columns; - } + if ( ! isset( $_GET['orderby'] ) ) { + $query->set( 'orderby', 'title' ); + $query->set( 'order', 'ASC' ); + } + } /** * Add or update inventory item taxonomy term using the specified inventory From ee97a7c97facbcea13716f99c5c970e0db3bbbc4 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 5 Aug 2019 23:02:30 +0200 Subject: [PATCH 29/61] Remove unnecessary sort --- ssl-alp/includes/class-ssl-alp-pages.php | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-pages.php b/ssl-alp/includes/class-ssl-alp-pages.php index 7bc9f28..bfa46ed 100644 --- a/ssl-alp/includes/class-ssl-alp-pages.php +++ b/ssl-alp/includes/class-ssl-alp-pages.php @@ -28,9 +28,6 @@ public function register_hooks() { // Remove date column from admin page list. $loader->add_filter( 'manage_edit-page_columns', $this, 'manage_edit_columns' ); - - // Sort pages alphabetically by default. - $loader->add_filter( 'manage_edit-page_sortable_columns', $this, 'manage_edit_sortable_columns' ); } /** @@ -72,22 +69,4 @@ public function manage_edit_columns( $columns ) { return $columns; } - - /** - * Remove date column and sort columns alphabetically by name on list of pages in admin panel. - * - * @param array $columns Sortable columns. - * @return array Columns with title column set as default sort. - */ - public function manage_edit_sortable_columns( $columns ) { - if ( array_key_exists( 'date', $columns ) ) { - // Remove date column. - unset( $columns['date'] ); - } - - // Make title the default sort. - $columns['title'] = array( $columns['title'], true ); - - return $columns; - } } From 6092678ab1193d99695ae932725f165317e31fd0 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 5 Aug 2019 23:04:40 +0200 Subject: [PATCH 30/61] Fix sort order --- ssl-alp/includes/class-ssl-alp-inventory.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index 07e2e05..fb4faa1 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -42,7 +42,7 @@ public function register_hooks() { // Remove date column from admin post list. $loader->add_filter( 'manage_edit-ssl_alp_inventory_columns', $this, 'remove_date_edit_column' ); - // Set default inventory post list sort order to alphabetical by title. + // Make the post title the default sort order. $loader->add_action( 'pre_get_posts', $this, 'sort_posts_by_title' ); // Create/delete corresponding inventory item terms whenever posts are created/deleted. @@ -251,7 +251,7 @@ public function remove_date_edit_column( $columns ) { } /** - * Set default inventory post list sort order to alphabetical by title. + * Sort inventory post list in admin panel by title by default. * * @param WP_Query $query The query. */ @@ -261,7 +261,13 @@ public function sort_posts_by_title( $query ) { return; } - if ( ! isset( $_GET['orderby'] ) ) { + if ( ! is_admin() ) { + return; + } + + $screen = get_current_screen(); + + if ( 'edit' === $screen->base && 'ssl_alp_inventory' === $screen->post_type && ! isset( $_GET['orderby'] ) ) { $query->set( 'orderby', 'title' ); $query->set( 'order', 'ASC' ); } From 0e543199860c05136e814bb9647d05f6e3ff9abb Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Tue, 6 Aug 2019 20:20:36 +0200 Subject: [PATCH 31/61] Fix notice on e.g. diff admin page --- ssl-alp/includes/class-ssl-alp-inventory.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index fb4faa1..3502c78 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -267,6 +267,10 @@ public function sort_posts_by_title( $query ) { $screen = get_current_screen(); + if ( is_null( $screen ) || ! property_exists( $screen, 'base' ) || ! property_exists( $screen, 'post_type' ) ) { + return; + } + if ( 'edit' === $screen->base && 'ssl_alp_inventory' === $screen->post_type && ! isset( $_GET['orderby'] ) ) { $query->set( 'orderby', 'title' ); $query->set( 'order', 'ASC' ); From 3d498d80fb6e7c576d334bbe4bbc016a58e22e14 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Tue, 6 Aug 2019 21:39:54 +0200 Subject: [PATCH 32/61] Add support for inventory to theme --- themes/labbook/functions.php | 26 +- themes/labbook/inc/template-tags.php | 251 ++++++++++++++++-- themes/labbook/readme.txt | 4 +- themes/labbook/single-ssl_alp_inventory.php | 43 +++ themes/labbook/style.css | 46 +++- .../template-parts/content-inventory.php | 45 ++++ .../labbook/template-parts/content-none.php | 8 +- .../labbook/template-parts/content-page.php | 18 +- .../labbook/template-parts/content-search.php | 14 +- .../labbook/template-parts/content-single.php | 14 +- themes/labbook/template-parts/content.php | 18 +- 11 files changed, 429 insertions(+), 58 deletions(-) create mode 100644 themes/labbook/single-ssl_alp_inventory.php create mode 100644 themes/labbook/template-parts/content-inventory.php diff --git a/themes/labbook/functions.php b/themes/labbook/functions.php index 0a82814..67d09ed 100644 --- a/themes/labbook/functions.php +++ b/themes/labbook/functions.php @@ -163,6 +163,13 @@ function labbook_setup() { */ add_theme_support( 'ssl-alp-cross-references' ); + /** + * Add support for showing featured images on inventory items. + */ + if ( labbook_ssl_alp_inventory_enabled() ) { + add_theme_support( 'post-thumbnails', array( 'ssl_alp_inventory' ) ); + } + // Get default theme options. $labbook_default_options = labbook_get_theme_option_defaults(); } @@ -209,7 +216,7 @@ function labbook_widgets_init() { function labbook_scripts() { wp_enqueue_style( 'fontawesome', - get_template_directory_uri() . '/vendor/font-awesome/css/font-awesome.css', + get_template_directory_uri() . '/vendor/font-awesome/css/font-awesome.min.css', array(), LABBOOK_VERSION ); @@ -429,6 +436,23 @@ function labbook_ssl_alp_unread_flags_enabled() { return true; } +/** + * Check if inventory capabilities provided by the ALP plugin are available and enabled. + */ +function labbook_ssl_alp_inventory_enabled() { + global $ssl_alp; + + if ( ! labbook_ssl_alp_active() ) { + // Plugin is disabled. + return false; + } elseif ( ! get_option( 'ssl_alp_enable_inventory' ) ) { + // Inventory is disabled. + return false; + } + + return true; +} + /** * Page table of contents generator. */ diff --git a/themes/labbook/inc/template-tags.php b/themes/labbook/inc/template-tags.php index 665a65f..eba7961 100644 --- a/themes/labbook/inc/template-tags.php +++ b/themes/labbook/inc/template-tags.php @@ -230,16 +230,14 @@ function labbook_the_post_meta( $post = null ) { echo '  '; } - if ( 'page' === $post->post_type ) { - $permission = 'edit_page'; - } else { - $permission = 'edit_post'; - } + $post_type_obj = get_post_type_object( $post->post_type ); - if ( current_user_can( $permission, $post ) ) { - // Print edit post link. - labbook_the_post_edit_link( $post ); - echo '  '; + if ( ! is_null( $post_type_obj ) ) { + if ( current_user_can( $post_type_obj->cap->edit_post, $post ) ) { + // Print edit post link. + labbook_the_post_edit_link( $post ); + echo '  '; + } } echo ''; @@ -320,7 +318,7 @@ function labbook_the_post_edit_link( $post = null ) { function labbook_the_revisions_link( $post = null ) { global $ssl_alp; - if ( ! labbook_ssl_alp_edit_summaries_enabled() ) { + if ( ! labbook_get_option( 'show_edit_summaries' ) || ! labbook_ssl_alp_edit_summaries_enabled() ) { return; } @@ -479,11 +477,13 @@ function labbook_format_author( $author, $url = true ) { * handle it. It always uses the current post. */ function labbook_the_footer() { + $post = get_post(); + /* translators: used between list items, there is a space after the comma. */ $categories_list = get_the_category_list( __( ', ', 'labbook' ) ); - // Allowed category and tag HTML. - $cat_tag_tags = array( + // Allowed term HTML. + $term_tags = array( 'a' => array( 'href' => array(), 'rel' => array(), @@ -492,8 +492,9 @@ function labbook_the_footer() { if ( $categories_list ) { printf( - '%1$s', - wp_kses( $categories_list, $cat_tag_tags ) + '%2$s', + esc_attr__( 'Categories', 'labbook' ), + wp_kses( $categories_list, $term_tags ) ); echo '  '; } @@ -503,14 +504,29 @@ function labbook_the_footer() { if ( $tags_list ) { printf( - '%1$s', - wp_kses( $tags_list, $cat_tag_tags ) + '%2$s', + esc_attr__( 'Tags', 'labbook' ), + wp_kses( $tags_list, $term_tags ) ); echo '  '; } + if ( labbook_ssl_alp_inventory_enabled() ) { + /* translators: used between list items, there is a space after the comma. */ + $inventory_list = get_the_term_list( $post->ID, 'ssl_alp_inventory_item', '', __( ', ', 'labbook' ) ); + + if ( $inventory_list ) { + printf( + '%2$s', + esc_attr__( 'Inventory items', 'labbook' ), + wp_kses( $inventory_list, $term_tags ) + ); + echo '  '; + } + } + if ( ! is_single() && ! post_password_required() && ( comments_open() || get_comments_number() ) ) { - // Show comments link. + // Show commentss link. printf( '%2$s', esc_url( get_comments_link() ), @@ -526,17 +542,21 @@ function labbook_the_footer() { * Print revisions for the specified post. * * @param int|WP_Post|null $post Post ID or post object. Defaults to global $post. + * + * @global $ssl_alp */ function labbook_the_revisions( $post = null ) { - if ( ! labbook_get_option( 'show_edit_summaries' ) ) { + global $ssl_alp; + + if ( ! labbook_get_option( 'show_edit_summaries' ) || ! labbook_ssl_alp_edit_summaries_enabled() ) { // Display is unavailable. return; } $post = get_post( $post ); - if ( ! post_type_supports( $post->post_type, 'revisions' ) ) { - // Post type not supported. + // Check if edit summaries are available for this post. + if ( ! $ssl_alp->revisions->edit_summary_allowed( $post, false ) ) { return; } @@ -824,6 +844,8 @@ function labbook_get_revision_abbreviation( $revision, $url = true ) { * Print post references. * * @param int|WP_Post|null $post Post ID or post object. Defaults to global $post. + * + * @global $ssl_alp */ function labbook_the_references( $post = null ) { global $ssl_alp; @@ -929,6 +951,22 @@ function labbook_referenced_post_list_item( $referenced_post = null ) { ); } + // Post type (only for non-posts). + if ( 'post' !== $referenced_post->post_type ) { + $post_type = get_post_type_object( $referenced_post->post_type ); + $post_type_label = sprintf( + /* translators: 1: referenced post type label */ + __( '(%1$s)', 'labbook' ), + $post_type->labels->singular_name + ); + + echo ' '; + printf( + '%1$s', + esc_html( $post_type_label ) + ); + } + echo ''; } } // End if(). @@ -940,6 +978,8 @@ function labbook_referenced_post_list_item( $referenced_post = null ) { * @param int|WP_Post|null $page Post ID or post object. Defaults to global $post. */ function labbook_the_page_breadcrumbs( $page = null ) { + $page = get_post( $page ); + if ( ! is_page( $page ) ) { // Not a page. return; @@ -956,6 +996,53 @@ function labbook_the_page_breadcrumbs( $page = null ) { return; } + labbook_the_breadcrumb_trail( $breadcrumbs ); + } +endif; + +if ( ! function_exists( 'labbook_the_inventory_breadcrumbs' ) ) : + /** + * Print inventory breadcrumbs. + * + * @param int|WP_Post|null $post Post ID or post object. Defaults to global $post. + */ + function labbook_the_inventory_breadcrumbs( $post = null ) { + $post = get_post( $post ); + + if ( is_null( $post ) ) { + return; + } + + if ( 'ssl_alp_inventory' !== $post->post_type ) { + return; + } + + if ( ! labbook_get_option( 'show_page_breadcrumbs' ) ) { + // Display is unavailable. + return; + } + + $breadcrumbs = array( + array( + 'title' => __( 'Home', 'labbook' ), + 'url' => home_url(), + ), + array( + 'title' => __( 'Inventory', 'labbook' ), + ) + ); + + labbook_the_breadcrumb_trail( $breadcrumbs ); + } +endif; + +if ( ! function_exists( 'labbook_the_breadcrumb_trail' ) ) : + /** + * Print breadcrumb trail. + * + * @param array $breadcrumbs The breadcrumb trail. + */ + function labbook_the_breadcrumb_trail( $breadcrumbs ) { echo ' -

deletes the default WordPress roles from the database, meaning that these roles will remain even if the Academic Labbook Plugin is disabled or uninstalled in the future. For more information on roles, please see Roles and Capabilities in the WordPress Codex.', 'ssl-alp' ), 'https://codex.wordpress.org/Roles_and_Capabilities' ) ); ?>

+

+ deletes the default WordPress roles from the database, meaning that these roles will remain even if the Academic Labbook Plugin is disabled or uninstalled in the future. For more information on roles, please see Roles and Capabilities in the WordPress Codex.', 'ssl-alp' ), + 'https://codex.wordpress.org/Roles_and_Capabilities' + ) + ); + ?> +

@@ -159,7 +223,17 @@

-

run this tool via WP-CLI.', 'ssl-alp' ), 'https://alp.attackllama.com/documentation/rebuilding-cross-references/' ) ); ?>

+

+ run this tool via WP-CLI.', 'ssl-alp' ), + 'https://alp.attackllama.com/documentation/rebuilding-cross-references/' + ) + ); + ?> +

@@ -168,7 +242,17 @@

-

this settings page.', 'ssl-alp' ), 'options-general.php?page=ssl-alp-site-options' ) ); ?>

+

+ this settings page.', 'ssl-alp' ), + 'options-general.php?page=ssl-alp-site-options' + ) + ); + ?> +

@@ -177,12 +261,22 @@

- disabled/> + disabled/>

-

this settings page.', 'ssl-alp' ), 'options-general.php?page=ssl-alp-site-options' ) ); ?>

+

+ this settings page.', 'ssl-alp' ), + 'options-general.php?page=ssl-alp-site-options' + ) + ); + ?> +

diff --git a/ssl-alp/partials/admin/users/applications/display.php b/ssl-alp/partials/admin/users/applications/display.php index 4c4c0bf..dc68ada 100644 --- a/ssl-alp/partials/admin/users/applications/display.php +++ b/ssl-alp/partials/admin/users/applications/display.php @@ -6,7 +6,7 @@ ?>
-

+

From e18077bee2aad147af91a613bb0479be6436d500 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 11 Aug 2019 15:53:11 +0200 Subject: [PATCH 49/61] Fix pagination of unread posts (and remove ability to view others') --- ssl-alp/includes/class-ssl-alp-revisions.php | 23 +++++--------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-revisions.php b/ssl-alp/includes/class-ssl-alp-revisions.php index 22b5e49..62aef29 100644 --- a/ssl-alp/includes/class-ssl-alp-revisions.php +++ b/ssl-alp/includes/class-ssl-alp-revisions.php @@ -1164,8 +1164,8 @@ public function remove_adjacent_links_action() { */ public static function add_unread_post_rewrite_rules() { add_rewrite_rule( - '^unread/?(.*)/?$', - 'index.php?unread=' . self::$unread_flag_term_slug_prefix . '$matches[1]', + '^unread\/?(?:page\/(\d+))?\/?$', + 'index.php?unread=ssl_alp_unread_flag&paged=$matches[1]', 'top' // Required to avoid page matching rule. ); } @@ -1222,23 +1222,12 @@ public function set_unread_posts_archive_page_user() { // Cannot show useful unread posts page. $wp_query->set_404(); } else { - if ( get_query_var( 'unread' ) === self::$unread_flag_term_slug_prefix ) { - // No unread term is set (it defaults to the slug prefix) - use current user's slug. + if ( 'ssl_alp_unread_flag' === get_query_var( 'unread' ) ) { + // The request is for unread flags. + // Set the unread flag queryvar to the user's unread term slug. set_query_var( 'unread', $this->get_unread_flag_term_slug() ); } else { - // An unread archive slug is set, but does the user have permission to view it? - $term = get_term_by( 'slug', get_query_var( 'unread' ), 'ssl_alp_unread_flag' ); - - if ( $term ) { - $user = $this->get_user_from_unread_flag_term( $term ); - - if ( ! $this->check_unread_flag_permission( $user ) ) { - // User cannot view this page. - $wp_query->set_404(); - } - } else { - $wp_query->set_404(); - } + $wp_query->set_404(); } } } From d932eb7091ab1f363e6fc40284445d995d95e20b Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 11 Aug 2019 16:18:38 +0200 Subject: [PATCH 50/61] Rename "ssl_alp_inventory" post type to "ssl-alp-inventory" --- ssl-alp/includes/class-ssl-alp-inventory.php | 24 +++++++++---------- ssl-alp/includes/class-ssl-alp-references.php | 2 +- .../includes/class-ssl-alp-uninstaller.php | 7 +++--- ssl-alp/tests/unit/test-inventory.php | 12 +++++----- themes/labbook/functions.php | 2 +- themes/labbook/inc/template-tags.php | 4 ++-- themes/labbook/index.php | 2 +- ...ntory.php => single-ssl-alp-inventory.php} | 0 themes/labbook/style.css | 2 +- 9 files changed, 28 insertions(+), 27 deletions(-) rename themes/labbook/{single-ssl_alp_inventory.php => single-ssl-alp-inventory.php} (100%) diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index c52b557..f5927cf 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -40,7 +40,7 @@ public function register_hooks() { $loader->add_action( 'months_dropdown_results', $this, 'disable_months_dropdown_results', 10, 2 ); // Remove date column from admin post list. - $loader->add_filter( 'manage_edit-ssl_alp_inventory_columns', $this, 'remove_date_edit_column' ); + $loader->add_filter( 'manage_edit-ssl-alp-inventory_columns', $this, 'remove_date_edit_column' ); // Make the post title the default sort order. $loader->add_action( 'pre_get_posts', $this, 'sort_posts_by_title' ); @@ -60,10 +60,10 @@ public function register_hooks() { $loader->add_action( 'init', $this, 'register_taxonomy' ); // Add posts column to admin post list and make it sortable. - $loader->add_filter( 'manage_edit-ssl_alp_inventory_columns', $this, 'add_posts_column_to_edit_table' ); + $loader->add_filter( 'manage_edit-ssl-alp-inventory_columns', $this, 'add_posts_column_to_edit_table' ); // Add posts to rows of the admin post list. - $loader->add_action( 'manage_ssl_alp_inventory_posts_custom_column', $this, 'add_posts_row_data', 10, 2 ); + $loader->add_action( 'manage_ssl-alp-inventory_posts_custom_column', $this, 'add_posts_row_data', 10, 2 ); // Override default term links to point towards the term custom post instead of term // archive. @@ -114,7 +114,7 @@ public function register_settings_fields() { * Post multiple author settings field. */ add_settings_field( - 'ssl_alp_inventory_settings', + 'ssl-alp-inventory_settings', __( 'Inventory', 'ssl-alp' ), array( $this, 'inventory_settings_callback' ), SSL_ALP_SITE_SETTINGS_PAGE, @@ -216,7 +216,7 @@ public function register_post_type() { ), ); - register_post_type( 'ssl_alp_inventory', $args ); + register_post_type( 'ssl-alp-inventory', $args ); } /** @@ -227,7 +227,7 @@ public function register_post_type() { * @return array Empty array if post type is page, otherwise $months. */ public function disable_months_dropdown_results( $months, $post_type ) { - if ( 'ssl_alp_inventory' === $post_type ) { + if ( 'ssl-alp-inventory' === $post_type ) { // Return empty array to force it to hide (see months_dropdown() in class-wp-list-table.php). return array(); } @@ -273,7 +273,7 @@ public function sort_posts_by_title( $query ) { return; } - if ( 'edit' === $screen->base && 'ssl_alp_inventory' === $screen->post_type && ! isset( $_GET['orderby'] ) ) { + if ( 'edit' === $screen->base && 'ssl-alp-inventory' === $screen->post_type && ! isset( $_GET['orderby'] ) ) { $query->set( 'orderby', 'title' ); $query->set( 'order', 'ASC' ); } @@ -363,7 +363,7 @@ private function get_post_from_inventory_term( $term ) { } /** - * Associate a post in the ssl_alp_inventory custom post type with a corresponding + * Associate a post in the ssl-alp-inventory custom post type with a corresponding * ssl_alp_inventory_item term when created or saved. * * @param int $post_id The post ID. @@ -375,7 +375,7 @@ public function associate_inventory_post_with_term( $post_id, $post ) { return; } - if ( 'ssl_alp_inventory' !== $post->post_type ) { + if ( 'ssl-alp-inventory' !== $post->post_type ) { return; } @@ -411,7 +411,7 @@ public function delete_associated_inventory_post_term( $post_id ) { return; } - if ( 'ssl_alp_inventory' !== $post->post_type ) { + if ( 'ssl-alp-inventory' !== $post->post_type ) { return; } @@ -435,7 +435,7 @@ public function add_revisions_page() { global $ssl_alp; $hook_suffix = add_submenu_page( - 'edit.php?post_type=ssl_alp_inventory', + 'edit.php?post_type=ssl-alp-inventory', __( 'Revisions', 'ssl-alp' ), __( 'Revisions', 'ssl-alp' ), 'read', @@ -457,7 +457,7 @@ public function add_revisions_page() { public function load_revisions_page_screen_options() { global $ssl_alp; - return $ssl_alp->revisions->load_revisions_page_screen_options( 'ssl_alp_inventory', SSL_ALP_INVENTORY_REVISIONS_MENU_SLUG ); + return $ssl_alp->revisions->load_revisions_page_screen_options( 'ssl-alp-inventory', SSL_ALP_INVENTORY_REVISIONS_MENU_SLUG ); } /** diff --git a/ssl-alp/includes/class-ssl-alp-references.php b/ssl-alp/includes/class-ssl-alp-references.php index df2557b..28c48fd 100644 --- a/ssl-alp/includes/class-ssl-alp-references.php +++ b/ssl-alp/includes/class-ssl-alp-references.php @@ -23,7 +23,7 @@ class SSL_ALP_References extends SSL_ALP_Module { protected $supported_reference_post_types = array( 'post' => true, 'page' => false, - 'ssl_alp_inventory' => false, + 'ssl-alp-inventory' => false, ); /** diff --git a/ssl-alp/includes/class-ssl-alp-uninstaller.php b/ssl-alp/includes/class-ssl-alp-uninstaller.php index 93957fe..164b2de 100644 --- a/ssl-alp/includes/class-ssl-alp-uninstaller.php +++ b/ssl-alp/includes/class-ssl-alp-uninstaller.php @@ -271,9 +271,10 @@ private static function delete_user_metas() { self::delete_user_meta( 'ssl_alp_applications_per_page' ); // Screen column settings. - self::delete_user_meta( 'manageposts_page_ssl-alp-admin-revisionscolumnshidden' ); + self::delete_user_meta( 'manageposts_page_ssl-alp-admin-post-revisionscolumnshidden' ); + self::delete_user_meta( 'managepages_page_ssl-alp-admin-page-revisionscolumnshidden' ); + self::delete_user_meta( 'managessl-alp-inventory_page_ssl-alp-admin-inventory-revisionscolumnshidden' ); self::delete_user_meta( 'manageusers_page_ssl-alp-admin-applicationscolumnshidden' ); - self::delete_user_meta( 'managessl_alp_inventory_page_ssl-alp-admin-inventory-revisionscolumnshidden' ); } /** @@ -302,7 +303,7 @@ private static function delete_user_meta( $meta_key ) { */ private static function delete_custom_post_types() { // Change inventory posts to pages. - self::delete_custom_post_type_posts( 'ssl_alp_inventory', 'page' ); + self::delete_custom_post_type_posts( 'ssl-alp-inventory', 'page' ); } /** diff --git a/ssl-alp/tests/unit/test-inventory.php b/ssl-alp/tests/unit/test-inventory.php index d22bf67..dd98f85 100644 --- a/ssl-alp/tests/unit/test-inventory.php +++ b/ssl-alp/tests/unit/test-inventory.php @@ -49,11 +49,11 @@ public function test_creating_inventory_post_creates_corresponding_term() { $post = $this->factory->post->create_and_get( array( - 'post_type' => 'ssl_alp_inventory', + 'post_type' => 'ssl-alp-inventory', ) ); - $this->assertEquals( $post->post_type, 'ssl_alp_inventory' ); + $this->assertEquals( $post->post_type, 'ssl-alp-inventory' ); // A corresponding term should have been created. $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); $this->assertNotFalse( $term ); @@ -65,11 +65,11 @@ public function test_deleting_inventory_post_deletes_corresponding_term() { $post = $this->factory->post->create_and_get( array( - 'post_type' => 'ssl_alp_inventory', + 'post_type' => 'ssl-alp-inventory', ) ); - $this->assertEquals( $post->post_type, 'ssl_alp_inventory' ); + $this->assertEquals( $post->post_type, 'ssl-alp-inventory' ); $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); $this->assertNotFalse( $term ); $this->assertEquals( $term->slug, $post->ID ); @@ -87,11 +87,11 @@ public function test_trashing_inventory_post_does_not_delete_corresponding_term( $post = $this->factory->post->create_and_get( array( - 'post_type' => 'ssl_alp_inventory', + 'post_type' => 'ssl-alp-inventory', ) ); - $this->assertEquals( $post->post_type, 'ssl_alp_inventory' ); + $this->assertEquals( $post->post_type, 'ssl-alp-inventory' ); $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); $this->assertNotFalse( $term ); $this->assertEquals( $term->slug, $post->ID ); diff --git a/themes/labbook/functions.php b/themes/labbook/functions.php index 470b1b3..9e152aa 100644 --- a/themes/labbook/functions.php +++ b/themes/labbook/functions.php @@ -167,7 +167,7 @@ function labbook_setup() { * Add support for showing featured images on inventory items. */ if ( labbook_ssl_alp_inventory_enabled() ) { - add_theme_support( 'post-thumbnails', array( 'ssl_alp_inventory' ) ); + add_theme_support( 'post-thumbnails', array( 'ssl-alp-inventory' ) ); } // Get default theme options. diff --git a/themes/labbook/inc/template-tags.php b/themes/labbook/inc/template-tags.php index ec44c56..84d4296 100644 --- a/themes/labbook/inc/template-tags.php +++ b/themes/labbook/inc/template-tags.php @@ -1013,7 +1013,7 @@ function labbook_the_inventory_breadcrumbs( $post = null ) { return; } - if ( 'ssl_alp_inventory' !== $post->post_type ) { + if ( 'ssl-alp-inventory' !== $post->post_type ) { return; } @@ -1080,7 +1080,7 @@ function labbook_the_inventory_item_posts_link() { $post = get_post(); - if ( 'ssl_alp_inventory' !== $post->post_type ) { + if ( 'ssl-alp-inventory' !== $post->post_type ) { return; } diff --git a/themes/labbook/index.php b/themes/labbook/index.php index d32990a..25d01d8 100644 --- a/themes/labbook/index.php +++ b/themes/labbook/index.php @@ -42,7 +42,7 @@ endwhile; - the_post_navigation( + the_posts_navigation( array( 'next_text' => __( 'Newer posts', 'labbook' ) . ' ', 'prev_text' => ' ' . __( 'Older posts', 'labbook' ), diff --git a/themes/labbook/single-ssl_alp_inventory.php b/themes/labbook/single-ssl-alp-inventory.php similarity index 100% rename from themes/labbook/single-ssl_alp_inventory.php rename to themes/labbook/single-ssl-alp-inventory.php diff --git a/themes/labbook/style.css b/themes/labbook/style.css index 57e6701..7c8917a 100644 --- a/themes/labbook/style.css +++ b/themes/labbook/style.css @@ -1196,7 +1196,7 @@ a:hover, a:active { .post, .page, -.ssl_alp_inventory { +.ssl-alp-inventory { margin: 0 0 1.5em 0; } From dd90becc88f8d8eb5f972a4d3d40a0bee4eaee8b Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 11 Aug 2019 19:35:23 +0200 Subject: [PATCH 51/61] Simplify coauthor and inventory term permissions checks --- ssl-alp/includes/class-ssl-alp-coauthors.php | 70 +++-------------- ssl-alp/includes/class-ssl-alp-inventory.php | 80 ++------------------ 2 files changed, 19 insertions(+), 131 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-coauthors.php b/ssl-alp/includes/class-ssl-alp-coauthors.php index 7618552..293dca9 100644 --- a/ssl-alp/includes/class-ssl-alp-coauthors.php +++ b/ssl-alp/includes/class-ssl-alp-coauthors.php @@ -104,12 +104,9 @@ public function register_hooks() { // Delete or reassign user terms from posts when a user is deleted on a network site installation. $loader->add_action( 'remove_user_from_blog', $this, 'remove_user_from_blog', 10, 3 ); - // Filter to allow coauthors to edit posts and stop users deleting coauthor terms. + // Filter to allow coauthors to edit posts. $loader->add_filter( 'user_has_cap', $this, 'filter_user_has_cap', 10, 4 ); - // Stop super admins deleting coauthor terms. - $loader->add_filter( 'map_meta_cap', $this, 'filter_capabilities', 10, 4 ); - /** * Display hooks. */ @@ -211,14 +208,20 @@ public function register_taxonomy() { 'query_var' => false, 'rewrite' => false, 'public' => false, - 'sort' => true, // Remember order terms are added to posts. + 'sort' => true, // Remember order terms are added to posts. 'args' => array( // Default arguments used by `wp_get_object_terms`, see https://core.trac.wordpress.org/ticket/40496. 'orderby' => 'term_order', ), - 'show_ui' => true, // Show selector on edit page. - 'show_in_menu' => false, // Disable term edit page. - 'show_in_rest' => true, // Needed for block editor support. + 'capabilities' => array( + 'manage_terms' => 'do_not_allow', + 'edit_terms' => 'do_not_allow', + 'delete_terms' => 'do_not_allow', + 'assign_terms' => 'edit_posts', // Needed to allow assignment in block editor. + ), + 'show_ui' => true, // Show selector on edit page. + 'show_in_menu' => false, // Hide term edit page. + 'show_in_rest' => true, // Needed for block editor support. 'show_admin_column' => true, // Show associated terms in admin edit screen. 'update_count_callback' => array( $this, 'update_users_posts_count' ), // Override count. ); @@ -584,8 +587,7 @@ public function filter_manage_users_custom_column( $column_value, $column_name, } /** - * Allows coauthors to edit the post they're coauthors of, and stop - * users deleting coauthor terms. + * Allows coauthors to edit the post they're coauthors of. * * @param array $all_capabilities All user capabilities. * @param mixed $unused Unused. @@ -600,14 +602,6 @@ public function filter_user_has_cap( $all_capabilities, $unused, $args, $user ) $requested_capability = $args[0]; - if ( in_array( $requested_capability, array( 'edit_term', 'delete_term' ), true ) ) { - // Disallow in all circumstances. - $all_capabilities['edit_term'] = false; - $all_capabilities['delete_term'] = false; - - return $all_capabilities; - } - // Assume post. $post = get_post( isset( $args[2] ) ? $args[2] : 0 ); @@ -654,46 +648,6 @@ public function filter_user_has_cap( $all_capabilities, $unused, $args, $user ) return $all_capabilities; } - /** - * Filter capabilities of super admins to stop them editing or deleting coauthor terms. - * - * Coauthor terms are essential to the correct operation of the coauthors system. - * - * @param array $caps All capabilities. - * @param string $cap Capability being checked. - * @param int $user_id User ID. - * @param array $args Capability arguments. - */ - public function filter_capabilities( $caps, $cap, $user_id, $args ) { - // Construct list of capabilities based on post type. - $filtered_caps = array( - // Terms. - 'edit_term', - 'delete_term', - ); - - if ( ! in_array( $cap, $filtered_caps, true ) ) { - // this is not a capability we need to filter. - return $caps; - } - - // Get term. - $term = get_term( $args[0] ); - - if ( is_null( $term ) ) { - return $caps; - } - - $taxonomy = get_taxonomy( $term->taxonomy ); - - if ( 'ssl_alp_coauthor' === $taxonomy->name ) { - // Disallow. - $caps[] = 'do_not_allow'; - } - - return $caps; - } - /** * Filter the views listed on the admin post list to add a "Mine" view. * diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index f5927cf..eb12093 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -85,12 +85,6 @@ public function register_hooks() { // Support inventory item querystrings in WP_Query. $loader->add_action( 'parse_tax_query', $this, 'parse_query_vars' ); - - // Filter to stop users from editing or deleting inventory terms directly. - $loader->add_filter( 'user_has_cap', $this, 'filter_user_has_cap', 10, 4 ); - - // Stop super admins deleting inventory terms. - $loader->add_filter( 'map_meta_cap', $this, 'filter_capabilities', 10, 4 ); } /** @@ -488,8 +482,14 @@ public function register_taxonomy() { 'not_found' => __( 'No items found.', 'ssl-alp' ), 'no_terms' => __( 'No items', 'ssl-alp' ), ), + 'capabilities' => array( + 'manage_terms' => 'do_not_allow', + 'edit_terms' => 'do_not_allow', + 'delete_terms' => 'do_not_allow', + 'assign_terms' => 'edit_posts', // Needed to allow assignment in block editor. + ), 'public' => true, - 'show_in_menu' => false, // Disable term edit page. + 'show_in_menu' => false, // Hide term edit page. 'show_in_rest' => true, // Needed for block editor support. 'show_admin_column' => true, // Show associated terms in admin edit screen. 'rewrite' => array( @@ -794,70 +794,4 @@ public function parse_query_vars( $query ) { // Merge new taxonomy filters into existing ones. $query->tax_query->queries = wp_parse_args( $tax_query, $query->tax_query->queries ); } - - /** - * Stop users editing or deleting inventory terms. - * - * @param array $all_capabilities All user capabilities. - * @param mixed $unused Unused. - * @param array $args Capability arguments. - * @param WP_User $user User object. - */ - public function filter_user_has_cap( $all_capabilities, $unused, $args, $user ) { - if ( ! get_option( 'ssl_alp_enable_inventory' ) ) { - // Inventory disabled. - return $all_capabilities; - } - - $requested_capability = $args[0]; - - if ( in_array( $requested_capability, array( 'edit_term', 'delete_term' ), true ) ) { - // Disallow in all circumstances. - $all_capabilities['edit_term'] = false; - $all_capabilities['delete_term'] = false; - } - - return $all_capabilities; - } - - /** - * Filter capabilities of super admins to stop them editing or deleting inventory terms. - * - * Inventory terms are essential to the correct operation of the inventory system and are - * managed only by the inventory custom post type. - * - * @param array $caps All capabilities. - * @param string $cap Capability being checked. - * @param int $user_id User ID. - * @param array $args Capability arguments. - */ - public function filter_capabilities( $caps, $cap, $user_id, $args ) { - // Construct list of capabilities based on post type. - $filtered_caps = array( - // Terms. - 'edit_term', - 'delete_term', - ); - - if ( ! in_array( $cap, $filtered_caps, true ) ) { - // this is not a capability we need to filter. - return $caps; - } - - // Get term. - $term = get_term( $args[0] ); - - if ( is_null( $term ) ) { - return $caps; - } - - $taxonomy = get_taxonomy( $term->taxonomy ); - - if ( 'ssl_alp_inventory_item' === $taxonomy->name ) { - // Disallow. - $caps[] = 'do_not_allow'; - } - - return $caps; - } } From 2f97c0a76bd7641539694a3c686b9a2e3eb59dcb Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 11 Aug 2019 19:35:35 +0200 Subject: [PATCH 52/61] Fix permission check bug --- ssl-alp/includes/class-ssl-alp-terms.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-terms.php b/ssl-alp/includes/class-ssl-alp-terms.php index 07385db..1b5b9eb 100644 --- a/ssl-alp/includes/class-ssl-alp-terms.php +++ b/ssl-alp/includes/class-ssl-alp-terms.php @@ -74,7 +74,7 @@ public function register_hooks() { * Check if the current user can manage terms. */ private function user_can_manage_terms() { - if ( in_array( 'taxonomy', $_REQUEST, true ) ) { + if ( array_key_exists( 'taxonomy', $_REQUEST ) ) { $taxonomy = $_REQUEST['taxonomy']; } else { $taxonomy = 'post_tag'; @@ -82,7 +82,7 @@ private function user_can_manage_terms() { $taxonomy = get_taxonomy( $taxonomy ); - if ( ! $taxonomy ) { + if ( ! $taxonomy || is_wp_error( $taxonomy ) ) { return false; } From e4448fb497d0c14d168e3a84c88055b47185c24b Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Sun, 11 Aug 2019 19:38:56 +0200 Subject: [PATCH 53/61] Update README --- README.md | 9 ++++----- ssl-alp/README.txt | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1c60675..76a6653 100644 --- a/README.md +++ b/README.md @@ -167,11 +167,10 @@ outdated browsers, and this project is not concerned about losing sales from use ## Design principles - **Clean code**: there's an awful lot of terribly written code in the WordPress ecosystem. This plugin attempts to conform to coding standards, and to interfere minimally with the default - WordPress behaviour where possible. For some of the more major features, like coauthors, - some quiet major modifications are required to core behaviour, which means that ALP may not be - compatible with certain other plugins. - - **Modular**: most/all features can be enabled or disabled, and work independently from each - other. + WordPress behaviour where possible. + - **Modular**: most features can be enabled or disabled via the settings page, and work + independently from each other. The plugin can also be used without the corresponding theme, + though this hides a lot of the useful parts of the plugin from users. ## Future development plans The basic behaviour of ALP is already in place, but the plan is to keep adding useful features diff --git a/ssl-alp/README.txt b/ssl-alp/README.txt index 0184d89..59186b2 100644 --- a/ssl-alp/README.txt +++ b/ssl-alp/README.txt @@ -15,7 +15,7 @@ more. == Description == Please also visit [our website](https://alp.attackllama.com/)! -Academic Labbook Plugin (ALP) provides a lightweight but powerful set of tools +Academic Labbook Plugin (ALP) provides a powerful set of tools on top of core WordPress to allow researchers to write about their work, leveraging the powerful WordPress platform. With ALP, you can benefit from WordPress's post compositition, tagging and categorisation, media management and From 627e3e7272c4b87fbb324ab815e6881a3018946b Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 12 Aug 2019 20:40:08 +0200 Subject: [PATCH 54/61] Expand tools documentation --- ssl-alp/partials/admin/tools/display.php | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/ssl-alp/partials/admin/tools/display.php b/ssl-alp/partials/admin/tools/display.php index 180c5e6..a55ad7e 100644 --- a/ssl-alp/partials/admin/tools/display.php +++ b/ssl-alp/partials/admin/tools/display.php @@ -31,6 +31,17 @@

+

+ highly recommended to take a backup of your database before running these commands, as some require long execution times and so may time out or run out of memory without properly finishing. You can also run some of these commands via WP-CLI to avoid these issues - see the notes under the relevant tools for more details.', 'ssl-alp' ), + 'https://wp-cli.org/' + ) + ); + ?> +

run this tool via WP-CLI.', 'ssl-alp' ), + __( 'Note: this tool may take a long time to execute on large sites. Due to server configuration settings, the execution may time out or run out of memory. You may instead wish to run this tool via WP-CLI.', 'ssl-alp' ), 'https://alp.attackllama.com/documentation/rebuilding-cross-references/' ) ); @@ -258,6 +269,17 @@

+

+ run this tool via WP-CLI.', 'ssl-alp' ), + 'https://alp.attackllama.com/documentation/rebuilding-coauthors/' + ) + ); + ?> +

From 7dec32d247a2d217f980439d2ab1b49aa180b024 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 12 Aug 2019 21:05:47 +0200 Subject: [PATCH 55/61] Change ssl_alp_inventory_item to ssl-alp-inventory-item --- ssl-alp/includes/class-ssl-alp-inventory.php | 38 +++++++++---------- .../includes/class-ssl-alp-uninstaller.php | 2 +- ssl-alp/tests/unit/test-inventory.php | 14 +++---- themes/labbook/inc/template-tags.php | 4 +- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index eb12093..6d48358 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -291,7 +291,7 @@ private function update_inventory_item_term( $post ) { $term = $this->get_inventory_term( $post ); // Temporarily disable the filter that blocks creation of terms in the - // ssl_alp_inventory_item taxonomy. + // ssl-alp-inventory-item taxonomy. $this->disable_disallow_insert_term_filter(); if ( ! $term ) { @@ -300,7 +300,7 @@ private function update_inventory_item_term( $post ) { 'slug' => $this->get_inventory_term_slug( $post ), ); - wp_insert_term( $post->post_title, 'ssl_alp_inventory_item', $args ); + wp_insert_term( $post->post_title, 'ssl-alp-inventory-item', $args ); } else { // Update term. $args = array( @@ -308,7 +308,7 @@ private function update_inventory_item_term( $post ) { 'slug' => $this->get_inventory_term_slug( $post ), ); - wp_update_term( $term->term_id, 'ssl_alp_inventory_item', $args ); + wp_update_term( $term->term_id, 'ssl-alp-inventory-item', $args ); } // Re-enable the filter. @@ -324,7 +324,7 @@ public function get_inventory_term( $post ) { } $slug = $this->get_inventory_term_slug( $post ); - return get_term_by( 'slug', $slug, 'ssl_alp_inventory_item' ); + return get_term_by( 'slug', $slug, 'ssl-alp-inventory-item' ); } /** @@ -358,7 +358,7 @@ private function get_post_from_inventory_term( $term ) { /** * Associate a post in the ssl-alp-inventory custom post type with a corresponding - * ssl_alp_inventory_item term when created or saved. + * ssl-alp-inventory-item term when created or saved. * * @param int $post_id The post ID. * @param WP_Post $post The post object. @@ -416,8 +416,8 @@ public function delete_associated_inventory_post_term( $post_id ) { return; } - wp_delete_term( $term->term_id, 'ssl_alp_inventory_item' ); - clean_term_cache( array( $term->term_id ), 'ssl_alp_inventory_item' ); + wp_delete_term( $term->term_id, 'ssl-alp-inventory-item' ); + clean_term_cache( array( $term->term_id ), 'ssl-alp-inventory-item' ); } /** @@ -498,7 +498,7 @@ public function register_taxonomy() { ); // Create inventory taxonomy. - register_taxonomy( 'ssl_alp_inventory_item', $this->supported_post_types, $args ); + register_taxonomy( 'ssl-alp-inventory-item', $this->supported_post_types, $args ); } /** @@ -545,7 +545,7 @@ public function add_posts_row_data( $colname, $post_id ) { if ( $term->count > 0 ) { printf( '%3$d', - esc_url( 'edit.php?taxonomy=ssl_alp_inventory_item&term=' . $this->get_inventory_term_slug( $post_id ) ), + esc_url( 'edit.php?taxonomy=ssl-alp-inventory-item&term=' . $this->get_inventory_term_slug( $post_id ) ), esc_attr__( 'View posts for this inventory item', 'ssl-alp' ), esc_html( number_format_i18n( $term->count ) ) ); @@ -564,7 +564,7 @@ public function add_posts_row_data( $colname, $post_id ) { * @return string The overridden term link. */ public function override_term_link( $link, $term, $taxonomy ) { - if ( 'ssl_alp_inventory_item' !== $taxonomy ) { + if ( 'ssl-alp-inventory-item' !== $taxonomy ) { return $link; } @@ -594,14 +594,14 @@ public function get_inventory_term_archive_url( $term ) { return; } - if ( 'ssl_alp_inventory_item' !== $term->taxonomy ) { + if ( 'ssl-alp-inventory-item' !== $term->taxonomy ) { return; } // Temporarily disable filter that overrides term link. $this->disable_override_term_link(); - $url = get_term_link( $term, 'ssl_alp_inventory_item' ); + $url = get_term_link( $term, 'ssl-alp-inventory-item' ); // Re-enable filter. $this->enable_override_term_link(); @@ -625,7 +625,7 @@ public function get_inventory_term_archive_url( $term ) { * @return string|WP_Error $term The term, or error. */ public function disallow_insert_term( $term, $taxonomy ) { - if ( 'ssl_alp_inventory_item' !== $taxonomy ) { + if ( 'ssl-alp-inventory-item' !== $taxonomy ) { return $term; } @@ -647,7 +647,7 @@ public function disallow_insert_term( $term, $taxonomy ) { * @param string $taxonomy Taxonomy slug. */ public function reject_invalid_inventory_terms( $object_id, $tt_id, $taxonomy ) { - if ( 'ssl_alp_inventory_item' !== $taxonomy ) { + if ( 'ssl-alp-inventory-item' !== $taxonomy ) { return; } @@ -656,7 +656,7 @@ public function reject_invalid_inventory_terms( $object_id, $tt_id, $taxonomy ) return; } - $term = get_term_by( 'term_taxonomy_id', $tt_id, 'ssl_alp_inventory_item' ); + $term = get_term_by( 'term_taxonomy_id', $tt_id, 'ssl-alp-inventory-item' ); if ( ! $term ) { // Nothing to do here. @@ -668,7 +668,7 @@ public function reject_invalid_inventory_terms( $object_id, $tt_id, $taxonomy ) if ( ! $inventory_post ) { // This is not a valid inventory term - delete it. - wp_delete_term( $term->term_id, 'ssl_alp_inventory_item' ); + wp_delete_term( $term->term_id, 'ssl-alp-inventory-item' ); } } @@ -758,7 +758,7 @@ public function parse_query_vars( $query ) { // applies the relation as part of its instantiation. 'relation' => 'AND', array( - 'taxonomy' => 'ssl_alp_inventory_item', + 'taxonomy' => 'ssl-alp-inventory-item', 'terms' => $inventory_item_and, 'field' => 'term_id', 'operator' => 'AND', @@ -770,7 +770,7 @@ public function parse_query_vars( $query ) { if ( ! empty( $inventory_item_in ) ) { // Coauthor IN search criterion specified. $tax_query[] = array( - 'taxonomy' => 'ssl_alp_inventory_item', + 'taxonomy' => 'ssl-alp-inventory-item', 'terms' => $inventory_item_in, 'field' => 'term_id', 'include_children' => false, @@ -780,7 +780,7 @@ public function parse_query_vars( $query ) { if ( ! empty( $inventory_not_in ) ) { // Coauthor NOT IN search criterion specified. $tax_query[] = array( - 'taxonomy' => 'ssl_alp_inventory_item', + 'taxonomy' => 'ssl-alp-inventory-item', 'terms' => $inventory_not_in, 'field' => 'term_id', 'operator' => 'NOT IN', diff --git a/ssl-alp/includes/class-ssl-alp-uninstaller.php b/ssl-alp/includes/class-ssl-alp-uninstaller.php index 164b2de..b40f5bf 100644 --- a/ssl-alp/includes/class-ssl-alp-uninstaller.php +++ b/ssl-alp/includes/class-ssl-alp-uninstaller.php @@ -148,7 +148,7 @@ private static function delete_taxonomies() { self::delete_taxonomy( 'ssl_alp_coauthor' ); self::delete_taxonomy( 'ssl_alp_crossreference' ); self::delete_taxonomy( 'ssl_alp_unread_flag' ); - self::delete_taxonomy( 'ssl_alp_inventory_item' ); + self::delete_taxonomy( 'ssl-alp-inventory-item' ); } /** diff --git a/ssl-alp/tests/unit/test-inventory.php b/ssl-alp/tests/unit/test-inventory.php index dd98f85..f3cb53a 100644 --- a/ssl-alp/tests/unit/test-inventory.php +++ b/ssl-alp/tests/unit/test-inventory.php @@ -55,7 +55,7 @@ public function test_creating_inventory_post_creates_corresponding_term() { $this->assertEquals( $post->post_type, 'ssl-alp-inventory' ); // A corresponding term should have been created. - $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); + $term = get_term_by( 'slug', $post->ID, 'ssl-alp-inventory-item' ); $this->assertNotFalse( $term ); $this->assertEquals( $term->slug, $post->ID ); } @@ -70,7 +70,7 @@ public function test_deleting_inventory_post_deletes_corresponding_term() { ); $this->assertEquals( $post->post_type, 'ssl-alp-inventory' ); - $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); + $term = get_term_by( 'slug', $post->ID, 'ssl-alp-inventory-item' ); $this->assertNotFalse( $term ); $this->assertEquals( $term->slug, $post->ID ); @@ -78,7 +78,7 @@ public function test_deleting_inventory_post_deletes_corresponding_term() { wp_delete_post( $post->ID, true ); // The term should be deleted too. - $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); + $term = get_term_by( 'slug', $post->ID, 'ssl-alp-inventory-item' ); $this->assertFalse( $term ); } @@ -92,7 +92,7 @@ public function test_trashing_inventory_post_does_not_delete_corresponding_term( ); $this->assertEquals( $post->post_type, 'ssl-alp-inventory' ); - $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); + $term = get_term_by( 'slug', $post->ID, 'ssl-alp-inventory-item' ); $this->assertNotFalse( $term ); $this->assertEquals( $term->slug, $post->ID ); @@ -100,7 +100,7 @@ public function test_trashing_inventory_post_does_not_delete_corresponding_term( wp_trash_post( $post->ID ); // The term should still be present. - $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); + $term = get_term_by( 'slug', $post->ID, 'ssl-alp-inventory-item' ); $this->assertNotFalse( $term ); $this->assertEquals( $term->slug, $post->ID ); @@ -108,7 +108,7 @@ public function test_trashing_inventory_post_does_not_delete_corresponding_term( wp_delete_post( $post->ID ); // The term should be deleted too. - $term = get_term_by( 'slug', $post->ID, 'ssl_alp_inventory_item' ); + $term = get_term_by( 'slug', $post->ID, 'ssl-alp-inventory-item' ); $this->assertFalse( $term ); } @@ -123,7 +123,7 @@ public function test_user_cannot_create_inventory_item_terms_manually() { foreach ( $users as $user ) { wp_set_current_user( $user->ID ); - $term = wp_insert_term( 'Test', 'ssl_alp_inventory_item' ); + $term = wp_insert_term( 'Test', 'ssl-alp-inventory-item' ); $this->assertTrue( is_wp_error( $term ) ); } } diff --git a/themes/labbook/inc/template-tags.php b/themes/labbook/inc/template-tags.php index 84d4296..c24bf7c 100644 --- a/themes/labbook/inc/template-tags.php +++ b/themes/labbook/inc/template-tags.php @@ -513,7 +513,7 @@ function labbook_the_footer() { if ( labbook_ssl_alp_inventory_enabled() ) { /* translators: used between list items, there is a space after the comma. */ - $inventory_list = get_the_term_list( $post->ID, 'ssl_alp_inventory_item', '', __( ', ', 'labbook' ) ); + $inventory_list = get_the_term_list( $post->ID, 'ssl-alp-inventory-item', '', __( ', ', 'labbook' ) ); if ( $inventory_list ) { printf( @@ -1731,7 +1731,7 @@ function labbook_the_advanced_search_inventory_filter_table() { $inventory_items = get_terms( array( - 'taxonomy' => 'ssl_alp_inventory_item', + 'taxonomy' => 'ssl-alp-inventory-item', 'orderby' => 'name', 'order' => 'ASC', ) From 542081d53e58e4d0635075c0e26916849c5c6046 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 12 Aug 2019 21:11:34 +0200 Subject: [PATCH 56/61] Change ssl_alp_unread_flag to ssl-alp-unread-flag --- ssl-alp/includes/class-ssl-alp-revisions.php | 26 +++++++++---------- .../includes/class-ssl-alp-uninstaller.php | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-revisions.php b/ssl-alp/includes/class-ssl-alp-revisions.php index 62aef29..f58b364 100644 --- a/ssl-alp/includes/class-ssl-alp-revisions.php +++ b/ssl-alp/includes/class-ssl-alp-revisions.php @@ -1075,7 +1075,7 @@ private function get_user_unread_flag_term( $user = null ) { } $term_name = $this->get_unread_flag_term_name( $user ); - $term = get_term_by( 'name', $term_name, 'ssl_alp_unread_flag' ); + $term = get_term_by( 'name', $term_name, 'ssl-alp-unread-flag' ); if ( ! $term ) { // Term doesn't yet exist. @@ -1084,13 +1084,13 @@ private function get_user_unread_flag_term( $user = null ) { ); // Insert term using slugified username as term name. - $new_term_data = wp_insert_term( $term_name, 'ssl_alp_unread_flag', $args ); + $new_term_data = wp_insert_term( $term_name, 'ssl-alp-unread-flag', $args ); if ( is_wp_error( $new_term_data ) ) { return false; } - $term = get_term_by( 'id', $new_term_data['term_id'], 'ssl_alp_unread_flag' ); + $term = get_term_by( 'id', $new_term_data['term_id'], 'ssl-alp-unread-flag' ); } return $term; @@ -1119,7 +1119,7 @@ public function register_unread_flag_taxonomy() { ); // Create read flag taxonomy for posts. - register_taxonomy( 'ssl_alp_unread_flag', 'post', $args ); + register_taxonomy( 'ssl-alp-unread-flag', 'post', $args ); } /** @@ -1165,7 +1165,7 @@ public function remove_adjacent_links_action() { public static function add_unread_post_rewrite_rules() { add_rewrite_rule( '^unread\/?(?:page\/(\d+))?\/?$', - 'index.php?unread=ssl_alp_unread_flag&paged=$matches[1]', + 'index.php?unread=show&paged=$matches[1]', 'top' // Required to avoid page matching rule. ); } @@ -1222,7 +1222,7 @@ public function set_unread_posts_archive_page_user() { // Cannot show useful unread posts page. $wp_query->set_404(); } else { - if ( 'ssl_alp_unread_flag' === get_query_var( 'unread' ) ) { + if ( 'show' === get_query_var( 'unread' ) ) { // The request is for unread flags. // Set the unread flag queryvar to the user's unread term slug. set_query_var( 'unread', $this->get_unread_flag_term_slug() ); @@ -1728,7 +1728,7 @@ public function get_post_read_status( $post, $user = null ) { } // The term is assigned to the post if the post is unread. - return ! has_term( $user_unread_flag_term->name, 'ssl_alp_unread_flag', $post ); + return ! has_term( $user_unread_flag_term->name, 'ssl-alp-unread-flag', $post ); } /** @@ -1784,10 +1784,10 @@ public function set_post_read_status( $read, $post = null, $user = null ) { if ( $read ) { // Remove unread flag. - $success = wp_remove_object_terms( $post->ID, array( $user_unread_flag_term->name ), 'ssl_alp_unread_flag' ); + $success = wp_remove_object_terms( $post->ID, array( $user_unread_flag_term->name ), 'ssl-alp-unread-flag' ); } else { // Set unread flag. - $success = wp_set_post_terms( $post->ID, array( $user_unread_flag_term->name ), 'ssl_alp_unread_flag', true ); + $success = wp_set_post_terms( $post->ID, array( $user_unread_flag_term->name ), 'ssl-alp-unread-flag', true ); } if ( is_wp_error( $success ) ) { @@ -1862,7 +1862,7 @@ public function filter_edit_post_views( $views ) { // Build URL arguments. $unread_flag_args = array( - 'taxonomy' => 'ssl_alp_unread_flag', + 'taxonomy' => 'ssl-alp-unread-flag', 'term' => $unread_flag_slug, ); @@ -1870,7 +1870,7 @@ public function filter_edit_post_views( $views ) { $request_term = get_query_var( 'term' ); // Check if the current page is the "Mine" view. - if ( 'ssl_alp_unread_flag' === $request_tax && $unread_flag_slug === $request_term ) { + if ( 'ssl-alp-unread-flag' === $request_tax && $unread_flag_slug === $request_term ) { $class = 'current'; } else { $class = ''; @@ -1898,7 +1898,7 @@ public function filter_edit_post_views( $views ) { * @param string $title The archive page title. */ public function set_unread_post_archive_title( $title ) { - if ( ! is_tax( 'ssl_alp_unread_flag' ) ) { + if ( ! is_tax( 'ssl-alp-unread-flag' ) ) { // Not this taxonomy's page. return $title; } @@ -1911,7 +1911,7 @@ public function set_unread_post_archive_title( $title ) { $term = get_queried_object(); $tax = get_taxonomy( $term->taxonomy ); - if ( 'ssl_alp_unread_flag' !== $tax->name ) { + if ( 'ssl-alp-unread-flag' !== $tax->name ) { return $title; } diff --git a/ssl-alp/includes/class-ssl-alp-uninstaller.php b/ssl-alp/includes/class-ssl-alp-uninstaller.php index b40f5bf..6a97d7f 100644 --- a/ssl-alp/includes/class-ssl-alp-uninstaller.php +++ b/ssl-alp/includes/class-ssl-alp-uninstaller.php @@ -147,7 +147,7 @@ private static function delete_options() { private static function delete_taxonomies() { self::delete_taxonomy( 'ssl_alp_coauthor' ); self::delete_taxonomy( 'ssl_alp_crossreference' ); - self::delete_taxonomy( 'ssl_alp_unread_flag' ); + self::delete_taxonomy( 'ssl-alp-unread-flag' ); self::delete_taxonomy( 'ssl-alp-inventory-item' ); } From f973aaade374b39ef707ef4af77c3a5a287dad8a Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 12 Aug 2019 21:13:48 +0200 Subject: [PATCH 57/61] Change ssl_alp_crossreference to ssl-alp-crossreference --- ssl-alp/includes/class-ssl-alp-references.php | 12 ++++++------ ssl-alp/includes/class-ssl-alp-uninstaller.php | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-references.php b/ssl-alp/includes/class-ssl-alp-references.php index 28c48fd..8a90c7b 100644 --- a/ssl-alp/includes/class-ssl-alp-references.php +++ b/ssl-alp/includes/class-ssl-alp-references.php @@ -86,7 +86,7 @@ public function register_crossreference_taxonomy() { } register_taxonomy( - 'ssl_alp_crossreference', + 'ssl-alp-crossreference', array_keys( $this->supported_reference_post_types ), array( 'hierarchical' => false, @@ -152,12 +152,12 @@ public function extract_crossreferences( $post_id, $post ) { } // Update post's reference taxonomy terms (replaces any existing terms). - wp_set_post_terms( $post->ID, array_keys( $terms ), 'ssl_alp_crossreference' ); + wp_set_post_terms( $post->ID, array_keys( $terms ), 'ssl-alp-crossreference' ); // Set internal term metadata. foreach ( $terms as $term_name => $referenced_post_id ) { // Get term. - $term = get_term_by( 'name', $term_name, 'ssl_alp_crossreference' ); + $term = get_term_by( 'name', $term_name, 'ssl-alp-crossreference' ); // Add term metadata. update_term_meta( $term->term_id, 'reference-to-post-id', $referenced_post_id ); @@ -238,7 +238,7 @@ public function get_reference_to_posts( $post = null ) { return; } - $terms = get_the_terms( $post, 'ssl_alp_crossreference' ); + $terms = get_the_terms( $post, 'ssl-alp-crossreference' ); $posts = array(); @@ -253,7 +253,7 @@ public function get_reference_to_posts( $post = null ) { $referenced_post_id = get_term_meta( $term->term_id, 'reference-to-post-id', - 'ssl_alp_crossreference' + 'ssl-alp-crossreference' ); $referenced_post = get_post( $referenced_post_id ); @@ -327,7 +327,7 @@ public function get_reference_from_posts( $post = null ) { ", 'reference-to-post-id', $post->ID, - 'ssl_alp_crossreference' + 'ssl-alp-crossreference' ) ); diff --git a/ssl-alp/includes/class-ssl-alp-uninstaller.php b/ssl-alp/includes/class-ssl-alp-uninstaller.php index 6a97d7f..1b12f8b 100644 --- a/ssl-alp/includes/class-ssl-alp-uninstaller.php +++ b/ssl-alp/includes/class-ssl-alp-uninstaller.php @@ -146,7 +146,7 @@ private static function delete_options() { */ private static function delete_taxonomies() { self::delete_taxonomy( 'ssl_alp_coauthor' ); - self::delete_taxonomy( 'ssl_alp_crossreference' ); + self::delete_taxonomy( 'ssl-alp-crossreference' ); self::delete_taxonomy( 'ssl-alp-unread-flag' ); self::delete_taxonomy( 'ssl-alp-inventory-item' ); } From dca4cb440e022de74fd30a488296bc733c136548 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 12 Aug 2019 21:31:30 +0200 Subject: [PATCH 58/61] Change ssl_alp_coauthor to ssl-alp-coauthor --- ssl-alp/includes/class-ssl-alp-coauthors.php | 70 +++++++++---------- .../includes/class-ssl-alp-uninstaller.php | 2 +- ssl-alp/tests/unit/test-coauthors-search.php | 2 +- ssl-alp/tests/unit/test-coauthors.php | 10 +-- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-coauthors.php b/ssl-alp/includes/class-ssl-alp-coauthors.php index 293dca9..6341c8a 100644 --- a/ssl-alp/includes/class-ssl-alp-coauthors.php +++ b/ssl-alp/includes/class-ssl-alp-coauthors.php @@ -131,7 +131,7 @@ public function register_hooks() { $loader->add_filter( 'the_author', $this, 'fix_author_page_filter', 10, 1 ); // Filter the display of coauthor terms in the admin post list. - $loader->add_filter( 'ssl_alp_coauthor_name', $this, 'filter_coauthor_term_display', 10, 3 ); + $loader->add_filter( 'ssl-alp-coauthor_name', $this, 'filter_coauthor_term_display', 10, 3 ); /** * Authors widget. @@ -227,7 +227,7 @@ public function register_taxonomy() { ); // Create coauthor taxonomy. - register_taxonomy( 'ssl_alp_coauthor', $this->supported_post_types, $args ); + register_taxonomy( 'ssl-alp-coauthor', $this->supported_post_types, $args ); } /** @@ -302,7 +302,7 @@ public function get_coauthor_term( $user ) { } // Retrieve term associated with the user. - return get_term_by( 'slug', $this->get_coauthor_term_slug( $user ), 'ssl_alp_coauthor' ); + return get_term_by( 'slug', $this->get_coauthor_term_slug( $user ), 'ssl-alp-coauthor' ); } /** @@ -330,11 +330,11 @@ public function add_coauthor_term( $coauthor ) { 'slug' => $this->get_coauthor_term_slug( $coauthor ), ); - // Temporarily disable the filter that blocks creation of terms in the ssl_alp_coauthor + // Temporarily disable the filter that blocks creation of terms in the ssl-alp-coauthor // taxonomy. $this->disable_disallow_insert_term_filter(); - wp_insert_term( $coauthor->display_name, 'ssl_alp_coauthor', $args ); + wp_insert_term( $coauthor->display_name, 'ssl-alp-coauthor', $args ); // Re-enable the filter. $this->enable_disallow_insert_term_filter(); @@ -366,12 +366,12 @@ public function update_coauthor_term( $user_id, $old_user_object ) { 'slug' => $this->get_coauthor_term_slug( $user ), ); - // Temporarily disable the filter that blocks creation of terms in the ssl_alp_coauthor + // Temporarily disable the filter that blocks creation of terms in the ssl-alp-coauthor // taxonomy. $this->disable_disallow_insert_term_filter(); // Set term name. - wp_update_term( $term->term_id, 'ssl_alp_coauthor', $args ); + wp_update_term( $term->term_id, 'ssl-alp-coauthor', $args ); // Re-enable the filter. $this->enable_disallow_insert_term_filter(); @@ -422,7 +422,7 @@ public function delete_coauthor_term( $user ) { if ( $term ) { // Delete user's term. - wp_delete_term( $term->term_id, 'ssl_alp_coauthor' ); + wp_delete_term( $term->term_id, 'ssl-alp-coauthor' ); } } @@ -491,7 +491,7 @@ public function filter_terms_to_edit( $terms_to_edit, $taxonomy ) { return; } - if ( 'ssl_alp_coauthor' !== $taxonomy ) { + if ( 'ssl-alp-coauthor' !== $taxonomy ) { // Not our taxonomy. return $terms_to_edit; } @@ -499,7 +499,7 @@ public function filter_terms_to_edit( $terms_to_edit, $taxonomy ) { // Get terms in descending chronological order. $terms = wp_get_object_terms( $post->ID, - 'ssl_alp_coauthor', + 'ssl-alp-coauthor', array( 'orderby' => 'term_order', 'order' => 'ASC', @@ -574,7 +574,7 @@ public function filter_manage_users_custom_column( $column_value, $column_name, if ( $post_count > 0 ) { $column_value .= sprintf( '%3$d', - esc_url( 'edit.php?taxonomy=ssl_alp_coauthor&term=' . $this->get_coauthor_term_slug( $user ) ), + esc_url( 'edit.php?taxonomy=ssl-alp-coauthor&term=' . $this->get_coauthor_term_slug( $user ) ), esc_attr__( 'View posts by this author', 'ssl-alp' ), esc_html( $post_count ) ); @@ -676,7 +676,7 @@ public function filter_edit_post_views( $views ) { // Build URL arguments. $mine_args = array( - 'taxonomy' => 'ssl_alp_coauthor', + 'taxonomy' => 'ssl-alp-coauthor', 'term' => $coauthor_slug, ); @@ -684,7 +684,7 @@ public function filter_edit_post_views( $views ) { $request_term = get_query_var( 'term' ); // Check if the current page is the "Mine" view. - if ( 'ssl_alp_coauthor' === $request_tax && $coauthor_slug === $request_term ) { + if ( 'ssl-alp-coauthor' === $request_tax && $coauthor_slug === $request_term ) { $class = 'current'; } else { $class = ''; @@ -721,7 +721,7 @@ public function filter_edit_post_views( $views ) { * @param WP_Taxonomy $taxonomy Taxonomy. */ public function update_users_posts_count( $tt_ids, $taxonomy ) { - if ( 'ssl_alp_coauthor' !== $taxonomy->name ) { + if ( 'ssl-alp-coauthor' !== $taxonomy->name ) { return; } @@ -772,14 +772,14 @@ public function update_author_term_post_count( $term ) { GROUP BY {$wpdb->posts}.ID HAVING MAX( IF ( {$wpdb->term_taxonomy}.taxonomy = %s, IF ( {$having_terms}, 2, 1 ), 0 ) ) <> 1 ", - 'ssl_alp_coauthor' + 'ssl-alp-coauthor' ); $count = $wpdb->query( $query ); $wpdb->update( $wpdb->term_taxonomy, array( 'count' => $count ), array( 'term_taxonomy_id' => $term->term_taxonomy_id ) ); // Invalidate term cache. - clean_term_cache( $term->term_id, 'ssl_alp_coauthor', false ); + clean_term_cache( $term->term_id, 'ssl-alp-coauthor', false ); } /** @@ -825,7 +825,7 @@ public function posts_join_filter( $join, $query ) { return $join; } - if ( ! empty( $query->query_vars['post_type'] ) && ! is_object_in_taxonomy( $query->query_vars['post_type'], 'ssl_alp_coauthor' ) ) { + if ( ! empty( $query->query_vars['post_type'] ) && ! is_object_in_taxonomy( $query->query_vars['post_type'], 'ssl-alp-coauthor' ) ) { // Not a valid post type, so return unmodified. return $join; } @@ -864,7 +864,7 @@ public function posts_where_filter( $where, $query ) { return $where; } - if ( ! empty( $query->query_vars['post_type'] ) && ! is_object_in_taxonomy( $query->query_vars['post_type'], 'ssl_alp_coauthor' ) ) { + if ( ! empty( $query->query_vars['post_type'] ) && ! is_object_in_taxonomy( $query->query_vars['post_type'], 'ssl-alp-coauthor' ) ) { // Not a valid post type, so return unmodified. return $where; } @@ -903,7 +903,7 @@ public function posts_where_filter( $where, $query ) { $this->having_terms = ''; foreach ( $terms as $term ) { - $terms_implode .= "({$wpdb->term_taxonomy}.taxonomy = 'ssl_alp_coauthor' AND {$wpdb->term_taxonomy}.term_id = '{$term->term_id}') OR "; + $terms_implode .= "({$wpdb->term_taxonomy}.taxonomy = 'ssl-alp-coauthor' AND {$wpdb->term_taxonomy}.term_id = '{$term->term_id}') OR "; $this->having_terms .= " {$wpdb->term_taxonomy}.term_id = '{$term->term_id}' OR "; } @@ -911,7 +911,7 @@ public function posts_where_filter( $where, $query ) { $this->having_terms = rtrim( $this->having_terms, ' OR' ); // Match "wp_posts.post_author = [number]" or "wp_posts.post_author IN ([list of numbers])" - // and append "OR (wp_term_taxonomy.taxonomy = 'ssl_alp_coauthor' AND wp_term_taxonomy.term_id = '6')". + // and append "OR (wp_term_taxonomy.taxonomy = 'ssl-alp-coauthor' AND wp_term_taxonomy.term_id = '6')". $where = preg_replace( '/(\b(?:' . $wpdb->posts . '\.)?post_author\s*(?:=|IN)\s*\(?(\d+)\)?)/', '($1 OR ' . $terms_implode . ')', @@ -943,13 +943,13 @@ public function posts_groupby_filter( $groupby, $query ) { return $groupby; } - if ( ! empty( $query->query_vars['post_type'] ) && ! is_object_in_taxonomy( $query->query_vars['post_type'], 'ssl_alp_coauthor' ) ) { + if ( ! empty( $query->query_vars['post_type'] ) && ! is_object_in_taxonomy( $query->query_vars['post_type'], 'ssl-alp-coauthor' ) ) { // Not a valid post type, so return unmodified. return $groupby; } if ( $this->having_terms ) { - $having = "MAX( IF ( {$wpdb->term_taxonomy}.taxonomy = 'ssl_alp_coauthor', IF ( {$this->having_terms}, 2, 1 ), 0 ) ) <> 1 "; + $having = "MAX( IF ( {$wpdb->term_taxonomy}.taxonomy = 'ssl-alp-coauthor', IF ( {$this->having_terms}, 2, 1 ), 0 ) ) <> 1 "; $groupby = "{$wpdb->posts}.ID HAVING {$having}"; } @@ -1007,7 +1007,7 @@ public function add_user_to_draft( $post_id, $post ) { * @return string|WP_Error $term The term, or error. */ public function disallow_insert_term( $term, $taxonomy ) { - if ( 'ssl_alp_coauthor' !== $taxonomy ) { + if ( 'ssl-alp-coauthor' !== $taxonomy ) { return $term; } @@ -1029,7 +1029,7 @@ public function disallow_insert_term( $term, $taxonomy ) { * @param string $taxonomy Taxonomy slug. */ public function reject_invalid_coauthor_terms( $object_id, $tt_id, $taxonomy ) { - if ( 'ssl_alp_coauthor' !== $taxonomy ) { + if ( 'ssl-alp-coauthor' !== $taxonomy ) { return; } @@ -1038,7 +1038,7 @@ public function reject_invalid_coauthor_terms( $object_id, $tt_id, $taxonomy ) { return; } - $term = get_term_by( 'term_taxonomy_id', $tt_id, 'ssl_alp_coauthor' ); + $term = get_term_by( 'term_taxonomy_id', $tt_id, 'ssl-alp-coauthor' ); if ( ! $term ) { // Nothing to do here. @@ -1050,7 +1050,7 @@ public function reject_invalid_coauthor_terms( $object_id, $tt_id, $taxonomy ) { if ( ! $coauthor ) { // This is not a valid coauthor term - delete it. - wp_delete_term( $term->term_id, 'ssl_alp_coauthor' ); + wp_delete_term( $term->term_id, 'ssl-alp-coauthor' ); } } @@ -1070,7 +1070,7 @@ public function reject_invalid_coauthor_terms( $object_id, $tt_id, $taxonomy ) { public function check_post_author( $post_id, $term_ids, $tt_ids, $taxonomy ) { global $wpdb; - if ( 'ssl_alp_coauthor' !== $taxonomy ) { + if ( 'ssl-alp-coauthor' !== $taxonomy ) { return; } @@ -1096,7 +1096,7 @@ public function check_post_author( $post_id, $term_ids, $tt_ids, $taxonomy ) { $terms = array(); foreach ( $term_ids as $term_id ) { - $terms[] = get_term( $term_id, 'ssl_alp_coauthor' ); + $terms[] = get_term( $term_id, 'ssl-alp-coauthor' ); } $first_term = reset( $terms ); @@ -1206,7 +1206,7 @@ public function set_coauthors( $post, $coauthors ) { $coauthor_term_ids = wp_list_pluck( $coauthor_terms, 'term_id' ); // Update post's coauthors. - wp_set_post_terms( $post->ID, $coauthor_term_ids, 'ssl_alp_coauthor', false ); + wp_set_post_terms( $post->ID, $coauthor_term_ids, 'ssl-alp-coauthor', false ); } /** @@ -1295,7 +1295,7 @@ public function parse_query_vars( $query ) { // applies the relation as part of its instantiation. 'relation' => 'AND', array( - 'taxonomy' => 'ssl_alp_coauthor', + 'taxonomy' => 'ssl-alp-coauthor', 'terms' => $coauthor_and, 'field' => 'term_id', 'operator' => 'AND', @@ -1307,7 +1307,7 @@ public function parse_query_vars( $query ) { if ( ! empty( $coauthor_in ) ) { // Coauthor IN search criterion specified. $tax_query[] = array( - 'taxonomy' => 'ssl_alp_coauthor', + 'taxonomy' => 'ssl-alp-coauthor', 'terms' => $coauthor_in, 'field' => 'term_id', 'include_children' => false, @@ -1317,7 +1317,7 @@ public function parse_query_vars( $query ) { if ( ! empty( $coauthor_not_in ) ) { // Coauthor NOT IN search criterion specified. $tax_query[] = array( - 'taxonomy' => 'ssl_alp_coauthor', + 'taxonomy' => 'ssl-alp-coauthor', 'terms' => $coauthor_not_in, 'field' => 'term_id', 'operator' => 'NOT IN', @@ -1506,7 +1506,7 @@ public function get_coauthor_posts( $user ) { } // Get objects associated with term (assume everything is a post). - $term_objects = get_objects_in_term( $user_term->term_id, 'ssl_alp_coauthor' ); + $term_objects = get_objects_in_term( $user_term->term_id, 'ssl-alp-coauthor' ); foreach ( $term_objects as $post_id ) { // get_objects_in_term returns strings. @@ -1736,7 +1736,7 @@ public function get_coauthor_terms_for_post( $post = null ) { $coauthor_terms = wp_get_object_terms( $post->ID, - 'ssl_alp_coauthor', + 'ssl-alp-coauthor', array( 'orderby' => 'term_order', 'order' => 'ASC', @@ -1835,7 +1835,7 @@ public function filter_coauthor_term_display( $value, $term_id, $context ) { return $value; } - $term = get_term_by( 'id', $term_id, 'ssl_alp_coauthor' ); + $term = get_term_by( 'id', $term_id, 'ssl-alp-coauthor' ); // Get user from term. $user = $this->get_user_from_coauthor_term( $term ); diff --git a/ssl-alp/includes/class-ssl-alp-uninstaller.php b/ssl-alp/includes/class-ssl-alp-uninstaller.php index 1b12f8b..1bbb22d 100644 --- a/ssl-alp/includes/class-ssl-alp-uninstaller.php +++ b/ssl-alp/includes/class-ssl-alp-uninstaller.php @@ -145,7 +145,7 @@ private static function delete_options() { * Delete plugin taxonomies. */ private static function delete_taxonomies() { - self::delete_taxonomy( 'ssl_alp_coauthor' ); + self::delete_taxonomy( 'ssl-alp-coauthor' ); self::delete_taxonomy( 'ssl-alp-crossreference' ); self::delete_taxonomy( 'ssl-alp-unread-flag' ); self::delete_taxonomy( 'ssl-alp-inventory-item' ); diff --git a/ssl-alp/tests/unit/test-coauthors-search.php b/ssl-alp/tests/unit/test-coauthors-search.php index 2a14203..eb34011 100644 --- a/ssl-alp/tests/unit/test-coauthors-search.php +++ b/ssl-alp/tests/unit/test-coauthors-search.php @@ -68,7 +68,7 @@ private function create_coauthor_post( $author, $coauthors = array() ) { ); if ( ! empty( $terms ) ) { - wp_set_post_terms( $post->ID, $terms, 'ssl_alp_coauthor' ); + wp_set_post_terms( $post->ID, $terms, 'ssl-alp-coauthor' ); } return $post; diff --git a/ssl-alp/tests/unit/test-coauthors.php b/ssl-alp/tests/unit/test-coauthors.php index 50f2a87..a42e208 100644 --- a/ssl-alp/tests/unit/test-coauthors.php +++ b/ssl-alp/tests/unit/test-coauthors.php @@ -41,7 +41,7 @@ private function create_coauthor_post( $author, $coauthors = array() ) { ); if ( ! empty( $terms ) ) { - wp_set_post_terms( $post->ID, $terms, "ssl_alp_coauthor" ); + wp_set_post_terms( $post->ID, $terms, "ssl-alp-coauthor" ); } return $post; @@ -1401,14 +1401,14 @@ function test_invalid_coauthor_terms_are_removed() { $ssl_alp->coauthors->disable_disallow_insert_term_filter(); $junk1 = wp_insert_term( 'junk_term', - 'ssl_alp_coauthor', + 'ssl-alp-coauthor', array( 'slug' => 'junk-term', ) ); $junk2 = wp_insert_term( 'ssl_alp_coauthor_nonexistent_user', - 'ssl_alp_coauthor', + 'ssl-alp-coauthor', array( 'slug' => 'ssl-alp-coauthor-nonexistent-user', ) @@ -1421,12 +1421,12 @@ function test_invalid_coauthor_terms_are_removed() { $set_terms[] = $junk2['term_id']; // Set terms. - wp_set_post_terms( $post->ID, $set_terms, 'ssl_alp_coauthor' ); + wp_set_post_terms( $post->ID, $set_terms, 'ssl-alp-coauthor' ); // Get post terms. $new_terms = wp_get_object_terms( $post->ID, - 'ssl_alp_coauthor' + 'ssl-alp-coauthor' ); $new_term_ids = wp_list_pluck( $new_terms, 'term_id' ); From d3d9301297d17e7124a399d54e813ce0855889d8 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 12 Aug 2019 21:54:21 +0200 Subject: [PATCH 59/61] Remove inventory template --- ssl-alp/includes/class-ssl-alp-inventory.php | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/ssl-alp/includes/class-ssl-alp-inventory.php b/ssl-alp/includes/class-ssl-alp-inventory.php index 6d48358..9425644 100644 --- a/ssl-alp/includes/class-ssl-alp-inventory.php +++ b/ssl-alp/includes/class-ssl-alp-inventory.php @@ -183,20 +183,6 @@ public function register_post_type() { 'public' => true, 'hierarchical' => false, 'show_in_rest' => true, - 'template' => array( - array( - 'core/heading', - array( - 'content' => 'Location', - ), - ), - array( - 'core/paragraph', - array( - 'placeholder' => 'Location...', - ), - ), - ), 'menu_icon' => 'dashicons-book-alt', 'supports' => array( 'title', From 319c08b31c3c2502ebb0b3d4ebb269020ab7a502 Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 12 Aug 2019 22:05:37 +0200 Subject: [PATCH 60/61] Bump version --- ssl-alp/README.txt | 23 ++++++++++++++++++++++- ssl-alp/alp.php | 4 ++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/ssl-alp/README.txt b/ssl-alp/README.txt index 59186b2..c253d8c 100644 --- a/ssl-alp/README.txt +++ b/ssl-alp/README.txt @@ -4,7 +4,7 @@ Tags: logbook, coauthor, revisions, references, latex, tex, mathematics, wiki Requires at least: 5.1.0 Tested up to: 5.2.0 Requires PHP: 7.0.0 -Stable tag: 0.15.2 +Stable tag: 0.16.0 License: GNU General Public License v3 or later License URI: LICENCE @@ -79,6 +79,27 @@ on the ALP website. == Changelog == += 0.16.0 = + - Renamed taxonomy term names. This is a BREAKING change and requires some + custom queries to be run to update old terms. See the GitHub release notes + for details. + - Added inventory system. + - Changed post revisions widget to show only posts with line changes. + - Changed post revision widget to use transients instead of cache; default + update time set to 5 minutes. + - Added check to remove "Uncategorised" category from posts with at least one + other category. + - Added check to avoid referenced posts which cannot be read by user from + showing in the cross-references list. + - Simplified permission checks when editing custom taxonomy terms. + - Updated KaTeX to 0.10.2. + - Fixed bug with coauthors not being assigned to posts on sites with existing + posts. + - Fixed bug with unread posts list pagination. + - Added tool to detect pretty permalink status. + - Expanded admin documentation. + - Numerous minor bug fixes. + = 0.15.2 = - Fixed bug with media type definitions where trailing spaces caused types not to be saved. diff --git a/ssl-alp/alp.php b/ssl-alp/alp.php index 8118f56..42746d1 100644 --- a/ssl-alp/alp.php +++ b/ssl-alp/alp.php @@ -3,7 +3,7 @@ * Plugin Name: Academic Labbook * Plugin URI: https://alp.attackllama.com/ * Description: Turn WordPress into a collaborative academic labbook. - * Version: 0.15.2 + * Version: 0.16.0 * Author: Sean Leavey * Author URI: https://attackllama.com/ * License: GPL3 @@ -21,7 +21,7 @@ * Current plugin version. */ -define( 'SSL_ALP_VERSION', '0.15.2' ); +define( 'SSL_ALP_VERSION', '0.16.0' ); /** * Plugin name From a4a944f4effeba3e7b1cfec8016562cf36991c1f Mon Sep 17 00:00:00 2001 From: Sean Leavey Date: Mon, 12 Aug 2019 22:11:59 +0200 Subject: [PATCH 61/61] Bump version --- themes/labbook/functions.php | 2 +- themes/labbook/readme.txt | 13 ++++++++++++- themes/labbook/style.css | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/themes/labbook/functions.php b/themes/labbook/functions.php index 9e152aa..4cd0a18 100644 --- a/themes/labbook/functions.php +++ b/themes/labbook/functions.php @@ -8,7 +8,7 @@ */ // Theme version. -define( 'LABBOOK_VERSION', '1.1.9' ); +define( 'LABBOOK_VERSION', '1.1.10' ); // Required PHP version. define( 'LABBOOK_MINIMUM_PHP_VERSION', '7.0.0' ); diff --git a/themes/labbook/readme.txt b/themes/labbook/readme.txt index 9e55c85..9143dad 100644 --- a/themes/labbook/readme.txt +++ b/themes/labbook/readme.txt @@ -3,7 +3,7 @@ Contributors: seanleavey Tags: custom-background, custom-logo, custom-menu, editor-style, education, sticky-post, theme-options, threaded-comments, translation-ready, two-columns Requires at least: 5.0.0 Tested up to: 5.2.2 -Stable tag: 1.1.9 +Stable tag: 1.1.10 Requires PHP: 7.0.0 License: GNU General Public License v3 or later License URI: LICENCE @@ -52,6 +52,17 @@ of features provided in this theme. == Changelog == += 1.1.10 - 2019-08-12 = +* Added support for inventory post tag display to post footer. +* Added inventory post type template. +* Added thumbnail support for inventory post types. +* Changed cross-reference list to display post type in brackets after title if + not a standard post. +* Fixed bug with adjacent posts links. +* Fixed bug with unread posts pagination. +* Fixed post title overflows. +* Fixed overflow of long table columns. + = 1.1.9 - 2019-07-22 = * Fixed page IDs being printed incorrectly in page tables of contents. * Fixed non-namespaced translation. diff --git a/themes/labbook/style.css b/themes/labbook/style.css index 7c8917a..5fff282 100644 --- a/themes/labbook/style.css +++ b/themes/labbook/style.css @@ -4,7 +4,7 @@ Theme URI: https://alp.attackllama.com/documentation/themes/labbook/ Author: Sean Leavey Author URI: https://attackllama.com/ Description: Laboratory notebook theme, intended to be used in combination with Academic Labbook Plugin (ALP). ALP adds a whole bunch of features to WordPress to convert it into an electronic laboratory notebook. The Labbook theme enables the display of the front-end features provided by ALP. ALP is currently in beta and can be installed using the instructions here: https://alp.attackllama.com/documentation/installation/. -Version: 1.1.9 +Version: 1.1.10 License: GNU General Public License v3 or later License URI: LICENSE Text Domain: labbook