Skip to content

Commit 6534794

Browse files
committed
Merge remote-tracking branch 'origin/develop' into enhancement/11547-worker-task.
2 parents ee3195b + 12d8036 commit 6534794

File tree

10 files changed

+1609
-0
lines changed

10 files changed

+1609
-0
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
<?php
2+
/**
3+
* Class Google\Site_Kit\Core\Email_Reporting\Report_Options\Report_Options
4+
*
5+
* @package Google\Site_Kit\Core\Email_Reporting\Report_Options
6+
* @copyright 2025 Google LLC
7+
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
8+
* @link https://sitekit.withgoogle.com
9+
*/
10+
11+
namespace Google\Site_Kit\Core\Email_Reporting\Report_Options;
12+
13+
/**
14+
* Base helper for building email reporting report options.
15+
*
16+
* @since n.e.x.t
17+
* @access private
18+
* @ignore
19+
*/
20+
abstract class Report_Options {
21+
22+
/**
23+
* Current period date range.
24+
*
25+
* @since n.e.x.t
26+
*
27+
* @var array
28+
*/
29+
private $current_range;
30+
31+
/**
32+
* Compare period date range.
33+
*
34+
* @since n.e.x.t
35+
*
36+
* @var array
37+
*/
38+
private $compare_range;
39+
40+
/**
41+
* Constructor.
42+
*
43+
* @since n.e.x.t
44+
*
45+
* @param array $date_range Current period range array containing `startDate` and `endDate`.
46+
* @param array $compare_range Optional. Compare period range array containing `startDate` and `endDate`.
47+
* @throws \InvalidArgumentException When the required date range payload is missing.
48+
*/
49+
public function __construct( $date_range, $compare_range = array() ) {
50+
if ( empty( $date_range ) ) {
51+
throw new \InvalidArgumentException( 'Email reporting date range is required.' );
52+
}
53+
54+
$this->current_range = $this->normalize_range( $date_range, 'date range' );
55+
$this->compare_range = $this->normalize_range(
56+
$this->extract_compare_range( $date_range, $compare_range ),
57+
'compare date range'
58+
);
59+
}
60+
61+
/**
62+
* Applies the current (and optional compare) date range to the report options.
63+
*
64+
* @since n.e.x.t
65+
*
66+
* @param array $options Base report options.
67+
* @param bool $include_compare Optional. Whether to include compare dates. Default false.
68+
* @return array Report request options array with applied date ranges.
69+
*/
70+
protected function with_current_range( $options, $include_compare = false ) {
71+
$options['startDate'] = $this->current_range['startDate'];
72+
$options['endDate'] = $this->current_range['endDate'];
73+
74+
if ( $include_compare ) {
75+
$options['compareStartDate'] = $this->compare_range['startDate'];
76+
$options['compareEndDate'] = $this->compare_range['endDate'];
77+
}
78+
79+
return $options;
80+
}
81+
82+
/**
83+
* Gets a combined range spanning compare start to current end.
84+
*
85+
* @since n.e.x.t
86+
*
87+
* @return array Combined date range spanning compare start to current end.
88+
*/
89+
protected function get_combined_range() {
90+
return array(
91+
'startDate' => $this->compare_range['startDate'],
92+
'endDate' => $this->current_range['endDate'],
93+
);
94+
}
95+
96+
/**
97+
* Gets the current period range values.
98+
*
99+
* @since n.e.x.t
100+
*
101+
* @return array Current period range array.
102+
*/
103+
protected function get_current_range_values() {
104+
return $this->current_range;
105+
}
106+
107+
/**
108+
* Gets the compare period range values.
109+
*
110+
* @since n.e.x.t
111+
*
112+
* @return array Compare period range array.
113+
*/
114+
protected function get_compare_range_values() {
115+
return $this->compare_range;
116+
}
117+
118+
/**
119+
* Normalizes and validates the provided range.
120+
*
121+
* @since n.e.x.t
122+
*
123+
* @param array $range Potential date range.
124+
* @param string $label Human friendly label used in exceptions.
125+
* @throws \InvalidArgumentException When required start or end dates are absent.
126+
* @return array Normalized date range array.
127+
*/
128+
private function normalize_range( $range, $label ) {
129+
if ( empty( $range['startDate'] ) || empty( $range['endDate'] ) ) {
130+
throw new \InvalidArgumentException(
131+
sprintf( 'Email reporting %s must include startDate and endDate.', $label )
132+
);
133+
}
134+
135+
return array(
136+
'startDate' => $range['startDate'],
137+
'endDate' => $range['endDate'],
138+
);
139+
}
140+
141+
/**
142+
* Extracts the compare range array.
143+
*
144+
* @since n.e.x.t
145+
*
146+
* @param array $date_range Current period range (possibly containing compare keys).
147+
* @param array $compare_range Explicit compare range override.
148+
* @return array Compare range payload.
149+
*/
150+
private function extract_compare_range( $date_range, $compare_range ) {
151+
if ( ! empty( $compare_range ) ) {
152+
return $compare_range;
153+
}
154+
155+
$keys = array(
156+
'startDate' => $date_range['compareStartDate'] ?? null,
157+
'endDate' => $date_range['compareEndDate'] ?? null,
158+
);
159+
160+
return $keys;
161+
}
162+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
/**
3+
* Class Google\Site_Kit\Modules\AdSense\Email_Reporting\Report_Options
4+
*
5+
* @package Google\Site_Kit\Modules\AdSense\Email_Reporting
6+
* @copyright 2025 Google LLC
7+
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
8+
* @link https://sitekit.withgoogle.com
9+
*/
10+
11+
namespace Google\Site_Kit\Modules\AdSense\Email_Reporting;
12+
13+
use Google\Site_Kit\Core\Email_Reporting\Report_Options\Report_Options as Base_Report_Options;
14+
15+
/**
16+
* Builds AdSense-focused report option payloads for email reporting.
17+
*
18+
* This leverages Analytics 4 linked AdSense data (totalAdRevenue/adSourceName).
19+
*
20+
* @since n.e.x.t
21+
* @access private
22+
* @ignore
23+
*/
24+
class Report_Options extends Base_Report_Options {
25+
26+
/**
27+
* Linked AdSense account ID.
28+
*
29+
* @since n.e.x.t
30+
*
31+
* @var string
32+
*/
33+
private $account_id;
34+
35+
/**
36+
* Constructor.
37+
*
38+
* @since n.e.x.t
39+
*
40+
* @param array|null $date_range Current period range array.
41+
* @param array $compare_range Optional. Compare period range array.
42+
* @param string $account_id Optional. Connected AdSense account ID. Default empty.
43+
*/
44+
public function __construct( $date_range, $compare_range = array(), $account_id = '' ) {
45+
parent::__construct( $date_range, $compare_range );
46+
$this->account_id = $account_id;
47+
}
48+
49+
/**
50+
* Gets report options for total AdSense earnings.
51+
*
52+
* @since n.e.x.t
53+
*
54+
* @return array Report request options array.
55+
*/
56+
public function get_total_earnings_options() {
57+
$options = array(
58+
'metrics' => array(
59+
array( 'name' => 'totalAdRevenue' ),
60+
),
61+
);
62+
63+
$ad_source_filter = $this->get_ad_source_filter();
64+
if ( $ad_source_filter ) {
65+
$options['dimensionFilters'] = array(
66+
'adSourceName' => $ad_source_filter,
67+
);
68+
}
69+
70+
return $this->with_current_range( $options, true );
71+
}
72+
73+
/**
74+
* Builds the AdSense ad source filter value.
75+
*
76+
* @since n.e.x.t
77+
*
78+
* @return string Human-readable filter label referencing the linked AdSense account.
79+
*/
80+
private function get_ad_source_filter() {
81+
if ( empty( $this->account_id ) ) {
82+
return '';
83+
}
84+
85+
return sprintf( 'Google AdSense account (%s)', $this->account_id );
86+
}
87+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<?php
2+
/**
3+
* Class Google\Site_Kit\Modules\Analytics_4\Email_Reporting\Audience_Config
4+
*
5+
* @package Google\Site_Kit\Modules\Analytics_4\Email_Reporting
6+
* @copyright 2025 Google LLC
7+
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
8+
* @link https://sitekit.withgoogle.com
9+
*/
10+
11+
namespace Google\Site_Kit\Modules\Analytics_4\Email_Reporting;
12+
13+
use Google\Site_Kit\Core\User\Audience_Settings as User_Audience_Settings;
14+
use Google\Site_Kit\Modules\Analytics_4\Audience_Settings as Module_Audience_Settings;
15+
16+
/**
17+
* Helper that provides configured audience metadata/maps.
18+
*
19+
* @since n.e.x.t
20+
*/
21+
final class Audience_Config {
22+
23+
/**
24+
* User audience settings.
25+
*
26+
* @since n.e.x.t
27+
*
28+
* @var User_Audience_Settings
29+
*/
30+
private $user_settings;
31+
32+
/**
33+
* Module audience settings.
34+
*
35+
* @since n.e.x.t
36+
*
37+
* @var Module_Audience_Settings
38+
*/
39+
private $module_settings;
40+
41+
/**
42+
* Constructor.
43+
*
44+
* @since n.e.x.t
45+
*
46+
* @param User_Audience_Settings $user_settings User audience settings instance.
47+
* @param Module_Audience_Settings $module_settings Module audience settings instance.
48+
*/
49+
public function __construct( User_Audience_Settings $user_settings, Module_Audience_Settings $module_settings ) {
50+
$this->user_settings = $user_settings;
51+
$this->module_settings = $module_settings;
52+
}
53+
54+
/**
55+
* Gets configured custom audiences and metadata.
56+
*
57+
* @since n.e.x.t
58+
*
59+
* @return array Configured audience payload with sanitized resource names and audience metadata list.
60+
*/
61+
public function get_configured_audiences() {
62+
$user_settings = $this->user_settings->get();
63+
$configured = $this->sanitize_resource_names(
64+
$user_settings['configuredAudiences'] ?? array()
65+
);
66+
67+
if ( empty( $configured ) ) {
68+
return array(
69+
'resource_names' => array(),
70+
'audiences' => array(),
71+
);
72+
}
73+
74+
$available = $this->module_settings->get();
75+
$available = is_array( $available ) ? $available : array();
76+
$available_map = array();
77+
78+
foreach ( $available['availableAudiences'] ?? array() as $audience ) {
79+
if ( isset( $audience['name'] ) ) {
80+
$available_map[ $audience['name'] ] = $audience;
81+
}
82+
}
83+
84+
$audience_metadata = array_map(
85+
function ( $resource_name ) use ( $available_map ) {
86+
$display_name = $available_map[ $resource_name ]['displayName'] ?? $resource_name;
87+
88+
return array(
89+
'resourceName' => $resource_name,
90+
'displayName' => $display_name,
91+
);
92+
},
93+
$configured
94+
);
95+
96+
return array(
97+
'resource_names' => $configured,
98+
'audiences' => $audience_metadata,
99+
);
100+
}
101+
102+
/**
103+
* Builds a map of Site Kit audience slugs to resource names.
104+
*
105+
* @since n.e.x.t
106+
*
107+
* @return array Associative map of Site Kit audience slugs to resource names.
108+
*/
109+
public function get_site_kit_audience_map() {
110+
$available = $this->module_settings->get();
111+
$available = is_array( $available ) ? $available : array();
112+
113+
$map = array();
114+
115+
foreach ( $available['availableAudiences'] ?? array() as $audience ) {
116+
if ( empty( $audience['audienceSlug'] ) || empty( $audience['name'] ) ) {
117+
continue;
118+
}
119+
$map[ $audience['audienceSlug'] ] = $audience['name'];
120+
}
121+
122+
return $map;
123+
}
124+
125+
/**
126+
* Sanitizes a list of audience resource names.
127+
*
128+
* @since n.e.x.t
129+
*
130+
* @param array $audience_resource_names Audience resource names.
131+
* @return array Sanitized list.
132+
*/
133+
public function sanitize_resource_names( array $audience_resource_names ) {
134+
$audience_resource_names = array_filter(
135+
array_map(
136+
function ( $resource_name ) {
137+
$resource_name = is_string( $resource_name ) ? trim( $resource_name ) : '';
138+
return '' !== $resource_name ? $resource_name : null;
139+
},
140+
$audience_resource_names
141+
)
142+
);
143+
144+
return array_values( array_unique( $audience_resource_names ) );
145+
}
146+
}

0 commit comments

Comments
 (0)