WordPress.org

Make WordPress Core

Opened 5 years ago

Closed 13 months ago

Last modified 13 months ago

#13436 closed enhancement (wontfix)

WordPress class_exists() conflicts with __autoload() and php_auto_prepend

Reported by: galbus Owned by:
Milestone: Priority: normal
Severity: minor Version: 3.0
Component: Bootstrap/Load Keywords: needs-patch
Focuses: Cc:

Description (last modified by SergeyBiryukov)

Issue

WordPress core (and many plugins) use class_exists().

http://php.net/manual/en/function.class-exists.php

When WordPress is integrated with custom/third party applications that use php_auto_prepend and autoload() to include/require files based on the $class_name parameter this generates errors as class_exists() triggers the autoload() and the files cannot be found.

To reproduce

Using php_auto_prepend specify a file to include before every page request that contains the following PHP code:

<?php
function __autoload($class) {
    include($class.'.php');
}
?>

Visit any front-end or back-end WordPress page.

Solution

As there is no autoload() function defined in WordPress core the class_exists() should implement the second class_exists() parameter:

<?php
if (!class_exists('ExampleClass', false)) {
    ...
}
?>

This stops calls to __autoload() and would fix the errors seen when integrating WordPress with apps that implement this.

I have implemented this and tested it and WordPress works fine, but I can't find out where the SVN repo is for WordPress 3 Beta 2 (the SVN page on the site takes me to 2.x).

If someone could supply a link for SVN CO of WP3 I can provide the patch.

Change History (26)

comment:1 @Denis-de-Bernardy5 years ago

the 2nd parameter for class_exists() is php5. could you run tests using function_exists() instead, in the event that one behaves better?

http://svn.automattic.com/wordpress/trunk

comment:2 @galbus5 years ago

Good point. I didn't realise from the docs that the second param was PHP5 only. I'll code for PHP4 - thanks for the SVN repo.

comment:3 @dd325 years ago

  • Milestone Unassigned deleted
  • Resolution set to invalid
  • Status changed from new to closed

For reference, the SVN repository is available at http://core.svn.wordpress.org/trunk/

Closing as invalid, as this is not something that WordPress can do.

If an application wants to allow 3rd-party code to run, and uses __autoload(), it needs to handle 3rd-party classes. In this case, It'd involve checking either the class is a known class, or that the file exists before including it.

comment:4 @tychay5 years ago

  • Resolution invalid deleted
  • Status changed from closed to reopened
  • Version changed from 3.0 to 3.1

Now that WordPress 3.2 will be dropping PHP 4 support, it's time we added this patch back in for 3.2.

Here is the patchfile to be applied…

diff -crB b.orig/wp-admin/includes/class-wp-list-table.php b/wp-admin/includes/class-wp-list-table.php
*** b.orig/wp-admin/includes/class-wp-list-table.php	2010-10-25 08:39:30.000000000 +0000
--- b/wp-admin/includes/class-wp-list-table.php	2010-10-25 08:34:40.000000000 +0000
***************
*** 831,837 ****
  
  	require_list_table( $class );
  
! 	if ( class_exists( $class ) )
  		return new $class;
  	return false;
  }
--- 831,837 ----
  
  	require_list_table( $class );
  
! 	if ( class_exists( $class, false ) )
  		return new $class;
  	return false;
  }
***************
*** 860,863 ****
  	return false;
  }
  
! ?>
\ No newline at end of file
--- 860,863 ----
  	return false;
  }
  
! ?>
diff -crB b.orig/wp-admin/includes/deprecated.php b/wp-admin/includes/deprecated.php
*** b.orig/wp-admin/includes/deprecated.php	2010-10-25 08:39:30.000000000 +0000
--- b/wp-admin/includes/deprecated.php	2010-10-25 08:32:49.000000000 +0000
***************
*** 288,294 ****
  	return $wpdb->get_col( $wpdb->prepare("SELECT user_id FROM $wpdb->usermeta WHERE meta_key = %s AND meta_value = '0'", $level_key) );
  }
  
! if ( !class_exists('WP_User_Search') ) :
  /**
   * WordPress User Search class.
   *
--- 288,294 ----
  	return $wpdb->get_col( $wpdb->prepare("SELECT user_id FROM $wpdb->usermeta WHERE meta_key = %s AND meta_value = '0'", $level_key) );
  }
  
! if ( !class_exists('WP_User_Search',false) ) :
  /**
   * WordPress User Search class.
   *
diff -crB b.orig/wp-admin/includes/file.php b/wp-admin/includes/file.php
*** b.orig/wp-admin/includes/file.php	2010-10-25 08:39:30.000000000 +0000
--- b/wp-admin/includes/file.php	2010-10-25 08:31:58.000000000 +0000
***************
*** 552,558 ****
  		}
  	}
  
! 	if ( class_exists('ZipArchive') && apply_filters('unzip_file_use_ziparchive', true ) ) {
  		$result = _unzip_file_ziparchive($file, $to, $needed_dirs);
  		if ( true === $result ) {
  			return $result;
--- 552,558 ----
  		}
  	}
  
! 	if ( class_exists('ZipArchive',false) && apply_filters('unzip_file_use_ziparchive', true ) ) {
  		$result = _unzip_file_ziparchive($file, $to, $needed_dirs);
  		if ( true === $result ) {
  			return $result;
***************
*** 781,787 ****
  	if ( ! $method )
  		return false;
  
! 	if ( ! class_exists("WP_Filesystem_$method") ) {
  		$abstraction_file = apply_filters('filesystem_method_file', ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php', $method);
  		if ( ! file_exists($abstraction_file) )
  			return;
--- 781,787 ----
  	if ( ! $method )
  		return false;
  
! 	if ( ! class_exists("WP_Filesystem_$method",false) ) {
  		$abstraction_file = apply_filters('filesystem_method_file', ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php', $method);
  		if ( ! file_exists($abstraction_file) )
  			return;
diff -crB b.orig/wp-admin/includes/misc.php b/wp-admin/includes/misc.php
*** b.orig/wp-admin/includes/misc.php	2010-10-25 08:39:30.000000000 +0000
--- b/wp-admin/includes/misc.php	2010-10-25 08:29:20.000000000 +0000
***************
*** 397,403 ****
  		 * Lastly we make sure that PHP is running via FastCGI. This is important because if it runs
  		 * via ISAPI then pretty permalinks will not work.
  		 */
! 		$supports_permalinks = class_exists('DOMDocument') && isset($_SERVER['IIS_UrlRewriteModule']) && ( php_sapi_name() == 'cgi-fcgi' );
  	}
  
  	return apply_filters('iis7_supports_permalinks', $supports_permalinks);
--- 397,403 ----
  		 * Lastly we make sure that PHP is running via FastCGI. This is important because if it runs
  		 * via ISAPI then pretty permalinks will not work.
  		 */
! 		$supports_permalinks = class_exists('DOMDocument', false) && isset($_SERVER['IIS_UrlRewriteModule']) && ( php_sapi_name() == 'cgi-fcgi' );
  	}
  
  	return apply_filters('iis7_supports_permalinks', $supports_permalinks);
***************
*** 414,420 ****
  function iis7_rewrite_rule_exists($filename) {
  	if ( ! file_exists($filename) )
  		return false;
! 	if ( ! class_exists('DOMDocument') )
  		return false;
  
  	$doc = new DOMDocument();
--- 414,420 ----
  function iis7_rewrite_rule_exists($filename) {
  	if ( ! file_exists($filename) )
  		return false;
! 	if ( ! class_exists('DOMDocument', false) )
  		return false;
  
  	$doc = new DOMDocument();
***************
*** 441,447 ****
  	if ( ! file_exists($filename) )
  		return true;
  
! 	if ( ! class_exists('DOMDocument') )
  		return false;
  
  	$doc = new DOMDocument();
--- 441,447 ----
  	if ( ! file_exists($filename) )
  		return true;
  
! 	if ( ! class_exists('DOMDocument', false) )
  		return false;
  
  	$doc = new DOMDocument();
***************
*** 471,477 ****
   * @return bool
   */
  function iis7_add_rewrite_rule($filename, $rewrite_rule) {
! 	if ( ! class_exists('DOMDocument') )
  		return false;
  
  	// If configuration file does not exist then we create one.
--- 471,477 ----
   * @return bool
   */
  function iis7_add_rewrite_rule($filename, $rewrite_rule) {
! 	if ( ! class_exists('DOMDocument',false) )
  		return false;
  
  	// If configuration file does not exist then we create one.
diff -crB b.orig/wp-admin/includes/nav-menu.php b/wp-admin/includes/nav-menu.php
*** b.orig/wp-admin/includes/nav-menu.php	2010-10-25 08:39:30.000000000 +0000
--- b/wp-admin/includes/nav-menu.php	2010-10-25 08:32:22.000000000 +0000
***************
*** 1068,1074 ****
  
  		$walker_class_name = apply_filters( 'wp_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $menu_id );
  
! 		if ( class_exists( $walker_class_name ) )
  			$walker = new $walker_class_name;
  		else
  			return new WP_Error( 'menu_walker_not_exist', sprintf( __('The Walker class named <strong>%s</strong> does not exist.'), $walker_class_name ) );
--- 1068,1074 ----
  
  		$walker_class_name = apply_filters( 'wp_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $menu_id );
  
! 		if ( class_exists( $walker_class_name, false ) )
  			$walker = new $walker_class_name;
  		else
  			return new WP_Error( 'menu_walker_not_exist', sprintf( __('The Walker class named <strong>%s</strong> does not exist.'), $walker_class_name ) );
diff -crB b.orig/wp-content/plugins/akismet/akismet.php b/wp-content/plugins/akismet/akismet.php
*** b.orig/wp-content/plugins/akismet/akismet.php	2010-10-25 08:39:46.000000000 +0000
--- b/wp-content/plugins/akismet/akismet.php	2010-10-25 08:33:11.000000000 +0000
***************
*** 420,426 ****
  function akismet_get_user_roles($user_id ) {
  	$roles = false;
  	
! 	if ( !class_exists('WP_User') )
  		return false;
  	
  	if ( $user_id > 0 ) {
--- 420,426 ----
  function akismet_get_user_roles($user_id ) {
  	$roles = false;
  	
! 	if ( !class_exists('WP_User', false) )
  		return false;
  	
  	if ( $user_id > 0 ) {
diff -crB b.orig/wp-includes/class-feed.php b/wp-includes/class-feed.php
*** b.orig/wp-includes/class-feed.php	2010-10-25 08:38:21.000000000 +0000
--- b/wp-includes/class-feed.php	2010-10-25 08:24:11.000000000 +0000
***************
*** 1,6 ****
  <?php
  
! if ( !class_exists('SimplePie') )
  	require_once (ABSPATH . WPINC . '/class-simplepie.php');
  
  class WP_Feed_Cache extends SimplePie_Cache {
--- 1,6 ----
  <?php
  
! if ( !class_exists('SimplePie',false) )
  	require_once (ABSPATH . WPINC . '/class-simplepie.php');
  
  class WP_Feed_Cache extends SimplePie_Cache {
***************
*** 100,103 ****
  			}
  		}
  	}
! }
\ No newline at end of file
--- 100,103 ----
  			}
  		}
  	}
! }
diff -crB b.orig/wp-includes/class-json.php b/wp-includes/class-json.php
*** b.orig/wp-includes/class-json.php	2010-10-25 08:38:44.000000000 +0000
--- b/wp-includes/class-json.php	2010-10-25 08:31:07.000000000 +0000
***************
*** 1,5 ****
  <?php
! if ( !class_exists( 'Services_JSON' ) ) :
  /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  /**
   * Converts to and from JSON format.
--- 1,5 ----
  <?php
! if ( !class_exists( 'Services_JSON', false ) ) :
  /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  /**
   * Converts to and from JSON format.
***************
*** 822,828 ****
  	*/
  	function isError($data, $code = null)
  	{
! 		if (class_exists('pear')) {
  			return PEAR::isError($data, $code);
  		} elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
  								is_subclass_of($data, 'services_json_error'))) {
--- 822,828 ----
  	*/
  	function isError($data, $code = null)
  	{
! 		if (class_exists('pear', false)) {
  			return PEAR::isError($data, $code);
  		} elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
  								is_subclass_of($data, 'services_json_error'))) {
***************
*** 833,839 ****
  	}
  }
  
! if (class_exists('PEAR_Error')) {
  
  	class Services_JSON_Error extends PEAR_Error
  	{
--- 833,839 ----
  	}
  }
  
! if (class_exists('PEAR_Error',false)) {
  
  	class Services_JSON_Error extends PEAR_Error
  	{
diff -crB b.orig/wp-includes/class-simplepie.php b/wp-includes/class-simplepie.php
*** b.orig/wp-includes/class-simplepie.php	2010-10-25 08:38:44.000000000 +0000
--- b/wp-includes/class-simplepie.php	2010-10-25 08:30:40.000000000 +0000
***************
*** 6447,6453 ****
  		$this->title = $title;
  		$this->type = $type;
  		$this->width = $width;
! 		if (class_exists('idna_convert'))
  		{
  			$idn =& new idna_convert;
  			$parsed = SimplePie_Misc::parse_url($link);
--- 6447,6453 ----
  		$this->title = $title;
  		$this->type = $type;
  		$this->width = $width;
! 		if (class_exists('idna_convert', false))
  		{
  			$idn =& new idna_convert;
  			$parsed = SimplePie_Misc::parse_url($link);
***************
*** 7645,7651 ****
  
  	function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
  	{
! 		if (class_exists('idna_convert'))
  		{
  			$idn =& new idna_convert;
  			$parsed = SimplePie_Misc::parse_url($url);
--- 7645,7651 ----
  
  	function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
  	{
! 		if (class_exists('idna_convert', false))
  		{
  			$idn =& new idna_convert;
  			$parsed = SimplePie_Misc::parse_url($url);
***************
*** 10797,10805 ****
  		}
  		elseif (is_string($class1) && is_string($class2))
  		{
! 			if (class_exists($class1))
  			{
! 				if (class_exists($class2))
  				{
  					$class2 = strtolower($class2);
  					while ($class1 = strtolower(get_parent_class($class1)))
--- 10797,10805 ----
  		}
  		elseif (is_string($class1) && is_string($class2))
  		{
! 			if (class_exists($class1, false))
  			{
! 				if (class_exists($class2, false))
  				{
  					$class2 = strtolower($class2);
  					while ($class1 = strtolower(get_parent_class($class1)))
diff -crB b.orig/wp-includes/class-snoopy.php b/wp-includes/class-snoopy.php
*** b.orig/wp-includes/class-snoopy.php	2010-10-25 08:38:44.000000000 +0000
--- b/wp-includes/class-snoopy.php	2010-10-25 08:25:25.000000000 +0000
***************
*** 5,11 ****
   */
  _deprecated_file( basename( __FILE__ ), '3.0', WPINC . '/http.php' );
  
! if ( !class_exists( 'Snoopy' ) ) :
  /*************************************************
  
  Snoopy - the PHP net client
--- 5,11 ----
   */
  _deprecated_file( basename( __FILE__ ), '3.0', WPINC . '/http.php' );
  
! if ( !class_exists( 'Snoopy', false ) ) :
  /*************************************************
  
  Snoopy - the PHP net client
diff -crB b.orig/wp-includes/formatting.php b/wp-includes/formatting.php
*** b.orig/wp-includes/formatting.php	2010-10-25 08:38:44.000000000 +0000
--- b/wp-includes/formatting.php	2010-10-25 08:28:26.000000000 +0000
***************
*** 1578,1584 ****
  function get_gmt_from_date($string, $format = 'Y-m-d H:i:s') {
  	preg_match('#([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $string, $matches);
  	$tz = get_option('timezone_string');
! 	if( class_exists('DateTime') && $tz ) {
  		//PHP5
  		date_default_timezone_set( $tz );
  		$datetime = new DateTime( $string );
--- 1578,1584 ----
  function get_gmt_from_date($string, $format = 'Y-m-d H:i:s') {
  	preg_match('#([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $string, $matches);
  	$tz = get_option('timezone_string');
! 	if( class_exists('DateTime', false) && $tz ) {
  		//PHP5
  		date_default_timezone_set( $tz );
  		$datetime = new DateTime( $string );
diff -crB b.orig/wp-includes/pluggable.php b/wp-includes/pluggable.php
*** b.orig/wp-includes/pluggable.php	2010-10-25 08:38:44.000000000 +0000
--- b/wp-includes/pluggable.php	2010-10-25 08:34:34.000000000 +0000
***************
*** 6,12 ****
   * @package WordPress
   */
  
! if ( !function_exists('wp_set_current_user') ) :
  /**
   * Changes the current user by ID or name.
   *
--- 6,12 ----
   * @package WordPress
   */
  
! if ( !function_exists( 'wp_set_current_user' ) ) :
  /**
   * Changes the current user by ID or name.
   *
***************
*** 1713,1719 ****
  	$defaults = array( 'title' => '', 'title_left' => '', 'title_right' => '' );
  	$args = wp_parse_args( $args, $defaults );
  
! 	if ( !class_exists( 'WP_Text_Diff_Renderer_Table' ) )
  		require( ABSPATH . WPINC . '/wp-diff.php' );
  
  	$left_string  = normalize_whitespace($left_string);
--- 1713,1719 ----
  	$defaults = array( 'title' => '', 'title_left' => '', 'title_right' => '' );
  	$args = wp_parse_args( $args, $defaults );
  
! 	if ( !class_exists( 'WP_Text_Diff_Renderer_Table', false ) )
  		require( ABSPATH . WPINC . '/wp-diff.php' );
  
  	$left_string  = normalize_whitespace($left_string);
diff -crB b.orig/wp-includes/pomo/entry.php b/wp-includes/pomo/entry.php
*** b.orig/wp-includes/pomo/entry.php	2010-10-25 08:39:02.000000000 +0000
--- b/wp-includes/pomo/entry.php	2010-10-25 08:27:13.000000000 +0000
***************
*** 7,13 ****
   * @subpackage entry
   */
  
! if ( !class_exists( 'Translation_Entry' ) ):
  /**
   * Translation_Entry class encapsulates a translatable string
   */
--- 7,13 ----
   * @subpackage entry
   */
  
! if ( !class_exists( 'Translation_Entry', false ) ):
  /**
   * Translation_Entry class encapsulates a translatable string
   */
***************
*** 66,69 ****
  		return is_null($this->context)? $this->singular : $this->context.chr(4).$this->singular;
  	}
  }
! endif;
\ No newline at end of file
--- 66,69 ----
  		return is_null($this->context)? $this->singular : $this->context.chr(4).$this->singular;
  	}
  }
! endif;
diff -crB b.orig/wp-includes/pomo/mo.php b/wp-includes/pomo/mo.php
*** b.orig/wp-includes/pomo/mo.php	2010-10-25 08:39:02.000000000 +0000
--- b/wp-includes/pomo/mo.php	2010-10-25 08:27:48.000000000 +0000
***************
*** 10,16 ****
  require_once dirname(__FILE__) . '/translations.php';
  require_once dirname(__FILE__) . '/streams.php';
  
! if ( !class_exists( 'MO' ) ):
  class MO extends Gettext_Translations {
  
  	var $_nplurals = 2;
--- 10,16 ----
  require_once dirname(__FILE__) . '/translations.php';
  require_once dirname(__FILE__) . '/streams.php';
  
! if ( !class_exists( 'MO', false ) ):
  class MO extends Gettext_Translations {
  
  	var $_nplurals = 2;
***************
*** 228,231 ****
  		return $this->_nplurals;
  	}
  }
! endif;
\ No newline at end of file
--- 228,231 ----
  		return $this->_nplurals;
  	}
  }
! endif;
diff -crB b.orig/wp-includes/pomo/po.php b/wp-includes/pomo/po.php
*** b.orig/wp-includes/pomo/po.php	2010-10-25 08:39:02.000000000 +0000
--- b/wp-includes/pomo/po.php	2010-10-25 08:26:58.000000000 +0000
***************
*** 16,22 ****
  /**
   * Routines for working with PO files
   */
! if ( !class_exists( 'PO' ) ):
  class PO extends Gettext_Translations {
  
  
--- 16,22 ----
  /**
   * Routines for working with PO files
   */
! if ( !class_exists( 'PO', false ) ):
  class PO extends Gettext_Translations {
  
  
diff -crB b.orig/wp-includes/pomo/streams.php b/wp-includes/pomo/streams.php
*** b.orig/wp-includes/pomo/streams.php	2010-10-25 08:39:02.000000000 +0000
--- b/wp-includes/pomo/streams.php	2010-10-25 08:30:06.000000000 +0000
***************
*** 8,14 ****
   * @subpackage streams
   */
  
! if ( !class_exists( 'POMO_Reader' ) ):
  class POMO_Reader {
  
  	var $endian = 'little';
--- 8,14 ----
   * @subpackage streams
   */
  
! if ( !class_exists( 'POMO_Reader', false ) ):
  class POMO_Reader {
  
  	var $endian = 'little';
***************
*** 102,108 ****
  }
  endif;
  
! if ( !class_exists( 'POMO_FileReader' ) ):
  class POMO_FileReader extends POMO_Reader {
  	function POMO_FileReader($filename) {
  		parent::POMO_Reader();
--- 102,108 ----
  }
  endif;
  
! if ( !class_exists( 'POMO_FileReader', false ) ):
  class POMO_FileReader extends POMO_Reader {
  	function POMO_FileReader($filename) {
  		parent::POMO_Reader();
***************
*** 142,148 ****
  }
  endif;
  
! if ( !class_exists( 'POMO_StringReader' ) ):
  /**
   * Provides file-like methods for manipulating a string instead
   * of a physical file.
--- 142,148 ----
  }
  endif;
  
! if ( !class_exists( 'POMO_StringReader', false ) ):
  /**
   * Provides file-like methods for manipulating a string instead
   * of a physical file.
***************
*** 182,188 ****
  }
  endif;
  
! if ( !class_exists( 'POMO_CachedFileReader' ) ):
  /**
   * Reads the contents of the file in the beginning.
   */
--- 182,188 ----
  }
  endif;
  
! if ( !class_exists( 'POMO_CachedFileReader', false ) ):
  /**
   * Reads the contents of the file in the beginning.
   */
***************
*** 197,203 ****
  }
  endif;
  
! if ( !class_exists( 'POMO_CachedIntFileReader' ) ):
  /**
   * Reads the contents of the file in the beginning.
   */
--- 197,203 ----
  }
  endif;
  
! if ( !class_exists( 'POMO_CachedIntFileReader', false ) ):
  /**
   * Reads the contents of the file in the beginning.
   */
***************
*** 206,209 ****
  		parent::POMO_CachedFileReader($filename);
  	}
  }
! endif;
\ No newline at end of file
--- 206,209 ----
  		parent::POMO_CachedFileReader($filename);
  	}
  }
! endif;
diff -crB b.orig/wp-includes/pomo/translations.php b/wp-includes/pomo/translations.php
*** b.orig/wp-includes/pomo/translations.php	2010-10-25 08:39:02.000000000 +0000
--- b/wp-includes/pomo/translations.php	2010-10-25 08:33:55.000000000 +0000
***************
*** 9,15 ****
  
  require_once dirname(__FILE__) . '/entry.php';
  
! if ( !class_exists( 'Translations' ) ):
  class Translations {
  	var $entries = array();
  	var $headers = array();
--- 9,15 ----
  
  require_once dirname(__FILE__) . '/entry.php';
  
! if ( !class_exists( 'Translations', false ) ):
  class Translations {
  	var $entries = array();
  	var $headers = array();
***************
*** 205,211 ****
  }
  endif;
  
! if ( !class_exists( 'NOOP_Translations' ) ):
  /**
   * Provides the same interface as Translations, but doesn't do anything
   */
--- 205,211 ----
  }
  endif;
  
! if ( !class_exists( 'NOOP_Translations', false ) ):
  /**
   * Provides the same interface as Translations, but doesn't do anything
   */
diff -crB b.orig/wp-includes/wp-db.php b/wp-includes/wp-db.php
*** b.orig/wp-includes/wp-db.php	2010-10-25 08:38:44.000000000 +0000
--- b/wp-includes/wp-db.php	2010-10-25 08:25:47.000000000 +0000
***************
*** 1466,1472 ****
  	 */
  	function bail( $message, $error_code = '500' ) {
  		if ( !$this->show_errors ) {
! 			if ( class_exists( 'WP_Error' ) )
  				$this->error = new WP_Error($error_code, $message);
  			else
  				$this->error = $message;
--- 1466,1472 ----
  	 */
  	function bail( $message, $error_code = '500' ) {
  		if ( !$this->show_errors ) {
! 			if ( class_exists( 'WP_Error', false ) )
  				$this->error = new WP_Error($error_code, $message);
  			else
  				$this->error = $message;
diff -crB b.orig/wp-includes/wp-diff.php b/wp-includes/wp-diff.php
*** b.orig/wp-includes/wp-diff.php	2010-10-25 08:38:44.000000000 +0000
--- b/wp-includes/wp-diff.php	2010-10-25 08:24:59.000000000 +0000
***************
*** 8,14 ****
   * @subpackage Diff
   */
  
! if ( !class_exists( 'Text_Diff' ) ) {
  	/** Text_Diff class */
  	require( dirname(__FILE__).'/Text/Diff.php' );
  	/** Text_Diff_Renderer class */
--- 8,14 ----
   * @subpackage Diff
   */
  
! if ( !class_exists( 'Text_Diff', false ) ) {
  	/** Text_Diff class */
  	require( dirname(__FILE__).'/Text/Diff.php' );
  	/** Text_Diff_Renderer class */

Last edited 3 years ago by ocean90 (previous) (diff)

comment:5 @nacin5 years ago

  • Keywords needs-patch added; autoload class_exists php_auto_prepend removed
  • Milestone set to Future Release

You're welcome to submit an svn diff (not diff or diff -u) via: http://core.trac.wordpress.org/#HowtoSubmitPatches

comment:6 @azizur5 years ago

  • Cc azizur added

If anything related to IIS7 rewrite is applied recently on Trunk its causing issue.

Fatal error: Call to undefined function iis7_supports_permalinks() in D:\site.org.uk\wwwroot\wp-includes\canonical.php on line 40

Looks like \wp-includes\misc.php is not loaded before \wp-includes\canonical.php.

comment:7 @azizur5 years ago

  • Cc azizur removed
  • Type changed from enhancement to defect (bug)

comment:8 @azizur5 years ago

  • Cc azizur added

comment:9 follow-up: @nacin5 years ago

  • Type changed from defect (bug) to enhancement

azizur: There aren't any changes to trunk from this ticket, so this is definitely unrelated. Please open a new ticket.

comment:10 in reply to: ↑ 9 @azizur5 years ago

Replying to nacin:

azizur: ... Please open a new ticket.

New ticket created #15817 with more details.

comment:11 follow-up: @rmccue19 months ago

  • Milestone Future Release deleted
  • Resolution set to wontfix
  • Status changed from reopened to closed

Autoloaders should be using file_exists.

comment:12 in reply to: ↑ 11 ; follow-up: @Denis-de-Bernardy19 months ago

  • Resolution wontfix deleted
  • Status changed from closed to reopened

Replying to rmccue:

Autoloaders should be using file_exists.

And WordPress should be calling class_exists( $class, false ).

It's not as if this change would have the slightest impact on Core…

Last edited 19 months ago by Denis-de-Bernardy (previous) (diff)

comment:13 @SergeyBiryukov19 months ago

  • Description modified (diff)
  • Milestone set to Awaiting Review
  • Summary changed from Wordpress class_exists() conflicts with __autoload() and php_auto_prepend to WordPress class_exists() conflicts with __autoload() and php_auto_prepend
  • Version changed from 3.1 to 3.0

comment:14 in reply to: ↑ 12 @rmccue19 months ago

  • Keywords close added

Replying to Denis-de-Bernardy:

And WordPress should be calling class_exists( $class, false ).

It's not as if this change would have the slightest impact on Core…

I disagree, it's unneeded code churn. This ticket has been sitting around unchanged for 3 years with no actual patch; if it was going to be fixed, had no actual impact and actually affected people in the real world, it would have been fixed by now.

Using class_exists around a class definition might be better with $autoload set to false, but the other cases shouldn't be changed.

comment:15 @Denis-de-Bernardy19 months ago

As much as I agree it's a trivial fix that should have get checked in a long time ago, my issue with the idea of not fixing it for that reason is that WordPress ends up being, as always, the dirty little black sheep in the php community: one doesn't code with WP as much as one codes around it and its quirks (global variables, GPC escaping, awkward for autoloading, etc.).

It would be very sweet if, at some point, WordPress could get loaded like any other Symfony or Zend or Drupal or whatever bundle, module, component, you name it. Much progress has arguably been made in recent years to allow this, but surely -- seeing that you use composer and Symfony yourself, if I recollect your github account correctly -- you're aware that we're only a few notches beyond the stage where you load Wordapress and pray things won't blow up in your face.

comment:16 @nacin18 months ago

  • Component changed from General to Bootstrap/Load

comment:17 @SergeyBiryukov13 months ago

#28613 was marked as a duplicate.

comment:18 @jcjcc13 months ago

  • Keywords close removed

OK, fine. Sorry for the duplicate ticket, this ticket seemed dead.

To add to why this seems not to have been committed despite a patch being given by tychay, one of the developers commented

Autoloaders should be using file_exists.

I am not writing my own autoloader, I am calling spl_autoload_extensions(".class.php") and then spl_autoload_register() which registers the default autoloader. This loads a namespaced class "\core\blah" by looking in for "blah.class.php" in the folder "core".

But that's besides the point -- class_exists is documented to *throw an error* if the class cannot be loaded (it has nothing to do with file_exists...) and the second parameter is true (which is default). Thus, the code as it is right now is incorrect.

It just so happens that usually no autoloader is registered (or if plugins use autoloaders, their code is run after the erroneous core code), so nobody notices. I don't understand rmccue's "code churn" argument.

comment:19 @SergeyBiryukov13 months ago

  • Milestone changed from Awaiting Review to 4.0

comment:20 @Denis-de-Bernardy13 months ago

  • Keywords close added

Then again, your approach doesn't really play well with PSR-4, or does it?

https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md

Autoloader implementations MUST NOT throw exceptions, MUST NOT raise errors of any level, and SHOULD NOT return a value.

@rmccue's point was, in retrospect, that WP plays well with this already. So as much as it pained me when he closed it because this bit me a few times in the past as well, he was correct that this ticket ought to be closed as wontfix: any autoloader written in the age of PSR-4 should comply with it.

comment:21 follow-up: @jcjcc13 months ago

I didn't write my own autoloader -- this is the PHP default autoloader!

comment:22 in reply to: ↑ 21 @rmccue13 months ago

Replying to jcjcc:

I didn't write my own autoloader -- this is the PHP default autoloader!

I'm personally still OK with leaving this issue as is. PSR-4 explicitly notes "Autoloader implementations MUST NOT throw exceptions, MUST NOT raise errors of any level, and SHOULD NOT return a value" as noted by Denis. It's certainly OK for SPL to throw exceptions, but it's not PSR-4 compliant, and I don't think we need to support anything non-compliant with that (even in SPL).

That said, I cannot reproduce this error with the following:

spl_autoload_extensions('.php');
spl_autoload_register('spl_autoload');

var_dump(class_exists('Testing'));
var_dump(class_exists('\\Testing\\Foo'));

(PHP 5.4.9)

But that's besides the point -- class_exists is documented to *throw an error* if the class cannot be loaded (it has nothing to do with file_exists...) and the second parameter is true (which is default). Thus, the code as it is right now is incorrect.

I'm not sure where you're getting this from; the documentation for class_exists does not note this. class_exists is meant to return a boolean that indicates whether the class exists or not; a class not existing is not exceptional behaviour, so it shouldn't throw an exception. Doing so is a weird quirk that I'd argue is a PHP bug (albeit one we may need to work around for pragmatism's sake).

I don't understand rmccue's "code churn" argument.

Basically, I'm arguing against changing just for the sake of it. It's the same reason we reject whitespace-only fixes: if it ain't broke, don't fix it.


For what it's worth, I use autoloaders extensively on every project I work on with WordPress, and I've not hit any problems with it. Here's the one I use, for reference (consider it GPL). As long as you stick to the PSR-4 rules, you won't hit any problems.

It's worth mentioning that any project expecting PSR-4 compliant autoloading will likely have the same issue.

I still recommend close.

comment:23 follow-up: @jcjcc13 months ago

Try this

spl_autoload_extensions('.php');
spl_autoload_register();

var_dump(class_exists('Testing'));
var_dump(class_exists('\\Testing\\Foo'));

I agree that at this point, it seems like a PHP bug.

Apologies for claiming that class_exists was documented to throw an exception -- I did remember reading about the exception-throwing behavior in the docs, but it was in a comment, and not in the doc itself.

If it doesn't throw any errors when you call

spl_autoload_register('spl_autoload');

but it does when you call

spl_autoload_register();

then this is strange behavior to me as well. Can you get back to me on whether that happens? Let's leave it at that then after that.

Thanks rmccue, Denis-de-Bernardy, and SergeyBiryukov for your responses!

comment:24 in reply to: ↑ 23 @rmccue13 months ago

  • Milestone 4.0 deleted
  • Resolution set to wontfix
  • Status changed from reopened to closed

Replying to jcjcc:

Try this

spl_autoload_extensions('.php');
spl_autoload_register();

var_dump(class_exists('Testing'));
var_dump(class_exists('\\Testing\\Foo'));

Still no luck for me here:

$ wp shell
wp> spl_autoload_extensions('.php');
string(4) ".php"
wp> spl_autoload_register();
bool(true)
wp> class_exists('Testing');
bool(false)
wp> class_exists('\\Testing\\Foo');
bool(false)

Same result for spl_autoload_register('spl_autoload'). I suspect this depends on the PHP version as well as a bunch of other factors, but it seems inconsistent at best.

Let's leave it at that then after that.

Closing it for now then. :)

---

tl;dr for those seeing this ticket for the first time: we support PSR-4-compliant autoloaders, as well as most other autoloaders out of the box. spl_autoload throws an exception, which is against generally accepted behaviour in PHP userland, and hence can break.

Those looking for a replacement can use the following, which should be a drop-in replacement for spl_autoload (although I've not tested it fully):

spl_autoload_register( function ( $class ) {
	$class = strtolower( $class );
	$class = str_replace( '\\', DIRECTORY_SEPARATOR, $class );

	$extensions = explode( ',', spl_autoload_extensions() );

	foreach ( $extensions as $extension ) {
		$path = stream_resolve_include_path( $class . $extension );
		if ( ! empty( $path ) ) {
			include $path;
			return;
		}
	}
} );

comment:25 @rmccue13 months ago

  • Keywords close removed

comment:26 @jcjcc13 months ago

It sounds like the PHP bug was fixed sometime between my version (5.4.4-14+deb7u11) and yours (5.4.9) then! (It will be a while before Debian gets the patch sadly.)

Thanks for the very nice loader class on Gist and the drop-in replacement snippet :)

To add to the information for those seeing the ticket for the first time: the other workaround rmccue inadvertently discovered is to not set PHP to "default autoloader mode," but to load the default autoloader as a custom autoloader by passing "spl_autoload" to spl_autoload_register.

Yet another is to add a blank autoloader -- I guess this also unsets "default autoloader mode."

spl_autoload_register();
spl_autoload_register(function() {});
Note: See TracTickets for help on using tickets.