Server : Apache System : Linux pod-100823:apache2_74:v0.5.7 5.4.0-1138-gcp #147~18.04.1-Ubuntu SMP Mon Oct 7 21:46:26 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33.7 Disable Function : apache_child_terminate,apache_get_modules,apache_get_version,apache_getenv,apache_note,apache_setenv,disk_free_space,disk_total_space,diskfreespace,dl,exec,fastcgi_finish_request,link,opcache_compile_file,opcache_get_configuration,opcache_invalidate,opcache_is_script_cached,opcache_reset,passthru,pclose,pcntl_exec,popen,posix_getpid,posix_getppid,posix_getpwuid,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_uname,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,realpath_cache_get,shell_exec,show_source,symlink,system Directory : /nas/content/live/attorneyexperi/wp-content/plugins/diva/src/ |
<?php /** * Class ReaderThemeLoader. * * @package AmpProject\AmpWP */ namespace AmpProject\AmpWP; use AmpProject\AmpWP\Infrastructure\Registerable; use AmpProject\AmpWP\Infrastructure\Service; use AMP_Options_Manager; use AMP_Theme_Support; use AmpProject\AmpWP\Admin\ReaderThemes; use WP_Theme; use WP_Customize_Manager; /** * Switches to the designated Reader theme when template mode enabled and when requesting an AMP page. * * This class does not implement Conditional because other services need to always be able to access this * service in order to determine whether or a Reader theme is loaded, and if so, what the previously-active theme was. * * @package AmpProject\AmpWP * @since 2.0 * @internal */ final class ReaderThemeLoader implements Service, Registerable { /** * Paired routing service. * * @var PairedRouting */ private $paired_routing; /** * Reader theme. * * @var WP_Theme|null */ private $reader_theme; /** * Active theme. * * Theme which was active before switching to the Reader theme. * * @var WP_Theme */ private $active_theme; /** * Whether the active theme was overridden with the Reader theme. * * @var bool */ private $theme_overridden = false; /** * ReaderThemeLoader constructor. * * @param PairedRouting $paired_routing Paired routing service. */ public function __construct( PairedRouting $paired_routing ) { $this->paired_routing = $paired_routing; } /** * Is Reader mode with a Reader theme selected. * * @param array $options Options to check. If omitted, the currently-saved options are used. * @return bool Whether new Reader mode. */ public function is_enabled( $options = null ) { // If the theme was overridden then we know it is enabled. We can't check get_template() at this point because // it will be identical to $reader_theme. if ( $this->is_theme_overridden() ) { return true; } if ( null === $options ) { $options = AMP_Options_Manager::get_options(); } // If Reader mode is not enabled, then a Reader theme is definitely not going to be served. if ( ! isset( $options[ Option::THEME_SUPPORT ] ) || AMP_Theme_Support::READER_MODE_SLUG !== $options[ Option::THEME_SUPPORT ] ) { return false; } // If the Legacy Reader mode is active, then a Reader theme is not going to be served. if ( ! isset( $options[ Option::READER_THEME ] ) ) { return false; } $reader_theme = $options[ Option::READER_THEME ]; if ( ReaderThemes::DEFAULT_READER_THEME === $reader_theme ) { return false; } // If the Reader theme does not exist, then we cannot switch to the reader theme. The Legacy Reader theme will // be used as a fallback instead. if ( ! wp_get_theme( $reader_theme )->exists() ) { return false; } // Lastly, if the active theme is not the same as the reader theme, then we can switch to the reader theme. // Otherwise, the site should instead be in Transitional mode. Note that get_stylesheet() is used as opposed // to get_template() because the active theme should be allowed to be a child theme of a Reader theme. return get_stylesheet() !== $reader_theme; } /** * Whether the active theme was overridden with the reader theme. * * @return bool Whether theme overridden. */ public function is_theme_overridden() { return $this->theme_overridden; } /** * Register the service with the system. * * @return void */ public function register() { // The following needs to run at plugins_loaded because that is when _wp_customize_include runs. Otherwise, the // most logical action would be setup_theme. add_action( 'plugins_loaded', [ $this, 'override_theme' ], 9 ); add_filter( 'wp_prepare_themes_for_js', [ $this, 'filter_wp_prepare_themes_to_indicate_reader_theme' ] ); add_action( 'admin_print_footer_scripts-themes.php', [ $this, 'inject_theme_single_template_modifications' ] ); } /** * Filter themes for JS to remove action to delete the selected Reader theme and show a notice. * * @param array $prepared_themes Array of theme data. * @return array Themes. */ public function filter_wp_prepare_themes_to_indicate_reader_theme( $prepared_themes ) { if ( ! $this->is_enabled() ) { return $prepared_themes; } $reader_theme_obj = $this->get_reader_theme(); if ( ! $reader_theme_obj instanceof WP_Theme ) { return $prepared_themes; } $reader_theme = $reader_theme_obj->get_stylesheet(); if ( isset( $prepared_themes[ $reader_theme ] ) ) { // Make sure the AMP Reader theme appears right after the active theme in the list. $stylesheet = get_stylesheet(); if ( isset( $prepared_themes[ $stylesheet ] ) ) { $prepared_themes = array_merge( [ $stylesheet => $prepared_themes[ $stylesheet ], $reader_theme => $prepared_themes[ $reader_theme ], ], $prepared_themes ); } // Prevent Reader theme from being deleted. unset( $prepared_themes[ $reader_theme ]['actions']['delete'] ); // Make sure the Customize link goes to AMP. $prepared_themes[ $reader_theme ]['actions']['customize'] = amp_get_customizer_url(); // Force the theme to be styled as Active. $prepared_themes[ $reader_theme ]['active'] = true; // Make sure the hacked Backbone template will use the AMP action links. $prepared_themes[ $reader_theme ]['ampActiveReaderTheme'] = true; // Add AMP Reader theme notice. $prepared_themes[ $reader_theme ]['ampReaderThemeNotice'] = sprintf( wp_kses( /* translators: placeholder is link to AMP settings screen */ __( 'This has been <a href="%s">selected</a> as the AMP Reader theme.', 'amp' ), [ 'a' => [ 'href' => true ], ] ), esc_url( add_query_arg( 'page', AMP_Options_Manager::OPTION_NAME, admin_url( 'admin.php' ) ) . '#reader-themes' ) ); } return $prepared_themes; } /** * Inject new logic into the Backbone templates for rendering a theme lightbox. * * This is admittedly hacky, but WordPress doesn't provide a much better option. */ public function inject_theme_single_template_modifications() { if ( ! $this->is_enabled() ) { return; } $reader_theme = $this->get_reader_theme(); if ( ! $reader_theme instanceof WP_Theme ) { return; } ?> <script> (function( themeSingleTmpl ) { if ( ! themeSingleTmpl ) { return; } let text = themeSingleTmpl.text; text = text.replace( /(?=<p class="theme-description">)/, ` <# if ( data.ampReaderThemeNotice ) { #> <div class="notice notice-info notice-alt inline"> <p>{{{ data.ampReaderThemeNotice }}}</p><?php // phpcs:ignore WordPressVIPMinimum.Security.Mustache.OutputNotation -- Contains link and already sanitized with Kses. ?> </div> <# } #> ` ); // Inject our action links. text = text.replace( /(<div class="active-theme">)((?:.|\s)+?)(<\/div>)/, ( match, startDiv, actionLinks, endDiv ) => { return ` ${startDiv} <# if ( data.ampActiveReaderTheme ) { #> <a href="{{ data.actions.customize }}" class="button button-primary customize load-customize hide-if-no-customize"> <?php esc_html_e( 'Customize', 'default' ); ?> </a> <a href="<?php echo esc_url( add_query_arg( 'page', AMP_Options_Manager::OPTION_NAME, admin_url( 'admin.php' ) ) ); ?>" class="button button-secondary"> <?php esc_html_e( 'AMP Settings', 'amp' ); ?> </a> <# } else { #> ${actionLinks} <# } #> ${endDiv} `; } ); themeSingleTmpl.text = text; })( document.getElementById( 'tmpl-theme-single' ) ); (function ( themeTmpl, ssrThemeNamePrefixElement ) { // First update the card that was rendered server-side in wp-admin/themes.php. if ( ssrThemeNamePrefixElement ) { ssrThemeNamePrefixElement.textContent = <?php echo wp_json_encode( _x( 'Reader:', 'prefix for theme card in list', 'amp' ) ); ?>; } // Then update the Mustache template so that future renders will also have the proper prefix. if ( themeTmpl ) { themeTmpl.text = themeTmpl.text.replace( /(<div class="theme-id-container">)(\s*<# if)/, function ( match, startDiv ) { return ` ${startDiv} <# if ( data.ampActiveReaderTheme ) { #> <h2 class="theme-name" id="{{ data.id }}-name"> <span><?php echo esc_html( _x( 'Reader:', 'prefix for theme card in list', 'amp' ) ); ?></span> {{ data.name }} </h2> <# } else if `; } ); } }) ( document.getElementById( 'tmpl-theme' ), document.querySelector( <?php echo wp_json_encode( sprintf( '#%s-name > span', $reader_theme->get_stylesheet() ) ); ?> ) ); </script> <?php } /** * Get reader theme. * * If the Reader template mode is enabled * * @return WP_Theme|null Theme if selected and no errors. */ public function get_reader_theme() { if ( $this->reader_theme instanceof WP_Theme ) { return $this->reader_theme; } $reader_theme_slug = AMP_Options_Manager::get_option( Option::READER_THEME ); if ( ! $reader_theme_slug ) { return null; } $reader_theme = wp_get_theme( $reader_theme_slug ); if ( $reader_theme->errors() ) { return null; } return $reader_theme; } /** * Get active theme. * * The theme that was active before switching to the Reader theme. * * @return WP_Theme WP_Theme instance. */ public function get_active_theme() { return $this->active_theme; } /** * Switch theme if in Reader mode, a Reader theme was selected, and the AMP query var is present. * * Note that AMP_Theme_Support will redirect to the non-AMP version if AMP is not available for the query. * * @see WP_Customize_Manager::start_previewing_theme() which provides for much of the inspiration here. * @see switch_theme() which ensures the new theme includes the old theme's theme mods. */ public function override_theme() { $this->theme_overridden = false; if ( ! $this->is_enabled() || ! $this->paired_routing->has_endpoint() ) { return; } $theme = $this->get_reader_theme(); if ( ! $theme instanceof WP_Theme ) { return; } $this->active_theme = wp_get_theme(); $this->reader_theme = $theme; $this->theme_overridden = true; $get_template = function () { return $this->reader_theme->get_template(); }; $get_stylesheet = function () { return $this->reader_theme->get_stylesheet(); }; add_filter( 'stylesheet', $get_stylesheet ); add_filter( 'template', $get_template ); add_filter( 'pre_option_current_theme', function () { return $this->reader_theme->display( 'Name' ); } ); // @link: https://core.trac.wordpress.org/ticket/20027 add_filter( 'pre_option_stylesheet', $get_stylesheet ); add_filter( 'pre_option_template', $get_template ); // Handle custom theme roots. add_filter( 'pre_option_stylesheet_root', function () { return get_raw_theme_root( $this->reader_theme->get_stylesheet(), true ); } ); add_filter( 'pre_option_template_root', function () { return get_raw_theme_root( $this->reader_theme->get_template(), true ); } ); $this->disable_widgets(); add_filter( 'customize_previewable_devices', [ $this, 'customize_previewable_devices' ] ); add_action( 'customize_register', [ $this, 'remove_customizer_themes_panel' ], 11 ); } /** * Disable widgets. */ public function disable_widgets() { add_filter( 'sidebars_widgets', '__return_empty_array', PHP_INT_MAX ); add_filter( 'customize_loaded_components', static function( $components ) { return array_diff( $components, [ 'widgets' ] ); } ); remove_theme_support( 'widgets-block-editor' ); } /** * Make tablet (smartphone) the default device when opening AMP Customizer. * * @param array $devices Devices. * @return array Devices. */ public function customize_previewable_devices( $devices ) { if ( isset( $devices['tablet'] ) ) { unset( $devices['desktop']['default'] ); $devices['tablet']['default'] = true; } return $devices; } /** * Remove themes panel from AMP Customizer. * * @param WP_Customize_Manager $wp_customize Customize manager. */ public function remove_customizer_themes_panel( WP_Customize_Manager $wp_customize ) { $wp_customize->remove_panel( 'themes' ); } }