diff --git a/README.md b/README.md
index 02975fb1c..e74d84f37 100644
--- a/README.md
+++ b/README.md
@@ -3,8 +3,8 @@ Contributors: batmoo, danielbachhuber, sbressler, automattic
Donate link: http://editflow.org/contribute/
Tags: edit flow, workflow, editorial, newsroom, management, journalism, post status, custom status, notifications, email, comments, editorial comments, usergroups, calendars, editorial calendar, story budget
Requires at least: 4.5
-Tested up to: 4.6.1
-Stable tag: 0.8.2
+Tested up to: 4.9.6
+Stable tag: 0.8.3
Redefining your editorial workflow.
@@ -56,6 +56,9 @@ For support questions, feedback and ideas, please use the [WordPress.org forums]
## Upgrade Notice
+**0.8.3**
+Improvements and bugfixes.
+
**0.8.2**
Minor enhancements and bug fixes, translation updates.
@@ -80,10 +83,10 @@ Contributors and other users without the 'publish_posts' capability can access c
**0.7.1**
Enhancements and bug fixes, including defaulting to the proper date in the calendar and an Italian localization.
-**0.7**
+**0.7**
Complete rewrite into a modular architecture. Lots of polish added. Important note: If upgrading from pre-v0.6, please upgrade to v0.6.5 first
-**0.6.5**
+**0.6.5**
Fixes an issue where the post timestamp would be set as soon as a custom status was used.
**0.6.4**
@@ -103,6 +106,18 @@ New features, including story budget and editorial metadata, a completely rewrit
## Changelog
+**0.8.3 (June 14, 2018)**
+* UI Improvement: Made primary buttons on Settings screen consistent with WordPress UI. Props [cojennin](https://github.com/cojennin).
+* UI Improvement: Display who particularly was notified about an editorial comment. Props [goodguyry](https://github.com/goodguyry), [WPprodigy](https://github.com/WPprodigy)
+* Improvement: Updated Russian translation and documentation. Props [achumakov](https://github.com/achumakov).
+* Improvement: Eliminate a few cases of raw SQL queries in favor of `date_query`. Props [justnorris](https://github.com/justnorris).
+* Improvement: Cache calendar items for each user individually to prevent potential cache pollution. Props [justnorris](https://github.com/justnorris).
+* Improvement: various i18n updates.
+* Improvement: Move ef_story_budget_posts_query_args filter down to allow overriding the date query in Story Budget module.
+* Improvement: Limit results in Calendar to 200 per page, potentially saving from trouble on websites with large amount of content.
+* Improvement: Don’t generate rewrite rules for notepad as they're unused.
+* Improvement: Support modifying HTML output of a Calendar day via ef_pre_calendar_single_date_item_html filter. Props [cklosowski](https://github.com/cklosowski).
+
**0.8.2 (Sept. 16, 2016)**
* Improvement: Updated Spanish localization thanks to [moucho](https://github.com/moucho)
* Improvement: New Swedish localization thanks to [Warpsmith](https://github.com/Warpsmith)
@@ -306,13 +321,13 @@ The following folks did some tremendous work helping with the release of Edit Fl
* Added option to globally disable QuickPitch widget
* Bug fix: Custom Status names cannot be longer than 20 chars
* Bug fix: Deleted users are removed as subscribers from posts
-* Bug fix: Blank menu items should now be sorta hidden
+* Bug fix: Blank menu items should now be sorta hidden
**0.2**
* Custom Statuses are now supported for pages
* Editorial Comments (with threading)
* Email Notifications (on post status change and editorial comment)
-* Additional Post metadata
+* Additional Post metadata
* Quick Pitch Dashboard widget
* Bug fix: sorting issue on Manage Posts page (Mad props to David Smith from Columbia U.)
* Other bug fixes
diff --git a/common/php/class-module-with-view.php b/common/php/class-module-with-view.php
new file mode 100644
index 000000000..5e14d2a9b
--- /dev/null
+++ b/common/php/class-module-with-view.php
@@ -0,0 +1,181 @@
+modules as $mod_name => $mod_data ) {
+ if ( isset( $mod_data->options->enabled ) && $mod_data->options->enabled == 'on' && $mod_data->configure_page_cb )
+ $settings_view_slugs[] = $mod_data->settings_slug;
+ }
+
+ // The current page better be in the array of registered settings view slugs
+ if ( empty( $settings_view_slugs ) || ! in_array( $_GET['page'], $settings_view_slugs ) ) {
+ return false;
+ }
+
+ if ( $slug && $edit_flow->modules->{$slug}->settings_slug !== $_GET['page'] ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Check whether if we're at module settings view
+ * for the current module based on `is_module_settings_view` method
+ *
+ * @return bool
+ */
+ public function is_current_module_settings_view() {
+ return $this->is_module_settings_view( $this->module->name );
+ }
+
+
+ /**
+ * Check for admin page and whether the current post type is supported
+ * @param array $allowed_pages
+ *
+ * @return bool
+ */
+ function is_active_view( $allowed_pages = array( 'edit.php', 'post.php', 'post-new.php' ) ) {
+ return ( $this->is_admin_page( $allowed_pages ) && $this->is_supported_post_type() );
+ }
+
+
+ /**
+ * Check whether the current post type is supported for $this module
+ *
+ * @return bool
+ */
+ public function is_supported_post_type() {
+ $post_type = $this->get_current_post_type();
+
+ return (
+ $post_type
+ &&
+ in_array( $post_type, $this->get_post_types_for_module( $this->module ), true )
+ );
+ }
+
+ /**
+ * Checks for the current post type
+ *
+ * @since 0.7
+ * @return string|null $post_type The post type we've found, or null if no post type
+ */
+ function get_current_post_type() {
+ global $post, $typenow, $pagenow, $current_screen;
+ //get_post() needs a variable
+ $post_id = isset( $_REQUEST['post'] ) ? (int) $_REQUEST['post'] : false;
+
+ if ( $post && $post->post_type ) {
+ $post_type = $post->post_type;
+ } elseif ( $typenow ) {
+ $post_type = $typenow;
+ } elseif ( $current_screen && ! empty( $current_screen->post_type ) ) {
+ $post_type = $current_screen->post_type;
+ } elseif ( isset( $_REQUEST['post_type'] ) ) {
+ $post_type = sanitize_key( $_REQUEST['post_type'] );
+ } elseif ( 'post.php' == $pagenow
+ && $post_id
+ && ! empty( get_post( $post_id )->post_type ) ) {
+ $post_type = get_post( $post_id )->post_type;
+ } elseif ( in_array( $pagenow, array('edit.php', 'post-new.php' ) ) && empty( $_REQUEST['post_type'] ) ) {
+ $post_type = 'post';
+ } else {
+ $post_type = null;
+ }
+
+ return $post_type;
+ }
+
+ /**
+ * Check whether currently viewing the desired admin page
+ *
+ * @param array $allowed_pages
+ *
+ * @return bool
+ */
+ public function is_admin_page( $allowed_pages = array( 'edit.php', 'post.php', 'post-new.php' ) ) {
+ global $pagenow;
+
+ return ( $pagenow && in_array( $pagenow, $allowed_pages, true ) );
+ }
+
+
+ /**
+ * Shorthand for `is_active_view` to check for list type views ( list of posts pages, custom post types )
+ *
+ * @see is_active_view
+ * @return bool
+ */
+ public function is_active_list_view() {
+ return $this->is_active_view( array( 'edit.php' ) );
+ }
+
+ /**
+ * Shorthand for `is_active_view` to check for editor mode
+ *
+ * @see is_active_view
+ * @return bool
+ */
+ public function is_active_editor_view() {
+ return $this->is_active_view( array( 'post.php', 'posts-new.php' ) );
+ }
+
+
+ /**
+ * This method was supposed to check whether or not the current page is a user-facing Edit Flow View
+ * But it was never implemented
+ *
+ * It is now deprecated in favor of `$this->is_active_view`
+ * @see EF_Module::is_active_view()
+ * @since 0.7
+ * @deprecated 0.8.3
+ *
+ * @param string $module_name (Optional) Module name to check against
+ */
+ public function is_whitelisted_functional_view( $module_name = null ) {
+ _deprecated_function( __FUNCTION__, '0.8.3', 'is_active_view' );
+
+ return true;
+ }
+
+ /**
+ * Whether or not the current page is an Edit Flow settings view (either main or module)
+ * Determination is based on $pagenow, $_GET['page'], and the module's $settings_slug
+ * If there's no module name specified, it will return true against all Edit Flow settings views
+ *
+ * @since 0.7
+ * @deprecated 0.8.3
+ *
+ * @param string $module_name (Optional) Module name to check against
+ * @return bool $is_settings_view Return true if it is
+ */
+ public function is_whitelisted_settings_view( $module_name = null ) {
+ _deprecated_function( 'is_whitelisted_settings_view', '0.8.3', 'is_module_settings_view' );
+
+ return $this->is_module_settings_view( $module_name );
+ }
+
+}
\ No newline at end of file
diff --git a/common/php/class-module.php b/common/php/class-module.php
index c19034913..7824f7ff9 100755
--- a/common/php/class-module.php
+++ b/common/php/class-module.php
@@ -186,42 +186,7 @@ function filter_posts_link( $slug, $post_type = 'post' ) {
$filter_link = add_query_arg( 'post_type', $post_type, $filter_link );
return $filter_link;
}
-
- /**
- * Returns the friendly name for a given status
- *
- * @since 0.7
- *
- * @param string $status The status slug
- * @return string $status_friendly_name The friendly name for the status
- */
- function get_post_status_friendly_name( $status ) {
- global $edit_flow;
-
- $status_friendly_name = '';
-
- $builtin_stati = array(
- 'publish' => __( 'Published', 'edit-flow' ),
- 'draft' => __( 'Draft', 'edit-flow' ),
- 'future' => __( 'Scheduled', 'edit-flow' ),
- 'private' => __( 'Private', 'edit-flow' ),
- 'pending' => __( 'Pending Review', 'edit-flow' ),
- 'trash' => __( 'Trash', 'edit-flow' ),
- );
-
- // Custom statuses only handles workflow statuses
- if ( $this->module_enabled( 'custom_status' )
- && !in_array( $status, array( 'publish', 'future', 'private', 'trash' ) ) ) {
- $status_object = $edit_flow->custom_status->get_custom_status_by( 'slug', $status );
- if( $status_object && !is_wp_error( $status_object ) ) {
- $status_friendly_name = $status_object->name;
- }
- } else if ( array_key_exists( $status, $builtin_stati ) ) {
- $status_friendly_name = $builtin_stati[$status];
- }
- return $status_friendly_name;
- }
-
+
/**
* Enqueue any resources (CSS or JS) associated with datepicker functionality
*
@@ -243,38 +208,7 @@ function enqueue_datepicker_resources() {
wp_enqueue_style( 'jquery-ui-theme', EDIT_FLOW_URL . 'common/css/jquery.ui.theme.css', false, EDIT_FLOW_VERSION, 'screen' );
}
- /**
- * Checks for the current post type
- *
- * @since 0.7
- * @return string|null $post_type The post type we've found, or null if no post type
- */
- function get_current_post_type() {
- global $post, $typenow, $pagenow, $current_screen;
- //get_post() needs a variable
- $post_id = isset( $_REQUEST['post'] ) ? (int)$_REQUEST['post'] : false;
-
- if ( $post && $post->post_type ) {
- $post_type = $post->post_type;
- } elseif ( $typenow ) {
- $post_type = $typenow;
- } elseif ( $current_screen && !empty( $current_screen->post_type ) ) {
- $post_type = $current_screen->post_type;
- } elseif ( isset( $_REQUEST['post_type'] ) ) {
- $post_type = sanitize_key( $_REQUEST['post_type'] );
- } elseif ( 'post.php' == $pagenow
- && $post_id
- && !empty( get_post( $post_id )->post_type ) ) {
- $post_type = get_post( $post_id )->post_type;
- } elseif ( 'edit.php' == $pagenow && empty( $_REQUEST['post_type'] ) ) {
- $post_type = 'post';
- } else {
- $post_type = null;
- }
- return $post_type;
- }
-
/**
* Wrapper for the get_user_meta() function so we can replace it if we need to
*
@@ -331,55 +265,6 @@ function print_ajax_response( $status, $message = '' ) {
exit;
}
- /**
- * Whether or not the current page is a user-facing Edit Flow View
- * @todo Think of a creative way to make this work
- *
- * @since 0.7
- *
- * @param string $module_name (Optional) Module name to check against
- */
- function is_whitelisted_functional_view( $module_name = null ) {
-
- // @todo complete this method
-
- return true;
- }
-
- /**
- * Whether or not the current page is an Edit Flow settings view (either main or module)
- * Determination is based on $pagenow, $_GET['page'], and the module's $settings_slug
- * If there's no module name specified, it will return true against all Edit Flow settings views
- *
- * @since 0.7
- *
- * @param string $module_name (Optional) Module name to check against
- * @return bool $is_settings_view Return true if it is
- */
- function is_whitelisted_settings_view( $module_name = null ) {
- global $pagenow, $edit_flow;
-
- // All of the settings views are based on admin.php and a $_GET['page'] parameter
- if ( $pagenow != 'admin.php' || !isset( $_GET['page'] ) )
- return false;
-
- // Load all of the modules that have a settings slug/ callback for the settings page
- foreach ( $edit_flow->modules as $mod_name => $mod_data ) {
- if ( isset( $mod_data->options->enabled ) && $mod_data->options->enabled == 'on' && $mod_data->configure_page_cb )
- $settings_view_slugs[] = $mod_data->settings_slug;
- }
-
- // The current page better be in the array of registered settings view slugs
- if ( !in_array( $_GET['page'], $settings_view_slugs ) )
- return false;
-
- if ( $module_name && $edit_flow->modules->$module_name->settings_slug != $_GET['page'] )
- return false;
-
- return true;
- }
-
-
/**
* This is a hack, Hack, HACK!!!
* Encode all of the given arguments as a serialized array, and then base64_encode
@@ -507,7 +392,11 @@ function users_select_form( $selected = null, $args = null ) {
ID, $selected) ) ? 'checked="checked"' : ''; ?>
@@ -604,6 +493,7 @@ function upgrade_074_term_descriptions( $taxonomy ) {
wp_update_term( $term->term_id, $taxonomy, array( 'description' => $new_description ) );
}
}
-
+
+
}
}
diff --git a/edit_flow.php b/edit_flow.php
index 57eb5639f..d8ed8c996 100644
--- a/edit_flow.php
+++ b/edit_flow.php
@@ -4,7 +4,7 @@
Plugin URI: http://editflow.org/
Description: Remixing the WordPress admin for better editorial workflow options.
Author: Daniel Bachhuber, Scott Bressler, Mohammad Jangda, Automattic, and others
-Version: 0.8.2
+Version: 0.8.3
Author URI: http://editflow.org/
Copyright 2009-2016 Mohammad Jangda, Daniel Bachhuber, et al.
@@ -28,7 +28,7 @@
*/
// Define contants
-define( 'EDIT_FLOW_VERSION' , '0.8.3-alpha' );
+define( 'EDIT_FLOW_VERSION' , '0.8.3' );
define( 'EDIT_FLOW_ROOT' , dirname(__FILE__) );
define( 'EDIT_FLOW_FILE_PATH' , EDIT_FLOW_ROOT . '/' . basename(__FILE__) );
define( 'EDIT_FLOW_URL' , plugins_url( '/', __FILE__ ) );
@@ -93,7 +93,14 @@ private function load_modules() {
// Edit Flow base module
require_once( EDIT_FLOW_ROOT . '/common/php/class-module.php' );
-
+
+ /*
+ * Include interfaces:
+ */
+ require_once( EDIT_FLOW_ROOT . '/interfaces/EF_Script_Interface.php' );
+ require_once( EDIT_FLOW_ROOT . '/interfaces/EF_Style_Interface.php' );
+ require_once( EDIT_FLOW_ROOT . '/common/php/class-module-with-view.php' );
+
// Scan the modules directory and include any modules that exist there
$module_dirs = scandir( EDIT_FLOW_ROOT . '/modules/' );
$class_names = array();
@@ -128,8 +135,12 @@ private function load_modules() {
}
}
- // Supplementary plugins can hook into this, include their own modules
- // and add them to the $edit_flow object
+ /**
+ * Fires after edit_flow has loaded all Edit Flow internal modules.
+ *
+ * Plugin authors can hook into this action, include their own modules add them to the $edit_flow object
+ *
+ */
do_action( 'ef_modules_loaded' );
}
@@ -147,6 +158,13 @@ private function setup_actions() {
add_action( 'admin_init', array( $this, 'action_admin_init' ) );
+ /**
+ * Fires after setup of all edit_flow actions.
+ *
+ * Plugin authors can hook into this action to manipulate the edit_flow class after initial actions have been registered.
+ *
+ * @param edit_flow $this The core edit flow class
+ */
do_action_ref_array( 'editflow_after_setup_actions', array( &$this ) );
}
@@ -169,6 +187,12 @@ function action_init() {
if ( isset( $mod_data->options->enabled ) && $mod_data->options->enabled == 'on' )
$this->$mod_name->init();
+ /**
+ * Fires after edit_flow has loaded all modules and module options.
+ *
+ * Plugin authors can hook into this action to trigger functionaltiy after all Edit Flow module's have been loaded.
+ *
+ */
do_action( 'ef_init' );
}
@@ -248,6 +272,14 @@ public function register_module( $name, $args = array() ) {
add_action( 'load-edit-flow_page_' . $args['settings_slug'], array( &$this->$name, 'action_settings_help_menu' ) );
$this->modules->$name = (object) $args;
+
+ /**
+ * Fires after edit_flow has registered a module.
+ *
+ * Plugin authors can hook into this action to trigger functionaltiy after a module has been loaded.
+ *
+ * @param string $name The name of the registered module
+ */
do_action( 'ef_module_registered', $name );
return $this->modules->$name;
}
@@ -268,6 +300,13 @@ function load_module_options() {
$this->$mod_name->module = $this->modules->$mod_name;
}
+
+ /**
+ * Fires after edit_flow has loaded all of the module options from the database.
+ *
+ * Plugin authors can hook into this action to read and manipulate module settings.
+ *
+ */
do_action( 'ef_module_options_loaded' );
}
@@ -288,6 +327,9 @@ function action_init_after() {
/**
* Get a module by one of its descriptive values
+ *
+ * @param string $key The property to use for searching a module (ex: 'name')
+ * @param string|int|array $value The value to compare (using ==)
*/
function get_module_by( $key, $value ) {
$module = false;
diff --git a/interfaces/EF_Script_Interface.php b/interfaces/EF_Script_Interface.php
new file mode 100644
index 000000000..0f9218be4
--- /dev/null
+++ b/interfaces/EF_Script_Interface.php
@@ -0,0 +1,9 @@
+create_post_cap = apply_filters( 'ef_calendar_create_post_cap', 'edit_posts' );
-
- require_once( EDIT_FLOW_ROOT . '/common/php/' . 'screen-options.php' );
- add_screen_options_panel( self::usermeta_key_prefix . 'screen_options', __( 'Calendar Options', 'edit-flow' ), array( $this, 'generate_screen_options' ), self::screen_id, false, true );
+
+ add_action( 'admin_init', array( $this, 'add_screen_options_panel' ) );
add_action( 'admin_init', array( $this, 'handle_save_screen_options' ) );
add_action( 'admin_init', array( $this, 'register_settings' ) );
- add_action( 'admin_menu', array( $this, 'action_admin_menu' ) );
- add_action( 'admin_print_styles', array( $this, 'add_admin_styles' ) );
+ add_action( 'admin_menu', array( $this, 'action_admin_menu' ) );
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
// Ajax manipulation for the calendar
@@ -174,10 +173,11 @@ function action_admin_menu() {
*
* @uses wp_enqueue_style()
*/
- function add_admin_styles() {
- global $pagenow;
- // Only load calendar styles on the calendar page
- if ( $pagenow == 'index.php' && isset( $_GET['page'] ) && $_GET['page'] == 'calendar' )
+ public function enqueue_admin_styles() {
+ if ( ! $this->is_calendar_view() ) {
+ return;
+ }
+
wp_enqueue_style( 'edit-flow-calendar-css', $this->module_url . 'lib/calendar.css', false, EDIT_FLOW_VERSION );
}
@@ -189,9 +189,12 @@ function add_admin_styles() {
*/
function enqueue_admin_scripts() {
+ if ( ! $this->is_calendar_view() ) {
+ return;
+ }
+
$this->enqueue_datepicker_resources();
- if ( $this->is_whitelisted_functional_view() ) {
$js_libraries = array(
'jquery',
'jquery-ui-core',
@@ -199,6 +202,7 @@ function enqueue_admin_scripts() {
'jquery-ui-draggable',
'jquery-ui-droppable',
);
+
foreach( $js_libraries as $js_library ) {
wp_enqueue_script( $js_library );
}
@@ -206,7 +210,7 @@ function enqueue_admin_scripts() {
$ef_cal_js_params = array( 'can_add_posts' => current_user_can( $this->create_post_cap ) ? 'true' : 'false' );
wp_localize_script( 'edit-flow-calendar-js', 'ef_calendar_params', $ef_cal_js_params );
- }
+
}
@@ -244,6 +248,16 @@ function generate_screen_options() {
return $output;
}
+ /**
+ * Add module options to the screen panel
+ *
+ * @since 0.8.3
+ */
+ function add_screen_options_panel() {
+ require_once( EDIT_FLOW_ROOT . '/common/php/' . 'screen-options.php' );
+ add_screen_options_panel( self::usermeta_key_prefix . 'screen_options', __( 'Calendar Options', 'edit-flow' ), array( $this, 'generate_screen_options' ), self::screen_id, false, true );
+ }
+
/**
* Handle the request to save the screen options
*
@@ -385,7 +399,7 @@ function handle_ics_subscription() {
$start_date = self::ics_format_time( $post->post_date );
$end_date = self::ics_format_time( $post->post_date, 5 * MINUTE_IN_SECONDS );
$last_modified = self::ics_format_time( $post->post_modified );
-
+ $post_status_obj = get_post_status_object( get_post_status( $post->ID ) );
// Remove the convert chars and wptexturize filters from the title
remove_filter( 'the_title', 'convert_chars' );
remove_filter( 'the_title', 'wptexturize' );
@@ -393,7 +407,7 @@ function handle_ics_subscription() {
$formatted_post = array(
'BEGIN' => 'VEVENT',
'UID' => $post->guid,
- 'SUMMARY' => $this->do_ics_escaping( apply_filters( 'the_title', $post->post_title ) ) . ' - ' . $this->get_post_status_friendly_name( get_post_status( $post->ID ) ),
+ 'SUMMARY' => $this->do_ics_escaping( apply_filters( 'the_title', $post->post_title ) ) . ' - ' . $post_status_obj->label,
'DTSTART' => $start_date,
'DTEND' => $end_date,
'LAST-MODIFIED' => $last_modified,
@@ -782,10 +796,14 @@ function view_calendar() {
$this->hidden = 0;
if ( !empty( $week_posts[$week_single_date] ) ) {
- $week_posts[$week_single_date] = apply_filters( 'ef_calendar_posts_for_week', $week_posts[$week_single_date] );
+ $week_posts[$week_single_date] = apply_filters( 'ef_calendar_posts_for_week', $week_posts[$week_single_date], $week_single_date );
- foreach ( $week_posts[$week_single_date] as $num => $post ){
- echo $this->generate_post_li_html( $post, $week_single_date, $num );
+ foreach ( $week_posts[$week_single_date] as $num => $post ) {
+ $output = apply_filters( 'ef_pre_calendar_single_date_item_html', '', $this, $num, $post, $week_single_date );
+ if ( ! $output ) {
+ $output = $this->generate_post_li_html( $post, $week_single_date, $num );
+ }
+ echo $output;
}
}
@@ -856,6 +874,7 @@ function generate_post_li_html( $post, $post_date, $num = 0 ){
ob_start();
$post_id = $post->ID;
$edit_post_link = get_edit_post_link( $post_id );
+ $status_object = get_post_status_object( get_post_status( $post_id ) );
$post_classes = array(
'day-item',
@@ -884,7 +903,7 @@ function generate_post_li_html( $post, $post_date, $num = 0 ){
-
get_post_status_friendly_name( get_post_status( $post_id ) ), 'edit-flow' ); ?>
+
label ); ?>
ID ) ); ?>
@@ -1213,17 +1232,17 @@ function get_calendar_posts_for_week( $args = array(), $context = 'dashboard' )
$args = array_merge( $defaults, $args );
- // Unpublished as a status is just an array of everything but 'publish'
- if ( $args['post_status'] == 'unpublish' ) {
+ // Unpublished as a status is just an array of everything but 'publish'.
+ if ( 'unpublish' == $args['post_status'] ) {
$args['post_status'] = '';
- $post_statuses = $this->get_post_statuses();
- foreach ( $post_statuses as $post_status ) {
- $args['post_status'] .= $post_status->slug . ', ';
+ $post_stati = get_post_stati();
+ unset($post_stati['inherit'], $post_stati['auto-draft'], $post_stati['trash'], $post_stati['publish'] );
+ if ( ! apply_filters( 'ef_show_scheduled_as_unpublished', false ) ) {
+ unset( $post_stati['future'] );
+ }
+ foreach ( $post_stati as $post_status ) {
+ $args['post_status'] .= $post_status . ', ';
}
- $args['post_status'] = rtrim( $args['post_status'], ', ' );
- // Optional filter to include scheduled content as unpublished
- if ( apply_filters( 'ef_show_scheduled_as_unpublished', false ) )
- $args['post_status'] .= ', future';
}
// The WP functions for printing the category and author assign a value of 0 to the default
// options, but passing this to the query is bad (trashed and auto-draft posts appear!), so
@@ -1296,23 +1315,23 @@ function get_pagination_link( $direction = 'next', $filters = array(), $weeks_of
/**
* Given a day in string format, returns the day at the beginning of that week, which can be the given date.
- * The end of the week is determined by the blog option, 'start_of_week'.
+ * The beginning of the week is determined by the blog option, 'start_of_week'.
*
* @see http://www.php.net/manual/en/datetime.formats.date.php for valid date formats
*
* @param string $date String representing a date
- * @param string $format Date format in which the end of the week should be returned
+ * @param string $format Date format in which the beginning of the week should be returned
* @param int $week Number of weeks we're offsetting the range
- * @return string $formatted_start_of_week End of the week
+ * @return string $formatted_start_of_week Beginning of the week
*/
function get_beginning_of_week( $date, $format = 'Y-m-d', $week = 1 ) {
$date = strtotime( $date );
$start_of_week = get_option( 'start_of_week' );
$day_of_week = date( 'w', $date );
- $date += (( $start_of_week - $day_of_week - 7 ) % 7) * 60 * 60 * 24 * $week;
- $additional = 3600 * 24 * 7 * ( $week - 1 );
- $formatted_start_of_week = date( $format, $date + $additional );
+ $date += (( $start_of_week - $day_of_week - 7 ) % 7) * 60 * 60 * 24 ;
+ $date = strtotime ( '+' . ( $week - 1 ) . ' week', $date ) ;
+ $formatted_start_of_week = date( $format, $date );
return $formatted_start_of_week;
}
@@ -1334,8 +1353,8 @@ function get_ending_of_week( $date, $format = 'Y-m-d', $week = 1 ) {
$end_of_week = get_option( 'start_of_week' ) - 1;
$day_of_week = date( 'w', $date );
$date += (( $end_of_week - $day_of_week + 7 ) % 7) * 60 * 60 * 24;
- $additional = 3600 * 24 * 7 * ( $week - 1 );
- $formatted_end_of_week = date( $format, $date + $additional );
+ $date = strtotime ( '+' . ( $week - 1 ) . ' week', $date ) ;
+ $formatted_end_of_week = date( $format, $date );
return $formatted_end_of_week;
}
@@ -1683,10 +1702,9 @@ function sanitize_filter( $key, $dirty_value ) {
switch( $key ) {
case 'post_status':
// Whitelist-based validation for this parameter
- $valid_statuses = wp_list_pluck( $this->get_post_statuses(), 'slug' );
- $valid_statuses[] = 'future';
+ $valid_statuses = get_post_stati();
$valid_statuses[] = 'unpublish';
- $valid_statuses[] = 'publish';
+ unset( $valid_statuses['inherit'], $valid_statuses['auto-draft'], $valid_statuses['trash'] );
if ( in_array( $dirty_value, $valid_statuses ) )
return $dirty_value;
else
@@ -1716,18 +1734,19 @@ function sanitize_filter( $key, $dirty_value ) {
function calendar_filter_options( $select_id, $select_name, $filters ) {
switch( $select_id ){
case 'post_status':
- $post_statuses = $this->get_post_statuses();
+ $post_stati = get_post_stati();
+ unset( $post_stati['inherit'], $post_stati['auto-draft'], $post_stati['trash'] );
?>
disable_custom_statuses_for_post_type() )
+ if ( ! $this->is_custom_status_view() )
return;
// Register new taxonomy so that we can store all our fancy new custom statuses (or is it stati?)
@@ -254,70 +257,13 @@ function register_custom_statuses() {
}
}
- /**
- * Whether custom post statuses should be disabled for this post type.
- * Used to stop custom statuses from being registered for post types that don't support them.
- *
- * @since 0.7.5
- *
- * @return bool
- */
- function disable_custom_statuses_for_post_type( $post_type = null ) {
- global $pagenow;
-
- // Only allow deregistering on 'edit.php' and 'post.php'
- if ( ! in_array( $pagenow, array( 'edit.php', 'post.php', 'post-new.php' ) ) )
- return false;
-
- if ( is_null( $post_type ) )
- $post_type = $this->get_current_post_type();
-
- if ( $post_type && ! in_array( $post_type, $this->get_post_types_for_module( $this->module ) ) )
- return true;
-
- return false;
- }
-
- /**
- * Enqueue Javascript resources that we need in the admin:
- * - Primary use of Javascript is to manipulate the post status dropdown on Edit Post and Manage Posts
- * - jQuery Sortable plugin is used for drag and dropping custom statuses
- * - We have other custom code for Quick Edit and JS niceties
- */
- function action_admin_enqueue_scripts() {
- global $pagenow;
-
- if ( $this->disable_custom_statuses_for_post_type() )
- return;
-
- // Load Javascript we need to use on the configuration views (jQuery Sortable and Quick Edit)
- if ( $this->is_whitelisted_settings_view( $this->module->name ) ) {
- wp_enqueue_script( 'jquery-ui-sortable' );
- wp_enqueue_script( 'edit-flow-custom-status-configure', $this->module_url . 'lib/custom-status-configure.js', array( 'jquery', 'jquery-ui-sortable', 'edit-flow-settings-js' ), EDIT_FLOW_VERSION, true );
- }
-
- // Custom javascript to modify the post status dropdown where it shows up
- if ( $this->is_whitelisted_page() ) {
- wp_enqueue_script( 'edit_flow-custom_status', $this->module_url . 'lib/custom-status.js', array( 'jquery','post' ), EDIT_FLOW_VERSION, true );
- wp_enqueue_style( 'edit_flow-custom_status', $this->module_url . 'lib/custom-status.css', false, EDIT_FLOW_VERSION, 'all' );
- wp_localize_script('edit_flow-custom_status', '__ef_localize_custom_status', array(
- 'no_change' => esc_html__( "— No Change —", 'edit-flow' ),
- 'published' => esc_html__( 'Published', 'edit-flow' ),
- 'save_as' => esc_html__( 'Save as', 'edit-flow' ),
- 'save' => esc_html__( 'Save', 'edit-flow' ),
- 'edit' => esc_html__( 'Edit', 'edit-flow' ),
- 'ok' => esc_html__( 'OK', 'edit-flow' ),
- 'cancel' => esc_html__( 'Cancel', 'edit-flow' ),
- ));
- }
- }
/**
* Displays a notice to users if they have JS disabled
* Javascript is needed for custom statuses to be fully functional
*/
function no_js_notice() {
- if( $this->is_whitelisted_page() ) :
+ if( $this->is_custom_status_view() ) :
?>
get_post_statuses();
- foreach ( $post_statuses as $post_status ) {
- $args['post_status'] .= $post_status->slug . ', ';
+ $post_stati = get_post_stati();
+ unset( $post_stati['inherit'], $post_stati['auto-draft'], $post_stati['trash'], $post_stati['publish'] );
+ if ( ! apply_filters( 'ef_show_scheduled_as_unpublished', false ) ) {
+ unset( $post_stati['future'] );
+ }
+ foreach ( $post_stati as $post_status ) {
+ $args['post_status'] .= $post_status . ', ';
}
- $args['post_status'] = rtrim( $args['post_status'], ', ' );
- // Optional filter to include scheduled content as unpublished
- if ( apply_filters( 'ef_show_scheduled_as_unpublished', false ) )
- $args['post_status'] .= ', future';
}
-
+
// Filter by post_author if it's set
if ( $args['author'] === '0' ) unset( $args['author'] );
@@ -497,8 +512,8 @@ function term_column_default( $post, $column_name, $parent_term ) {
switch( $column_name ) {
case 'status':
- $status_name = $this->get_post_status_friendly_name( $post->post_status );
- return $status_name;
+ $status_name = get_post_status_object( $post->post_status );
+ return $status_name->label;
break;
case 'author':
$post_author = get_userdata( $post->post_author );
@@ -510,8 +525,7 @@ function term_column_default( $post, $column_name, $parent_term ) {
return $output;
break;
case 'post_modified':
- $modified_time_gmt = strtotime( $post->post_modified_gmt . " GMT" );
- return $this->timesince( $modified_time_gmt );
+ return sprintf( esc_html__( '%s ago', 'edit-flow' ), human_time_diff( get_the_time( 'U', $post->ID ), current_time( 'timestamp' ) ) );
break;
default:
break;
@@ -716,17 +730,18 @@ function story_budget_filters() {
function story_budget_filter_options( $select_id, $select_name, $filters ) {
switch( $select_id ) {
case 'post_status':
- $post_statuses = $this->get_post_statuses();
+ $post_stati = get_post_stati();
+ unset( $post_stati['inherit'], $post_stati['auto-draft'], $post_stati['trash'] );
?>
is_whitelisted_functional_view() || $this->is_whitelisted_settings_view( $this->module->name ) ) {
+
+ if ( $this->is_current_module_settings_view() ) {
wp_enqueue_script( 'jquery-listfilterizer' );
wp_enqueue_script( 'jquery-quicksearch' );
wp_enqueue_script( 'edit-flow-user-groups-js', $this->module_url . 'lib/user-groups.js', array( 'jquery', 'jquery-listfilterizer', 'jquery-quicksearch' ), EDIT_FLOW_VERSION, true );
- }
-
- if ( $this->is_whitelisted_settings_view( $this->module->name ) )
wp_enqueue_script( 'edit-flow-user-groups-configure-js', $this->module_url . 'lib/user-groups-configure.js', array( 'jquery' ), EDIT_FLOW_VERSION, true );
+ }
+
}
/**
* Enqueue necessary admin styles, but only on the proper pages
*
* @since 0.7
+ * @updated 0.8.3
*
* @uses wp_enqueue_style()
*/
function enqueue_admin_styles() {
-
- if ( $this->is_whitelisted_functional_view() || $this->is_whitelisted_settings_view() ) {
+ if ( $this->is_current_module_settings_view() ) {
wp_enqueue_style( 'jquery-listfilterizer' );
wp_enqueue_style( 'edit-flow-user-groups-css', $this->module_url . 'lib/user-groups.css', false, EDIT_FLOW_VERSION );
}
@@ -844,6 +844,9 @@ function get_usergroup_by( $field, $value ) {
$usergroup->$key = $value;
}
}
+
+ $usergroup = apply_filters( 'ef_usergroup_object', $usergroup );
+
return $usergroup;
}
@@ -1067,7 +1070,8 @@ function get_usergroups_for_user( $user_id_or_login, $ids_or_objects = 'ids' ) {
return false;
}
}
-
+
+
}
}
diff --git a/readme.txt b/readme.txt
index 26ab4367e..ee998ea72 100644
--- a/readme.txt
+++ b/readme.txt
@@ -3,8 +3,8 @@ Contributors: batmoo, danielbachhuber, sbressler, automattic
Donate link: http://editflow.org/contribute/
Tags: edit flow, workflow, editorial, newsroom, management, journalism, post status, custom status, notifications, email, comments, editorial comments, usergroups, calendars, editorial calendar, story budget
Requires at least: 4.5
-Tested up to: 4.8
-Stable tag: 0.8.2
+Tested up to: 4.9.6
+Stable tag: 0.8.3
Redefining your editorial workflow.
@@ -56,6 +56,9 @@ For support questions, feedback and ideas, please use the [WordPress.org forums]
== Upgrade Notice ==
+= 0.8.3 =
+Improvements and bugfixes.
+
= 0.8.2 =
Minor enhancements and bug fixes, translation updates.
@@ -103,6 +106,29 @@ New features, including story budget and editorial metadata, a completely rewrit
== Changelog ==
+= 0.8.3 (June 14, 2018) =
+* UI Improvement: Made primary buttons on Settings screen consistent with WordPress UI. Props [cojennin](https://github.com/cojennin).
+* UI Improvement: Display who particularly was notified about an editorial comment. Props [goodguyry](https://github.com/goodguyry), [WPprodigy](https://github.com/WPprodigy)
+* Improvement: Updated Russian translation and documentation. Props [achumakov](https://github.com/achumakov).
+* Improvement: Eliminate a few cases of raw SQL queries in favor of `date_query`. Props [justnorris](https://github.com/justnorris).
+* Improvement: Cache calendar items for each user individually to prevent potential cache pollution. Props [justnorris](https://github.com/justnorris).
+* Improvement: various i18n updates.
+* Improvement: Move ef_story_budget_posts_query_args filter down to allow overriding the date query in Story Budget module.
+* Improvement: Limit results in Calendar to 200 per page, potentially saving from trouble on websites with large amount of content.
+* Improvement: Don’t generate rewrite rules for notepad as they're unused.
+* Improvement: Support modifying HTML output of a Calendar day via ef_pre_calendar_single_date_item_html filter. Props [cklosowski](https://github.com/cklosowski).
+
+* Improvement: show custom post statuses in Calendar and Story Budget. Props [mikeyarce](https://github.com/mikeyarce)
+* WordPress Coding Standards improvements and code cleanup by many unsung heroes (primarily [justnorris](https://github.com/justnorris)).
+* Bug fix: Prevent user from removing "Draft" post status, breaking the auto-draft functionality.
+* Bug fix: Fix ef_pre_insert_editorial_comment filter so that it actually has meaning. Props [sudar](https://github.com/sudar).
+* Bug fix: Fix PHP Warning: array_map(): Argument #2 should be an array. Props Michael Auteri.
+* Bug fix: Always offset post times to UTC+0 for Calendars to prevent incorrect times when adding to iCalendar/Google Calendar. Props [justnorris](https://github.com/justnorris).
+* Bug fix: Use taxonomy when checking for term existence when trying to prevent term collision. Props [shadyvb](https://github.com/shadyvb).
+* Bug fix: Correctly handle screen options update for Story Budget columns. Props [raduconst](https://github.com/raduconst)
+* Bug fix: EF_Calendar::get_beginning_of_week and EF_Calendar::get_ending_of_week should respect DST now. Props [FewKinG](https://github.com/FewKinG)
+* Bug fix: Build home_url() previews with trailing slash. Props [jeremyfelt](https://github.com/jeremyfelt)
+
= 0.8.2 (Sept 16, 2016) =
* Improvement: Updated Spanish localization thanks to [moucho](https://github.com/moucho)
* Improvement: New Swedish localization thanks to [Warpsmith](https://github.com/Warpsmith)
diff --git a/vipgo-helper.php b/vipgo-helper.php
index 77ad84fad..be0166473 100644
--- a/vipgo-helper.php
+++ b/vipgo-helper.php
@@ -4,6 +4,16 @@
*/
add_action( 'after_setup_theme', 'EditFlow' );
+/**
+ * Caps don't get loaded on install on VIP Go. Instead, let's add
+ * them via filters.
+ */
+add_filter( 'ef_kill_add_caps_to_role', '__return_true' );
+add_filter( 'ef_view_calendar_cap', function() {return 'edit_posts'; } );
+add_filter( 'ef_view_story_budget_cap', function() { return 'edit_posts'; } );
+add_filter( 'ef_edit_post_subscriptions_cap', function() { return 'edit_others_posts'; } );
+add_filter( 'ef_manage_usergroups_cap', function() { return 'manage_options'; } );
+
/**
* Edit Flow loads modules after plugins_loaded, which has already been fired when loading via wpcom_vip_load_plugins
* Let's run the method at after_setup_themes