#43374 closed defect (bug) (fixed)
PHP 7.2 Warning: count(): Parameter must be an array or an object that implements Countable in /wp-includes/theme.php on line 356
Reported by: | burlingtonbytes | Owned by: | SergeyBiryukov |
---|---|---|---|
Milestone: | 4.9.6 | Priority: | normal |
Severity: | minor | Version: | |
Component: | Themes | Keywords: | good-first-bug has-patch |
Focuses: | Cc: |
Description
After upgrading to PHP 7.2 from 7.0 we observed PHP warnings on every pageload. It looks like get_theme_roots()
runs count()
on global $wp_theme_directories
without checking the value first.
Proposed solution: check if empty($wp_theme_directories)
before performing count()
.
patched version of get_theme_roots (wp-includes/theme.php line 356 in WP 4.9.4)
function get_theme_roots() { global $wp_theme_directories; if ( empty($wp_theme_directories) || count($wp_theme_directories) <= 1 ) return '/themes'; $theme_roots = get_site_transient( 'theme_roots' ); if ( false === $theme_roots ) { search_theme_directories( true ); // Regenerate the transient. $theme_roots = get_site_transient( 'theme_roots' ); } return $theme_roots; }
We haven't observed this in a clean WordPress install, so we aren't sure why $wp_theme_directories
would be empty, but this patch resolves the PHP warning while maintaining the existing, expected PHP <7.2 behavior.
Attachments (3)
Change History (14)
#1
@
7 years ago
- Focuses coding-standards removed
- Resolution set to duplicate
- Status changed from new to closed
#2
@
7 years ago
- Severity changed from normal to minor
Hi @jrf,
Thank you for your insight on the proposed solution.
If $wp_theme_directories
should always be an array, then this conditional addresses the issue more comprehensively:
if ( empty($wp_theme_directories) || ( is_array($wp_theme_directories) && count($wp_theme_directories) <= 1 ) ) {
This way, we still return the default '/themes' if $wp_theme_directories
is null, zero, or other invalid empty()
value, OR is a valid array with 1 or fewer items. count()
is only executed if is_array()
passes.
I looked into #42814 before submitting this, but believe this to be a distinct issue because that ticket does not cover this specific use of count()
in get_theme_roots()
. The warning is effectively the same but in this case it is being generated in wp-includes/theme.php which is not referenced at all in #42814.
I may be missing something but I do not believe #42814 addresses this.
#3
@
7 years ago
If $wp_theme_directories should always be an array, then this conditional addresses the issue more comprehensively:
if ( empty($wp_theme_directories) || ( is_array($wp_theme_directories) && count($wp_theme_directories) <= 1 ) ) {
Yes, however, now you're using a superfluous condition as the empty()
is not needed is you first do an is_array()
. Rewriting to the below would be simpler: (presuming $wp_theme_directories
is always defined, otherwise an isset()
would still be needed)
if ( ! is_array( $wp_theme_directories ) || count( $wp_theme_directories ) <= 1 ) ) {
I may be missing something but I do not believe #42814 addresses this.
AFAIK ticket #42814 is intended as the master ticket for these type of warnings, so I would suggest continuing the discussion there.
#4
@
7 years ago
- Keywords needs-patch good-first-bug added
- Milestone changed from Awaiting Review to Future Release
- Resolution duplicate deleted
- Status changed from closed to reopened
- Version 4.9.4 deleted
A check for is_array()
makes sense here. This would be consistent with wp_get_themes()
for example.
#42814 is not a master ticket.
#7
@
6 years ago
#43583 will introduce an is_countable()
polyfill for the PHP 7.3 function with the same name. I think it makes sense to start using that function here to fix this warning.
43374.patch utilizes the is_countable()
function to avoid the PHP warning. Of course, this depends on the patch in #43583 being committed first.
Hi there and thanks for your report!
Please note that this is already being tracked in #42814.
As a side-note, your proposed solution is definitely not the correct way to go about it as
empty()
will also returnfalse
on a non-empty string, a non-0 integer etc. and all of those would still cause the same warning to be thrown in PHP 7.2.