File: //scripts/cache-control.php
<?php
switch( $_GET['action'] ) {
case 'cached-scripts-compile':
$rval = array(
'compiled' => 0,
'discarded' => 0,
'compile_errors' => 0,
'slept' => 0,
'compile_error_files' => array(),
);
if ( empty( $_POST['files'] ) ) {
die( json_encode( $rval ) . "\n" );
}
$files = json_decode( $_POST['files'] );
if ( ! is_array( $files ) ) {
header( 'HTTP/1.1 400 Invalid files data' );
die( json_encode( $rval ) . "\n" );
}
foreach( $files as $file ) {
if ( $file === '/scripts/env.php' ) {
// because this file is php_admin_value[auto_prepend_file] we cannot compile it. we will
// get error messages like the following in the poolx.atomicsites.blog error log:
// PHP Fatal error: Cannot redeclare __atomic_env_define() (previously declared in /scripts/env.php:15) in /scripts/env.php on line 15
// PHP Warning: Zend OPcache could not compile file /scripts/env.php in /scripts/cache-control.php on line 24
continue;
}
if ( ! file_exists( $file ) ) {
$rval['discarded']++;
continue;
}
if ( opcache_is_script_cached( $file ) ) {
// handle resuming
continue;
}
$start = microtime( true );
if ( false === opcache_compile_file( $file ) ) {
$rval['compile_error_files'][] = $file;
$rval['compile_errors']++;
continue;
}
$took = microtime( true ) - $start;
$rval['compiled']++;
$sleepfor = $took * 1000000 * 5;
usleep( $sleepfor );
$rval['slept'] += ( $took * 5 );
}
die( json_encode( $rval ) . "\n" );
case 'cached-scripts-list':
$rval = array();
$status = opcache_get_status( true );
if ( ! isset( $status['scripts'] ) || empty( $status['scripts'] ) ) {
die( json_encode( $rval ) );
}
foreach( $status['scripts'] as $entry ) {
if ( empty( $entry['full_path'] ) ) {
// hmm...
continue;
}
if ( $entry['full_path'] === '/scripts/env.php' ) {
// because this file is php_admin_value[auto_prepend_file] we cannot compile it. we will
// get error messages like the following in the poolx.atomicsites.blog error log:
// PHP Fatal error: Cannot redeclare __atomic_env_define() (previously declared in /scripts/env.php:15) in /scripts/env.php on line 15
// PHP Warning: Zend OPcache could not compile file /scripts/env.php in /scripts/cache-control.php on line 24
continue;
}
if ( ! opcache_is_script_cached( $entry['full_path'] ) ) {
// Because the opcache is shared by all php-fpm worker pools. And because of the quirk of
// these entries only showing the name of the script as being bwlow the docroot while still
// accounting of them as individual per docroot (based on the inod, internally, IIRC) we
// get a list of all cached files across all possible chroots. But opcache_is_script_cached()
// does properly check that the version of this file specific to this chroot is or is not
// cached. Therefor we can simply skip any file that opcache_get_status() lists but that
// opcache_is_script_cached() does not claim since the file you are looking for is in
// another castle.
continue;
}
if ( ! file_exists( $entry['full_path'] ) ) {
// Under v3 I would assume that this meant that the file did exist but now has changed such
// as with a plugin version change. But under v4 this should not happen since the new chroot
// is in a physically different location
//header( 'HTTP/1.1 500 Impossible File Found' );
//print_r( $entry );
//die();
continue;
}
$rval[] = $entry['full_path'];
}
die( json_encode( $rval ) );
case 'prefix_invalidations':
if ( empty( $_POST['prefixes'] ) ) {
die( 'OK' );
}
if ( ! is_array( $_POST['prefixes'] ) ) {
$_POST['prefixes'] = array( $_POST['prefixes'] );
}
$status = opcache_get_status( true );
$invalidations = array();
foreach ( $_POST['prefixes'] as $prefix ) {
$invalidations[ $prefix ] = array(
'invalidations' => array(
'total' => 0,
'paths' => 0,
'keys' => 0,
),
'skipped' => array(
'uncached' => 0
),
);
foreach ( $status['scripts'] as $key => $script ) {
if ( 0 !== strpos( $script['full_path'], $prefix ) ) {
continue;
}
$invalidated = false;
if ( $key !== $script['full_path'] ) {
if ( false !== opcache_is_script_cached( $key ) ) {
opcache_invalidate( $key, true );
$invalidated = true;
$invalidations[ $prefix ]['invalidations']['keys']++;
$invalidations[ $prefix ]['invalidations']['total']++;
}
}
if ( false !== opcache_is_script_cached( $script['full_path'] ) ) {
opcache_invalidate( $script['full_path'], true );
$invalidated = true;
$invalidations[ $prefix ]['invalidations']['paths']++;
$invalidations[ $prefix ]['invalidations']['total']++;
}
if ( false === $invalidated ) {
$invalidations[ $prefix ]['skipped']['uncached']++;
}
}
}
die( json_encode( $invalidations, JSON_PRETTY_PRINT ) );
default:
if ( empty( $_POST['delete_files'] ) ) {
die( 'OK' );
}
foreach( $_POST['delete_files'] as $file ) {
if ( ! opcache_is_script_cached( $file ) ) {
echo '.';
continue;
}
if ( ! opcache_invalidate( $file, true ) ) {
echo '-';
continue;
}
echo '+';
}
}