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":221782,"date":"2019-05-31T09:33:39","date_gmt":"2019-05-31T09:33:39","guid":{"rendered":"https:\/\/infosculturedufaso.net\/?p=221782"},"modified":"2019-05-31T09:43:42","modified_gmt":"2019-05-31T09:43:42","slug":"concert-le-groupe-afrikanda-sera-en-concert-live-le-8-juin-2019","status":"publish","type":"post","link":"https:\/\/www.infosculturedufaso.net\/concert-le-groupe-afrikanda-sera-en-concert-live-le-8-juin-2019\/","title":{"rendered":"CONCERT : le Groupe AFRIKAN’DA sera en concert live le 8 juin 2019."},"content":{"rendered":"

Apr\u00e8s une tourn\u00e9e mondiale qui les aura vu parcourir l’Europe \u00e0 travers les festivals, anim\u00e9 des s\u00e9ances de formation et des panels sur le slam, le groupe Afrikan’da est revenu en Afrique pour \u00e9crire leur nom en lettre d’or au FISH de Bamako du cot\u00e9 du Mali.<\/strong><\/p>\n

\"\"<\/p>\n

Selon Soldat de Jah, \u00ab il \u00e9tait grand tant de revenir au Pays des Hommes Int\u00e8gres \u00bb leur Faso natal.
\nSelon leur dire, \u00ab le concert 100% live du 8 Juin 2019 est pour nous un moyen de dire merci \u00e0 nos fans et vivre des moments de pur bonheur en leur compagnie car depuis 2012, ann\u00e9e de cr\u00e9ation du groupe, ils nous ont toujours soutenu et ne nous ont jamais quitter des yeux o\u00f9 que nous soyons.<\/p>\n

\"\"La preuve d\u00e8s que la date du concert a \u00e9t\u00e9 publi\u00e9e les \u00e9chos qui nous parviennent sont tr\u00e8s positifs alors nous allons r\u00e9p\u00e9ter comme des \u00ab\u00a0malades\u00a0\u00bb pour leur offrir un spectacle de r\u00eave le 8 Juin \u00bb.
\nAu vu de l’engouement autour de ce concert il faut pas \u00eatre \u00e9tonn\u00e9 de voir le Centre Culturel les Bambous refuser du monde le Samedi 8 Juin 2019 car l’histoire d’amour entre le publique bobolais et le Groupe AFRIKAN’DA est comme ils le disent \u00ab\u00a0c’est \u00e0 la vie \u00e0 l’amour\u00a0\u00bb.<\/p>\n

\"\"C’est ainsi que AFRIKAN’DA promet de bosser \u00e0 plus de 100% pour \u00eatre parfait le jour j.
\nC’est dans une ambiance bon enfant que nous nous sommes donn\u00e9 rendez vous tr\u00e8s bient\u00f4t pour voir l’\u00e9tat d’avancement des pr\u00e9paratifs.<\/p>\n

 <\/p>\n

Abdoul Isma\u00ebl Rasack TRAOR\u00c9<\/p>\n","protected":false},"excerpt":{"rendered":"

Apr\u00e8s une tourn\u00e9e mondiale qui les aura vu parcourir l’Europe \u00e0 travers les festivals, anim\u00e9 des s\u00e9ances de formation et des panels sur le slam, le groupe Afrikan’da est revenu en Afrique pour \u00e9crire leur nom en lettre d’or au FISH de Bamako du cot\u00e9 du Mali. Selon Soldat de Jah, \u00ab il \u00e9tait grand […]<\/p>\n","protected":false},"author":2,"featured_media":221784,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[60,13,10],"tags":[1500,172,1475],"class_list":{"0":"post-221782","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-entretiens","8":"category-musique","9":"category-musique-moderne","10":"tag-afrikanda","11":"tag-bobo-dioulasso","12":"tag-centre-culturel-les-bambous"},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/posts\/221782","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/comments?post=221782"}],"version-history":[{"count":3,"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/posts\/221782\/revisions"}],"predecessor-version":[{"id":221790,"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/posts\/221782\/revisions\/221790"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/media\/221784"}],"wp:attachment":[{"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/media?parent=221782"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/categories?post=221782"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.infosculturedufaso.net\/wp-json\/wp\/v2\/tags?post=221782"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}