File "Cache_Primer.php"
Full Path: /home/romayxjt/public_html/wp-content/plugins/kadence-starter-templates/inc/resources/Image_Downloader/Cache_Primer.php
File size: 5.27 KB
MIME-type: text/x-php
Charset: utf-8
<?php declare( strict_types=1 );
namespace KadenceWP\KadenceStarterTemplates\Image_Downloader;
use KadenceWP\KadenceStarterTemplates\Hasher;
use KadenceWP\KadenceStarterTemplates\Psr\Log\LoggerInterface;
use KadenceWP\KadenceStarterTemplates\Shutdown\Contracts\Terminable;
use KadenceWP\KadenceStarterTemplates\Symfony\Contracts\HttpClient\HttpClientInterface;
use Throwable;
/**
* Prime Pexels HTTP cache for future image downloading.
*/
final class Cache_Primer implements Terminable {
/**
* @var HttpClientInterface
*/
private $client;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var Hasher
*/
private $hasher;
/**
* How long in seconds to wait until we remotely prime the collection of images again.
*
* @var int Time in seconds.
*/
private $cache_duration;
/**
* How many external cache requests to create before removing them.
*
* @var int
*/
private $batch_size;
/**
* The collections cache, to run when the class is destroyed.
*
* @var array<array{
* collection_slug: string,
* image_type: string,
* images: array<int, array{
* id: int,
* width: int,
* height: int,
* alt: string,
* url: string,
* photographer: string,
* photographer_url: string,
* avg_color: string,
* sizes: non-empty-array<int,array{name: string, src: string}>
* }>
* }> $collections
*/
private $collections;
/**
* @param HttpClientInterface $client The HTTP client.
* @param LoggerInterface $logger The logger.
* @param Hasher $hasher The hasher.
* @param int $cache_duration The cache duration in seconds.
* @param int $batch_size How many external cache requests to create before removing them.
*/
public function __construct(
HttpClientInterface $client,
LoggerInterface $logger,
Hasher $hasher,
int $cache_duration,
int $batch_size = 500
) {
$this->client = $client;
$this->logger = $logger;
$this->hasher = $hasher;
$this->cache_duration = $cache_duration;
$this->batch_size = $batch_size;
}
/**
* Assign which collections will be primed on the WordPress shutdown hook.
*
* @param array<array{
* collection_slug: string,
* image_type: string,
* images: array<int, array{
* id: int,
* width: int,
* height: int,
* alt: string,
* url: string,
* photographer: string,
* photographer_url: string,
* avg_color: string,
* sizes: non-empty-array<int,array{name: string, src: string}>
* }>
* }> $collections
*
* @return void
*/
public function init( array $collections ): void {
if ( empty( $collections ) ) {
return;
}
$this->collections = $collections;
}
/**
* Prime cache on shutdown.
*
* @action shutdown
*
* @return void
* @throws \InvalidArgumentException
* @throws \RuntimeException
*/
public function terminate(): void {
$this->execute();
}
/**
* On shutdown, make asynchronous HEAD requests to all the potential images we'll download
* to ensure that Pexels caches their response to make downloading much quicker.
*
* This allows for 0 blocking.
*
* @action shutdown
*
* @return void
*
* @throws \InvalidArgumentException
* @throws \RuntimeException
*/
private function execute(): void {
if ( ! isset( $this->collections ) ) {
return;
}
$batch = 0;
$cache_key = $this->hasher->hash( $this->collections );
if ( get_transient( $cache_key ) !== false ) {
$this->logger->debug( sprintf( 'Found cache key "%s", skipping image cache priming', $cache_key ) );
unset( $this->collections );
return;
}
// Search results differ slightly from industry collections, reformat.
if ( isset( $this->collections['images'] ) ) {
$this->collections = [ $this->collections ];
}
foreach ( $this->collections as $collection ) {
$this->logger->debug( sprintf( 'Priming image cache for %d images...', count( $collection['images'] ) ) );
foreach ( $collection['images'] as $image ) {
$this->logger->debug( sprintf( 'Priming image cache for: %s', $image['url'] ) );
foreach ( $image['sizes'] as $size ) {
try {
$batch++;
$url = $size['src'];
// These are async requests; We won't wait for the responses.
$promises[ $url ] = $this->client->request( 'HEAD', $url, [
'timeout' => 0.1,
'max_duration' => 0.1,
] );
} catch ( Throwable $e ) {
}
// Remove existing promises when batch size reached.
if ( $batch >= $this->batch_size ) {
$batch = 0;
try {
unset( $promises );
} catch ( Throwable $e ) {
}
}
}
}
}
// Remove any remaining promises.
try {
unset( $promises );
} catch ( Throwable $e ) {
}
// Clear collections state in case this is accessed again in the same request.
unset( $this->collections );
$this->logger->debug( sprintf( 'Caching image priming using key "%s" for %d seconds', $cache_key, $this->cache_duration ) );
set_transient( $cache_key, true, $this->cache_duration );
}
}