diff --git a/common/php/class-module.php b/common/php/class-module.php index 7e5cf723..cadb1b72 100644 --- a/common/php/class-module.php +++ b/common/php/class-module.php @@ -15,6 +15,10 @@ class EF_Module { 'private', ); + public $module_url; + + public $module; + function __construct() {} /** @@ -437,7 +441,7 @@ function timesince( $original ) { } } - return sprintf( _n( "1 $name ago", "$count ${name}s ago", $count), $count); + return sprintf( _n( "1 $name ago", "$count {$name}s ago", $count), $count); } /** diff --git a/edit_flow.php b/edit_flow.php index cfa7ed8a..77adf6a9 100644 --- a/edit_flow.php +++ b/edit_flow.php @@ -53,6 +53,7 @@ function _ef_print_php_version_admin_notice() { define( 'EDIT_FLOW_SETTINGS_PAGE' , add_query_arg( 'page', 'ef-settings', get_admin_url( null, 'admin.php' ) ) ); // Core class +#[\AllowDynamicProperties] class edit_flow { // Unique identified added as a prefix to all options @@ -64,6 +65,25 @@ class edit_flow { */ private static $instance; + /** + * Active modules. + * + * @var \stdClass + */ + public $modules; + + /** + * Number of active modules. + * + * @var int + */ + public $modules_count; + + /** + * @var EF_Module + */ + public $helpers; + /** * Main EditFlow Instance * diff --git a/modules/calendar/calendar.php b/modules/calendar/calendar.php index 8f9dc226..2d20b016 100644 --- a/modules/calendar/calendar.php +++ b/modules/calendar/calendar.php @@ -8,12 +8,12 @@ if ( !class_exists('EF_Calendar') ) { class EF_Calendar extends EF_Module { - + const usermeta_key_prefix = 'ef_calendar_'; const screen_id = 'dashboard_page_calendar'; - + var $module; - + var $start_date = ''; var $current_week = 1; var $total_weeks = 6; // default number of weeks to show per screen @@ -22,9 +22,11 @@ class EF_Calendar extends EF_Module { private $post_date_cache = array(); private static $post_li_html_cache_key = 'ef_calendar_post_li_html'; + private int $max_weeks; + private string $create_post_cap; /** - * Calendar published statuses are the same as other + * Calendar published statuses are the same as other * components but without the future */ public $published_statuses = array( @@ -37,7 +39,7 @@ class EF_Calendar extends EF_Module { */ function __construct() { $this->max_weeks = 12; - + $this->module_url = $this->get_module_url( __FILE__ ); // Register the module with Edit Flow $args = array( @@ -73,17 +75,17 @@ function __construct() { ), 'settings_help_sidebar' => __( '

For more information:

Calendar Documentation

Edit Flow Forum

Edit Flow on Github

', 'edit-flow' ), ); - $this->module = EditFlow()->register_module( 'calendar', $args ); - + $this->module = EditFlow()->register_module( 'calendar', $args ); + } - + /** * Initialize all of our methods and such. Only runs if the module is active * * @uses add_action() */ function init() { - + // .ics calendar subscriptions add_action( 'wp_ajax_ef_calendar_ics_subscription', array( $this, 'handle_ics_subscription' ) ); add_action( 'wp_ajax_nopriv_ef_calendar_ics_subscription', array( $this, 'handle_ics_subscription' ) ); @@ -98,15 +100,15 @@ function init() { 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_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) ); - + // Ajax manipulation for the calendar add_action( 'wp_ajax_ef_calendar_drag_and_drop', array( $this, 'handle_ajax_drag_and_drop' ) ); - + // Ajax insert post placeholder for a specific date add_action( 'wp_ajax_ef_insert_post', array( $this, 'handle_ajax_insert_post' ) ); @@ -123,7 +125,7 @@ function init() { add_action( 'pre_post_update', array( $this, 'fix_post_date_on_update_part_one' ), 10, 2 ); add_action( 'post_updated', array( $this, 'fix_post_date_on_update_part_two' ), 10, 3 ); } - + /** * Load the capabilities onto users the first time the module is run * @@ -166,18 +168,18 @@ function upgrade( $previous_version ) { // Technically we've run this code before so we don't want to auto-install new data $edit_flow->update_module_option( $this->module->name, 'loaded_once', true ); } - + } - + /** * Add the calendar link underneath the "Dashboard" * * @uses add_submenu_page */ - function action_admin_menu() { + function action_admin_menu() { add_submenu_page('index.php', __('Calendar', 'edit-flow'), __('Calendar', 'edit-flow'), apply_filters( 'ef_view_calendar_cap', 'ef_view_calendar' ), $this->module->slug, array( $this, 'view_calendar' ) ); } - + /** * Add any necessary CSS to the WordPress admin * @@ -191,7 +193,7 @@ function add_admin_styles() { wp_enqueue_style( 'edit-flow-calendar-react-css', $this->module_url . 'lib/dist/calendar.react.style.build.css', array( 'wp-components' ), EDIT_FLOW_VERSION ); } } - + /** * Add any necessary JS to the WordPress admin * @@ -200,7 +202,7 @@ function add_admin_styles() { */ function enqueue_admin_scripts() { global $pagenow; - + if ( 'index.php' === $pagenow && isset( $_GET['page'] ) && 'calendar' === $_GET['page'] ) { $this->enqueue_datepicker_resources(); @@ -216,7 +218,7 @@ function enqueue_admin_scripts() { wp_enqueue_script( $js_library ); } wp_enqueue_script( 'edit-flow-calendar-js', $this->module_url . 'lib/calendar.js', $js_libraries, EDIT_FLOW_VERSION, true ); - + $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 ); @@ -224,25 +226,25 @@ function enqueue_admin_scripts() { * Powering the new React interface */ wp_enqueue_script( 'edit-flow-calendar-react-js', $this->module_url . 'lib/dist/calendar.react.build.js', array( 'react', 'react-dom', 'wp-components', 'wp-url', 'wp-data', 'moment' ), EDIT_FLOW_VERSION, true ); - + wp_add_inline_script( 'edit-flow-calendar-react-js', 'var EF_CALENDAR = ' . wp_json_encode( $this->get_calendar_frontend_config() ), 'before' ); } - + } - + /** * Prepare the options that need to appear in Screen Options * * @since 0.7 - */ + */ function generate_screen_options() { - + $output = ''; - + $args = array( 'action' => 'ef_calendar_ics_subscription', 'user' => wp_get_current_user()->user_login, @@ -252,10 +254,10 @@ function generate_screen_options() { $output .= '
'; $output .= __( 'Subscribe in iCal or Google Calendar', 'edit-flow' ); $output .= ':
'; - - return $output; + + return $output; } - + /** * Add module options to the screen panel * @@ -264,40 +266,40 @@ function generate_screen_options() { function add_screen_options_panel() { require_once( EDIT_FLOW_ROOT . '/common/php/' . 'screen-options.php' ); if ( 'on' == $this->module->options->ics_subscription && $this->module->options->ics_secret_key ) { - 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_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 * * @since 0.7 */ function handle_save_screen_options() { - + // Only handle screen options submissions from the current screen if ( ! isset( $_POST['screen-options-apply'] ) ) return; - + // Nonce check // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized if ( !isset( $_POST['_wpnonce-' . self::usermeta_key_prefix . 'screen_options'] ) || !wp_verify_nonce ( $_POST['_wpnonce-' . self::usermeta_key_prefix . 'screen_options'], 'save_settings-' . self::usermeta_key_prefix . 'screen_options' ) ) { wp_die( esc_html( $this->module->messages['nonce-failed'] ) ); } - + // Get the current screen options $screen_options = $this->get_screen_options(); - + // Save the screen options $current_user = wp_get_current_user(); $this->update_user_meta( $current_user->ID, self::usermeta_key_prefix . 'screen_options', $screen_options ); - + // Redirect after we're complete $redirect_to = menu_page_url( $this->module->slug, false ); wp_redirect( $redirect_to ); exit; } - + /** * Handle an AJAX request from the calendar to update a post's timestamp. * Notes: @@ -310,7 +312,7 @@ function handle_save_screen_options() { */ function handle_ajax_drag_and_drop() { global $wpdb; - + // Nonce check! if ( !isset( $_POST['nonce'] ) || !wp_verify_nonce( $_POST['nonce'], 'ef-calendar-modify' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $this->print_ajax_response( 'error', $this->module->messages['nonce-failed'] ); @@ -318,7 +320,7 @@ function handle_ajax_drag_and_drop() { if ( !isset( $_POST['post_id'] ) ) { $this->print_ajax_response( 'error', $this->module->messages['missing-post'] ); - } + } // Check that we got a proper post $post_id = (int) $_POST['post_id']; @@ -326,12 +328,12 @@ function handle_ajax_drag_and_drop() { if ( !$post ) { $this->print_ajax_response( 'error', $this->module->messages['missing-post'] ); } - + // Check that the user can modify the post if ( !$this->current_user_can_modify_post( $post ) ) { $this->print_ajax_response( 'error', $this->module->messages['invalid-permissions'] ); } - + // Check that it's not yet published if ( in_array( $post->post_status, $this->published_statuses ) ) { $this->print_ajax_response( 'error', sprintf( $this->module->messages['published-post-ajax'], get_edit_post_link( $post_id ) ) ); @@ -340,13 +342,13 @@ function handle_ajax_drag_and_drop() { if ( !isset( $_POST['next_date'] ) ) { $this->print_ajax_response( 'error', __( 'Missing new date.', 'edit-flow' ) ); } - + // Check that the new date passed is a valid one $next_date_full = strtotime( $_POST['next_date'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized if ( !$next_date_full ) { $this->print_ajax_response( 'error', __( 'Something is wrong with the format for the new date.', 'edit-flow' ) ); } - + // Persist the old hourstamp because we can't manipulate the exact time on the calendar // Bump the last modified timestamps too $existing_time = date( 'H:i:s', strtotime( $post->post_date ) ); @@ -356,24 +358,24 @@ function handle_ajax_drag_and_drop() { 'post_modified' => current_time( 'mysql' ), 'post_modified_gmt' => current_time( 'mysql', 1 ), ); - + // By default, changing a post on the calendar won't set the timestamp. // If the user desires that to be the behaviour, they can set the result of this filter to 'true' // With how WordPress works internally, setting 'post_date_gmt' will set the timestamp if ( apply_filters( 'ef_calendar_allow_ajax_to_set_timestamp', false ) ) { $new_values['post_date_gmt'] = date( 'Y-m-d', $next_date_full ) . ' ' . $existing_time_gmt; } - + // We have to do SQL unfortunately because of core bugginess // Note to those reading this: bug Nacin to allow us to finish the custom status API // See http://core.trac.wordpress.org/ticket/18362 $response = $wpdb->update( $wpdb->posts, $new_values, array( 'ID' => $post->ID ) ); clean_post_cache( $post->ID ); - + if ( !$response ) { $this->print_ajax_response( 'error', $this->module->messages['update-error'] ); } - + $this->print_ajax_response( 'success', $this->module->messages['post-date-updated'] ); exit; } @@ -583,7 +585,7 @@ public function handle_regenerate_calendar_feed_secret() { wp_safe_redirect( add_query_arg( 'message', 'key-regenerated', menu_page_url( $this->module->settings_slug, false ) ) ); exit; } - + /** * Get a user's screen options * @@ -593,7 +595,7 @@ public function handle_regenerate_calendar_feed_secret() { * @return array $screen_options The screen options values */ function get_screen_options() { - + /** * `num_weeks` has been moved to a filter and out of screen options, it's maintained here for legacy purposes * @deprecated `num_weeks` @@ -604,21 +606,21 @@ function get_screen_options() { $current_user = wp_get_current_user(); $screen_options = $this->get_user_meta( $current_user->ID, self::usermeta_key_prefix . 'screen_options', true ); $screen_options = array_merge( (array)$defaults, (array)$screen_options ); - + return $screen_options; } - + /** * Get the user's filters for calendar, either with $_GET or from saved * * @uses get_user_meta() * @return array $filters All of the set or saved calendar filters */ - function get_filters() { + function get_filters() { $current_user = wp_get_current_user(); $filters = array(); $old_filters = $this->get_user_meta( $current_user->ID, self::usermeta_key_prefix . 'filters', true ); - + /** * To support legacy screen option for num_weeks */ @@ -633,7 +635,7 @@ function get_filters() { 'start_date' => date( 'Y-m-d', current_time( 'timestamp' ) ), ); $old_filters = array_merge( $default_filters, isset( $screen_options['num_weeks'] ) ? array( 'num_weeks' => $screen_options['num_weeks'] ) : array(), (array)$old_filters ); - + // Sanitize and validate any newly added filters foreach( $old_filters as $key => $old_value ) { if ( isset( $_GET[$key] ) && false !== ( $new_value = $this->sanitize_filter( $key, $_GET[$key] ) ) ) @@ -646,19 +648,16 @@ function get_filters() { $filters['start_date'] = $this->get_beginning_of_week( $filters['start_date'] ); $filters = apply_filters( 'ef_calendar_filter_values', $filters, $old_filters ); - + $this->update_user_meta( $current_user->ID, self::usermeta_key_prefix . 'filters', $filters ); - + return $filters; } - + /** * Build all of the HTML for the calendar view */ function view_calendar() { - - $this->dropdown_taxonomies = array(); - $supported_post_types = $this->get_post_types_for_module( $this->module ); // Get filters either from $_GET or from user settings @@ -667,13 +666,13 @@ function view_calendar() { // Total number of weeks to display on the calendar. Run it through a filter in case we want to override the // user's standard $this->total_weeks = apply_filters( 'ef_calendar_total_weeks', $filters['num_weeks'], 'dashboard' ); - + $dotw = array( 'Sat', 'Sun', ); $dotw = apply_filters( 'ef_calendar_weekend_days', $dotw ); - + // For generating the WP Query objects later on $post_query_args = array( 'post_status' => $filters['post_status'], @@ -682,7 +681,7 @@ function view_calendar() { 'author' => $filters['author'] ); $this->start_date = $filters['start_date']; - + // We use this later to label posts if they need labeling if ( count( $supported_post_types ) > 1 ) { $all_post_types = get_post_types( null, 'objects' ); @@ -693,7 +692,7 @@ function view_calendar() { $dates[$i] = $heading_date; $heading_date = date( 'Y-m-d', strtotime( "+1 day", strtotime( $heading_date ) ) ); } - + // we sort by post statuses....... eventually $post_statuses = $this->get_calendar_post_stati(); ?> @@ -737,17 +736,17 @@ function view_calendar() { $table_classes[] = 'two-weeks-showing'; elseif ( $this->total_weeks == 3 ) $table_classes[] = 'three-weeks-showing'; - + $table_classes = apply_filters( 'ef_calendar_table_classes', $table_classes ); ?> - get_time_period_header( $dates ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> + get_time_period_header( $dates ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> - + total_weeks; $current_week++ ): @@ -766,7 +765,7 @@ function view_calendar() { $current_month = $single_date_month; } $week_single_date = date( 'Y-m-d', strtotime( "+1 day", strtotime( $week_single_date ) ) ); - } + } ?> @@ -802,26 +801,26 @@ function view_calendar() { unset( $week_posts[$week_single_date] ); foreach( $week_posts_by_status as $status ) { foreach( $status as $num => $post ) { - $week_posts[$week_single_date][] = $post; + $week_posts[$week_single_date][] = $post; } } } - + $td_classes = array( 'day-unit', ); $day_name = date( 'D', strtotime( $week_single_date ) ); - + if ( in_array( $day_name, $dotw ) ) $td_classes[] = 'weekend-day'; - + if ( $week_single_date == date( 'Y-m-d', current_time( 'timestamp' ) ) ) $td_classes[] = 'today'; - + // Last day of the week if ( $day_num == 6 ) $td_classes[] = 'last-day'; - + $td_classes = apply_filters( 'ef_calendar_table_td_classes', $td_classes, $week_single_date ); ?> - + - - + +
@@ -843,9 +842,9 @@ function view_calendar() { $output = $this->generate_post_li_html( $post, $week_single_date, $num ); } echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - } + } - } + } ?> hidden ): ?> @@ -858,14 +857,14 @@ function view_calendar() {
-

get_quick_create_post_type_name(), $date_formatted ) ); ?>

+

get_quick_create_post_type_name(), $date_formatted ) ); ?>

-
+
get_quick_create_post_type_name() ) ); ?> » -
+
 
@@ -873,22 +872,22 @@ function view_calendar() {
- +
- 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', 'custom-status-' . $post->post_status, @@ -924,10 +923,10 @@ function generate_post_li_html( $post, $post_date, $num = 0 ){ // This is checked on the ajax request too. if ( $this->current_user_can_modify_post( $post ) && !in_array( $post->post_status, $this->published_statuses ) ) $post_classes[] = 'sortable'; - + if ( in_array( $post->post_status, $this->published_statuses ) ) $post_classes[] = 'is-published'; - + // Hide posts over a certain number to prevent clutter, unless user is only viewing 1 or 2 weeks $max_visible_posts = apply_filters( 'ef_calendar_max_visible_posts_per_date', $this->max_visible_posts_per_date); @@ -936,7 +935,7 @@ function generate_post_li_html( $post, $post_date, $num = 0 ){ $this->hidden++; } $post_classes = apply_filters( 'ef_calendar_table_td_li_classes', $post_classes, $post_date, $post->ID ); - + ?>
  • @@ -975,9 +974,9 @@ function generate_post_li_html( $post, $post_date, $num = 0 ){ * has been separated out so various ajax functions can reload certain * parts of an inner html element. * @param array $ef_calendar_item_information_fields - * @param WP_Post $post - * @param array $published_statuses - * + * @param WP_Post $post + * @param array $published_statuses + * * @since 0.8 */ function get_inner_information( $ef_calendar_item_information_fields, $post ) { @@ -1054,12 +1053,12 @@ function get_editable_html( $type, $value ) { break; case 'checkbox': $output = ''; return $output; @@ -1164,7 +1163,7 @@ function get_post_information_fields( $post ) { if( current_user_can( $ed_cap, $post->ID ) ) $information_fields[$key]['editable'] = true; } - + $information_fields = apply_filters( 'ef_calendar_item_information_fields', $information_fields, $post->ID ); foreach( $information_fields as $field => $values ) { // Allow filters to hide empty fields or to hide any given individual field. Hide empty fields by default. @@ -1174,7 +1173,7 @@ function get_post_information_fields( $post ) { } return $information_fields; } - + /** * Generate the calendar header for a given range of dates * @@ -1182,18 +1181,18 @@ function get_post_information_fields( $post ) { * @return string $html Generated HTML for the header */ function get_time_period_header( $dates ) { - + $html = ''; foreach( $dates as $date ) { $html .= ''; $html .= esc_html( date_i18n('l', strtotime( $date ) ) ); $html .= ''; } - + return $html; - + } - + /** * Query to get all of the calendar posts for a given day * @@ -1202,7 +1201,7 @@ function get_time_period_header( $dates ) { * @return array $posts All of the posts as an array sorted by date */ function get_calendar_posts_for_week( $args = array(), $context = 'dashboard' ) { - + $supported_post_types = $this->get_post_types_for_module( $this->module ); $defaults = array( 'post_status' => null, @@ -1211,9 +1210,9 @@ function get_calendar_posts_for_week( $args = array(), $context = 'dashboard' ) 'post_type' => $supported_post_types, 'posts_per_page' => 200, ); - + $args = array_merge( $defaults, $args ); - + // Unpublished as a status is just an array of everything but 'publish'. if ( 'unpublish' == $args['post_status'] ) { $args['post_status'] = ''; @@ -1259,9 +1258,9 @@ function get_calendar_posts_for_week( $args = array(), $context = 'dashboard' ) $key_date = date( 'Y-m-d', strtotime( $post->post_date ) ); $posts[$key_date][] = $post; } - + return $posts; - + } /** @@ -1269,31 +1268,31 @@ function get_calendar_posts_for_week( $args = array(), $context = 'dashboard' ) * * @param string $direction 'previous' or 'next', direction to go in time * @param array $filters Any filters that need to be applied - * @param int $weeks_offset Number of weeks we're offsetting the range + * @param int $weeks_offset Number of weeks we're offsetting the range * @return string $url The URL for the next page */ function get_pagination_link( $direction = 'next', $filters = array(), $weeks_offset = null ) { $supported_post_types = $this->get_post_types_for_module( $this->module ); - + if ( !isset( $weeks_offset ) ) $weeks_offset = $this->total_weeks; else if ( $weeks_offset == 0 ) $filters['start_date'] = $this->get_beginning_of_week( date( 'Y-m-d', current_time( 'timestamp' ) ) ); - + if ( $direction == 'previous' ) $weeks_offset = '-' . $weeks_offset; - + $filters['start_date'] = date( 'Y-m-d', strtotime( $weeks_offset . " weeks", strtotime( $filters['start_date'] ) ) ); $url = add_query_arg( $filters, menu_page_url( $this->module->slug, false ) ); if ( count( $supported_post_types ) > 1 ) $url = add_query_arg( 'cpt', $filters['cpt'] , $url ); - + return $url; - + } - + /** * Given a day in string format, returns the day at the beginning of that week, which can be the given date. * The beginning of the week is determined by the blog option, 'start_of_week'. @@ -1302,7 +1301,7 @@ function get_pagination_link( $direction = 'next', $filters = array(), $weeks_of * * @param string $date String representing a date * @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 + * @param int $week Number of weeks we're offsetting the range * @return string $formatted_start_of_week Beginning of the week */ function get_beginning_of_week( $date, $format = 'Y-m-d', $week = 1 ) { @@ -1314,22 +1313,22 @@ function get_beginning_of_week( $date, $format = 'Y-m-d', $week = 1 ) { $date = strtotime ( '+' . ( $week - 1 ) . ' week', $date ) ; $formatted_start_of_week = date( $format, $date ); return $formatted_start_of_week; - + } - + /** * Given a day in string format, returns the day at the end of that week, which can be the given date. * The end 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 + * @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 int $week Number of weeks we're offsetting the range + * @param int $week Number of weeks we're offsetting the range * @return string $formatted_end_of_week End of the week */ function get_ending_of_week( $date, $format = 'Y-m-d', $week = 1 ) { - + $date = strtotime( $date ); $end_of_week = get_option( 'start_of_week' ) - 1; $day_of_week = date( 'w', $date ); @@ -1337,9 +1336,9 @@ function get_ending_of_week( $date, $format = 'Y-m-d', $week = 1 ) { $date = strtotime ( '+' . ( $week - 1 ) . ' week', $date ) ; $formatted_end_of_week = date( $format, $date ); return $formatted_end_of_week; - + } - + /** * Human-readable time range for the calendar * Shows something like "for October 30th through November 26th" for a four-week period @@ -1347,7 +1346,7 @@ function get_ending_of_week( $date, $format = 'Y-m-d', $week = 1 ) { * @since 0.7 */ function calendar_time_range() { - + $first_datetime = strtotime( $this->start_date ); $first_date = date_i18n( get_option( 'date_format' ), $first_datetime ); $total_days = ( $this->total_weeks * 7 ) - 1; @@ -1355,7 +1354,7 @@ function calendar_time_range() { $last_date = date_i18n( get_option( 'date_format' ), $last_datetime ); echo esc_html( sprintf( __( 'for %1$s through %2$s', 'edit-flow' ), $first_date, $last_date ) ); } - + /** * Check whether the current user should have the ability to modify the post * @@ -1365,10 +1364,10 @@ function calendar_time_range() { * @return bool $can Whether or not the current user can modify the post */ function current_user_can_modify_post( $post ) { - + if ( !$post ) return false; - + $post_type_object = get_post_type_object( $post->post_type ); // Editors and admins are fine @@ -1380,26 +1379,26 @@ function current_user_can_modify_post( $post ) { // Those who can publish posts can move any of their own stuff if ( current_user_can( $post_type_object->cap->publish_posts, $post->ID ) && wp_get_current_user()->ID == $post->post_author ) return true; - + return false; } - + /** * Register settings for notifications so we can partially use the Settings API * We use the Settings API for form generation, but not saving because we have our * own way of handling the data. - * + * * @since 0.7 */ function register_settings() { - + add_settings_section( $this->module->options_group_name . '_general', false, '__return_false', $this->module->options_group_name ); add_settings_field( 'post_types', __( 'Post types to show', 'edit-flow' ), array( $this, 'settings_post_types_option' ), $this->module->options_group_name, $this->module->options_group_name . '_general' ); add_settings_field( 'quick_create_post_type', __( 'Post type to create directly from calendar', 'edit-flow' ), array( $this, 'settings_quick_create_post_type_option' ), $this->module->options_group_name, $this->module->options_group_name . '_general' ); add_settings_field( 'ics_subscription', __( 'Subscription in iCal or Google Calendar', 'edit-flow' ), array( $this, 'settings_ics_subscription_option' ), $this->module->options_group_name, $this->module->options_group_name . '_general' ); } - + /** * Choose the post types that should be displayed on the calendar * @@ -1416,11 +1415,11 @@ function settings_post_types_option() { * @since 0.8 */ function settings_quick_create_post_type_option() { - + $allowed_post_types = $this->get_all_post_types(); echo ""; @@ -1475,7 +1474,7 @@ function settings_validate( $new_options ) { return $options; } - + /** * Settings page for calendar */ @@ -1484,8 +1483,8 @@ function print_configure_view() { ?>
    module->options_group_name ); ?> - module->options_group_name ); ?> - module->options_group_name ); ?> + module->name ) . '" />'; ?>

    @@ -1527,7 +1526,7 @@ function handle_ajax_insert_post() { $post_date = sanitize_text_field( $_POST['ef_insert_date'] ); $post_status = $this->get_default_post_status(); - + // Set new post parameters $post_placeholder = array( 'post_title' => $post_title, @@ -1563,7 +1562,7 @@ function handle_ajax_insert_post() { /** * Returns the singular label for the posts that are * quick-created on the calendar - * + * * @return str Singular label for a post-type */ function get_quick_create_post_type_name(){ @@ -1591,7 +1590,7 @@ function handle_ajax_update_metadata() { if ( !isset( $_POST['post_id'] ) ) { $this->print_ajax_response( 'error', $this->module->messages['missing-post'] ); } - + // Check that we got a proper post $post_id = ( int )$_POST['post_id']; $post = get_post( $post_id ); @@ -1606,8 +1605,8 @@ function handle_ajax_update_metadata() { $edit_check = 'edit_post'; if ( !current_user_can( $edit_check, $post->ID ) ) - $this->print_ajax_response( 'error', $this->module->messages['invalid-permissions'] ); - + $this->print_ajax_response( 'error', $this->module->messages['invalid-permissions'] ); + // Check that the user can modify the post if ( ! $this->current_user_can_modify_post( $post ) ) $this->print_ajax_response( 'error', $this->module->messages['invalid-permissions'] ); @@ -1620,8 +1619,8 @@ function handle_ajax_update_metadata() { $metadata_types = array(); if ( !$this->module_enabled( 'editorial_metadata' ) ) - $this->print_ajax_response( 'error', $this->module->messages['update-error'] ); - + $this->print_ajax_response( 'error', $this->module->messages['update-error'] ); + $metadata_types = array_keys( EditFlow()->editorial_metadata->get_supported_metadata_types() ); // Update an editorial metadata field @@ -1659,7 +1658,7 @@ function handle_ajax_update_metadata() { $this->print_ajax_response( 'error', __( 'Metadata could not be updated.', 'edit-flow' ) ); } - function calendar_filters() { + function calendar_filters() { $select_filter_names = array(); $select_filter_names['post_status'] = 'post_status'; @@ -1678,7 +1677,7 @@ function calendar_filters() { * * @param string $key Filter being sanitized * @param string $dirty_value Value to be sanitized - * @return string $sanitized_value Safe to use value + * @return string $sanitized_value Safe to use value */ function sanitize_filter( $key, $dirty_value ) { @@ -1734,14 +1733,14 @@ public function action_clean_li_html_cache( $post_id ) { /** * This is a hack! hack! hack! until core is fixed - * + * * The calendar uses 'post_date' field to store the position on the calendar * If a post has a core post status assigned (e.g. 'draft' or 'pending'), the `post_date` * field will be reset when `wp_update_post()` * is used: http://core.trac.wordpress.org/browser/tags/3.7.1/src/wp-includes/post.php#L2998 - * + * * This method temporarily caches the `post_date` field if it needs to be restored. - * + * * @uses fix_post_date_on_update_part_two() */ public function fix_post_date_on_update_part_one( $post_ID, $data ) { @@ -1761,14 +1760,14 @@ public function fix_post_date_on_update_part_one( $post_ID, $data ) { /** * This is a hack! hack! hack! until core is fixed - * + * * The calendar uses 'post_date' field to store the position on the calendar * If a post has a core post status assigned (e.g. 'draft' or 'pending'), the `post_date` * field will be reset when `wp_update_post()` * is used: http://core.trac.wordpress.org/browser/tags/3.7.1/src/wp-includes/post.php#L2998 - * + * * This method restores the `post_date` field if it needs to be restored. - * + * * @uses fix_post_date_on_update_part_one() */ public function fix_post_date_on_update_part_two( $post_ID, $post_after, $post_before ) { @@ -1785,13 +1784,13 @@ public function fix_post_date_on_update_part_two( $post_ID, $post_after, $post_b /** * Returns a list of custom status objects used by the calendar - * + * * @return array An array of StdClass objects representing statuses */ public function get_calendar_post_stati() { $post_stati = get_post_stati( array(), 'object' ); $custom_status_slugs = wp_list_pluck( $this->get_post_statuses(), 'slug' ); - $custom_status_slugs[] = 'future'; + $custom_status_slugs[] = 'future'; $custom_status_slugs[] = 'publish'; $custom_status_slug_keys = array_flip( $custom_status_slugs ); @@ -1838,18 +1837,18 @@ public function get_calendar_frontend_config() { $config = array( 'POST_STATI' => $this->get_calendar_post_stati(), - 'USERS' => array_map( + 'USERS' => array_map( function( $item ) { - return array( - 'id' => $item->ID, + return array( + 'id' => $item->ID, 'display_name' => $item->display_name, ); - }, - $this->get_calendar_users() + }, + $this->get_calendar_users() ), 'CATEGORIES' => $this->get_calendar_categories(), - 'POST_TYPES' => array_map( function ( $item ) use ( $all_post_types ) { - return $all_post_types[ $item ]; + 'POST_TYPES' => array_map( function ( $item ) use ( $all_post_types ) { + return $all_post_types[ $item ]; }, $this->get_post_types_for_module( $this->module ) ), 'NUM_WEEKS' => array( 'MAX' => $this->max_weeks, @@ -1863,7 +1862,7 @@ function( $item ) { return apply_filters( 'ef_calendar_frontend_config', $config ); } - + } // EF_Calendar - + } // class_exists('EF_Calendar') diff --git a/modules/story-budget/story-budget.php b/modules/story-budget/story-budget.php index c31ad321..ee524097 100644 --- a/modules/story-budget/story-budget.php +++ b/modules/story-budget/story-budget.php @@ -6,32 +6,34 @@ * @author sbressler */ class EF_Story_Budget extends EF_Module { - + var $taxonomy_used = 'category'; - + var $module; - + var $num_columns = 0; - + var $max_num_columns; - + var $no_matching_posts = true; - + var $terms = array(); - + var $user_filters; - + const screen_id = 'dashboard_page_story-budget'; - + const usermeta_key_prefix = 'ef_story_budget_'; - + const default_num_columns = 1; - + + private $term_columns; + /** * Register the module with Edit Flow but don't do anything else */ function __construct() { - + $this->module_url = $this->get_module_url( __FILE__ ); // Register the module with Edit Flow $args = array( @@ -48,18 +50,18 @@ function __construct() { 'autoload' => false, ); $this->module = EditFlow()->register_module( 'story_budget', $args ); - + } - + /** * Initialize the rest of the stuff in the class if the module is active */ function init() { - + $view_story_budget_cap = apply_filters( 'ef_view_story_budget_cap', 'ef_view_story_budget' ); if ( !current_user_can( $view_story_budget_cap ) ) return; - + $this->num_columns = $this->get_num_columns(); $this->max_num_columns = apply_filters( 'ef_story_budget_max_num_columns', 3 ); @@ -71,14 +73,14 @@ function init() { // Register the columns of data appearing on every term. This is hooked into admin_init // so other Edit Flow modules can register their filters if needed add_action( 'admin_init', array( $this, 'register_term_columns' ) ); - + add_action( 'admin_menu', array( $this, 'action_admin_menu' ) ); // Load necessary scripts and stylesheets add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'action_enqueue_admin_styles' ) ); - + } - + /** * Give users the appropriate permissions to view the story budget the first time the module is loaded * @@ -118,9 +120,9 @@ function upgrade( $previous_version ) { // Technically we've run this code before so we don't want to auto-install new data $edit_flow->update_module_option( $this->module->name, 'loaded_once', true ); } - + } - + /** * Include the story budget link in the admin menu. * @@ -129,7 +131,7 @@ function upgrade( $previous_version ) { function action_admin_menu() { add_submenu_page( 'index.php', __('Story Budget', 'edit-flow'), __('Story Budget', 'edit-flow'), apply_filters( 'ef_view_story_budget_cap', 'ef_view_story_budget' ), $this->module->slug, array( $this, 'story_budget') ); } - + /** * Enqueue necessary admin scripts only on the story budget page. * @@ -137,30 +139,30 @@ function action_admin_menu() { */ function enqueue_admin_scripts() { global $current_screen; - + if ( $current_screen->id != self::screen_id ) return; - + $num_columns = $this->get_num_columns(); echo ''; - + $this->enqueue_datepicker_resources(); wp_enqueue_script( 'edit_flow-story_budget', $this->module_url . 'lib/story-budget.js', array( 'edit_flow-date_picker' ), EDIT_FLOW_VERSION, true ); } - + /** * Enqueue a screen and print stylesheet for the story budget. */ function action_enqueue_admin_styles() { global $current_screen; - + if ( $current_screen->id != self::screen_id ) return; - + wp_enqueue_style( 'edit_flow-story_budget-styles', $this->module_url . 'lib/story-budget.css', false, EDIT_FLOW_VERSION, 'screen' ); wp_enqueue_style( 'edit_flow-story_budget-print-styles', $this->module_url . 'lib/story-budget-print.css', false, EDIT_FLOW_VERSION, 'print' ); } - + /** * Register the columns of information that appear for each term module. * Modeled after how WP_List_Table works, but focused on hooks instead of OOP extending @@ -168,7 +170,7 @@ function action_enqueue_admin_styles() { * @since 0.7 */ function register_term_columns() { - + $term_columns = array( 'title' => __( 'Title', 'edit-flow' ), 'status' => __( 'Status', 'edit-flow' ), @@ -176,32 +178,32 @@ function register_term_columns() { 'post_date' => __( 'Post Date', 'edit-flow' ), 'post_modified' => __( 'Last Modified', 'edit-flow' ), ); - + $term_columns = apply_filters( 'ef_story_budget_term_columns', $term_columns ); $this->term_columns = $term_columns; } - + /** * Handle a form submission to change the user's date range on the budget * * @since 0.7 */ function handle_form_date_range_change() { - + if ( ! isset( $_POST['ef-story-budget-range-submit'], $_POST['ef-story-budget-number-days'], $_POST['ef-story-budget-start-date_hidden'] ) ) { return; } - + if ( !wp_verify_nonce( $_POST['nonce'], 'change-date' ) ) wp_die( $this->module->messages['nonce-failed'] ); - + $current_user = wp_get_current_user(); $new_filters = array ( 'start_date' => $_POST['ef-story-budget-start-date_hidden'], 'number_days' => (int) $_POST['ef-story-budget-number-days'], ); $user_filters = $this->update_user_filters_from_form_date_range_change( $current_user, $new_filters ); - + $this->update_user_meta( $current_user->ID, self::usermeta_key_prefix . 'filters', $user_filters ); wp_redirect( menu_page_url( $this->module->slug, false ) ); exit; @@ -236,10 +238,10 @@ public function update_user_filters_from_form_date_range_change( $current_user, $existing_filters['number_days'] = $new_filters['number_days']; } } - + return $existing_filters; } - + /** * Get the number of columns to show on the story budget */ @@ -256,7 +258,7 @@ function get_num_columns() { } return $this->num_columns; } - + /** * Add module options to the screen panel * @@ -266,7 +268,7 @@ function add_screen_options_panel() { require_once( EDIT_FLOW_ROOT . '/common/php/' . 'screen-options.php' ); add_screen_options_panel( self::usermeta_key_prefix . 'screen_columns', __( 'Screen Layout', 'edit-flow' ), array( $this, 'print_column_prefs' ), self::screen_id, array( $this, 'save_column_prefs' ), true ); } - + /** * Print column number preferences for screen options */ @@ -277,7 +279,7 @@ function print_column_prefs() { } return $return_val; } - + /** * Save the current user's preference for number of columns. */ @@ -285,7 +287,7 @@ function save_column_prefs( $posted_fields ) { $key = self::usermeta_key_prefix . 'screen_columns'; $this->num_columns = (int) $posted_fields[ $key ]; - + $current_user = wp_get_current_user(); $this->update_user_meta( $current_user->ID, $key, $this->num_columns ); } @@ -299,7 +301,7 @@ function story_budget() { // Update the current user's filters with the variables set in $_GET $this->user_filters = $this->update_user_filters(); - + if ( !empty( $this->user_filters[$this->taxonomy_used] ) ) { $terms = array(); $terms[] = get_term( $this->user_filters[$this->taxonomy_used], $this->taxonomy_used ); @@ -314,7 +316,7 @@ function story_budget() { $terms = get_terms( $this->taxonomy_used, $args ); } $this->terms = apply_filters( 'ef_story_budget_filter_terms', $terms ); // allow for reordering or any other filtering of terms - + ?>
    @@ -347,7 +349,7 @@ function story_budget() {
    user_filters['number_days'] ); ?> - user_filters['number_days'], 'edit-flow' ) ); ?> + user_filters['number_days'], 'edit-flow' ) ); ?> @@ -371,7 +373,7 @@ function story_budget_time_range() { - null, 'author' => null, 'posts_per_page' => apply_filters( 'ef_story_budget_max_query', 200 ), - ); + ); $args = array_merge( $defaults, $args ); - + // Filter to the term and any children if it's hierarchical $arg_terms = array( $term->term_id, @@ -432,18 +434,18 @@ function get_posts_for_term( $term, $args = null ) { $args = apply_filters( 'ef_story_budget_posts_query_args', $args ); $term_posts_query_results = new WP_Query( $args ); - + $term_posts = array(); while ( $term_posts_query_results->have_posts() ) { $term_posts_query_results->the_post(); global $post; $term_posts[] = $post; } - + return $term_posts; } - + /** * Prints the stories in a single term in the story budget. * @@ -455,7 +457,7 @@ function print_term( $term ) { if ( !empty( $posts ) ) // Don't display the message for $no_matching_posts $this->no_matching_posts = false; - + ?>

    @@ -485,7 +487,7 @@ function print_term( $term ) {
    post_status ); @@ -548,9 +550,9 @@ function term_column_default( $post, $column_name, $parent_term ) { default: break; } - + } - + /** * Prepare the data for the title term column * @@ -558,14 +560,14 @@ function term_column_default( $post, $column_name, $parent_term ) { */ function term_column_title( $post, $parent_term ) { $post_title = _draft_or_post_title( $post->ID ); - + $post_type_object = get_post_type_object( $post->post_type ); $can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID ); if ( $can_edit_post ) - $output = '' . esc_html( $post_title ) . ''; + $output = '' . esc_html( $post_title ) . ''; else $output = '' . esc_html( $post_title ) . ''; - + // Edit or Trash or View $output .= '
    '; $item_actions = array(); @@ -593,20 +595,20 @@ function term_column_title( $post, $parent_term ) { return $output; } - + /** * Print any messages that should appear based on the action performed */ function print_messages() { ?> - +

    '; - + // Following mostly stolen from edit.php - + if ( isset( $_GET['trashed'] ) && (int) $_GET['trashed'] ) { printf( _n( 'Item moved to the trash.', '%d items moved to the trash.', $_GET['trashed'] ), number_format_i18n( $_GET['trashed'] ) ); $ids = isset($_GET['ids']) ? $_GET['ids'] : 0; @@ -618,11 +620,11 @@ function print_messages() { printf( _n( 'Item restored from the Trash.', '%d items restored from the Trash.', $_GET['untrashed'] ), number_format_i18n( $_GET['untrashed'] ) ); unset($_GET['undeleted']); } - + echo '

    '; } } - + /** * Print the table navigation and filter controls, using the current user's filters if any are set. */ @@ -632,9 +634,9 @@ function table_navigation() {
    - story_budget_filters() as $select_id => $select_name ) { - echo $this->story_budget_filter_options( $select_id, $select_name, $this->user_filters ); + echo $this->story_budget_filter_options( $select_id, $select_name, $this->user_filters ); } ?> @@ -644,7 +646,7 @@ function table_navigation() { - story_budget_filters() as $select_id => $select_name ) { echo ''; } @@ -652,16 +654,16 @@ function table_navigation() {
    - +
    - +
    $this->filter_get_param( 'post_status' ), 'cat' => $this->filter_get_param( 'cat' ), @@ -677,47 +679,47 @@ function update_user_filters() { 'start_date' => $this->filter_get_param( 'start_date' ), 'number_days' => $this->filter_get_param( 'number_days' ) ); - + $current_user_filters = array(); $current_user_filters = $this->get_user_meta( $current_user->ID, self::usermeta_key_prefix . 'filters', true ); - + // If any of the $_GET vars are missing, then use the current user filter foreach ( $user_filters as $key => $value ) { if ( is_null( $value ) && !empty( $current_user_filters[$key] ) ) { $user_filters[$key] = $current_user_filters[$key]; } } - + if ( !$user_filters['start_date'] ) $user_filters['start_date'] = date( 'Y-m-d' ); - + if ( !$user_filters['number_days'] ) $user_filters['number_days'] = 10; - + $user_filters = apply_filters('ef_story_budget_filter_values', $user_filters, $current_user_filters); $this->update_user_meta( $current_user->ID, self::usermeta_key_prefix . 'filters', $user_filters ); return $user_filters; } - + /** * Get the filters for the current user for the story budget display, or insert the default * filters if not already set. - * + * * @return array The filters for the current user, or the default filters if the current user has none. */ function get_user_filters() { - + $current_user = wp_get_current_user(); $user_filters = array(); $user_filters = $this->get_user_meta( $current_user->ID, self::usermeta_key_prefix . 'filters', true ); - + // If usermeta didn't have filters already, insert defaults into DB if ( empty( $user_filters ) ) $user_filters = $this->update_user_filters(); return $user_filters; } - + /** * * @param string $param The parameter to look for in $_GET @@ -731,7 +733,7 @@ function filter_get_param( $param ) { } else if ( empty( $_GET[$param] ) ) { return ''; } - + return sanitize_key( $_GET[$param] ); } @@ -747,13 +749,13 @@ function story_budget_filters() { function story_budget_filter_options( $select_id, $select_name, $filters ) { switch( $select_id ) { - case 'post_status': + case 'post_status': $post_stati = $this->get_budget_post_stati(); ?>