Implemented three requested features.

- FuzeWorks\Core now manages autoloading of classes for Plugins. Plugins no longer need to implement this themselves. Autoloading for libraries to be added soon.
- FuzeWorks\Factory::getInstance('') now returns a requested component. No arguments will result in the Factory being returned. This should simplify invoking components. cloneInstance() replaces old functionality.
- FuzeWorks\Logger can now properly write logs to file. It's unknown how this issue wasn't discovered before.
This commit is contained in:
Abel Hoogeveen 2019-07-22 19:48:13 +02:00
parent c1b29cea5f
commit 8b01dd2f84
23 changed files with 350 additions and 149 deletions

View File

@ -36,6 +36,7 @@
namespace FuzeWorks;
use FuzeWorks\Exception\CoreException;
use FuzeWorks\Exception\EventException;
/**
@ -43,6 +44,7 @@ use FuzeWorks\Exception\EventException;
*
* Holds all the modules and starts the framework. Allows for starting and managing modules
*
* @todo Implement unit tests for autoloader() methods
* @author TechFuze <contact@techfuze.net>
* @copyright Copyright (c) 2013 - 2019, TechFuze. (http://techfuze.net)
*/
@ -53,7 +55,7 @@ class Core
*
* @var string Framework version
*/
public static $version = '1.0.0';
public static $version = '1.2.0';
/**
* Working directory of the Framework.
@ -108,6 +110,7 @@ class Core
register_shutdown_function(array('\FuzeWorks\Core', 'shutdown'));
set_error_handler(array('\FuzeWorks\Core', 'errorHandler'), E_ALL);
set_exception_handler(array('\FuzeWorks\Core', 'exceptionHandler'));
spl_autoload_register(['\FuzeWorks\Core', 'autoloader'], true,false);
// Return the Factory
return new Factory();
@ -186,7 +189,6 @@ class Core
}
}
/**
* Add an exception handler to be called when an exception occurs
*
@ -249,6 +251,47 @@ class Core
}
}
protected static $autoloadMap = [];
/**
* @param string $nameSpacePrefix
* @param string $filePath
* @throws CoreException
*/
public static function addAutoloadMap(string $nameSpacePrefix, string $filePath)
{
// Remove leading slashes
$nameSpacePrefix = ltrim($nameSpacePrefix, '\\');
if (isset(self::$autoloadMap[$nameSpacePrefix]))
throw new CoreException("Could not add classes to autoloader. ClassMap already exists.");
if (!file_exists($filePath) && !is_dir($filePath))
throw new CoreException("Could not add classes to autoloader. Provided filePath does not exist.");
self::$autoloadMap[$nameSpacePrefix] = $filePath;
}
public static function autoloader(string $class)
{
// Remove leading slashes
$class = ltrim($class, '\\');
// First attempt and find if the prefix of the class is in the autoloadMap
foreach (self::$autoloadMap as $prefix => $path)
{
// If not, try next
if (strpos($class, $prefix) === false)
continue;
// If it contains the prefix, attempt to find the file
$className = substr($class, strlen($prefix) + 1);
$filePath = $path . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $className) . '.php';
if (file_exists($filePath) && is_file($filePath))
require($filePath);
}
}
/**
* Tests for file writability
*

View File

@ -71,13 +71,6 @@ class Factory
*/
private static $sharedFactoryInstance;
/**
* Whether to clone all Factory instances upon calling Factory::getInstance()
*
* @var bool Clone all Factory instances.
*/
private static $cloneInstances = false;
/**
* Whether the Factory has been initialized or not
*
@ -124,6 +117,7 @@ class Factory
/**
* Factory instance constructor. Should only really be called once
* @throws ConfigException
* @throws FactoryException
*/
public function __construct()
{
@ -174,9 +168,7 @@ class Factory
// Disable events if requested to do so
if (!$cfg->get('enable_events'))
{
Events::disable();
}
// Initialize all components
foreach ($this as $component)
@ -201,40 +193,25 @@ class Factory
return $this;
}
/**
* Get a new instance of the Factory class.
*
* @param bool $cloneInstance Whether to get a cloned instance (true) or exactly the same instance (false)
* @return Factory Instance
*/
public static function getInstance($cloneInstance = false): Factory
{
if ($cloneInstance === true || self::$cloneInstances === true)
{
return clone self::$sharedFactoryInstance;
}
/**
* Get an instance of a componentClass.
*
* @param string|null $instanceName
* @return mixed
* @throws FactoryException
*/
public static function getInstance(string $instanceName = null)
{
if (is_null($instanceName))
return self::$sharedFactoryInstance;
return self::$sharedFactoryInstance;
}
// Determine the instance name
$instanceName = strtolower($instanceName);
/**
* Enable cloning all Factory instances upon calling Factory::getInstance()
*
* @return void
*/
public static function enableCloneInstances()
{
self::$cloneInstances = true;
}
if (!isset(self::$sharedFactoryInstance->{$instanceName}))
throw new FactoryException("Could not get instance. Instance was not found.");
/**
* Disable cloning all Factory instances upon calling Factory::getInstance()
*
* @return void
*/
public static function disableCloneInstances()
{
self::$cloneInstances = false;
return self::$sharedFactoryInstance->{$instanceName};
}
/**
@ -275,25 +252,29 @@ class Factory
* Clone an instance of one of the loaded classes.
* It clones the class. It does NOT re-create it.
*
* If the $onlyReturn = true is provided, the cloned instance will only be returned, and not set to the factory.
*
* @param string $className The name of the loaded class, WITHOUT the namespace
* @return Factory Instance
* @param bool $onlyReturn
* @return mixed
* @throws FactoryException
*/
public function cloneInstance($className): self
public static function cloneInstance(string $className, bool $onlyReturn = false)
{
// Determine the class to load
$instanceName = strtolower($className);
if (!isset($this->{$instanceName}))
{
if (!isset(self::$sharedFactoryInstance->{$instanceName}))
throw new FactoryException("Could not clone instance of '".$instanceName."'. Instance was not found.", 1);
}
if ($onlyReturn)
return clone self::$sharedFactoryInstance->{$instanceName};
// Clone the instance
$this->{$instanceName} = clone $this->{$instanceName};
self::$sharedFactoryInstance->{$instanceName} = clone self::$sharedFactoryInstance->{$instanceName};
// Return itself
return $this;
return self::$sharedFactoryInstance->{$instanceName};
}
/**

View File

@ -182,9 +182,7 @@ class Libraries
{
// First check to see if the library is already loaded
if (!class_exists($libraryClass, false))
{
throw new LibraryException("Could not initiate library. Class not found", 1);
}
// Determine what parameters to use
if (empty($parameters))
@ -200,6 +198,9 @@ class Libraries
// Load the class object
$classObject = new $libraryClass($parameters);
// @todo Check if library has all required methods (iLibrary)
// @todo Implement autoloading for libraries
// Check if the address is already reserved, if it is, we can presume that a new instance is requested.
// Otherwise this code would not be reached

View File

@ -223,9 +223,7 @@ class Logger {
}
if (self::$log_last_request == true)
{
self::logLastRequest();
}
if (self::$log_errors_to_file == true)
self::logErrorsToFile();
@ -342,9 +340,8 @@ class Logger {
require(dirname(__DIR__) . DS . 'Layout' . DS . 'layout.logger_file.php');
$contents = ob_get_clean();
$file = Core::$logDir . DS . 'fwlog_request.log';
if (is_writable(dirname($file))) {
if (is_writable(dirname($file)))
file_put_contents($file, $contents);
}
}
/**
@ -357,14 +354,14 @@ class Logger {
$logs = [];
foreach (self::$logs as $log)
{
if ($log['type'] === 'ERROR')
if ($log['type'] === 'ERROR' || $log['type'] === 'EXCEPTION')
$logs[] = $log;
}
require(dirname(__DIR__) . DS . 'Layout' . DS . 'layout.logger_file.php');
$contents = ob_get_clean();
$file = Core::$logDir . DS . 'fwlog_errors.log';
if (is_writable(dirname($file)))
file_put_contents($file, $contents, FILE_APPEND | LOCK_EX);
file_put_contents($file, $contents, FILE_APPEND);
}
/* =========================================LOGGING METHODS============================================================== */

View File

@ -38,6 +38,7 @@ namespace FuzeWorks;
use FuzeWorks\ConfigORM\ConfigORM;
use FuzeWorks\Event\PluginGetEvent;
use FuzeWorks\Exception\ConfigException;
use FuzeWorks\Exception\CoreException;
use FuzeWorks\Exception\PluginException;
use ReflectionClass;
use ReflectionException;
@ -210,10 +211,8 @@ class Plugins
*/
public function get($pluginName, array $parameters = null)
{
if (empty($pluginName))
{
if (empty($pluginName))
throw new PluginException("Could not load plugin. No name provided", 1);
}
// Determine the name of the plugin
$pluginName = ucfirst($pluginName);
@ -222,38 +221,45 @@ class Plugins
/** @var PluginGetEvent $event */
$event = Events::fireEvent('pluginGetEvent', $pluginName);
if ($event->isCancelled())
{
return false;
}
elseif ($event->getPlugin() != null)
{
return $event->getPlugin();
}
// Otherwise just set the variables
$pluginName = $event->pluginName;
// Check if the plugin is already loaded and return directly
if (isset($this->plugins[$pluginName]))
{
return $this->plugins[$pluginName];
}
// Check if the plugin header exists
if (!isset($this->headers[$pluginName]))
{
throw new PluginException("Could not load plugin. Plugin header does not exist", 1);
}
// If disabled, don't bother
if (in_array($pluginName, $this->cfg->get('disabled_plugins')))
{
throw new PluginException("Could not load plugin. Plugin is disabled", 1);
}
// Determine what file to load
/** @var iPluginHeader $header */
$header = $this->headers[$pluginName];
// Add to autoloader
// @todo Find a more reliable method for determining header directory
$headerReflection = new ReflectionClass( get_class($header) );
$prefix = $header->getClassesPrefix();
$filePath = dirname($headerReflection->getFileName()) . (!empty($header->getSourceDirectory()) ? DS . $header->getSourceDirectory() : '');
$pluginClass = $header->getPluginClass();
if (!is_null($prefix) && !is_null($filePath))
{
try {
Core::addAutoloadMap($prefix, $filePath);
} catch (CoreException $e) {
throw new PluginException("Could not load plugin. Autoloader invalid: '".$e->getMessage()."'");
}
}
// If a 'getPlugin' method is found in the header, call that instead
if (method_exists($header, 'getPlugin'))
{
@ -262,26 +268,11 @@ class Plugins
return $this->plugins[$pluginName];
}
// Determine class name and file
// @todo Find a more reliable method for determining header directory
$headerReflection = new ReflectionClass( get_class($header) );
$directory = dirname($headerReflection->getFileName());
$classFile = (isset($header->classFile) ? $directory.DS.$header->classFile : $directory.DS.'plugin.'.strtolower($pluginName).".php");
$className = (isset($header->className) ? $header->className : '\Application\Plugin\\'.$pluginName);
// Try to access the file
if (!file_exists($classFile))
{
throw new PluginException("Could not load plugin. Class file does not exist", 1);
}
// Attempt to load the plugin
require_once($classFile);
if (!class_exists($className, false))
{
if (!class_exists($pluginClass, true))
throw new PluginException("Could not load plugin. Class does not exist", 1);
}
$this->plugins[$pluginName] = new $className($parameters);
$this->plugins[$pluginName] = new $pluginClass($parameters);
Logger::log('Loaded Plugin: \'' . $pluginName . '\'');
// And return it

View File

@ -39,6 +39,50 @@ namespace FuzeWorks;
interface iPluginHeader
{
/**
* Should return the name of the plugin.
*
* This is the name used to access the plugin when using Plugins::get()
* @return string
*/
public function getName(): string;
/**
* Should return the namespace prefix of the classes of this plugin.
*
* Used to autoload classes of this plugin.
* @see https://www.php-fig.org/psr/psr-4/
*
* Invoked upon `FuzeWorks\Plugins::get`. Autoloading plugin classes before that is not possible.
*
* @return string|null
*/
public function getClassesPrefix(): ?string;
/**
* Should return the directory where the classes of this plugin can be found.
*
* Only the source directory within the plugin should be returned, e.g:
* If the source directory is 'src' within the plugin directory, return 'src'
*
* @return string|null
*/
public function getSourceDirectory(): ?string;
/**
* Should return the className of the main class of this plugin
*
* Should only return null if the pluginHeader has the optional getPlugin() method.
*
* @return string|null
*/
public function getPluginClass(): ?string;
/**
* Initializes the pluginHeader. This method allows the developer to hook into multiple systems of FuzeWorks
* upon FuzeWorks initialization. See the FuzeWorks boot process for more information.
*
* @return mixed
*/
public function init();
}

View File

@ -34,19 +34,16 @@
* @version Version 1.2.0
*/
$mask = "|%5s |%-95s |\n";
$mask = "|%5s |%5s |%-90s |\n";
$id = 1;
if (!empty($logs))
printf($mask, $id, ' REQUEST ' . date('Y-m-d H:i') . '-'.substr(sha1(uniqid()), 0, 8).'');
printf($mask, $id, 'REQUEST', ' ' . date('Y-m-d H:i') . '-'.substr(sha1(uniqid()), 0, 8).'');
foreach ($logs as $log) {
$id++;
$string = '';
$string .= '[ERROR]' . ' - ';
$string .= $log['message'];
printf($mask, $id, $log['type'], $log['message']);
}
if (!empty($logs))
printf($mask, $id, '');
printf($mask, $id, 'HALT', '---------------------');

View File

@ -54,6 +54,32 @@ class factoryTest extends CoreTestAbstract
$this->assertInstanceOf('FuzeWorks\Factory', Factory::getInstance());
}
/**
* @covers ::getInstance
*/
public function testGetInstance()
{
// Add the mock
$mock = $this->getMockBuilder(MockFactory::class)->getMock();
Factory::getInstance()->setInstance('Mock', $mock);
// First test a global getInstance Factory
$this->assertInstanceOf('\FuzeWorks\Factory', Factory::getInstance());
// Second, test retrieving a component
$this->assertInstanceOf(get_class($mock), Factory::getInstance('Mock'));
}
/**
* @depends testGetInstance
* @covers ::getInstance
* @expectedException \FuzeWorks\Exception\FactoryException
*/
public function testGetInstanceNotFound()
{
Factory::getInstance('NotFound');
}
/**
* @depends testCanLoadFactory
* @covers ::getInstance
@ -70,11 +96,23 @@ class factoryTest extends CoreTestAbstract
*/
public function testLoadDifferentInstance()
{
// Add the mock
$mock = $this->getMockBuilder(MockFactory::class)->getMock();
Factory::getInstance()->setInstance('Mock', $mock);
// First a situation where one is the shared instance and one is a cloned instance
$this->assertNotSame(Factory::getInstance(), Factory::getInstance(true));
$a = Factory::getInstance('Mock');
$b = Factory::cloneInstance('Mock');
$this->assertInstanceOf(get_class($mock), $a);
$this->assertInstanceOf(get_class($mock), $b);
$this->assertNotSame($a,$b);
// And a situation where both are cloned instances
$this->assertNotSame(Factory::getInstance(true), Factory::getInstance(true));
$a = Factory::cloneInstance('Mock');
$b = Factory::cloneInstance('Mock');
$this->assertInstanceOf(get_class($mock), $a);
$this->assertInstanceOf(get_class($mock), $b);
$this->assertNotSame($a,$b);
}
/**
@ -91,6 +129,8 @@ class factoryTest extends CoreTestAbstract
$this->assertFalse(isset(Factory::getInstance()->mock));
// Same instance factories
/** @var Factory $factory1 */
/** @var Factory $factory2 */
$factory1 = Factory::getInstance()->setInstance('Mock', $mock);
$factory2 = Factory::getInstance()->setInstance('Mock', $mock);
@ -98,8 +138,8 @@ class factoryTest extends CoreTestAbstract
$this->assertSame($factory1->mock, $factory2->mock);
// Different instance factories
$factory3 = Factory::getInstance(true)->setInstance('Mock', $mock);
$factory4 = Factory::getInstance(true)->setInstance('Mock', $mock);
$factory3 = Factory::getInstance()->setInstance('Mock', $mock);
$factory4 = Factory::getInstance()->setInstance('Mock', $mock);
// Return the mocks
$this->assertSame($factory3->mock, $factory4->mock);
@ -121,23 +161,23 @@ class factoryTest extends CoreTestAbstract
$factory2 = Factory::getInstance()->setInstance('Mock', $mock);
// Clone the instance in factory2
$factory2->cloneInstance('Mock');
$factory2mock = $factory2->cloneInstance('Mock');
// Should be true, since both Factories use the same Mock instance
$this->assertSame($factory1->mock, $factory2->mock);
$this->assertSame($factory1->mock, $factory2mock);
// Different instance factories
$factory3 = Factory::getInstance(true)->setInstance('Mock', $mock);
$factory4 = Factory::getInstance(true)->setInstance('Mock', $mock);
$factory3 = Factory::getInstance()->setInstance('Mock', $mock);
$factory4 = Factory::getInstance()->setInstance('Mock', $mock);
// Should be same for now
$this->assertSame($factory3->mock, $factory4->mock);
// Clone the instance in factory4
$factory4->cloneInstance('Mock');
$factory4mock = $factory4->cloneInstance('Mock', true);
// Should be false, since both Factories use a different Mock instance
$this->assertNotSame($factory3->mock, $factory4->mock);
$this->assertNotSame($factory3->mock, $factory4mock);
}
/**
@ -154,31 +194,6 @@ class factoryTest extends CoreTestAbstract
$factory->cloneInstance('fake');
}
/**
* @depends testCanLoadFactory
* @covers ::enableCloneInstances
* @covers ::disableCloneInstances
* @covers ::cloneInstance
* @covers ::getInstance
*/
public function testGlobalCloneInstance()
{
// First test without global cloning
$this->assertSame(Factory::getInstance(), Factory::getInstance());
// Now enable global cloning
Factory::enableCloneInstances();
// Now test without global cloning
$this->assertNotSame(Factory::getInstance(), Factory::getInstance());
// Disable global cloning
Factory::disableCloneInstances();
// And test again without global cloning
$this->assertSame(Factory::getInstance(), Factory::getInstance());
}
/**
* @depends testCanLoadFactory
* @covers ::getInstance
@ -295,13 +310,9 @@ class factoryTest extends CoreTestAbstract
public function tearDown()
{
Factory::disableCloneInstances();
$factory = Factory::getInstance();
if (isset($factory->Mock))
{
$factory->removeInstance('Mock');
}
if (isset($factory->mock))
$factory->removeInstance('mock');
}
}

View File

@ -55,6 +55,7 @@ class pluginTest extends CoreTestAbstract
public function setUp()
{
$this->plugins = new Plugins();
$this->plugins->init();
$this->plugins->addComponentPath('test'.DS.'plugins');
$this->plugins->loadHeadersFromPluginPaths();
}
@ -73,7 +74,7 @@ class pluginTest extends CoreTestAbstract
*/
public function testLoadPlugin()
{
$this->assertInstanceOf('\Application\Plugin\TestLoadPlugin', $this->plugins->get('testLoadPlugin'));
$this->assertInstanceOf('\FuzeWorks\UnitTest\Plugins\TestLoadPlugin\TestLoadPlugin', $this->plugins->get('testLoadPlugin'));
}
/**
@ -99,7 +100,7 @@ class pluginTest extends CoreTestAbstract
$this->plugins->addPlugin($header);
// Assert the plugin
$this->assertInstanceOf('Application\Plugin\Plug', $this->plugins->get('Plug'));
$this->assertInstanceOf('\FuzeWorks\UnitTest\Plugins\TestLoadHeader\Plug', $this->plugins->get('Plug'));
}
/**
@ -125,9 +126,9 @@ class pluginTest extends CoreTestAbstract
* @depends testLoadPlugin
* @covers ::get
*/
public function testGetPluginWithClassFile()
public function testGetPluginWithClassMap()
{
$this->assertInstanceOf('OtherPlug', $this->plugins->get('TestGetPluginWithClassFile'));
$this->assertInstanceOf('FuzeWorks\UnitTest\Plugins\TestGetPluginWithClassMap\OtherPlug', $this->plugins->get('TestGetPluginWithClassMap'));
}
/**

View File

@ -47,4 +47,19 @@ class TestDisabledPluginHeader implements iPluginHeader
public function init()
{
}
public function getClassesPrefix(): ?string
{
return null;
}
public function getSourceDirectory(): ?string
{
return null;
}
public function getPluginClass(): ?string
{
return null;
}
}

View File

@ -52,4 +52,19 @@ class TestGetPluginMethodHeader implements iPluginHeader
{
return 'test_string';
}
public function getClassesPrefix(): ?string
{
return null;
}
public function getSourceDirectory(): ?string
{
return null;
}
public function getPluginClass(): ?string
{
return null;
}
}

View File

@ -34,6 +34,8 @@
* @version Version 1.2.0
*/
namespace FuzeWorks\UnitTest\Plugins\TestGetPluginWithClassMap;
class OtherPlug
{

View File

@ -36,18 +36,31 @@
namespace Application\Plugin;
use FuzeWorks\iPluginHeader;
class TestGetPluginWithClassFileHeader implements iPluginHeader
class TestGetPluginWithClassMapHeader implements iPluginHeader
{
public $classFile = 'OtherPlugFile.php';
public $className = 'OtherPlug';
public function getName(): string
{
return "TestGetPluginWithClassFile";
return "TestGetPluginWithClassMap";
}
public function getClassesPrefix(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestGetPluginWithClassMap';
}
public function getSourceDirectory(): ?string
{
return '';
}
public function getPluginClass(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestGetPluginWithClassMap\OtherPlug';
}
public function init()
{
}
}

View File

@ -44,6 +44,21 @@ class TestInvalidClassHeader implements iPluginHeader
return "TestInvalidClass";
}
public function getClassesPrefix(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestInvalidClassHeader';
}
public function getSourceDirectory(): ?string
{
return '';
}
public function getPluginClass(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestInvalidClassHeader\TestInvalidClass';
}
public function init()
{
}

View File

@ -33,7 +33,7 @@
*
* @version Version 1.2.0
*/
namespace Application\Plugin;
namespace FuzeWorks\UnitTest\Plugins\TestLoadHeader;
class Plug
{

View File

@ -44,6 +44,21 @@ class TestLoadHeaderHeader implements iPluginHeader
return "Plug";
}
public function getClassesPrefix(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestLoadHeader';
}
public function getSourceDirectory(): ?string
{
return '';
}
public function getPluginClass(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestLoadHeader\Plug';
}
public function init()
{
}

View File

@ -33,7 +33,7 @@
*
* @version Version 1.2.0
*/
namespace Application\Plugin;
namespace FuzeWorks\UnitTest\Plugins\TestLoadHeaderNotIPluginHeader;
class TestLoadPlugin
{

View File

@ -43,6 +43,21 @@ class TestLoadHeaderNotIPluginHeaderHeader
return "TestLoadHeaderNotIPluginHeader";
}
public function getClassesPrefix(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestLoadHeaderNotIPluginHeader';
}
public function getSourceDirectory(): ?string
{
return '';
}
public function getPluginClass(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestLoadHeaderNotIPluginHeader\TestLoadPlugin';
}
public function init()
{
}

View File

@ -33,7 +33,7 @@
*
* @version Version 1.2.0
*/
namespace Application\Plugin;
namespace FuzeWorks\UnitTest\Plugins\TestLoadPlugin;
class TestLoadPlugin
{

View File

@ -44,6 +44,21 @@ class TestLoadPluginHeader implements iPluginHeader
return "TestLoadPlugin";
}
public function getClassesPrefix(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestLoadPlugin';
}
public function getSourceDirectory(): ?string
{
return '';
}
public function getPluginClass(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestLoadPlugin\TestLoadPlugin';
}
public function init()
{
}

View File

@ -44,6 +44,21 @@ class TestMissingPluginHeader implements iPluginHeader
return "TestMissingPlugin";
}
public function getClassesPrefix(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestMissingPlugin';
}
public function getSourceDirectory(): ?string
{
return '';
}
public function getPluginClass(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestMissingPluginHeader\TestMissingPlugin';
}
public function init()
{
}

View File

@ -33,7 +33,7 @@
*
* @version Version 1.2.0
*/
namespace Application\Plugin;
namespace FuzeWorks\UnitTest\Plugins\TestReloadPlugin;
class TestReloadPlugin
{

View File

@ -44,6 +44,21 @@ class TestReloadPluginHeader implements iPluginHeader
return "TestReloadPlugin";
}
public function getClassesPrefix(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestReloadPlugin';
}
public function getSourceDirectory(): ?string
{
return '';
}
public function getPluginClass(): ?string
{
return '\FuzeWorks\UnitTest\Plugins\TestReloadPlugin\TestReloadPlugin';
}
public function init()
{
}