uawdijnntqw1x1x1
IP : 3.134.94.230
Hostname : premium160.web-hosting.com
Kernel : Linux premium160.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
Disable Function : None :)
OS : Linux
PATH:
/
home
/
batcwwjx
/
www
/
wp-content
/
plugins
/
..
/
plugins
/
autoptimize
/
classes
/
autoptimizeCriticalCSSCron.php
/
/
<?php /** * Critical CSS Cron logic: * processes the queue, submitting jobs to criticalcss.com and retrieving generated CSS from criticalcss.com and saving rules. */ if ( ! defined( 'ABSPATH' ) ) { exit; } class autoptimizeCriticalCSSCron { /** * Critical CSS object. * * @var object */ protected $criticalcss; public function __construct() { $this->criticalcss = autoptimize()->criticalcss(); // Add queue control to a registered event. add_action( 'ao_ccss_queue', array( $this, 'ao_ccss_queue_control' ) ); // Add cleaning job to a registered event. add_action( 'ao_ccss_maintenance', array( $this, 'ao_ccss_cleaning' ) ); } public function ao_ccss_queue_control() { // The queue execution backend. $key = $this->criticalcss->get_option( 'key' ); if ( empty( $key ) ) { // no key set, not processing the queue! $this->criticalcss->log( 'No key set, so not processing queue.', 3 ); return; } /** * Provide a debug facility for the queue * This debug facility provides a way to easily force some queue behaviors useful for development and testing. * To enable this feature, create the file AO_CCSS_DIR . 'queue.json' with a JSON object like the one bellow: * * {"enable":bool,"htcode":int,"status":0|"str","resultStatus ":0|"str","validationStatus":0|"str"} * * Where values are: * - enable : 0 or 1, enable or disable this debug facility straight from the file * - htcode : 0 or any HTTP reponse code (e.g. 2xx, 4xx, 5xx) to force API responses * - status : 0 or a valid value for 'status' (see 'Generating critical css - Job Status Types' in spec docs) * - resultStatus : 0 or a valid value for 'resultStatus' (see 'Appendix - Result status types' in the spec docs) * - validationStatus: 0 or a valid value for 'validationStatus' (see 'Appendix - Validation status types' in the spec docs) * * When properly set, queue will always finish a job with the declared settings above regardless of the real API responses. */ $queue_debug = false; if ( file_exists( AO_CCSS_DEBUG ) ) { $qdobj_raw = file_get_contents( AO_CCSS_DEBUG ); $qdobj = json_decode( $qdobj_raw, true ); if ( $qdobj ) { if ( 1 === $qdobj['enable'] ) { $queue_debug = true; $this->criticalcss->log( 'Queue operating in debug mode with the following settings: <' . $qdobj_raw . '>', 3 ); } } } // Set some default values for $qdobj to avoid function call warnings. if ( ! $queue_debug ) { $qdobj['htcode'] = false; } // Check if queue is already running. $queue_lock = false; if ( file_exists( AO_CCSS_LOCK ) ) { $queue_lock = true; } // Proceed with the queue if it's not already running. if ( ! $queue_lock ) { // Log queue start and create the lock file. $this->criticalcss->log( 'Queue control started', 3 ); if ( touch( AO_CCSS_LOCK ) ) { $this->criticalcss->log( 'Queue control locked', 3 ); } // Attach required variables. $queue = $this->criticalcss->get_option( 'queue' ); $rtimelimit = $this->criticalcss->get_option( 'rtimelimit' ); // make sure we have the queue and bail if not. if ( empty( $queue ) || ! is_array( $queue ) ) { $this->criticalcss->log( 'Job processing cannot work on an empty queue, aborting.', 3 ); unlink( AO_CCSS_LOCK ); return; } // Initialize counters. if ( 0 == $rtimelimit ) { // no time limit set, let's go with 1000 seconds. $rtimelimit = 1000; } $mt = time() + $rtimelimit; // maxtime queue processing can run. $jc = 1; // job count number. $jr = 1; // jobs requests number. $jt = count( $queue ); // number of jobs in queue. // Sort queue by ascending job status (e.g. ERROR, JOB_ONGOING, JOB_QUEUED, NEW...). array_multisort( array_column( $queue, 'jqstat' ), $queue ); // @codingStandardsIgnoreLine // Iterates over the entire queue. foreach ( $queue as $path => $jprops ) { // Prepare flags and target rule. $update = false; $deljob = false; $rule_update = false; $oldccssfile = false; $trule = explode( '|', $jprops['rtarget'] ); // Log job count. $this->criticalcss->log( 'Processing job ' . $jc . ' of ' . $jt . ' with id <' . $jprops['ljid'] . '> and status <' . $jprops['jqstat'] . '>', 3 ); // Process NEW jobs. if ( 'NEW' == $jprops['jqstat'] ) { // Log the new job. $this->criticalcss->log( 'Found NEW job with local ID <' . $jprops['ljid'] . '>, starting its queue processing', 3 ); // Compare job and rule hashes (if any). $hash = $this->ao_ccss_diff_hashes( $jprops['ljid'], $jprops['hash'], $jprops['hashes'], $jprops['rtarget'] ); // If job hash is new or different of a previous one. if ( $hash ) { if ( $jr > 2 ) { // we already posted 2 jobs to criticalcss.com, don't post more this run // but we can keep on processing the queue to keep it tidy. $this->criticalcss->log( 'Holding off on generating request for job with local ID <' . $jprops['ljid'] . '>, maximum number of POSTS reached.', 3 ); continue; } // Set job hash. $jprops['hash'] = $hash; // Dispatch the job generate request and increment request count. $apireq = $this->ao_ccss_api_generate( $path, $queue_debug, $qdobj['htcode'] ); $jr++; // NOTE: All the following conditions maps to the ones in admin_settings_queue.js.php. if ( empty( $apireq ) ) { // ERROR: no response // Update job properties. $jprops['jqstat'] = 'NO_RESPONSE'; $jprops['jrstat'] = 'NONE'; $jprops['jvstat'] = 'NONE'; $jprops['jftime'] = microtime( true ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> request has no response, status now is <' . $jprops['jqstat'] . '>', 3 ); } elseif ( array_key_exists( 'errorCode', $apireq ) && 'INVALID_JWT_TOKEN' == $apireq['errorCode'] ) { // ERROR: key validation // Update job properties. $jprops['jqstat'] = $apireq['errorCode']; $jprops['jrstat'] = $apireq['error']; $jprops['jvstat'] = 'NONE'; $jprops['jftime'] = microtime( true ); $this->criticalcss->log( 'API key validation error when processing job id <' . $jprops['ljid'] . '>, job status is now <' . $jprops['jqstat'] . '>', 3 ); } elseif ( array_key_exists( 'job', $apireq ) && array_key_exists( 'status', $apireq['job'] ) && ( 'JOB_QUEUED' == $apireq['job']['status'] || 'JOB_ONGOING' == $apireq['job']['status'] ) ) { // SUCCESS: request has a valid result. // Update job properties. $jprops['jid'] = $apireq['job']['id']; $jprops['jqstat'] = $apireq['job']['status']; $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> generate request successful, remote id <' . $jprops['jid'] . '>, status now is <' . $jprops['jqstat'] . '>', 3 ); } elseif ( array_key_exists( 'job', $apireq ) && array_key_exists( 'status', $apireq['job'] ) && 'STATUS_JOB_BAD' == $apireq['job']['status'] ) { // ERROR: concurrent requests // Update job properties. $jprops['jid'] = $apireq['job']['id']; $jprops['jqstat'] = $apireq['job']['status']; if ( $apireq['job']['error'] ) { $jprops['jrstat'] = $apireq['job']['error']; } else { $jprops['jrstat'] = 'Baby did a bad bad thing'; } $jprops['jvstat'] = 'NONE'; $jprops['jftime'] = microtime( true ); $this->criticalcss->log( 'Concurrent requests when processing job id <' . $jprops['ljid'] . '>, job status is now <' . $jprops['jqstat'] . '>', 3 ); } else { // UNKNOWN: unhandled generate exception // Update job properties. $jprops['jqstat'] = 'JOB_UNKNOWN'; $jprops['jrstat'] = 'NONE'; $jprops['jvstat'] = 'NONE'; $jprops['jftime'] = microtime( true ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> generate request has an UNKNOWN condition, status now is <' . $jprops['jqstat'] . '>, check log messages above for more information', 2 ); $this->criticalcss->log( 'Job response was: ' . json_encode( $apireq ), 3 ); } } else { // SUCCESS: Job hash is equal to a previous one, so it's done // Update job status and finish time. $jprops['jqstat'] = 'JOB_DONE'; $jprops['jftime'] = microtime( true ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> requires no further processing, status now is <' . $jprops['jqstat'] . '>', 3 ); } // Set queue update flag. $update = true; } elseif ( 'JOB_QUEUED' == $jprops['jqstat'] || 'JOB_ONGOING' == $jprops['jqstat'] ) { // Process QUEUED and ONGOING jobs // Log the pending job. $this->criticalcss->log( 'Found PENDING job with local ID <' . $jprops['ljid'] . '>, continuing its queue processing', 3 ); // Dispatch the job result request and increment request count. $apireq = $this->ao_ccss_api_results( $jprops['jid'], $queue_debug, $qdobj['htcode'] ); // NOTE: All the following condigitons maps to the ones in admin_settings_queue.js.php // Replace API response values if queue debugging is enabled and some value is set. if ( $queue_debug ) { if ( $qdobj['status'] ) { $apireq['status'] = $qdobj['status']; } if ( $qdobj['resultStatus'] ) { $apireq['resultStatus'] = $qdobj['resultStatus']; } if ( $qdobj['validationStatus'] ) { $apireq['validationStatus'] = $qdobj['validationStatus']; } } if ( empty( $apireq ) || ! is_array( $apireq ) ) { // ERROR: no response // Update job properties. $jprops['jqstat'] = 'NO_RESPONSE'; $jprops['jrstat'] = 'NONE'; $jprops['jvstat'] = 'NONE'; $jprops['jftime'] = microtime( true ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> request has no response, status now is <' . $jprops['jqstat'] . '>', 3 ); } elseif ( array_key_exists( 'status', $apireq ) && ( 'JOB_QUEUED' == $apireq['status'] || 'JOB_ONGOING' == $apireq['status'] ) ) { // SUCCESS: request has a valid result // Process a PENDING job // Update job properties. $jprops['jqstat'] = $apireq['status']; $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . '> unchanged', 3 ); } elseif ( array_key_exists( 'status', $apireq ) && 'JOB_DONE' == $apireq['status'] ) { // Process a DONE job // New resultStatus from ccss.com "HTML_404", consider as "GOOD" for now. if ( 'HTML_404' == $apireq['resultStatus'] ) { $apireq['resultStatus'] = 'GOOD'; } if ( 'GOOD' == $apireq['resultStatus'] && ( 'GOOD' == $apireq['validationStatus'] || 'WARN' == $apireq['validationStatus'] ) ) { // SUCCESS: GOOD job with GOOD or WARN validation // Update job properties. $jprops['file'] = $this->ao_ccss_save_file( $apireq['css'], $trule, false ); $jprops['jqstat'] = $apireq['status']; $jprops['jrstat'] = $apireq['resultStatus']; $jprops['jvstat'] = $apireq['validationStatus']; $jprops['jftime'] = microtime( true ); $rule_update = true; do_action( 'autoptimize_action_ccss_cron_rule_saved', $jprops['rtarget'], $jprops['file'] ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . '>, file saved <' . $jprops['file'] . '>', 3 ); } elseif ( 'GOOD' == $apireq['resultStatus'] && ( 'BAD' == $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' == $apireq['validationStatus'] ) ) { // SUCCESS: GOOD job with BAD or SCREENSHOT_WARN_BLANK validation // Update job properties. $jprops['jqstat'] = $apireq['status']; $jprops['jrstat'] = $apireq['resultStatus']; $jprops['jvstat'] = $apireq['validationStatus']; $jprops['jftime'] = microtime( true ); if ( apply_filters( 'autoptimize_filter_ccss_save_review_rules', true ) ) { $jprops['file'] = $this->ao_ccss_save_file( $apireq['css'], $trule, true ); $rule_update = true; do_action( 'autoptimize_action_ccss_cron_rule_saved', $jprops['rtarget'], $jprops['file'] ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . ', file saved <' . $jprops['file'] . '> but requires REVIEW', 3 ); } else { $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . ', file not saved because it required REVIEW.', 3 ); } } elseif ( 'GOOD' != $apireq['resultStatus'] && ( 'GOOD' != $apireq['validationStatus'] || 'WARN' != $apireq['validationStatus'] || 'BAD' != $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' != $apireq['validationStatus'] ) ) { // ERROR: no GOOD, WARN or BAD results // Update job properties. $jprops['jqstat'] = $apireq['status']; $jprops['jrstat'] = $apireq['resultStatus']; $jprops['jvstat'] = $apireq['validationStatus']; $jprops['jftime'] = microtime( true ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful but job FAILED, status now is <' . $jprops['jqstat'] . '>', 3 ); $apireq['css'] = '/* critical css removed for DEBUG logging purposes */'; $this->criticalcss->log( 'Job response was: ' . json_encode( $apireq ), 3 ); } else { // UNKNOWN: unhandled JOB_DONE exception // Update job properties. $jprops['jqstat'] = 'JOB_UNKNOWN'; $jprops['jrstat'] = $apireq['resultStatus']; $jprops['jvstat'] = $apireq['validationStatus']; $jprops['jftime'] = microtime( true ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful but job is UNKNOWN, status now is <' . $jprops['jqstat'] . '>', 2 ); $apireq['css'] = '/* critical css removed for DEBUG logging purposes */'; $this->criticalcss->log( 'Job response was: ' . json_encode( $apireq ), 3 ); } } elseif ( array_key_exists( 'job', $apireq ) && is_array( $apireq['job'] ) && array_key_exists( 'status', $apireq['job'] ) && ( 'JOB_FAILED' == $apireq['job']['status'] || 'STATUS_JOB_BAD' == $apireq['job']['status'] ) ) { // ERROR: failed job // Update job properties. $jprops['jqstat'] = $apireq['job']['status']; if ( $apireq['job']['error'] ) { $jprops['jrstat'] = $apireq['job']['error']; } else { $jprops['jrstat'] = 'Baby did a bad bad thing'; } $jprops['jvstat'] = 'NONE'; $jprops['jftime'] = microtime( true ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful but job FAILED, status now is <' . $jprops['jqstat'] . '>', 3 ); } elseif ( array_key_exists( 'error', $apireq ) && 'This css no longer exists. Please re-generate it.' == $apireq['error'] ) { // ERROR: CSS doesn't exist // Update job properties. $jprops['jqstat'] = 'NO_CSS'; $jprops['jrstat'] = $apireq['error']; $jprops['jvstat'] = 'NONE'; $jprops['jftime'] = microtime( true ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful but job FAILED, status now is <' . $jprops['jqstat'] . '>', 3 ); } else { // UNKNOWN: unhandled results exception // Update job properties. $jprops['jqstat'] = 'JOB_UNKNOWN'; $jprops['jrstat'] = 'NONE'; $jprops['jvstat'] = 'NONE'; $jprops['jftime'] = microtime( true ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request has an UNKNOWN condition, status now is <' . $jprops['jqstat'] . '>, check log messages above for more information', 2 ); } // Set queue update flag. $update = true; } // Mark DONE jobs for removal. if ( 'JOB_DONE' == $jprops['jqstat'] ) { $update = true; $deljob = true; } // Persist updated queue object. if ( $update ) { if ( ! $deljob ) { // Update properties of a NEW or PENDING job... $queue[ $path ] = $jprops; } else { // ...or remove the DONE job. unset( $queue[ $path ] ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> is DONE and was removed from the queue', 3 ); } // Update queue object. $queue_raw = json_encode( $queue ); update_option( 'autoptimize_ccss_queue', $queue_raw, false ); $this->criticalcss->log( 'Queue updated by job id <' . $jprops['ljid'] . '>', 3 ); // Update target rule. if ( $rule_update ) { $this->ao_ccss_rule_update( $jprops['ljid'], $jprops['rtarget'], $jprops['file'], $jprops['hash'] ); $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> updated the target rule <' . $jprops['rtarget'] . '>', 3 ); } } else { // Or log no queue action. $this->criticalcss->log( 'Nothing to do on this job', 3 ); } // Break the loop if request time limit is (almost exceeded). if ( time() > $mt ) { $this->criticalcss->log( 'The time limit of ' . $rtimelimit . ' seconds was exceeded, queue control must finish now', 3 ); break; } // Increment job counter. $jc++; } // Remove the lock file and log the queue end. if ( file_exists( AO_CCSS_LOCK ) ) { unlink( AO_CCSS_LOCK ); $this->criticalcss->log( 'Queue control unlocked', 3 ); } $this->criticalcss->log( 'Queue control finished', 3 ); // Log that queue is locked. } else { $this->criticalcss->log( 'Queue is already running, skipping the attempt to run it again', 3 ); } } public function ao_ccss_diff_hashes( $ljid, $hash, $hashes, $rule ) { // Compare job hashes // STEP 1: update job hashes. if ( 1 == count( $hashes ) ) { // Job with a single hash // Set job hash. $hash = $hashes[0]; $this->criticalcss->log( 'Job id <' . $ljid . '> updated with SINGLE hash <' . $hash . '>', 3 ); } else { // Job with multiple hashes // Loop through hashes to concatenate them. $nhash = ''; foreach ( $hashes as $shash ) { $nhash .= $shash; } // Set job hash. $hash = md5( $nhash ); $this->criticalcss->log( 'Job id <' . $ljid . '> updated with a COMPOSITE hash <' . $hash . '>', 3 ); } // STEP 2: compare job to existing jobs to prevent double submission for same type+hash. $queue = $this->criticalcss->get_option( 'queue' ); foreach ( $queue as $queue_item ) { $this->criticalcss->log( 'Comparing <' . $rule . $hash . '> with <' . $queue_item['rtarget'] . $queue_item['hash'] . '>', 3 ); if ( $queue_item['hash'] == $hash && $queue_item['rtarget'] == $rule && in_array( $queue_item['jqstat'], array( 'JOB_QUEUED', 'JOB_ONGOING', 'JOB_DONE' ) ) ) { $this->criticalcss->log( 'Job id <' . $ljid . '> matches the already pending job <' . $queue_item['ljid'] . '>', 3 ); return false; } } // STEP 3: compare job and existing rule (if any) hashes // Attach required arrays. $rules = $this->criticalcss->get_option( 'rules' ); // Prepare rule variables. $trule = explode( '|', $rule ); if ( is_array( $trule ) && ! empty( $trule ) && array_key_exists( $trule[1], $rules[ $trule[0] ] ) ) { $srule = $rules[ $trule[0] ][ $trule[1] ]; } else { $srule = ''; } // If hash is empty, set it to now for a "forced job". if ( empty( $hash ) ) { $hash = 'new'; $this->criticalcss->log( 'Job id <' . $ljid . '> had no hash, assuming forced job so setting hash to new', 3 ); } // Check if a MANUAL rule exist and return false. if ( ! empty( $srule ) && ( 0 == $srule['hash'] && 0 != $srule['file'] ) ) { $this->criticalcss->log( 'Job id <' . $ljid . '> matches the MANUAL rule <' . $trule[0] . '|' . $trule[1] . '>', 3 ); return false; } elseif ( ! empty( $srule ) ) { // Check if an AUTO rule exist. if ( $hash === $srule['hash'] && is_file( AO_CCSS_DIR . $srule['file'] ) && 0 != filesize( AO_CCSS_DIR . $srule['file'] ) ) { // Check if job hash matches rule, if the CCSS file exists said file is not empty and return FALSE is so. $this->criticalcss->log( 'Job id <' . $ljid . '> with hash <' . $hash . '> MATCH the one in rule <' . $trule[0] . '|' . $trule[1] . '>', 3 ); return false; } else { // Or return the new hash if they differ. $this->criticalcss->log( 'Job id <' . $ljid . '> with hash <' . $hash . '> DOES NOT MATCH the one in rule <' . $trule[0] . '|' . $trule[1] . '> or rule\'s CCSS file was invalid.', 3 ); return $hash; } } else { // Return the hash for a job that has no rule yet. $this->criticalcss->log( 'Job id <' . $ljid . '> with hash <' . $hash . '> has no rule yet', 3 ); return $hash; } } public function ao_ccss_api_generate( $path, $debug, $dcode ) { // POST jobs to criticalcss.com and return responses // Get key and key status. $key = $this->criticalcss->get_option( 'key' ); $key_status = $this->criticalcss->get_option( 'keyst' ); $noptimize = $this->criticalcss->get_option( 'noptimize' ); // Prepare full URL to request. $site_host = get_site_url(); $site_path = parse_url( $site_host, PHP_URL_PATH ); if ( ! empty( $site_path ) ) { $site_host = str_replace( $site_path, '', $site_host ); } // Logic to bind to one domain to avoid site clones of sites would // automatically begin spawning requests to criticalcss.com which has // a per domain cost. $domain = $this->criticalcss->get_option( 'domain' ); if ( empty( $domain ) ) { // first request being done, update option to allow future requests are only allowed if from same domain. update_option( 'autoptimize_ccss_domain', str_rot13( $site_host ) ); } elseif ( trim( $domain, '\'"' ) !== 'none' && parse_url( $site_host, PHP_URL_HOST ) !== parse_url( $domain, PHP_URL_HOST ) && apply_filters( 'autoptimize_filter_ccss_bind_domain', true ) ) { // not the same domain, log as error and return without posting to criticalcss.com. $this->criticalcss->log( 'Request for domain ' . $site_host . ' does not match bound domain ' . $domain . ' so not proceeding.', 2 ); return false; } $src_url = $site_host . $path; // Avoid AO optimizations if required by config or avoid lazyload if lazyload is active in AO. if ( ! empty( $noptimize ) ) { $src_url .= '?ao_noptirocket=1'; } elseif ( ( class_exists( 'autoptimizeImages', false ) && autoptimizeImages::should_lazyload_wrapper() ) || apply_filters( 'autoptimize_filter_ccss_enforce_nolazy', false ) ) { $src_url .= '?ao_nolazy=1'; } $src_url = apply_filters( 'autoptimize_filter_ccss_cron_srcurl', $src_url ); if ( true !== autoptimizeUtils::is_local_server( parse_url( $src_url, PHP_URL_HOST ) ) ) { // Initialize request body. $body = array(); $body['url'] = $src_url; $body['aff'] = 1; $body['aocssv'] = AO_CCSS_VER; // Prepare and add viewport size to the body if available. $viewport = $this->criticalcss->viewport(); if ( ! empty( $viewport['w'] ) && ! empty( $viewport['h'] ) ) { $body['width'] = $viewport['w']; $body['height'] = $viewport['h']; } // Prepare and add forceInclude to the body if available. $finclude = $this->criticalcss->get_option( 'finclude' ); $finclude = $this->ao_ccss_finclude( $finclude ); if ( ! empty( $finclude ) ) { $body['forceInclude'] = $finclude; } // Add filter to allow the body array to be altered (e.g. to add customPageHeaders). $body = apply_filters( 'autoptimize_ccss_cron_api_generate_body', $body ); // Body must be json and log it. $body = json_encode( $body, JSON_UNESCAPED_SLASHES ); $this->criticalcss->log( 'criticalcss.com: POST generate request body is ' . $body, 3 ); // Prepare the request. $url = esc_url_raw( AO_CCSS_API . 'generate?aover=' . AO_CCSS_VER ); $args = array( 'headers' => apply_filters( 'autoptimize_ccss_cron_api_generate_headers', array( 'User-Agent' => 'Autoptimize v' . AO_CCSS_VER, 'Content-type' => 'application/json; charset=utf-8', 'Authorization' => 'JWT ' . $key, 'Connection' => 'close', ) ), 'body' => $body, ); // Dispatch the request and store its response code. $req = wp_safe_remote_post( $url, $args ); $code = wp_remote_retrieve_response_code( $req ); $body = json_decode( wp_remote_retrieve_body( $req ), true ); if ( $debug && $dcode ) { // If queue debug is active, change response code. $code = $dcode; } if ( 200 == $code ) { // Response code is OK. // Workaround criticalcss.com non-RESTful reponses. if ( 'JOB_QUEUED' == $body['job']['status'] || 'JOB_ONGOING' == $body['job']['status'] || 'STATUS_JOB_BAD' == $body['job']['status'] ) { // Log successful and return encoded request body. $this->criticalcss->log( 'criticalcss.com: POST generate request for path <' . $src_url . '> replied successfully', 3 ); // This code also means the key is valid, so cache key status for 24h if not already cached. if ( ( ! $key_status || 2 != $key_status ) && $key ) { update_option( 'autoptimize_ccss_keyst', 2 ); $this->criticalcss->log( 'criticalcss.com: API key is valid, updating key status', 3 ); } // Return the request body. return $body; } else { // Log successful requests with invalid reponses. $this->criticalcss->log( 'criticalcss.com: POST generate request for path <' . $src_url . '> replied with code <' . $code . '> and an UNKNOWN error condition, body follows...', 2 ); $this->criticalcss->log( print_r( $body, true ), 2 ); return $body; } } else { // Response code is anything else. // Log failed request with a valid response code and return body. if ( $code ) { $this->criticalcss->log( 'criticalcss.com: POST generate request for path <' . $src_url . '> replied with error code <' . $code . '>, body follows...', 2 ); $this->criticalcss->log( print_r( $body, true ), 2 ); if ( 401 == $code ) { // If request is unauthorized, also clear key status. update_option( 'autoptimize_ccss_keyst', 1 ); $this->criticalcss->log( 'criticalcss.com: API key is invalid, updating key status', 3 ); } // Return the request body. return $body; } else { // Log failed request with no response and return false. $this->criticalcss->log( 'criticalcss.com: POST generate request for path <' . $src_url . '> has no response, this could be a service timeout', 2 ); if ( is_wp_error( $req ) ) { $this->criticalcss->log( $req->get_error_message(), 2 ); } return false; } } } else { // localhost/ private network server, no CCSS possible. $this->criticalcss->log( 'ccss cron: job not created at ccss.com as for local server', 3 ); return false; } } public function ao_ccss_api_results( $jobid, $debug, $dcode ) { // GET jobs from criticalcss.com and return responses // Get key. $key = $this->criticalcss->get_option( 'key' ); // Prepare the request. $url = AO_CCSS_API . 'results?resultId=' . $jobid; $args = array( 'headers' => apply_filters( 'autoptimize_ccss_cron_api_generate_headers', array( 'User-Agent' => 'Autoptimize CriticalCSS Power-Up v' . AO_CCSS_VER, 'Authorization' => 'JWT ' . $key, 'Connection' => 'close', ) ), ); // Dispatch the request and store its response code. $req = wp_safe_remote_get( $url, $args ); $code = wp_remote_retrieve_response_code( $req ); $body = json_decode( wp_remote_retrieve_body( $req ), true ); if ( $debug && $dcode ) { // If queue debug is active, change response code. $code = $dcode; } if ( 200 == $code ) { // Response code is OK. if ( is_array( $body ) && ( array_key_exists( 'status', $body ) || array_key_exists( 'job', $body ) ) && ( 'JOB_QUEUED' == $body['status'] || 'JOB_ONGOING' == $body['status'] || 'JOB_DONE' == $body['status'] || 'JOB_FAILED' == $body['status'] || 'JOB_UNKNOWN' == $body['status'] || 'STATUS_JOB_BAD' == $body['job']['status'] ) ) { // Workaround criticalcss.com non-RESTful reponses // Log successful and return encoded request body. $this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied successfully', 3 ); return $body; } elseif ( is_array( $body ) && ( array_key_exists( 'error', $body ) && 'This css no longer exists. Please re-generate it.' == $body['error'] ) ) { // Handle no CSS reply // Log no CSS error and return encoded request body. $this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied successfully but the CSS for it does not exist anymore', 3 ); return $body; } else { // Log failed request and return false. $this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied with code <' . $code . '> and an UNKNOWN error condition, body follows...', 2 ); $this->criticalcss->log( print_r( $body, true ), 2 ); return false; } } else { // Response code is anything else // Log failed request with a valid response code and return body. if ( $code ) { $this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied with error code <' . $code . '>, body follows...', 2 ); $this->criticalcss->log( print_r( $body, true ), 2 ); if ( 401 == $code ) { // If request is unauthorized, also clear key status. update_option( 'autoptimize_ccss_keyst', 1 ); $this->criticalcss->log( 'criticalcss.com: API key is invalid, updating key status', 3 ); } // Return the request body. return $body; } else { // Log failed request with no response and return false. $this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> has no response, this could be a service timeout', 2 ); return false; } } } public function ao_ccss_save_file( $ccss, $target, $review ) { // Save critical CSS into the filesystem and return its filename // Prepare review mark. if ( $review ) { $rmark = '_R'; } else { $rmark = ''; } // Prepare target rule, filename and content. $filename = false; $content = $ccss; if ( $this->criticalcss->check_contents( $content ) ) { // Sanitize content, set filename and try to save file. $file = AO_CCSS_DIR . 'ccss_' . md5( $ccss . $target[1] ) . $rmark . '.css'; $status = file_put_contents( $file, $content, LOCK_EX ); $filename = pathinfo( $file, PATHINFO_BASENAME ); $this->criticalcss->log( 'Critical CSS file for the rule <' . $target[0] . '|' . $target[1] . '> was saved as <' . $filename . '>, size in bytes is <' . $status . '>', 3 ); if ( ! $status ) { // If file has not been saved, reset filename. $this->criticalcss->log( 'Critical CSS file <' . $filename . '> could not be not saved', 2 ); $filename = false; return $filename; } } else { $this->criticalcss->log( 'Critical CSS received did not pass content check', 2 ); return $filename; } // Remove old critical CSS if a previous one existed in the rule and if that file exists in filesystem // Attach required arrays. $rules = $this->criticalcss->get_option( 'rules' ); // Only proceed if the rule already existed. if ( array_key_exists( $target[1], $rules[ $target[0] ] ) ) { $srule = $rules[ $target[0] ][ $target[1] ]; $oldfile = $srule['file']; if ( $oldfile && $oldfile !== $filename ) { $delfile = AO_CCSS_DIR . $oldfile; if ( file_exists( $delfile ) ) { $unlinkst = unlink( $delfile ); if ( $unlinkst ) { $this->criticalcss->log( 'A previous critical CSS file <' . $oldfile . '> was removed for the rule <' . $target[0] . '|' . $target[1] . '>', 3 ); } } } } // Return filename or false. return $filename; } public function ao_ccss_rule_update( $ljid, $srule, $file, $hash ) { // Update or create a rule // Attach required arrays. $rules = $this->criticalcss->get_option( 'rules' ); // Prepare rule variables. $trule = explode( '|', $srule ); if ( array_key_exists( $trule[1], $rules[ $trule[0] ] ) ) { $rule = $rules[ $trule[0] ][ $trule[1] ]; } else { $rule = array(); } $action = false; $rtype = ''; if ( is_array( $rule ) && array_key_exists( 'hash', $rule ) && 0 === $rule['hash'] && array_key_exists( 'file', $rule ) && 0 !== $rule['file'] ) { // manual rule, don't ever overwrite. $action = 'NOT UPDATED'; $rtype = 'MANUAL'; } elseif ( is_array( $rule ) && array_key_exists( 'hash', $rule ) && 0 === $rule['hash'] && array_key_exists( 'file', $rule ) && 0 === $rule['file'] ) { // If this is an user created AUTO rule with no hash and file yet, update its hash and filename // Set rule hash, file and action flag. $rule['hash'] = $hash; $rule['file'] = $file; $action = 'UPDATED'; $rtype = 'AUTO'; } elseif ( is_array( $rule ) && array_key_exists( 'hash', $rule ) && 0 !== $rule['hash'] && ctype_alnum( $rule['hash'] ) ) { // If this is an genuine AUTO rule, update its hash and filename // Set rule hash, file and action flag. $rule['hash'] = $hash; $rule['file'] = $file; $action = 'UPDATED'; $rtype = 'AUTO'; } else { // If rule doesn't exist, create an AUTO rule // AUTO rules were only for types, but will now also work for paths. if ( ( 'types' == $trule[0] || 'paths' == $trule[0] ) && ! empty( $trule[1] ) ) { // Set rule hash and file and action flag. $rule['hash'] = $hash; $rule['file'] = $file; $action = 'CREATED'; $rtype = 'AUTO'; } else { // Log that no rule was created. $this->criticalcss->log( 'Exception, no AUTO rule created', 3 ); } } if ( $action ) { // If a rule creation/update is required, persist updated rules object. $rules[ $trule[0] ][ $trule[1] ] = $rule; $rules_raw = json_encode( $rules ); update_option( 'autoptimize_ccss_rules', $rules_raw ); $this->criticalcss->flush_options(); $this->criticalcss->log( 'Target rule <' . $srule . '> of type <' . $rtype . '> was ' . $action . ' for job id <' . $ljid . '>', 3 ); // and trigger action for whoever needs to be aware. do_action( 'autoptimize_action_ccss_cron_rule_updated', $srule, $file, '' ); } else { $this->criticalcss->log( 'No rule action required', 3 ); } } function ao_ccss_finclude( $finclude_raw ) { // Prepare forceInclude object. if ( ! empty( $finclude_raw ) ) { // If there are any content // Convert raw string into arra and initialize the returning object. $fincludes = explode( ',', $finclude_raw ); $finclude = array(); // Interacts over every rule. $i = 0; foreach ( $fincludes as $include ) { // Trim leading and trailing whitespaces. $include = trim( $include ); if ( substr( $include, 0, 2 ) === '//' ) { // Regex rule // Format value as required. $include = str_replace( '//', '/', $include ); $include = $include . '/i'; // Store regex object. $finclude[ $i ]['type'] = 'RegExp'; $finclude[ $i ]['value'] = $include; } else { // Simple value rule. $finclude[ $i ]['value'] = $include; } $i++; } // Return forceInclude object. return $finclude; } else { // Or just return false if empty. return false; } } public function ao_ccss_cleaning() { // Perform plugin maintenance // Truncate log file >= 1MB . if ( file_exists( AO_CCSS_LOG ) ) { if ( filesize( AO_CCSS_LOG ) >= 1048576 ) { $logfile = fopen( AO_CCSS_LOG, 'w' ); fclose( $logfile ); } } // Remove lock file. if ( file_exists( AO_CCSS_LOCK ) ) { unlink( AO_CCSS_LOCK ); } // Make sure queue processing is scheduled, recreate if not. if ( ! wp_next_scheduled( 'ao_ccss_queue' ) ) { wp_schedule_event( time(), apply_filters( 'ao_ccss_queue_schedule', 'ao_ccss' ), 'ao_ccss_queue' ); } // Queue cleaning. $queue = $this->criticalcss->get_option( 'queue' ); if ( isset( $queue ) && is_array( $queue ) ) { $queue_purge_threshold = 100; $queue_purge_age = 24 * 60 * 60; $queue_length = count( $queue ); $timestamp_yesterday = microtime( true ) - $queue_purge_age; $remove_old_new = false; $queue_altered = false; if ( $queue_length > $queue_purge_threshold ) { $remove_old_new = true; } foreach ( $queue as $path => $job ) { if ( ( $remove_old_new && 'NEW' == $job['jqstat'] && $job['jctime'] < $timestamp_yesterday ) || in_array( $job['jqstat'], array( 'JOB_FAILED', 'STATUS_JOB_BAD', 'NO_CSS', 'NO_RESPONSE' ) ) ) { unset( $queue[ $path ] ); $queue_altered = true; } } // save queue to options! if ( $queue_altered ) { $queue_raw = json_encode( $queue ); update_option( 'autoptimize_ccss_queue', $queue_raw, false ); $this->criticalcss->log( 'Queue cleaning done.', 3 ); } } // re-check key if invalid. $keyst = $this->criticalcss->get_option( 'keyst' ); if ( 1 == $keyst ) { $this->ao_ccss_api_generate( '', '', '' ); } } }
/home/batcwwjx/www/wp-content/plugins/../plugins/autoptimize/classes/autoptimizeCriticalCSSCron.php