diff --git a/includes/admin/class-admin.php b/includes/admin/class-admin.php index 6512115c..88ebb2a1 100644 --- a/includes/admin/class-admin.php +++ b/includes/admin/class-admin.php @@ -1904,7 +1904,7 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { * Manual check templates versions. */ public function check_templates_version() { - UM()->common()->theme()->check_outdated_templates(); + UM()->common()->theme()->flush_transient_templates_data(); $url = add_query_arg( array( diff --git a/includes/admin/class-site-health.php b/includes/admin/class-site-health.php index c8caf3dc..77501694 100644 --- a/includes/admin/class-site-health.php +++ b/includes/admin/class-site-health.php @@ -31,10 +31,14 @@ class Site_Health { } public function register_site_status_tests( $tests ) { - $tests['direct']['um_override_templates'] = array( - 'label' => esc_html__( 'Are the Ultimate Member templates out of date?', 'ultimate-member' ), - 'test' => array( $this, 'override_templates_test' ), - ); + $custom_templates = UM()->common()->theme()->get_custom_templates_list(); + + if ( ! empty( $custom_templates ) ) { + $tests['direct']['um_override_templates'] = array( + 'label' => esc_html__( 'Are the Ultimate Member templates out of date?', 'ultimate-member' ), + 'test' => array( $this, 'override_templates_test' ), + ); + } return $tests; } @@ -55,9 +59,7 @@ class Site_Health { 'test' => 'um_override_templates', ); - UM()->common()->theme()->check_outdated_templates(); - - if ( true === (bool) get_option( 'um_override_templates_outdated' ) ) { + if ( UM()->common()->theme()->is_outdated_template_exist() ) { $result['label'] = __( 'Your custom templates are out of date', 'ultimate-member' ); $result['status'] = 'critical'; $result['badge']['color'] = 'red'; diff --git a/includes/admin/core/class-admin-notices.php b/includes/admin/core/class-admin-notices.php index 86e51a7b..e1c0a483 100644 --- a/includes/admin/core/class-admin-notices.php +++ b/includes/admin/core/class-admin-notices.php @@ -49,8 +49,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { $this->extensions_page(); - $this->template_version(); - $this->child_theme_required(); // Removed for now to avoid the bad reviews. @@ -766,36 +764,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { ), 2 ); } - /** - * Check Templates Versions notice - */ - public function template_version() { - if ( true === (bool) get_option( 'um_override_templates_outdated' ) ) { - $link = admin_url( 'admin.php?page=um_options&tab=advanced§ion=override_templates' ); - ob_start(); - ?> - -
- override templates status page and update templates.', 'ultimate-member' ), $link ), UM()->get_allowed_html( 'admin_notice' ) ); - ?> -
- - admin()->notices()->add_notice( - 'um_override_templates_notice', - array( - 'class' => 'error', - 'message' => $message, - 'dismissible' => false, - ), - 10 - ); - } - } - /** * Check if there isn't installed child-theme. Child theme is required for safely saved customizations. */ diff --git a/includes/admin/core/class-admin-settings.php b/includes/admin/core/class-admin-settings.php index f2cd32aa..6d6c555d 100644 --- a/includes/admin/core/class-admin-settings.php +++ b/includes/admin/core/class-admin-settings.php @@ -51,9 +51,6 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { //custom content for licenses tab add_filter( 'um_settings_section_licenses__custom_content', array( $this, 'settings_licenses_tab' ), 10, 3 ); - //custom content for override templates tab - add_action( 'plugins_loaded', array( $this, 'um_check_template_version' ), 10 ); - add_filter( 'um_settings_structure', array( $this, 'sorting_licenses_options' ), 9999, 1 ); //save handlers @@ -2244,6 +2241,12 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { unset( $this->settings_structure['']['sections']['account']['form_sections']['notifications_tab'] ); } + // Hide sub tab if there aren't custom templates in theme. + $custom_templates = UM()->common()->theme()->get_custom_templates_list(); + if ( empty( $custom_templates ) ) { + unset( $this->settings_structure['advanced']['sections']['override_templates'] ); + } + if ( defined( 'UM_DEV_MODE' ) && UM_DEV_MODE ) { } else { @@ -3355,27 +3358,17 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { return ob_get_clean(); } - /** - * Periodically checking the versions of templates. - * - * @since 2.6.1 - * - * @return void - */ - public function um_check_template_version() { - $um_check_version = get_transient( 'um_check_template_versions' ); - if ( false === $um_check_version ) { - $this->get_override_templates(); - } - } - /** * HTML for Settings > Advanced > Override Templates tab. * * @return string */ - public function settings_override_templates_tab( $content ) { - $um_check_version = get_transient( 'um_check_template_versions' ); + public function settings_override_templates_tab() { + $um_check_version = time(); + $custom_templates = get_transient( 'um_custom_templates_list' ); + if ( false !== $custom_templates && array_key_exists( 'time', $custom_templates ) ) { + $um_check_version = $custom_templates['time']; + } $check_url = add_query_arg( array( @@ -3383,148 +3376,24 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { '_wpnonce' => wp_create_nonce( 'check_templates_version' ), ) ); + ob_start(); ?> - - $files ) { - foreach ( $files as $file ) { - if ( false === strpos( $file, 'email/' ) ) { - $located = array(); - /** - * Filters an array of the template files for scanning versions based on $key. - * - * Note: $key - means um or extension key. - * - * @since 2.6.1 - * @hook um_override_templates_get_template_path__{$key} - * - * @param {array} $located Template file paths for scanning versions. - * @param {string} $file Template file name. - * - * @return {array} Template file paths for scanning versions. - */ - $located = apply_filters( "um_override_templates_get_template_path__{$key}", $located, $file ); - - $exceptions = array( - 'members-grid.php', - 'members-header.php', - 'members-list.php', - 'members-pagination.php', - 'searchform.php', - 'login-to-view.php', - 'profile/comments.php', - 'profile/comments-single.php', - 'profile/posts.php', - 'profile/posts-single.php', - 'modal/um_upload_single.php', - 'modal/um_view_photo.php', - ); - - if ( ! empty( $located ) ) { - $theme_file = $located['theme']; - } elseif ( in_array( $file, $exceptions, true ) && file_exists( get_stylesheet_directory() . '/ultimate-member/' . $file ) ) { - $theme_file = get_stylesheet_directory() . '/ultimate-member/' . $file; - } elseif ( file_exists( get_stylesheet_directory() . '/ultimate-member/templates/' . $file ) ) { - $theme_file = get_stylesheet_directory() . '/ultimate-member/templates/' . $file; - } else { - $theme_file = false; - } - - if ( ! empty( $theme_file ) ) { - $core_file = $file; - - if ( ! empty( $located ) ) { - $core_path = $located['core']; - $core_file_path = stristr( $core_path, 'wp-content' ); - } else { - $core_path = UM_PATH . '/templates/' . $core_file; - $core_file_path = stristr( UM_PATH . 'templates/' . $core_file, 'wp-content' ); - } - $core_version = self::get_file_version( $core_path ); - $theme_version = self::get_file_version( $theme_file ); - - $status = esc_html__( 'Theme version up to date', 'ultimate-member' ); - $status_code = 1; - if ( version_compare( $theme_version, $core_version, '<' ) ) { - $status = esc_html__( 'Theme version is out of date', 'ultimate-member' ); - $status_code = 0; - } - if ( '' === $theme_version ) { - $status = esc_html__( 'Theme version is empty', 'ultimate-member' ); - $status_code = 0; - } - if ( 0 === $status_code ) { - $out_date = true; - update_option( 'um_override_templates_outdated', true ); - } - $outdated_files[] = array( - 'core_version' => $core_version, - 'theme_version' => $theme_version, - 'core_file' => $core_file_path, - 'theme_file' => stristr( $theme_file, 'wp-content' ), - 'status' => $status, - 'status_code' => $status_code, - ); - } - } - } - } - - if ( false === $out_date ) { - delete_option( 'um_override_templates_outdated' ); - } - update_option( 'um_template_statuses', $outdated_files ); - if ( true === $get_list ) { - return $outdated_files; - } - } - - /** * Scan the template files. * @@ -3532,58 +3401,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { * @return array */ public static function scan_template_files( $template_path ) { - $files = @scandir( $template_path ); // @codingStandardsIgnoreLine. - $result = array(); - - if ( ! empty( $files ) ) { - - foreach ( $files as $value ) { - - if ( ! in_array( $value, array( '.', '..' ), true ) ) { - - if ( is_dir( $template_path . DIRECTORY_SEPARATOR . $value ) ) { - $sub_files = self::scan_template_files( $template_path . DIRECTORY_SEPARATOR . $value ); - foreach ( $sub_files as $sub_file ) { - $result[] = $value . DIRECTORY_SEPARATOR . $sub_file; - } - } else { - $result[] = $value; - } - } - } - } - return $result; - } - - /** - * @param $file string - * - * @return string - */ - public static function get_file_version( $file ) { - // Avoid notices if file does not exist. - if ( ! file_exists( $file ) ) { - return ''; - } - - // We don't need to write to the file, so just open for reading. - $fp = fopen( $file, 'r' ); // @codingStandardsIgnoreLine. - - // Pull only the first 8kiB of the file in. - $file_data = fread( $fp, 8192 ); // @codingStandardsIgnoreLine. - - // PHP will close a file handle, but we are good citizens. - fclose( $fp ); // @codingStandardsIgnoreLine. - - // Make sure we catch CR-only line endings. - $file_data = str_replace( "\r", "\n", $file_data ); - $version = ''; - - if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( '@version', '/' ) . '(.*)$/mi', $file_data, $match ) && $match[1] ) { - $version = _cleanup_header_comment( $match[1] ); - } - - return $version; + return UM()->common()->theme()::scan_template_files( $template_path ); } /** diff --git a/includes/admin/core/list-tables/version-template-list-table.php b/includes/admin/core/list-tables/version-template-list-table.php index bf1360fe..f116b0c8 100644 --- a/includes/admin/core/list-tables/version-template-list-table.php +++ b/includes/admin/core/list-tables/version-template-list-table.php @@ -58,8 +58,7 @@ class UM_Versions_List_Table extends WP_List_Table { $sortable = $this->get_sortable_columns(); $this->_column_headers = array( $columns, array(), $sortable ); - $templates = get_option( 'um_template_statuses', array() ); - $templates = is_array( $templates ) ? $templates : array(); + $templates = UM()->common()->theme()->build_templates_data(); @uasort( $templates, diff --git a/includes/common/class-theme.php b/includes/common/class-theme.php index c667646a..896627ef 100644 --- a/includes/common/class-theme.php +++ b/includes/common/class-theme.php @@ -13,26 +13,230 @@ if ( ! defined( 'ABSPATH' ) ) { class Theme { public function hooks() { - add_action( 'after_switch_theme', array( &$this, 'check_outdated_templates' ) ); + add_action( 'after_switch_theme', array( &$this, 'flush_transient_templates_data' ) ); } /** * Find outdated UM templates and notify Administrator. * */ - public function check_outdated_templates() { - $templates = UM()->admin_settings()->get_override_templates( true ); - $out_date = false; + public function flush_transient_templates_data() { + // Flush transient with the custom templates list. + delete_transient( 'um_custom_templates_list' ); + } - foreach ( $templates as $template ) { - if ( 0 === $template['status_code'] ) { - $out_date = true; + /** + * Scan the template files. + * + * @param string $template_path Path to the template directory. + * @return array + */ + public static function scan_template_files( $template_path ) { + $files = @scandir( $template_path ); // @codingStandardsIgnoreLine. + $result = array(); + + if ( ! empty( $files ) ) { + + foreach ( $files as $value ) { + + if ( ! in_array( $value, array( '.', '..' ), true ) ) { + + if ( is_dir( $template_path . DIRECTORY_SEPARATOR . $value ) ) { + $sub_files = self::scan_template_files( $template_path . DIRECTORY_SEPARATOR . $value ); + foreach ( $sub_files as $sub_file ) { + $result[] = $value . DIRECTORY_SEPARATOR . $sub_file; + } + } else { + $result[] = $value; + } + } + } + } + return $result; + } + + public static function get_all_templates() { + $scan_files['um'] = self::scan_template_files( UM_PATH . '/templates/' ); + /** + * Filters an array of the template files for scanning versions. + * + * @since 2.6.1 + * @hook um_override_templates_scan_files + * + * @param {array} $scan_files Template files for scanning versions. + * + * @return {array} Template files for scanning versions. + */ + return apply_filters( 'um_override_templates_scan_files', $scan_files ); + } + + /** + * @param $file string + * + * @return string + */ + public static function get_file_version( $file ) { + // Avoid notices if file does not exist. + if ( ! file_exists( $file ) ) { + return ''; + } + + // We don't need to write to the file, so just open for reading. + $fp = fopen( $file, 'r' ); // @codingStandardsIgnoreLine. + + // Pull only the first 8kiB of the file in. + $file_data = fread( $fp, 8192 ); // @codingStandardsIgnoreLine. + + // PHP will close a file handle, but we are good citizens. + fclose( $fp ); // @codingStandardsIgnoreLine. + + // Make sure we catch CR-only line endings. + $file_data = str_replace( "\r", "\n", $file_data ); + $version = ''; + + if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( '@version', '/' ) . '(.*)$/mi', $file_data, $match ) && $match[1] ) { + $version = _cleanup_header_comment( $match[1] ); + } + + return $version; + } + + public function get_custom_templates_list() { + $files_in_theme = array(); + $scan_files = self::get_all_templates(); + foreach ( $scan_files as $key => $files ) { + foreach ( $files as $file ) { + if ( false === strpos( $file, 'email/' ) ) { + /** + * Filters an array of the template files for scanning versions based on $key. + * + * Note: $key - means um or extension key. + * + * @since 2.6.1 + * @hook um_override_templates_get_template_path__{$key} + * + * @param {array} $located Template file paths for scanning versions. + * @param {string} $file Template file name. + * + * @return {array} Template file paths for scanning versions. + */ + $located = apply_filters( "um_override_templates_get_template_path__{$key}", array(), $file ); + + $exceptions = array( + 'members-grid.php', + 'members-header.php', + 'members-list.php', + 'members-pagination.php', + 'searchform.php', + 'login-to-view.php', + 'profile/comments.php', + 'profile/comments-single.php', + 'profile/posts.php', + 'profile/posts-single.php', + 'modal/um_upload_single.php', + 'modal/um_view_photo.php', + ); + + $theme_file = false; + if ( ! empty( $located ) ) { + $theme_file = $located['theme']; + } elseif ( in_array( $file, $exceptions, true ) && file_exists( get_stylesheet_directory() . '/ultimate-member/' . $file ) ) { + $theme_file = get_stylesheet_directory() . '/ultimate-member/' . $file; + } elseif ( file_exists( get_stylesheet_directory() . '/ultimate-member/templates/' . $file ) ) { + $theme_file = get_stylesheet_directory() . '/ultimate-member/templates/' . $file; + } + + if ( ! empty( $theme_file ) ) { + if ( ! empty( $located ) ) { + $core_path = $located['core']; + } else { + $core_path = UM_PATH . 'templates/' . $file; + } + + $files_in_theme[] = array( + 'core' => $core_path, + 'theme' => $theme_file, + ); + } + } + } + } + + return $files_in_theme; + } + + public function is_outdated_template_exist() { + $outdated_exists = false; + $templates = $this->get_custom_templates_list(); + foreach ( $templates as $files ) { + if ( ! array_key_exists( 'core', $files ) || ! array_key_exists( 'theme', $files ) ) { + continue; + } + + $core_path = $files['core']; + $theme_file = $files['theme']; + + $core_version = self::get_file_version( $core_path ); + $theme_version = self::get_file_version( $theme_file ); + + if ( '' === $theme_version || version_compare( $theme_version, $core_version, '<' ) ) { + $outdated_exists = true; break; } } - if ( false === $out_date ) { - delete_option( 'um_override_templates_outdated' ); + return $outdated_exists; + } + + public function build_templates_data() { + $templates_data = array(); + + // Get from cache if isn't empty and request isn't force. + $transient = get_transient( 'um_custom_templates_list' ); + if ( false !== $transient && array_key_exists( 'data', $transient ) ) { + return $transient['data']; } + + $templates = $this->get_custom_templates_list(); + foreach ( $templates as $files ) { + if ( ! array_key_exists( 'core', $files ) || ! array_key_exists( 'theme', $files ) ) { + continue; + } + + $core_path = $files['core']; + $theme_file = $files['theme']; + + $core_version = self::get_file_version( $core_path ); + $theme_version = self::get_file_version( $theme_file ); + + $status = esc_html__( 'Theme version up to date', 'ultimate-member' ); + $status_code = 1; + + if ( '' === $theme_version ) { + $status = esc_html__( 'Theme version is empty', 'ultimate-member' ); + $status_code = 0; + } elseif ( version_compare( $theme_version, $core_version, '<' ) ) { + $status = esc_html__( 'Theme version is out of date', 'ultimate-member' ); + $status_code = 0; + } + + $templates_data[] = array( + 'core_version' => $core_version, + 'theme_version' => $theme_version, + 'core_file' => stristr( $core_path, 'wp-content' ), + 'theme_file' => stristr( $theme_file, 'wp-content' ), + 'status' => $status, + 'status_code' => $status_code, + ); + } + + // Cache results via transient setting. + $transient = array( + 'data' => $templates_data, + 'time' => time(), + ); + set_transient( 'um_custom_templates_list', $transient, 5 * MINUTE_IN_SECONDS ); + + return $templates_data; } }