Allowed the Factory class to be extended.

A class can now extend the Factory class and use all of its properties.
Properties like the layout system can be called like $this->layout, when extended. Just like the old days with the Bus abstract class.
Advantage of this system is that you don't require the use of extending the Factory class. Calling the factory for just one use is also possible.

Closes #93.
This commit is contained in:
Abel Hoogeveen 2016-06-02 13:57:32 +02:00
parent 57c54b0126
commit 544a84434c
6 changed files with 133 additions and 32 deletions

View File

@ -33,7 +33,6 @@
namespace Application\Controller;
use FuzeWorks\ControllerAbstract;
use FuzeWorks\Layout;
/**
* The default controller of FuzeWorks.
@ -55,6 +54,6 @@ class Standard extends ControllerAbstract
*/
public function index($path = null)
{
Layout::view('home');
$this->layout->view('home');
}
}

View File

@ -40,6 +40,6 @@ namespace FuzeWorks;
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
*/
abstract class ControllerAbstract
abstract class ControllerAbstract extends Factory
{
}

View File

@ -127,6 +127,7 @@ class Core
}
// Load core abstracts
include_once 'Core/System/class.factory.php';
include_once 'Core/System/class.exceptions.php';
include_once 'Core/System/class.abstract.event.php';
@ -153,7 +154,6 @@ class Core
include_once 'Core/System/class.security.php';
include_once 'Core/System/class.input.php';
include_once 'Core/System/class.output.php';
include_once 'Core/System/class.factory.php';
// Load the core classes
new Factory();

View File

@ -180,4 +180,14 @@ class UriException extends Exception
*/
class SecurityException extends Exception
{
}
/**
* Class FactoryException.
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
*/
class FactoryException extends Exception
{
}

View File

@ -48,6 +48,8 @@ namespace FuzeWorks;
* It is also possible to load a cloned instance of the Factory class, so that all properties are independant as well,
* all to suit your very needs.
*
* The Factory class is also extendible. This allows classes that extend Factory to access all it's properties.
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
*/
@ -81,23 +83,34 @@ class Factory
*/
public function __construct()
{
self::$sharedFactoryInstance = $this;
$this->instances['Config'] = new Config();
$this->instances['Logger'] = new Logger();
$this->instances['Events'] = new Events();
$this->instances['Models'] = new Models();
$this->instances['Layout'] = new Layout();
$this->instances['Modules'] = new Modules();
$this->instances['Libraries'] = new Libraries();
$this->instances['Helpers'] = new Helpers();
$this->instances['Database'] = new Database();
$this->instances['Language'] = new Language();
$this->instances['Utf8'] = new Utf8();
$this->instances['URI'] = new URI();
$this->instances['Security'] = new Security();
$this->instances['Input'] = new Input();
$this->instances['Router'] = new Router();
$this->instances['Output'] = new Output();
// If there is no sharedFactoryInstance, prepare it
if (is_null(self::$sharedFactoryInstance))
{
self::$sharedFactoryInstance = $this;
$this->instances['Config'] = new Config();
$this->instances['Logger'] = new Logger();
$this->instances['Events'] = new Events();
$this->instances['Models'] = new Models();
$this->instances['Layout'] = new Layout();
$this->instances['Modules'] = new Modules();
$this->instances['Libraries'] = new Libraries();
$this->instances['Helpers'] = new Helpers();
$this->instances['Database'] = new Database();
$this->instances['Language'] = new Language();
$this->instances['Utf8'] = new Utf8();
$this->instances['URI'] = new URI();
$this->instances['Security'] = new Security();
$this->instances['Input'] = new Input();
$this->instances['Router'] = new Router();
$this->instances['Output'] = new Output();
return true;
}
// Otherwise, copy the existing instances
$this->instances = self::getInstance()->getClassInstances();
return true;
}
/**
@ -136,6 +149,16 @@ class Factory
self::$cloneInstances = false;
}
/**
* Return the instance array where all the instances are loaded
*
* @return array Array of all loaded classes in THIS Factory
*/
public function getClassInstances()
{
return $this->instances;
}
/**
* Create a new instance of one of the loaded classes.
* It reloads the class. It does NOT clone it.
@ -150,6 +173,15 @@ class Factory
$instanceName = ucfirst($className);
$className = $namespace.$instanceName;
if (!isset($this->instances[$instanceName]))
{
throw new FactoryException("Could not load new instance of '".$instanceName."'. Instance was not found.", 1);
}
elseif (!class_exists($className, false))
{
throw new FactoryException("Could not load new instance of '".$instanceName."'. Class not found.", 1);
}
// Remove the current instance
unset($this->instances[$instanceName]);
@ -172,6 +204,11 @@ class Factory
// Determine the class to load
$instanceName = ucfirst($className);
if (!isset($this->instances[$instanceName]))
{
throw new FactoryException("Could not clone instance of '".$instanceName."'. Instance was not found.", 1);
}
// Clone the instance
$this->instances[$instanceName] = clone $this->instances[$instanceName];
@ -211,6 +248,11 @@ class Factory
// Determine the instance name
$instanceName = ucfirst($className);
if (!isset($this->instances[$instanceName]))
{
throw new FactoryException("Could not remove instance of '".$instanceName."'. Instance was not found.", 1);
}
// Unset
unset($this->instances[$instanceName]);
@ -234,6 +276,28 @@ class Factory
return null;
}
/**
* Test if a class is set to the Factory instance
*
* @param string $objectName Name of the class to get
* @return bool Whether the class is set
*/
public function __isset($objectName)
{
return isset($this->instances[ucfirst($objectName)]);
}
/**
* Unset a class set to the Factory instance
*
* @param string $objectName Name of the class to get
* @return void
*/
public function __unset($objectName)
{
unset($this->instances[ucfirst($objectName)]);
}
/* --------------------------------- Compatibility classes --------------------------------- */
/**

View File

@ -49,7 +49,7 @@ class factoryTest extends CoreTestAbstract
*/
public function testLoadSameInstance()
{
$this->assertTrue(Factory::getInstance() === Factory::getInstance());
$this->assertSame(Factory::getInstance(), Factory::getInstance());
}
/**
@ -58,10 +58,10 @@ class factoryTest extends CoreTestAbstract
public function testLoadDifferentInstance()
{
// First a situation where one is the shared instance and one is a cloned instance
$this->assertFalse(Factory::getInstance() === Factory::getInstance(true));
$this->assertNotSame(Factory::getInstance(), Factory::getInstance(true));
// And a situation where both are cloned instances
$this->assertFalse(Factory::getInstance(true) === Factory::getInstance(true));
$this->assertNotSame(Factory::getInstance(true), Factory::getInstance(true));
}
/**
@ -80,14 +80,14 @@ class factoryTest extends CoreTestAbstract
$factory2 = Factory::getInstance()->setInstance('Mock', $mock);
// Return the mocks
$this->assertTrue($factory1->mock === $factory2->mock);
$this->assertSame($factory1->mock, $factory2->mock);
// Different instance factories
$factory3 = Factory::getInstance(true)->setInstance('Mock', $mock);
$factory4 = Factory::getInstance(true)->setInstance('Mock', $mock);
// Return the mocks
$this->assertTrue($factory3->mock === $factory4->mock);
$this->assertSame($factory3->mock, $factory4->mock);
}
/**
@ -109,7 +109,7 @@ class factoryTest extends CoreTestAbstract
$factory2->cloneInstance('Mock');
// Should be true, since both Factories use the same Mock instance
$this->assertTrue($factory1->mock === $factory2->mock);
$this->assertSame($factory1->mock, $factory2->mock);
// Different instance factories
$factory3 = Factory::getInstance(true)->setInstance('Mock', $mock);
@ -119,31 +119,59 @@ class factoryTest extends CoreTestAbstract
$factory4->cloneInstance('Mock');
// Should be false, since both Factories use a different Mock instance
$this->assertFalse($factory3->mock === $factory4->mock);
$this->assertNotSame($factory3->mock, $factory4->mock);
}
public function testGlobalCloneInstance()
{
// First test without global cloning
$this->assertTrue(Factory::getInstance() === Factory::getInstance());
$this->assertSame(Factory::getInstance(), Factory::getInstance());
// Now enable global cloning
Factory::enableCloneInstances();
// Now test without global cloning
$this->assertFalse(Factory::getInstance() === Factory::getInstance());
$this->assertNotSame(Factory::getInstance(), Factory::getInstance());
// Disable global cloning
Factory::disableCloneInstances();
// And test again without global cloning
$this->assertTrue(Factory::getInstance() === Factory::getInstance());
$this->assertSame(Factory::getInstance(), Factory::getInstance());
}
public function testNewFactoryInstance()
{
// Load the different factories
$factory = new Factory();
$factory2 = Factory::getInstance();
// Test if the objects are different factory instances
$this->assertNotSame($factory, $factory2);
// Fetch the instances
$instances1 = $factory->getClassInstances();
$instances2 = $factory2->getClassInstances();
// And test if all ClassInstances are the same
foreach ($instances1 as $className => $object) {
$this->assertSame($object, $instances2[$className]);
}
// And test when changing one classInstance
$factory->newInstance('Layout');
$this->assertNotSame($factory->getLayout(), $factory2->getLayout());
}
public function tearDown()
{
Factory::getInstance()->removeInstance('Mock');
Factory::disableCloneInstances();
$factory = Factory::getInstance();
if (isset($factory->Mock))
{
$factory->removeInstance('Mock');
}
}
}