initial
This commit is contained in:
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\Jetpack_Boost\Lib\Critical_CSS;
|
||||
|
||||
use WP_Error;
|
||||
|
||||
class Critical_CSS_State {
|
||||
|
||||
const GENERATION_STATES = array(
|
||||
'not_generated' => 'not_generated',
|
||||
'pending' => 'pending',
|
||||
'generated' => 'generated',
|
||||
'error' => 'error',
|
||||
);
|
||||
|
||||
const PROVIDER_STATES = array(
|
||||
'pending' => 'pending',
|
||||
'success' => 'success',
|
||||
'error' => 'error',
|
||||
);
|
||||
public $state;
|
||||
|
||||
public function __construct() {
|
||||
$this->state = jetpack_boost_ds_get( 'critical_css_state' );
|
||||
}
|
||||
|
||||
public function clear() {
|
||||
jetpack_boost_ds_delete( 'critical_css_state' );
|
||||
}
|
||||
|
||||
public function save() {
|
||||
$this->state['updated'] = microtime( true );
|
||||
jetpack_boost_ds_set( 'critical_css_state', $this->state );
|
||||
|
||||
if ( $this->is_generated() ) {
|
||||
/**
|
||||
* Fires when critical CSS has successfully been generated.
|
||||
*/
|
||||
do_action( 'jetpack_boost_critical_css_generated' );
|
||||
}
|
||||
}
|
||||
|
||||
public function set_error( $message ) {
|
||||
if ( empty( $message ) ) {
|
||||
error_log( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
|
||||
'Critical CSS: set_error() called with empty message'
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->state['status_error'] = $message;
|
||||
$this->state['status'] = self::GENERATION_STATES['error'];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function set_provider_error_dismissed( $provider_key, $error_type, $dismissed ) {
|
||||
if ( empty( $this->state['providers'] ) ) {
|
||||
return new WP_Error( 'invalid_provider_key', 'No providers exist' );
|
||||
}
|
||||
|
||||
$provider_index = array_search( $provider_key, array_column( $this->state['providers'], 'key' ), true );
|
||||
if ( $provider_index === false ) {
|
||||
return new WP_Error( 'invalid_provider_key', 'Invalid provider key' );
|
||||
}
|
||||
|
||||
if ( ! isset( $this->state['providers'][ $provider_index ]['dismissed_errors'] ) ) {
|
||||
$this->state['providers'][ $provider_index ]['dismissed_errors'] = array();
|
||||
}
|
||||
|
||||
if ( $dismissed ) {
|
||||
if ( ! in_array( $error_type, $this->state['providers'][ $provider_index ]['dismissed_errors'], true ) ) {
|
||||
$this->state['providers'][ $provider_index ]['dismissed_errors'][] = $error_type;
|
||||
}
|
||||
} else {
|
||||
$key = array_search( $error_type, $this->state['providers'][ $provider_index ]['dismissed_errors'], true );
|
||||
if ( $key !== false ) {
|
||||
unset( $this->state['providers'][ $provider_index ]['dismissed_errors'][ $key ] );
|
||||
$this->state['providers'][ $provider_index ]['dismissed_errors'] = array_values( $this->state['providers'][ $provider_index ]['dismissed_errors'] );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a provider's state. The provider must already exist in the state to be updated.
|
||||
*
|
||||
* @param string $provider_key The provider key.
|
||||
* @param array $state An array to overlay over the current state.
|
||||
* @return bool|WP_Error True on success, WP_Error on failure.
|
||||
*/
|
||||
private function update_provider_state( $provider_key, $state ) {
|
||||
if ( empty( $this->state['providers'] ) ) {
|
||||
return new WP_Error( 'invalid_provider_key', 'No providers exist' );
|
||||
}
|
||||
|
||||
$provider_index = array_search( $provider_key, array_column( $this->state['providers'], 'key' ), true );
|
||||
if ( $provider_index === false ) {
|
||||
return new WP_Error( 'invalid_provider_key', 'Invalid provider key' );
|
||||
}
|
||||
|
||||
$this->state['providers'][ $provider_index ] = array_merge(
|
||||
$this->state['providers'][ $provider_index ],
|
||||
$state
|
||||
);
|
||||
|
||||
$this->maybe_set_generated();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a provider's state to error.
|
||||
*
|
||||
* @param string $provider_key The provider key.
|
||||
* @param array $errors A list of errors to store with this provider.
|
||||
* @return bool|WP_Error True on success, WP_Error on failure.
|
||||
*/
|
||||
public function set_provider_errors( $provider_key, $errors ) {
|
||||
return $this->update_provider_state(
|
||||
$provider_key,
|
||||
array(
|
||||
'status' => self::PROVIDER_STATES['error'],
|
||||
'errors' => $errors,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a provider's state to success.
|
||||
*
|
||||
* @param string $provider_key The provider key.
|
||||
* @return bool|WP_Error True on success, WP_Error on failure.
|
||||
*/
|
||||
public function set_provider_success( $provider_key ) {
|
||||
return $this->update_provider_state(
|
||||
$provider_key,
|
||||
array(
|
||||
'status' => self::PROVIDER_STATES['success'],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state to generated if all providers are done. Should be called wherever
|
||||
* a provider's state is updated.
|
||||
*/
|
||||
private function maybe_set_generated() {
|
||||
if ( empty( $this->state['providers'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$provider_states = array_column( $this->state['providers'], 'status' );
|
||||
$is_done = ! in_array( self::GENERATION_STATES['pending'], $provider_states, true );
|
||||
|
||||
if ( $is_done ) {
|
||||
$this->state['status'] = self::GENERATION_STATES['generated'];
|
||||
}
|
||||
}
|
||||
|
||||
public function has_errors() {
|
||||
// Check if any of the providers have errors as well.
|
||||
$any_provider_has_error = in_array(
|
||||
'error',
|
||||
array_unique(
|
||||
wp_list_pluck(
|
||||
$this->state['providers'],
|
||||
'status'
|
||||
)
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
return self::GENERATION_STATES['error'] === $this->state['status'] || $any_provider_has_error;
|
||||
}
|
||||
|
||||
public function get_error_message() {
|
||||
return $this->state['status_error'] ?? null;
|
||||
}
|
||||
|
||||
public function is_generated() {
|
||||
return self::GENERATION_STATES['generated'] === $this->state['status'];
|
||||
}
|
||||
|
||||
public function is_requesting() {
|
||||
return self::GENERATION_STATES['pending'] === $this->state['status'];
|
||||
}
|
||||
|
||||
public function prepare_request() {
|
||||
$this->state = array(
|
||||
'status' => self::GENERATION_STATES['pending'],
|
||||
'providers' => array(),
|
||||
'created' => microtime( true ),
|
||||
'updated' => microtime( true ),
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function set_pending_providers( $providers ) {
|
||||
foreach ( $providers as $key => $provider ) {
|
||||
$providers[ $key ]['status'] = self::PROVIDER_STATES['pending'];
|
||||
}
|
||||
$this->state['providers'] = $providers;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add providers to the state, sets their status to pending
|
||||
* and sets the generation status to pending.
|
||||
*
|
||||
* @param array $providers The providers to include in the state and set as pending.
|
||||
* @return $this
|
||||
*/
|
||||
public function prepare_for_generation( $providers ) {
|
||||
$this->set_pending_providers( $providers );
|
||||
$this->state['status'] = self::GENERATION_STATES['pending'];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fresh state
|
||||
*/
|
||||
public function get() {
|
||||
$this->state = jetpack_boost_ds_get( 'critical_css_state' );
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
public function has_pending_provider( $needles = array() ) {
|
||||
if ( empty( $this->state['providers'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$providers = $this->state['providers'];
|
||||
foreach ( $providers as $provider ) {
|
||||
if (
|
||||
! empty( $provider['key'] )
|
||||
&& ! empty( $provider['status'] )
|
||||
&& self::PROVIDER_STATES['pending'] === $provider['status']
|
||||
&& in_array( $provider['key'], $needles, true )
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user