Make WordPress Core

Opened 7 years ago

Closed 6 years ago

Last modified 6 years ago

#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's profile burlingtonbytes Owned by: sergeybiryukov's profile 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)

#43374.patch (722 bytes) - added by teddytime 7 years ago.
This is a patch that resolves the warning
43374.2.diff (543 bytes) - added by lbenicio 7 years ago.
43374.patch (439 bytes) - added by desrosj 6 years ago.

Download all attachments as: .zip

Change History (14)

#1 @jrf
7 years ago

  • Focuses coding-standards removed
  • Resolution set to duplicate
  • Status changed from new to closed

Hi there and thanks for your report!

Please note that this is already being tracked in #42814.

Proposed solution: check if empty($wp_theme_directories) before performing count().

As a side-note, your proposed solution is definitely not the correct way to go about it as empty() will also return false 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.

#2 @burlingtonbytes
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 @jrf
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 @ocean90
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.

@teddytime
7 years ago

This is a patch that resolves the warning

@lbenicio
7 years ago

#5 @toddhalfpenny
7 years ago

  • Keywords has-patch added; needs-patch removed

#6 @SergeyBiryukov
7 years ago

  • Milestone changed from Future Release to 4.9.6

@desrosj
6 years ago

#7 @desrosj
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.

This ticket was mentioned in Slack in #core by desrosj. View the logs.


6 years ago

#9 @SergeyBiryukov
6 years ago

  • Owner set to SergeyBiryukov
  • Status changed from reopened to reviewing

#10 @SergeyBiryukov
6 years ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

In 43039:

Themes: Avoid a PHP 7.2 warning in get_theme_roots() when $wp_theme_directories is an uncountable value.

See [41174] for wp_get_themes() and get_raw_theme_root().

Props burlingtonbytes, teddytime, lbenicio, desrosj.
Fixes #43374. See #40109.

#11 @SergeyBiryukov
6 years ago

In 43040:

Themes: Avoid a PHP 7.2 warning in get_theme_roots() when $wp_theme_directories is an uncountable value.

See [41174] for wp_get_themes() and get_raw_theme_root().

Props burlingtonbytes, teddytime, lbenicio, desrosj.
Merges [43039] to the 4.9 branch.
Fixes #43374. See #40109.

Note: See TracTickets for help on using tickets.