Feature #23956 » 16267.diff
tests/t3lib/t3lib_divTest.php (working copy) | ||
---|---|---|
* @subpackage t3lib
|
||
*/
|
||
class t3lib_divTest extends tx_phpunit_testcase {
|
||
/**
|
||
* Enable backup of global and system variables
|
||
*
|
||
... | ... | |
*/
|
||
protected $backupGlobalsBlacklist = array('TYPO3_DB');
|
||
public function tearDown() {
|
||
t3lib_div::purgeInstances();
|
||
}
|
||
///////////////////////////////
|
||
// Tests concerning validIP
|
||
... | ... | |
t3lib_div::dirname($input)
|
||
);
|
||
}
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
// Tests concerning makeInstance, setSingletonInstance, addInstance, purgeInstances
|
||
/////////////////////////////////////////////////////////////////////////////////////
|
||
/**
|
||
* @test
|
||
*
|
||
* @expectedException InvalidArgumentException
|
||
*/
|
||
public function makeInstanceWithEmptyClassNameThrowsException() {
|
||
t3lib_div::makeInstance('');
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function makeInstanceCanReturnInstanceOfNonSingletonClass() {
|
||
$className = get_class($this->getMock('foo'));
|
||
$this->assertTrue(
|
||
t3lib_div::makeInstance($className) instanceof $className
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function makeInstancePassesParametersToConstructor() {
|
||
$className = 'testingClass' . uniqid();
|
||
if (!class_exists($className, FALSE)) {
|
||
eval(
|
||
'class ' . $className . ' {' .
|
||
' public $constructorParameter;' .
|
||
' public function __construct($parameter) {' .
|
||
' $this->constructorParameter = $parameter;' .
|
||
' }' .
|
||
'}'
|
||
);
|
||
}
|
||
$instance = t3lib_div::makeInstance($className, 42);
|
||
$this->assertEquals(
|
||
42,
|
||
$instance->constructorParameter
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function makeInstanceCalledTwoTimesForNonSingletonClassReturnsDifferentInstances() {
|
||
$className = get_class($this->getMock('foo'));
|
||
$this->assertNotSame(
|
||
t3lib_div::makeInstance($className),
|
||
t3lib_div::makeInstance($className)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function makeInstanceCanReturnInstanceOfSingletonClass() {
|
||
$singletonClassName = get_class($this->getMock('t3lib_Singleton'));
|
||
$this->assertTrue(
|
||
t3lib_div::makeInstance($singletonClassName) instanceof $singletonClassName
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function makeInstanceCalledTwoTimesForSingletonClassReturnsSameInstance() {
|
||
$className = get_class($this->getMock('t3lib_Singleton'));
|
||
$this->assertSame(
|
||
t3lib_div::makeInstance($className),
|
||
t3lib_div::makeInstance($className)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function makeInstanceCalledTwoTimesForSingletonClassWithPurgeInstancesInbetweenReturnsDifferentInstances() {
|
||
$className = get_class($this->getMock('t3lib_Singleton'));
|
||
$instance = t3lib_div::makeInstance($className);
|
||
t3lib_div::purgeInstances();
|
||
$this->assertNotSame(
|
||
$instance,
|
||
t3lib_div::makeInstance($className)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*
|
||
* @expectedException InvalidArgumentException
|
||
*/
|
||
public function setSingletonInstanceForEmptyClassNameThrowsException() {
|
||
$instance = $this->getMock('t3lib_Singleton');
|
||
t3lib_div::setSingletonInstance('', $instance);
|
||
}
|
||
/**
|
||
* @test
|
||
*
|
||
* @expectedException InvalidArgumentException
|
||
*/
|
||
public function setSingletonInstanceForClassThatIsNoSubclassOfProvidedClassThrowsException() {
|
||
$instance = $this->getMock('t3lib_Singleton', array('foo'));
|
||
$singletonClassName = get_class($this->getMock('t3lib_Singleton'));
|
||
t3lib_div::setSingletonInstance($singletonClassName, $instance);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function setSingletonInstanceMakesMakeInstanceReturnThatInstance() {
|
||
$instance = $this->getMock('t3lib_Singleton');
|
||
$singletonClassName = get_class($instance);
|
||
t3lib_div::setSingletonInstance($singletonClassName, $instance);
|
||
$this->assertSame(
|
||
$instance,
|
||
t3lib_div::makeInstance($singletonClassName)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function setSingletonInstanceCalledTwoTimesMakesMakeInstanceReturnLastSetInstance() {
|
||
$instance1 = $this->getMock('t3lib_Singleton');
|
||
$singletonClassName = get_class($instance1);
|
||
$instance2 = new $singletonClassName();
|
||
t3lib_div::setSingletonInstance($singletonClassName, $instance1);
|
||
t3lib_div::setSingletonInstance($singletonClassName, $instance2);
|
||
$this->assertSame(
|
||
$instance2,
|
||
t3lib_div::makeInstance($singletonClassName)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*
|
||
* @expectedException InvalidArgumentException
|
||
*/
|
||
public function addInstanceForEmptyClassNameThrowsException() {
|
||
$instance = $this->getMock('foo');
|
||
t3lib_div::addInstance('', $instance);
|
||
}
|
||
/**
|
||
* @test
|
||
*
|
||
* @expectedException InvalidArgumentException
|
||
*/
|
||
public function addInstanceForClassThatIsNoSubclassOfProvidedClassThrowsException() {
|
||
$instance = $this->getMock('foo', array('bar'));
|
||
$singletonClassName = get_class($this->getMock('foo'));
|
||
t3lib_div::addInstance($singletonClassName, $instance);
|
||
}
|
||
/**
|
||
* @test
|
||
*
|
||
* @expectedException InvalidArgumentException
|
||
*/
|
||
public function addInstanceWithSingletonInstanceThrowsException() {
|
||
$instance = $this->getMock('t3lib_Singleton');
|
||
t3lib_div::addInstance(get_class($instance), $instance);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function addInstanceMakesMakeInstanceReturnThatInstance() {
|
||
$instance = $this->getMock('foo');
|
||
$className = get_class($instance);
|
||
t3lib_div::addInstance($className, $instance);
|
||
$this->assertSame(
|
||
$instance,
|
||
t3lib_div::makeInstance($className)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function makeInstanceCalledTwoTimesAfterAddInstanceReturnTwoDifferentInstances() {
|
||
$instance = $this->getMock('foo');
|
||
$className = get_class($instance);
|
||
t3lib_div::addInstance($className, $instance);
|
||
$this->assertNotSame(
|
||
t3lib_div::makeInstance($className),
|
||
t3lib_div::makeInstance($className)
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function addInstanceCalledTwoTimesMakesMakeInstanceReturnBothInstancesInAddingOrder() {
|
||
$instance1 = $this->getMock('foo');
|
||
$className = get_class($instance1);
|
||
t3lib_div::addInstance($className, $instance1);
|
||
$instance2 = new $className();
|
||
t3lib_div::addInstance($className, $instance2);
|
||
$this->assertSame(
|
||
$instance1,
|
||
t3lib_div::makeInstance($className),
|
||
'The first returned instance does not match the first added instance.'
|
||
);
|
||
$this->assertSame(
|
||
$instance2,
|
||
t3lib_div::makeInstance($className),
|
||
'The second returned instance does not match the second added instance.'
|
||
);
|
||
}
|
||
/**
|
||
* @test
|
||
*/
|
||
public function purgeInstancesDropsAddedInstance() {
|
||
$instance = $this->getMock('foo');
|
||
$className = get_class($instance);
|
||
t3lib_div::addInstance($className, $instance);
|
||
t3lib_div::purgeInstances();
|
||
$this->assertNotSame(
|
||
$instance,
|
||
t3lib_div::makeInstance($className)
|
||
);
|
||
}
|
||
}
|
||
?>
|
t3lib/class.t3lib_div.php (working copy) | ||
---|---|---|
* @subpackage t3lib
|
||
*/
|
||
final class t3lib_div {
|
||
// Severity constants used by t3lib_div::sysLog()
|
||
const SYSLOG_SEVERITY_INFO = 0;
|
||
const SYSLOG_SEVERITY_NOTICE = 1;
|
||
... | ... | |
const SYSLOG_SEVERITY_ERROR = 3;
|
||
const SYSLOG_SEVERITY_FATAL = 4;
|
||
/**
|
||
* singleton instances returned by makeInstance, using the class names as
|
||
* array keys
|
||
*
|
||
* @var array<t3lib_Singleton>
|
||
*/
|
||
static protected $singletonInstances = array();
|
||
/**
|
||
* instances returned by makeInstance, using the class names as array keys
|
||
*
|
||
* @var array<array><object>
|
||
*/
|
||
static protected $nonSingletonInstances = array();
|
||
/*************************
|
||
*
|
||
... | ... | |
* You can also pass arguments for a constructor:
|
||
* t3lib_div::makeInstance('myClass', $arg1, $arg2, ..., $argN)
|
||
*
|
||
* @param string Class name to instantiate
|
||
* @return object A reference to the object
|
||
* @param string $className
|
||
* name of the class to instantiate, must not be empty
|
||
*
|
||
* @return object the created instance
|
||
*/
|
||
public static function makeInstance($className) {
|
||
// holds references of singletons
|
||
static $instances = array();
|
||
if ($className === '') {
|
||
throw new InvalidArgumentException('$className must not be empty.', 1288965219);
|
||
}
|
||
// Get final classname
|
||
$className = self::getClassName($className);
|
||
$finalClassName = self::getClassName($className);
|
||
if (isset($instances[$className])) {
|
||
// it's a singleton, get the existing instance
|
||
$instance = $instances[$className];
|
||
} else {
|
||
if (func_num_args() > 1) {
|
||
// getting the constructor arguments by removing this
|
||
// method's first argument (the class name)
|
||
$constructorArguments = func_get_args();
|
||
array_shift($constructorArguments);
|
||
if (isset(self::$singletonInstances[$finalClassName])) {
|
||
return self::$singletonInstances[$finalClassName];
|
||
}
|
||
$reflectedClass = new ReflectionClass($className);
|
||
$instance = $reflectedClass->newInstanceArgs($constructorArguments);
|
||
} else {
|
||
$instance = new $className;
|
||
}
|
||
if (isset(self::$nonSingletonInstances[$finalClassName])
|
||
&& !empty(self::$nonSingletonInstances[$finalClassName])
|
||
) {
|
||
return array_shift(self::$nonSingletonInstances[$finalClassName]);
|
||
}
|
||
if ($instance instanceof t3lib_Singleton) {
|
||
// it's a singleton, save the instance for later reuse
|
||
$instances[$className] = $instance;
|
||
}
|
||
if (func_num_args() > 1) {
|
||
$constructorArguments = func_get_args();
|
||
array_shift($constructorArguments);
|
||
$reflectedClass = new ReflectionClass($finalClassName);
|
||
$instance = $reflectedClass->newInstanceArgs($constructorArguments);
|
||
} else {
|
||
$instance = new $finalClassName;
|
||
}
|
||
if ($instance instanceof t3lib_Singleton) {
|
||
self::$singletonInstances[$finalClassName] = $instance;
|
||
}
|
||
return $instance;
|
||
... | ... | |
}
|
||
/**
|
||
* Sets the instance of a singleton class to be returned by makeInstance.
|
||
*
|
||
* If this function is called multiple times for the same $className,
|
||
* makeInstance will return the last set instance.
|
||
*
|
||
* This function is intendend help with unit testing.
|
||
*
|
||
* @param string $className
|
||
* the name of the class to set, must not be empty
|
||
* @param t3lib_Singleton $instance
|
||
* the instance to set, must be an instance of $className
|
||
*
|
||
* @return void
|
||
*
|
||
* @see makeInstance
|
||
*/
|
||
public function setSingletonInstance($className, t3lib_Singleton $instance) {
|
||
self::checkInstanceClassName($className, $instance);
|
||
self::$singletonInstances[$className] = $instance;
|
||
}
|
||
/**
|
||
* Sets the instance of a non-singleton class to be returned by makeInstance.
|
||
*
|
||
* If this function is called multiple times for the same $className,
|
||
* makeInstance will return the instances in the order in which they have
|
||
* been added.
|
||
*
|
||
* This function is intendend help with unit testing.
|
||
*
|
||
* @param string $className
|
||
* the name of the class to set, must not be empty
|
||
* @param object $instance
|
||
* the instance to set, must be an instance of $className
|
||
*
|
||
* @return void
|
||
*
|
||
* @see makeInstance
|
||
*/
|
||
public function addInstance($className, $instance) {
|
||
self::checkInstanceClassName($className, $instance);
|
||
if ($instance instanceof t3lib_Singleton) {
|
||
throw new InvalidArgumentException(
|
||
'$instance must not be an instance of t3lib_Singleton. ' .
|
||
'For setting singletons, please use setSingletonInstance.',
|
||
1288969325
|
||
);
|
||
}
|
||
if (!isset(self::$nonSingletonInstances[$className])) {
|
||
self::$nonSingletonInstances[$className] = array();
|
||
}
|
||
self::$nonSingletonInstances[$className][] = $instance;
|
||
}
|
||
/**
|
||
* Checks that $className is non-empty and that $instance is an instance of
|
||
* $className.
|
||
*
|
||
* @param string $className a class name
|
||
* @param object $instance an object
|
||
*
|
||
* @throws InvalidArgumentException
|
||
* if $className is empty or if $instance is no instance of $className
|
||
*/
|
||
static protected function checkInstanceClassName($className, $instance) {
|
||
if ($className === '') {
|
||
throw new InvalidArgumentException('$className must not be empty.', 1288967479);
|
||
}
|
||
if (!($instance instanceof $className)) {
|
||
throw new InvalidArgumentException(
|
||
'$instance must be an instance of ' . $className . ', but actually is an instance of ' . get_class($instance) . '.',
|
||
1288967686
|
||
);
|
||
}
|
||
}
|
||
/**
|
||
* Purges all instances returned by makeInstance.
|
||
*
|
||
* This function is most useful when called from tearDown in a testcase
|
||
* to drop any instances that have been created by the tests.
|
||
*
|
||
* @return void
|
||
*
|
||
* @see makeInstance
|
||
*/
|
||
static public function purgeInstances() {
|
||
self::$singletonInstances = array();
|
||
self::$nonSingletonInstances = array();
|
||
}
|
||
/**
|
||
* Find the best service and check if it works.
|
||
* Returns object of the service class.
|
||
*
|
||
... | ... | |
echo $obContent;
|
||
}
|
||
}
|
||
?>
|
||
?>
|
NEWS.txt (working copy) | ||
---|---|---|
Backend
|
||
=======
|
||
* The frameset was removed. This makes the Backend a lot faster.
|
||
* The frameset was removed. This makes the Backend a lot faster.
|
||
Now the navigation tree also can be resized. The new backend works
|
||
using the ExtJS viewport, providing an easy and unified interface
|
||
to manipulate the content of the different panels.
|
||
... | ... | |
having no console like the IE
|
||
* ExtDirect is available in the frontend now (#15754):
|
||
http://wiki.typo3.org/ExtDirect
|
||
* t3lib_div now provides two functions setSingletonInstance and addInstance
|
||
that will set the objects to be returned by makeInstance. (#16267)
|
||
This will allow unit tests to inject mocks into makeInstance.
|
||
In addition, there now is a function purgeInstances that makes
|
||
makeInstance return fresh instances (singleton as well as non-singleton).
|
||
TypoScript
|
||
==========
|