Author: Derick Rethans Date: 2006-11-17 14:06:33 +0100 (Fri, 17 Nov 2006) New Revision: 3958
Log: - Fixed issue #9390: Classes in external repositories that map to the same autoload filename of an internal component where added to the external autoload cache array as well. - Fixed issue #8507: Two autoload directories with the same basepath don't work. - Added some additional test cases. Added: trunk/Base/src/exceptions/double_class_repository_prefix.php trunk/Base/tests/extra_repository/ trunk/Base/tests/extra_repository/Translation/ trunk/Base/tests/extra_repository/Translation/test.php trunk/Base/tests/extra_repository/autoload/ trunk/Base/tests/extra_repository/autoload/translation_autoload.php trunk/Base/tests/test_repository/TestClasses/base_test_long_class.php trunk/Base/tests/test_repository/autoload_files/basetest_long_autoload.php Modified: trunk/Base/ChangeLog trunk/Base/src/base.php trunk/Base/src/base_autoload.php trunk/Base/tests/base_test.php trunk/Base/tests/test_repository/autoload_files/basetest_autoload.php Modified: trunk/Base/ChangeLog =================================================================== --- trunk/Base/ChangeLog 2006-11-17 12:57:12 UTC (rev 3957) +++ trunk/Base/ChangeLog 2006-11-17 13:06:33 UTC (rev 3958) @@ -1,3 +1,13 @@ +1.2beta2 - [RELEASEDATE] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Fixed issue #9390: Classes in external repositories that map to the same + autoload filename of an internal component where added to the external + autoload cache array as well. +- Fixed issue #8507: Two autoload directories with the same basepath don't + work. + + 1.2beta1 - Tuesday 24 October 2006 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Modified: trunk/Base/src/base.php =================================================================== --- trunk/Base/src/base.php 2006-11-17 12:57:12 UTC (rev 3957) +++ trunk/Base/src/base.php 2006-11-17 13:06:33 UTC (rev 3958) @@ -42,10 +42,14 @@ protected static $packageDir; /** - * @var array(string->array) Stores info with additional paths where + * @var array(string=>array) Stores info with additional paths where * autoload files and classes for autoloading * could be found. Each item of $repositoryDirs * looks like array( autoloadFileDir, baseDir ). + * The array key is the prefix belonging to + * classes within that repository - if provided + * when calling addClassRepository(), or an + * autoincrement integer otherwise. */ protected static $repositoryDirs = array(); @@ -93,7 +97,7 @@ } // Check whether the classname is already in the cached autoloadArray - // for external repositories.. + // for external repositories. if ( array_key_exists( $className, ezcBase::$externalAutoloadArray ) ) { // Is it registered as 'unloadable'? @@ -109,25 +113,25 @@ // Not cached, so load the autoload from the package. // Matches the first and optionally the second 'word' from the classname. $fileNames = array(); - if ( preg_match( "/^[a-z]*([A-Z][a-z0-9]*)([A-Z][a-z0-9]*)?/", $className, $matches ) !== false ) + if ( preg_match( "/^([a-z]*)([A-Z][a-z0-9]*)([A-Z][a-z0-9]*)?/", $className, $matches ) !== false ) { $autoloadFile = ""; // Try to match with both names, if available. switch ( sizeof( $matches ) ) { - case 3: - $autoloadFile = strtolower( "{$matches[1]}_{$matches[2]}_autoload.php" ); + case 4: + $autoloadFile = strtolower( "{$matches[2]}_{$matches[3]}_autoload.php" ); $fileNames[] = $autoloadFile; - if ( ezcBase::requireFile( $autoloadFile, $className ) ) + if ( ezcBase::requireFile( $autoloadFile, $className, $matches[1] ) ) { return true; } // break intentionally missing. - case 2: - $autoloadFile = strtolower( "{$matches[1]}_autoload.php" ); + case 3: + $autoloadFile = strtolower( "{$matches[2]}_autoload.php" ); $fileNames[] = $autoloadFile; - if ( ezcBase::requireFile( $autoloadFile, $className ) ) + if ( ezcBase::requireFile( $autoloadFile, $className, $matches[1] ) ) { return true; } @@ -143,6 +147,8 @@ $realPath = realpath( $path ); if ( $realPath == '' ) { + // Can not be tested, because if this happens, then the autoload + // environment has not been set-up correctly. trigger_error( "Couldn't find autoload directory '$path'", E_USER_ERROR ); } /* FIXME: this should go away - only for development */ @@ -203,14 +209,14 @@ * @return bool True is returned when the file is correctly loaded. * Otherwise false is returned. */ - protected static function requireFile( $fileName, $className ) + protected static function requireFile( $fileName, $className, $prefix ) { $autoloadDir = ezcBase::$packageDir . "autoload/"; // We need the full path to the fileName. The method file_exists() doesn't // automatically check the (php.ini) library paths. Therefore: // file_exists( "ezc/autoload/$fileName" ) doesn't work. - if ( file_exists( "$autoloadDir$fileName" ) ) + if ( $prefix === 'ezc' && file_exists( "$autoloadDir$fileName" ) ) { $array = require( "$autoloadDir$fileName" ); @@ -225,10 +231,16 @@ // It is not in components autoload/ dir. // try to search in additional dirs. - foreach ( ezcBase::$repositoryDirs as $extraDir ) + foreach ( ezcBase::$repositoryDirs as $repositoryPrefix => $extraDir ) { + if ( gettype( $repositoryPrefix ) === 'string' && $repositoryPrefix !== $prefix ) + { + continue; + } + if ( file_exists( $extraDir['autoloadDirPath'] . '/' . $fileName ) ) { + $array = array(); $originalArray = require( $extraDir['autoloadDirPath'] . '/' . $fileName ); // Building paths. @@ -298,6 +310,8 @@ } else { + // Can not be tested, because if this happens, then one of the + // components has a broken autoload file. throw new ezcBaseFileNotFoundException( ezcBase::$packageDir.$file ); } } @@ -341,6 +355,7 @@ } else { + // Can not be tested as it would abort the PHP script. die( "\nThe {$component} component depends on the default PHP extension '{$value}', which is not loaded.\n" ); } break; @@ -353,6 +368,7 @@ } else { + // Can not be tested as it would abort the PHP script. die( "\nThe {$component} component depends on the PHP version '{$value}', but the current version is '{$phpVersion}'.\n" ); } break; @@ -376,7 +392,7 @@ $autoloadDirs = array(); ezcBase::setPackageDir(); $repositoryDir = self::$currentWorkingDirectory ? self::$currentWorkingDirectory : ( realpath( dirname( __FILE__ ) . '/../../' ) ); - $autoloadDirs[$repositoryDir] = array( 'ezc', $repositoryDir . "/autoload" ); + $autoloadDirs['ezc'] = array( 'ezc', $repositoryDir . "/autoload" ); foreach ( ezcBase::$repositoryDirs as $extraDirKey => $extraDirArray ) { @@ -447,7 +463,7 @@ * ./repos/You/yourclass1.php * ./repos/You/yourclass2.php * </code> - + * * To use this repository with the autoload mechanism you have to use the * following code: * <code> @@ -461,7 +477,7 @@ * @param string $autoloadDirPath * @param string $basePath */ - public static function addClassRepository( $basePath, $autoloadDirPath = null ) + public static function addClassRepository( $basePath, $autoloadDirPath = null, $prefix = null ) { // check if base path exists if ( !is_dir( $basePath ) ) @@ -482,11 +498,23 @@ } // add info to $repositoryDirs - // $autoloadDirPath will be used as a key in $repositoryDirs - $array = array( $basePath => array( 'basePath' => $basePath, 'autoloadDirPath' => $autoloadDirPath ) ); - - // add info to the list of extra dirs if it exists there it will not be doubled. - ezcBase::$repositoryDirs = array_merge( ezcBase::$repositoryDirs, $array ); + if ( $prefix === null ) + { + $array = array( 'basePath' => $basePath, 'autoloadDirPath' => $autoloadDirPath ); + + // add info to the list of extra dirs + ezcBase::$repositoryDirs[] = $array; + } + else + { + if ( array_key_exists( $prefix, ezcBase::$repositoryDirs ) ) + { + throw new ezcBaseDoubleClassRepositoryPrefix( $prefix, $basePath, $autoloadDirPath ); + } + + // add info to the list of extra dirs, and use the prefix to identify the new repository. + ezcBase::$repositoryDirs[$prefix] = array( 'basePath' => $basePath, 'autoloadDirPath' => $autoloadDirPath ); + } } } ?> Modified: trunk/Base/src/base_autoload.php =================================================================== --- trunk/Base/src/base_autoload.php 2006-11-17 12:57:12 UTC (rev 3957) +++ trunk/Base/src/base_autoload.php 2006-11-17 13:06:33 UTC (rev 3958) @@ -17,6 +17,7 @@ 'ezcBaseException' => 'Base/exceptions/exception.php', 'ezcBaseFileException' => 'Base/exceptions/file_exception.php', + 'ezcBaseDoubleClassRepositoryPrefix' => 'Base/exceptions/double_class_repository_prefix.php', 'ezcBaseFileNotFoundException' => 'Base/exceptions/file_not_found.php', 'ezcBaseFileIoException' => 'Base/exceptions/file_io.php', 'ezcBaseFilePermissionException' => 'Base/exceptions/file_permission.php', Added: trunk/Base/src/exceptions/double_class_repository_prefix.php =================================================================== --- trunk/Base/src/exceptions/double_class_repository_prefix.php 2006-11-17 12:57:12 UTC (rev 3957) +++ trunk/Base/src/exceptions/double_class_repository_prefix.php 2006-11-17 13:06:33 UTC (rev 3958) @@ -0,0 +1,28 @@ +<?php +/** + * File containing the ezcBaseDoubleClassRepositoryPrefix class + * + * @package Base + * @version //autogen// + * @copyright Copyright (C) 2005, 2006 eZ systems as. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + */ +/** + * ezcBaseDoubleClassRepositoryPrefix is thrown whenever you try to register a + * class repository with a prefix that has already been added before. + * + * @package Base + * @version //autogen// + */ +class ezcBaseDoubleClassRepositoryPrefix extends ezcBaseException +{ + /** + * Constructs a new ezcBaseDoubleClassRepositoryPrefix for the $prefix that + * points to $basePath with autoload directory $autoloadDirPath. + */ + function __construct( $prefix, $basePath, $autoloadDirPath ) + { + parent::__construct( "The class repository in <{$basePath}> (with autoload dir <{$autoloadDirPath}>) can not be added because another class repository already uses the prefix <{$prefix}>." ); + } +} +?> Property changes on: trunk/Base/src/exceptions/double_class_repository_prefix.php ___________________________________________________________________ Name: svn:eol-style + native Modified: trunk/Base/tests/base_test.php =================================================================== --- trunk/Base/tests/base_test.php 2006-11-17 12:57:12 UTC (rev 3957) +++ trunk/Base/tests/base_test.php 2006-11-17 13:06:33 UTC (rev 3958) @@ -53,6 +53,18 @@ } } + public function testConfigExceptionOutOfRange3() + { + try + { + throw new ezcBaseSettingValueException( 'broken', array(1, 1, 3, 4, 5), 'int' ); + } + catch ( ezcBaseSettingValueException $e ) + { + $this->assertEquals( "The value <a:5:{i:0;i:1;i:1;i:1;i:2;i:3;i:3;i:4;i:4;i:5;}> that you were trying to assign to setting <broken> is invalid. Allowed values are: int", $e->getMessage() ); + } + } + public function testFileIoException1() { try @@ -185,6 +197,18 @@ } } + public function testFilePermissionException6() + { + try + { + throw new ezcBaseFilePermissionException( 'testfile.php', ezcBaseFilePermissionException::REMOVE, "Extra extra" ); + } + catch ( ezcBaseException $e ) + { + $this->assertEquals( "The file <testfile.php> can not be removed. (Extra extra)", $e->getMessage() ); + } + } + public function testPropertyNotFoundException() { try @@ -280,18 +304,18 @@ $this->fail( "Duplicating or missing extra autoload dirs while adding." ); } - $packageDir = realpath( dirname( __FILE__ ) . '/../..' ); - if ( !isset( $resultArray[$packageDir] ) ) + if ( !isset( $resultArray['ezc'] ) ) { $this->fail( "No packageDir found in result of getRepositoryDirectories()" ); } - if ( !isset( $resultArray['.'] ) || $resultArray['.'][1] != './autoload' ) + if ( !isset( $resultArray[0] ) || $resultArray[0][1] != './autoload' ) { $this->fail( "Extra autoload dir <{$resultArray['.'][1]}> is added incorrectly" ); } } + // this test is sorta obsolete, but we keep it around for good measure public function testBaseAddAndGetAutoloadDirs2() { ezcBase::addClassRepository( '.', './autoload' ); @@ -299,37 +323,89 @@ ezcBase::addClassRepository( './Base/tests/test_repository', './Base/tests/test_repository/autoload_files' ); $resultArray = ezcBase::getRepositoryDirectories(); - if ( count( $resultArray ) != 3 ) + if ( count( $resultArray ) != 5 ) { $this->fail( "Duplicating or missing extra autoload dirs while adding." ); } - $packageDir = realpath( dirname( __FILE__ ) . '/../..' ); - if ( !isset( $resultArray[$packageDir] ) ) + if ( !isset( $resultArray['ezc'] ) ) { $this->fail( "No packageDir found in result of getRepositoryDirectories()" ); } - if ( !isset( $resultArray['./Base/tests/test_repository'] ) || $resultArray['./Base/tests/test_repository'][1] != './Base/tests/test_repository/autoload_files' ) + if ( !isset( $resultArray[2] ) || $resultArray[2][1] != './Base/tests/test_repository/autoload_files' ) { - $this->fail( "Extra autoload dir <{$resultArray['./Base/tests/test_repository'][1]}> is added incorrectly" ); + $this->fail( "Extra autoload dir <{$resultArray[2][1]}> is added incorrectly" ); } self::assertEquals( true, class_exists( 'trBasetestClass', true ) ); self::assertEquals( true, class_exists( 'trBasetestClass2', true ) ); self::assertEquals( false, @class_exists( 'trBasetestClass3', true ) ); + self::assertEquals( true, class_exists( 'trBasetestLongClass', true ) ); + + try + { + class_exists( 'trBasetestClass4', true ); + self::fail( 'The expected exception was not thrown.' ); + } + catch ( ezcBaseFileNotFoundException $e ) + { + self::assertEquals( 'The file <./Base/tests/test_repository/TestClasses/base_test_class_number_four.php> could not be found.', $e->getMessage() ); + } } + public function testBaseAddAndGetAutoloadDirs3() + { + ezcBase::addClassRepository( './Base/tests/extra_repository', null, 'ext' ); + + $resultArray = ezcBase::getRepositoryDirectories(); + self::assertEquals( true, array_key_exists( 'ezc', $resultArray ) ); + self::assertEquals( true, array_key_exists( 'ext', $resultArray ) ); + + self::assertEquals( true, class_exists( 'extTranslationTest', true ) ); + self::assertEquals( true, class_exists( 'ezcTranslationTsBackend', true ) ); + } + + public function testBaseAddAndGetAutoloadDirs4() + { + ezcBase::addClassRepository( './Base/tests/test_repository', './Base/tests/test_repository/autoload_files', 'tr' ); + + try + { + ezcBase::addClassRepository( './Base/tests/test_repository', './Base/tests/test_repository/autoload_files', 'tr' ); + } + catch ( ezcBaseDoubleClassRepositoryPrefix $e ) + { + self::assertEquals( 'The class repository in <./Base/tests/test_repository> (with autoload dir <./Base/tests/test_repository/autoload_files>) can not be added because another class repository already uses the prefix <tr>.', $e->getMessage() ); + } + + $resultArray = ezcBase::getRepositoryDirectories(); + self::assertEquals( 7, count( $resultArray ) ); + + self::assertEquals( true, array_key_exists( 'ezc', $resultArray ) ); + self::assertEquals( true, array_key_exists( 'tr', $resultArray ) ); + } + public function testNoPrefixAutoload() { ezcBase::addClassRepository( './Base/tests/test_repository', './Base/tests/test_repository/autoload_files' ); __autoload( 'Object' ); - if( !class_exists( 'Object' ) ) + if ( !class_exists( 'Object' ) ) { $this->fail( "Autoload does not handle classes with no prefix" ); } } + public function testCheckDependencyExtension() + { + ezcBase::checkDependency( 'Tester', ezcBase::DEP_PHP_EXTENSION, 'standard' ); + } + + public function testCheckDependencyVersion() + { + ezcBase::checkDependency( 'Tester', ezcBase::DEP_PHP_VERSION, '5.1.1' ); + } + public function testInvalidClass() { set_error_handler( array( $this, "ErrorHandlerTest" ) ); @@ -351,7 +427,7 @@ { $this->errorMessage = $errstr; } - + public static function suite() { return new PHPUnit_Framework_TestSuite("ezcBaseTest"); Added: trunk/Base/tests/extra_repository/Translation/test.php =================================================================== --- trunk/Base/tests/extra_repository/Translation/test.php 2006-11-17 12:57:12 UTC (rev 3957) +++ trunk/Base/tests/extra_repository/Translation/test.php 2006-11-17 13:06:33 UTC (rev 3958) @@ -0,0 +1,8 @@ +<?php + +class extTranslationTest +{ + +} + +?> Property changes on: trunk/Base/tests/extra_repository/Translation/test.php ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/Base/tests/extra_repository/autoload/translation_autoload.php =================================================================== --- trunk/Base/tests/extra_repository/autoload/translation_autoload.php 2006-11-17 12:57:12 UTC (rev 3957) +++ trunk/Base/tests/extra_repository/autoload/translation_autoload.php 2006-11-17 13:06:33 UTC (rev 3958) @@ -0,0 +1,7 @@ +<?php + +return array( + 'extTranslationTest' => 'Translation/test.php', +); + +?> Property changes on: trunk/Base/tests/extra_repository/autoload/translation_autoload.php ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/Base/tests/test_repository/TestClasses/base_test_long_class.php =================================================================== --- trunk/Base/tests/test_repository/TestClasses/base_test_long_class.php 2006-11-17 12:57:12 UTC (rev 3957) +++ trunk/Base/tests/test_repository/TestClasses/base_test_long_class.php 2006-11-17 13:06:33 UTC (rev 3958) @@ -0,0 +1,6 @@ +<?php +ezcTestRunner::addFileToFilter( __FILE__ ); + +class trBasetestLongClass { +} +?> Property changes on: trunk/Base/tests/test_repository/TestClasses/base_test_long_class.php ___________________________________________________________________ Name: svn:eol-style + native Modified: trunk/Base/tests/test_repository/autoload_files/basetest_autoload.php =================================================================== --- trunk/Base/tests/test_repository/autoload_files/basetest_autoload.php 2006-11-17 12:57:12 UTC (rev 3957) +++ trunk/Base/tests/test_repository/autoload_files/basetest_autoload.php 2006-11-17 13:06:33 UTC (rev 3958) @@ -3,6 +3,7 @@ return array( 'trBasetestClass' => 'TestClasses/base_test_class.php', - 'trBasetestClass2' => 'TestClasses/base_test_class_number_two.php' + 'trBasetestClass2' => 'TestClasses/base_test_class_number_two.php', + 'trBasetestClass4' => 'TestClasses/base_test_class_number_four.php', ); ?> Added: trunk/Base/tests/test_repository/autoload_files/basetest_long_autoload.php =================================================================== --- trunk/Base/tests/test_repository/autoload_files/basetest_long_autoload.php 2006-11-17 12:57:12 UTC (rev 3957) +++ trunk/Base/tests/test_repository/autoload_files/basetest_long_autoload.php 2006-11-17 13:06:33 UTC (rev 3958) @@ -0,0 +1,7 @@ +<?php +ezcTestRunner::addFileToFilter( __FILE__ ); + +return array( + 'trBasetestLongClass' => 'TestClasses/base_test_long_class.php', +); +?> Property changes on: trunk/Base/tests/test_repository/autoload_files/basetest_long_autoload.php ___________________________________________________________________ Name: svn:eol-style + native -- svn-components mailing list svn-components@lists.ez.no http://lists.ez.no/mailman/listinfo/svn-components