Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 67 additions & 58 deletions src/wp-admin/includes/class-wp-debug-data.php
Original file line number Diff line number Diff line change
Expand Up @@ -472,74 +472,83 @@ private static function get_wp_server(): array {
);

// Opcode Cache.
if ( function_exists( 'opcache_get_status' ) ) {
$opcache_status = @opcache_get_status( false ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Warning emitted in failure case.

if ( false === $opcache_status ) {
$fields['opcode_cache'] = array(
'label' => __( 'Opcode cache' ),
'value' => __( 'Disabled by configuration' ),
'debug' => 'not available',
);
} else {
$fields['opcode_cache'] = array(
'label' => __( 'Opcode cache' ),
'value' => $opcache_status['opcache_enabled'] ? __( 'Enabled' ) : __( 'Disabled' ),
'debug' => $opcache_status['opcache_enabled'],
// Only query opcache_get_status() when the genuine Zend OPcache extension
// is loaded, so a userland opcache_get_status() polyfill cannot spoof the
// reported status.
$opcache_status = ( extension_loaded( 'Zend OPcache' ) && function_exists( 'opcache_get_status' ) )
? @opcache_get_status( false ) // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Warning emitted in failure case.
: false;

if ( is_array( $opcache_status ) ) {
$fields['opcode_cache'] = array(
'label' => __( 'Opcode cache' ),
'value' => $opcache_status['opcache_enabled'] ? __( 'Enabled' ) : __( 'Disabled' ),
'debug' => $opcache_status['opcache_enabled'],
);

if ( true === $opcache_status['opcache_enabled'] ) {
$fields['opcode_cache_memory_usage'] = array(
'label' => __( 'Opcode cache memory usage' ),
'value' => sprintf(
/* translators: 1: Used memory, 2: Total memory */
__( '%1$s of %2$s' ),
size_format( $opcache_status['memory_usage']['used_memory'] ),
size_format( $opcache_status['memory_usage']['free_memory'] + $opcache_status['memory_usage']['used_memory'] )
),
'debug' => sprintf(
'%s of %s',
$opcache_status['memory_usage']['used_memory'],
$opcache_status['memory_usage']['free_memory'] + $opcache_status['memory_usage']['used_memory']
),
);

if ( true === $opcache_status['opcache_enabled'] ) {
$fields['opcode_cache_memory_usage'] = array(
'label' => __( 'Opcode cache memory usage' ),
if ( 0 !== $opcache_status['interned_strings_usage']['buffer_size'] ) {
$fields['opcode_cache_interned_strings_usage'] = array(
'label' => __( 'Opcode cache interned strings usage' ),
'value' => sprintf(
/* translators: 1: Used memory, 2: Total memory */
__( '%1$s of %2$s' ),
size_format( $opcache_status['memory_usage']['used_memory'] ),
size_format( $opcache_status['memory_usage']['free_memory'] + $opcache_status['memory_usage']['used_memory'] )
/* translators: 1: Percentage used, 2: Total memory, 3: Free memory */
__( '%1$s%% of %2$s (%3$s free)' ),
number_format_i18n( ( $opcache_status['interned_strings_usage']['used_memory'] / $opcache_status['interned_strings_usage']['buffer_size'] ) * 100, 2 ),
size_format( $opcache_status['interned_strings_usage']['buffer_size'] ),
size_format( $opcache_status['interned_strings_usage']['free_memory'] )
),
'debug' => sprintf(
'%s of %s',
$opcache_status['memory_usage']['used_memory'],
$opcache_status['memory_usage']['free_memory'] + $opcache_status['memory_usage']['used_memory']
'%s%% of %s (%s free)',
round( ( $opcache_status['interned_strings_usage']['used_memory'] / $opcache_status['interned_strings_usage']['buffer_size'] ) * 100, 2 ),
$opcache_status['interned_strings_usage']['buffer_size'],
$opcache_status['interned_strings_usage']['free_memory']
),
);
}

if ( 0 !== $opcache_status['interned_strings_usage']['buffer_size'] ) {
$fields['opcode_cache_interned_strings_usage'] = array(
'label' => __( 'Opcode cache interned strings usage' ),
'value' => sprintf(
/* translators: 1: Percentage used, 2: Total memory, 3: Free memory */
__( '%1$s%% of %2$s (%3$s free)' ),
number_format_i18n( ( $opcache_status['interned_strings_usage']['used_memory'] / $opcache_status['interned_strings_usage']['buffer_size'] ) * 100, 2 ),
size_format( $opcache_status['interned_strings_usage']['buffer_size'] ),
size_format( $opcache_status['interned_strings_usage']['free_memory'] )
),
'debug' => sprintf(
'%s%% of %s (%s free)',
round( ( $opcache_status['interned_strings_usage']['used_memory'] / $opcache_status['interned_strings_usage']['buffer_size'] ) * 100, 2 ),
$opcache_status['interned_strings_usage']['buffer_size'],
$opcache_status['interned_strings_usage']['free_memory']
),
);
}

$fields['opcode_cache_hit_rate'] = array(
'label' => __( 'Opcode cache hit rate' ),
'value' => sprintf(
/* translators: %s: Hit rate percentage */
__( '%s%%' ),
number_format_i18n( $opcache_status['opcache_statistics']['opcache_hit_rate'], 2 )
),
'debug' => round( $opcache_status['opcache_statistics']['opcache_hit_rate'], 2 ),
);
$fields['opcode_cache_hit_rate'] = array(
'label' => __( 'Opcode cache hit rate' ),
'value' => sprintf(
/* translators: %s: Hit rate percentage */
__( '%s%%' ),
number_format_i18n( $opcache_status['opcache_statistics']['opcache_hit_rate'], 2 )
),
'debug' => round( $opcache_status['opcache_statistics']['opcache_hit_rate'], 2 ),
);

$fields['opcode_cache_full'] = array(
'label' => __( 'Is the Opcode cache full?' ),
'value' => $opcache_status['cache_full'] ? __( 'Yes' ) : __( 'No' ),
'debug' => $opcache_status['cache_full'],
);
}
$fields['opcode_cache_full'] = array(
'label' => __( 'Is the Opcode cache full?' ),
'value' => $opcache_status['cache_full'] ? __( 'Yes' ) : __( 'No' ),
'debug' => $opcache_status['cache_full'],
);
}
} elseif ( extension_loaded( 'Zend OPcache' ) && ini_get( 'opcache.enable' ) ) {
/*
* OPcache is enabled but opcache_get_status() returned no data, for
* example in file cache only mode (opcache.file_cache_only=1) or when the
* function is listed in disable_functions. Detailed statistics are
* unavailable in this case.
*/
$fields['opcode_cache'] = array(
'label' => __( 'Opcode cache' ),
'value' => __( 'Enabled' ),
'debug' => true,
);
} else {
$fields['opcode_cache'] = array(
'label' => __( 'Opcode cache' ),
Expand Down
19 changes: 15 additions & 4 deletions src/wp-admin/includes/class-wp-site-health.php
Original file line number Diff line number Diff line change
Expand Up @@ -2810,10 +2810,21 @@ public function get_test_search_engine_visibility() {
*/
public function get_test_opcode_cache(): array {
$opcode_cache_enabled = false;
if ( function_exists( 'opcache_get_status' ) ) {
$status = @opcache_get_status( false ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Warning emitted in failure case.
if ( $status && true === $status['opcache_enabled'] ) {
$opcode_cache_enabled = true;
if ( extension_loaded( 'Zend OPcache' ) && ini_get( 'opcache.enable' ) ) {
/*
* OPcache is enabled. When it operates in file cache only mode
* (opcache.file_cache_only=1), opcache_get_status() returns false
* even though opcode caching is active, so treat the extension being
* enabled as sufficient and only defer to opcache_get_status() when
* it returns usable data.
*/
$opcode_cache_enabled = true;

if ( function_exists( 'opcache_get_status' ) ) {
$status = @opcache_get_status( false ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Warning emitted in failure case.
if ( is_array( $status ) && isset( $status['opcache_enabled'] ) ) {
$opcode_cache_enabled = (bool) $status['opcache_enabled'];
}
}
}

Expand Down
17 changes: 12 additions & 5 deletions tests/phpunit/tests/admin/wpSiteHealth.php
Original file line number Diff line number Diff line change
Expand Up @@ -681,20 +681,27 @@ public function test_get_test_opcode_cache_return_structure() {
/**
* Tests get_test_opcode_cache() result when opcode cache is enabled or not.
*
* Covers: opcache enabled, disabled, not available, and opcache_get_status() returns false.
* Covers: opcache enabled, disabled, not available, file cache only mode
* (where opcache_get_status() returns false), and opcache_get_status()
* being unavailable via disable_functions.
*
* @ticket 63697
* @ticket 64707
*
* @covers ::get_test_opcode_cache()
*/
public function test_get_test_opcode_cache_result_by_environment() {
$result = $this->instance->get_test_opcode_cache();

$opcache_enabled = false;
if ( function_exists( 'opcache_get_status' ) ) {
$status = @opcache_get_status( false ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Warning emitted in failure case.
if ( $status && true === $status['opcache_enabled'] ) {
$opcache_enabled = true;
if ( extension_loaded( 'Zend OPcache' ) && ini_get( 'opcache.enable' ) ) {
$opcache_enabled = true;

if ( function_exists( 'opcache_get_status' ) ) {
$status = @opcache_get_status( false ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Warning emitted in failure case.
if ( is_array( $status ) && isset( $status['opcache_enabled'] ) ) {
$opcache_enabled = (bool) $status['opcache_enabled'];
}
}
}

Expand Down
Loading