diff --git a/app/apis/RoutingTestClass.php b/app/apis/RoutingTestClass.php
index 93bab031..6b9f7822 100644
--- a/app/apis/RoutingTestClass.php
+++ b/app/apis/RoutingTestClass.php
@@ -1,5 +1,4 @@
@@ -28,12 +28,6 @@ public function __construct() {
'two-group',
]);
}
- /**
- * Execute a set of instructions before accessing the application.
- */
- public function before(Request $request, Response $response) {
- //TODO: Implement the action to perform before processing the request.
- }
/**
* Execute a set of instructions after processing the request and before sending back the response.
*/
@@ -46,4 +40,10 @@ public function after(Request $request, Response $response) {
public function afterSend(Request $request, Response $response) {
//TODO: Implement the action to perform after sending the request.
}
+ /**
+ * Execute a set of instructions before accessing the application.
+ */
+ public function before(Request $request, Response $response) {
+ //TODO: Implement the action to perform before processing the request.
+ }
}
diff --git a/app/tasks/Fail1TestTask.php b/app/tasks/Fail1TestTask.php
index ab1869dd..dd0b326a 100644
--- a/app/tasks/Fail1TestTask.php
+++ b/app/tasks/Fail1TestTask.php
@@ -42,6 +42,7 @@ public function afterExec() {
*/
public function execute() {
TasksManager::logInfo('Task '.$this->getTaskName().' Is executing...');
+
return false;
}
/**
diff --git a/php_cs.php.dist b/php_cs.php.dist
index 346f35e1..3c2e444c 100644
--- a/php_cs.php.dist
+++ b/php_cs.php.dist
@@ -24,7 +24,6 @@ return $config->setRules([
],
'indentation_type' => true,
'method_chaining_indentation' => true,
- 'statement_indentation' => true,
'no_trailing_whitespace' => true,
'no_trailing_whitespace_in_comment' => true,
'blank_line_after_opening_tag' => true,
diff --git a/webfiori/framework/App.php b/webfiori/framework/App.php
index 28e1aed9..a024dbd2 100644
--- a/webfiori/framework/App.php
+++ b/webfiori/framework/App.php
@@ -417,6 +417,15 @@ private static function autoRegisterHelper($options) {
} catch (Error $ex) {
}
}
+ private static function call($func) {
+ try {
+ call_user_func($func);
+ } catch (Exception $ex) {
+ if (self::getRunner()->isCLI()) {
+ printf("WARNING: ".$ex->getMessage().' at '.$ex->getFile().':'.$ex->getLine()."\n");
+ }
+ }
+ }
private function checkAppDir() {
if (!defined('DS')) {
/**
@@ -577,15 +586,6 @@ private function initMiddleware() {
}
self::call(APP_DIR.'\ini\InitMiddleware::init');
}
- private static function call($func) {
- try {
- call_user_func($func);
- } catch (Exception $ex) {
- if (self::getRunner()->isCLI()) {
- printf("WARNING: ".$ex->getMessage().' at '.$ex->getFile().':'.$ex->getLine()."\n");
- }
- }
- }
/**
* @throws FileException
*/
diff --git a/webfiori/framework/ThemeLoader.php b/webfiori/framework/ThemeLoader.php
index e78e519d..7ae18ffd 100644
--- a/webfiori/framework/ThemeLoader.php
+++ b/webfiori/framework/ThemeLoader.php
@@ -10,16 +10,16 @@
*/
namespace webfiori\framework;
+use const DS;
use Error;
use Exception;
+use const ROOT_PATH;
+use const THEMES_PATH;
use webfiori\file\File;
use webfiori\framework\exceptions\InitializationException;
use webfiori\framework\exceptions\NoSuchThemeException;
use webfiori\framework\router\Router;
use webfiori\http\Response;
-use const DS;
-use const ROOT_PATH;
-use const THEMES_PATH;
/**
diff --git a/webfiori/framework/autoload/ClassInfo.php b/webfiori/framework/autoload/ClassInfo.php
index 394d3671..a54da9ff 100644
--- a/webfiori/framework/autoload/ClassInfo.php
+++ b/webfiori/framework/autoload/ClassInfo.php
@@ -9,11 +9,16 @@
*
*/
namespace webfiori\framework\autoload;
+
/**
* A class that contains the names of indices that are used by loaded class info array.
*
*/
class ClassInfo {
+ /**
+ * A constant that represents the value 'cached' of class.
+ */
+ const CACHED = 'loaded-from-cache';
/**
* A constant that represents the value 'name' of class.
*/
@@ -26,8 +31,4 @@ class ClassInfo {
* A constant that represents the value 'path' of class.
*/
const PATH = 'path';
- /**
- * A constant that represents the value 'cached' of class.
- */
- const CACHED = 'loaded-from-cache';
}
diff --git a/webfiori/framework/autoload/ClassLoader.php b/webfiori/framework/autoload/ClassLoader.php
index ab51106a..3a55cc04 100644
--- a/webfiori/framework/autoload/ClassLoader.php
+++ b/webfiori/framework/autoload/ClassLoader.php
@@ -16,23 +16,17 @@
*
* The class aims to provide all needed utilities to autoload any classes
* which are within the scope of the framework. In addition, the developer
- * can add his own custom folders to the autoloader. More to that, the autoloader
- * will load any class which exist in the folder 'vendor' if composer
- * is used to collect the dependencies. To activate this feature, the constant
- * 'LOAD_COMPOSER_PACKAGES' must be defined and set to true. The class can be used independent of
- * any other component to load classes.
+ * can add his own custom folders to the autoloader.
*
* @author Ibrahim
*
- * @version 1.1.7
*/
class ClassLoader {
/**
* The name of the file that represents autoloader's cache.
* @var string
- * @since 1.1.6
*/
- const CACHE_NAME = 'autoload.cache';
+ const CACHE_NAME = 'class-loader.cache';
/**
* An array that contains the possible things that can be performed
* if a class has failed to load.
@@ -41,7 +35,6 @@ class ClassLoader {
*
throw-exception,
* do-nothing
*
- * @since 1.1.6
*/
const ON_FAIL_ACTIONS = [
'throw-exception',
@@ -54,7 +47,6 @@ class ClassLoader {
*
* @var array
*
- * @since 1.1.6
*/
private $cacheArr;
/**
@@ -62,7 +54,6 @@ class ClassLoader {
*
* @var array
*
- * @since 1.1.4
*/
private $loadedClasses;
/**
@@ -70,7 +61,6 @@ class ClassLoader {
*
* @var ClassLoader
*
- * @since 1.0
*/
private static $loader;
/**
@@ -79,7 +69,6 @@ class ClassLoader {
*
* @var string|callable
*
- * @since 1.1.3
*/
private $onFail;
/**
@@ -87,7 +76,6 @@ class ClassLoader {
*
* @var string
*
- * @since 1.0
*/
private $rootDir;
/**
@@ -95,7 +83,6 @@ class ClassLoader {
*
* @var array
*
- * @since 1.0
*/
private $searchFolders;
@@ -107,7 +94,6 @@ class ClassLoader {
* @param string $onFail
* @throws ClassLoaderException
* @throws Exception
- * @since 1.0
*/
private function __construct(string $root = '', array $searchFolders = [], bool $defineRoot = false, string $onFail = self::ON_FAIL_ACTIONS[0]) {
$this->searchFolders = [];
@@ -115,6 +101,7 @@ private function __construct(string $root = '', array $searchFolders = [], bool
$this->loadedClasses = [];
require_once 'ClassLoaderException.php';
require_once 'ClassInfo.php';
+
if (defined('ROOT_PATH')) {
$this->rootDir = ROOT_PATH;
} else if (strlen($root) != 0 && is_dir($root)) {
@@ -169,6 +156,43 @@ private function __construct(string $root = '', array $searchFolders = [], bool
ClassInfo::CACHED => false
];
}
+ /**
+ * Load a class using its specified path.
+ *
+ * This method can be used in case the class that the user tries to load does
+ * not comply with PSR-4 standard for placing classes in correct folder
+ * with correct namespace. Once loaded, it will be added to the cache.
+ *
+ * @param string $className The name of the class that will be loaded.
+ *
+ * @param string $classWithNs The full name of the class including its namespace.
+ *
+ * @param string $path The path to PHP file that has class implementation.
+ *
+ * @return bool If file is exist and class is loaded, true is returned. False
+ * otherwise.
+ */
+ public function addClassMap(string $className, string $classWithNs, string $path) : bool {
+ $ns = count(explode('\\', $classWithNs)) == 1 ? '\\' : substr($classWithNs, 0, strlen($classWithNs) - strlen($className) - 1);
+
+ if ($this->loadFromCache($ns, $className)) {
+ return true;
+ }
+
+ if (!file_exists($path)) {
+ return false;
+ }
+ require_once $path;
+
+ $this->loadedClasses[] = [
+ ClassInfo::NAME => $className,
+ ClassInfo::NS => $ns,
+ ClassInfo::PATH => $path,
+ ClassInfo::CACHED => false
+ ];
+
+ return true;
+ }
/**
* Returns a single instance of the class 'ClassLoader'.
*
@@ -247,7 +271,6 @@ public static function get(array $options = [
return self::$loader;
}
-
/**
* Returns an array that contains all cached classes information.
*
@@ -257,7 +280,6 @@ public static function get(array $options = [
*
* @return array An array that contains all cached classes information.
* @throws Exception
- * @since 1.1.7
*/
public static function getCacheArray(): array {
return self::get()->cacheArr;
@@ -295,7 +317,6 @@ public static function getCachePath() : string {
* @throws Exception
* loaded.
*
- * @since 1.0
*/
public static function getClassPath(string $className, string $namespace = null, bool $load = false): array {
$retVal = [];
@@ -328,7 +349,6 @@ public static function getClassPath(string $className, string $namespace = null,
* @return array An array of all added search folders.
*
* @throws Exception
- * @since 1.1.1
*/
public static function getFolders(): array {
$folders = [];
@@ -358,7 +378,6 @@ public static function getFolders(): array {
* @return array An associative array that contains loaded classes info.
*
* @throws Exception
- * @since 1.1.4
*/
public static function getLoadedClasses(): array {
return self::get()->loadedClasses;
@@ -377,7 +396,6 @@ public static function getLoadedClasses(): array {
* Else, it will return false.
*
* @throws Exception
- * @since 1.1.5
*/
public static function isLoaded(string $class, string $ns = null): bool {
foreach (self::getLoadedClasses() as $classArr) {
@@ -393,6 +411,73 @@ public static function isLoaded(string $class, string $ns = null): bool {
return false;
}
+ /**
+ * Checks if provided string represents a valid namespace or not.
+ *
+ * @param string $ns A string to be validated.
+ *
+ * @return bool If the provided string represents a valid namespace, the
+ * method will return true. False if it does not represent a valid namespace.
+ */
+ public static function isValidNamespace(string $ns) {
+ if ($ns == '\\') {
+ return true;
+ }
+ $split = explode('\\', $ns);
+
+ foreach ($split as $subNs) {
+ $len = strlen($subNs);
+
+ for ($x = 0 ; $x < $len ; $x++) {
+ $char = $subNs[$x];
+
+ if ($x == 0 && $char >= '0' && $char <= '9') {
+ return false;
+ }
+
+ if (!(($char <= 'Z' && $char >= 'A') || ($char <= 'z' && $char >= 'a') || ($char >= '0' && $char <= '9') || $char == '_')) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+ /**
+ * Load a class using its specified path.
+ *
+ * This method can be used in case the class that the user tries to load does
+ * not comply with PSR-4 standard for placing classes in correct folder
+ * with correct namespace. Once loaded, it will be added to the cache.
+ *
+ * @param string $className The name of the class that will be loaded.
+ *
+ * @param string $classWithNs The full name of the class including its namespace.
+ *
+ * @param string $filePath The path to PHP file that has class implementation.
+ *
+ * @return bool If file is exist and class is loaded, true is returned. False
+ * otherwise.
+ */
+ public static function map(string $className, string $classWithNs, string $filePath) {
+ self::get()->addClassMap($className, $classWithNs, $filePath);
+ }
+ /**
+ * Load multiple classes from same path which belongs to same namespace.
+ *
+ * This helper method can be used to autoload classes which are non-PSR-4 compliant.
+ *
+ * @param string $ns The namespace at which classes belongs to.
+ *
+ * @param string $path The location at which all classes stored at.
+ *
+ * @param array $classes An array that holds the names of the classes.
+ */
+ public static function mapAll(string $ns, string $path, array $classes) {
+ foreach ($classes as $className) {
+ self::map($className, $ns.'\\'.$className, $path.DIRECTORY_SEPARATOR.$className.'.php');
+ }
+ }
/**
* Adds new folder to the set folder at which the autoloader will try to search
@@ -405,7 +490,6 @@ public static function isLoaded(string $class, string $ns = null): bool {
* are inside the given directory will be included in the search.
*
* @throws Exception
- * @since 1.1.2
*/
public static function newSearchFolder(string $dir, bool $incSubFolders = true) {
self::get()->addSearchDirectory($dir,$incSubFolders);
@@ -417,7 +501,6 @@ public static function newSearchFolder(string $dir, bool $incSubFolders = true)
* @return string The root directory that is used to search inside.
*
* @throws Exception
- * @since 1.1.5
*/
public static function root(): string {
return self::get()->getRoot();
@@ -434,7 +517,6 @@ public static function root(): string {
*
*
* @throws Exception
- * @since 1.1.5
*/
public static function setOnFail($onFail) {
if (is_callable($onFail)) {
@@ -459,7 +541,6 @@ public static function setOnFail($onFail) {
* @param string $appendRoot If set to true, Root directory of the search will
* be added as a prefix to the path.
*
- * @since 1.0
*
* @deprecated since version 1.1.2
*/
@@ -530,13 +611,44 @@ private static function checkComposer() {
self::$loader->addSearchDirectory($vendorFolder, true, false);
}
}
+ private function createNSFromPath(string $filePath, string $className) {
+ $split = explode(DIRECTORY_SEPARATOR, $filePath);
+ $nsArr = ['\\'.$className];
+ $currentNs = '';
+
+ foreach ($split as $str) {
+ if (self::isValidNamespace($str)) {
+ if (strlen($currentNs) == 0) {
+ $currentNs = '\\'.$str;
+ } else {
+ $currentNs = $currentNs.'\\'.$str;
+ }
+ $nsArr[] = $currentNs.'\\'.$className;
+ }
+ }
+ $currentNs = '';
+
+ for ($x = count($split) - 1 ; $x > -1 ; $x--) {
+ $str = $split[$x];
+
+ if (self::isValidNamespace($str)) {
+ if (strlen($currentNs) == 0) {
+ $currentNs = '\\'.$str;
+ } else {
+ $currentNs = '\\'.$str.$currentNs;
+ }
+ $nsArr[] = $currentNs.'\\'.$className;
+ }
+ }
+
+ return $nsArr;
+ }
/**
* Returns an array string that contains all possible paths for the folder
* 'vendor'.
*
* @return array
*
- * @since 1.1.6
*/
private static function getComposerVendorDirs(): array {
$DS = DIRECTORY_SEPARATOR;
@@ -570,7 +682,6 @@ private static function getComposerVendorDirs(): array {
*
* @return string The root directory that is used to search inside.
*
- * @since 1.0
*/
private function getRoot(): string {
return $this->rootDir;
@@ -583,7 +694,6 @@ private function getRoot(): string {
*
* @throws ClassLoaderException
* @throws Exception
- * @since 1.0
*/
private function loadClass(string $classWithNs) {
$cArr = explode('\\', $classWithNs);
@@ -642,7 +752,7 @@ private function loadClassHelper(string $className, string $classWithNs, string
if (!$isFileLoaded && file_exists($f)) {
$nsFromPath = $this->createNSFromPath($f, $className);
-
+
if (in_array('\\'.$classWithNs, $nsFromPath)) {
require_once $f;
$ns = count(explode('\\', $classWithNs)) == 1 ? '\\' : substr($classWithNs, 0, strlen($classWithNs) - strlen($className) - 1);
@@ -658,68 +768,6 @@ private function loadClassHelper(string $className, string $classWithNs, string
return $loaded;
}
- /**
- * Checks if provided string represents a valid namespace or not.
- *
- * @param string $ns A string to be validated.
- *
- * @return bool If the provided string represents a valid namespace, the
- * method will return true. False if it does not represent a valid namespace.
- */
- public static function isValidNamespace(string $ns) {
- if ($ns == '\\') {
- return true;
- }
- $split = explode('\\', $ns);
-
- foreach ($split as $subNs) {
- $len = strlen($subNs);
-
- for ($x = 0 ; $x < $len ; $x++) {
- $char = $subNs[$x];
-
- if ($x == 0 && $char >= '0' && $char <= '9') {
- return false;
- }
-
- if (!(($char <= 'Z' && $char >= 'A') || ($char <= 'z' && $char >= 'a') || ($char >= '0' && $char <= '9') || $char == '_')) {
- return false;
- }
- }
- }
-
- return true;
- }
- private function createNSFromPath(string $filePath, string $className) {
- $split = explode(DIRECTORY_SEPARATOR, $filePath);
- $nsArr = ['\\'.$className];
- $currentNs = '';
- foreach ($split as $str) {
- if (self::isValidNamespace($str)) {
- if (strlen($currentNs) == 0) {
- $currentNs = '\\'.$str;
- } else {
- $currentNs = $currentNs.'\\'.$str;
- }
- $nsArr[] = $currentNs.'\\'.$className;
- }
-
- }
- $currentNs = '';
- for ($x = count($split) - 1 ; $x > -1 ; $x--) {
- $str = $split[$x];
- if (self::isValidNamespace($str)) {
- if (strlen($currentNs) == 0) {
- $currentNs = '\\'.$str;
- } else {
- $currentNs = '\\'.$str.$currentNs;
- }
- $nsArr[] = $currentNs.'\\'.$className;
- }
-
- }
- return $nsArr;
- }
private function loadFromCache($classNS, $className): bool {
$loaded = false;
@@ -766,7 +814,6 @@ private function parseCacheString($str) {
/**
* Read the file which contains autoloader cached content.
*
- * @since 1.1.6
*/
private function readCache() {
$autoloadCachePath = $this->getRoot().DIRECTORY_SEPARATOR.APP_DIR.DIRECTORY_SEPARATOR.'sto';
@@ -786,7 +833,6 @@ private function readCache() {
* This method is called every time a new class is loaded to update the cache.
*
* @throws Exception
- * @since 1.1.6
*/
private function updateCacheHelper() {
$autoloadCache = self::getCachePath();
diff --git a/webfiori/framework/cli/commands/ListThemesCommand.php b/webfiori/framework/cli/commands/ListThemesCommand.php
index 53e42386..72c8376d 100644
--- a/webfiori/framework/cli/commands/ListThemesCommand.php
+++ b/webfiori/framework/cli/commands/ListThemesCommand.php
@@ -10,8 +10,8 @@
*/
namespace webfiori\framework\cli\commands;
-use webfiori\cli\CLICommand;
use webfiori\cli\Argument;
+use webfiori\cli\CLICommand;
use webfiori\framework\ThemeLoader;
/**
diff --git a/webfiori/framework/cli/commands/RunSQLQueryCommand.php b/webfiori/framework/cli/commands/RunSQLQueryCommand.php
index 34810332..59a9321a 100644
--- a/webfiori/framework/cli/commands/RunSQLQueryCommand.php
+++ b/webfiori/framework/cli/commands/RunSQLQueryCommand.php
@@ -10,8 +10,8 @@
*/
namespace webfiori\framework\cli\commands;
-use webfiori\cli\CLICommand;
use webfiori\cli\Argument;
+use webfiori\cli\CLICommand;
use webfiori\database\Database;
use webfiori\database\DatabaseException;
use webfiori\database\Table;
@@ -122,15 +122,15 @@ private function connectionBased($dbConnections) : int {
if ($file !== null) {
$fileObj = new File(ROOT_PATH.DS.$file);
-
+
if (!$fileObj->isExist()) {
$fileObj = new File($file);
}
-
+
if ($fileObj->isExist()) {
$fileObj->read();
$mime = $fileObj->getMIME();
-
+
if ($mime == 'application/sql' || $mime == 'application/x-sql') {
return $this->runFileQuery($schema, $fileObj);
} else {
@@ -211,7 +211,7 @@ private function queryFromFile($schema) {
while (!File::isFileExist($filePath)) {
$filePath = $this->getInput('File path:');
$modified = ROOT_PATH.DS.$filePath;
-
+
if (File::isFileExist($modified)) {
$filePath = $modified;
}
@@ -233,7 +233,7 @@ private function queryFromFile($schema) {
return $this->runFileQuery($schema, $file);
}
-
+
private function queryOnSchema(DB $schema) {
if ($this->isArgProvided('--create')) {
$schema->createTables();
diff --git a/webfiori/framework/cli/commands/SchedulerCommand.php b/webfiori/framework/cli/commands/SchedulerCommand.php
index cd8291d5..e62e5df7 100644
--- a/webfiori/framework/cli/commands/SchedulerCommand.php
+++ b/webfiori/framework/cli/commands/SchedulerCommand.php
@@ -10,8 +10,8 @@
*/
namespace webfiori\framework\cli\commands;
-use webfiori\cli\CLICommand;
use webfiori\cli\Argument;
+use webfiori\cli\CLICommand;
use webfiori\framework\scheduler\AbstractTask;
use webfiori\framework\scheduler\TasksManager;
/**
@@ -111,7 +111,7 @@ public function listTasks() {
}
private function checkTaskArgs($taskName) {
$task = TasksManager::getTask($taskName);
-
+
if ($task === null) {
return;
}
diff --git a/webfiori/framework/cli/commands/UpdateSettingsCommand.php b/webfiori/framework/cli/commands/UpdateSettingsCommand.php
index dde9ee0b..be850b02 100644
--- a/webfiori/framework/cli/commands/UpdateSettingsCommand.php
+++ b/webfiori/framework/cli/commands/UpdateSettingsCommand.php
@@ -11,8 +11,8 @@
namespace webfiori\framework\cli\commands;
use Throwable;
-use webfiori\cli\CLICommand;
use webfiori\cli\Argument;
+use webfiori\cli\CLICommand;
use webfiori\cli\InputValidator;
use webfiori\framework\App;
use webfiori\framework\config\Controller;
@@ -104,6 +104,7 @@ private function getThemeNs() {
if ($instance instanceof Theme) {
return true;
}
+
return false;
} catch (Throwable $exc) {
return false;
diff --git a/webfiori/framework/cli/commands/UpdateTableCommand.php b/webfiori/framework/cli/commands/UpdateTableCommand.php
index 50d8f392..8bfb30a7 100644
--- a/webfiori/framework/cli/commands/UpdateTableCommand.php
+++ b/webfiori/framework/cli/commands/UpdateTableCommand.php
@@ -10,8 +10,8 @@
*/
namespace webfiori\framework\cli\commands;
-use webfiori\cli\CLICommand;
use webfiori\cli\Argument;
+use webfiori\cli\CLICommand;
use webfiori\framework\cli\CLIUtils;
use webfiori\framework\cli\helpers\CreateTableObj;
use webfiori\framework\cli\helpers\TableObjHelper;
diff --git a/webfiori/framework/cli/helpers/CreateAPITestCase.php b/webfiori/framework/cli/helpers/CreateAPITestCase.php
index 7a83e604..1fea484b 100644
--- a/webfiori/framework/cli/helpers/CreateAPITestCase.php
+++ b/webfiori/framework/cli/helpers/CreateAPITestCase.php
@@ -42,16 +42,16 @@ public function readClassInfo() {
array_pop($nsArr);
$ns = implode('\\', $nsArr);
$this->setClassName($this->writer->getServiceName().'Test');
- $this->setNamespace('tests\\'. $ns);
- $this->setPath(ROOT_PATH.DS.'tests'.DS. implode(DS, $nsArr));
-
+ $this->setNamespace('tests\\'.$ns);
+ $this->setPath(ROOT_PATH.DS.'tests'.DS.implode(DS, $nsArr));
+
if ($this->getCommand()->isArgProvided('--defaults')) {
$this->writeClass();
} else {
-
$this->checkPlace($ns);
}
+
return true;
}
private function checkPlace($ns) {
@@ -60,7 +60,7 @@ private function checkPlace($ns) {
$this->println("Name: ".$this->getWriter()->getName(true));
$this->println("Path: ".$this->getWriter()->getPath());
$confrm = $this->confirm('Would you like to use default parameters?', true);
-
+
if ($confrm) {
$this->writeClass();
} else {
@@ -69,57 +69,64 @@ private function checkPlace($ns) {
$this->writeClass();
}
}
- private function readServiceInfo() {
- $selected = $this->getCommand()->getArgValue('--service');
- $services = $this->writer->getServicesManager()->getServices();
- if ($selected !== null) {
- if (!isset($services[$selected])) {
- $this->info('Selected services manager has no service with name \''.$selected.'\'.');
- } else {
- $this->writer->setService($services[$selected]);
- return;
- }
- }
- if (count($services) == 0) {
- $this->info('Provided services manager has 0 registered services.');
- return;
- }
- $selected = $this->select('Which service you would like to have a test case for?', array_keys($services));
- $this->writer->setService($services[$selected]);
- }
private function readManagerInfo() {
$m = $this->getCommand()->getArgValue('--manager');
$instance = null;
-
+
if ($m !== null) {
if (class_exists($m)) {
$instance = new $m();
if ($instance instanceof WebServicesManager) {
$this->writer->setServicesManager($instance);
+
return true;
} else {
$this->error("The argument --manager has invalid value.");
+
return false;
}
} else {
$this->error("The argument --manager has invalid value.");
+
return false;
}
}
+
if ($instance === null) {
while (!($instance instanceof WebServicesManager)) {
$instance = $this->getCommand()->readInstance('Please enter services manager information:');
-
+
if (!($instance instanceof WebServicesManager)) {
$this->error('Provided class is not an instance of '.WebServicesManager::class);
} else {
$this->writer->setServicesManager($instance);
+
return true;
}
}
-
}
}
+ private function readServiceInfo() {
+ $selected = $this->getCommand()->getArgValue('--service');
+ $services = $this->writer->getServicesManager()->getServices();
+
+ if ($selected !== null) {
+ if (!isset($services[$selected])) {
+ $this->info('Selected services manager has no service with name \''.$selected.'\'.');
+ } else {
+ $this->writer->setService($services[$selected]);
+ return;
+ }
+ }
+
+ if (count($services) == 0) {
+ $this->info('Provided services manager has 0 registered services.');
+
+ return;
+ }
+ $selected = $this->select('Which service you would like to have a test case for?', array_keys($services));
+ $this->writer->setService($services[$selected]);
+ }
}
diff --git a/webfiori/framework/cli/helpers/CreateCLIClassHelper.php b/webfiori/framework/cli/helpers/CreateCLIClassHelper.php
index 72a9caa4..a6f83e1f 100644
--- a/webfiori/framework/cli/helpers/CreateCLIClassHelper.php
+++ b/webfiori/framework/cli/helpers/CreateCLIClassHelper.php
@@ -63,6 +63,7 @@ private function getArgs() : array {
continue;
}
$argObj->setDescription($this->getInput('Describe this argument and how to use it:', ''));
+
foreach ($this->getFixedValues() as $v) {
$argObj->addAllowedValue($v);
}
diff --git a/webfiori/framework/cli/helpers/CreateClassHelper.php b/webfiori/framework/cli/helpers/CreateClassHelper.php
index 71e0613a..aad7e229 100644
--- a/webfiori/framework/cli/helpers/CreateClassHelper.php
+++ b/webfiori/framework/cli/helpers/CreateClassHelper.php
@@ -204,7 +204,7 @@ public function select($prompt, $choices, $defaultIndex = -1) {
public function setClassInfo(string $ns, string $suffix) {
$classInfo = $this->getClassInfo($ns, $suffix);
$this->setNamespace($classInfo['namespace']);
-
+
if ($suffix != $classInfo['name']) {
$this->setClassName($classInfo['name']);
}
@@ -232,14 +232,14 @@ public function setClassName(string $name) : bool {
public function setNamespace($ns) : bool {
return $this->getWriter()->setNamespace($ns);
}
- /**
- * Sets the location at which the class will be created on.
- *
- * @param string $path A string that represents folder path.
- *
- * @return boolean If the path is successfully set, the method will return true.
- * Other than that, false is returned.
- */
+ /**
+ * Sets the location at which the class will be created on.
+ *
+ * @param string $path A string that represents folder path.
+ *
+ * @return boolean If the path is successfully set, the method will return true.
+ * Other than that, false is returned.
+ */
public function setPath(string $path): bool {
return $this->getWriter()->setPath($path);
}
diff --git a/webfiori/framework/config/Controller.php b/webfiori/framework/config/Controller.php
index 4b5dcaaf..843e81c5 100644
--- a/webfiori/framework/config/Controller.php
+++ b/webfiori/framework/config/Controller.php
@@ -14,7 +14,7 @@
class Controller {
const NL = "\n";
/**
- *
+ *
* @var ConfigurationDriver
*/
private $driver;
@@ -27,20 +27,13 @@ public function __construct() {
$this->driver = new $driverClazz();
$this->init($this->driver);
}
- private static function init(ConfigurationDriver $driver, bool $reCreate = false) {
- try {
- $driver->initialize($reCreate);
- } catch (Exception $ex) {
- throw new InitializationException('Unable to initialize configuration driver due to an error: '.$ex->getMessage(), $ex->getCode(), $ex);
- }
- }
/**
* Adds new environment variable to the configuration of the app.
- *
+ *
* @param string $name The name of the variable such as 'MY_VAR'.
- *
+ *
* @param mixed $value The value of the variable.
- *
+ *
* @param string|null $description An optional text that describes the variable.
*/
public function addEnvVar(string $name, $value, string $description = null) {
@@ -77,7 +70,6 @@ public function copy(ConfigurationDriver $new) {
}
foreach ($current->getEnvVars() as $name => $probs) {
-
$new->addEnvVar($name, $probs['value'], $probs['description']);
}
$new->setPrimaryLanguage($current->getPrimaryLanguage());
@@ -136,4 +128,11 @@ public static function updateEnv() {
}
}
}
+ private static function init(ConfigurationDriver $driver, bool $reCreate = false) {
+ try {
+ $driver->initialize($reCreate);
+ } catch (Exception $ex) {
+ throw new InitializationException('Unable to initialize configuration driver due to an error: '.$ex->getMessage(), $ex->getCode(), $ex);
+ }
+ }
}
diff --git a/webfiori/framework/config/JsonDriver.php b/webfiori/framework/config/JsonDriver.php
index 6b908147..bd56c043 100644
--- a/webfiori/framework/config/JsonDriver.php
+++ b/webfiori/framework/config/JsonDriver.php
@@ -123,9 +123,9 @@ public function addOrUpdateSMTPAccount(SMTPAccount $emailAccount) {
}
/**
* Returns the name of the application in specific display language.
- *
+ *
* @param string $langCode Language code such as 'AR'.
- *
+ *
* @return string|null Application name or null if language code does not
* exist.
*/
@@ -332,12 +332,11 @@ public function getPrimaryLanguage(): string {
*/
public function getSchedulerPassword(): string {
$pass = $this->json->get('scheduler-password') ?? 'NO_PASSWORD';
-
+
if (strlen($pass.'') == 0 || $pass == 'NO_PASSWORD') {
-
return 'NO_PASSWORD';
}
-
+
return $pass;
}
/**
@@ -383,7 +382,7 @@ public function getSMTPConnections(): array {
$jsonObj = $prop->getValue();
$acc = new SMTPAccount();
$acc->setAccountName($name);
-
+
$acc->setAddress($this->getProp($jsonObj, 'address', $name));
$acc->setPassword($this->getProp($jsonObj, 'password', $name));
$acc->setPort($this->getProp($jsonObj, 'port', $name));
@@ -398,7 +397,7 @@ public function getSMTPConnections(): array {
/**
* Returns the name or the namespace of default theme that the application
* will use in case a page does not have specific theme.
- *
+ *
* @return string
*/
public function getTheme(): string {
@@ -459,10 +458,10 @@ public function getTitleSeparator(): string {
}
/**
* Creates application configuration file.
- *
+ *
* This method will attempt to create a JSON configuration file in the folder
* 'config' of the application.
- *
+ *
* @param bool $reCreate If this parameter is set to true and there already a configuration
* file with same name, it will be overriden.
*/
@@ -476,7 +475,7 @@ public function initialize(bool $reCreate = false) {
}
/**
* Deletes configuration file.
- *
+ *
* Note that in order to remove specific configuration file, its name must
* be set using the method JsonDriver::setConfigFileName()
*/
@@ -488,20 +487,26 @@ public function removeAllDBConnections() {
$this->json->add('database-connections', new Json([], 'none', 'same'));
$this->writeJson();
}
+ /**
+ * Removes all added SMTP connections.
+ */
+ public function removeAllSMTPAccounts() {
+ $this->json->add('smtp-connections', new Json([], 'none', 'same'));
+ $this->writeJson();
+ }
public function removeDBConnection(string $connectionName) {
$connections = $this->getDBConnections();
$accountNameTrimmed = trim($connectionName);
$toAdd = [];
-
+
foreach ($connections as $connection) {
-
if ($connection->getName() != $accountNameTrimmed) {
$toAdd[] = $connection;
}
}
$this->removeAllDBConnections();
-
+
foreach ($toAdd as $account) {
$this->addOrUpdateDBConnection($account);
}
@@ -515,31 +520,23 @@ public function removeEnvVar(string $name) {
$this->json->get('env-vars')->remove($name);
$this->writeJson();
}
- /**
- * Removes all added SMTP connections.
- */
- public function removeAllSMTPAccounts() {
- $this->json->add('smtp-connections', new Json([], 'none', 'same'));
- $this->writeJson();
- }
/**
* Removes specific SMTP connection from the configuration given its name.
- *
+ *
* @param string $accountName The name of the connection.
*/
public function removeSMTPAccount(string $accountName) {
$connections = $this->getSMTPConnections();
$accountNameTrimmed = trim($accountName);
$toAdd = [];
-
+
foreach ($connections as $connection) {
-
if ($connection->getAccountName() != $accountNameTrimmed) {
$toAdd[] = $connection;
}
}
$this->removeAllSMTPAccounts();
-
+
foreach ($toAdd as $account) {
$this->addOrUpdateSMTPAccount($account);
}
@@ -582,14 +579,14 @@ public function setAppVersion(string $vNum, string $vType, string $releaseDate)
}
/**
* Sets the base URL of the application.
- *
+ *
* This is usually used in fetching resources.
- *
+ *
* @param string $url
*/
public function setBaseURL(string $url) {
$trim = trim($url);
-
+
if (strlen($trim) == 0) {
$this->json->add('base-url', 'DYNAMIC');
} else {
@@ -640,9 +637,9 @@ public function setDescription(string $description, string $langCode) {
*/
public function setHomePage(string $url) {
$trim = trim($url);
-
+
if (strlen($trim) == 0) {
- $this->json->add('home-page', 'BASE_URL');
+ $this->json->add('home-page', 'BASE_URL');
} else {
$this->json->add('home-page', $trim);
}
diff --git a/webfiori/framework/handlers/APICallErrHandler.php b/webfiori/framework/handlers/APICallErrHandler.php
index 852f53c7..0acd6b41 100644
--- a/webfiori/framework/handlers/APICallErrHandler.php
+++ b/webfiori/framework/handlers/APICallErrHandler.php
@@ -33,7 +33,6 @@ class APICallErrHandler extends AbstractHandler {
public function __construct() {
parent::__construct();
$this->setName('API Call Errors Handler');
-
}
/**
* Handles the exception
diff --git a/webfiori/framework/handlers/CLIErrHandler.php b/webfiori/framework/handlers/CLIErrHandler.php
index 96e01ef7..a98de53f 100644
--- a/webfiori/framework/handlers/CLIErrHandler.php
+++ b/webfiori/framework/handlers/CLIErrHandler.php
@@ -17,8 +17,8 @@
use webfiori\framework\scheduler\TasksManager;
/**
* Exceptions handler which is used to handle exceptions in case of running
- * CLI applications.
- *
+ * CLI applications.
+ *
* The priority of the handler
* is set to 0 which indicates that it will be executed last.
*
diff --git a/webfiori/framework/handlers/HTTPErrHandler.php b/webfiori/framework/handlers/HTTPErrHandler.php
index 8f1a95eb..c080e379 100644
--- a/webfiori/framework/handlers/HTTPErrHandler.php
+++ b/webfiori/framework/handlers/HTTPErrHandler.php
@@ -18,8 +18,8 @@
use webfiori\http\Response;
/**
* Errors and exceptions handler which is used to handle errors in case of
- * HTTP request.
- *
+ * HTTP request.
+ *
* The priority of the handler
* is set to 0 which indicates that it will be executed last.
*
diff --git a/webfiori/framework/router/Router.php b/webfiori/framework/router/Router.php
index 3ce28e03..b8f6a435 100644
--- a/webfiori/framework/router/Router.php
+++ b/webfiori/framework/router/Router.php
@@ -604,6 +604,7 @@ public static function redirect(string $path, string $to, int $code = 301) {
}
Response::addHeader('location', $to);
Response::setCode($httpCode);
+
if (!Runner::isCLI()) {
Response::send();
}
@@ -639,6 +640,7 @@ public static function removeRoute(string $path) : bool {
$pathFix = self::getInstance()->fixUriPath($path);
$retVal = false;
$routes = &self::getInstance()->routes;
+
if (isset($routes['static'][$pathFix])) {
unset($routes['static'][$pathFix]);
diff --git a/webfiori/framework/scheduler/AbstractTask.php b/webfiori/framework/scheduler/AbstractTask.php
index c548cb20..72f1e394 100644
--- a/webfiori/framework/scheduler/AbstractTask.php
+++ b/webfiori/framework/scheduler/AbstractTask.php
@@ -183,7 +183,7 @@ public function __construct(string $taskName = '', string $when = '* * * * *', s
$this->taskDetails['days-of-month'] = [];
$this->taskDetails['months'] = [];
$this->taskDetails['days-of-week'] = [];
-
+
if (!$this->cron($when)) {
@@ -206,7 +206,7 @@ public function __construct(string $taskName = '', string $when = '* * * * *', s
*
* @param string|TaskArgument $nameOrObj The name of the argument. This also can be an
* object of type TaskArgument.
- *
+ *
* @throws InvalidArgumentException If provided argument is not a string or an object of type
* 'TaskArgument'.
*
@@ -353,33 +353,6 @@ public function dailyAt(int $hour = 0, int $minute = 0) : bool {
public function everyHour() {
$this->cron('0 * * * *');
}
- /**
- * Schedules a task to run weekly at specific week day and time.
- *
- * @param int $dayNameOrNum A 3 letter day name (such as 'sun' or 'tue') or a day number from 0 to 6.
- * 0 for sunday. Default is 0.
- *
- * @param string $time A time in the form 'HH:MM'. HH can have any value
- * between 0 and 23 inclusive. MM can have any value between 0 and 59 inclusive.
- * default is '00:00'.
- *
- * @return bool If the time for the task is set, the method will
- * return true. If not, it will return false.
- */
- public function everyWeek($dayNameOrNum = 0, string $time = '00:00') : bool {
- return $this->weeklyOn($dayNameOrNum, $time);
- }
- /**
- * Schedule a task to run every specific number of hours.
- *
- * The expression that will be used is "At minute 0 past every X hour" where
- * x is the number of hours.
- *
- * @param int $xHour The number of hours at which the job will be executed.
- */
- public function everyXHour(int $xHour) {
- $this->cron('0 */'.$xHour.' * * *');
- }
/**
* Schedules a task to run every month on specific day and time.
*
@@ -409,12 +382,39 @@ public function everyMonthOn(int $dayNum = 1, string $time = '00:00') : bool {
return false;
}
+ /**
+ * Schedules a task to run weekly at specific week day and time.
+ *
+ * @param int $dayNameOrNum A 3 letter day name (such as 'sun' or 'tue') or a day number from 0 to 6.
+ * 0 for sunday. Default is 0.
+ *
+ * @param string $time A time in the form 'HH:MM'. HH can have any value
+ * between 0 and 23 inclusive. MM can have any value between 0 and 59 inclusive.
+ * default is '00:00'.
+ *
+ * @return bool If the time for the task is set, the method will
+ * return true. If not, it will return false.
+ */
+ public function everyWeek($dayNameOrNum = 0, string $time = '00:00') : bool {
+ return $this->weeklyOn($dayNameOrNum, $time);
+ }
+ /**
+ * Schedule a task to run every specific number of hours.
+ *
+ * The expression that will be used is "At minute 0 past every X hour" where
+ * x is the number of hours.
+ *
+ * @param int $xHour The number of hours at which the job will be executed.
+ */
+ public function everyXHour(int $xHour) {
+ $this->cron('0 */'.$xHour.' * * *');
+ }
/**
* Schedule a task to run every specific number of minutes.
- *
+ *
* Assuming that 5 is supplied as a value, this means that the job will be
* executed every 5 minutes within an hour.
- *
+ *
* @param int $step The number of minutes that a job will be executed after.
*/
public function everyXMinuts(int $step) {
@@ -1433,7 +1433,7 @@ private function getArgValFromTerminal($name) {
*/
private function getSubExprType(string $expr): string {
$retVal = self::ANY_VAL;
-
+
if ($expr != '*') {
$split0 = explode('/', $expr);
$count = count($split0);
@@ -1463,6 +1463,7 @@ private function getSubExprType(string $expr): string {
if (!(strlen($split0[0]) != 0 && strlen($split0[1]) != 0)) {
return self::INV_VAL;
}
+
return self::STEP_VAL;
}
}
@@ -1541,7 +1542,7 @@ private function logExeException(Throwable $ex, string $meth = '') {
$e = new TraceEntry($firstEntry);
TasksManager::log('#'.$index.' '.$e);
$index++;
-
+
foreach ($trace as $traceEntry) {
$e = new TraceEntry($traceEntry);
TasksManager::log('#'.$index.' '.$e);
diff --git a/webfiori/framework/scheduler/TasksManager.php b/webfiori/framework/scheduler/TasksManager.php
index 3d93fed3..181b0db5 100644
--- a/webfiori/framework/scheduler/TasksManager.php
+++ b/webfiori/framework/scheduler/TasksManager.php
@@ -479,7 +479,7 @@ public static function initRoutes() {
*
* @param string $message A string that act as a log message. It will be
* appended as passed without any changes.
- *
+ *
* @param string $type The type of the message that will be logged. It can
* be one of the following values:
*
@@ -489,7 +489,7 @@ public static function initRoutes() {
* - info
*
* Default is 'none'.
- *
+ *
* @since 1.0.8
*/
public static function log(string $message, string $type = 'none') {
@@ -509,17 +509,17 @@ public static function log(string $message, string $type = 'none') {
}
/**
* Appends a message to the array that contains logged messages.
- *
+ *
* @param string $msg A string that act as a log message. It will be
* appended as passed without any changes. Note that if running in CLI,
- * this will appear as a success message
+ * this will appear as a error message
*/
- public static function logSuccess(string $msg) {
- self::log($msg, 'success');
+ public static function logErr(string $msg) {
+ self::log($msg, 'error');
}
/**
* Appends a message to the array that contains logged messages.
- *
+ *
* @param string $msg A string that act as a log message. It will be
* appended as passed without any changes. Note that if running in CLI,
* this will appear as a info message
@@ -529,13 +529,13 @@ public static function logInfo(string $msg) {
}
/**
* Appends a message to the array that contains logged messages.
- *
+ *
* @param string $msg A string that act as a log message. It will be
* appended as passed without any changes. Note that if running in CLI,
- * this will appear as a error message
+ * this will appear as a success message
*/
- public static function logErr(string $msg) {
- self::log($msg, 'error');
+ public static function logSuccess(string $msg) {
+ self::log($msg, 'success');
}
/**
* Create a task that will be executed once every month.
diff --git a/webfiori/framework/session/SessionDB.php b/webfiori/framework/session/SessionDB.php
index 556a63ee..e1860622 100644
--- a/webfiori/framework/session/SessionDB.php
+++ b/webfiori/framework/session/SessionDB.php
@@ -36,20 +36,6 @@ public function __construct() {
$this->addTable(new MSSQLSessionDataTable());
$this->addTable(new MySQLSessionDataTable());
}
- /**
- * Removes database tables which are used to store session information.
- */
- public function removeTables() {
-
- $this->transaction(function (DB $db) {
- try {
- $db->table('session_data')->drop()->execute();
- $db->table('sessions')->drop()->execute();
- } catch (DatabaseException $ex) {
- return;
- }
- });
- }
/**
* Clears the sessions which are older than the constant 'SESSION_GC' or
* older than 30 days if the constant is not defined.
@@ -168,6 +154,20 @@ public function removeSession(string $sId) {
$this->table('session_data')->delete()->where('s-id', $sId)->execute();
$this->table('sessions')->delete()->where('s-id', $sId)->execute();
}
+ /**
+ * Removes database tables which are used to store session information.
+ */
+ public function removeTables() {
+ $this->transaction(function (DB $db)
+ {
+ try {
+ $db->table('session_data')->drop()->execute();
+ $db->table('sessions')->drop()->execute();
+ } catch (DatabaseException $ex) {
+ return;
+ }
+ });
+ }
/**
* Store session state.
diff --git a/webfiori/framework/session/SessionOption.php b/webfiori/framework/session/SessionOption.php
index aea91495..a7806534 100644
--- a/webfiori/framework/session/SessionOption.php
+++ b/webfiori/framework/session/SessionOption.php
@@ -8,7 +8,6 @@
* https://github.com/WebFiori/.github/blob/main/LICENSE
*
*/
-
namespace webfiori\framework\session;
/**
@@ -22,16 +21,16 @@ class SessionOption {
* An option which is used to set session duration (minutes)
*/
const DURATION = 'duration';
- /**
- * An option which is used to set if session timeout will be refreshed on
- * each request or not (bool)
- */
- const REFRESH = 'refresh';
/**
* An option which is used to set the name of the session. The name will be
* same as session cookie.
*/
const NAME = 'name';
+ /**
+ * An option which is used to set if session timeout will be refreshed on
+ * each request or not (bool)
+ */
+ const REFRESH = 'refresh';
/**
* An option which is used to set the ID of the session.
*/
diff --git a/webfiori/framework/session/SessionStatus.php b/webfiori/framework/session/SessionStatus.php
index 9fca10c0..46003718 100644
--- a/webfiori/framework/session/SessionStatus.php
+++ b/webfiori/framework/session/SessionStatus.php
@@ -9,6 +9,7 @@
*
*/
namespace webfiori\framework\session;
+
/**
* A class which is used to hold constants which represents different statuses
* of a session.
diff --git a/webfiori/framework/session/SessionsManager.php b/webfiori/framework/session/SessionsManager.php
index 51925ddd..1f96c854 100644
--- a/webfiori/framework/session/SessionsManager.php
+++ b/webfiori/framework/session/SessionsManager.php
@@ -104,30 +104,6 @@ public static function destroy() {
self::getInstance()->activeSession = null;
}
}
- /**
- * Returns a date string that represents the time at which all sessions
- * that was created before it will be cleared.
- *
- * This method will try to use the environment variable 'SESSION_GC' to
- * decide on the time. If this environment variable does not exist,
- * it will use the value 30 days to create the date time string which
- * indicates that any session created 30 days ago will be cleared.
- *
- * @return string A date string in the format 'YYYY-MM-DD HH:MM:SS'.
- */
- public static function getGCTime() : string {
- $olderThan = time() - 60 * 60 * 24 * 30;
- $fromEnv = getenv('SESSION_GC') !== false ? intval(getenv('SESSION_GC')) : 0;
- $fromConst = defined('SESSION_GC') && intval(SESSION_GC) > 0 ? intval(SESSION_GC) : 0;
-
- if ($fromEnv != 0) {
- $olderThan = $fromEnv;
- } else if ($fromConst != 0) {
- $olderThan = $fromConst;
- }
-
- return date('Y-m-d H:i:s', $olderThan);
- }
/**
* Returns the value of a session variable.
*
@@ -192,6 +168,32 @@ public static function getCookiesHeaders() : array {
return $retVal;
}
+ /**
+ * Returns a date string that represents the time at which all sessions
+ * that was created before it will be cleared.
+ *
+ * This method will try to use the environment variable 'SESSION_GC' to
+ * decide on the time. If this environment variable does not exist,
+ * it will use the value 30 days to create the date time string which
+ * indicates that any session created 30 days ago will be cleared.
+ *
+ * @return string A date string in the format 'YYYY-MM-DD HH:MM:SS'.
+ */
+ public static function getGCTime() : string {
+ $olderThan = time() - 60 * 60 * 24 * 30;
+ $fromEnv = getenv('SESSION_GC') !== false ? intval(getenv('SESSION_GC')) : 0;
+ $fromConst = defined('SESSION_GC') && intval(SESSION_GC) > 0 ? intval(SESSION_GC) : 0;
+
+ if ($fromEnv != 0) {
+ $olderThan = $fromEnv;
+ } else {
+ if ($fromConst != 0) {
+ $olderThan = $fromConst;
+ }
+ }
+
+ return date('Y-m-d H:i:s', $olderThan);
+ }
/**
* Returns the ID of a session from a cookie given its name.
*
@@ -259,7 +261,7 @@ public static function getStorage() : SessionStorage {
* Checks if the active session has a cookie or not.
*
* Note that in command line, the method will always return false.
- *
+ *
* @return bool true if The active session has a cookie. False if not. If no
* session is active, false is returned.
*/
diff --git a/webfiori/framework/ui/WebPage.php b/webfiori/framework/ui/WebPage.php
index 531934b9..c1eb7f33 100644
--- a/webfiori/framework/ui/WebPage.php
+++ b/webfiori/framework/ui/WebPage.php
@@ -574,11 +574,10 @@ public function getTitleSep() : string {
*
*/
public function getTranslation() : Lang {
-
if (!$this->skipLangCheck && $this->tr === null) {
$this->usingLanguage();
}
-
+
return $this->tr;
}
/**
@@ -774,13 +773,6 @@ public function render(bool $formatted = false, bool $returnResult = false) {
return $this->getDocument();
}
- private function getConfigVar(string $meth, string $default = null, array $params = []) {
- try{
- return call_user_func_array([App::getConfig(), $meth], $params);
- } catch (InitializationException $ex) {
- return $default;
- }
- }
/**
* Resets page attributes to default values.
*
@@ -792,7 +784,7 @@ public function reset() {
$this->checkLang();
$this->usingLanguage();
-
+
$this->setWebsiteName($this->getConfigVar('getAppName', 'WebFiori App', [$this->getLangCode()]));
$this->setDescription($this->getConfigVar('getDescription', '', [$this->getLangCode()]));
$this->setTitle($this->getConfigVar('getTitle', 'Hello World', [$this->getLangCode()]));
@@ -802,10 +794,10 @@ public function reset() {
$langObj = $this->getTranslation();
$this->contentDir = $langObj->getWritingDir();
} catch (TypeError $ex) {
- $this->contentDir = 'ltr';
+ $this->contentDir = 'ltr';
}
-
+
$this->incFooter = true;
$this->incHeader = true;
@@ -1015,7 +1007,7 @@ public function setTheme($themeNameOrClass = null) {
return;
}
$xthemeName = $themeNameOrClass;
-
+
if (strlen(trim($themeNameOrClass.'')) == 0) {
$xthemeName = $this->getConfigVar('getTheme', $themeNameOrClass);
}
@@ -1196,13 +1188,20 @@ private function checkLang() {
}
$this->setLang($langCodeFromSession);
}
+ private function getConfigVar(string $meth, string $default = null, array $params = []) {
+ try {
+ return call_user_func_array([App::getConfig(), $meth], $params);
+ } catch (InitializationException $ex) {
+ return $default;
+ }
+ }
private function getHead() {
$loadedTheme = $this->getTheme();
$defaultBase = Util::getBaseURL();
$base = $this->getConfigVar('getBaseURL', $defaultBase);
-
+
$headNode = new HeadNode(
$this->getTitle().$this->getTitleSep().$this->getWebsiteName(),
$this->getCanonical(),
@@ -1333,6 +1332,7 @@ private function usingLanguage() {
if (!$this->skipLangCheck) {
throw new MissingLangException($ex->getMessage());
}
+
return;
}
$pageLang = $this->getTranslation();
diff --git a/webfiori/framework/writers/APITestCaseWriter.php b/webfiori/framework/writers/APITestCaseWriter.php
index b9eee6c9..d921df55 100644
--- a/webfiori/framework/writers/APITestCaseWriter.php
+++ b/webfiori/framework/writers/APITestCaseWriter.php
@@ -1,5 +1,4 @@
phpunitV = $num;
- }
- /**
- * Returns PHPUnit version number.
- *
- * This is used to check if annotations or attributes should be used in test case
- * method declaration. Starting with PHPUnit 10, attributes are used.
- *
- * @return int
- */
- public function getPhpUnitVersion() : int {
- return $this->phpunitV;
- }
/**
* Creates new instance of the class.
- *
+ *
* @param WebServicesManager|null $manager Web services manager instance.
- *
+ *
* @param AbstractWebService $service The web service at which the test case
* will be based on.
*/
public function __construct(WebServicesManager $manager = null, $service = null) {
parent::__construct('WebService', ROOT_PATH.'\\tests\\apis', ROOT_PATH.'tests\\apis');
$this->setSuffix('Test');
+
if ($manager !== null) {
$this->setServicesManager($manager);
}
$this->setPhpUnitVersion(9);
+
if (!($service instanceof AbstractWebService)) {
if ($service !== null && class_exists($service)) {
$s = new $service();
-
+
if ($s instanceof AbstractWebService) {
$this->setService($s);
}
@@ -71,33 +50,60 @@ public function __construct(WebServicesManager $manager = null, $service = null)
} else {
$this->setService($service);
}
-
+ }
+ /**
+ * Returns PHPUnit version number.
+ *
+ * This is used to check if annotations or attributes should be used in test case
+ * method declaration. Starting with PHPUnit 10, attributes are used.
+ *
+ * @return int
+ */
+ public function getPhpUnitVersion() : int {
+ return $this->phpunitV;
+ }
+ /**
+ * Returns the web service object which was associated with the writer.
+ *
+ * @return AbstractWebService
+ */
+ public function getService() : AbstractWebService {
+ return $this->serviceObj;
+ }
+ /**
+ * Returns the name of the class of the web service.
+ *
+ * @return string
+ */
+ public function getServiceName() : string {
+ return $this->serviceObjName;
}
/**
* Returns the associated web services manager that will be used by the test case.
- *
+ *
* @return WebServicesManager
*/
public function getServicesManager() : WebServicesManager {
return $this->servicesManager;
}
/**
- * Sets the associated web services manager that will be used by the test case.
- *
- * @param WebServicesManager $m
+ * Returns the name of web services manager class.
+ *
+ * @return string
*/
- public function setServicesManager(WebServicesManager $m) {
- $this->servicesManager = $m;
- $clazzExp = explode('\\', get_class($m));
- $this->servicesManagerName = $clazzExp[count($clazzExp) - 1];
+ public function getServicesManagerName() : string {
+ return $this->servicesManagerName;
}
/**
- * Returns the web service object which was associated with the writer.
+ * Sets PHPUnit version number.
*
- * @return AbstractWebService
+ * This is used to check if annotations or attributes should be used in test case
+ * method declaration. Starting with PHPUnit 10, attributes are used.
+ *
+ * @param int $num
*/
- public function getService() : AbstractWebService {
- return $this->serviceObj;
+ public function setPhpUnitVersion(int $num) {
+ $this->phpunitV = $num;
}
/**
@@ -110,6 +116,16 @@ public function setService(AbstractWebService $service) {
$clazzExp = explode('\\', get_class($service));
$this->serviceObjName = $clazzExp[count($clazzExp) - 1];
}
+ /**
+ * Sets the associated web services manager that will be used by the test case.
+ *
+ * @param WebServicesManager $m
+ */
+ public function setServicesManager(WebServicesManager $m) {
+ $this->servicesManager = $m;
+ $clazzExp = explode('\\', get_class($m));
+ $this->servicesManagerName = $clazzExp[count($clazzExp) - 1];
+ }
/**
* Write the test case class.
@@ -119,22 +135,6 @@ public function writeClass() {
$this->addAllUse();
parent::writeClass();
}
- /**
- * Returns the name of the class of the web service.
- *
- * @return string
- */
- public function getServiceName() : string {
- return $this->serviceObjName;
- }
- /**
- * Returns the name of web services manager class.
- *
- * @return string
- */
- public function getServicesManagerName() : string {
- return $this->servicesManagerName;
- }
public function writeClassBody() {
$this->writeNotAllowedRequestMethodTestCases();
$this->writeRequiredParametersTestCases();
@@ -152,130 +152,139 @@ public function writeClassComment() {
public function writeClassDeclaration() {
$this->append('class '.$this->getName().' extends APITestCase {');
}
+ private function addAllUse() {
+ $this->addUseStatement(APITestCase::class);
+ $this->addUseStatement(RequestMethod::class);
+ $this->addUseStatement(get_class($this->getService()));
+ $this->addUseStatement(get_class($this->getServicesManager()));
+ $this->addUseStatement('PHPUnit\Framework\Attributes\Test');
+ }
+ private function addTestAnnotation() {
+ if ($this->phpunitV >= 10) {
+ $this->append('#[Test]', 1);
+ } else {
+ $this->append('/**', 1);
+ $this->append(' * @test', 1);
+ $this->append(' */', 1);
+ }
+ }
+ private function getMethName($reqMeth) {
+ if ($reqMeth == RequestMethod::GET) {
+ return 'getRequest';
+ } else {
+ if ($reqMeth == RequestMethod::PUT) {
+ return 'putRequest';
+ } else {
+ if ($reqMeth == RequestMethod::POST) {
+ return 'postRequest';
+ } else {
+ if ($reqMeth == RequestMethod::DELETE) {
+ return 'getRequest';
+ } else {
+ return 'callEndpoint';
+ }
+ }
+ }
+ }
+ }
+ private function writeNotAllowedRequestMethodTestCases() {
+ $methods = $this->getService()->getRequestMethods();
+ $testCasesCount = 0;
+
+ foreach (RequestMethod::getAll() as $method) {
+ if (!in_array($method, $methods)) {
+ $this->addTestAnnotation();
+ $this->append('public function testRequestMethodNotAllowed'.($testCasesCount < 10 ? '0'.$testCasesCount : $testCasesCount).'() {', 1);
+ $methodName = $this->getMethName($method);
+
+ if ($methodName == 'callEndpoint') {
+ $this->append('$output = $this->'.$methodName.'(new '.$this->getServicesManagerName().'(), RequestMethod::'.strtoupper($method).', '.$this->getServiceName().'::class, []);', 2);
+ } else {
+ $this->append('$output = $this->'.$methodName.'(new '.$this->getServicesManagerName().'(), '.$this->getServiceName().'::class, []);', 2);
+ }
+ $this->append("\$this->assertEquals('{'.self::NL", 2);
+ $this->append(". ' \"message\":\"Method Not Allowed.\",'.self::NL", 2);
+ $this->append(". ' \"type\":\"error\",'.self::NL", 2);
+ $this->append(". ' \"http_code\":405'.self::NL", 2);
+ $this->append(". '}', \$output);", 2);
+ $this->append('}', 1);
+ $testCasesCount++;
+ }
+ }
+ }
private function writeRequiredParametersTestCases() {
$params = $this->getService()->getParameters();
$responseMessage = ResponseMessage::get('404-2');
$missingArr = [];
+
foreach ($params as $param) {
-
if (!$param->isOptional()) {
$missingArr[] = $param->getName();
}
}
+
if (count($missingArr) !== 0) {
$requestMethod = $this->getService()->getRequestMethods()[0];
$this->addTestAnnotation();
$this->append('public function testRequiredParameters() {', 1);
- $this->append('$output = $this->callEndpoint(new '.$this->getServicesManagerName().'(), RequestMethod::'. strtoupper($requestMethod).', '.$this->getServiceName().'::class, []);', 2);
+ $this->append('$output = $this->callEndpoint(new '.$this->getServicesManagerName().'(), RequestMethod::'.strtoupper($requestMethod).', '.$this->getServiceName().'::class, []);', 2);
$this->append("\$this->assertEquals('{'.self::NL", 2);
- $this->append(". ' \"message\":\"$responseMessage\'". implode("\',", $missingArr)."\'.\",'.self::NL", 2);
- $this->append(". ' \"type\":\"error\",'.self::NL", 2);
- $this->append(". ' \"http_code\":404,'.self::NL", 2);
- $this->append(". ' \"more_info\":{'.self::NL", 2);
- $this->append(". ' \"missing\":['.self::NL", 2);
- for ($x = 0 ; $x < count($missingArr) ; $x++) {
- $item = $missingArr[$x];
- if ($x + 1 == count($missingArr)) {
- $this->append(". ' \"$item\"'.self::NL", 2);
- } else {
- $this->append(". ' \"$item\"',.self::NL", 2);
- }
+ $this->append(". ' \"message\":\"$responseMessage\'".implode("\',", $missingArr)."\'.\",'.self::NL", 2);
+ $this->append(". ' \"type\":\"error\",'.self::NL", 2);
+ $this->append(". ' \"http_code\":404,'.self::NL", 2);
+ $this->append(". ' \"more_info\":{'.self::NL", 2);
+ $this->append(". ' \"missing\":['.self::NL", 2);
+
+ for ($x = 0 ; $x < count($missingArr) ; $x++) {
+ $item = $missingArr[$x];
+
+ if ($x + 1 == count($missingArr)) {
+ $this->append(". ' \"$item\"'.self::NL", 2);
+ } else {
+ $this->append(". ' \"$item\"',.self::NL", 2);
}
- $this->append(". ' ]'.self::NL", 2);
- $this->append(". ' }'.self::NL", 2);
- $this->append(". '}', \$output);", 2);
+ }
+ $this->append(". ' ]'.self::NL", 2);
+ $this->append(". ' }'.self::NL", 2);
+ $this->append(". '}', \$output);", 2);
$this->append('}', 1);
}
}
private function writeTestCases() {
$methods = $this->getService()->getRequestMethods();
$testCasesCount = 0;
-
+
foreach (RequestMethod::getAll() as $method) {
if (in_array($method, $methods)) {
$this->addTestAnnotation();
$this->append('public function test'.$method.'Request00() {', 1);
$this->append("//TODO: Write test case for $method request.", 2);
$methodName = $this->getMethName($method);
-
+
if (count($this->getService()->getParameters()) == 0) {
if ($methodName == 'callEndpoint') {
- $this->append('$output = $this->'.$methodName.'(new '.$this->getServicesManagerName().'(), RequestMethod::'. strtoupper($method).', '.$this->getServiceName().'::class, []);', 2);
+ $this->append('$output = $this->'.$methodName.'(new '.$this->getServicesManagerName().'(), RequestMethod::'.strtoupper($method).', '.$this->getServiceName().'::class, []);', 2);
} else {
$this->append('$output = $this->'.$methodName.'(new '.$this->getServicesManagerName().'(), '.$this->getServiceName().'::class, []);', 2);
}
} else {
if ($methodName == 'callEndpoint') {
- $this->append('$output = $this->'.$methodName.'(new '.$this->getServicesManagerName().'(), RequestMethod::'. strtoupper($method).', '.$this->getServiceName().'::class, [', 2);
+ $this->append('$output = $this->'.$methodName.'(new '.$this->getServicesManagerName().'(), RequestMethod::'.strtoupper($method).', '.$this->getServiceName().'::class, [', 2);
} else {
$this->append('$output = $this->'.$methodName.'(new '.$this->getServicesManagerName().'(), '.$this->getServiceName().'::class, [', 2);
}
+
foreach ($this->getService()->getParameters() as $reqParam) {
$this->append("'".$reqParam->getName()."' => null,", 3);
}
$this->append(']);', 2);
}
-
- $this->append("\$this->assertEquals('{'.self::NL", 2);
- $this->append(". '}', \$output);", 2);
- $this->append('}', 1);
- $testCasesCount++;
- }
- }
- }
- private function addTestAnnotation() {
- if ($this->phpunitV >= 10) {
- $this->append('#[Test]', 1);
- } else {
- $this->append('/**', 1);
- $this->append(' * @test', 1);
- $this->append(' */', 1);
- }
- }
- private function writeNotAllowedRequestMethodTestCases() {
- $methods = $this->getService()->getRequestMethods();
- $testCasesCount = 0;
-
- foreach (RequestMethod::getAll() as $method) {
- if (!in_array($method, $methods)) {
- $this->addTestAnnotation();
- $this->append('public function testRequestMethodNotAllowed'.($testCasesCount < 10 ? '0'.$testCasesCount : $testCasesCount).'() {', 1);
- $methodName = $this->getMethName($method);
-
- if ($methodName == 'callEndpoint') {
- $this->append('$output = $this->'.$methodName.'(new '.$this->getServicesManagerName().'(), RequestMethod::'. strtoupper($method).', '.$this->getServiceName().'::class, []);', 2);
- } else {
- $this->append('$output = $this->'.$methodName.'(new '.$this->getServicesManagerName().'(), '.$this->getServiceName().'::class, []);', 2);
- }
+
$this->append("\$this->assertEquals('{'.self::NL", 2);
- $this->append(". ' \"message\":\"Method Not Allowed.\",'.self::NL", 2);
- $this->append(". ' \"type\":\"error\",'.self::NL", 2);
- $this->append(". ' \"http_code\":405'.self::NL", 2);
$this->append(". '}', \$output);", 2);
$this->append('}', 1);
$testCasesCount++;
}
}
}
- private function getMethName($reqMeth) {
- if ($reqMeth == RequestMethod::GET) {
- return 'getRequest';
- } else if ($reqMeth == RequestMethod::PUT) {
- return 'putRequest';
- } else if ($reqMeth == RequestMethod::POST) {
- return 'postRequest';
- } else if ($reqMeth == RequestMethod::DELETE) {
- return 'getRequest';
- } else {
- return 'callEndpoint';
- }
- }
- private function addAllUse() {
- $this->addUseStatement(APITestCase::class);
- $this->addUseStatement(RequestMethod::class);
- $this->addUseStatement(get_class($this->getService()));
- $this->addUseStatement(get_class($this->getServicesManager()));
- $this->addUseStatement('PHPUnit\Framework\Attributes\Test');
- }
-
}
diff --git a/webfiori/framework/writers/CLICommandClassWriter.php b/webfiori/framework/writers/CLICommandClassWriter.php
index d233cfe4..5b2f73a6 100644
--- a/webfiori/framework/writers/CLICommandClassWriter.php
+++ b/webfiori/framework/writers/CLICommandClassWriter.php
@@ -181,9 +181,8 @@ private function writeConstructor() {
$this->append(["parent::__construct('$this->name', ["], 2);
foreach ($this->args as $argObj) {
-
$this->append("'".$argObj->getName()."' => [", 3);
-
+
if (strlen($argObj->getDescription()) != 0) {
$this->append("'description' => '".str_replace("'", "\'", $argObj->getDescription())."',", 4);
}
diff --git a/webfiori/framework/writers/SchedulerTaskClassWriter.php b/webfiori/framework/writers/SchedulerTaskClassWriter.php
index b603875f..acc01579 100644
--- a/webfiori/framework/writers/SchedulerTaskClassWriter.php
+++ b/webfiori/framework/writers/SchedulerTaskClassWriter.php
@@ -27,7 +27,7 @@ class SchedulerTaskClassWriter extends ClassWriter {
*
* @param string $className The name of the class that will represent the
* task.
- *
+ *
* @param string $taskName The name of the task.
*
* @param string $taskDesc A short description that description what does the
diff --git a/webfiori/framework/writers/TableClassWriter.php b/webfiori/framework/writers/TableClassWriter.php
index ea029874..9f40c52a 100644
--- a/webfiori/framework/writers/TableClassWriter.php
+++ b/webfiori/framework/writers/TableClassWriter.php
@@ -254,7 +254,6 @@ private function addFKOption(Column $colObj) {
$fks = $this->getTable()->getForeignKeys();
foreach ($fks as $fk) {
-
$sourceCols = array_values($fk->getOwnerCols());
if (count($sourceCols) == 1 && $sourceCols[0]->getNormalName() == $colObj->getNormalName()) {