Current path: home/webdevt/www/wdp/wp-content/plugins/google-site-kit/includes/Core/Email_Reporting/
?? Go up: /home/webdevt/www/wdp/wp-content/plugins/google-site-kit/includes/Core
<?php
/**
* Class Google\Site_Kit\Core\Email_Reporting\Sections_Map
*
* @package Google\Site_Kit\Core\Email_Reporting
* @copyright 2025 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Core\Email_Reporting;
use Google\Site_Kit\Context;
use Google\Site_Kit\Core\Golinks\Golinks;
/**
* Class for mapping email report sections and their layout configuration.
*
* @since 1.168.0
*/
class Sections_Map {
/**
* Plugin context.
*
* @since 1.168.0
* @var Context
*/
protected $context;
/**
* Gets the mapping of section part keys to their display labels.
*
* @since 1.170.0
*
* @return array<string, string> Mapping of part keys to localized labels.
*/
public static function get_part_labels() {
return array(
'traffic_channels' => __( 'Traffic channels by visitor count', 'google-site-kit' ),
'top_ctr_keywords' => __( 'Keywords with highest CTR in Search', 'google-site-kit' ),
'popular_content' => __( 'Pages with the most pageviews', 'google-site-kit' ),
'top_pages_by_clicks' => __( 'Pages with the most clicks from Search', 'google-site-kit' ),
'top_authors' => __( 'Top authors by pageviews', 'google-site-kit' ),
'top_categories' => __( 'Top categories by pageviews', 'google-site-kit' ),
'keywords_ctr_increase' => __( 'Search keywords with the biggest increase in CTR', 'google-site-kit' ),
'pages_clicks_increase' => __( 'Pages with the biggest increase in Search clicks', 'google-site-kit' ),
);
}
/**
* Gets the label for a specific part key.
*
* @since 1.170.0
*
* @param string $part_key The part key to get the label for.
* @return string The localized label, or empty string if not found.
*/
public static function get_part_label( $part_key ) {
$labels = self::get_part_labels();
return $labels[ $part_key ] ?? '';
}
/**
* Payload data for populating section templates.
*
* @since 1.168.0
* @var array
*/
protected $payload;
/**
* Golinks instance.
*
* @since 1.174.0
* @var Golinks
*/
protected $golinks;
/**
* Constructor.
*
* @since 1.168.0
* @since 1.174.0 Added golinks dependency.
*
* @param Context $context Plugin context.
* @param array $payload The payload data to be used in sections.
* @param Golinks $golinks Golinks instance.
*/
public function __construct( Context $context, $payload, Golinks $golinks ) {
$this->context = $context;
$this->payload = $payload;
$this->golinks = $golinks;
}
/**
* Gets the dashboard golink URL.
*
* @since 1.174.0
*
* @return string Dashboard URL.
*/
protected function get_dashboard_url() {
return $this->golinks->get_url( 'dashboard' );
}
/**
* Gets all sections for the email report.
*
* Returns an array describing the layout sections, where each section contains:
* - title: The section heading
* - icon: Icon identifier for the section
* - section_parts: Array of template parts with their data
*
* @since 1.168.0
*
* @return array Array of sections with their configuration.
*/
public function get_sections() {
return array_merge(
$this->get_visitors_section(),
$this->get_traffic_sources_section(),
$this->get_attention_section(),
$this->get_growth_drivers_section()
);
}
/**
* Gets the visitors section.
*
* @since 1.168.0
*
* @return array Section configuration array.
*/
protected function get_visitors_section() {
$section_parts = array();
$section_parts['total_visitors'] = array(
'data' => $this->payload['total_visitors'] ?? array(),
);
$section_parts['new_visitors'] = array(
'data' => $this->payload['new_visitors'] ?? array(),
);
$section_parts['returning_visitors'] = array(
'data' => $this->payload['returning_visitors'] ?? array(),
);
// Insert custom audience parts (if available) immediately after returning_visitors.
if ( is_array( $this->payload ) ) {
foreach ( $this->payload as $key => $data ) {
if ( 0 !== strpos( $key, 'custom_audience_' ) ) {
continue;
}
$section_parts[ $key ] = array(
'data' => $data,
);
}
}
$section_parts['total_impressions'] = array(
'data' => $this->payload['total_impressions'] ?? array(),
);
$section_parts['total_clicks'] = array(
'data' => $this->payload['total_clicks'] ?? array(),
);
$section_parts = $this->filter_section_parts( $section_parts );
if ( empty( $section_parts ) ) {
return array();
}
return array(
'how_many_people_are_finding_and_visiting_my_site' => array(
'title' => esc_html__( 'How many people are finding and visiting my site?', 'google-site-kit' ),
'icon' => 'visitors',
'section_template' => 'section-metrics',
'dashboard_url' => $this->get_dashboard_url(),
'section_parts' => $section_parts,
),
);
}
/**
* Gets the traffic sources section.
*
* @since 1.168.0
*
* @return array Section configuration array.
*/
protected function get_traffic_sources_section() {
$section_parts = array(
'traffic_channels' => array(
'data' => $this->payload['traffic_channels'] ?? array(),
),
'top_ctr_keywords' => array(
'data' => $this->payload['top_ctr_keywords'] ?? array(),
),
);
$section_parts = $this->filter_section_parts( $section_parts );
if ( empty( $section_parts ) ) {
return array();
}
return array(
'how_are_people_finding_me' => array(
'title' => esc_html__( 'How are people finding me?', 'google-site-kit' ),
'icon' => 'search',
'section_template' => 'section-page-metrics',
'dashboard_url' => $this->get_dashboard_url(),
'section_parts' => $section_parts,
),
);
}
/**
* Gets the attention section.
*
* @since 1.168.0
*
* @return array Section configuration array.
*/
protected function get_attention_section() {
$section_parts = array(
'popular_content' => array(
'data' => $this->payload['popular_content'] ?? array(),
),
'top_pages_by_clicks' => array(
'data' => $this->payload['top_pages_by_clicks'] ?? array(),
),
'top_authors' => array(
'data' => $this->payload['top_authors'] ?? array(),
),
'top_categories' => array(
'data' => $this->payload['top_categories'] ?? array(),
),
);
$section_parts = $this->filter_section_parts( $section_parts );
if ( empty( $section_parts ) ) {
return array();
}
return array(
'whats_grabbing_their_attention' => array(
'title' => esc_html__( 'What’s grabbing their attention?', 'google-site-kit' ),
'icon' => 'views',
'section_template' => 'section-page-metrics',
'dashboard_url' => $this->get_dashboard_url(),
'section_parts' => $section_parts,
),
);
}
/**
* Gets the growth drivers section.
*
* @since 1.168.0
*
* @return array Section configuration array.
*/
protected function get_growth_drivers_section() {
$section_parts = array(
'keywords_ctr_increase' => array(
'data' => $this->payload['keywords_ctr_increase'] ?? array(),
),
'pages_clicks_increase' => array(
'data' => $this->payload['pages_clicks_increase'] ?? array(),
),
);
$section_parts = $this->filter_section_parts( $section_parts );
if ( empty( $section_parts ) ) {
return array();
}
return array(
'what_is_driving_growth_and_bringing_more_visitors' => array(
'title' => esc_html__( 'What is driving growth and bringing more visitors?', 'google-site-kit' ),
'icon' => 'growth',
'section_template' => 'section-page-metrics',
'dashboard_url' => $this->get_dashboard_url(),
'section_parts' => $section_parts,
),
);
}
/**
* Filters section parts to only include meaningful data.
*
* @since 1.171.0
*
* @param array $section_parts Section parts to filter.
* @return array Filtered section parts.
*/
protected function filter_section_parts( array $section_parts ) {
$filtered = array();
foreach ( $section_parts as $part_key => $part_config ) {
$data = $part_config['data'] ?? null;
if ( ! $this->has_data( $data ) ) {
continue;
}
$filtered[ $part_key ] = $part_config;
}
return $filtered;
}
/**
* Determines whether a section part has meaningful data.
*
* @since 1.171.0
*
* @param mixed $data Section part data.
* @return bool Whether the data contains values to render.
*/
protected function has_data( $data ) {
if ( empty( $data ) || ! is_array( $data ) ) {
return false;
}
if ( isset( $data['values'] ) && is_array( $data['values'] ) ) {
foreach ( $data['values'] as $value ) {
if ( $this->has_non_zero_value( $value ) ) {
return true;
}
}
}
if ( array_key_exists( 'value', $data ) ) {
return $this->has_non_zero_value( $data['value'] );
}
return false;
}
/**
* Determines whether a value represents non-zero, meaningful data.
*
* @since 1.171.0
*
* @param mixed $value Value to evaluate.
* @return bool Whether the value is non-zero or non-empty.
*/
protected function has_non_zero_value( $value ) {
if ( null === $value ) {
return false;
}
if ( is_bool( $value ) ) {
return $value;
}
if ( is_numeric( $value ) ) {
return 0.0 !== (float) $value;
}
if ( is_string( $value ) ) {
$trimmed = trim( $value );
if ( '' === $trimmed ) {
return false;
}
$normalized = str_replace( '%', '', $trimmed );
if ( is_numeric( $normalized ) ) {
return 0.0 !== (float) $normalized;
}
return true;
}
return ! empty( $value );
}
}