diff --git a/composer.json b/composer.json index fdfb1ad9..9a34166d 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "ext-mbstring": "*", "ext-fileinfo": "*", "ext-openssl": "*", - "webfiori/http":"v3.3.8", + "webfiori/http":"v3.3.9", "webfiori/file":"v1.3.4", "webfiori/jsonx":"v3.3.0", "webfiori/ui":"v2.6.1", diff --git a/ecs.php b/ecs.php index 3ae60220..ff05957f 100644 --- a/ecs.php +++ b/ecs.php @@ -6,13 +6,14 @@ use Symplify\EasyCodingStandard\Config\ECSConfig; use Symplify\EasyCodingStandard\ValueObject\Set\SetList; -return function (ECSConfig $ecsConfig): void { +return function (ECSConfig $ecsConfig): void +{ $ecsConfig->paths([ - __DIR__ . '/app', - __DIR__ . '/public', - __DIR__ . '/tests', - __DIR__ . '/themes', - __DIR__ . '/webfiori', + __DIR__.'/app', + __DIR__.'/public', + __DIR__.'/tests', + __DIR__.'/themes', + __DIR__.'/webfiori', ]); // this way you add a single rule diff --git a/tests/webfiori/framework/test/cli/CreateCommandTest.php b/tests/webfiori/framework/test/cli/CreateCommandTest.php index 556d1232..650f1311 100644 --- a/tests/webfiori/framework/test/cli/CreateCommandTest.php +++ b/tests/webfiori/framework/test/cli/CreateCommandTest.php @@ -62,78 +62,4 @@ public function testCreate01() { "9: Quit. <--\n", ], $runner->getOutput()); } - - - - - /** - * @test - */ - public function testCreateWebService00() { - $runner = $runner = App::getRunner(); - $runner->setInputs([ - '2', - 'NewWeb', - '', - 'get-hello', - '0', - 'y', - '6', - 'name', - 'n', - 'n', - '', - ]); - $runner->setArgsVector([ - 'webfiori', - 'create' - ]); - $result = $runner->start(); - $this->assertEquals(0, $result); - $this->assertEquals([ - "What would you like to create?\n", - "0: Database table class.\n", - "1: Entity class from table.\n", - "2: Web service.\n", - "3: Background Task.\n", - "4: Middleware.\n", - "5: CLI Command.\n", - "6: Theme.\n", - "7: Database access class based on table.\n", - "8: Complete REST backend (Database table, entity, database access and web services).\n", - "9: Quit. <--\n", - "Enter a name for the new class:\n", - "Enter an optional namespace for the class: Enter = 'app\apis'\n", - "Enter a name for the new web service:\n", - "Request method:\n", - "0: CONNECT\n", - "1: DELETE\n", - "2: GET <--\n", - "3: HEAD\n", - "4: OPTIONS\n", - "5: POST\n", - "6: PUT\n", - "7: TRACE\n", - - "Would you like to add request parameters to the service?(y/N)\n", - "Choose parameter type:\n", - "0: array <--\n", - "1: boolean\n", - "2: email\n", - "3: double\n", - "4: integer\n", - "5: json-obj\n", - "6: string\n", - "7: url\n", - "Enter a name for the request parameter:\n", - "Is this parameter optional?(Y/n)\n", - "Success: New parameter added to the service 'get-hello'.\n", - "Would you like to add another parameter?(y/N)\n", - "Creating the class...\n", - 'Info: New class was created at "'.ROOT_PATH.DS.'app'.DS."apis\".\n", - "Info: Don't forget to add the service to a services manager.\n", - ], $runner->getOutput()); - $this->assertTrue(class_exists('\\app\\apis\\NewWebService')); - $this->removeClass('\\app\\apis\\NewWebService'); - } } diff --git a/tests/webfiori/framework/test/cli/CreateTableTest.php b/tests/webfiori/framework/test/cli/CreateTableTest.php index 27ca07bf..357aa397 100644 --- a/tests/webfiori/framework/test/cli/CreateTableTest.php +++ b/tests/webfiori/framework/test/cli/CreateTableTest.php @@ -496,6 +496,7 @@ public function testCreateTable05() { $this->assertEquals(DataType::INT, $idCol->getDatatype()); $this->assertTrue($idCol->isPrimary()); $this->assertTrue($idCol->isUnique()); + return $clazz; } /** @@ -546,7 +547,7 @@ public function testCreateTable06($refTable) { $output = $runner->getOutput(); $clazz = '\\app\\database\\Cool06Table'; $this->assertTrue(class_exists($clazz)); - + $this->removeClass($clazz); $this->assertEquals(array_merge([ "Database type:\n", @@ -597,7 +598,7 @@ public function testCreateTable06($refTable) { "Would you like to create an entity class that maps to the database table?(y/N)\n", 'Info: New class was created at "'.ROOT_PATH.DS.'app'.DS."database\".\n", ]), $output); - + $instance = new $clazz(); $instance instanceof Table; $this->assertEquals(1, $instance->getForeignKeysCount()); diff --git a/tests/webfiori/framework/test/cli/CreateWebServiceTest.php b/tests/webfiori/framework/test/cli/CreateWebServiceTest.php new file mode 100644 index 00000000..cbea6455 --- /dev/null +++ b/tests/webfiori/framework/test/cli/CreateWebServiceTest.php @@ -0,0 +1,319 @@ +setInputs([ + '2', + 'NewWeb', + '', + 'get-hello', + 'Service Desc', + '', + 'n', + 'y', + 'name', + '6', + 'Random desc', + 'n', + 'n', + 'n', + '', + ]); + $runner->setArgsVector([ + 'webfiori', + 'create' + ]); + $result = $runner->start(); + //$this->assertEquals(0, $result); + $this->assertEquals([ + "What would you like to create?\n", + "0: Database table class.\n", + "1: Entity class from table.\n", + "2: Web service.\n", + "3: Background Task.\n", + "4: Middleware.\n", + "5: CLI Command.\n", + "6: Theme.\n", + "7: Database access class based on table.\n", + "8: Complete REST backend (Database table, entity, database access and web services).\n", + "9: Quit. <--\n", + "Enter a name for the new class:\n", + "Enter an optional namespace for the class: Enter = 'app\apis'\n", + "Enter a name for the new web service:\n", + "Description:\n", + "Request method:\n", + "0: CONNECT\n", + "1: DELETE\n", + "2: GET <--\n", + "3: HEAD\n", + "4: OPTIONS\n", + "5: POST\n", + "6: PUT\n", + "7: TRACE\n", + "Would you like to add another request method?(y/N)\n", + "Would you like to add request parameters to the service?(y/N)\n", + "Enter a name for the request parameter:\n", + "Choose parameter type:\n", + "0: array <--\n", + "1: boolean\n", + "2: email\n", + "3: double\n", + "4: integer\n", + "5: json-obj\n", + "6: string\n", + "7: url\n", + "Description:\n", + "Is this parameter optional?(Y/n)\n", + "Are empty values allowed?(y/N)\n", + "Would you like to set minimum and maximum length?(y/N)\n", + "Success: New parameter added.\n", + "Would you like to add another parameter?(y/N)\n", + "Creating the class...\n", + 'Info: New class was created at "'.ROOT_PATH.DS.'app'.DS."apis\".\n", + "Info: Don't forget to add the service to a services manager.\n", + ], $runner->getOutput()); + $clazz = '\\app\\apis\\NewWebService'; + $this->assertTrue(class_exists($clazz)); + $this->removeClass('\\app\\apis\\NewWebService'); + $instance = new $clazz(); + $instance instanceof AbstractWebService; + $this->assertEquals('get-hello', $instance->getName()); + $this->assertEquals(1, count($instance->getParameters())); + $this->assertEquals('Service Desc', $instance->getDescription()); + $this->assertEquals([RequestMethod::GET], $instance->getRequestMethods()); + $param00 = $instance->getParameters()[0]; + $this->assertRequestParameter($param00, [ + ParamOption::NAME => 'name', + ParamOption::TYPE => ParamType::STRING, + ParamOption::DESCRIPTION => 'Random desc', + ParamOption::DEFAULT => null, + ParamOption::EMPTY => false, + ParamOption::MAX => null, + ParamOption::MAX_LENGTH => null, + ParamOption::MIN => null, + ParamOption::MIN_LENGTH => null, + ParamOption::OPTIONAL => false, + ]); + } + /** + * @test + */ + public function test01() { + $runner = $runner = App::getRunner(); + $runner->setInputs([ + 'NewWeb2', + '', + 'get-hello-2', + 'Service\'s Desc', + '', + 'y', + '5', + 'n', + 'y', + 'a-number', + '3', + 'Random\'s desc', + 'n', + '', + '', + ]); + $runner->setArgsVector([ + 'webfiori', + 'create', + '--c' => 'web-service' + ]); + $result = $runner->start(); + //$this->assertEquals(0, $result); + $this->assertEquals([ + "Enter a name for the new class:\n", + "Enter an optional namespace for the class: Enter = 'app\apis'\n", + "Enter a name for the new web service:\n", + "Description:\n", + "Request method:\n", + "0: CONNECT\n", + "1: DELETE\n", + "2: GET <--\n", + "3: HEAD\n", + "4: OPTIONS\n", + "5: POST\n", + "6: PUT\n", + "7: TRACE\n", + "Would you like to add another request method?(y/N)\n", + "Request method:\n", + "0: CONNECT\n", + "1: DELETE\n", + "2: GET <--\n", + "3: HEAD\n", + "4: OPTIONS\n", + "5: POST\n", + "6: PUT\n", + "7: TRACE\n", + "Would you like to add another request method?(y/N)\n", + "Would you like to add request parameters to the service?(y/N)\n", + "Enter a name for the request parameter:\n", + "Choose parameter type:\n", + "0: array <--\n", + "1: boolean\n", + "2: email\n", + "3: double\n", + "4: integer\n", + "5: json-obj\n", + "6: string\n", + "7: url\n", + "Description:\n", + "Is this parameter optional?(Y/n)\n", + "Would you like to set minimum and maximum limites?(y/N)\n", + "Success: New parameter added.\n", + "Would you like to add another parameter?(y/N)\n", + "Creating the class...\n", + 'Info: New class was created at "'.ROOT_PATH.DS.'app'.DS."apis\".\n", + "Info: Don't forget to add the service to a services manager.\n", + ], $runner->getOutput()); + $clazz = '\\app\\apis\\NewWeb2Service'; + $this->assertTrue(class_exists($clazz)); + $this->removeClass('\\app\\apis\\NewWeb2Service'); + $instance = new $clazz(); + $instance instanceof AbstractWebService; + $this->assertEquals('get-hello-2', $instance->getName()); + $this->assertEquals(1, count($instance->getParameters())); + $this->assertEquals('Service\'s Desc', $instance->getDescription()); + $this->assertEquals([RequestMethod::GET, RequestMethod::POST], $instance->getRequestMethods()); + $param00 = $instance->getParameters()[0]; + $this->assertRequestParameter($param00, [ + ParamOption::NAME => 'a-number', + ParamOption::TYPE => ParamType::DOUBLE, + ParamOption::DESCRIPTION => 'Random\'s desc', + ParamOption::DEFAULT => null, + ParamOption::EMPTY => false, + ParamOption::MAX => defined('PHP_FLOAT_MAX') ? PHP_FLOAT_MAX : 1.7976931348623E+308, + ParamOption::MAX_LENGTH => null, + ParamOption::MIN => defined('PHP_FLOAT_MIN') ? PHP_FLOAT_MIN : 2.2250738585072E-308, + ParamOption::MIN_LENGTH => null, + ParamOption::OPTIONAL => false, + ]); + } + /** + * @test + */ + public function test02() { + $runner = $runner = App::getRunner(); + $runner->setInputs([ + 'NewWeb3', + '', + 'get-hello-3', + 'Service\'s Desc', + '', + 'y', + '5', + 'n', + 'y', + 'a-number', + '4', + 'Random\'s desc', + 'n', + '', + '', + ]); + $runner->setArgsVector([ + 'webfiori', + 'create', + '--c' => 'web-service' + ]); + $result = $runner->start(); + //$this->assertEquals(0, $result); + $this->assertEquals([ + "Enter a name for the new class:\n", + "Enter an optional namespace for the class: Enter = 'app\apis'\n", + "Enter a name for the new web service:\n", + "Description:\n", + "Request method:\n", + "0: CONNECT\n", + "1: DELETE\n", + "2: GET <--\n", + "3: HEAD\n", + "4: OPTIONS\n", + "5: POST\n", + "6: PUT\n", + "7: TRACE\n", + "Would you like to add another request method?(y/N)\n", + "Request method:\n", + "0: CONNECT\n", + "1: DELETE\n", + "2: GET <--\n", + "3: HEAD\n", + "4: OPTIONS\n", + "5: POST\n", + "6: PUT\n", + "7: TRACE\n", + "Would you like to add another request method?(y/N)\n", + "Would you like to add request parameters to the service?(y/N)\n", + "Enter a name for the request parameter:\n", + "Choose parameter type:\n", + "0: array <--\n", + "1: boolean\n", + "2: email\n", + "3: double\n", + "4: integer\n", + "5: json-obj\n", + "6: string\n", + "7: url\n", + "Description:\n", + "Is this parameter optional?(Y/n)\n", + "Would you like to set minimum and maximum limites?(y/N)\n", + "Success: New parameter added.\n", + "Would you like to add another parameter?(y/N)\n", + "Creating the class...\n", + 'Info: New class was created at "'.ROOT_PATH.DS.'app'.DS."apis\".\n", + "Info: Don't forget to add the service to a services manager.\n", + ], $runner->getOutput()); + $clazz = '\\app\\apis\\NewWeb3Service'; + $this->assertTrue(class_exists($clazz)); + $this->removeClass($clazz); + $instance = new $clazz(); + $instance instanceof AbstractWebService; + $this->assertEquals('get-hello-3', $instance->getName()); + $this->assertEquals(1, count($instance->getParameters())); + $this->assertEquals('Service\'s Desc', $instance->getDescription()); + $this->assertEquals([RequestMethod::GET, RequestMethod::POST], $instance->getRequestMethods()); + $param00 = $instance->getParameters()[0]; + $this->assertRequestParameter($param00, [ + ParamOption::NAME => 'a-number', + ParamOption::TYPE => ParamType::INT, + ParamOption::DESCRIPTION => 'Random\'s desc', + ParamOption::DEFAULT => null, + ParamOption::EMPTY => false, + ParamOption::MAX => PHP_INT_MAX, + ParamOption::MAX_LENGTH => null, + ParamOption::MIN => defined('PHP_INT_MIN') ? PHP_INT_MIN : ~PHP_INT_MAX, + ParamOption::MIN_LENGTH => null, + ParamOption::OPTIONAL => false, + ]); + } + private function assertRequestParameter(RequestParameter $param, array $expected) { + $this->assertEquals($expected[ParamOption::NAME], $param->getName()); + $this->assertEquals($expected[ParamOption::TYPE], $param->getType()); + $this->assertEquals($expected[ParamOption::DESCRIPTION], $param->getDescription()); + $this->assertEquals($expected[ParamOption::MIN_LENGTH], $param->getMinLength()); + $this->assertEquals($expected[ParamOption::MAX_LENGTH], $param->getMaxLength()); + $this->assertEquals($expected[ParamOption::MIN], $param->getMinValue()); + $this->assertEquals($expected[ParamOption::MAX], $param->getMaxValue()); + $this->assertEquals($expected[ParamOption::EMPTY], $param->isEmptyStringAllowed()); + $this->assertEquals($expected[ParamOption::OPTIONAL], $param->isOptional()); + $this->assertEquals($expected[ParamOption::DEFAULT], $param->getDefault()); + } +} diff --git a/tests/webfiori/framework/test/cli/RunSQLCommandTest.php b/tests/webfiori/framework/test/cli/RunSQLCommandTest.php index 349f3136..f7b4396a 100644 --- a/tests/webfiori/framework/test/cli/RunSQLCommandTest.php +++ b/tests/webfiori/framework/test/cli/RunSQLCommandTest.php @@ -88,7 +88,6 @@ public function testCLIQuery01() { * @test */ public function testCLIQuery02() { - JsonDriver::setConfigFileName('run-sql-test'); App::setConfigDriver(JsonDriver::class); @@ -97,11 +96,11 @@ public function testCLIQuery02() { App::getConfig()->addOrUpdateDBConnection($conn); $driver = new JsonDriver(); $driver->setConfigFileName('run-sql-test'); - + Controller::setDriver($driver); - + $this->assertTrue(get_class(App::getConfig()) == JsonDriver::class); - + $runner = App::getRunner(); $runner->setArgsVector([ 'webfiori', diff --git a/tests/webfiori/framework/test/cli/SchedulerCommandTest.php b/tests/webfiori/framework/test/cli/SchedulerCommandTest.php index a0b436d1..8c906348 100644 --- a/tests/webfiori/framework/test/cli/SchedulerCommandTest.php +++ b/tests/webfiori/framework/test/cli/SchedulerCommandTest.php @@ -172,8 +172,8 @@ public function test05() { "Stack Trace:\n", "#0 At class app\\tasks\Fail2TestTask line 1083\n", "#1 At class webfiori\\framework\scheduler\AbstractTask line 406\n", - "#2 At class webfiori\\framework\scheduler\AbstractTask line 904\n", - "#3 At class webfiori\\framework\scheduler\TasksManager line 600\n", + "#2 At class webfiori\\framework\scheduler\AbstractTask line 903\n", + "#3 At class webfiori\\framework\scheduler\TasksManager line 625\n", "#4 At class webfiori\\framework\scheduler\TasksManager line 135\n", "#5 At class webfiori\\framework\cli\commands\SchedulerCommand line 86\n", "#6 At class webfiori\\framework\cli\commands\SchedulerCommand line 328\n", @@ -184,6 +184,7 @@ public function test05() { "Skip"]; $actual = $runner->getOutput(); $idx = 0; + foreach ($expected as $item) { if ($item == 'Skip') { break; diff --git a/tests/webfiori/framework/test/router/RouterTest.php b/tests/webfiori/framework/test/router/RouterTest.php index 97d8b122..ceab4fe2 100644 --- a/tests/webfiori/framework/test/router/RouterTest.php +++ b/tests/webfiori/framework/test/router/RouterTest.php @@ -25,13 +25,13 @@ public function test00() { */ public function testAddAPIRoute00() { $this->assertTrue(Router::api([ - RouteOption::PATH => '/call-api-00', - RouteOption::TO => '/my-api.php'])); + RouteOption::PATH => '/call-api-00', + RouteOption::TO => '/my-api.php'])); $this->assertFalse(Router::page([ - RouteOption::PATH => '/call-api-00', - RouteOption::TO => '/my-other-api.php'])); + RouteOption::PATH => '/call-api-00', + RouteOption::TO => '/my-other-api.php'])); $this->assertTrue(Router::page([ - RouteOption::PATH => '/call-api-01', + RouteOption::PATH => '/call-api-01', RouteOption::TO => '/my-api.php'])); } /** @@ -45,20 +45,20 @@ public function testAddClosureRoute00() { { }; $this->assertTrue(Router::closure([ - RouteOption::PATH => '/call', - RouteOption::TO => $c1 + RouteOption::PATH => '/call', + RouteOption::TO => $c1 ])); $this->assertFalse(Router::closure([ - RouteOption::PATH => '/call', - RouteOption::TO => $c2 + RouteOption::PATH => '/call', + RouteOption::TO => $c2 ])); $this->assertTrue(Router::closure([ - RouteOption::PATH => '/call-2', - RouteOption::TO => $c1 + RouteOption::PATH => '/call-2', + RouteOption::TO => $c1 ])); $this->assertFalse(Router::closure([ - RouteOption::PATH => '/call', - RouteOption::TO => 'Not Func' + RouteOption::PATH => '/call', + RouteOption::TO => 'Not Func' ])); } /** @@ -66,14 +66,14 @@ public function testAddClosureRoute00() { */ public function testAddViewRoute00() { $this->assertTrue(Router::page([ - RouteOption::PATH => '/view-something', - RouteOption::TO => 'my-view.php'])); + RouteOption::PATH => '/view-something', + RouteOption::TO => 'my-view.php'])); $this->assertFalse(Router::page([ - RouteOption::PATH => '/view-something', - RouteOption::TO => '/my-other-view.php'])); + RouteOption::PATH => '/view-something', + RouteOption::TO => '/my-other-view.php'])); $this->assertTrue(Router::page([ - RouteOption::PATH => '/view-something-2', - RouteOption::TO => '/my-view.php'])); + RouteOption::PATH => '/view-something-2', + RouteOption::TO => '/my-view.php'])); } /** * @test @@ -84,8 +84,8 @@ public function testOptionalParam00() { { }); Router::closure([ - RouteOption::PATH => '{var-1}/{var-2?}', - RouteOption::TO => function() + RouteOption::PATH => '{var-1}/{var-2?}', + RouteOption::TO => function() { }, RouteOption::VALUES => [ @@ -110,8 +110,8 @@ public function testOptionalParam01() { Router::removeAll(); Router::closure([ - RouteOption::PATH => '{var-1}/{var-2?}', - RouteOption::TO => function() + RouteOption::PATH => '{var-1}/{var-2?}', + RouteOption::TO => function() { } ]); @@ -132,8 +132,8 @@ public function testRoute00() { { }); Router::closure([ - RouteOption::PATH => '{var-1}/{var-2}', - RouteOption::TO => function() + RouteOption::PATH => '{var-1}/{var-2}', + RouteOption::TO => function() { } ]); @@ -155,8 +155,8 @@ public function testRoute01() { { }); Router::closure([ - RouteOption::PATH => '{var-1}/{var-2}/{var-1}', - RouteOption::TO => function() + RouteOption::PATH => '{var-1}/{var-2}/{var-1}', + RouteOption::TO => function() { } ]); @@ -172,37 +172,37 @@ public function testRoute01() { public function testRoutesGroup00() { Router::removeAll(); Router::page([ - RouteOption::PATH => 'users', + RouteOption::PATH => 'users', RouteOption::CASE_SENSITIVE => false, RouteOption::MIDDLEWARE => 'M1', RouteOption::LANGS => ['EN'], RouteOption::REQUEST_METHODS => RequestMethod::POST, - RouteOption::SUB_ROUTES => [ + RouteOption::SUB_ROUTES => [ [ - RouteOption::PATH => 'view-user/{user-id}', - RouteOption::TO => 'ViewUserPage.php', - RouteOption::LANGS => ['AR'] + RouteOption::PATH => 'view-user/{user-id}', + RouteOption::TO => 'ViewUserPage.php', + RouteOption::LANGS => ['AR'] ], [ - RouteOption::PATH => 'get-users', - RouteOption::LANGS => ['AR'], + RouteOption::PATH => 'get-users', + RouteOption::LANGS => ['AR'], RouteOption::CASE_SENSITIVE => true, - RouteOption::SUB_ROUTES => [ + RouteOption::SUB_ROUTES => [ [ - RouteOption::PATH => 'by-name', - RouteOption::TO => 'GetUserByName.php', - RouteOption::LANGS => ['FR'], + RouteOption::PATH => 'by-name', + RouteOption::TO => 'GetUserByName.php', + RouteOption::LANGS => ['FR'], RouteOption::CASE_SENSITIVE => false, ], [ - RouteOption::PATH => 'by-email', - RouteOption::TO => 'GetUserByEmail.php' + RouteOption::PATH => 'by-email', + RouteOption::TO => 'GetUserByEmail.php' ] ], ], [ - RouteOption::PATH => '/', - RouteOption::TO => 'ListUsers.php', + RouteOption::PATH => '/', + RouteOption::TO => 'ListUsers.php', RouteOption::CASE_SENSITIVE => true, RouteOption::REQUEST_METHODS => [RequestMethod::OPTIONS, RequestMethod::GET] ] diff --git a/tests/webfiori/framework/test/writers/WebServiceWritterTest.php b/tests/webfiori/framework/test/writers/WebServiceWritterTest.php index 08aca701..a2f0d18f 100644 --- a/tests/webfiori/framework/test/writers/WebServiceWritterTest.php +++ b/tests/webfiori/framework/test/writers/WebServiceWritterTest.php @@ -19,7 +19,8 @@ public function test00() { $this->assertEquals([ "webfiori\\framework\\EAbstractWebService", "webfiori\http\ParamType", - "webfiori\http\ParamOption" + "webfiori\http\ParamOption", + "webfiori\\http\\RequestMethod" ], $writter->getUseStatements()); } /** @@ -34,7 +35,8 @@ public function test01() { $this->assertEquals([ "webfiori\\framework\\EAbstractWebService", "webfiori\http\ParamType", - "webfiori\http\ParamOption" + "webfiori\http\ParamOption", + "webfiori\\http\\RequestMethod" ], $writter->getUseStatements()); $writter->addRequestParam([ 'name' => 'param-1', @@ -61,7 +63,8 @@ public function test02() { $this->assertEquals([ "webfiori\\framework\\EAbstractWebService", "webfiori\http\ParamType", - "webfiori\http\ParamOption" + "webfiori\http\ParamOption", + "webfiori\\http\\RequestMethod" ], $writter->getUseStatements()); $writter->addRequestParam([ 'name' => 'param-1', diff --git a/webfiori/framework/App.php b/webfiori/framework/App.php index d008d476..0f2886a8 100644 --- a/webfiori/framework/App.php +++ b/webfiori/framework/App.php @@ -45,31 +45,6 @@ * */ class App { - /** - * Sets the class that will be used as configuration driver. - * - * This method must be used before calling the method 'App::start()' in order - * to set proper configuration driver. - * - * @param string $clazz The full name of the class including namespace. - */ - public static function setConfigDriver(string $clazz) { - self::$ConfigDriver = $clazz; - } - /** - * Returns the class that represents configuration driver. - * - * @return string The full name of the class including namespace. - */ - public static function getConfigDriver() : string { - return self::$ConfigDriver; - } - /** - * A string which points to the class that represents configuration driver. - * - * @var string - */ - private static $ConfigDriver = 'webfiori\\framework\\config\\ClassDriver'; /** * A constant that indicates that the status of the class is 'initialized'. * @@ -106,6 +81,12 @@ public static function getConfigDriver() : string { * @var Runner */ private static $CliRunner; + /** + * A string which points to the class that represents configuration driver. + * + * @var string + */ + private static $ConfigDriver = 'webfiori\\framework\\config\\ClassDriver'; /** * A single instance of the class. * @@ -295,14 +276,23 @@ public static function getClassStatus() { */ public static function getConfig(): ConfigurationDriver { $driver = Controller::getDriver(); - + if (get_class($driver) != self::$ConfigDriver) { Controller::setDriver(new self::$ConfigDriver()); Controller::get()->updateEnv(); $driver = Controller::getDriver(); } + return $driver; } + /** + * Returns the class that represents configuration driver. + * + * @return string The full name of the class including namespace. + */ + public static function getConfigDriver() : string { + return self::$ConfigDriver; + } /** * Returns an instance which represents the class that is used to run the @@ -368,6 +358,17 @@ public static function getRunner() : Runner { return self::$CliRunner; } + /** + * Sets the class that will be used as configuration driver. + * + * This method must be used before calling the method 'App::start()' in order + * to set proper configuration driver. + * + * @param string $clazz The full name of the class including namespace. + */ + public static function setConfigDriver(string $clazz) { + self::$ConfigDriver = $clazz; + } /** * Start your WebFiori application. @@ -420,7 +421,7 @@ private function checkAppDir() { /** * Directory separator. */ - define('DS', DIRECTORY_SEPARATOR); + define('DS', DIRECTORY_SEPARATOR); } if (!defined('APP_DIR')) { @@ -437,13 +438,14 @@ private function checkAppDir() { http_response_code(500); die('Error: Unable to initialize the application. Invalid application directory name: "'.APP_DIR.'".'); } + if (!defined('APP_PATH')) { /** * The absolute path to application directory. * * @var string */ - define('APP_PATH', ROOT_PATH.DIRECTORY_SEPARATOR.APP_DIR.DIRECTORY_SEPARATOR); + define('APP_PATH', ROOT_PATH.DIRECTORY_SEPARATOR.APP_DIR.DIRECTORY_SEPARATOR); } } @@ -540,7 +542,7 @@ private function initFrameworkVersionInfo() { * * @since 2.1 */ - define('WF_VERSION', '3.0.0-RC19'); + define('WF_VERSION', '3.0.0-Beta.1'); /** * A constant that tells the type of framework version. * @@ -548,7 +550,7 @@ private function initFrameworkVersionInfo() { * * @since 2.1 */ - define('WF_VERSION_TYPE', 'Release Candidate'); + define('WF_VERSION_TYPE', 'Beta'); /** * The date at which the framework version was released. * @@ -556,7 +558,7 @@ private function initFrameworkVersionInfo() { * * @since 2.1 */ - define('WF_RELEASE_DATE', '2023-11-07'); + define('WF_RELEASE_DATE', '2024-01-17'); } /** @@ -569,7 +571,7 @@ private function initMiddleware() { }); if (!class_exists(APP_DIR.'\ini\InitMiddleware')) { - Ini::get()->createIniClass('InitMiddleware', 'Register middleware which are created outside the folder \'app/middleware\'.'); + Ini::get()->createIniClass('InitMiddleware', 'Register middleware which are created outside the folder \'[APP_DIR]/middleware\'.'); } call_user_func(APP_DIR.'\ini\InitMiddleware::init'); } diff --git a/webfiori/framework/DB.php b/webfiori/framework/DB.php index 56c8f5c2..caa6a3ed 100644 --- a/webfiori/framework/DB.php +++ b/webfiori/framework/DB.php @@ -62,7 +62,7 @@ public function __construct($connName) { } if (!($conn instanceof ConnectionInfo)) { - throw new DatabaseException("No connection was found which has the name '$connName'. Driver: ". get_class(App::getConfig()).'.'); + throw new DatabaseException("No connection was found which has the name '$connName'. Driver: ".get_class(App::getConfig()).'.'); } } parent::__construct($conn); diff --git a/webfiori/framework/EmailMessage.php b/webfiori/framework/EmailMessage.php index 859f5585..978fc46e 100644 --- a/webfiori/framework/EmailMessage.php +++ b/webfiori/framework/EmailMessage.php @@ -10,10 +10,10 @@ */ namespace webfiori\framework; +use webfiori\email\Email; use webfiori\email\exceptions\SMTPException; use webfiori\email\SMTPAccount; use webfiori\framework\exceptions\MissingLangException; -use webfiori\email\Email; /** * A class that can be used to write HTML formatted Email messages. * @@ -82,13 +82,12 @@ public function getTranslation() { * * @return Email The method will return same instance at which the method is * called on. - * + * * @throws MissingLangException */ public function setLang(string $lang = 'EN') : Email { if (parent::setLang($lang)) { $this->usingLanguage(); - } return $this; diff --git a/webfiori/framework/Ini.php b/webfiori/framework/Ini.php index e79a5c95..8ead27dc 100644 --- a/webfiori/framework/Ini.php +++ b/webfiori/framework/Ini.php @@ -34,10 +34,32 @@ class Ini { */ private static $singleton; private function __construct() { - } - + + /** + * Creates all directories at which the application needs to run. + */ + public static function createAppDirs() { + $DS = DIRECTORY_SEPARATOR; + self::mkdir(ROOT_PATH.$DS.APP_DIR); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'ini'); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'ini'.$DS.'routes'); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'pages'); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'commands'); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'tasks'); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'middleware'); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'langs'); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'apis'); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'config'); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'.$DS.'uploads'); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'.$DS.'logs'); + self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'.$DS.'sessions'); + self::mkdir(ROOT_PATH.$DS.'public'); + } + + /** * Creates initialization class. @@ -126,29 +148,6 @@ public static function get(): Ini { return self::$singleton; } - - - /** - * Creates all directories at which the application needs to run. - */ - public static function createAppDirs() { - $DS = DIRECTORY_SEPARATOR; - self::mkdir(ROOT_PATH.$DS.APP_DIR); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'ini'); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'ini'.$DS.'routes'); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'pages'); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'commands'); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'tasks'); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'middleware'); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'langs'); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'apis'); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'config'); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'.$DS.'uploads'); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'.$DS.'logs'); - self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'.$DS.'sessions'); - self::mkdir(ROOT_PATH.$DS.'public'); - } public static function mkdir($dir) { if (!is_dir($dir)) { set_error_handler(function (int $errno, string $errstr) diff --git a/webfiori/framework/ThemeLoader.php b/webfiori/framework/ThemeLoader.php index 2b1b1ed1..9056e06c 100644 --- a/webfiori/framework/ThemeLoader.php +++ b/webfiori/framework/ThemeLoader.php @@ -55,7 +55,7 @@ private function __construct() { * * This method will return an associative array. The key is the theme * name and the value is an object of type Theme that contains theme info. - * + * * @param bool $updateCache If set to true, cached data of descovered themes * will reset and search will be performed again. * @@ -251,7 +251,7 @@ private static function scanDir($filesInDir, $pathToScan, $dirName) { $ns = require_once $pathToScan.DS.$fileName; $aNs = gettype($ns) == 'string' ? $ns.'\\' : '\\'; $aCName = $aNs.$cName; - + if (!class_exists($aCName)) { $aCName = '\\'.self::THEMES_DIR.'\\'.$dirName.'\\'.$cName; } diff --git a/webfiori/framework/cli/helpers/CreateWebService.php b/webfiori/framework/cli/helpers/CreateWebService.php index 17f4c8f3..9cca0a82 100644 --- a/webfiori/framework/cli/helpers/CreateWebService.php +++ b/webfiori/framework/cli/helpers/CreateWebService.php @@ -33,13 +33,27 @@ public function __construct(CreateCommand $command) { $this->serviceObj = new ServiceHolder(); parent::__construct($command, new WebServiceWriter($this->serviceObj)); } + public function addRequestMethods() { + $toSelect = RequestMethod::getAll(); + $addOne = true; + + while ($addOne) { + array_multisort($toSelect); + $this->serviceObj->addRequestMethod($this->select('Request method:', $toSelect, 2)); + + if (count($toSelect) > 1) { + $addOne = $this->confirm('Would you like to add another request method?', false); + } else { + $addOne = false; + } + } + } public function readClassInfo() { $this->setClassInfo(APP_DIR.'\\apis', 'Service'); $this->setServiceName(); - $methods = RequestMethod::getAll(); - array_multisort($methods); - $this->serviceObj->addRequestMethod($this->select('Request method:', $methods, 2)); + $this->serviceObj->setDescription($this->getInput('Description:')); + $this->addRequestMethods(); if ($this->confirm('Would you like to add request parameters to the service?', false)) { $this->addParamsToService(); @@ -52,19 +66,72 @@ public function readClassInfo() { private function addParamsToService() { do { $paramObj = new RequestParameter('h'); - $paramObj->setType($this->select('Choose parameter type:', ParamType::getTypes(), 0)); $this->setParamName($paramObj); + $paramObj->setType($this->select('Choose parameter type:', ParamType::getTypes(), 0)); + $paramObj->setDescription($this->getInput('Description:')); $added = $this->serviceObj->addParameter($paramObj); $paramObj->setIsOptional($this->confirm('Is this parameter optional?', true)); + if ($paramObj->getType() == ParamType::STRING || $paramObj->getType() == ParamType::URL || $paramObj->getType() == ParamType::EMAIL) { + $paramObj->setIsEmptyStringAllowed($this->confirm('Are empty values allowed?', false)); + $this->setMinAndMaxLength($paramObj); + } + + if ($paramObj->getType() == ParamType::INT || $paramObj->getType() == ParamType::DOUBLE) { + $this->setMinAndMax($paramObj); + } + if ($added) { - $this->success('New parameter added to the service \''.$this->serviceObj->getName().'\'.'); + $this->success('New parameter added.'); } else { $this->warning('The parameter was not added.'); } $addMore = $this->confirm('Would you like to add another parameter?', false); } while ($addMore); } + private function setMinAndMax(RequestParameter $param) { + $setMinMax = $this->confirm('Would you like to set minimum and maximum limites?', false); + + if (!$setMinMax) { + return; + } + $isValid = false; + $method = $param->getType() == ParamType::INT ? 'readInteger' : 'readFloat'; + + while (!$isValid) { + $min = $this->getCommand()->$method('Minimum value:'); + $max = $this->getCommand()->$method('Maximum value:'); + + if ($min < $max) { + $param->setMinValue($min); + $param->setMaxValue($max); + $isValid = true; + } else { + $this->error('Minimum and maximum should not overlap.'); + } + } + } + private function setMinAndMaxLength(RequestParameter $param) { + $setMinMax = $this->confirm('Would you like to set minimum and maximum length?', false); + + if (!$setMinMax) { + return; + } + $isValid = false; + + while (!$isValid) { + $min = $this->getCommand()->readInteger('Minimum length:'); + $max = $this->getCommand()->readInteger('Maximum length:'); + + if ($min < $max) { + $param->setMinLength($min); + $param->setMaxLength($max); + $isValid = true; + } else { + $this->error('Minimum and maximum should not overlap.'); + } + } + } /** * * @param RequestParameter $paramObj diff --git a/webfiori/framework/config/ClassDriver.php b/webfiori/framework/config/ClassDriver.php index 90236dc7..43b3209d 100644 --- a/webfiori/framework/config/ClassDriver.php +++ b/webfiori/framework/config/ClassDriver.php @@ -33,6 +33,26 @@ public function __construct() { $this->docEmptyLine = " * "; $this->initDefaultConfig(); } + public static function a($file, $str, $tabSize = 0) { + $isResource = is_resource($file); + $tabStr = $tabSize > 0 ? ' ' : ''; + + if (gettype($str) == 'array') { + foreach ($str as $subStr) { + if ($isResource) { + fwrite($file, str_repeat($tabStr, $tabSize).$subStr.self::NL); + } else { + $file->append(str_repeat($tabStr, $tabSize).$subStr.self::NL); + } + } + } else { + if ($isResource) { + fwrite($file, str_repeat($tabStr, $tabSize).$str.self::NL); + } else { + $file->append(str_repeat($tabStr, $tabSize).$str.self::NL); + } + } + } /** * Adds application environment variable to the configuration. * @@ -54,15 +74,6 @@ public function addEnvVar(string $name, $value, string $description = null) { ]; $this->writeAppConfig(); } - /** - * Removes specific application environment variable given its name. - * - * @param string $name The name of the variable. - */ - public function removeEnvVar(string $name) { - unset($this->configVars['env-vars'][$name]); - $this->writeAppConfig(); - } /** * Adds new database connections information or update existing connection. * @@ -362,6 +373,15 @@ public function removeDBConnection(string $connectionName) { $this->configVars['database-connections'] = $updated; $this->writeAppConfig(); } + /** + * Removes specific application environment variable given its name. + * + * @param string $name The name of the variable. + */ + public function removeEnvVar(string $name) { + unset($this->configVars['env-vars'][$name]); + $this->writeAppConfig(); + } public function removeSMTPAccount(string $accountName) { if (isset($this->configVars['smtp-connections'][$accountName])) { @@ -861,26 +881,6 @@ public function writeAppConfig() { self::a($cFile, "}"); $cFile->write(false, true); } - public static function a($file, $str, $tabSize = 0) { - $isResource = is_resource($file); - $tabStr = $tabSize > 0 ? ' ' : ''; - - if (gettype($str) == 'array') { - foreach ($str as $subStr) { - if ($isResource) { - fwrite($file, str_repeat($tabStr, $tabSize).$subStr.self::NL); - } else { - $file->append(str_repeat($tabStr, $tabSize).$subStr.self::NL); - } - } - } else { - if ($isResource) { - fwrite($file, str_repeat($tabStr, $tabSize).$str.self::NL); - } else { - $file->append(str_repeat($tabStr, $tabSize).$str.self::NL); - } - } - } private function initDefaultConfig() { $this->configVars = [ 'smtp-connections' => [], diff --git a/webfiori/framework/config/ConfigurationDriver.php b/webfiori/framework/config/ConfigurationDriver.php index 40fcd411..367eade9 100644 --- a/webfiori/framework/config/ConfigurationDriver.php +++ b/webfiori/framework/config/ConfigurationDriver.php @@ -27,12 +27,6 @@ interface ConfigurationDriver { * of the constant. */ public function addEnvVar(string $name, $value, string $description = null); - /** - * Removes specific application environment variable given its name. - * - * @param string $name The name of the variable. - */ - public function removeEnvVar(string $name); /** * Adds new database connections information or update existing connections. * @@ -257,6 +251,12 @@ public function removeAllDBConnections(); * */ public function removeDBConnection(string $connectionName); + /** + * Removes specific application environment variable given its name. + * + * @param string $name The name of the variable. + */ + public function removeEnvVar(string $name); /** * Removes SMTP account if it exists. * diff --git a/webfiori/framework/config/JsonDriver.php b/webfiori/framework/config/JsonDriver.php index e457b380..4fd096fc 100644 --- a/webfiori/framework/config/JsonDriver.php +++ b/webfiori/framework/config/JsonDriver.php @@ -19,10 +19,6 @@ * @author Ibrahim */ class JsonDriver implements ConfigurationDriver { - /** - * The name of JSON configuration file. - */ - private static $configFileName = 'app-config'; /** * The location at which the configuration file will be kept at. * @@ -30,29 +26,9 @@ class JsonDriver implements ConfigurationDriver { */ const JSON_CONFIG_FILE_PATH = APP_PATH.'config'.DIRECTORY_SEPARATOR; /** - * Sets the name of the file that configuration values will be taken from. - * - * The file must exist on the directory [APP_PATH]/config/ . - * - * @param string $name - */ - public static function setConfigFileName(string $name) { - $split = explode('.', trim($name)); - if (count($split) == 2) { - self::$configFileName = $split[0]; - } else if (count($split) == 1) { - self::$configFileName = trim($name); - } - } - /** - * Returns the name of the file at which the application is using to - * read configuration. - * - * @return string + * The name of JSON configuration file. */ - public static function getConfigFileName() : string { - return self::$configFileName; - } + private static $configFileName = 'app-config'; private $json; /** * Creates new instance of the class. @@ -118,15 +94,6 @@ public function addEnvVar(string $name, $value, string $description = null) { ])); $this->writeJson(); } - /** - * Removes specific application environment variable given its name. - * - * @param string $name The name of the variable. - */ - public function removeEnvVar(string $name) { - $this->json->get('env-vars')->remove($name); - $this->writeJson(); - } public function addOrUpdateDBConnection(ConnectionInfo $dbConnectionsInfo) { $connectionJAsJson = new Json([ 'type' => $dbConnectionsInfo->getDatabaseType(), @@ -190,19 +157,30 @@ public function getAppVersionType() : string { } /** * Returns the base URL of the application. - * + * * Note that if the base is set so 'DYNAMIC' in the configuration, it will * be auto-generated at run time. - * + * * @return string A string such as 'http://example.com:8989'. */ public function getBaseURL(): string { $val = $this->json->get('base-url'); + if ($val == '' || $val == 'DYNAMIC') { return Uri::getBaseURL(); } + return $val; } + /** + * Returns the name of the file at which the application is using to + * read configuration. + * + * @return string + */ + public static function getConfigFileName() : string { + return self::$configFileName; + } public function getDBConnection(string $conName) { $jsonObj = $this->json->get('database-connections')->get($conName); @@ -210,11 +188,13 @@ public function getDBConnection(string $conName) { if ($jsonObj !== null) { $extras = $jsonObj->get('extras'); $extrasArr = []; + if ($extras instanceof Json) { foreach ($extras->getProperties() as $prop) { $extrasArr[$prop->getName()] = $prop->getValue(); } } + return new ConnectionInfo( $jsonObj->get('type'), $jsonObj->get('username'), @@ -239,15 +219,15 @@ public function getDBConnections(): array { $name = $propObj->getName(); $jsonObj = $propObj->getValue(); $acc = new ConnectionInfo( - $this->getProp($jsonObj, 'type', $name), - $this->getProp($jsonObj, 'username', $name), - $this->getProp($jsonObj, 'password', $name), - $this->getProp($jsonObj, 'database', $name)); + $this->getProp($jsonObj, 'type', $name), + $this->getProp($jsonObj, 'username', $name), + $this->getProp($jsonObj, 'password', $name), + $this->getProp($jsonObj, 'database', $name)); $extrasObj = $jsonObj->get('extras'); - + if ($extrasObj !== null && $extrasObj instanceof Json) { $extrasArr = []; - + foreach ($extrasObj->getProperties() as $prop) { $extrasArr[$prop->getName()] = $prop->getValue(); } @@ -261,13 +241,6 @@ public function getDBConnections(): array { return $retVal; } - private function getProp(Json $j, $name, string $connName) { - $val = $j->get($name); - if ($val === null) { - throw new InitializationException('The property "'.$name.'" of the connection "'.$connName.'" is missing.'); - } - return $val; - } public function getDescription(string $langCode) { return $this->json->get('app-descriptions')->get(strtoupper(trim($langCode))); @@ -305,17 +278,19 @@ public function getEnvVars(): array { } /** * Returns a string that represent the home page of the application. - * + * * Note that if home page is set to 'BASE_URL' in configuration, the * method will use the base URL as the home page. - * + * * @return string */ public function getHomePage() : string { $home = $this->json->get('home-page') ?? ''; + if ($home == 'BASE_URL') { return $this->getBaseURL(); } + return $home; } @@ -367,7 +342,7 @@ public function getSMTPConnection(string $name) { } /** * Returns an array that contains all added SMTP accounts. - * + * * @return array An array that contains all added SMTP accounts. */ public function getSMTPConnections(): array { @@ -406,11 +381,11 @@ public function getTheme(): string { public function getTitle(string $lang) : string { $titles = $this->json->get('titles'); $langU = strtoupper(trim($lang)); - + if (strlen($langU) == 0) { return ''; } - + foreach ($titles->getProperties() as $prob) { if ($prob->getName() == $langU) { return $prob->getValue(); @@ -465,6 +440,15 @@ public function removeAllDBConnections() { public function removeDBConnection(string $connectionName) { } + /** + * Removes specific application environment variable given its name. + * + * @param string $name The name of the variable. + */ + public function removeEnvVar(string $name) { + $this->json->get('env-vars')->remove($name); + $this->writeJson(); + } public function removeSMTPAccount(string $accountName) { $this->json->add('smtp-connections', new Json()); @@ -509,6 +493,22 @@ public function setAppVersion(string $vNum, string $vType, string $releaseDate) public function setBaseURL(string $url) { } + /** + * Sets the name of the file that configuration values will be taken from. + * + * The file must exist on the directory [APP_PATH]/config/ . + * + * @param string $name + */ + public static function setConfigFileName(string $name) { + $split = explode('.', trim($name)); + + if (count($split) == 2) { + self::$configFileName = $split[0]; + } else if (count($split) == 1) { + self::$configFileName = trim($name); + } + } /** * Sets or update default description of the application that will be used * by web pages. @@ -595,7 +595,7 @@ public function setTitle(string $title, string $langCode) { return; } $trimmedTitle = trim($title); - + if (strlen($trimmedTitle) == 0) { return; } @@ -612,7 +612,7 @@ public function setTitle(string $title, string $langCode) { */ public function setTitleSeparator(string $separator) { $trimmed = trim($separator); - + if (strlen($trimmed) != 0) { $this->json->add('name-separator', $separator); $this->writeJson(); @@ -621,6 +621,15 @@ public function setTitleSeparator(string $separator) { public function toJSON() : Json { return $this->json; } + private function getProp(Json $j, $name, string $connName) { + $val = $j->get($name); + + if ($val === null) { + throw new InitializationException('The property "'.$name.'" of the connection "'.$connName.'" is missing.'); + } + + return $val; + } private function isValidLangCode($langCode) { $code = strtoupper(trim($langCode)); @@ -638,6 +647,4 @@ private function writeJson() { $file->setRawData($json.''); $file->write(false, true); } - - } diff --git a/webfiori/framework/router/RouteOption.php b/webfiori/framework/router/RouteOption.php index c97bc121..0a3827d7 100644 --- a/webfiori/framework/router/RouteOption.php +++ b/webfiori/framework/router/RouteOption.php @@ -8,7 +8,6 @@ * https://github.com/WebFiori/.github/blob/main/LICENSE * */ - namespace webfiori\framework\router; /** @@ -18,55 +17,55 @@ */ class RouteOption { /** - * An option that represents the path part of the URI. - */ - const PATH = 'path'; - /** - * An option which is used to set the resource at which the route will point to. + * An option which is used to set the name of controller action that will be invoked (MVC). */ - const TO = 'route-to'; + const ACTION = 'action'; /** - * An option which is used to set route type. + * An option which is used to treat the route as an API call. */ - const TYPE = 'type'; + const API = 'as-api'; /** * An option which is used to indicate if path is case sensitive or not. */ const CASE_SENSITIVE = 'case-sensitive'; /** - * An option which is used to tell if the route should be part of auto-generated sitemap or not. + * An option which is used to set an array as closure parameters (applies to routes of type closure only) */ - const SITEMAP = 'in-sitemap'; + const CLOSURE_PARAMS = 'closure-params'; /** - * An option which is used to treat the route as an API call. + * An option which is used to set the languages at which the route will be available at (used in building sitemap). */ - const API = 'as-api'; + const LANGS = 'languages'; /** - * An option which is used to set an array as closure parameters (applies to routes of type closure only) + * An option which is used to set the middleware that will be applied to the route. */ - const CLOSURE_PARAMS = 'closure-params'; + const MIDDLEWARE = 'middleware'; /** - * An option which is used to set the name of controller action that will be invoked (MVC). + * An option that represents the path part of the URI. */ - const ACTION = 'action'; + const PATH = 'path'; /** * An option which is used to set an array of allowed request methods. */ const REQUEST_METHODS = 'methods'; /** - * An option which is used to set the languages at which the route will be available at (used in building sitemap). + * An option which is used to tell if the route should be part of auto-generated sitemap or not. */ - const LANGS = 'languages'; + const SITEMAP = 'in-sitemap'; /** - * An option which is used to set an array of allowed values to route parameters. + * An option which is used to set sub-routes. */ - const VALUES = 'vars-values'; + const SUB_ROUTES = 'routes'; /** - * An option which is used to set the middleware that will be applied to the route. + * An option which is used to set the resource at which the route will point to. */ - const MIDDLEWARE = 'middleware'; + const TO = 'route-to'; /** - * An option which is used to set sub-routes. + * An option which is used to set route type. */ - const SUB_ROUTES = 'routes'; + const TYPE = 'type'; + /** + * An option which is used to set an array of allowed values to route parameters. + */ + const VALUES = 'vars-values'; } diff --git a/webfiori/framework/router/Router.php b/webfiori/framework/router/Router.php index 795eed6c..3285bf05 100644 --- a/webfiori/framework/router/Router.php +++ b/webfiori/framework/router/Router.php @@ -1103,6 +1103,16 @@ private function fixUriPath(string $path): string { return $path; } + private function getFileDirAndName($absDir): array { + $explode = explode(DS, $absDir); + $fileName = $explode[count($explode) - 1]; + $dir = substr($absDir, 0, strlen($absDir) - strlen($fileName)); + + return [ + 'name' => $fileName, + 'dir' => $dir + ]; + } /** * Creates and Returns a single instance of the router. * @@ -1118,16 +1128,6 @@ private static function getInstance(): Router { return self::$router; } - private function getFileDirAndName($absDir): array { - $explode = explode(DS, $absDir); - $fileName = $explode[count($explode) - 1]; - $dir = substr($absDir, 0, strlen($absDir) - strlen($fileName)); - - return [ - 'name' => $fileName, - 'dir' => $dir - ]; - } /** * Returns an array that holds allowed request methods for fetching the * specified resource. diff --git a/webfiori/framework/scheduler/TasksManager.php b/webfiori/framework/scheduler/TasksManager.php index 142ea81f..932a0f4a 100644 --- a/webfiori/framework/scheduler/TasksManager.php +++ b/webfiori/framework/scheduler/TasksManager.php @@ -281,6 +281,20 @@ public static function get(): TasksManager { return self::$tasksManager; } + /** + * Returns the number of current hour in the day as integer. + * + * This method is used by the class 'AbstractTask' to validate task + * execution time. The method will always return a value between 0 and 23 + * inclusive. + * + * @return int An integer that represents current hour number in + * the day. + * @since 1.0.2 + */ + public static function getHour() : int { + return self::get()->timestamp['hour']; + } /** * Returns the array that contains logged messages. * @@ -294,6 +308,48 @@ public static function get(): TasksManager { public static function getLogArray() : array { return self::get()->logsArray; } + /** + * Returns the number of current minute in the current hour as integer. + * + * This method is used by the class 'AbstractTask' to validate task + * execution time. The method will always return a value between 0 and 59 + * inclusive. + * + * @return int An integer that represents current minute number in + * the current hour. + * + * @since 1.0.2 + */ + public static function getMinute() : int { + return self::get()->timestamp['minute']; + } + /** + * Returns the number of current month as integer. + * + * This method is used by the class 'AbstracTask' to validate task + * execution time. The method will always return a value between 1 and 12 + * inclusive. + * + * @return int An integer that represents current month's number. + * @since 1.0.2 + */ + public static function getMonth() : int { + return self::get()->timestamp['month']; + } + /** + * Gets the password that is used to protect tasks execution. + * + * The password is used to prevent unauthorized access to execute tasks. + * The provided password must be 'sha256' hashed string. It is recommended + * to hash the password externally then use the hash inside your code. + * + * @return string If the password is set, the method will return it. + * If not set, the method will return the string 'NO_PASSWORD'. + * + */ + public static function getPassword() : string { + return self::get()->getPasswordHelper(); + } /** * Returns a task given its name. * @@ -338,18 +394,42 @@ public static function getTasksNames() : array { return self::get()->tasksNamesArr; } /** - * Returns the number of current hour in the day as integer. + * Returns the time at which tasks check was initialized. * - * This method is used by the class 'AbstractTask' to validate task - * execution time. The method will always return a value between 0 and 23 - * inclusive. + * @return string The method will return a time string in the format + * 'YY-DD HH:MM' where: + *