HEX
Server: nginx
System: Linux pool64-304-45.dca.atomicsites.net 5.10.0-31-amd64 #1 SMP Debian 5.10.221-1 (2024-07-14) x86_64
User: (0)
PHP: 8.4.18
Disabled: pcntl_fork
Upload Files
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 '+';
		}
}