| 2277 | |
| 2278 | /** |
| 2279 | * Attempt to clear the opcode cache for an individual PHP file. |
| 2280 | * |
| 2281 | * This function can be called safely without having to check the file extension |
| 2282 | * or availability of the OPcache extension. |
| 2283 | * |
| 2284 | * Whether or not invalidation is possible is cached to improve performance. |
| 2285 | * |
| 2286 | * @since 5.5 |
| 2287 | * |
| 2288 | * @link https://www.php.net/manual/en/function.opcache-invalidate.php |
| 2289 | * |
| 2290 | * @param string $filepath Path to the file, including extension, for which the opcode cache is to be cleared. |
| 2291 | * @param bool $force Invalidate even if the modification time is not newer than the file in cache. Default `false`. |
| 2292 | * |
| 2293 | * @return bool `true` if opcache was invalidated for `$filepath`, or there was nothing to invalidate. |
| 2294 | * `false` if opcache invalidation is not available, or is disabled via filter. |
| 2295 | */ |
| 2296 | function wp_opcache_invalidate( $filepath, $force = false ) { |
| 2297 | static $can_invalidate = null; |
| 2298 | |
| 2299 | /* |
| 2300 | * Check to see if WordPress is able to run `opcache_invalidate()` or not, and cache the value. |
| 2301 | * |
| 2302 | * First, check to see if the function is available to call, then if the host has restricted |
| 2303 | * the ability to run the function to avoid a PHP warning. |
| 2304 | * |
| 2305 | * `opcache.restrict_api` can specify the path for files allowed to call `opcache_invalidate()`. |
| 2306 | * |
| 2307 | * If the host has this set, check whether the path in `opcache.restrict_api` matches |
| 2308 | * the beginning of the path of the origin file. |
| 2309 | * |
| 2310 | * `$_SERVER['SCRIPT_FILENAME']` approximates the origin file's path, but |
| 2311 | * `realpath()` is necessary because `SCRIPT_FILENAME` can be a relative path |
| 2312 | * when run from CLI. |
| 2313 | * |
| 2314 | * For more details, see: |
| 2315 | * - https://www.php.net/manual/en/opcache.configuration.php |
| 2316 | * - https://www.php.net/manual/en/reserved.variables.server.php |
| 2317 | * - https://core.trac.wordpress.org/ticket/36455 |
| 2318 | */ |
| 2319 | if ( $can_invalidate === null ) { |
| 2320 | $can_invalidate = function_exists( 'opcache_invalidate' ) && |
| 2321 | ( ! ini_get( 'opcache.restrict_api' ) || |
| 2322 | stripos( realpath( $_SERVER['SCRIPT_FILENAME'] ), ini_get( 'opcache.restrict_api' ) ) === 0 ); |
| 2323 | } |
| 2324 | |
| 2325 | // If invalidation is not available, return early. |
| 2326 | if ( ! $can_invalidate ) { |
| 2327 | return false; |
| 2328 | } |
| 2329 | |
| 2330 | // Verify that file to be invalidated has a PHP extension. |
| 2331 | if ( ! preg_match( '/\.(?:php)$/i', $filepath ) ) { |
| 2332 | return false; |
| 2333 | } |
| 2334 | |
| 2335 | /** |
| 2336 | * Filters whether to invalidate a file from the opcode cache. |
| 2337 | * |
| 2338 | * @since 5.5 |
| 2339 | * |
| 2340 | * @param bool $will_invalidate Whether WordPress will invalidate `$filename`. Default `true`. |
| 2341 | * @param string $filename The PHP filename to invalidate. |
| 2342 | */ |
| 2343 | if ( apply_filters( 'wp_opcache_invalidate_file', true, $filepath ) ) { |
| 2344 | return opcache_invalidate( $filepath, $force ); |
| 2345 | } |
| 2346 | |
| 2347 | return false; |
| 2348 | } |