diff --git a/assets/js/admin/settings/conditionals.js b/assets/js/admin/settings/conditionals.js new file mode 100644 index 0000000..2a65011 --- /dev/null +++ b/assets/js/admin/settings/conditionals.js @@ -0,0 +1,223 @@ +/** + * Handles conditional loading of specific setting fields. + * + * @package SM + */ + +if ( typeof sm_conditionals !== 'undefined' ) { + // Bind to elements. + jQuery( + function () { + jQuery.each( + sm_conditionals, + function ( element_id, element_conditionals ) { + /** + * The element that should be shown or hidden. + * + * @type object + */ + let target_element = jQuery( '#' + element_id ); + + /** + * The element's table row. + * + * @type object + */ + let table_row = target_element.closest( 'tr' ); + + // Go through each conditional. + jQuery.each( + element_conditionals, + function ( index, condition_data ) { + /** + * The element's HTML ID & database ID. + */ + let conditional_element_id = condition_data.id; + + /** + * The element itself. + * + * @type object + */ + let conditional_element = jQuery( '#' + conditional_element_id ); + + /** + * The value that we are looking for in the element. + * + * @type string + */ + let target_value = sm_isset( condition_data[ "value" ] ) ? condition_data[ "value" ] : condition_data[ "!value" ]; + + /** + * If we should invert the value. + * + * @type boolean + */ + let not = sm_isset( condition_data[ "!value" ] ); + + // Hook into element's change event, so we can act on it. + conditional_element.on( + 'change', + function () { + /** + * Currently selected value. + * + * @type string + */ + let selected_value = this.value; + + // Hide or show the elements. + sm_hide_show_elements( target_value, selected_value, not, table_row ); + } + ); + + // Call the function first time. + sm_hide_show_elements( target_value, conditional_element.val(), not, table_row ); + } + ); + } + ); + } + ); +} + +/** + * Hides or shows the element based on its value. + * + * @param {string} target_value Value that we are looking for. + * @param {string} current_value The current value of the element. + * @param {boolean} not If we should invert the value. + * @param {object} table_row The table row to hide or show. + */ +function sm_hide_show_elements( target_value, current_value, not, table_row ) { + let element = table_row.find( 'select' ); + + /** + * If we should hide the row. + * + * @type {boolean} + */ + let hide = target_value !== current_value; + + /** + * If the element should get data via Ajax. + * + * @type boolean + */ + let is_ajax = element.data( 'ajax' ) ? element.data( 'ajax' ) : false; + + // Invert if needed. + hide = not ? ! hide : hide; + + // Do hide. + if ( ! is_ajax ) { + if ( hide ) { + table_row.addClass( 'hidden' ); + } else { + table_row.removeClass( 'hidden' ); + } + } + + // If we should get options via Ajax. + if ( is_ajax ) { + sm_reset_option_value( element, ! table_row.hasClass( 'hidden' ) ); + + let data = { + 'action': 'sm_settings_get_select_data', + 'id': current_value, + }; + + // Request element data. + jQuery.ajax( + { + method: 'POST', + url: ajaxurl, + data: data, + } + ).always( + function () { + sm_reset_option_value( element, ! table_row.hasClass( 'hidden' ) ); + } + ).done( + function ( response ) { + // Convert JSON to array/object. + if ( 'false' === response ) { + response = false; + } else { + try { + response = JSON.parse( response ); + } catch ( err ) { + response = false; + } + } + + // Write received values to element. + if ( typeof response === 'object' ) { + table_row.removeClass( 'hidden' ); + + switch ( element.prop( 'tagName' ) ) { + case 'SELECT': + element.find( 'option' ).each( + function () { + jQuery( this.remove() ); + } + ); + jQuery.each( + response, + function ( id, item ) { + table_row.find( 'select' ).append( jQuery( '' ).val( id ).text( item ) ); + } + ); + break; + } + } + + if ( false === response ) { + table_row.addClass( 'hidden' ); + } + } + ).fail( + function () { + // Write error message if response is invalid. + switch ( element.prop( 'tabName' ) ) { + case 'SELECT': + element.append( jQuery( '' ).val( '' ).text( 'Error.' ) ); + break; + } + } + ); + } +} + +/** + * Clears the current option value. + * + * @type {object} The option element. + * @type {boolean} If we should show that it's loading. + */ +function sm_reset_option_value( element, write_loading ) { + switch ( element.prop( 'tagName' ) ) { + case 'SELECT': + element.find( 'option' ).each( + function () { + jQuery( this.remove() ); + } + ); + } + if ( write_loading ) { + element.append( jQuery( '' ).val( '' ).text( 'Loading...' ) ); + } +} + +/** + * Checks to see if a value is set. + * + * @param {*} value The value to check. + */ +function sm_isset( value ) { + try { + return typeof value !== 'undefined' + } catch ( e ) { + return false + } +} diff --git a/assets/js/admin/settings/conditionals.min.js b/assets/js/admin/settings/conditionals.min.js new file mode 100644 index 0000000..8d2f9f4 --- /dev/null +++ b/assets/js/admin/settings/conditionals.min.js @@ -0,0 +1 @@ +"undefined"!=typeof sm_conditionals&&jQuery(function(){jQuery.each(sm_conditionals,function(a,b){let c=jQuery("#"+a),d=c.closest("tr");jQuery.each(b,function(a,b){let c=b.id,e=jQuery("#"+c),f=sm_isset(b.value)?b.value:b["!value"],g=sm_isset(b["!value"]);e.on("change",function(){let a=this.value;sm_hide_show_elements(f,a,g,d)}),sm_hide_show_elements(f,e.val(),g,d)})})});function sm_hide_show_elements(a,b,c,d){let e=d.find("select"),f=a!==b,g=!!e.data("ajax")&&e.data("ajax");if(f=c?!f:f,g||(f?d.addClass("hidden"):d.removeClass("hidden")),g){sm_reset_option_value(e,!d.hasClass("hidden"));jQuery.ajax({method:"POST",url:ajaxurl,data:{action:"sm_settings_get_select_data",id:b}}).always(function(){sm_reset_option_value(e,!d.hasClass("hidden"))}).done(function(a){if("false"===a)a=!1;else try{a=JSON.parse(a)}catch(b){a=!1}if("object"==typeof a)switch(d.removeClass("hidden"),e.prop("tagName")){case"SELECT":e.find("option").each(function(){jQuery(this.remove())}),jQuery.each(a,function(a,b){d.find("select").append(jQuery("").val(a).text(b))});}!1===a&&d.addClass("hidden")}).fail(function(){switch(e.prop("tabName")){case"SELECT":e.append(jQuery("").val("").text("Error."));}})}}function sm_reset_option_value(a,b){switch(a.prop("tagName")){case"SELECT":a.find("option").each(function(){jQuery(this.remove())});}b&&a.append(jQuery("").val("").text("Loading..."))}function sm_isset(a){try{return"undefined"!=typeof a}catch(a){return!1}} \ No newline at end of file diff --git a/composer.json b/composer.json index be98482..a2296fe 100644 --- a/composer.json +++ b/composer.json @@ -5,5 +5,8 @@ "phpcompatibility/php-compatibility": "*", "wp-coding-standards/wpcs": "*", "phpunit/phpunit": "^7" + }, + "require": { + "ext-calendar": "*" } } diff --git a/includes/admin/class-sm-admin-post-types.php b/includes/admin/class-sm-admin-post-types.php index 75a75e2..ac92afe 100644 --- a/includes/admin/class-sm-admin-post-types.php +++ b/includes/admin/class-sm-admin-post-types.php @@ -300,14 +300,19 @@ public function sermon_filters() { global $wp_query; // Type filtering. - $terms = get_terms( 'wpfc_service_type' ); + $terms = get_terms( + array( + 'taxonomy' => 'wpfc_service_type', + 'hide_empty' => false, + ) + ); $output = ''; $output .= ''; $output .= '' . __( 'Filter by Service Type', 'sermon-manager-for-wordpress' ) . ''; foreach ( $terms as $term ) { - $output .= 'slug . '" '; if ( isset( $wp_query->query['wpfc_service_type'] ) ) { $output .= selected( $term->slug, $wp_query->query['wpfc_service_type'], false ); diff --git a/includes/admin/class-sm-admin-settings.php b/includes/admin/class-sm-admin-settings.php index e57ca9e..2d7a575 100644 --- a/includes/admin/class-sm-admin-settings.php +++ b/includes/admin/class-sm-admin-settings.php @@ -203,15 +203,17 @@ public static function add_error( $text ) { * @param array $values The array of custom values. Optional. */ public static function output_fields( $options, $values = array() ) { - foreach ( $options as $value ) { - if ( ! isset( $value['type'] ) ) { + $display_conditions = array(); + + foreach ( $options as $option ) { + if ( ! isset( $option['type'] ) ) { continue; } // Fill out data that is not set. - $value += array( + $option += array( 'id' => '', - 'title' => isset( $value['name'] ) ? $value['name'] : '', + 'title' => isset( $option['name'] ) ? $option['name'] : '', 'class' => '', 'css' => '', 'default' => '', @@ -220,62 +222,74 @@ public static function output_fields( $options, $values = array() ) { 'placeholder' => '', 'size' => '', 'disabled' => false, + 'display_if' => array(), + 'ajax' => false, ); + // Get conditional display. + if ( ! empty( $option['display_if'] ) ) { + $display_conditions[ $option['id'] ] = isset( $display_conditions[ $option['id'] ] ) ? $display_conditions[ $option['id'] ] : array(); + $display_conditions[ $option['id'] ][] = $option['display_if']; + } + // Custom attribute handling. $custom_attributes = array(); - if ( ! empty( $value['custom_attributes'] ) ) { - if ( is_array( $value['custom_attributes'] ) ) { - foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) { + if ( ! empty( $option['custom_attributes'] ) ) { + if ( is_array( $option['custom_attributes'] ) ) { + foreach ( $option['custom_attributes'] as $attribute => $attribute_value ) { $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"'; } - } elseif ( is_string( $value['custom_attributes'] ) ) { - $custom_attributes[] = $value['custom_attributes']; + } elseif ( is_string( $option['custom_attributes'] ) ) { + $custom_attributes[] = $option['custom_attributes']; } } + if ( $option['ajax'] ) { + $custom_attributes[] = 'data-ajax="true"'; + } + // Get descriptions. - $field_description = self::get_field_description( $value ); + $field_description = self::get_field_description( $option ); $description = $field_description['description']; $tooltip_html = $field_description['tooltip_html']; // Execute a function to get the options in (multi)select if it's specified. - if ( isset( $value['options'] ) ) { - $value['options'] = self::_maybe_populate_options( $value['options'] ); + if ( isset( $option['options'] ) ) { + $option['options'] = self::_maybe_populate_options( $option['options'] ); } // Get the value. if ( empty( $values ) ) { - $option_value = self::get_option( $value['id'], $value['default'] ); + $option_value = self::get_option( $option['id'], $option['default'] ); } else { - $option_value = empty( $values[ $value['id'] ] ) ? $value['default'] : $values[ $value['id'] ]; + $option_value = empty( $values[ $option['id'] ] ) ? $option['default'] : $values[ $option['id'] ]; } // Output the field based on type. - switch ( $value['type'] ) { + switch ( $option['type'] ) { // Section Titles. case 'title': - if ( ! empty( $value['title'] ) ) { - echo '' . esc_html( $value['title'] ) . ''; + if ( ! empty( $option['title'] ) ) { + echo '' . esc_html( $option['title'] ) . ''; } - if ( ! empty( $value['desc'] ) ) { - echo wpautop( wptexturize( wp_kses_post( $value['desc'] ) ) ); + if ( ! empty( $option['desc'] ) ) { + echo wpautop( wptexturize( wp_kses_post( $option['desc'] ) ) ); } echo '' . "\n\n"; - if ( ! empty( $value['id'] ) ) { - do_action( 'sm_settings_' . sanitize_title( $value['id'] ) ); + if ( ! empty( $option['id'] ) ) { + do_action( 'sm_settings_' . sanitize_title( $option['id'] ) ); } break; // Section Ends. case 'sectionend': - if ( ! empty( $value['id'] ) ) { - do_action( 'sm_settings_' . sanitize_title( $value['id'] ) . '_end' ); + if ( ! empty( $option['id'] ) ) { + do_action( 'sm_settings_' . sanitize_title( $option['id'] ) . '_end' ); } echo ''; - if ( ! empty( $value['id'] ) ) { - do_action( 'sm_settings_' . sanitize_title( $value['id'] ) . '_after' ); + if ( ! empty( $option['id'] ) ) { + do_action( 'sm_settings_' . sanitize_title( $option['id'] ) . '_after' ); } break; @@ -284,27 +298,27 @@ public static function output_fields( $options, $values = array() ) { case 'email': case 'number': case 'password': - if ( substr( $value['id'], 0, 2 ) === '__' && strlen( $value['id'] ) > 2 ) { - $option_value = $value['value']; + if ( substr( $option['id'], 0, 2 ) === '__' && strlen( $option['id'] ) > 2 ) { + $option_value = $option['value']; } ?> - + - + + class="" + placeholder="" + size="" + disabled="disabled" @@ -319,27 +333,27 @@ class="" ?> - + - + + class="colorpick" + placeholder="" + disabled="disabled" /> - @@ -351,20 +365,20 @@ class="colorpick" ?> - + - + - + disabled="disabled" > @@ -379,23 +393,23 @@ class="" ?> - + - + - - + + disabled="disabled" > $val ) { + foreach ( $option['options'] as $key => $val ) { ?> - + - + + disabled="disabled" > $val ) { + foreach ( $option['options'] as $key => $val ) { ?> /> @@ -464,47 +478,47 @@ class="" $option_value = is_bool( $option_value ) ? ( $option_value ? 'yes' : 'no' ) : $option_value; $visbility_class = array(); - if ( ! isset( $value['hide_if_checked'] ) ) { - $value['hide_if_checked'] = false; + if ( ! isset( $option['hide_if_checked'] ) ) { + $option['hide_if_checked'] = false; } - if ( ! isset( $value['show_if_checked'] ) ) { - $value['show_if_checked'] = false; + if ( ! isset( $option['show_if_checked'] ) ) { + $option['show_if_checked'] = false; } - if ( 'yes' == $value['hide_if_checked'] || 'yes' == $value['show_if_checked'] ) { + if ( 'yes' == $option['hide_if_checked'] || 'yes' == $option['show_if_checked'] ) { $visbility_class[] = 'hidden_option'; } - if ( 'option' == $value['hide_if_checked'] ) { + if ( 'option' == $option['hide_if_checked'] ) { $visbility_class[] = 'hide_options_if_checked'; } - if ( 'option' == $value['show_if_checked'] ) { + if ( 'option' == $option['show_if_checked'] ) { $visbility_class[] = 'show_options_if_checked'; } ?> - + + disabled="disabled" > - + - + @@ -522,26 +536,26 @@ class=" - + - + + class="" + placeholder="" + disabled="disabled" /> @@ -572,8 +586,8 @@ class="upload_image_button" case 'description': ?> - - + + - + @@ -590,8 +604,8 @@ class="upload_image_button" case 'separator_title': ?> - - + + ' . wp_kses_post( $description ) . ''; - } elseif ( $description && in_array( $value['type'], array( 'checkbox' ) ) ) { + } elseif ( $description && in_array( $option['type'], array( 'checkbox' ) ) ) { $description = wp_kses_post( $description ); - } elseif ( $description && in_array( $value['type'], array( 'select', 'multiselect' ) ) ) { + } elseif ( $description && in_array( $option['type'], array( 'select', 'multiselect' ) ) ) { $description = '' . $description . ''; } elseif ( $description ) { $description = '' . wp_kses_post( $description ) . ''; } - if ( $tooltip_html && in_array( $value['type'], array( 'checkbox' ) ) ) { + if ( $tooltip_html && in_array( $option['type'], array( 'checkbox' ) ) ) { $tooltip_html = '' . $tooltip_html . ''; } elseif ( $tooltip_html ) { $tooltip_html = sm_help_tip( $tooltip_html ); @@ -675,11 +694,11 @@ protected static function _maybe_populate_options( $options ) { $function = $options; } elseif ( is_array( $options ) ) { if ( count( $options ) === 1 ) { - foreach ( $options as $function => $args ) { - // Let's assume that it's a function with arguments. - if ( is_array( $args ) ) { - break; - } + $function = key( $options ); + $args = $options[ $function ]; + + if ( ! function_exists( $function ) ) { + return $options; } } else { return $options; @@ -698,11 +717,11 @@ protected static function _maybe_populate_options( $options ) { } if ( count( $options ) === 0 ) { - $options = array( 0 => '-- ' . __( 'None' ) . ' --' ); + $options = array( 0 => '-- ' . __( 'None' ) . ' --' ); // phpcs:ignore } } else { $options = array( - 0 => __( 'Error.' ), + 0 => __( 'Error in populating field options.', 'sermon-manager-for-wordpress' ), ); } diff --git a/includes/admin/settings/class-sm-settings-debug.php b/includes/admin/settings/class-sm-settings-debug.php index e0c1cea..284d25b 100644 --- a/includes/admin/settings/class-sm-settings-debug.php +++ b/includes/admin/settings/class-sm-settings-debug.php @@ -50,14 +50,6 @@ public function get_settings() { 'id' => 'sort_bible_books', 'default' => 'yes', ), - array( - 'title' => __( 'Date Used', 'sermon-manager-for-wordpress' ), - 'type' => 'checkbox', - 'desc' => __( 'Show "Published" date instead of "Preached" date', 'sermon-manager-for-wordpress' ), - 'desc_tip' => __( 'This will just change what date will be shown on frontend and in the podcast feed. Ordering will be the same. Default unchecked.', 'sermon-manager-for-wordpress' ), - 'id' => 'use_published_date', - 'default' => 'no', - ), array( 'title' => __( 'Background Updates', 'sermon-manager-for-wordpress' ), 'desc' => __( 'Execute all update functions that have not been executed yet.', 'sermon-manager-for-wordpress' ), @@ -175,6 +167,14 @@ public function get_settings() { 'id' => 'force_layouts', 'default' => 'no', ), + array( + 'title' => __( 'Clear All Transients', 'sermon-manager-for-wordpress' ), + 'type' => 'checkbox', + 'desc' => __( 'Clear all transients on save.', 'sermon-manager-for-wordpress' ), + 'desc_tip' => __( 'Removes all transients from the database on save. Useful for debugging RSS feed. Your website will not break by executing this.', 'sermon-manager-for-wordpress' ), + 'id' => 'clear_transients', + 'default' => 'no', + ), array( 'type' => 'sectionend', diff --git a/includes/admin/settings/class-sm-settings-display.php b/includes/admin/settings/class-sm-settings-display.php index 4d932ed..eadebc2 100644 --- a/includes/admin/settings/class-sm-settings-display.php +++ b/includes/admin/settings/class-sm-settings-display.php @@ -55,6 +55,31 @@ public function get_settings() { 'title' => __( 'Archive', 'sermon-manager-for-wordpress' ), 'type' => 'separator_title', ), + array( + 'title' => __( 'Order sermons by', 'sermon-manager-for-wordpress' ), + 'type' => 'select', + 'options' => array( + 'date_preached' => 'Date Preached', + 'date' => 'Date Published', + 'title' => 'Title', + 'ID' => 'ID', + 'random' => 'Random', + ), + 'desc' => __( 'Changes the way sermons are ordered by default. Affects the RSS feed and shown date as well. Default "Date Preached".', 'sermon-manager-for-wordpress' ), + 'default' => 'date_preached', + 'id' => 'archive_orderby', + ), + array( + 'title' => __( 'Order direction', 'sermon-manager-for-wordpress' ), + 'type' => 'select', + 'options' => array( + 'desc' => 'Descending', + 'asc' => 'Ascending', + ), + 'desc' => __( 'Related to the setting above. Default descending.', 'sermon-manager-for-wordpress' ), + 'default' => 'desc', + 'id' => 'archive_order', + ), array( 'title' => __( 'Display Audio Player', 'sermon-manager-for-wordpress' ), 'type' => 'checkbox', @@ -98,7 +123,7 @@ public function get_settings() { 'desc_tip' => __( 'Displays service type filtering on archive pages. Default unchecked.', 'sermon-manager-for-wordpress' ), 'id' => 'service_type_filtering', 'default' => 'no', - 'disabled' => method_exists('\SermonManagerPro\Templating\Templating_Manager', 'is_active') ? \SermonManagerPro\Templating\Templating_Manager::is_active() : false, + 'disabled' => method_exists( '\SermonManagerPro\Templating\Templating_Manager', 'is_active' ) ? \SermonManagerPro\Templating\Templating_Manager::is_active() : false, ), array( 'title' => __( 'Use Previous/Next Pagination', 'sermon-manager-for-wordpress' ), diff --git a/includes/class-sm-dates-wp.php b/includes/class-sm-dates-wp.php index 7e189c3..316254e 100644 --- a/includes/class-sm-dates-wp.php +++ b/includes/class-sm-dates-wp.php @@ -49,7 +49,7 @@ public static function hook() { /** * Exit if disabled. */ - if ( apply_filters( 'sm_dates_wp', true ) === false || SermonManager::getOption( 'use_published_date' ) ) { + if ( apply_filters( 'sm_dates_wp', true ) === false || 'date' === SermonManager::getOption( 'archive_orderby' ) ) { return; } diff --git a/includes/class-sm-shortcodes.php b/includes/class-sm-shortcodes.php index f77f482..1c2a877 100755 --- a/includes/class-sm-shortcodes.php +++ b/includes/class-sm-shortcodes.php @@ -560,11 +560,13 @@ function display_latest_series_image( $atts = array() ) { $args = shortcode_atts( $args, $atts, 'latest_series' ); // Get latest series. - $latest_series = $this->get_latest_series( 0, $args['service_type'] ); + $latest_series = $this->get_latest_series_with_image( 0, $args['service_type'] ); // If for some reason we couldn't get latest series. if ( null === $latest_series ) { return 'No latest series found.'; + } elseif ( false === $latest_series ) { + return 'No latest series image found.'; } // Image ID. @@ -612,25 +614,45 @@ function display_latest_series_image( $atts = array() ) { } /** - * Get all sermon series as WP_Term object. - * - * @param int $latest_sermon Optional. Latest sermon ID. If not provided, it will try to get it automatically. - * @param int $service_type Optional. Service Type for getting latest sermon ID. + * Get latest sermon series that has an image. * - * @return WP_Term|null + * @return WP_Term|null|false Term if found, null if there are no terms, false if there is no term with image. */ - public function get_latest_series( $latest_sermon = 0, $service_type = 0 ) { - if ( empty( $latest_sermon ) ) { - $latest_sermon = $this->get_latest_sermon_id( $service_type ); + public function get_latest_series_with_image() { + $default_orderby = SermonManager::getOption( 'archive_orderby' ); + $default_order = SermonManager::getOption( 'archive_order' ); + + $query_args = array( + 'taxonomy' => 'wpfc_sermon_series', + 'hide_empty' => false, + 'order' => strtoupper( $default_order ), + ); + + switch ( $default_orderby ) { + case 'date_preached': + $query_args += array( + 'orderby' => 'meta_value_num', + 'meta_key' => 'sermon_date', + 'meta_value' => time(), + 'meta_compare' => '<=', + ); + break; + default: + $query_args += array( + 'orderby' => $default_orderby, + ); } - $latest_series = get_the_terms( $latest_sermon, 'wpfc_sermon_series' ); + $series = get_terms( $query_args ); - if ( is_array( $latest_series ) && ! empty( $latest_series ) ) { - return $latest_series[0]; + // Fallback to next one until we find the one that has an image. + foreach ( $series as $serie ) { + if ( $this->get_latest_series_image_id( $serie ) ) { + return $serie; + } } - return null; + return is_array( $series ) && count( $series ) > 0 ? false : null; } /** @@ -700,16 +722,16 @@ public function get_latest_sermon_id( $service_type = 0 ) { * @return int|null */ function get_latest_series_image_id( $series = 0 ) { - if ( 0 === $series ) { - $series = $this->get_latest_series(); - - if ( null === $series ) { - return null; - } + if ( 0 !== $series && is_numeric( $series ) ) { + $series = intval( $series ); + } elseif ( $series instanceof WP_Term ) { + $series = $series->term_id; + } else { + return null; } $associations = sermon_image_plugin_get_associations(); - $tt_id = absint( $series->term_taxonomy_id ); + $tt_id = absint( $series ); if ( array_key_exists( $tt_id, $associations ) ) { $id = absint( $associations[ $tt_id ] ); @@ -738,8 +760,6 @@ function get_latest_series_image_id( $series = 0 ) { * @type string $atts ['filter_value'] ID/slug of allowed filters. * @type int $atts ['year'] 4 digit year (e.g. 2011). * @type int $atts ['month'] Month number (from 1 to 12). - * @type int $atts ['week'] Week of the year (from 0 to 53). - * @type int $atts ['day'] Day of the month (from 1 to 31). * @type string $atts ['after'] Date to retrieve posts after. Accepts strtotime()-compatible string. * @type string $atts ['before'] Date to retrieve posts before. Accepts strtotime()-compatible string. * @type bool $atts ['show_initial'] Show Initial Sermon. Shows the single view of the first sermon on an @@ -767,16 +787,14 @@ function display_sermons( $atts = array() ) { $args = array( 'per_page' => get_option( 'posts_per_page' ) ?: 10, 'sermons' => false, // Show only sermon IDs that are set here. - 'order' => 'DESC', - 'orderby' => 'date', + 'order' => strtoupper( SermonManager::getOption( 'archive_order' ) ), + 'orderby' => SermonManager::getOption( 'archive_orderby' ), 'disable_pagination' => 0, 'image_size' => 'post-thumbnail', 'filter_by' => '', 'filter_value' => '', 'year' => '', 'month' => '', - 'week' => '', - 'day' => '', 'after' => '', 'before' => '', 'hide_filters' => true, @@ -784,6 +802,7 @@ function display_sermons( $atts = array() ) { 'hide_series' => '', 'hide_preachers' => '', 'hide_books' => '', + 'hide_dates' => '', 'include' => '', 'exclude' => '', 'hide_service_types' => \SermonManager::getOption( 'service_type_filtering' ) ? '' : 'yes', @@ -818,6 +837,7 @@ function display_sermons( $atts = array() ) { 'hide_preachers' => $args['hide_preachers'], 'hide_books' => $args['hide_books'], 'hide_service_types' => $args['hide_service_types'], + 'hide_dates' => $args['hide_dates'], ); // Set query args. @@ -826,17 +846,15 @@ function display_sermons( $atts = array() ) { 'posts_per_page' => $args['per_page'], 'order' => $args['order'], 'paged' => get_query_var( 'paged' ), - 'year' => $args['year'], - 'month' => $args['month'], - 'week' => $args['week'], - 'day' => $args['day'], - 'after' => $args['after'], - 'before' => $args['before'], ); // Check if it's a valid ordering argument. if ( ! in_array( strtolower( $args['orderby'] ), array( 'date', + 'preached', + 'date_preached', + 'published', + 'date_published', 'id', 'none', 'title', @@ -844,19 +862,116 @@ function display_sermons( $atts = array() ) { 'rand', 'comment_count', ) ) ) { - $args['orderby'] = 'date'; + $args['orderby'] = 'date_preached'; } if ( 'date' === $args['orderby'] ) { - $args['orderby'] = 'meta_value_num'; + $args['orderby'] = 'date' === SermonManager::getOption( 'archive_orderby' ) ? 'date_published' : 'date_preached'; + } - $query_args['meta_key'] = 'sermon_date'; - $query_args['meta_value_num'] = time(); - $query_args['meta_compare'] = '<='; + switch ( $args['orderby'] ) { + case 'preached': + case 'date_preached': + case '': + $args['orderby'] = 'meta_value_num'; + + $query_args['meta_query'] = array( + array( + 'key' => 'sermon_date', + 'value' => time(), + 'type' => 'numeric', + 'compare' => '<=', + ), + ); + break; + case 'published': + case 'date_published': + $args['orderby'] = 'date'; + break; + case 'id': + $args['orderby'] = 'ID'; + break; } $query_args['orderby'] = $args['orderby']; + // Add year month etc filter, adjusted for sermon date. + if ( 'meta_value_num' === $query_args['orderby'] ) { + $date_args = array( + 'year', + 'month', + ); + + foreach ( $date_args as $date_arg ) { + if ( ! isset( $args[ $date_arg ] ) || ! $args[ $date_arg ] ) { + continue; + } + + // Reset the query. + $query_args['meta_query'] = array(); + + switch ( $date_arg ) { + case 'year': + $year = $args['year']; + + $query_args['meta_query'][] = array( + 'key' => 'sermon_date', + 'value' => array( + strtotime( $year . '-01-01' ), + strtotime( $year . '-12-31' ), + ), + 'compare' => 'BETWEEN', + ); + break; + case 'month': + $year = $args['year'] ?: date( 'Y' ); + $month = intval( $args['month'] ) ?: date( 'm' ); + + $query_args['meta_query'][] = array( + 'key' => 'sermon_date', + 'value' => array( + strtotime( $year . '-' . $args['month'] . '-' . '01' ), + strtotime( $year . '-' . $month . '-' . cal_days_in_month( CAL_GREGORIAN, $month, $year ) ), + ), + 'compare' => 'BETWEEN', + ); + break; + } + } + } + + // Add before and after parameters. + if ( 'meta_value_num' === $query_args['orderby'] && ( $args['before'] || $args['after'] ) ) { + if ( ! isset( $query_args['meta_query'] ) ) { + $query_args['meta_query'] = array(); + } + + if ( $args['before'] ) { + $before = strtotime( $args['before'] ); + + $query_args['meta_query'][] = array( + 'key' => 'sermon_date', + 'value' => $before, + 'compare' => '<=', + ); + } + + if ( $args['after'] ) { + $after = strtotime( $args['after'] ); + + $query_args['meta_query'][] = array( + 'key' => 'sermon_date', + 'value' => $after, + 'compare' => '=>', + ); + } + } + + // Use all meta queries. + if ( isset( $query_args['meta_query'] ) && count( $query_args['meta_query'] ) > 1 ) { + $query_args['meta_query']['relation'] = 'AND'; + } + // If we should show just specific sermons. if ( $args['include'] ) { $posts_in = explode( ',', $args['include'] ); @@ -1104,6 +1219,7 @@ public function display_sermon_sorting( $atts = array() ) { 'hide_preachers' => '', 'hide_books' => '', 'hide_service_types' => \SermonManager::getOption( 'service_type_filtering' ) ? '' : 'yes', + 'hide_dates' => '', 'action' => 'none', 'smp_override_settings' => true, ); diff --git a/includes/sm-core-functions.php b/includes/sm-core-functions.php index 1961b16..ea7a39d 100644 --- a/includes/sm-core-functions.php +++ b/includes/sm-core-functions.php @@ -605,7 +605,14 @@ function sm_debug_get_update_functions() { } } - return $options; + /** + * Allows to modify the update functions list. + * + * @param array $options The update functions. + * + * @since 2.15.14 + */ + return apply_filters( 'sm_get_update_functions', $options ); } /** diff --git a/includes/sm-template-functions.php b/includes/sm-template-functions.php index 2153bf7..e8c756e 100755 --- a/includes/sm-template-functions.php +++ b/includes/sm-template-functions.php @@ -94,6 +94,7 @@ function render_wpfc_sorting( $args = array() ) { 'wpfc_preacher' => 'hide_preachers', 'wpfc_bible_book' => 'hide_books', 'wpfc_service_type' => 'hide_service_types', + 'wpfc_dates' => 'hide_dates', ) ); // Save orig args for filters. @@ -114,6 +115,7 @@ function render_wpfc_sorting( $args = array() ) { 'hide_preachers' => '', 'hide_books' => '', 'hide_service_types' => SermonManager::getOption( 'service_type_filtering' ) ? '' : 'yes', + 'hide_dates' => '', 'hide_filters' => ! SermonManager::getOption( 'hide_filters' ), 'action' => 'none', ); @@ -737,3 +739,36 @@ function sm_get_views_path( $template = '' ) { return $template; } + +/** + * Renders the pagination in views files. + * + * @since 2.15.14 + */ +function sm_pagination() { + if ( SermonManager::getOption( 'use_prev_next_pagination' ) ) { + posts_nav_link(); + } else { + if ( function_exists( 'wp_pagenavi' ) ) : + wp_pagenavi(); + elseif ( function_exists( 'oceanwp_pagination' ) ) : + oceanwp_pagination(); + elseif ( function_exists( 'pagination' ) ) : + pagination(); + elseif ( function_exists( 'mfn_pagination' ) ) : + echo mfn_pagination(); + elseif ( function_exists( 'presscore_complex_pagination' ) ) : + presscore_complex_pagination( $GLOBALS['wp_query'] ); + elseif ( function_exists( 'cro_paging' ) ) : + cro_paging(); + elseif ( function_exists( 'twentynineteen_the_posts_navigation' ) ) : + twentynineteen_the_posts_navigation(); + elseif ( function_exists( 'exodoswp_pagination' ) ) : + echo ''; + exodoswp_pagination(); + echo ''; + else : + the_posts_pagination(); + endif; + } +} diff --git a/readme.txt b/readme.txt index 0e03d00..7b7ac6b 100755 --- a/readme.txt +++ b/readme.txt @@ -3,9 +3,9 @@ Contributors: wpforchurch, nikolam Donate link: http://wpforchurch.com/ Tags: church, sermon, sermons, preaching, podcasting, manage, managing, podcasts, itunes Requires at least: 4.7.0 -Tested up to: 5.0 +Tested up to: 5.1 Requires PHP: 5.3 -Stable tag: 2.15.13 +Stable tag: 2.15.14 License: GPLv2 License URI: https://www.gnu.org/licenses/gpl-2.0.html @@ -122,6 +122,16 @@ Visit the [plugin homepage](https://wpforchurch.com/wordpress-plugins/sermon-man 2. Sermon Files ## Changelog ## +### 2.15.14 ### +* New: Add compatibility for Pro theme +* New: Add a setting to change default sermon ordering (in "Display" tab) +* Fix: Date filtering in shortcode +* Fix: Improve [latest_series] shortcode +* Fix: Service Type filter in backend not working when slug is different from default +* Dev: Add conditional fields in settings +* Dev: Add dynamic option retrieval in settings +* Dev: Fix select field in settings returning error when only one option is defined for it + ### 2.15.13 ### * New: Dutch translation (thanks @LeonCB!) * New: Add support for Dunamis theme diff --git a/sermons.php b/sermons.php index 5c8b147..a3363cc 100755 --- a/sermons.php +++ b/sermons.php @@ -3,11 +3,11 @@ * Plugin Name: Sermon Manager for WordPress * Plugin URI: https://www.wpforchurch.com/products/sermon-manager-for-wordpress/ * Description: Add audio and video sermons, manage speakers, series, and more. - * Version: 2.15.13 + * Version: 2.15.14 * Author: WP for Church * Author URI: https://www.wpforchurch.com/ * Requires at least: 4.5 - * Tested up to: 4.9 + * Tested up to: 5.1 * * Text Domain: sermon-manager-for-wordpress * Domain Path: /languages/ @@ -250,11 +250,27 @@ public function render_sermon_into_content( $post_ID = 0, $post = null, $skip_ch public static function fix_sermons_ordering( $query ) { if ( ! is_admin() && ( $query->is_main_query() ) ) { if ( is_post_type_archive( 'wpfc_sermon' ) || is_tax( sm_get_taxonomies() ) ) { - $query->set( 'meta_key', 'sermon_date' ); - $query->set( 'meta_value_num', time() ); - $query->set( 'meta_compare', '<=' ); - $query->set( 'orderby', 'meta_value_num' ); - $query->set( 'order', 'DESC' ); + $orderby = SermonManager::getOption( 'archive_orderby' ); + $order = SermonManager::getOption( 'archive_order' ); + + switch ( $orderby ) { + case 'date_preached': + $query->set( 'meta_key', 'sermon_date' ); + $query->set( 'meta_value_num', time() ); + $query->set( 'meta_compare', '<=' ); + $query->set( 'orderby', 'meta_value_num' ); + break; + case 'date_published': + $query->set( 'orderby', 'date' ); + break; + case 'title': + case 'random': + case 'id': + $query->set( 'orderby', $orderby ); + break; + } + + $query->set( 'order', strtoupper( $order ) ); /** * Allows to filter the sermon query. @@ -659,6 +675,27 @@ function ( $value ) { } ); + // Clear all transients. + add_action( + 'sm_admin_settings_sanitize_option_clear_transients', + function ( $value ) { + if ( '' !== $value ) { + global $wpdb; + + $sql = 'DELETE FROM ' . $wpdb->options . ' WHERE ( `option_name` LIKE "_transient_%" OR `option_name` LIKE "transient_%")'; + $wpdb->query( $sql ); + + ?> + + Removed rows_affected; ?> transient fields. + + '; - if ( SermonManager::getOption( 'use_prev_next_pagination' ) ) { - posts_nav_link(); - } else { - if ( function_exists( 'wp_pagenavi' ) ) : - wp_pagenavi(); - elseif ( function_exists( 'oceanwp_pagination' ) ) : - oceanwp_pagination(); - elseif ( function_exists( 'pagination' ) ) : - pagination(); - elseif ( function_exists( 'mfn_pagination' ) ) : - echo mfn_pagination(); - elseif ( function_exists( 'presscore_complex_pagination' ) ) : - presscore_complex_pagination( $GLOBALS['wp_query'] ); - elseif ( function_exists( 'cro_paging' ) ) : - cro_paging(); - elseif ( function_exists( 'twentynineteen_the_posts_navigation' ) ) : - twentynineteen_the_posts_navigation(); - elseif ( function_exists( 'exodoswp_pagination' ) ) : - echo ''; - exodoswp_pagination(); - echo ''; - else : - the_posts_pagination(); - endif; - } + sm_pagination(); echo ''; else : echo __( 'Sorry, but there aren\'t any posts matching your query.' ); diff --git a/views/partials/content-sermon-archive.php b/views/partials/content-sermon-archive.php index e5e63a7..e386ed5 100644 --- a/views/partials/content-sermon-archive.php +++ b/views/partials/content-sermon-archive.php @@ -64,7 +64,7 @@ - + diff --git a/views/partials/content-sermon-single.php b/views/partials/content-sermon-single.php index 9063523..bebb2c1 100644 --- a/views/partials/content-sermon-single.php +++ b/views/partials/content-sermon-single.php @@ -31,7 +31,7 @@ - + diff --git a/views/partials/content-sermon-wrapper-end.php b/views/partials/content-sermon-wrapper-end.php index 41fa1d5..35deb92 100644 --- a/views/partials/content-sermon-wrapper-end.php +++ b/views/partials/content-sermon-wrapper-end.php @@ -78,6 +78,7 @@ get_sidebar(); echo ''; break; + case 'pro': case 'x': $fullwidth = get_post_meta( get_the_ID(), '_x_post_layout', true ); // phpcs:ignore diff --git a/views/partials/content-sermon-wrapper-start.php b/views/partials/content-sermon-wrapper-start.php index 0a71a48..0088a67 100644 --- a/views/partials/content-sermon-wrapper-start.php +++ b/views/partials/content-sermon-wrapper-start.php @@ -67,6 +67,7 @@ case 'oceanwp': echo ''; break; + case 'pro': case 'x': if ( function_exists( 'x_main_content_class' ) ) { ob_start(); diff --git a/views/taxonomy-wpfc_bible_book.php b/views/taxonomy-wpfc_bible_book.php index 6120121..c076d71 100644 --- a/views/taxonomy-wpfc_bible_book.php +++ b/views/taxonomy-wpfc_bible_book.php @@ -1,48 +1,38 @@ - - - - -'; - if ( SermonManager::getOption( 'use_prev_next_pagination' ) ) { - posts_nav_link(); - } else { - if ( function_exists( 'wp_pagenavi' ) ) : - wp_pagenavi(); - elseif ( function_exists( 'oceanwp_pagination' ) ) : - oceanwp_pagination(); - else : - the_posts_pagination(); - endif; - } - echo ''; -else : - echo __( 'Sorry, but there are no posts matching your query.' ); -endif; -?> - - - - + + + +'; + sm_pagination(); + echo ''; +else : + echo __( 'Sorry, but there are no posts matching your query.' ); +endif; +?> + + + + - - - -'; - if ( SermonManager::getOption( 'use_prev_next_pagination' ) ) { - posts_nav_link(); - } else { - if ( function_exists( 'wp_pagenavi' ) ) : - wp_pagenavi(); - elseif ( function_exists( 'oceanwp_pagination' ) ) : - oceanwp_pagination(); - else : - the_posts_pagination(); - endif; - } - echo ''; -else : - echo __( 'Sorry, but there are no posts matching your query.' ); -endif; -?> - - - - + + + +'; + sm_pagination(); + echo ''; +else : + echo __( 'Sorry, but there are no posts matching your query.' ); +endif; +?> + + + + - - - -'; - if ( SermonManager::getOption( 'use_prev_next_pagination' ) ) { - posts_nav_link(); - } else { - if ( function_exists( 'wp_pagenavi' ) ) : - wp_pagenavi(); - elseif ( function_exists( 'oceanwp_pagination' ) ) : - oceanwp_pagination(); - else : - the_posts_pagination(); - endif; - } - echo ''; -else : - echo __( 'Sorry, but there are no posts matching your query.' ); -endif; -?> - - - - + + + +'; + sm_pagination(); + echo ''; +else : + echo __( 'Sorry, but there are no posts matching your query.' ); +endif; +?> + + + + - - - -'; - if ( SermonManager::getOption( 'use_prev_next_pagination' ) ) { - posts_nav_link(); - } else { - if ( function_exists( 'wp_pagenavi' ) ) : - wp_pagenavi(); - elseif ( function_exists( 'oceanwp_pagination' ) ) : - oceanwp_pagination(); - else : - the_posts_pagination(); - endif; - } - echo ''; -else : - echo __( 'Sorry, but there are no posts matching your query.' ); -endif; -?> - - - - + + + +'; + sm_pagination(); + echo ''; +else : + echo __( 'Sorry, but there are no posts matching your query.' ); +endif; +?> + + + + - - - -'; - if ( SermonManager::getOption( 'use_prev_next_pagination' ) ) { - posts_nav_link(); - } else { - if ( function_exists( 'wp_pagenavi' ) ) : - wp_pagenavi(); - elseif ( function_exists( 'oceanwp_pagination' ) ) : - oceanwp_pagination(); - else : - the_posts_pagination(); - endif; - } - echo ''; -else : - echo __( 'Sorry, but there are no posts matching your query.' ); -endif; -?> - - - - + + + +'; + sm_pagination(); + echo ''; +else : + echo __( 'Sorry, but there are no posts matching your query.' ); +endif; +?> + + + + '', 'podcast_sermon_image_series' => '', 'podtrac' => '', - 'use_published_date' => '', ); // If there is no default. @@ -69,17 +68,16 @@ // in this script (or be blank). } +// Show published date if we are ordering by published. +$settings['use_published_date'] = 'date' === SermonManager::getOption( 'archive_orderby' ); + /** * Create the query for sermons. */ $args = array( 'post_type' => 'wpfc_sermon', 'posts_per_page' => $settings['podcasts_per_page'], - 'meta_key' => 'sermon_date', - 'meta_value_num' => time(), - 'meta_compare' => '<=', - 'orderby' => 'meta_value_num', - 'order' => 'DESC', + 'order' => strtoupper( SermonManager::getOption( 'archive_order' ) ), 'paged' => isset( $_GET['paged'] ) ? intval( $_GET['paged'] ) : 1, 'meta_query' => array( 'relation' => 'AND', @@ -95,6 +93,23 @@ ), ); +switch ( SermonManager::getOption( 'archive_orderby' ) ) { + case 'date_preached': + $args += array( + 'meta_key' => 'sermon_date', + 'meta_value_num' => time(), + 'meta_compare' => '<=', + 'orderby' => 'meta_value_num', + ); + break; + default: + $args += array( + 'orderby' => SermonManager::getOption( 'archive_orderby' ), + ); + break; +} + + /** * If feed is being loaded via taxonomy feed URL, such as "https://www.example.com/service-type/service-type-slug" */ @@ -308,7 +323,7 @@ -
' . $description . '
' . $tooltip_html . '
Removed rows_affected; ?> transient fields.