Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions includes/Core/Email_Reporting/Email_Reporting.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
namespace Google\Site_Kit\Core\Email_Reporting;

use Google\Site_Kit\Context;
use Google\Site_Kit\Core\Email\Email;
use Google\Site_Kit\Core\Authentication\Authentication;
use Google\Site_Kit\Core\Email\Email;
use Google\Site_Kit\Core\Email_Reporting\Eligible_Subscribers_Query;
use Google\Site_Kit\Core\Modules\Modules;
use Google\Site_Kit\Core\Storage\Options;
use Google\Site_Kit\Core\Storage\User_Options;
Expand Down Expand Up @@ -195,18 +196,19 @@ public function __construct(
$this->user_settings = new User_Email_Reporting_Settings( $this->user_options );
$this->was_analytics_4_connected = new Was_Analytics_4_Connected( $this->options );

$frequency_planner = new Frequency_Planner();
$subscribed_users_query = new Subscribed_Users_Query( $this->user_settings, $this->modules );
$max_execution_limiter = new Max_Execution_Limiter( (int) ini_get( 'max_execution_time' ) );
$batch_query = new Email_Log_Batch_Query();
$email_sender = new Email();
$section_builder = new Email_Report_Section_Builder( $this->context );
$template_formatter = new Email_Template_Formatter( $this->context, $section_builder );
$template_renderer_factory = new Email_Template_Renderer_Factory( $this->context );
$report_sender = new Email_Report_Sender( $template_renderer_factory, $email_sender );
$log_processor = new Email_Log_Processor( $batch_query, $this->data_requests, $template_formatter, $report_sender );

$this->rest_controller = new REST_Email_Reporting_Controller( $this->settings, $this->was_analytics_4_connected, $this->modules, $this->user_options, $this->user_settings );
$frequency_planner = new Frequency_Planner();
$subscribed_users_query = new Subscribed_Users_Query( $this->user_settings, $this->modules );
$eligible_subscribers_query = new Eligible_Subscribers_Query( $this->modules, $this->user_options );
$max_execution_limiter = new Max_Execution_Limiter( (int) ini_get( 'max_execution_time' ) );
$batch_query = new Email_Log_Batch_Query();
$email_sender = new Email();
$section_builder = new Email_Report_Section_Builder( $this->context );
$template_formatter = new Email_Template_Formatter( $this->context, $section_builder );
$template_renderer_factory = new Email_Template_Renderer_Factory( $this->context );
$report_sender = new Email_Report_Sender( $template_renderer_factory, $email_sender );
$log_processor = new Email_Log_Processor( $batch_query, $this->data_requests, $template_formatter, $report_sender );

$this->rest_controller = new REST_Email_Reporting_Controller( $this->settings, $this->was_analytics_4_connected, $this->modules, $this->user_settings, $eligible_subscribers_query, $email_sender );
$this->email_log = new Email_Log( $this->context );
$this->scheduler = new Email_Reporting_Scheduler( $frequency_planner );
$this->initiator_task = new Initiator_Task( $this->scheduler, $subscribed_users_query );
Expand Down
112 changes: 107 additions & 5 deletions includes/Core/Email_Reporting/REST_Email_Reporting_Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@

namespace Google\Site_Kit\Core\Email_Reporting;

use Google\Site_Kit\Core\Email\Email;
use Google\Site_Kit\Core\Email_Reporting\Eligible_Subscribers_Query;
use Google\Site_Kit\Core\Modules\Modules;
use Google\Site_Kit\Core\Permissions\Permissions;
use Google\Site_Kit\Core\REST_API\REST_Route;
use Google\Site_Kit\Core\REST_API\REST_Routes;
use Google\Site_Kit\Core\Storage\User_Options;
use Google\Site_Kit\Core\User\Email_Reporting_Settings as User_Email_Reporting_Settings;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;
use WP_User;
use WP_Error;

/**
* Class for handling Email Reporting site settings via REST API.
Expand Down Expand Up @@ -70,6 +72,14 @@ class REST_Email_Reporting_Controller {
*/
private $eligible_subscribers_query;

/**
* Email instance.
*
* @since n.e.x.t
* @var Email
*/
private $email;

/**
* Constructor.
*
Expand All @@ -79,21 +89,24 @@ class REST_Email_Reporting_Controller {
* @param Email_Reporting_Settings $settings Email_Reporting_Settings instance.
* @param Was_Analytics_4_Connected $was_analytics_4_connected Was_Analytics_4_Connected instance.
* @param Modules $modules Modules instance.
* @param User_Options $user_options User options instance.
* @param User_Email_Reporting_Settings $user_email_reporting_settings User email reporting settings instance.
* @param Eligible_Subscribers_Query $eligible_subscribers_query Eligible subscribers query.
* @param Email $email Email sender instance.
*/
public function __construct(
Email_Reporting_Settings $settings,
Was_Analytics_4_Connected $was_analytics_4_connected,
Modules $modules,
User_Options $user_options,
User_Email_Reporting_Settings $user_email_reporting_settings
User_Email_Reporting_Settings $user_email_reporting_settings,
Eligible_Subscribers_Query $eligible_subscribers_query,
Email $email
) {
$this->settings = $settings;
$this->modules = $modules;
$this->was_analytics_4_connected = $was_analytics_4_connected;
$this->user_email_reporting_settings = $user_email_reporting_settings;
$this->eligible_subscribers_query = new Eligible_Subscribers_Query( $this->modules, $user_options );
$this->eligible_subscribers_query = $eligible_subscribers_query;
$this->email = $email;
}

/**
Expand Down Expand Up @@ -203,6 +216,69 @@ function ( WP_User $user ) use ( $meta_key ) {
),
)
),
new REST_Route(
'core/site/data/email-reporting-invite-user',
array(
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => function ( WP_REST_Request $request ) {
$user_id = (int) $request->get_param( 'userId' );

if ( $user_id <= 0 ) {
return new WP_Error( 'invalid_user', __( 'Invalid user ID.', 'google-site-kit' ), array( 'status' => 400 ) );
}

$target_user = get_user_by( 'id', $user_id );

if ( ! $target_user instanceof WP_User ) {
return new WP_Error( 'invalid_user', __( 'User not found.', 'google-site-kit' ), array( 'status' => 400 ) );
}

$eligible_users = $this->eligible_subscribers_query->get_eligible_users( get_current_user_id() );
$eligible_ids = wp_list_pluck( $eligible_users, 'ID' );

if ( ! in_array( $user_id, $eligible_ids, true ) ) {
return new WP_Error( 'ineligible_user', __( 'User is not eligible for email reports.', 'google-site-kit' ), array( 'status' => 400 ) );
}

if ( $this->is_user_subscribed( $user_id ) ) {
return new WP_Error( 'already_subscribed', __( 'User is already subscribed to email reports.', 'google-site-kit' ), array( 'status' => 400 ) );
}

$rate_limit_key = $this->get_invite_rate_limit_key( $user_id );

if ( get_transient( $rate_limit_key ) ) {
return new WP_Error( 'rate_limited', __( 'An invitation was recently sent to this user.', 'google-site-kit' ), array( 'status' => 429 ) );
}

// @TODO - Implement proper email template when available (invoke method from renderer etc).
$invite = '';

if ( empty( $invite['subject'] ) || empty( $invite['content'] ) ) {
return new WP_Error( 'invite_render_failed', __( 'Failed to build invitation email.', 'google-site-kit' ), array( 'status' => 500 ) );
}

$headers = $this->email->build_headers( array( 'Content-Type: text/html; charset=UTF-8' ) );
$result = $this->email->send( $target_user->user_email, $invite['subject'], $invite['content'], $headers );

if ( is_wp_error( $result ) ) {
return new WP_Error( 'invite_send_failed', $result->get_error_message(), array( 'status' => 500 ) );
}

set_transient( $rate_limit_key, 1, DAY_IN_SECONDS );

return new WP_REST_Response( array( 'success' => true ) );
},
'permission_callback' => $can_manage,
'args' => array(
'userId' => array(
'type' => 'integer',
'required' => true,
),
),
),
)
),
new REST_Route(
'core/site/data/was-analytics-4-connected',
array(
Expand All @@ -218,6 +294,32 @@ function ( WP_User $user ) use ( $meta_key ) {
);
}

/**
* Determines if a user is already subscribed.
*
* @since n.e.x.t
*
* @param int $user_id User ID.
* @return bool
*/
private function is_user_subscribed( $user_id ) {
$settings = get_user_meta( $user_id, $this->user_email_reporting_settings->get_meta_key(), true );

return is_array( $settings ) && ! empty( $settings['subscribed'] );
}

/**
* Gets the rate limit transient key for user invites.
*
* @since n.e.x.t
*
* @param int $user_id User ID.
* @return string
*/
private function get_invite_rate_limit_key( $user_id ) {
return 'googlesitekit_email_reporting_invite_' . (int) $user_id;
}

/**
* Maps a user to the REST response shape.
*
Expand Down