support', 10, 2 ); /** * Register the service with the system. * * @return void */ public function register() { add_filter( 'amp_options_updating', [ $this, 'filter_amp_options_updating' ] ); add_action( 'after_switch_theme', [ $this, 'handle_theme_update' ] ); add_action( self::ACTION_UPDATE_CACHED_PRIMARY_THEME_SUPPORT, [ $this, 'update_cached_theme_support' ] ); add_action( 'upgrader_process_complete', function ( $upgrader ) { if ( $upgrader instanceof Theme_Upgrader ) { $this->update_cached_theme_support(); } } ); add_action( 'amp_post_template_head', [ $this, 'print_theme_support_styles' ] ); add_action( 'wp_head', [ $this, 'print_theme_support_styles' ], 9 // Because wp_print_styles happens at priority 8, and we want the primary theme's colors to override any conflicting theme color assignments. ); } /** * Check whether all the required props are present for a given feature item. * * @param string $feature Feature name. * @param array $props Props to check. * * @return bool Whether all are present. */ public function has_required_feature_props( $feature, $props ) { if ( empty( $props ) || ! is_array( $props ) ) { return false; } foreach ( self::SUPPORTED_FEATURES[ $feature ] as $required_prop ) { if ( ! array_key_exists( $required_prop, $props ) ) { return false; } } return true; } /** * Filter the AMP options when they are updated to add the primary theme's features. * * @param array $options Options. * @return array Options. */ public function filter_amp_options_updating( $options ) { if ( $this->reader_theme_loader->is_enabled( $options ) ) { $options[ Option::PRIMARY_THEME_SUPPORT ] = $this->get_theme_support_features( true ); } else { $options[ Option::PRIMARY_THEME_SUPPORT ] = null; } return $options; } /** * Handle updating the cached primary_theme_support after updating/switching theme. * * In the case of switching the theme via WP-CLI, it could be that the next request is for an AMP page and * the `check_theme_switched()` function will run in the context of a Reader theme being loaded. In that case, * the added theme support won't be for the primary theme and we need to schedule an immediate event in WP-Cron to * try again in the context of a cron request in which a Reader theme will never be overriding the primary theme. */ public function handle_theme_update() { if ( $this->reader_theme_loader->is_theme_overridden() ) { wp_schedule_single_event( time(), self::ACTION_UPDATE_CACHED_PRIMARY_THEME_SUPPORT ); } else { $this->update_cached_theme_support(); } } /** * Update primary theme's cached theme support. */ public function update_cached_theme_support() { if ( $this->reader_theme_loader->is_enabled() ) { AMP_Options_Manager::update_option( Option::PRIMARY_THEME_SUPPORT, $this->get_theme_support_features( true ) ); } else { AMP_Options_Manager::update_option( Option::PRIMARY_THEME_SUPPORT, null ); } } /** * Get the theme support features. * * @param bool $reduced Whether to reduce the feature props down to just what is required. * @return array Theme support features. */ public function get_theme_support_features( $reduced = false ) { $features = []; foreach ( array_keys( self::SUPPORTED_FEATURES ) as $feature_key ) { if ( wp_theme_has_theme_json() ) { $feature_value = []; $global_settings = wp_get_global_settings( self::SUPPORTED_THEME_JSON_FEATURES[ $feature_key ], self::KEY_THEME ); if ( isset( $global_settings[ self::KEY_THEME ] ) ) { $feature_value = array_merge( $feature_value, $global_settings[ self::KEY_THEME ] ); } if ( isset( $global_settings[ self::KEY_DEFAULT ] ) ) { $feature_value = array_merge( $feature_value, $global_settings[ self::KEY_DEFAULT ] ); } } else { $feature_value = current( (array) get_theme_support( $feature_key ) ); } if ( ! is_array( $feature_value ) || empty( $feature_value ) ) { continue; } // Avoid reducing font sizes if theme.json is used for the sake of fluid typography. if ( wp_theme_has_theme_json() && self::FEATURE_EDITOR_FONT_SIZES === $feature_key ) { $reduced = false; } if ( $reduced ) { $features[ $feature_key ] = []; foreach ( $feature_value as $item ) { if ( $this->has_required_feature_props( $feature_key, $item ) ) { $features[ $feature_key ][] = wp_array_slice_assoc( $item, self::SUPPORTED_FEATURES[ $feature_key ] ); } } } else { $features[ $feature_key ] = $feature_value; } } return $features; } /** * Determines whether the request is for an AMP page in Reader mode. * * @return bool Whether AMP Reader request. */ public function is_reader_request() { return ( ( amp_is_legacy() || $this->reader_theme_loader->is_theme_overridden() ) && amp_is_request() ); } /** * Print theme support styles. */ public function print_theme_support_styles() { if ( ! $this->is_reader_request() ) { return; } $features = []; if ( $this->reader_theme_loader->is_enabled() ) { $features = AMP_Options_Manager::get_option( Option::PRIMARY_THEME_SUPPORT ); } elseif ( amp_is_legacy() ) { $features = $this->get_theme_support_features(); } if ( empty( $features ) ) { return; } foreach ( array_keys( self::SUPPORTED_FEATURES ) as $feature ) { if ( empty( $features[ $feature ] ) || ! is_array( $features[ $feature ] ) ) { continue; } $value = $features[ $feature ]; switch ( $feature ) { case self::FEATURE_EDITOR_COLOR_PALETTE: $this->print_editor_color_palette_styles( $value ); break; case self::FEATURE_EDITOR_FONT_SIZES: $this->print_editor_font_sizes_styles( $value ); break; case self::FEATURE_EDITOR_GRADIENT_PRESETS: $this->print_editor_gradient_presets_styles( $value ); break; } } // Print the custom properties for the spacing sizes. if ( wp_theme_has_theme_json() ) { $this->print_spacing_sizes_custom_properties(); } } /** * Print editor-color-palette styles. * * @param array $color_palette Color palette. */ private function print_editor_color_palette_styles( array $color_palette ) { echo ''; } /** * Print editor-font-sizes styles. * * @param array $font_sizes Font sizes. */ private function print_editor_font_sizes_styles( array $font_sizes ) { echo ''; } /** * Print editor-gradient-presets styles. * * @param array $gradient_presets Gradient presets. */ private function print_editor_gradient_presets_styles( array $gradient_presets ) { echo ''; } /** * Print spacing sizes custom properties. */ private function print_spacing_sizes_custom_properties() { $custom_properties = []; $spacing = wp_get_global_settings( [ self::KEY_SPACING ], self::KEY_THEME ); $spacing_sizes = $spacing[ self::KEY_SPACING_SIZES ] ?? []; $custom_spacing_size = $spacing[ self::KEY_CUSTOM_SPACING_SIZE ] ?? false; $spacing_scale = $spacing[ self::KEY_SPACING_SCALE ] ?? []; /** * By default check for `defaultSpacingSizes` boolean introduced in theme.json (v3) * and if it's false, then check for `steps` in `spacingScale` which is v2 default. * * @see . */ $is_wp_generating_spacing_sizes = $spacing[ self::KEY_DEFAULT_SPACING_SIZES ] ?? false; if ( array_key_exists( self::KEY_STEPS, $spacing_scale ) ) { $is_wp_generating_spacing_sizes = 0 !== $spacing_scale[ self::KEY_STEPS ]; } if ( ! $is_wp_generating_spacing_sizes && $custom_spacing_size ) { if ( isset( $spacing_sizes[ self::KEY_THEME ] ) ) { $custom_properties = array_merge( $custom_properties, $spacing_sizes[ self::KEY_THEME ] ); } } else { if ( isset( $spacing_sizes[ self::KEY_DEFAULT ] ) ) { $custom_properties = array_merge( $custom_properties, $spacing_sizes[ self::KEY_DEFAULT ] ); } } if ( empty( $custom_properties ) ) { return; } echo ''; } /** * Get relative luminance from color hex value. * * Copied from `\Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex()`. * * @see https://github.com/WordPress/wordpress-develop/blob/acbbbd18b32b5429264622141a6d058b64f3a5ad/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-custom-colors.php#L138-L156 * * @param string $hex Color hex value. * @return int Relative luminance value. */ public function get_relative_luminance_from_hex( $hex ) { // Remove the "#" symbol from the beginning of the color. $hex = ltrim( $hex, '#' ); // Make sure there are 6 digits for the below calculations. if ( 3 === strlen( $hex ) ) { $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2]; } // Get red, green, blue. $red = hexdec( substr( $hex, 0, 2 ) ); $green = hexdec( substr( $hex, 2, 2 ) ); $blue = hexdec( substr( $hex, 4, 2 ) ); // Calculate the luminance. $lum = ( 0.2126 * $red ) + ( 0.7152 * $green ) + ( 0.0722 * $blue ); return (int) round( $lum ); } } /** * Register the service with the system. * * @return void */ public function register() { add_filter( 'amp_options_updating', [ $this, 'filter_amp_options_updating' ] ); add_action( 'after_switch_theme', [ $this, 'handle_theme_update' ] ); add_action( self::ACTION_UPDATE_CACHED_PRIMARY_THEME_SUPPORT, [ $this, 'update_cached_theme_support' ] ); add_action( 'upgrader_process_complete', function ( $upgrader ) { if ( $upgrader instanceof Theme_Upgrader ) { $this->update_cached_theme_support(); } } ); add_action( 'amp_post_template_head', [ $this, 'print_theme_support_styles' ] ); add_action( 'wp_head', [ $this, 'print_theme_support_styles' ], 9 // Because wp_print_styles happens at priority 8, and we want the primary theme's colors to override any conflicting theme color assignments. ); } /** * Check whether all the required props are present for a given feature item. * * @param string $feature Feature name. * @param array $props Props to check. * * @return bool Whether all are present. */ public function has_required_feature_props( $feature, $props ) { if ( empty( $props ) || ! is_array( $props ) ) { return false; } foreach ( self::SUPPORTED_FEATURES[ $feature ] as $required_prop ) { if ( ! array_key_exists( $required_prop, $props ) ) { return false; } } return true; } /** * Filter the AMP options when they are updated to add the primary theme's features. * * @param array $options Options. * @return array Options. */ public function filter_amp_options_updating( $options ) { if ( $this->reader_theme_loader->is_enabled( $options ) ) { $options[ Option::PRIMARY_THEME_SUPPORT ] = $this->get_theme_support_features( true ); } else { $options[ Option::PRIMARY_THEME_SUPPORT ] = null; } return $options; } /** * Handle updating the cached primary_theme_support after updating/switching theme. * * In the case of switching the theme via WP-CLI, it could be that the next request is for an AMP page and * the `check_theme_switched()` function will run in the context of a Reader theme being loaded. In that case, * the added theme support won't be for the primary theme and we need to schedule an immediate event in WP-Cron to * try again in the context of a cron request in which a Reader theme will never be overriding the primary theme. */ public function handle_theme_update() { if ( $this->reader_theme_loader->is_theme_overridden() ) { wp_schedule_single_event( time(), self::ACTION_UPDATE_CACHED_PRIMARY_THEME_SUPPORT ); } else { $this->update_cached_theme_support(); } } /** * Update primary theme's cached theme support. */ public function update_cached_theme_support() { if ( $this->reader_theme_loader->is_enabled() ) { AMP_Options_Manager::update_option( Option::PRIMARY_THEME_SUPPORT, $this->get_theme_support_features( true ) ); } else { AMP_Options_Manager::update_option( Option::PRIMARY_THEME_SUPPORT, null ); } } /** * Get the theme support features. * * @param bool $reduced Whether to reduce the feature props down to just what is required. * @return array Theme support features. */ public function get_theme_support_features( $reduced = false ) { $features = []; foreach ( array_keys( self::SUPPORTED_FEATURES ) as $feature_key ) { if ( wp_theme_has_theme_json() ) { $feature_value = []; $global_settings = wp_get_global_settings( self::SUPPORTED_THEME_JSON_FEATURES[ $feature_key ], self::KEY_THEME ); if ( isset( $global_settings[ self::KEY_THEME ] ) ) { $feature_value = array_merge( $feature_value, $global_settings[ self::KEY_THEME ] ); } if ( isset( $global_settings[ self::KEY_DEFAULT ] ) ) { $feature_value = array_merge( $feature_value, $global_settings[ self::KEY_DEFAULT ] ); } } else { $feature_value = current( (array) get_theme_support( $feature_key ) ); } if ( ! is_array( $feature_value ) || empty( $feature_value ) ) { continue; } // Avoid reducing font sizes if theme.json is used for the sake of fluid typography. if ( wp_theme_has_theme_json() && self::FEATURE_EDITOR_FONT_SIZES === $feature_key ) { $reduced = false; } if ( $reduced ) { $features[ $feature_key ] = []; foreach ( $feature_value as $item ) { if ( $this->has_required_feature_props( $feature_key, $item ) ) { $features[ $feature_key ][] = wp_array_slice_assoc( $item, self::SUPPORTED_FEATURES[ $feature_key ] ); } } } else { $features[ $feature_key ] = $feature_value; } } return $features; } /** * Determines whether the request is for an AMP page in Reader mode. * * @return bool Whether AMP Reader request. */ public function is_reader_request() { return ( ( amp_is_legacy() || $this->reader_theme_loader->is_theme_overridden() ) && amp_is_request() ); } /** * Print theme support styles. */ public function print_theme_support_styles() { if ( ! $this->is_reader_request() ) { return; } $features = []; if ( $this->reader_theme_loader->is_enabled() ) { $features = AMP_Options_Manager::get_option( Option::PRIMARY_THEME_SUPPORT ); } elseif ( amp_is_legacy() ) { $features = $this->get_theme_support_features(); } if ( empty( $features ) ) { return; } foreach ( array_keys( self::SUPPORTED_FEATURES ) as $feature ) { if ( empty( $features[ $feature ] ) || ! is_array( $features[ $feature ] ) ) { continue; } $value = $features[ $feature ]; switch ( $feature ) { case self::FEATURE_EDITOR_COLOR_PALETTE: $this->print_editor_color_palette_styles( $value ); break; case self::FEATURE_EDITOR_FONT_SIZES: $this->print_editor_font_sizes_styles( $value ); break; case self::FEATURE_EDITOR_GRADIENT_PRESETS: $this->print_editor_gradient_presets_styles( $value ); break; } } // Print the custom properties for the spacing sizes. if ( wp_theme_has_theme_json() ) { $this->print_spacing_sizes_custom_properties(); } } /** * Print editor-color-palette styles. * * @param array $color_palette Color palette. */ private function print_editor_color_palette_styles( array $color_palette ) { echo ''; } /** * Print editor-font-sizes styles. * * @param array $font_sizes Font sizes. */ private function print_editor_font_sizes_styles( array $font_sizes ) { echo ''; } /** * Print editor-gradient-presets styles. * * @param array $gradient_presets Gradient presets. */ private function print_editor_gradient_presets_styles( array $gradient_presets ) { echo ''; } /** * Print spacing sizes custom properties. */ private function print_spacing_sizes_custom_properties() { $custom_properties = []; $spacing = wp_get_global_settings( [ self::KEY_SPACING ], self::KEY_THEME ); $spacing_sizes = $spacing[ self::KEY_SPACING_SIZES ] ?? []; $custom_spacing_size = $spacing[ self::KEY_CUSTOM_SPACING_SIZE ] ?? false; $spacing_scale = $spacing[ self::KEY_SPACING_SCALE ] ?? []; /** * By default check for `defaultSpacingSizes` boolean introduced in theme.json (v3) * and if it's false, then check for `steps` in `spacingScale` which is v2 default. * * @see . */ $is_wp_generating_spacing_sizes = $spacing[ self::KEY_DEFAULT_SPACING_SIZES ] ?? false; if ( array_key_exists( self::KEY_STEPS, $spacing_scale ) ) { $is_wp_generating_spacing_sizes = 0 !== $spacing_scale[ self::KEY_STEPS ]; } if ( ! $is_wp_generating_spacing_sizes && $custom_spacing_size ) { if ( isset( $spacing_sizes[ self::KEY_THEME ] ) ) { $custom_properties = array_merge( $custom_properties, $spacing_sizes[ self::KEY_THEME ] ); } } else { if ( isset( $spacing_sizes[ self::KEY_DEFAULT ] ) ) { $custom_properties = array_merge( $custom_properties, $spacing_sizes[ self::KEY_DEFAULT ] ); } } if ( empty( $custom_properties ) ) { return; } echo ''; } /** * Get relative luminance from color hex value. * * Copied from `\Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex()`. * * @see https://github.com/WordPress/wordpress-develop/blob/acbbbd18b32b5429264622141a6d058b64f3a5ad/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-custom-colors.php#L138-L156 * * @param string $hex Color hex value. * @return int Relative luminance value. */ public function get_relative_luminance_from_hex( $hex ) { // Remove the "#" symbol from the beginning of the color. $hex = ltrim( $hex, '#' ); // Make sure there are 6 digits for the below calculations. if ( 3 === strlen( $hex ) ) { $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2]; } // Get red, green, blue. $red = hexdec( substr( $hex, 0, 2 ) ); $green = hexdec( substr( $hex, 2, 2 ) ); $blue = hexdec( substr( $hex, 4, 2 ) ); // Calculate the luminance. $lum = ( 0.2126 * $red ) + ( 0.7152 * $green ) + ( 0.0722 * $blue ); return (int) round( $lum ); } } /** * Register the service with the system. * * @return void */ public function register() { add_filter( 'amp_options_updating', [ $this, 'filter_amp_options_updating' ] ); add_action( 'after_switch_theme', [ $this, 'handle_theme_update' ] ); add_action( self::ACTION_UPDATE_CACHED_PRIMARY_THEME_SUPPORT, [ $this, 'update_cached_theme_support' ] ); add_action( 'upgrader_process_complete', function ( $upgrader ) { if ( $upgrader instanceof Theme_Upgrader ) { $this->update_cached_theme_support(); } } ); add_action( 'amp_post_template_head', [ $this, 'print_theme_support_styles' ] ); add_action( 'wp_head', [ $this, 'print_theme_support_styles' ], 9 // Because wp_print_styles happens at priority 8, and we want the primary theme's colors to override any conflicting theme color assignments. ); } /** * Check whether all the required props are present for a given feature item. * * @param string $feature Feature name. * @param array $props Props to check. * * @return bool Whether all are present. */ public function has_required_feature_props( $feature, $props ) { if ( empty( $props ) || ! is_array( $props ) ) { return false; } foreach ( self::SUPPORTED_FEATURES[ $feature ] as $required_prop ) { if ( ! array_key_exists( $required_prop, $props ) ) { return false; } } return true; } /** * Filter the AMP options when they are updated to add the primary theme's features. * * @param array $options Options. * @return array Options. */ public function filter_amp_options_updating( $options ) { if ( $this->reader_theme_loader->is_enabled( $options ) ) { $options[ Option::PRIMARY_THEME_SUPPORT ] = $this->get_theme_support_features( true ); } else { $options[ Option::PRIMARY_THEME_SUPPORT ] = null; } return $options; } /** * Handle updating the cached primary_theme_support after updating/switching theme. * * In the case of switching the theme via WP-CLI, it could be that the next request is for an AMP page and * the `check_theme_switched()` function will run in the context of a Reader theme being loaded. In that case, * the added theme support won't be for the primary theme and we need to schedule an immediate event in WP-Cron to * try again in the context of a cron request in which a Reader theme will never be overriding the primary theme. */ public function handle_theme_update() { if ( $this->reader_theme_loader->is_theme_overridden() ) { wp_schedule_single_event( time(), self::ACTION_UPDATE_CACHED_PRIMARY_THEME_SUPPORT ); } else { $this->update_cached_theme_support(); } } /** * Update primary theme's cached theme support. */ public function update_cached_theme_support() { if ( $this->reader_theme_loader->is_enabled() ) { AMP_Options_Manager::update_option( Option::PRIMARY_THEME_SUPPORT, $this->get_theme_support_features( true ) ); } else { AMP_Options_Manager::update_option( Option::PRIMARY_THEME_SUPPORT, null ); } } /** * Get the theme support features. * * @param bool $reduced Whether to reduce the feature props down to just what is required. * @return array Theme support features. */ public function get_theme_support_features( $reduced = false ) { $features = []; foreach ( array_keys( self::SUPPORTED_FEATURES ) as $feature_key ) { if ( wp_theme_has_theme_json() ) { $feature_value = []; $global_settings = wp_get_global_settings( self::SUPPORTED_THEME_JSON_FEATURES[ $feature_key ], self::KEY_THEME ); if ( isset( $global_settings[ self::KEY_THEME ] ) ) { $feature_value = array_merge( $feature_value, $global_settings[ self::KEY_THEME ] ); } if ( isset( $global_settings[ self::KEY_DEFAULT ] ) ) { $feature_value = array_merge( $feature_value, $global_settings[ self::KEY_DEFAULT ] ); } } else { $feature_value = current( (array) get_theme_support( $feature_key ) ); } if ( ! is_array( $feature_value ) || empty( $feature_value ) ) { continue; } // Avoid reducing font sizes if theme.json is used for the sake of fluid typography. if ( wp_theme_has_theme_json() && self::FEATURE_EDITOR_FONT_SIZES === $feature_key ) { $reduced = false; } if ( $reduced ) { $features[ $feature_key ] = []; foreach ( $feature_value as $item ) { if ( $this->has_required_feature_props( $feature_key, $item ) ) { $features[ $feature_key ][] = wp_array_slice_assoc( $item, self::SUPPORTED_FEATURES[ $feature_key ] ); } } } else { $features[ $feature_key ] = $feature_value; } } return $features; } /** * Determines whether the request is for an AMP page in Reader mode. * * @return bool Whether AMP Reader request. */ public function is_reader_request() { return ( ( amp_is_legacy() || $this->reader_theme_loader->is_theme_overridden() ) && amp_is_request() ); } /** * Print theme support styles. */ public function print_theme_support_styles() { if ( ! $this->is_reader_request() ) { return; } $features = []; if ( $this->reader_theme_loader->is_enabled() ) { $features = AMP_Options_Manager::get_option( Option::PRIMARY_THEME_SUPPORT ); } elseif ( amp_is_legacy() ) { $features = $this->get_theme_support_features(); } if ( empty( $features ) ) { return; } foreach ( array_keys( self::SUPPORTED_FEATURES ) as $feature ) { if ( empty( $features[ $feature ] ) || ! is_array( $features[ $feature ] ) ) { continue; } $value = $features[ $feature ]; switch ( $feature ) { case self::FEATURE_EDITOR_COLOR_PALETTE: $this->print_editor_color_palette_styles( $value ); break; case self::FEATURE_EDITOR_FONT_SIZES: $this->print_editor_font_sizes_styles( $value ); break; case self::FEATURE_EDITOR_GRADIENT_PRESETS: $this->print_editor_gradient_presets_styles( $value ); break; } } // Print the custom properties for the spacing sizes. if ( wp_theme_has_theme_json() ) { $this->print_spacing_sizes_custom_properties(); } } /** * Print editor-color-palette styles. * * @param array $color_palette Color palette. */ private function print_editor_color_palette_styles( array $color_palette ) { echo ''; } /** * Print editor-font-sizes styles. * * @param array $font_sizes Font sizes. */ private function print_editor_font_sizes_styles( array $font_sizes ) { echo ''; } /** * Print editor-gradient-presets styles. * * @param array $gradient_presets Gradient presets. */ private function print_editor_gradient_presets_styles( array $gradient_presets ) { echo ''; } /** * Print spacing sizes custom properties. */ private function print_spacing_sizes_custom_properties() { $custom_properties = []; $spacing = wp_get_global_settings( [ self::KEY_SPACING ], self::KEY_THEME ); $spacing_sizes = $spacing[ self::KEY_SPACING_SIZES ] ?? []; $custom_spacing_size = $spacing[ self::KEY_CUSTOM_SPACING_SIZE ] ?? false; $spacing_scale = $spacing[ self::KEY_SPACING_SCALE ] ?? []; /** * By default check for `defaultSpacingSizes` boolean introduced in theme.json (v3) * and if it's false, then check for `steps` in `spacingScale` which is v2 default. * * @see . */ $is_wp_generating_spacing_sizes = $spacing[ self::KEY_DEFAULT_SPACING_SIZES ] ?? false; if ( array_key_exists( self::KEY_STEPS, $spacing_scale ) ) { $is_wp_generating_spacing_sizes = 0 !== $spacing_scale[ self::KEY_STEPS ]; } if ( ! $is_wp_generating_spacing_sizes && $custom_spacing_size ) { if ( isset( $spacing_sizes[ self::KEY_THEME ] ) ) { $custom_properties = array_merge( $custom_properties, $spacing_sizes[ self::KEY_THEME ] ); } } else { if ( isset( $spacing_sizes[ self::KEY_DEFAULT ] ) ) { $custom_properties = array_merge( $custom_properties, $spacing_sizes[ self::KEY_DEFAULT ] ); } } if ( empty( $custom_properties ) ) { return; } echo ''; } /** * Get relative luminance from color hex value. * * Copied from `\Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex()`. * * @see https://github.com/WordPress/wordpress-develop/blob/acbbbd18b32b5429264622141a6d058b64f3a5ad/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-custom-colors.php#L138-L156 * * @param string $hex Color hex value. * @return int Relative luminance value. */ public function get_relative_luminance_from_hex( $hex ) { // Remove the "#" symbol from the beginning of the color. $hex = ltrim( $hex, '#' ); // Make sure there are 6 digits for the below calculations. if ( 3 === strlen( $hex ) ) { $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2]; } // Get red, green, blue. $red = hexdec( substr( $hex, 0, 2 ) ); $green = hexdec( substr( $hex, 2, 2 ) ); $blue = hexdec( substr( $hex, 4, 2 ) ); // Calculate the luminance. $lum = ( 0.2126 * $red ) + ( 0.7152 * $green ) + ( 0.0722 * $blue ); return (int) round( $lum ); } } /** * Register the service with the system. * * @return void */ public function register() { add_filter( 'amp_options_updating', [ $this, 'filter_amp_options_updating' ] ); add_action( 'after_switch_theme', [ $this, 'handle_theme_update' ] ); add_action( self::ACTION_UPDATE_CACHED_PRIMARY_THEME_SUPPORT, [ $this, 'update_cached_theme_support' ] ); add_action( 'upgrader_process_complete', function ( $upgrader ) { if ( $upgrader instanceof Theme_Upgrader ) { $this->update_cached_theme_support(); } } ); add_action( 'amp_post_template_head', [ $this, 'print_theme_support_styles' ] ); add_action( 'wp_head', [ $this, 'print_theme_support_styles' ], 9 // Because wp_print_styles happens at priority 8, and we want the primary theme's colors to override any conflicting theme color assignments. ); } /** * Check whether all the required props are present for a given feature item. * * @param string $feature Feature name. * @param array $props Props to check. * * @return bool Whether all are present. */ public function has_required_feature_props( $feature, $props ) { if ( empty( $props ) || ! is_array( $props ) ) { return false; } foreach ( self::SUPPORTED_FEATURES[ $feature ] as $required_prop ) { if ( ! array_key_exists( $required_prop, $props ) ) { return false; } } return true; } /** * Filter the AMP options when they are updated to add the primary theme's features. * * @param array $options Options. * @return array Options. */ public function filter_amp_options_updating( $options ) { if ( $this->reader_theme_loader->is_enabled( $options ) ) { $options[ Option::PRIMARY_THEME_SUPPORT ] = $this->get_theme_support_features( true ); } else { $options[ Option::PRIMARY_THEME_SUPPORT ] = null; } return $options; } /** * Handle updating the cached primary_theme_support after updating/switching theme. * * In the case of switching the theme via WP-CLI, it could be that the next request is for an AMP page and * the `check_theme_switched()` function will run in the context of a Reader theme being loaded. In that case, * the added theme support won't be for the primary theme and we need to schedule an immediate event in WP-Cron to * try again in the context of a cron request in which a Reader theme will never be overriding the primary theme. */ public function handle_theme_update() { if ( $this->reader_theme_loader->is_theme_overridden() ) { wp_schedule_single_event( time(), self::ACTION_UPDATE_CACHED_PRIMARY_THEME_SUPPORT ); } else { $this->update_cached_theme_support(); } } /** * Update primary theme's cached theme support. */ public function update_cached_theme_support() { if ( $this->reader_theme_loader->is_enabled() ) { AMP_Options_Manager::update_option( Option::PRIMARY_THEME_SUPPORT, $this->get_theme_support_features( true ) ); } else { AMP_Options_Manager::update_option( Option::PRIMARY_THEME_SUPPORT, null ); } } /** * Get the theme support features. * * @param bool $reduced Whether to reduce the feature props down to just what is required. * @return array Theme support features. */ public function get_theme_support_features( $reduced = false ) { $features = []; foreach ( array_keys( self::SUPPORTED_FEATURES ) as $feature_key ) { if ( wp_theme_has_theme_json() ) { $feature_value = []; $global_settings = wp_get_global_settings( self::SUPPORTED_THEME_JSON_FEATURES[ $feature_key ], self::KEY_THEME ); if ( isset( $global_settings[ self::KEY_THEME ] ) ) { $feature_value = array_merge( $feature_value, $global_settings[ self::KEY_THEME ] ); } if ( isset( $global_settings[ self::KEY_DEFAULT ] ) ) { $feature_value = array_merge( $feature_value, $global_settings[ self::KEY_DEFAULT ] ); } } else { $feature_value = current( (array) get_theme_support( $feature_key ) ); } if ( ! is_array( $feature_value ) || empty( $feature_value ) ) { continue; } // Avoid reducing font sizes if theme.json is used for the sake of fluid typography. if ( wp_theme_has_theme_json() && self::FEATURE_EDITOR_FONT_SIZES === $feature_key ) { $reduced = false; } if ( $reduced ) { $features[ $feature_key ] = []; foreach ( $feature_value as $item ) { if ( $this->has_required_feature_props( $feature_key, $item ) ) { $features[ $feature_key ][] = wp_array_slice_assoc( $item, self::SUPPORTED_FEATURES[ $feature_key ] ); } } } else { $features[ $feature_key ] = $feature_value; } } return $features; } /** * Determines whether the request is for an AMP page in Reader mode. * * @return bool Whether AMP Reader request. */ public function is_reader_request() { return ( ( amp_is_legacy() || $this->reader_theme_loader->is_theme_overridden() ) && amp_is_request() ); } /** * Print theme support styles. */ public function print_theme_support_styles() { if ( ! $this->is_reader_request() ) { return; } $features = []; if ( $this->reader_theme_loader->is_enabled() ) { $features = AMP_Options_Manager::get_option( Option::PRIMARY_THEME_SUPPORT ); } elseif ( amp_is_legacy() ) { $features = $this->get_theme_support_features(); } if ( empty( $features ) ) { return; } foreach ( array_keys( self::SUPPORTED_FEATURES ) as $feature ) { if ( empty( $features[ $feature ] ) || ! is_array( $features[ $feature ] ) ) { continue; } $value = $features[ $feature ]; switch ( $feature ) { case self::FEATURE_EDITOR_COLOR_PALETTE: $this->print_editor_color_palette_styles( $value ); break; case self::FEATURE_EDITOR_FONT_SIZES: $this->print_editor_font_sizes_styles( $value ); break; case self::FEATURE_EDITOR_GRADIENT_PRESETS: $this->print_editor_gradient_presets_styles( $value ); break; } } // Print the custom properties for the spacing sizes. if ( wp_theme_has_theme_json() ) { $this->print_spacing_sizes_custom_properties(); } } /** * Print editor-color-palette styles. * * @param array $color_palette Color palette. */ private function print_editor_color_palette_styles( array $color_palette ) { echo ''; } /** * Print editor-font-sizes styles. * * @param array $font_sizes Font sizes. */ private function print_editor_font_sizes_styles( array $font_sizes ) { echo ''; } /** * Print editor-gradient-presets styles. * * @param array $gradient_presets Gradient presets. */ private function print_editor_gradient_presets_styles( array $gradient_presets ) { echo ''; } /** * Print spacing sizes custom properties. */ private function print_spacing_sizes_custom_properties() { $custom_properties = []; $spacing = wp_get_global_settings( [ self::KEY_SPACING ], self::KEY_THEME ); $spacing_sizes = $spacing[ self::KEY_SPACING_SIZES ] ?? []; $custom_spacing_size = $spacing[ self::KEY_CUSTOM_SPACING_SIZE ] ?? false; $spacing_scale = $spacing[ self::KEY_SPACING_SCALE ] ?? []; /** * By default check for `defaultSpacingSizes` boolean introduced in theme.json (v3) * and if it's false, then check for `steps` in `spacingScale` which is v2 default. * * @see . */ $is_wp_generating_spacing_sizes = $spacing[ self::KEY_DEFAULT_SPACING_SIZES ] ?? false; if ( array_key_exists( self::KEY_STEPS, $spacing_scale ) ) { $is_wp_generating_spacing_sizes = 0 !== $spacing_scale[ self::KEY_STEPS ]; } if ( ! $is_wp_generating_spacing_sizes && $custom_spacing_size ) { if ( isset( $spacing_sizes[ self::KEY_THEME ] ) ) { $custom_properties = array_merge( $custom_properties, $spacing_sizes[ self::KEY_THEME ] ); } } else { if ( isset( $spacing_sizes[ self::KEY_DEFAULT ] ) ) { $custom_properties = array_merge( $custom_properties, $spacing_sizes[ self::KEY_DEFAULT ] ); } } if ( empty( $custom_properties ) ) { return; } echo ''; } /** * Get relative luminance from color hex value. * * Copied from `\Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex()`. * * @see https://github.com/WordPress/wordpress-develop/blob/acbbbd18b32b5429264622141a6d058b64f3a5ad/src/wp-content/themes/twentytwentyone/classes/class-twenty-twenty-one-custom-colors.php#L138-L156 * * @param string $hex Color hex value. * @return int Relative luminance value. */ public function get_relative_luminance_from_hex( $hex ) { // Remove the "#" symbol from the beginning of the color. $hex = ltrim( $hex, '#' ); // Make sure there are 6 digits for the below calculations. if ( 3 === strlen( $hex ) ) { $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2]; } // Get red, green, blue. $red = hexdec( substr( $hex, 0, 2 ) ); $green = hexdec( substr( $hex, 2, 2 ) ); $blue = hexdec( substr( $hex, 4, 2 ) ); // Calculate the luminance. $lum = ( 0.2126 * $red ) + ( 0.7152 * $green ) + ( 0.0722 * $blue ); return (int) round( $lum ); } } {"id":18821,"count":1,"description":"","link":"https:\/\/www.infosculturedufaso.net\/tag\/chef-du-quartier-tiwega-de-kaya\/","name":"chef du quartier Tiwega de Kaya","slug":"chef-du-quartier-tiwega-de-kaya","taxonomy":"post_tag","meta":[],"_links":{"self":[{"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/tags\/18821","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/tags"}],"about":[{"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/taxonomies\/post_tag"}],"wp:post_type":[{"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/posts?tags=18821"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}