-
Notifications
You must be signed in to change notification settings - Fork 227
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
23 changed files
with
1,222 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
144 changes: 144 additions & 0 deletions
144
inc/Engine/Media/PreconnectExternalDomains/AJAX/Controller.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
namespace WP_Rocket\Engine\Media\PreconnectExternalDomains\AJAX; | ||
|
||
use WP_Rocket\Engine\Common\Context\ContextInterface; | ||
use WP_Rocket\Engine\Common\PerformanceHints\AJAX\AJAXControllerTrait; | ||
use WP_Rocket\Engine\Common\PerformanceHints\AJAX\ControllerInterface; | ||
use WP_Rocket\Engine\Media\PreconnectExternalDomains\Database\Queries\PreconnectExternalDomains as PreconnectQuery; | ||
|
||
class Controller implements ControllerInterface { | ||
use AJAXControllerTrait; | ||
|
||
/** | ||
* Preconnect external domain instance | ||
* | ||
* @var PreconnectQuery | ||
*/ | ||
private $query; | ||
|
||
/** | ||
* PreconnectExternalDomains Context. | ||
* | ||
* @var ContextInterface | ||
*/ | ||
protected $context; | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param PreconnectQuery $query Preconnect External Domains Query instance. | ||
* @param ContextInterface $context Context interface. | ||
*/ | ||
public function __construct( PreconnectQuery $query, ContextInterface $context ) { | ||
$this->query = $query; | ||
$this->context = $context; | ||
} | ||
|
||
/** | ||
* Add Preconnect external domains data to the database | ||
* | ||
* @return array | ||
*/ | ||
public function add_data(): array { | ||
check_ajax_referer( 'rocket_beacon', 'rocket_beacon_nonce' ); | ||
$payload = []; | ||
|
||
if ( ! $this->context->is_allowed() ) { | ||
$payload['preconnect_external_domains'] = 'not allowed'; | ||
|
||
return $payload; | ||
} | ||
|
||
$url = isset( $_POST['url'] ) ? untrailingslashit( esc_url_raw( wp_unslash( $_POST['url'] ) ) ) : ''; | ||
$is_mobile = isset( $_POST['is_mobile'] ) ? filter_var( wp_unslash( $_POST['is_mobile'] ), FILTER_VALIDATE_BOOLEAN ) : false; | ||
$results = isset( $_POST['results'] ) ? json_decode( wp_unslash( $_POST['results'] ) ) : (object) [ 'domains' => [] ]; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized | ||
$domains = $results->domains ?? []; | ||
|
||
$preconnect_domains = []; | ||
|
||
/** | ||
* Filters the maximum number of preconnect external domains being saved into the database. | ||
* | ||
* @param int $max_number Maximum number to allow. | ||
* @param string $url Current page url. | ||
* @param string[]|array $hashes Current list of preconnect external domains. | ||
*/ | ||
$max_preconnect_domains_number = wpm_apply_filters_typed( 'integer', 'rocket_preconnect_external_domains_number', 20, $url, $domains ); | ||
if ( 0 >= $max_preconnect_domains_number ) { | ||
$max_preconnect_domains_number = 1; | ||
} | ||
|
||
foreach ( (array) $domains as $index => $domain ) { | ||
$preconnect_domains[ $index ] = sanitize_url( wp_unslash( $domain ) ); | ||
--$max_preconnect_domains_number; | ||
} | ||
|
||
$row = $this->query->get_row( $url, $is_mobile ); | ||
if ( ! empty( $row ) ) { | ||
$payload['preconnect_external_domains'] = 'item already in the database'; | ||
|
||
return $payload; | ||
} | ||
|
||
$status = isset( $_POST['status'] ) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : ''; | ||
list( $status_code, $status_message ) = $this->get_status_code_message( $status ); | ||
|
||
$item = [ | ||
'url' => $url, | ||
'is_mobile' => $is_mobile, | ||
'status' => $status_code, | ||
'error_message' => $status_message, | ||
'domains' => wp_json_encode( $preconnect_domains ), | ||
'created_at' => current_time( 'mysql', true ), | ||
'last_accessed' => current_time( 'mysql', true ), | ||
]; | ||
|
||
$result = $this->query->add_item( $item ); | ||
|
||
if ( ! $result ) { | ||
$payload['preconnect_external_domains'] = 'error when adding the entry to the database'; | ||
|
||
return $payload; | ||
} | ||
|
||
$payload['preconnect_external_domains'] = $item; | ||
|
||
return $payload; | ||
} | ||
|
||
/** | ||
* Checks if there is existing data for the current URL and device type from the beacon script. | ||
* | ||
* This method is called via AJAX. It checks if there is existing preconnect domains data for the current URL and device type. | ||
* If the data exists, it returns a JSON success response with true. If the data does not exist, it returns a JSON success response with false. | ||
* If the context is not allowed, it returns a JSON error response with false. | ||
* | ||
* @return array | ||
*/ | ||
public function check_data(): array { | ||
$payload = [ | ||
'preconnect_external_domains' => false, | ||
]; | ||
|
||
check_ajax_referer( 'rocket_beacon', 'rocket_beacon_nonce' ); | ||
|
||
if ( ! $this->context->is_allowed() ) { | ||
$payload['preconnect_external_domains'] = true; | ||
|
||
return $payload; | ||
} | ||
|
||
$is_mobile = isset( $_POST['is_mobile'] ) ? filter_var( wp_unslash( $_POST['is_mobile'] ), FILTER_VALIDATE_BOOLEAN ) : false; | ||
$url = isset( $_POST['url'] ) ? untrailingslashit( esc_url_raw( wp_unslash( $_POST['url'] ) ) ) : ''; | ||
|
||
$row = $this->query->get_row( $url, $is_mobile ); | ||
|
||
if ( ! empty( $row ) ) { | ||
$payload['preconnect_external_domains'] = true; | ||
} | ||
|
||
return $payload; | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
inc/Engine/Media/PreconnectExternalDomains/Context/Context.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
namespace WP_Rocket\Engine\Media\PreconnectExternalDomains\Context; | ||
|
||
use WP_Rocket\Admin\Options_Data; | ||
use WP_Rocket\Engine\Common\Context\ContextInterface; | ||
|
||
class Context implements ContextInterface { | ||
|
||
/** | ||
* Options instance | ||
* | ||
* @var Options_Data | ||
*/ | ||
private $options; | ||
|
||
|
||
/** | ||
* Constructor | ||
* | ||
* @param Options_Data $options Options instance. | ||
*/ | ||
public function __construct( Options_Data $options ) { | ||
$this->options = $options; | ||
} | ||
|
||
/** | ||
* Determine if the action is allowed. | ||
* | ||
* @param array $data Data to pass to the context. | ||
* @return bool | ||
*/ | ||
public function is_allowed( array $data = [] ): bool { | ||
if ( $this->options->get( 'wp_rocket_no_licence', 0 ) ) { | ||
return false; | ||
} | ||
|
||
/** | ||
* Filters to manage above the fold optimization | ||
* | ||
* @param bool $allow True to allow, false otherwise. | ||
*/ | ||
return wpm_apply_filters_typed( 'boolean', 'rocket_preconnect_external_domains_optimization', true ); | ||
} | ||
} |
92 changes: 92 additions & 0 deletions
92
inc/Engine/Media/PreconnectExternalDomains/Database/Queries/PreconnectExternalDomains.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
namespace WP_Rocket\Engine\Media\PreconnectExternalDomains\Database\Queries; | ||
|
||
use WP_Rocket\Engine\Common\PerformanceHints\Database\Queries\AbstractQueries; | ||
use WP_Rocket\Engine\Common\PerformanceHints\Database\Queries\QueriesInterface; | ||
use WP_Rocket\Engine\Media\PreconnectExternalDomains\Database\Schema\PreconnectExternalDomains as PreconnectExternalDomainsSchema; | ||
use WP_Rocket\Engine\Media\PreconnectExternalDomains\Database\Row\PreconnectExternalDomains as PreconnectExternalDomainsRow; | ||
|
||
class PreconnectExternalDomains extends AbstractQueries implements QueriesInterface { | ||
|
||
/** | ||
* Name of the database table to query. | ||
* | ||
* @var string | ||
*/ | ||
protected $table_name = 'wpr_preconnect_external_domains'; | ||
|
||
/** | ||
* String used to alias the database table in MySQL statement. | ||
* | ||
* Keep this short, but descriptive. I.E. "tr" for term relationships. | ||
* | ||
* This is used to avoid collisions with JOINs. | ||
* | ||
* @var string | ||
*/ | ||
protected $table_alias = 'wpr_pre'; | ||
|
||
/** | ||
* Name of class used to setup the database schema. | ||
* | ||
* @var string | ||
*/ | ||
protected $table_schema = PreconnectExternalDomainsSchema::class; | ||
|
||
/** Item ******************************************************************/ | ||
|
||
/** | ||
* Name for a single item. | ||
* | ||
* Use underscores between words. I.E. "term_relationship" | ||
* | ||
* This is used to automatically generate action hooks. | ||
* | ||
* @var string | ||
*/ | ||
protected $item_name = 'preconnect_external_domains'; | ||
|
||
/** | ||
* Plural version for a group of items. | ||
* | ||
* Use underscores between words. I.E. "term_relationships" | ||
* | ||
* This is used to automatically generate action hooks. | ||
* | ||
* @var string | ||
*/ | ||
protected $item_name_plural = 'preconnect_external_domains'; | ||
|
||
/** | ||
* Name of class used to turn IDs into first-class objects. | ||
* | ||
* This is used when looping through return values to guarantee their shape. | ||
* | ||
* @var mixed | ||
*/ | ||
protected $item_shape = PreconnectExternalDomainsRow::class; | ||
|
||
/** | ||
* Delete all rows which were not accessed in the last month. | ||
* | ||
* @return bool|int | ||
*/ | ||
public function delete_old_rows() { | ||
// Get the database interface. | ||
$db = $this->get_db(); | ||
|
||
// Early bailout if no database interface is available. | ||
if ( ! $db ) { | ||
return false; | ||
} | ||
|
||
$delete_interval = $this->cleanup_interval; | ||
|
||
$prefixed_table_name = $db->prefix . $this->table_name; | ||
$query = "DELETE FROM `$prefixed_table_name` WHERE status = 'failed' OR `last_accessed` <= date_sub(now(), interval $delete_interval month)"; | ||
|
||
return $db->query( $query ); | ||
} | ||
} |
Oops, something went wrong.