From 3a95e37c29aba4a77172ce9654ca1ee65b573b92 Mon Sep 17 00:00:00 2001 From: Osahenrumwen Aigbogun Date: Sat, 16 Dec 2023 19:22:39 +0100 Subject: [PATCH 01/10] First batch of production --- .gitignore | 1 + README.md | 4 +- __internal/Domain/Plaster.php | 52 ++++ __internal/Domain/index.php | 11 + __internal/Domain/layout/body.inc | 2 + __internal/Domain/layout/head.inc | 5 + __internal/Domain/layout/script.inc | 3 + __internal/Domain/plaster/another.view | 10 + __internal/Domain/plaster/homepage.view | 10 + __internal/Domain/static/dev/css/another.css | 9 + __internal/Domain/static/dev/css/style.css | 3 + __internal/Domain/static/dev/js/another.js | 1 + bob | 6 + bob.php | 185 -------------- compress.php | 6 +- deploy_composer | 4 +- init-project/files/DefaultViews.php | 6 +- init-project/files/Email.php | 4 +- init-project/files/EndUsers.php | 2 +- init-project/files/api.php | 2 +- init-project/files/error.view | 7 +- init-project/files/git-auto-deploy.php | 2 +- init-project/files/head.inc | 2 +- init-project/files/index.php | 2 +- init-project/files/layconfig.php | 2 +- init-project/files/root_index.php | 2 +- init-project/files/script.inc | 2 +- Autoloader.php => src/Autoloader.php | 8 +- src/BobDBuilder/Cmd/Make.php | 41 ++++ src/BobDBuilder/Cmd/Project.php | 54 ++++ src/BobDBuilder/Cmd/Symlink.php | 153 ++++++++++++ src/BobDBuilder/Engine.php | 73 ++++++ src/BobDBuilder/EnginePlug.php | 231 ++++++++++++++++++ src/BobDBuilder/Enum/CmdOutType.php | 11 + src/BobDBuilder/Helper/Console/Console.php | 52 ++++ .../Helper/Console/Format/Background.php | 15 ++ .../Helper/Console/Format/Foreground.php | 28 +++ .../Helper/Console/Format/Style.php | 11 + src/BobDBuilder/Interface/CmdLayout.php | 26 ++ src/{core/api => Core/Api}/ApiEngine.php | 8 +- src/{core/api => Core/Api}/ApiHooks.php | 6 +- .../Api/Enums}/ApiRequestMethod.php | 2 +- .../Enums}/CustomContinueBreak.php | 2 +- src/Core/Enums/LayMode.php | 9 + src/{core => Core}/Exception.php | 4 +- src/Core/LayConfig.php | 17 ++ src/{core/traits => Core/Traits}/Config.php | 16 +- src/{core/traits => Core/Traits}/Includes.php | 8 +- src/{core/traits => Core/Traits}/Init.php | 32 ++- .../traits => Core/Traits}/IsSingleton.php | 2 +- .../traits => Core/Traits}/Resources.php | 93 ++++--- src/{core/view => Core/View}/Domain.php | 14 +- .../view => Core/View}/DomainResource.php | 20 +- .../View/Enums}/DomainCacheKeys.php | 2 +- .../enums => Core/View/Enums}/DomainType.php | 2 +- .../view/tags => Core/View/Tags}/Anchor.php | 12 +- .../view/tags => Core/View/Tags}/Img.php | 14 +- .../view/tags => Core/View/Tags}/Link.php | 6 +- .../view/tags => Core/View/Tags}/Script.php | 10 +- .../View/Tags/Traits}/Standard.php | 4 +- src/{core/view => Core/View}/ViewBuilder.php | 151 +++++++++--- src/{core/view => Core/View}/ViewCast.php | 4 +- src/{core/view => Core/View}/ViewEngine.php | 23 +- src/{core/view => Core/View}/ViewSrc.php | 2 +- src/{libs => Libs}/CopyDirectory.php | 2 +- src/{libs => Libs}/DeleteDirectory.php | 2 +- src/{libs => Libs}/LayArraySearch.php | 2 +- src/{libs => Libs}/LayCSV.php | 2 +- src/{libs => Libs}/LayCache.php | 8 +- src/{libs => Libs}/LayCalendarEvent.php | 4 +- src/{libs => Libs}/LayCookieStorage.php | 217 ++++++++-------- src/Libs/LayCopyDir.php | 65 +++++ src/{libs => Libs}/LayCron.php | 6 +- src/{libs => Libs}/LayDate.php | 4 +- src/{libs => Libs}/LayGenId.php | 6 +- src/{libs => Libs}/LayImage.php | 8 +- src/{libs => Libs}/LayMail.php | 16 +- src/{libs => Libs}/LayObject.php | 6 +- src/{libs => Libs}/LayPassword.php | 2 +- src/{libs => Libs}/LayWordCount.php | 4 +- src/{orm => Orm}/Config.php | 2 +- src/{orm => Orm}/Exception.php | 66 +++-- src/{orm => Orm}/QueryStatus.php | 2 +- src/{orm => Orm}/SQL.php | 4 +- src/{orm => Orm}/StoreResult.php | 2 +- src/{orm/traits => Orm/Traits}/Clean.php | 4 +- src/{orm/traits => Orm/Traits}/Controller.php | 4 +- .../traits => Orm/Traits}/SelectorOOP.php | 4 +- .../traits => Orm/Traits}/SelectorOOPCrud.php | 4 +- src/core/LayConfig.php | 17 -- src/interfaces/Model.php | 11 - src/{omj$ => static/omjs}/index.js | 0 src/{omj$ => static/omjs}/index.min.js | 0 tests/Unit/FakeControllerSingleton.php | 2 +- tests/Unit/api/ApiRequestTest.php | 2 +- 95 files changed, 1418 insertions(+), 571 deletions(-) create mode 100644 __internal/Domain/Plaster.php create mode 100644 __internal/Domain/index.php create mode 100644 __internal/Domain/layout/body.inc create mode 100644 __internal/Domain/layout/head.inc create mode 100644 __internal/Domain/layout/script.inc create mode 100644 __internal/Domain/plaster/another.view create mode 100644 __internal/Domain/plaster/homepage.view create mode 100644 __internal/Domain/static/dev/css/another.css create mode 100644 __internal/Domain/static/dev/css/style.css create mode 100644 __internal/Domain/static/dev/js/another.js create mode 100644 bob delete mode 100644 bob.php rename Autoloader.php => src/Autoloader.php (88%) create mode 100644 src/BobDBuilder/Cmd/Make.php create mode 100644 src/BobDBuilder/Cmd/Project.php create mode 100644 src/BobDBuilder/Cmd/Symlink.php create mode 100644 src/BobDBuilder/Engine.php create mode 100644 src/BobDBuilder/EnginePlug.php create mode 100644 src/BobDBuilder/Enum/CmdOutType.php create mode 100644 src/BobDBuilder/Helper/Console/Console.php create mode 100644 src/BobDBuilder/Helper/Console/Format/Background.php create mode 100644 src/BobDBuilder/Helper/Console/Format/Foreground.php create mode 100644 src/BobDBuilder/Helper/Console/Format/Style.php create mode 100644 src/BobDBuilder/Interface/CmdLayout.php rename src/{core/api => Core/Api}/ApiEngine.php (98%) rename src/{core/api => Core/Api}/ApiHooks.php (81%) rename src/{core/api/enums => Core/Api/Enums}/ApiRequestMethod.php (79%) rename src/{core/enums => Core/Enums}/CustomContinueBreak.php (79%) create mode 100644 src/Core/Enums/LayMode.php rename src/{core => Core}/Exception.php (87%) create mode 100644 src/Core/LayConfig.php rename src/{core/traits => Core/Traits}/Config.php (97%) rename src/{core/traits => Core/Traits}/Includes.php (96%) rename src/{core/traits => Core/Traits}/Init.php (87%) rename src/{core/traits => Core/Traits}/IsSingleton.php (91%) rename src/{core/traits => Core/Traits}/Resources.php (68%) rename src/{core/view => Core/View}/Domain.php (97%) rename src/{core/view => Core/View}/DomainResource.php (83%) rename src/{core/view/enums => Core/View/Enums}/DomainCacheKeys.php (80%) rename src/{core/view/enums => Core/View/Enums}/DomainType.php (70%) rename src/{core/view/tags => Core/View/Tags}/Anchor.php (89%) rename src/{core/view/tags => Core/View/Tags}/Img.php (78%) rename src/{core/view/tags => Core/View/Tags}/Link.php (91%) rename src/{core/view/tags => Core/View/Tags}/Script.php (83%) rename src/{core/view/tags/traits => Core/View/Tags/Traits}/Standard.php (90%) rename src/{core/view => Core/View}/ViewBuilder.php (70%) rename src/{core/view => Core/View}/ViewCast.php (96%) rename src/{core/view => Core/View}/ViewEngine.php (96%) rename src/{core/view => Core/View}/ViewSrc.php (96%) rename src/{libs => Libs}/CopyDirectory.php (98%) rename src/{libs => Libs}/DeleteDirectory.php (96%) rename src/{libs => Libs}/LayArraySearch.php (98%) rename src/{libs => Libs}/LayCSV.php (97%) rename src/{libs => Libs}/LayCache.php (94%) rename src/{libs => Libs}/LayCalendarEvent.php (96%) rename src/{libs => Libs}/LayCookieStorage.php (67%) create mode 100644 src/Libs/LayCopyDir.php rename src/{libs => Libs}/LayCron.php (99%) rename src/{libs => Libs}/LayDate.php (98%) rename src/{libs => Libs}/LayGenId.php (96%) rename src/{libs => Libs}/LayImage.php (97%) rename src/{libs => Libs}/LayMail.php (95%) rename src/{libs => Libs}/LayObject.php (95%) rename src/{libs => Libs}/LayPassword.php (98%) rename src/{libs => Libs}/LayWordCount.php (95%) rename src/{orm => Orm}/Config.php (99%) rename src/{orm => Orm}/Exception.php (81%) rename src/{orm => Orm}/QueryStatus.php (76%) rename src/{orm => Orm}/SQL.php (98%) rename src/{orm => Orm}/StoreResult.php (98%) rename src/{orm/traits => Orm/Traits}/Clean.php (99%) rename src/{orm/traits => Orm/Traits}/Controller.php (57%) rename src/{orm/traits => Orm/Traits}/SelectorOOP.php (98%) rename src/{orm/traits => Orm/Traits}/SelectorOOPCrud.php (99%) delete mode 100644 src/core/LayConfig.php delete mode 100644 src/interfaces/Model.php rename src/{omj$ => static/omjs}/index.js (100%) rename src/{omj$ => static/omjs}/index.min.js (100%) diff --git a/.gitignore b/.gitignore index 131ac19..208a362 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ .logs logs *.log +*.lock npm-debug.log* yarn-debug.log* yarn-error.log* diff --git a/README.md b/README.md index 1e786f0..237932d 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Current Version: `1.0.0` ## Get Started 1. Ensure you have at the latest specified version of php installed. -2. Copy the `init-lay` file to your server root directory or where you wish to initialize new projects using the command line. +2. Copy the `_init-lay` file to your server root directory or where you wish to initialize new projects using the command line. 3. Open the script and replace the `$default_lay_location` variable with the path of the Lay package you cloned. -4. To create a new project, open your command line app and type `php init-lay sample-project` or use `php init-lay -h` for help on how to use the script. +4. To create a new project, open your command line app and type `php _init-lay sample-project` or use `php _init-lay -h` for help on how to use the script. 5. When the script is done, you can open the project like a regular webserver project. Example: `localhost/sample-project` ## Documentation diff --git a/__internal/Domain/Plaster.php b/__internal/Domain/Plaster.php new file mode 100644 index 0000000..a847af6 --- /dev/null +++ b/__internal/Domain/Plaster.php @@ -0,0 +1,52 @@ +builder->init_start() + ->body_attr("dark", 'id="body-id"') + ->local("logo", DomainResource::get()->shared->img_default->logo) + ->local("section", "app") + ->init_end(); + } + + public function pages(): void + { + $this->builder->route("index")->bind(function (ViewBuilder $builder) { + $builder + ->page("title", "Homepage") + ->page("desc", "This is the default homepage description") + ->assets( + "@css/another.css", + ) + ->body("homepage"); + }); + + $this->builder->route("another-page")->bind(function (ViewBuilder $builder) { + $builder->connect_db() + ->page("title", "Another Page") + ->page("desc", "This is another page's description") + ->assets( + "@css/another.css", + ) + ->body("another"); + }); + } + + public function default(): void + { + $this->builder->route($this->builder::DEFAULT_ROUTE)->bind(function (ViewBuilder $builder){ + $builder->page('title', $this->builder->request('route') . " - Page not Found") + ->body_attr("default-home") + ->local("section", "error") + ->body('error'); + }); + } +} \ No newline at end of file diff --git a/__internal/Domain/index.php b/__internal/Domain/index.php new file mode 100644 index 0000000..c6ab06c --- /dev/null +++ b/__internal/Domain/index.php @@ -0,0 +1,11 @@ +create( + id: "default", + builder: new \web\domains\Default\Plaster(), +); \ No newline at end of file diff --git a/__internal/Domain/layout/body.inc b/__internal/Domain/layout/body.inc new file mode 100644 index 0000000..a2dc584 --- /dev/null +++ b/__internal/Domain/layout/body.inc @@ -0,0 +1,2 @@ +body; diff --git a/__internal/Domain/layout/head.inc b/__internal/Domain/layout/head.inc new file mode 100644 index 0000000..719d405 --- /dev/null +++ b/__internal/Domain/layout/head.inc @@ -0,0 +1,5 @@ +rel("stylesheet")->href("@css/style.css"); + +echo \BrickLayer\Lay\core\view\DomainResource::plaster()->head; diff --git a/__internal/Domain/layout/script.inc b/__internal/Domain/layout/script.inc new file mode 100644 index 0000000..9f3d080 --- /dev/null +++ b/__internal/Domain/layout/script.inc @@ -0,0 +1,3 @@ +src("@js/another.js"); +echo \BrickLayer\Lay\Core\View\DomainResource::plaster()->script; diff --git a/__internal/Domain/plaster/another.view b/__internal/Domain/plaster/another.view new file mode 100644 index 0000000..f4f097a --- /dev/null +++ b/__internal/Domain/plaster/another.view @@ -0,0 +1,10 @@ + + +
Lay Logo
+

page->title ?>

+

This is the another page of Lay a lite php framework

+

Modify the necessary things to start your project

+Link to home page diff --git a/__internal/Domain/plaster/homepage.view b/__internal/Domain/plaster/homepage.view new file mode 100644 index 0000000..4ce0939 --- /dev/null +++ b/__internal/Domain/plaster/homepage.view @@ -0,0 +1,10 @@ + + +
Lay Logo
+

page->title ?>

+

This is the default index page of Lay a lite php framework

+

Modify the necessary things to start your project

+Link to another page diff --git a/__internal/Domain/static/dev/css/another.css b/__internal/Domain/static/dev/css/another.css new file mode 100644 index 0000000..d37e4c6 --- /dev/null +++ b/__internal/Domain/static/dev/css/another.css @@ -0,0 +1,9 @@ +body{ + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + color: #041039; + flex-flow: column; + font-size: 1.2rem; +} \ No newline at end of file diff --git a/__internal/Domain/static/dev/css/style.css b/__internal/Domain/static/dev/css/style.css new file mode 100644 index 0000000..bce52fc --- /dev/null +++ b/__internal/Domain/static/dev/css/style.css @@ -0,0 +1,3 @@ +body { + border: solid 2px #e00; +} \ No newline at end of file diff --git a/__internal/Domain/static/dev/js/another.js b/__internal/Domain/static/dev/js/another.js new file mode 100644 index 0000000..78487f2 --- /dev/null +++ b/__internal/Domain/static/dev/js/another.js @@ -0,0 +1 @@ +osNote("Hurray🥳🥳 Lay is all set up ") diff --git a/bob b/bob new file mode 100644 index 0000000..be94ab0 --- /dev/null +++ b/bob @@ -0,0 +1,6 @@ +#!/usr/bin/env php +>> BobTheBuilder SAYS (::--__--::)\n\n"; - - foreach (explode("\n", $message) as $m) { - print " " . $m . "\n"; - } - - print "\n####> BobTheBuilder DONE TALKING...(-_-)\n"; - die; -}; - - -if($argc == 1) { - $intro(); - die; -} - -$opts = []; -foreach ($argv as $k => $a) { - get_arg($a, $k, $opts['link_htaccess'], "link:htaccess"); - get_arg($a, [$k, $k + 1], $opts['link_dir'], "link:dir"); - get_arg($a, [$k, $k + 1], $opts['link_file'], "link:file"); - get_arg($a, 0, $opts['force_action'], "--force"); -} - -if(@$opts['help']) { - $intro(); - cmd_out( - ">>> Bob The Builder is meant aid in building your application\n" . - ">>> directory indicated using the -o flag. This helps save production time\n" . - "----------------------------------------------------------\n" . - "### Usage: [$script_name] {directory_name} [--output || -o] {output_directory}\n" . - "### Example: php $script_name dir/js -o prod-dir/js" - , ["type" => "info"] - ); -} - -$fs = LayConfig::server_data(); -$s = DIRECTORY_SEPARATOR; -$force = $opts['force_action'] ?? false; - -if($dest = @$opts['link_htaccess']) { - $dest = $fs->domains . rtrim(str_replace(".htaccess","", $dest), "/") . $s; - - if(!is_dir($dest)) { - if(!$force) - cmd_out("Directory $dest does not exist! if you want the directory to be created automatically, pass the flag --force", [ - "type" => "fail" - ]); - - umask(0); - mkdir($dest, 0777, true); - } - - $dest .= ".htaccess"; - - if(file_exists($dest)) { - if(!$force) - cmd_out( - "htaccess exists already at: $dest" - . "If you want to REPLACE!! it, pass the flag --force\n" - . "***### Take Note:: You will be deleting the former htaccess if you decide to pass the flag --force" - , ["type" => "warn"] - ); - - unlink($dest); - } - - symlink($fs->web . ".htaccess", $dest); - - cmd_out("htaccess successfully linked to: $dest", [ - "type" => "success" - ]); -} - -if($link = @$opts['link_dir']) { - - $src = $fs->root . $link[0]; - $dest = $fs->root . $link[1]; - - if(!is_dir($src)) - cmd_out( - "Source directory $src does not exist!\n" - . "You cannot link a directory that doesn't exist" - , ["type" => "fail"] - ); - - if(is_dir($dest)) { - if(!$force) - cmd_out( - "Destination directory: $dest exists already!\n" - . "If you want to REPLACE!! it, pass the flag --force\n" - . "***### Take Note:: You will be deleting the former directory if you decide to pass the flag --force" - , ["type" => "warn"] - ); - - unlink($dest); - } - - symlink($src, $dest); - - cmd_out( - "Directory link created successfully!\n" - . "Source Directory: $src\n" - . "Destination Directory: $dest" - , [ "type" => "success" ] - ); -} - -if($link = @$opts['link_file']) { - - $src = $fs->root . $link[0]; - $dest = $fs->root . $link[1]; - - if(!file_exists($src)) - cmd_out("Source file $src does not exist! You cannot link a file that doesn't exist", [ - "type" => "fail" - ]); - - if(file_exists($dest)) { - if(!$force) - cmd_out( - "Destination file: $dest exists already!\n" - . "If you want to REPLACE!! it, pass the flag --force\n" - . "***### Take Note:: You will be deleting the former file if you decide to pass the flag --force" - ,["type" => "warn"] - ); - - unlink($dest); - } - - symlink($src, $dest); - - cmd_out( - "Directory link created successfully!\n" - . "Source Directory: $src\n" - . "Destination Directory: $dest" - , [ "type" => "success" ] - ); -} - diff --git a/compress.php b/compress.php index 467fc9d..5030f3d 100644 --- a/compress.php +++ b/compress.php @@ -1,9 +1,9 @@ root; $temp = $server->temp; $command = file_exists($root . "composer.lock") ? "update" : "install"; @@ -12,4 +12,4 @@ exec("export HOME=$root && cd $root && composer $command --no-dev --optimize-aut file_put_contents($temp . "deploy_composer_output.txt", implode("\n", $out)); // unset cron job after updating composer packages -\BrickLayer\Lay\libs\LayCron::new()->unset("update-composer-pkgs"); +\BrickLayer\Lay\Libs\LayCron::new()->unset("update-composer-pkgs"); diff --git a/init-project/files/DefaultViews.php b/init-project/files/DefaultViews.php index 09d8a25..63688c8 100644 --- a/init-project/files/DefaultViews.php +++ b/init-project/files/DefaultViews.php @@ -3,9 +3,9 @@ namespace res\server\view; -use BrickLayer\Lay\core\LayConfig; -use BrickLayer\Lay\core\view\ViewBuilder; -use BrickLayer\Lay\core\view\ViewCast; +use BrickLayer\Lay\Core\LayConfig; +use BrickLayer\Lay\Core\View\ViewBuilder; +use BrickLayer\Lay\Core\View\ViewCast; class DefaultViews extends ViewCast { diff --git a/init-project/files/Email.php b/init-project/files/Email.php index 83071f2..eaf6124 100644 --- a/init-project/files/Email.php +++ b/init-project/files/Email.php @@ -2,8 +2,8 @@ namespace res\server\utils; -use BrickLayer\Lay\core\traits\IsSingleton; -use BrickLayer\Lay\libs\LayMail; +use BrickLayer\Lay\Core\Traits\IsSingleton; +use BrickLayer\Lay\Libs\LayMail; class Email extends LayMail { diff --git a/init-project/files/EndUsers.php b/init-project/files/EndUsers.php index 6fac28c..7e03e3d 100644 --- a/init-project/files/EndUsers.php +++ b/init-project/files/EndUsers.php @@ -2,7 +2,7 @@ namespace res\server\controller\__front; -use BrickLayer\Lay\libs\LayObject; +use BrickLayer\Lay\Libs\LayObject; use res\server\utils\Email; class EndUsers diff --git a/init-project/files/api.php b/init-project/files/api.php index 57e29fa..5c77f48 100644 --- a/init-project/files/api.php +++ b/init-project/files/api.php @@ -4,7 +4,7 @@ require_once __DIR__ . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . "layconfig.php"; -$req = \BrickLayer\Lay\core\api\ApiEngine::new(); +$req = \BrickLayer\Lay\Core\Api\ApiEngine::new(); $req::fetch(); $req->prefix("client") diff --git a/init-project/files/error.view b/init-project/files/error.view index a0d0d62..2aa8fec 100644 --- a/init-project/files/error.view +++ b/init-project/files/error.view @@ -1,6 +1,3 @@ - -

page->title ?>

+

page->title ?>

This is the default error page of Lay Framework

-Return Home +Return Home diff --git a/init-project/files/git-auto-deploy.php b/init-project/files/git-auto-deploy.php index ea01b95..41369a2 100644 --- a/init-project/files/git-auto-deploy.php +++ b/init-project/files/git-auto-deploy.php @@ -29,7 +29,7 @@ echo shell_exec('git reset --hard origin/main 2>&1'); // push composer deployment for later execution to avoid 504 (timeout error) -echo \BrickLayer\Lay\libs\LayCron::new() +echo \BrickLayer\Lay\Libs\LayCron::new() ->job_id("update-composer-pkgs") ->every_minute() ->new_job("Lay/deploy_composer")['msg']; diff --git a/init-project/files/head.inc b/init-project/files/head.inc index 4faf0f6..3d34507 100644 --- a/init-project/files/head.inc +++ b/init-project/files/head.inc @@ -1,6 +1,6 @@ rel("stylesheet")->href("@custom/css/style.css"); +\BrickLayer\Lay\Core\View\Tags\Link::new()->rel("stylesheet")->href("@custom/css/style.css"); ?>

This is the default error page of Lay Framework

- Return Home + Return Home $const[self::key_body] ?? null, self::key_script => $const[self::key_script] ?? null, /** - * `assets` searches for assets based on the `ARRAY_KEY`/`DIRECTORY_NAME` + * `assets` searches for assets based on the `ARRAY_KEY`/`PATH_TO_FILE` * @example "assets" => [ "@shared_js/contact-us.js", "@css/style.css" ]. * The entries can also be an array: * @example "assets" => [ ["src" => "@shared_js/contact-us.js", "async" => true, "type" => "text/javascript"], ] @@ -102,7 +102,7 @@ public function paint(array $page_data) : void { $const[self::key_page]['title_raw'] = $const[self::key_page]['title']; if(strtolower($const[self::key_page]['title_raw']) == "homepage"){ - $const[self::key_page]['title'] = $data->name->full; + $const[self::key_page]['title'] = $data->name->long; $const[self::key_page]['title_raw'] = $data->name->short; } else{ @@ -284,6 +284,11 @@ private function dump_assets(string $asset_type) : void // if the asset item is an array; // ['src' => asset_file, 'defer' => true, 'async' => false, 'type' => 'text/javascript'] if (is_array($asset)) { + if(isset($asset['href'])) { + $asset['src'] = $asset['href']; + unset($asset['href']); + } + if (isset($asset['src'])) { if(!str_ends_with($asset['src'],".$asset_type")) return ""; diff --git a/src/core/view/ViewSrc.php b/src/Core/View/ViewSrc.php similarity index 96% rename from src/core/view/ViewSrc.php rename to src/Core/View/ViewSrc.php index 21b986e..c65e136 100644 --- a/src/core/view/ViewSrc.php +++ b/src/Core/View/ViewSrc.php @@ -1,6 +1,6 @@ clean(self::lay()->get_site_data('name','short'),6); + private static string $table = "lay_cookie_storages"; + + public static function save_to_db(string $immutable_key): bool + { + self::init(); + + self::delete_expired_tokens(); + + if (isset($_COOKIE[self::$session_user_cookie])) + return true; + + + return self::set_cookie( + self::$session_user_cookie, + LayPassword::crypt(LayCookieStorage::save_user_token($immutable_key)) + ); + } + + private static function init(): void + { + if (!isset(self::$session_user_cookie)) + self::$session_user_cookie = "lay_cok_" . self::orm()->clean(self::lay()::site_data()->name->short, 6); self::create_table(); } - private static function lay (): LayConfig { + + private static function lay(): LayConfig + { return LayConfig::instance(); } - private static function create_table() : void { + private static function create_table(): void + { $table = self::$table; // check if table exists, but catch the error self::orm()->open(self::$table)->catch()->clause("LIMIT 1")->select(); // Check if the above query had an error. If no error, table exists, else table doesn't exist - if(self::orm()->query_info['has_error'] === false) + if (self::orm()->query_info['has_error'] === false) return; self::orm()->query("CREATE TABLE IF NOT EXISTS `$table` ( @@ -50,27 +74,30 @@ private static function create_table() : void { "); } - private static function orm() : SQL { - return SQL::instance(); + private static function delete_expired_tokens(): void + { + $today = LayDate::date(); + self::orm()->open(self::$table)->delete("DATEDIFF('$today',`expire`) > 30"); } - private static function set_cookie(string $name, string $value, array $options = [] ) : bool { + private static function set_cookie(string $name, string $value, array $options = []): bool + { extract([ 'expires' => $options['expires'] ?? "30 days", 'path' => $options['path'] ?? "/", - 'domain' => $options['domain'] ?? null, - 'httponly' => $options['httponly'] ?? false, - 'samesite' => $options['samesite'] ?? "Lax", - 'secure' => $options['secure'] ?? null, + 'domain' => $options['domain'] ?? null, + 'httponly' => $options['httponly'] ?? false, + 'samesite' => $options['samesite'] ?? "Lax", + 'secure' => $options['secure'] ?? null, ]); if (self::lay()::$ENV_IS_DEV) $secure = $secure ?? false; - $name = str_replace(["=", ",", ";", " ", "\t", "\r", "\n", "\013","\014"],"",$name); + $name = str_replace(["=", ",", ";", " ", "\t", "\r", "\n", "\013", "\014"], "", $name); setcookie($name, $value, [ - "expires" => $expires == 0 ? (int) $expires : strtotime($expires), + "expires" => $expires == 0 ? (int)$expires : strtotime($expires), "path" => $path, "domain" => $domain ?? $_SERVER['HTTP_HOST'], "secure" => $secure ?? true, @@ -81,32 +108,12 @@ private static function set_cookie(string $name, string $value, array $options = return isset($_COOKIE[$name]); } - private static function store_user_token(string $user_id) : ?string { - $orm = self::orm(); - $env_info = self::browser_info() . " IP: " . LayConfig::get_ip(); - $expire = LayDate::date("30 days"); - $now = LayDate::date(); - $user_id = $orm->clean($user_id,16,'strict'); - - self::delete_expired_tokens(); - - $orm->open(self::$table)->then_insert([ - "id" => "UUID()", - "created_by" => $user_id, - "created_at" => $now, - "auth" => LayPassword::hash($user_id), - "expire" => $expire, - "env_info" => $env_info - ]); - - return $orm->table(self::$table)->last_item("created_at")['id']; - } - - private static function save_user_token(string $user_id) : ?string { + private static function save_user_token(string $user_id): ?string + { $today = LayDate::date(); $data = self::validate_cookie()['data']; - if(!empty($data)) { + if (!empty($data)) { self::orm()->open(self::$table) ->column(["expire" => $today]) ->then_update("WHERE created_by='{$data['created_by']}' AND auth='{$data['auth']}'"); @@ -116,89 +123,111 @@ private static function save_user_token(string $user_id) : ?string { return self::store_user_token($user_id); } - private static function get_user_token(string $id) : array { - $orm = self::orm(); - $id = $orm->clean($id,16,'strict'); + public static function validate_cookie(): array + { + self::init(); - return $orm->open(self::$table) - ->column("created_by, auth") - ->then_select("WHERE id='$id'"); - } + if (!isset($_COOKIE[self::$session_user_cookie])) + return ["code" => 2, "msg" => "Cookie is not set", "data" => null]; - private static function destroy_cookie($name) : void { - self::set_cookie($name, "", ["expires" => "now",]); + if ($id = self::decrypt_cookie()) + return [ + "code" => 1, + "msg" => "Cookie found!", + "data" => self::get_user_token($id) + ]; + + return ["code" => 0, "msg" => "Could not decrypt, invalid token saved", "data" => null]; } - private static function decrypt_cookie() : ?string { + private static function decrypt_cookie(): ?string + { self::init(); - if(!isset($_COOKIE[self::$session_user_cookie])) + if (!isset($_COOKIE[self::$session_user_cookie])) return null; $cookie = $_COOKIE[self::$session_user_cookie] ?? null; - if(!$cookie) + if (!$cookie) return null; return LayPassword::crypt($cookie, false); } - private static function delete_expired_tokens() : void { - $today = LayDate::date(); - self::orm()->open(self::$table)->delete("DATEDIFF('$today',`expire`) > 30"); + private static function get_user_token(string $id): array + { + $orm = self::orm(); + $id = $orm->clean($id, 16, 'strict'); + + return $orm->open(self::$table) + ->column("created_by, auth") + ->then_select("WHERE id='$id'"); } - private static function delete_user_token(string $token_id) : void { - $token_id = self::orm()->clean($token_id,11,'PREVENT_SQL_INJECTION'); - self::orm()->open(self::$table)->delete("id='$token_id'"); + private static function orm(): SQL + { + return SQL::instance(); } + private static function store_user_token(string $user_id): ?string + { + $orm = self::orm(); + $env_info = self::browser_info() . " IP: " . LayConfig::get_ip(); + $expire = LayDate::date("30 days"); + $now = LayDate::date(); + $user_id = $orm->clean($user_id, 16, 'strict'); - /* - * ### PUBLIC ### - */ + self::delete_expired_tokens(); - public static function save_to_db(string $immutable_key) : bool { - self::init(); + $orm->open(self::$table)->then_insert([ + "id" => "UUID()", + "created_by" => $user_id, + "created_at" => $now, + "auth" => LayPassword::hash($user_id), + "expire" => $expire, + "env_info" => $env_info + ]); - self::delete_expired_tokens(); + return $orm->table(self::$table)->last_item("created_at")['id']; + } - if(isset($_COOKIE[self::$session_user_cookie])) - return true; + /* + * ### PUBLIC ### + */ - return self::set_cookie( - self::$session_user_cookie, - LayPassword::crypt(LayCookieStorage::save_user_token($immutable_key)) - ); + public static function browser_info(): string + { + $root = self::lay()->get_res__server('root'); + + $browser = new BrowserDetection(); + return $browser->getName() . " " . $browser->getPlatform() . " " . $browser->getUserAgent(); } - public static function clear_from_db() : void { + public static function clear_from_db(): void + { self::init(); - if($id = self::decrypt_cookie()) + if ($id = self::decrypt_cookie()) LayCookieStorage::delete_user_token($id); self::destroy_cookie(self::$session_user_cookie); } - public static function validate_cookie() : array { - self::init(); - - if(!isset($_COOKIE[self::$session_user_cookie])) - return ["code" => 2, "msg" => "Cookie is not set", "data" => null]; - - if($id = self::decrypt_cookie()) - return [ - "code" => 1, - "msg" => "Cookie found!", - "data" => self::get_user_token($id) - ]; + private static function delete_user_token(string $token_id): void + { + $token_id = self::orm()->clean($token_id, 11, 'PREVENT_SQL_INJECTION'); + self::orm()->open(self::$table)->delete("id='$token_id'"); + } - return ["code" => 0, "msg" => "Could not decrypt, invalid token saved", "data" => null]; + private static function destroy_cookie($name): void + { + self::set_cookie($name, "", ["expires" => "now",]); } - public static function save(string $cookie_name, string $cookie_value, string $expire="30 days", string $path="/", ?string $domain = null, ?bool $secure = null, ?bool $http_only = null, ?string $same_site = null) : bool { + public static function save(string $cookie_name, string $cookie_value, string $expire = "30 days", string $path = "/", ?string $domain = null, ?bool $secure = null, ?bool $http_only = null, ?string $same_site = null): bool + { return self::set_cookie($cookie_name, $cookie_value, [ "expires" => $expire, @@ -211,14 +240,8 @@ public static function save(string $cookie_name, string $cookie_value, string $e ); } - public static function clear(string $cookie_name) : void { + public static function clear(string $cookie_name): void + { self::destroy_cookie($cookie_name); } - - public static function browser_info() : string { - $root = self::lay()->get_res__server('root'); - - $browser = new \Wolfcast\BrowserDetection(); - return $browser->getName() . " " . $browser->getPlatform() . " " . $browser->getUserAgent(); - } } \ No newline at end of file diff --git a/src/Libs/LayCopyDir.php b/src/Libs/LayCopyDir.php new file mode 100644 index 0000000..25df9c5 --- /dev/null +++ b/src/Libs/LayCopyDir.php @@ -0,0 +1,65 @@ +__construct( + $src_dir . $s . $file, + $dest_dir . $s . $file, + $pre_copy, + $post_copy, + $permissions, + $recursive, + ); + continue; + } + + $pre_copy = $pre_copy($file, $src_dir, $dest_dir); + + if ($pre_copy == CustomContinueBreak::CONTINUE) + continue; + + if ($pre_copy == CustomContinueBreak::BREAK) + break; + + copy( + $src_dir . $s . $file, + $dest_dir . $s . $file + ); + + $post_copy($file, $src_dir, $dest_dir); + } + + closedir($dir); + } +} \ No newline at end of file diff --git a/src/libs/LayCron.php b/src/Libs/LayCron.php similarity index 99% rename from src/libs/LayCron.php rename to src/Libs/LayCron.php index d028f48..aacf601 100644 --- a/src/libs/LayCron.php +++ b/src/Libs/LayCron.php @@ -1,10 +1,10 @@ Username = self::$credentials['username']; self::$mail_link->Password = self::$credentials['password']; }catch (\Exception $e){ - \BrickLayer\Lay\core\Exception::throw_exception("SMTP Credentials has not been setup. " . $e->getMessage(),"SMTPCredentialsError", stack_track: $e->getTrace()); + \BrickLayer\Lay\Core\Exception::throw_exception("SMTP Credentials has not been setup. " . $e->getMessage(),"SMTPCredentialsError", stack_track: $e->getTrace()); } } @@ -170,7 +170,7 @@ final public function queue() : ?bool { $name = $this->client['name'] ?? null; if((empty($email) || empty($name)) && $this->to_client) - \BrickLayer\Lay\core\Exception::throw_exception("Sending an email to a client with an empty `email`: [$email] or `name`: [$name] is not allowed!. If you wish to send to the server, use `->to_server()` method.", "EmptyRequiredField"); + \BrickLayer\Lay\Core\Exception::throw_exception("Sending an email to a client with an empty `email`: [$email] or `name`: [$name] is not allowed!. If you wish to send to the server, use `->to_server()` method.", "EmptyRequiredField"); $server_mail_from = $this->server_from->mail ?? self::$credentials['default_sender_email'] ?? $site_data->mail->{0}; $server_name_from = $this->server_from->name ?? self::$credentials['default_sender_name'] ?? $site_data->name->short; @@ -196,12 +196,12 @@ final public function queue() : ?bool { } if(@empty($this->subject)) - \BrickLayer\Lay\core\Exception::throw_exception("Sending an email with an empty `subject` is not allowed!", "EmptyRequiredField"); + \BrickLayer\Lay\Core\Exception::throw_exception("Sending an email with an empty `subject` is not allowed!", "EmptyRequiredField"); self::$mail_link->Subject = $this->subject; if(@empty($this->body)) - \BrickLayer\Lay\core\Exception::throw_exception("Sending an email with an empty `body` is not allowed!", "EmptyRequiredField"); + \BrickLayer\Lay\Core\Exception::throw_exception("Sending an email with an empty `body` is not allowed!", "EmptyRequiredField"); self::$mail_link->msgHTML($this->email_template($this->body)); @@ -229,7 +229,7 @@ final public function queue() : ?bool { ); else { if(!file_exists($this->attachment['filename'])) - \BrickLayer\Lay\core\Exception::throw_exception("The file you're trying to attach does not exist", "AttachmentNotFound"); + \BrickLayer\Lay\Core\Exception::throw_exception("The file you're trying to attach does not exist", "AttachmentNotFound"); self::$mail_link->addAttachment( $this->attachment['filename'], @@ -250,7 +250,7 @@ final public function queue() : ?bool { return true; } catch (\Exception) { - \BrickLayer\Lay\core\Exception::throw_exception(htmlspecialchars($recipient['to']) . ' LayMail.php' . self::$mail_link->ErrorInfo, "MailerError", false); + \BrickLayer\Lay\Core\Exception::throw_exception(htmlspecialchars($recipient['to']) . ' LayMail.php' . self::$mail_link->ErrorInfo, "MailerError", false); // Reset the connection to abort sending this message // If Loop the loop will continue trying to send to the rest of the list self::$mail_link->getSMTPInstance()->reset(); diff --git a/src/libs/LayObject.php b/src/Libs/LayObject.php similarity index 95% rename from src/libs/LayObject.php rename to src/Libs/LayObject.php index 5e5121c..46c3fe4 100644 --- a/src/libs/LayObject.php +++ b/src/Libs/LayObject.php @@ -1,10 +1,10 @@ get_env(); $display = $env == "DEVELOPMENT" || $other['core'] == "view"; + $cli_mode = LayConfig::get_mode() === LayMode::CLI; - if (!empty($other['raw'])) + if (!empty($other['raw'])) { foreach ($other['raw'] as $k => $r) { $this->convertRaw($r, $k, $body); } + } - $referer = $_SERVER['HTTP_REFERER'] ?? 'unknown'; + $referer = $_SERVER['HTTP_REFERER'] ?? ($cli_mode ? "CLI MODE" : 'unknown'); $ip = LayConfig::get_ip(); $stack = "
Referrer: $referer
IP: $ip
"; @@ -84,7 +96,7 @@ private function container($title, $body, $other = []): string
STACK; $stack_raw .= <<

$title

$body

@@ -100,8 +112,24 @@ private function container($title, $body, $other = []): string
$stack
DEBUG; + + if($cli_mode) { + $body = strip_tags($body); + Console::log(" $title ", Foreground::bold); + print "---------------------\n"; + Console::log($body, Foreground::red); + print "---------------------\n"; + print $stack_raw; + + return $other['act'] ?? "kill"; + } + + echo $display; + return $other['act'] ?? "kill"; - } else { + } + + else { $dir = LayConfig::server_data()->temp; $file_log = $dir . DIRECTORY_SEPARATOR . "exceptions.log"; @@ -189,7 +217,9 @@ class_alias(get_class($anon_class), $exception_class); break; } - http_response_code(500); + if(LayConfig::get_mode() === LayMode::HTTP) + http_response_code(500); + if ($act == "kill") die; } diff --git a/src/orm/QueryStatus.php b/src/Orm/QueryStatus.php similarity index 76% rename from src/orm/QueryStatus.php rename to src/Orm/QueryStatus.php index 22d62dd..fda7667 100644 --- a/src/orm/QueryStatus.php +++ b/src/Orm/QueryStatus.php @@ -1,6 +1,6 @@ Date: Sat, 16 Dec 2023 22:29:22 +0100 Subject: [PATCH 02/10] First real test --- __internal/Domain/Plaster.php | 52 ---------- __internal/Domain/index.php | 11 --- __internal/Domain/plaster/homepage.view | 3 +- src/BobDBuilder/Cmd/Make.php | 95 +++++++++++++++++++ src/BobDBuilder/EnginePlug.php | 2 +- src/Core/View/ViewCast.php | 7 +- .../{DeleteDirectory.php => LayUnlinkDir.php} | 17 ++-- 7 files changed, 109 insertions(+), 78 deletions(-) delete mode 100644 __internal/Domain/Plaster.php delete mode 100644 __internal/Domain/index.php rename src/Libs/{DeleteDirectory.php => LayUnlinkDir.php} (50%) diff --git a/__internal/Domain/Plaster.php b/__internal/Domain/Plaster.php deleted file mode 100644 index a847af6..0000000 --- a/__internal/Domain/Plaster.php +++ /dev/null @@ -1,52 +0,0 @@ -builder->init_start() - ->body_attr("dark", 'id="body-id"') - ->local("logo", DomainResource::get()->shared->img_default->logo) - ->local("section", "app") - ->init_end(); - } - - public function pages(): void - { - $this->builder->route("index")->bind(function (ViewBuilder $builder) { - $builder - ->page("title", "Homepage") - ->page("desc", "This is the default homepage description") - ->assets( - "@css/another.css", - ) - ->body("homepage"); - }); - - $this->builder->route("another-page")->bind(function (ViewBuilder $builder) { - $builder->connect_db() - ->page("title", "Another Page") - ->page("desc", "This is another page's description") - ->assets( - "@css/another.css", - ) - ->body("another"); - }); - } - - public function default(): void - { - $this->builder->route($this->builder::DEFAULT_ROUTE)->bind(function (ViewBuilder $builder){ - $builder->page('title', $this->builder->request('route') . " - Page not Found") - ->body_attr("default-home") - ->local("section", "error") - ->body('error'); - }); - } -} \ No newline at end of file diff --git a/__internal/Domain/index.php b/__internal/Domain/index.php deleted file mode 100644 index c6ab06c..0000000 --- a/__internal/Domain/index.php +++ /dev/null @@ -1,11 +0,0 @@ -create( - id: "default", - builder: new \web\domains\Default\Plaster(), -); \ No newline at end of file diff --git a/__internal/Domain/plaster/homepage.view b/__internal/Domain/plaster/homepage.view index 4ce0939..79dfa36 100644 --- a/__internal/Domain/plaster/homepage.view +++ b/__internal/Domain/plaster/homepage.view @@ -1,10 +1,11 @@ local->href; ?>
Lay Logo

page->title ?>

This is the default index page of Lay a lite php framework

Modify the necessary things to start your project

-Link to another page +Link to another page diff --git a/src/BobDBuilder/Cmd/Make.php b/src/BobDBuilder/Cmd/Make.php index 02e19b0..5b1a00a 100644 --- a/src/BobDBuilder/Cmd/Make.php +++ b/src/BobDBuilder/Cmd/Make.php @@ -6,6 +6,7 @@ use BrickLayer\Lay\BobDBuilder\Enum\CmdOutType; use BrickLayer\Lay\BobDBuilder\Interface\CmdLayout; use BrickLayer\Lay\Core\Traits\IsSingleton; +use BrickLayer\Lay\Libs\LayUnlinkDir; use BrickLayer\Lay\Libs\LayCopyDir; class Make implements CmdLayout @@ -14,9 +15,13 @@ class Make implements CmdLayout private readonly EnginePlug $plug; private readonly array $tags; + private readonly string $internal_dir; + public function _init(EnginePlug $plug) : void { $this->plug = $plug; + $this->internal_dir = $this->plug->server->lay . "__internal" . $this->plug->s; + $plug->add_arg($this, ["make:domain"], 'make_domain', 0); } @@ -34,8 +39,98 @@ public function make() : void if(!$domain) $this->plug->write_fail("No domain specified"); + $domain = explode(" ", ucwords($domain)); + $domain = implode("", $domain); + $domain_dir = $this->plug->server->domains . $domain; + $exists = is_dir($domain_dir); + + if($this->plug->force && $exists) + $this->plug->write_fail( + "Domain directory *$domain_dir* exists already!\n" + . "If you wish to force this action, pass the tag --force with the command\n" + ); + + if($exists) + new LayUnlinkDir($domain_dir); + + // Copy the default Domain directory to the web + new LayCopyDir($this->internal_dir . "Domain", $domain_dir); + // Copy default files to the newly created domain directory + $this->domain_default_files($domain, $domain_dir); + + // link htaccess from the root web folder + symlink($this->plug->server->web . ".htaccess", $domain_dir . $this->plug->s . ".htaccess"); + + // link shared folder to domain + symlink($this->plug->server->shared, $domain_dir . $this->plug->s . "shared"); + } + + public function domain_default_files(string $domain_name, string $domain_dir) : void + { + file_put_contents( + $domain_dir . $this->plug->s . + "index.php", + <<create( + id: "default", + builder: new \web\domains\{$domain_name}\Plaster(), + ); + FILE + ); + file_put_contents( + $domain_dir . $this->plug->s . + "Plaster.php", + <<builder->init_start() + ->body_attr("dark", 'id="body-id"') + ->local("logo", DomainResource::get()->shared->img_default->logo) + ->local("section", "app") + ->init_end(); + } + + public function pages(): void + { + \$this->builder->route("index")->bind(function (ViewBuilder \$builder) { + \$builder->page("title", "Homepage") + ->page("desc", "This is the default homepage description") + ->assets( + "@css/another.css", + ) + ->body("homepage"); + }); + + \$this->builder->route("another-page")->bind(function (ViewBuilder \$builder) { + \$builder->page("title", "Another Page") + ->page("desc", "This is another page's description") + ->assets( + "@css/another.css", + ) + ->body("another"); + }); + } + } + FILE + ); } } \ No newline at end of file diff --git a/src/BobDBuilder/EnginePlug.php b/src/BobDBuilder/EnginePlug.php index 383ac0d..429a10d 100644 --- a/src/BobDBuilder/EnginePlug.php +++ b/src/BobDBuilder/EnginePlug.php @@ -104,7 +104,7 @@ private function load_cmd_classes() : void $namespace = implode("\\", $namespace) . "\\Cmd"; foreach (scandir(__DIR__ . $this->s . "Cmd") as $class) { - if ($class == "." || $class == "..") + if ($class == "." || $class == ".." || is_dir($class)) continue; $cmd_class = $namespace . "\\" . explode(".php", $class)[0]; diff --git a/src/Core/View/ViewCast.php b/src/Core/View/ViewCast.php index bf21dde..297fb98 100644 --- a/src/Core/View/ViewCast.php +++ b/src/Core/View/ViewCast.php @@ -14,7 +14,6 @@ public function __construct() { public function init_pages(): void { $this->builder->init_start() - ->page('type', 'front') ->page('section', 'app'); $this->builder->init_end(); } @@ -35,7 +34,7 @@ final public function init(): void public function pages(): void { - $this->builder->route("index")->bind(function (ViewBuilder $builder, array $init_values) { + $this->builder->route("index")->bind(function (ViewBuilder $builder) { $builder->page("title", "Default Lay Page") ->page("desc", "A default description. This goes to the meta tags responsible for the page description") ->local("current_page", "home") @@ -50,10 +49,10 @@ public function pages(): void */ public function default(): void { - $this->builder->route($this->builder::DEFAULT_ROUTE)->bind(function (ViewBuilder $builder, array $init_values) { + $this->builder->route($this->builder::DEFAULT_ROUTE)->bind(function (ViewBuilder $builder) { $builder ->page("title", $builder->request('route') . " - Page not found") - ->body_attr("defult-home") + ->body_attr("default-home") ->local("current_page", "error") ->local("section", "error") ->body(function (array $meta) { ?> diff --git a/src/Libs/DeleteDirectory.php b/src/Libs/LayUnlinkDir.php similarity index 50% rename from src/Libs/DeleteDirectory.php rename to src/Libs/LayUnlinkDir.php index 7d3625b..d3b7ae0 100644 --- a/src/Libs/DeleteDirectory.php +++ b/src/Libs/LayUnlinkDir.php @@ -2,14 +2,14 @@ declare(strict_types=1); namespace BrickLayer\Lay\Libs; -class DeleteDirectory { +class LayUnlinkDir { public static bool $result; /** * @param string $dir Directory to be deleted - * @param string|null $break_directory optional child directory to stop delete recursion, before the root directory on arg 1 [$dir] */ - public function __construct(string $dir, ?string $break_directory = null){ + public function __construct(string $dir) + { if (!is_dir($dir)) { self::$result = false; return; @@ -19,15 +19,14 @@ public function __construct(string $dir, ?string $break_directory = null){ if ($object == "." || $object == "..") continue; - if (filetype($dir . "/" . $object) == "dir") { - if(rtrim($object,"/") == $break_directory) - break; - - new self($dir . "/" . $object); + if (!is_dir($dir . "/" . $object)) { + unlink($dir."/".$object); continue; } - unlink($dir."/".$object); + + new self($dir . "/" . $object); + } self::$result = rmdir($dir); From 3676fa712e2bebe200eab466ca095457b0f87150 Mon Sep 17 00:00:00 2001 From: Osahenrumwen Aigbogun Date: Sat, 16 Dec 2023 22:34:48 +0100 Subject: [PATCH 03/10] Updated the relative directory of domain index.php --- src/BobDBuilder/Cmd/Make.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BobDBuilder/Cmd/Make.php b/src/BobDBuilder/Cmd/Make.php index 5b1a00a..31a7aa3 100644 --- a/src/BobDBuilder/Cmd/Make.php +++ b/src/BobDBuilder/Cmd/Make.php @@ -77,7 +77,7 @@ public function domain_default_files(string $domain_name, string $domain_dir) : const DOMAIN_SET = true; - include_once __DIR__ . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . "index.php"; + include_once __DIR__ . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . "index.php"; Domain::new()->create( id: "default", From 4e248c7df32bb5c4f88d096cafbc124da3dc5ac2 Mon Sep 17 00:00:00 2001 From: Osahenrumwen Aigbogun Date: Sat, 16 Dec 2023 23:06:27 +0100 Subject: [PATCH 04/10] Fixed some bugs --- src/BobDBuilder/Cmd/Project.php | 8 ++++++++ src/Core/Traits/Init.php | 12 +++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/BobDBuilder/Cmd/Project.php b/src/BobDBuilder/Cmd/Project.php index d105304..f9c47f6 100644 --- a/src/BobDBuilder/Cmd/Project.php +++ b/src/BobDBuilder/Cmd/Project.php @@ -14,6 +14,7 @@ class Project implements CmdLayout use IsSingleton; private readonly EnginePlug $plug; + private readonly array $tags; public function _init(EnginePlug $plug) : void { @@ -26,11 +27,18 @@ public function _spin(): void if(!$this->plug->project_mode) return; + $this->tags = $this->plug->tags; + $this->create(); } public function create() : void { + $cmd = $this->tags['project:create'][0] ?? null; + + if(!$cmd) + return; + $server = $this->plug->server; // copy env file if it doesn't exist diff --git a/src/Core/Traits/Init.php b/src/Core/Traits/Init.php index 73adca6..8b1f411 100644 --- a/src/Core/Traits/Init.php +++ b/src/Core/Traits/Init.php @@ -37,7 +37,13 @@ private static function set_web_root(&$options) : void } private static function set_dir() : void { - self::$dir = Autoloader::get_root_dir(); + $s = DIRECTORY_SEPARATOR; + + self::$dir = explode + ( + "{$s}vendor{$s}bricklayer{$s}structure", + __DIR__ . $s + )[0] . $s; } private static function first_class_citizens() : void { @@ -132,9 +138,9 @@ private static function initialize() : self { ]; self::$COMPRESS_HTML = $options['compress_html']; - + self::$server = new stdClass(); - + $options['mail'][0] = $options['mail'][0] ?? "info@" . self::$base_no_proto; self::set_web_root($options); From 953e6d44956e594f2be9a249fc69679d69f7cee1 Mon Sep 17 00:00:00 2001 From: Osahenrumwen Aigbogun Date: Sun, 17 Dec 2023 00:44:35 +0100 Subject: [PATCH 05/10] Batch of fixes based on test --- src/BobDBuilder/Cmd/Project.php | 12 ++------ src/BobDBuilder/Engine.php | 16 +++++----- src/BobDBuilder/EnginePlug.php | 18 +++++++++-- src/Core/Traits/Config.php | 8 +++-- src/Core/Traits/Init.php | 11 ++++++- src/Core/Traits/Resources.php | 8 ++--- src/Libs/LayCopyDir.php | 5 +-- src/Orm/Exception.php | 54 +++++++++++++++++++++++++-------- 8 files changed, 91 insertions(+), 41 deletions(-) diff --git a/src/BobDBuilder/Cmd/Project.php b/src/BobDBuilder/Cmd/Project.php index f9c47f6..241846c 100644 --- a/src/BobDBuilder/Cmd/Project.php +++ b/src/BobDBuilder/Cmd/Project.php @@ -34,7 +34,7 @@ public function _spin(): void public function create() : void { - $cmd = $this->tags['project:create'][0] ?? null; + $cmd = $this->tags['project_create'][0] ?? null; if(!$cmd) return; @@ -49,14 +49,6 @@ public function create() : void new LayCopyDir($server->lay_static . "omjs", $server->shared . "lay"); // copy helper js file to project lay folder - copy( - $server->lay_static . "js" . $this->plug->s . "constants.js", - $server->shared . "lay" . $this->plug->s . "constants.js" - ); - - copy( - $server->lay_static . "js" . $this->plug->s . "constants.min.js", - $server->shared . "lay" . $this->plug->s . "constants.min.js" - ); + new LayCopyDir($server->lay_static . "js", $server->shared . "lay"); } } \ No newline at end of file diff --git a/src/BobDBuilder/Engine.php b/src/BobDBuilder/Engine.php index bed47ad..d36e7fd 100644 --- a/src/BobDBuilder/Engine.php +++ b/src/BobDBuilder/Engine.php @@ -30,8 +30,7 @@ public function __construct( $this->plug->fire(); - if(empty($this->plug->active_cmd)) - $this->end(); + $this->end(); } public function intro(bool $close_talk = true): void @@ -62,11 +61,14 @@ public function help(): void public function end(): void { - $this->plug->write_info( - "-- Bob has determined that the current command is invalid\n" - . "-- Please use --help to see the list of commands available" - , ["current_cmd" => $this->plug->typed_cmd] - ); + if(empty($this->plug->active_cmd)) + $this->plug->write_info( + "-- Bob has determined that the current command is invalid\n" + . "-- Please use --help to see the list of commands available" + , ["current_cmd" => $this->plug->typed_cmd] + ); + + $this->plug->write_success("-- Operation completed!"); } diff --git a/src/BobDBuilder/EnginePlug.php b/src/BobDBuilder/EnginePlug.php index 429a10d..9d070e0 100644 --- a/src/BobDBuilder/EnginePlug.php +++ b/src/BobDBuilder/EnginePlug.php @@ -51,6 +51,19 @@ public function fire(): void $this->force = $this->tags['force_action'] ?? $this->force; $spun_correct_class = false; + set_error_handler(function (int $err_no, string $err_str, string $err_file, int $err_line) { + if(error_reporting() === 0) + return false; + + Exception::throw_exception( + $err_str . "\n" + . "File: " . $err_file . ":$err_line", + "BobWarnings", + ); + + return true; + }, E_WARNING|E_USER_WARNING); + foreach ($this->cmd_classes as $cmd_class) { if($spun_correct_class) break; @@ -63,8 +76,9 @@ public function fire(): void } catch (\TypeError|\Error|\Exception $e){ Exception::throw_exception( - $e->getMessage(), - "BobError " . $cmd_class::class, + $e->getMessage() . "\n" + . $e->getFile() . ":" . $e->getLine() + , "BobError " . $cmd_class::class, stack_track: $e->getTrace() ); } diff --git a/src/Core/Traits/Config.php b/src/Core/Traits/Config.php index 951d26a..6e18331 100644 --- a/src/Core/Traits/Config.php +++ b/src/Core/Traits/Config.php @@ -202,6 +202,8 @@ public static function validate_lay(): void { if (!defined("SAFE_TO_INIT_LAY") || !SAFE_TO_INIT_LAY) Exception::throw_exception("This script cannot be accessed this way, please return home", "BadRequest"); + + SQL::new()->capture_errors(); } public function dont_compress_html(): self @@ -234,12 +236,12 @@ public function set_global_api(string $uri): self return $this->header_data("api", $uri); } - + public function init_name(string $short, string $full): self { return $this->metadata("name", ["short" => $short, "full" => $full]); } - + public function init_color(string $pry, string $sec): self { return $this->metadata("color", ["pry" => $pry, "sec" => $sec]); @@ -269,7 +271,7 @@ public function init_end(): void { self::initialize(); } - + public function is_mobile(): bool { return (bool)strpos(strtolower($_SERVER['HTTP_USER_AGENT'] ?? "cli"), "mobile"); diff --git a/src/Core/Traits/Init.php b/src/Core/Traits/Init.php index 8b1f411..d42374b 100644 --- a/src/Core/Traits/Init.php +++ b/src/Core/Traits/Init.php @@ -2,7 +2,6 @@ declare(strict_types=1); namespace BrickLayer\Lay\Core\Traits; use BrickLayer\Lay\Core\Enums\LayMode; -use BrickLayer\Lay\Autoloader; use stdClass; trait Init { @@ -147,11 +146,21 @@ private static function initialize() : self { self::set_internal_site_data($options); self::set_internal_res_server(self::$dir); self::load_env(); + self::autoload_project_classes(); self::$INITIALIZED = true; return self::$instance; } + public static function autoload_project_classes(): void + { + spl_autoload_register(function ($className) { + $location = str_replace('\\', DIRECTORY_SEPARATOR, $className); + + @include_once self::$dir . $location . '.php'; + }); + } + public static function is_init(bool $init_first_class = false) : void { if($init_first_class && !self::$FIRST_CLASS_CITI_ACTIVE) { self::init_first_class(); diff --git a/src/Core/Traits/Resources.php b/src/Core/Traits/Resources.php index 34d13d2..12bec4b 100644 --- a/src/Core/Traits/Resources.php +++ b/src/Core/Traits/Resources.php @@ -15,15 +15,15 @@ trait Resources { private static bool $env_loaded = false; private static string $CLIENT_VALUES = ""; - + protected static function set_internal_res_server(string $dir) : void { $slash = DIRECTORY_SEPARATOR; $obj = new \stdClass(); - $obj->lay_static =$dir . "vendor" . $slash . "bricklayer" . $slash . "lay" . $slash . "src" . $slash . "static" . $slash; - $obj->lay = $dir . "vendor" . $slash . "bricklayer" . $slash . "lay" . $slash; + $obj->lay_static =$dir . "vendor" . $slash . "bricklayer" . $slash . "structure" . $slash . "src" . $slash . "static" . $slash; + $obj->lay = $dir . "vendor" . $slash . "bricklayer" . $slash . "structure" . $slash; $obj->root = $dir; $obj->temp = $dir . ".lay_temp" . $slash; $obj->bricks = $dir . "bricks" . $slash; @@ -31,7 +31,7 @@ protected static function set_internal_res_server(string $dir) : void { $obj->web = $dir . "web" . $slash; $obj->shared = $dir . "web" . $slash . "shared" . $slash; $obj->domains = $dir . "web" . $slash . "domains" . $slash; - + self::$server = $obj; } protected static function set_internal_site_data(array $options) : void { diff --git a/src/Libs/LayCopyDir.php b/src/Libs/LayCopyDir.php index 25df9c5..751958a 100644 --- a/src/Libs/LayCopyDir.php +++ b/src/Libs/LayCopyDir.php @@ -44,7 +44,7 @@ public function __construct( continue; } - $pre_copy = $pre_copy($file, $src_dir, $dest_dir); + $pre_copy = !is_null($pre_copy) ? $pre_copy($file, $src_dir, $dest_dir) : null; if ($pre_copy == CustomContinueBreak::CONTINUE) continue; @@ -57,7 +57,8 @@ public function __construct( $dest_dir . $s . $file ); - $post_copy($file, $src_dir, $dest_dir); + if(!is_null($post_copy)) + $post_copy($file, $src_dir, $dest_dir); } closedir($dir); diff --git a/src/Orm/Exception.php b/src/Orm/Exception.php index 3c54213..4253eff 100644 --- a/src/Orm/Exception.php +++ b/src/Orm/Exception.php @@ -3,11 +3,8 @@ namespace BrickLayer\Lay\Orm; -use BrickLayer\Lay\Autoloader; use BrickLayer\Lay\BobDBuilder\Helper\Console\Console; -use BrickLayer\Lay\BobDBuilder\Helper\Console\Format\Background; use BrickLayer\Lay\BobDBuilder\Helper\Console\Format\Foreground; -use BrickLayer\Lay\BobDBuilder\Helper\Console\Format\Style; use BrickLayer\Lay\Core\Enums\LayMode; use BrickLayer\Lay\Core\LayConfig; @@ -15,6 +12,37 @@ class Exception { private static string $ENV = "DEVELOPMENT"; + public function capture_errors() : void { + + set_error_handler(function (int $err_no, string $err_str, string $err_file, int $err_line) + { + if(error_reporting() != E_ALL) + return; + + $eol = LayConfig::get_mode() == LayMode::HTTP ? "
" : "\n"; + + if($err_no === E_WARNING || $err_no === E_USER_WARNING) { + $this->use_exception( + "LayWarnings", + $err_str . $eol + . "File: " . $err_file . ":$err_line" . $eol, + kill: false + ); + + return true; + } + + $this->use_exception( + "LayErrors", + $err_str . $eol + . "File: " . $err_file . ":$err_line" . $eol + ); + + return true; + }, E_ALL|E_STRICT); + } + + public function set_env(string $ENV): void { $ENV = strtolower($ENV); @@ -45,19 +73,22 @@ public function use_exception(string $title, string $body, bool $kill = true, ar private function container($title, $body, $other = []): string { + $title_color = "#5656f5"; + $body_color = "#dea303"; + $cli_color = Foreground::light_cyan; + switch ($other['core']){ - default: - $title_color = "#5656f5"; - $body_color = "#dea303"; - break; + default: break; case "error": $title_color = "#ff0014"; $body_color = "#ff5000"; - break; + $cli_color = Foreground::red; + break; case "success": $title_color = "#1cff03"; $body_color = "#1b8b07"; - break; + $cli_color = Foreground::green; + break; } $env = $this->get_env(); @@ -117,7 +148,7 @@ private function container($title, $body, $other = []): string $body = strip_tags($body); Console::log(" $title ", Foreground::bold); print "---------------------\n"; - Console::log($body, Foreground::red); + Console::log($body, $cli_color); print "---------------------\n"; print $stack_raw; @@ -218,10 +249,9 @@ class_alias(get_class($anon_class), $exception_class); } if(LayConfig::get_mode() === LayMode::HTTP) - http_response_code(500); + @http_response_code(500); if ($act == "kill") die; } } - From aacd5450f8bdb37f18828554677e088c1a26e7db Mon Sep 17 00:00:00 2001 From: Osahenrumwen Aigbogun Date: Sun, 17 Dec 2023 02:17:15 +0100 Subject: [PATCH 06/10] another round of bug fixes, due to test --- __internal/Domain/plaster/another.view | 3 +- src/Autoloader.php | 54 -------------------------- src/Core/View/Domain.php | 2 + src/Core/View/DomainResource.php | 34 ++++++++-------- src/Core/View/Tags/Anchor.php | 36 +++++++++-------- src/Core/View/ViewCast.php | 12 +++--- src/Core/View/ViewSrc.php | 4 +- src/Orm/Exception.php | 6 +-- 8 files changed, 53 insertions(+), 98 deletions(-) delete mode 100644 src/Autoloader.php diff --git a/__internal/Domain/plaster/another.view b/__internal/Domain/plaster/another.view index f4f097a..3d19c5d 100644 --- a/__internal/Domain/plaster/another.view +++ b/__internal/Domain/plaster/another.view @@ -1,10 +1,11 @@ local->href; ?>
Lay Logo

page->title ?>

This is the another page of Lay a lite php framework

Modify the necessary things to start your project

-Link to home page +Link to home page diff --git a/src/Autoloader.php b/src/Autoloader.php deleted file mode 100644 index 6b775fa..0000000 --- a/src/Autoloader.php +++ /dev/null @@ -1,54 +0,0 @@ -composer dump-autoload on your project root.\n"; - } - } -} - -Autoloader::load_composer(); -Autoloader::load_framework_classes(); \ No newline at end of file diff --git a/src/Core/View/Domain.php b/src/Core/View/Domain.php index 002643d..e7b87d9 100644 --- a/src/Core/View/Domain.php +++ b/src/Core/View/Domain.php @@ -160,7 +160,9 @@ private function check_route_is_static_file(string $view) : string { $ext = strtolower((string) end($x)); if(count($x) > 1 && in_array($ext,$ext_array,true)) { + header("Content-Type: application/json"); http_response_code(404); + echo "{error: 404, response: 'resource not found'}"; die; } diff --git a/src/Core/View/DomainResource.php b/src/Core/View/DomainResource.php index fa72856..2563059 100644 --- a/src/Core/View/DomainResource.php +++ b/src/Core/View/DomainResource.php @@ -11,7 +11,7 @@ class DomainResource { use IsSingleton; - + private static object $resource; private static object $plaster; @@ -43,10 +43,10 @@ public static function init() : void $base = $domain->domain_base; $env_src = $data->use_prod && LayConfig::$ENV_IS_PROD ? 'prod' : 'dev'; - $obj->base = $base . "uploads/"; - $obj->upload = $base . "uploads/"; - $obj->static_root = $base . "static/"; - $obj->root = $obj->static_root . $env_src . "/"; + $obj->root = $base; + $obj->upload = $base . "uploads/"; + $obj->static = $base . "static/"; + $obj->static_env = $obj->static . $env_src . "/"; $obj->css = $obj->root . "css/"; $obj->img = $obj->root . "images/"; @@ -55,14 +55,15 @@ public static function init() : void $shared = $obj->root . "shared/"; $obj->shared = (object) [ "root" => $shared, - "css" => $shared . "css/", - "img" => $shared . "images/", - "js" => $shared . "js/", + "static" => $shared . "static/", + "css" => $shared . "static/" . $env_src . "/css/", + "img" => $shared . "static/" . $env_src . "/images/", + "js" => $shared . "static/" . $env_src . "/js/", "img_default" => (object) [ - "logo" => $shared . "images/logo.png", - "favicon" => $shared . "images/favicon.png", - "icon" => $shared . "images/icon.png", - "meta" => $shared . "images/meta.png", + "logo" => $shared . "static/" . $env_src . "/images/logo.png", + "favicon" => $shared . "static/" . $env_src . "/images/favicon.png", + "icon" => $shared . "static/" . $env_src . "/images/icon.png", + "meta" => $shared . "static/" . $env_src . "/images/meta.png", ] ]; @@ -82,16 +83,17 @@ public static function set_res(string $key, mixed $value) : void } #[ObjectShape([ - 'lay' => 'object', - 'upload' => 'string', - 'static_root' => 'string', 'root' => 'string', + 'upload' => 'string', + 'static' => 'string', + 'static_env' => 'string', 'css' => 'string', 'img' => 'string', 'js' => 'string', - 'shared' => 'object', + 'shared' => 'object [root, static, css, img, js, img_default [object [logo, favicon, icon, meta]]]', 'server' => 'object', 'domain' => 'object', + 'lay' => 'object [uri, root]', ])] public static function get() : object { diff --git a/src/Core/View/Tags/Anchor.php b/src/Core/View/Tags/Anchor.php index 7ac3238..c6fe7a3 100644 --- a/src/Core/View/Tags/Anchor.php +++ b/src/Core/View/Tags/Anchor.php @@ -2,23 +2,27 @@ declare(strict_types=1); namespace BrickLayer\Lay\Core\View\Tags; +use BrickLayer\Lay\Core\View\DomainResource; +use BrickLayer\Lay\Core\View\Tags\Traits\Standard; use Couchbase\View; use JetBrains\PhpStorm\ExpectedValues; use BrickLayer\Lay\Core\LayConfig; use BrickLayer\Lay\Core\View\Enums\DomainType; use BrickLayer\Lay\Core\View\ViewBuilder; -use BrickLayer\Lay\Core\View\Domain; final class Anchor { private string $link = ""; - use \BrickLayer\Lay\Core\View\Tags\Traits\Standard; + use Standard; public function href(?string $link = "", ?string $domain_id = null) : self { - $req = ViewBuilder::new()->request('*'); + $dom = DomainResource::get()->domain; + $link = is_null($link) ? '' : $link; + $link = ltrim($link, "/"); + $base = LayConfig::site_data(); - $base_full = $base->base; + $base_full = $base->domain; if(str_starts_with($link,"http")) { $base_full = ""; @@ -26,26 +30,24 @@ public function href(?string $link = "", ?string $domain_id = null) : self { } if($domain_id) { - $same_domain = $domain_id == $req['domain_id']; - $domain_id = Domain::new()->get_domain_by_id($domain_id); + $same_domain = $domain_id == $dom->domain_id; - $req['pattern'] = $domain_id ? $domain_id['patterns'][0] : "*"; - - if($req['pattern'] != "*" && LayConfig::$ENV_IS_PROD) { - $x = explode(".", $base->base_no_proto, 2); - $base_full = $base->proto . "://" . $req['pattern'] . "." . end($x) . "/"; - $req['pattern'] = "*"; + if($dom->pattern != "*" && LayConfig::$ENV_IS_PROD) { + $x = explode(".", $base->domain_no_proto, 2); + $base_full = $base->proto . "://" . $dom->pattern . "." . end($x); + $base_full = rtrim($base_full, "/") . "/"; + $dom->pattern = "*"; } - if(!$same_domain && $req['domain_type'] == DomainType::SUB) { - $x = explode(".", $base->base_no_proto, 2); + if(!$same_domain && $dom->domain_type == DomainType::SUB) { + $x = explode(".", $base->domain_no_proto, 2); $base_full = $base->proto . "://" . end($x) . "/"; } } - $domain = $req['pattern'] == "*" ? "" : $req['pattern']; + $domain = $dom->pattern == "*" ? "" : $dom->pattern; - if($req['domain_type'] == DomainType::LOCAL) + if($dom->domain_type == DomainType::LOCAL) $domain = $domain ? $domain . "/" : $domain; else $domain = ""; @@ -73,7 +75,7 @@ public function target(#[ExpectedValues(['_blank','_parent','_top','_self'])] st public function children(string ...$children) : string { $attr = $this->get_attr(); $children = implode(" ", $children); - + return <<$children LNK; diff --git a/src/Core/View/ViewCast.php b/src/Core/View/ViewCast.php index 297fb98..d7e9310 100644 --- a/src/Core/View/ViewCast.php +++ b/src/Core/View/ViewCast.php @@ -55,14 +55,16 @@ public function default(): void ->body_attr("default-home") ->local("current_page", "error") ->local("section", "error") - ->body(function (array $meta) { ?> + ->body(function () { + $meta = DomainResource::plaster() + ?> -

+

page->title ?>

This is the default error page of Lay Framework

- Return Home + Return Home shared->root, $client->root, $client->static_root, + $client->shared->root, $client->root, $client->static, $client->shared->js, $client->js, $client->shared->img, $client->img, $client->shared->css, $client->css, diff --git a/src/Orm/Exception.php b/src/Orm/Exception.php index 4253eff..c4f15de 100644 --- a/src/Orm/Exception.php +++ b/src/Orm/Exception.php @@ -23,7 +23,7 @@ public function capture_errors() : void { if($err_no === E_WARNING || $err_no === E_USER_WARNING) { $this->use_exception( - "LayWarnings", + "LayWarning", $err_str . $eol . "File: " . $err_file . ":$err_line" . $eol, kill: false @@ -33,7 +33,7 @@ public function capture_errors() : void { } $this->use_exception( - "LayErrors", + "LayError", $err_str . $eol . "File: " . $err_file . ":$err_line" . $eol ); @@ -136,7 +136,7 @@ private function container($title, $body, $other = []): string if ($display) { $display = << +

$title

$body

$env ENVIRONMENT
From d042992c3de5b8972fe3775c1881ee86002a7671 Mon Sep 17 00:00:00 2001 From: Osahenrumwen Aigbogun Date: Mon, 18 Dec 2023 18:21:34 +0100 Subject: [PATCH 07/10] More fixes based on test result --- LICENSE | 28 +-- src/BobDBuilder/Cmd/Make.php | 115 +--------- src/BobDBuilder/Cmd/MakeTraits/Brick.php | 12 + src/BobDBuilder/Cmd/MakeTraits/Domain.php | 205 ++++++++++++++++++ src/BobDBuilder/Cmd/Project.php | 12 +- src/BobDBuilder/Cmd/Symlink.php | 18 +- src/BobDBuilder/Engine.php | 63 ++++-- src/BobDBuilder/EnginePlug.php | 112 +++++++--- src/BobDBuilder/Enum/CmdOutType.php | 1 + src/BobDBuilder/Helper/Console/Console.php | 2 +- .../Helper/Console/Format/Foreground.php | 4 - .../Helper/Console/Format/Style.php | 4 + src/Core/Exception.php | 12 +- src/Core/Traits/Config.php | 15 +- src/Core/View/Domain.php | 12 +- src/Core/View/DomainResource.php | 6 +- src/Core/View/ViewSrc.php | 6 +- src/Libs/LayUnlinkDir.php | 9 + src/Orm/Exception.php | 38 +++- 19 files changed, 450 insertions(+), 224 deletions(-) create mode 100644 src/BobDBuilder/Cmd/MakeTraits/Brick.php create mode 100644 src/BobDBuilder/Cmd/MakeTraits/Domain.php diff --git a/LICENSE b/LICENSE index f288702..1ece531 100644 --- a/LICENSE +++ b/LICENSE @@ -13,14 +13,14 @@ software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free +share and change all versions of a program--to domain sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you +price. Our General Public Licenses are designed to domain sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new @@ -33,7 +33,7 @@ you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive +freedoms that you received. You must domain sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. @@ -62,7 +62,7 @@ of the GPL, as needed to protect the freedom of users. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that +domain it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and @@ -90,14 +90,14 @@ earlier work or a work "based on" the earlier work. on the Program. To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for +permission, would domain you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through +parties to domain or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" @@ -161,10 +161,10 @@ covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. - You may make, run and propagate covered works that you do not + You may domain, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you +of having them domain modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works @@ -230,7 +230,7 @@ terms of section 4, provided that you also meet all of these conditions: d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. + work need not domain them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, @@ -486,14 +486,14 @@ this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and +domain, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a +party means to domain such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, @@ -523,7 +523,7 @@ the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment +in the business of distributing software, under which you domain payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory @@ -623,7 +623,7 @@ copy of the Program in return for a fee. How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it +possible use to the public, the best way to achieve this is to domain it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest @@ -649,7 +649,7 @@ the "copyright" line and a pointer to where the full notice is found. Also add information on how to contact you by electronic and paper mail. - If the program does terminal interaction, make it output a short + If the program does terminal interaction, domain it output a short notice like this when it starts in an interactive mode: Copyright (C) diff --git a/src/BobDBuilder/Cmd/Make.php b/src/BobDBuilder/Cmd/Make.php index 31a7aa3..130357c 100644 --- a/src/BobDBuilder/Cmd/Make.php +++ b/src/BobDBuilder/Cmd/Make.php @@ -2,135 +2,36 @@ namespace BrickLayer\Lay\BobDBuilder\Cmd; +use BrickLayer\Lay\BobDBuilder\Cmd\MakeTraits\Brick; +use BrickLayer\Lay\BobDBuilder\Cmd\MakeTraits\Domain; use BrickLayer\Lay\BobDBuilder\EnginePlug; -use BrickLayer\Lay\BobDBuilder\Enum\CmdOutType; use BrickLayer\Lay\BobDBuilder\Interface\CmdLayout; use BrickLayer\Lay\Core\Traits\IsSingleton; -use BrickLayer\Lay\Libs\LayUnlinkDir; -use BrickLayer\Lay\Libs\LayCopyDir; class Make implements CmdLayout { use IsSingleton; + use Domain; + use Brick; + private readonly EnginePlug $plug; private readonly array $tags; private readonly string $internal_dir; - public function _init(EnginePlug $plug) : void + public function _init(EnginePlug $plug): void { $this->plug = $plug; $this->internal_dir = $this->plug->server->lay . "__internal" . $this->plug->s; - $plug->add_arg($this, ["make:domain"], 'make_domain', 0); + $plug->add_arg($this, ["make:domain"], 'make_domain', 0, 1); } public function _spin(): void { $this->tags = $this->plug->tags; - $this->make(); - } - - public function make() : void - { - $domain = $this->tags['make_domain'][0] ?? null; - - if(!$domain) - $this->plug->write_fail("No domain specified"); - - $domain = explode(" ", ucwords($domain)); - $domain = implode("", $domain); - $domain_dir = $this->plug->server->domains . $domain; - $exists = is_dir($domain_dir); - - if($this->plug->force && $exists) - $this->plug->write_fail( - "Domain directory *$domain_dir* exists already!\n" - . "If you wish to force this action, pass the tag --force with the command\n" - ); - - if($exists) - new LayUnlinkDir($domain_dir); - - // Copy the default Domain directory to the web - new LayCopyDir($this->internal_dir . "Domain", $domain_dir); - - // Copy default files to the newly created domain directory - $this->domain_default_files($domain, $domain_dir); - - // link htaccess from the root web folder - symlink($this->plug->server->web . ".htaccess", $domain_dir . $this->plug->s . ".htaccess"); - - // link shared folder to domain - symlink($this->plug->server->shared, $domain_dir . $this->plug->s . "shared"); - } - - public function domain_default_files(string $domain_name, string $domain_dir) : void - { - file_put_contents( - $domain_dir . $this->plug->s . - "index.php", - <<create( - id: "default", - builder: new \web\domains\{$domain_name}\Plaster(), - ); - FILE - ); - - file_put_contents( - $domain_dir . $this->plug->s . - "Plaster.php", - <<builder->init_start() - ->body_attr("dark", 'id="body-id"') - ->local("logo", DomainResource::get()->shared->img_default->logo) - ->local("section", "app") - ->init_end(); - } - - public function pages(): void - { - \$this->builder->route("index")->bind(function (ViewBuilder \$builder) { - \$builder->page("title", "Homepage") - ->page("desc", "This is the default homepage description") - ->assets( - "@css/another.css", - ) - ->body("homepage"); - }); - - \$this->builder->route("another-page")->bind(function (ViewBuilder \$builder) { - \$builder->page("title", "Another Page") - ->page("desc", "This is another page's description") - ->assets( - "@css/another.css", - ) - ->body("another"); - }); - } - } - FILE - ); + $this->domain(); } } \ No newline at end of file diff --git a/src/BobDBuilder/Cmd/MakeTraits/Brick.php b/src/BobDBuilder/Cmd/MakeTraits/Brick.php new file mode 100644 index 0000000..23e9880 --- /dev/null +++ b/src/BobDBuilder/Cmd/MakeTraits/Brick.php @@ -0,0 +1,12 @@ +tags['make_domain'][0] ?? null; + $pattern = $this->tags['make_domain'][1] ?? null; + + $talk = fn($msg) => $this->plug->write_talk($msg); + + if (!$domain) + $this->plug->write_fail("No domain specified"); + + if (!$pattern) + $this->plug->write_fail( + "No domain pattern specified!\n" + . "Pattern has to be in quotes ('').\n" + . "\n" + . "See pattern examples below:\n" + . "Example: 'blog-posts,blog'\n" + . "Example: 'case-study'\n" + ); + + if (empty($pattern) || trim($pattern) == "*") + $this->plug->write_warn( + "Pattern cannot be an empty quote or '*'\n" + . "\n" + . "See pattern examples below:\n" + . "Example: 'blog-posts,blog'\n" + . "Example: 'case-study'\n" + ); + + + $domain = explode(" ", ucwords($domain)); + $domain_id = implode("-", $domain) . "-id"; + $domain = implode("", $domain); + $domain_dir = $this->plug->server->domains . $domain; + $exists = is_dir($domain_dir); + + if ($this->plug->force && $exists) + $this->plug->write_fail( + "Domain directory *$domain_dir* exists already!\n" + . "If you wish to force this action, pass the tag --force with the command\n" + . "Note, using --force will delete the existing directory and this process cannot be reversed!" + ); + + if ($exists) { + $talk( + "- Directory *$domain_dir* exists but --force tag detected\n" + . "- Deleting existing *$domain_dir*" + ); + + new LayUnlinkDir($domain_dir); + } + + $talk("- Creating new Domain directory in *$domain_dir*"); + new LayCopyDir($this->internal_dir . "Domain", $domain_dir); + + $talk("- Copying default files"); + $this->domain_default_files($domain, $domain_dir); + + $talk("- Linking .htaccess *{$this->plug->server->web}*"); + symlink($this->plug->server->web . ".htaccess", $domain_dir . $this->plug->s . ".htaccess"); + + $talk("- Linking shared directory *{$this->plug->server->shared}*"); + symlink($this->plug->server->shared, $domain_dir . $this->plug->s . "shared"); + + $talk("- Updating domains entry in *{$this->plug->server->web}index.php*"); + $this->update_general_domain_entry($domain, $domain_id, $pattern); + } + + public function domain_default_files(string $domain_name, string $domain_dir): void + { + file_put_contents( + $domain_dir . $this->plug->s . + "index.php", + <<create( + id: "default", + builder: new \web\domains\{$domain_name}\Plaster(), + ); + + FILE + ); + + file_put_contents( + $domain_dir . $this->plug->s . + "Plaster.php", + <<builder->init_start() + ->body_attr("dark", 'id="body-id"') + ->local("logo", DomainResource::get()->shared->img_default->logo) + ->local("section", "app") + ->init_end(); + } + + public function pages(): void + { + \$this->builder->route("index")->bind(function (ViewBuilder \$builder) { + \$builder->page("title", "Homepage") + ->page("desc", "This is the default homepage description") + ->assets( + "@css/another.css", + ) + ->body("homepage"); + }); + + \$this->builder->route("another-page")->bind(function (ViewBuilder \$builder) { + \$builder->page("title", "Another Page") + ->page("desc", "This is another page's description") + ->assets( + "@css/another.css", + ) + ->body("another"); + }); + } + } + + FILE + ); + } + + public function update_general_domain_entry(string $domain, string $domain_id, string $patterns): void + { + $pattern = ""; + foreach (explode(",", $patterns) as $p) { + $pattern .= '"' . $p . '",'; + } + + $pattern = rtrim($pattern, ","); + + $file = new SplFileObject($this->plug->server->web . "index.php", 'w+'); + $file->setFlags(SplFileObject::DROP_NEW_LINE | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY); + + $page = []; + $domains = []; + $key = 0; + $storing_domain = false; + + while (!$file->eof()) { + $entry = $file->fgets(); + + if (str_starts_with($entry, "Domain::new()")) + $storing_domain = true; + + if ($storing_domain) { + if (empty($entry)) + continue; + + $domains[$key][] = $entry; + + if (str_ends_with($entry, ";")) { + $storing_domain = false; + $key++; + } + + continue; + } + + $page[] = $entry; + } + + $default_domain = end($domains); + + $new_domain = [ + 'Domain::new()->create(', + ' id: "' . $domain_id . '",', + ' builder: new \web\domains\\' . $domain . '\\Plaster(),', + ' patterns: [' . $pattern . '],', + ');', + '', + ]; + + array_pop($domains); + array_push($page, $domains, $new_domain, $default_domain); + + $file->fwrite(implode("\n", $page)); + } +} \ No newline at end of file diff --git a/src/BobDBuilder/Cmd/Project.php b/src/BobDBuilder/Cmd/Project.php index 241846c..0db74f5 100644 --- a/src/BobDBuilder/Cmd/Project.php +++ b/src/BobDBuilder/Cmd/Project.php @@ -2,9 +2,7 @@ namespace BrickLayer\Lay\BobDBuilder\Cmd; -use BrickLayer\Lay\BobDBuilder\Engine; use BrickLayer\Lay\BobDBuilder\EnginePlug; -use BrickLayer\Lay\BobDBuilder\Enum\CmdOutType; use BrickLayer\Lay\BobDBuilder\Interface\CmdLayout; use BrickLayer\Lay\Core\Traits\IsSingleton; use BrickLayer\Lay\Libs\LayCopyDir; @@ -16,7 +14,7 @@ class Project implements CmdLayout private readonly EnginePlug $plug; private readonly array $tags; - public function _init(EnginePlug $plug) : void + public function _init(EnginePlug $plug): void { $this->plug = $plug; $plug->add_arg($this, ["project:create"], 'project_create', true); @@ -24,7 +22,7 @@ public function _init(EnginePlug $plug) : void public function _spin(): void { - if(!$this->plug->project_mode) + if (!$this->plug->project_mode) return; $this->tags = $this->plug->tags; @@ -32,17 +30,17 @@ public function _spin(): void $this->create(); } - public function create() : void + public function create(): void { $cmd = $this->tags['project_create'][0] ?? null; - if(!$cmd) + if (!$cmd) return; $server = $this->plug->server; // copy env file if it doesn't exist - if(!file_exists($server->root . ".env")) + if (!file_exists($server->root . ".env")) copy($server->root . ".env.example", $server->root . ".env"); // copy core lay js file to project lay folder diff --git a/src/BobDBuilder/Cmd/Symlink.php b/src/BobDBuilder/Cmd/Symlink.php index 681a6e4..2d2fc83 100644 --- a/src/BobDBuilder/Cmd/Symlink.php +++ b/src/BobDBuilder/Cmd/Symlink.php @@ -2,9 +2,7 @@ namespace BrickLayer\Lay\BobDBuilder\Cmd; -use BrickLayer\Lay\BobDBuilder\Engine; use BrickLayer\Lay\BobDBuilder\EnginePlug; -use BrickLayer\Lay\BobDBuilder\Enum\CmdOutType; use BrickLayer\Lay\BobDBuilder\Interface\CmdLayout; use BrickLayer\Lay\Core\Traits\IsSingleton; @@ -14,7 +12,7 @@ class Symlink implements CmdLayout private readonly EnginePlug $plug; - public function _init(EnginePlug $plug) : void + public function _init(EnginePlug $plug): void { $this->plug = $plug; @@ -73,7 +71,7 @@ private function dir(): void { $link = $this->plug->tags['link_dir'] ?? null; - if(!$link) + if (!$link) return; if (!isset($link[0])) @@ -87,15 +85,15 @@ private function dir(): void if (!is_dir($src)) $this->plug->write_fail( - "Source directory $src does not exist!\n" + "Source directory *$src* does not exist!\n" . "You cannot link a directory that doesn't exist" ); if (is_dir($dest)) { if (!$this->plug->force) $this->plug->write_warn( - "Destination directory: $dest exists already!\n" - . "If you want to REPLACE!! it, pass the flag --force\n" + "Destination directory: *$dest* exists already!\n" + . "If you want to REPLACE!! it, pass the flag *--force*\n" . "***### Take Note:: You will be deleting the former directory if you decide to pass the flag --force" ); @@ -106,8 +104,8 @@ private function dir(): void $this->plug->write_success( "Directory link created successfully!\n" - . "Source Directory: $src\n" - . "Destination Directory: $dest" + . "Source Directory: *$src*\n" + . "Destination Directory: *$dest*" ); } @@ -115,7 +113,7 @@ private function file(): void { $link = $this->plug->tags['link_file'] ?? null; - if(!$link) + if (!$link) return; if (!isset($link[0])) diff --git a/src/BobDBuilder/Engine.php b/src/BobDBuilder/Engine.php index d36e7fd..77a2b1a 100644 --- a/src/BobDBuilder/Engine.php +++ b/src/BobDBuilder/Engine.php @@ -11,16 +11,45 @@ class Engine public EnginePlug $plug; public function __construct( - private readonly array $args + private array $args ) { + $show_help = array_search("--help", $this->args, true); + $show_help = $show_help === false ? array_search("--h", $this->args, true) : $show_help; + + if ($show_help !== false) { + unset($this->args[$show_help]); + $show_help = true; + } + + $force_action = array_search("--force", $this->args, true); + $force_action = $force_action === false ? array_search("--f", $this->args, true) : $force_action; + + if ($force_action !== false) { + unset($this->args[$force_action]); + $force_action = true; + } + $this->plug = new EnginePlug($this->args); + $this->plug->force = $force_action ?? false; + $this->plug->show_help = $show_help ?? false; + foreach ($this->args as $i => $arg) { if($this->plug->run($i, $arg) == CustomContinueBreak::BREAK) break; } + // start BOB Execution + $this->plug->write( + "", + CmdOutType::TALK, + [ + 'open_talk' => true, + 'hide_current_cmd' => false, + ] + ); + if ($this->plug->show_intro) { $this->intro(); die; @@ -30,7 +59,22 @@ public function __construct( $this->plug->fire(); - $this->end(); + // End Bob execution + if(empty($this->plug->active_cmd)) + $this->plug->write_info( + "-- Bob has determined that the current command is invalid\n" + . "-- Please use --help to see the list of available commands" + , ["current_cmd" => $this->plug->typed_cmd] + ); + + $this->plug->write_success( + "\n" . ( + isset($this->plug->active_cmd_class) ? + "-- Operation completed!" : + "" + ), + ['close_talk' => true] + ); } public function intro(bool $close_talk = true): void @@ -47,7 +91,7 @@ public function intro(bool $close_talk = true): void public function help(): void { - if (!$this->plug->tags['show_help']) + if (!$this->plug->show_help) return; $this->intro(false); @@ -59,17 +103,4 @@ public function help(): void ); } - public function end(): void - { - if(empty($this->plug->active_cmd)) - $this->plug->write_info( - "-- Bob has determined that the current command is invalid\n" - . "-- Please use --help to see the list of commands available" - , ["current_cmd" => $this->plug->typed_cmd] - ); - - $this->plug->write_success("-- Operation completed!"); - } - - } \ No newline at end of file diff --git a/src/BobDBuilder/EnginePlug.php b/src/BobDBuilder/EnginePlug.php index 9d070e0..21daf96 100644 --- a/src/BobDBuilder/EnginePlug.php +++ b/src/BobDBuilder/EnginePlug.php @@ -6,21 +6,22 @@ use BrickLayer\Lay\BobDBuilder\Helper\Console\Console; use BrickLayer\Lay\BobDBuilder\Helper\Console\Format\Background; use BrickLayer\Lay\BobDBuilder\Helper\Console\Format\Foreground; +use BrickLayer\Lay\BobDBuilder\Helper\Console\Format\Style; use BrickLayer\Lay\BobDBuilder\Interface\CmdLayout; use BrickLayer\Lay\Core\Enums\CustomContinueBreak; use BrickLayer\Lay\Core\Exception; use BrickLayer\Lay\Core\LayConfig; use Error; use ReflectionClass; +use ReflectionException; +use TypeError; class EnginePlug { - /** - * @var bool - */ public bool $show_intro = true; - public bool $cmd_found = false; + public bool $show_help = false; public bool $force = false; + public bool $cmd_found = false; public array $tags = []; public array $plugged_args = []; public string $typed_cmd = ""; @@ -48,21 +49,15 @@ public function __construct( public function fire(): void { - $this->force = $this->tags['force_action'] ?? $this->force; $spun_correct_class = false; - set_error_handler(function (int $err_no, string $err_str, string $err_file, int $err_line) { - if(error_reporting() === 0) - return false; + Exception::new()->capture_errors(true); - Exception::throw_exception( - $err_str . "\n" - . "File: " . $err_file . ":$err_line", - "BobWarnings", - ); - - return true; - }, E_WARNING|E_USER_WARNING); + // This property is active when the command sent matches any on the existing Cmd classes + // If it's not set, there's no need to loop through the existing classes to spin their methods, + // we simply need to break out of this method and save php the stress. + if(!isset($this->active_cmd_class)) + return; foreach ($this->cmd_classes as $cmd_class) { if($spun_correct_class) @@ -74,7 +69,7 @@ public function fire(): void try{ $cmd_class->_spin(); } - catch (\TypeError|\Error|\Exception $e){ + catch (TypeError|Error|\Exception $e){ Exception::throw_exception( $e->getMessage() . "\n" . $e->getFile() . ":" . $e->getLine() @@ -97,12 +92,6 @@ public function run(int $index, string $arg): CustomContinueBreak if ($index == 1) $this->typed_cmd = $arg; - if ($this->arg(self::class, ["--help", "-h", "help"], $this->tags['show_help'], true)) - return CustomContinueBreak::BREAK; - - if ($this->arg(self::class, ["--force", "-f"], $this->tags['force_action'], true)) - return CustomContinueBreak::BREAK; - foreach ($this->plugged_args as $key => $arg) { if ($this->arg($arg['class'], [...$arg['cmd']], $this->tags[$key], ...$arg['value'])) return CustomContinueBreak::BREAK; @@ -127,7 +116,7 @@ private function load_cmd_classes() : void try { $class = $class->getMethod('new'); - } catch (\ReflectionException) { + } catch (ReflectionException) { Exception::throw_exception( " $cmd_class is not a singleton. \n" . " All Cmd classes must be singletons, use the trait `IsSingleton` to clear this error", @@ -196,30 +185,51 @@ public function write_success(string $message, array $opts = []) : void { } public function write_fail(string $message, array $opts = []) : void { + $opts['close_talk'] = true; + $opts['kill'] = true; + $this->write($message, CmdOutType::FAIL, $opts); } + public function write_talk(string $message, array $opts = []) : void { + $opts['color'] = "red"; + $this->write($message, CmdOutType::TALK, $opts); + } + public function write_warn(string $message, array $opts = []) : void { + $opts['close_talk'] = true; + $opts['kill'] = true; + $this->write($message, CmdOutType::WARN, $opts); } - public function write(string $message, CmdOutType $type, array $opts = []): void + public function write(string $message, ?CmdOutType $type = null, array $opts = []): void { - $kill = $opts['kill'] ?? true; - $close_talk = $opts['close_talk'] ?? true; - $open_talk = $opts['open_talk'] ?? true; + $kill = $opts['kill'] ?? false; + $open_talk = $opts['open_talk'] ?? false; + $close_talk = $opts['close_talk'] ?? false; $current_cmd = $this->active_cmd ?: ($opts['current_cmd'] ?? ""); - $hide_cur_cmd = $opts['hide_current_cmd'] ?? false; + $hide_cur_cmd = $opts['hide_current_cmd'] ?? true; $color = match ($type) { - default => Foreground::normal, + default => Style::normal, CmdOutType::SUCCESS => Foreground::green, CmdOutType::INFO => Foreground::light_cyan, + CmdOutType::WARN => Foreground::yellow, CmdOutType::FAIL => Foreground::red, + CmdOutType::TALK => Foreground::light_purple, }; + $color = $opts['color'] ?? $color; + + if(gettype($color) !== "object" || get_class($color) != Foreground::class) + Exception::throw_exception( + "Invalid Color Type received. Color must be of " . Foreground::class, + "InvalidConsoleColor" + ); + if ($open_talk) - Console::log("##>>> BobTheBuilder SAYS (::--__--::)", Foreground::light_gray); + Console::log("(^_^) Bob is Building --::--", Foreground::light_gray); if (!$hide_cur_cmd && !empty($current_cmd)) { print " CURRENT COMMAND "; @@ -229,16 +239,48 @@ public function write(string $message, CmdOutType $type, array $opts = []): void ); } - foreach (explode("\n", $message) as $m) { - Console::log(" " . $m, $color); + $list = false; + + if($type == CmdOutType::TALK && str_starts_with($message, "-")) { + Console::log(" o", Foreground::light_blue, newline: false); + $message = ltrim($message, "-"); + $list = true; + } + + foreach (explode("\n", $message) as $k => $m) { + if(empty($m)) + continue; + + if($list && $k > 0) + $m = " " . $m; + + if(!$list) + $m = " " . $m; + + if(str_contains($m, "*")) { + $m = preg_replace("/\*+/", "*", $m); + + foreach (explode("*", $m) as $i => $s) { + if($i % 2 == 0) + Console::log($s, $color, newline: false); + else + Console::log($s, Foreground::cyan, style: Style::bold , newline: false); + } + + Console::log(""); + + continue; + } + + Console::log($m, $color); } if ($close_talk) - Console::log("####> BobTheBuilder DONE TALKING...(-_-)", Foreground::light_gray); + Console::log("(-_-) Bob is Done -----", Foreground::light_gray); Console::bell(); - if ($kill) + if($kill) die; } diff --git a/src/BobDBuilder/Enum/CmdOutType.php b/src/BobDBuilder/Enum/CmdOutType.php index c9dbb65..041828b 100644 --- a/src/BobDBuilder/Enum/CmdOutType.php +++ b/src/BobDBuilder/Enum/CmdOutType.php @@ -8,4 +8,5 @@ enum CmdOutType case WARN; case FAIL; case SUCCESS; + case TALK; } diff --git a/src/BobDBuilder/Helper/Console/Console.php b/src/BobDBuilder/Helper/Console/Console.php index 8992a32..cc546c3 100644 --- a/src/BobDBuilder/Helper/Console/Console.php +++ b/src/BobDBuilder/Helper/Console/Console.php @@ -26,7 +26,7 @@ class Console { * @param boolean $newline Append EOF? * @return void */ - public static function log(string $text = '', Foreground $color = Foreground::normal, ?Background $bg_color = null, ?Style $style = null, bool $newline = true) : void + public static function log(string $text = '', Foreground|Style $color = Style::normal, ?Background $bg_color = null, ?Style $style = null, bool $newline = true) : void { $colored_string = "\033[" . $color->value . "m"; diff --git a/src/BobDBuilder/Helper/Console/Format/Foreground.php b/src/BobDBuilder/Helper/Console/Format/Foreground.php index 8df5e97..477b3c7 100644 --- a/src/BobDBuilder/Helper/Console/Format/Foreground.php +++ b/src/BobDBuilder/Helper/Console/Format/Foreground.php @@ -4,10 +4,6 @@ enum Foreground : string { - case bold = '1'; - case normal = '0;39'; - case dim = '2'; - case black = '0;30'; case blue = '0;34'; case green = '0;32'; diff --git a/src/BobDBuilder/Helper/Console/Format/Style.php b/src/BobDBuilder/Helper/Console/Format/Style.php index e0160b3..1cb015d 100644 --- a/src/BobDBuilder/Helper/Console/Format/Style.php +++ b/src/BobDBuilder/Helper/Console/Format/Style.php @@ -4,6 +4,10 @@ enum Style : string { + case bold = '1'; + case normal = '0;39'; + case dim = '2'; + case underline = '4'; case reverse = '7'; case blink = '5'; diff --git a/src/Core/Exception.php b/src/Core/Exception.php index c39e1a9..88161bf 100644 --- a/src/Core/Exception.php +++ b/src/Core/Exception.php @@ -2,13 +2,17 @@ declare(strict_types=1); namespace BrickLayer\Lay\Core; -use BrickLayer\Lay\Orm\SQL; - abstract class Exception { /** * @throws \Exception */ - public static function throw_exception(string $message, string $title = "Generic", bool $kill = true, bool $use_lay_error = true, array $stack_track = []) : void { - SQL::instance()->use_exception("LayExp_$title", $message, $kill, trace: $stack_track, use_lay_error: $use_lay_error); + public static function throw_exception(string $message, string $title = "Generic", bool $kill = true, bool $use_lay_error = true, array $stack_track = []) : void + { + self::new()->use_exception("LayExp_$title", $message, $kill, trace: $stack_track, use_lay_error: $use_lay_error); + } + + public static function new() : \BrickLayer\Lay\Orm\Exception + { + return \BrickLayer\Lay\Orm\Exception::new(); } } \ No newline at end of file diff --git a/src/Core/Traits/Config.php b/src/Core/Traits/Config.php index 6e18331..7306564 100644 --- a/src/Core/Traits/Config.php +++ b/src/Core/Traits/Config.php @@ -171,11 +171,14 @@ public static function set_smtp(): void public static function get_orm(): SQL { self::is_init(); - try { - return self::$SQL_INSTANCE; - } catch (\Error $e){ - Exception::throw_exception("Trying to access the database without connecting; call `LayConfig::connect()` or if you are in a View Handler, call `\$this->builder->connect_db()`.","ORMErr"); - } + + if(!isset(self::$SQL_INSTANCE)) + Exception::throw_exception( + "Trying to access the database without connecting; use`\$this->builder->connect_db()` to connect db.", + "OrmNotDetected" + ); + + return self::$SQL_INSTANCE; } public static function is_page_compressed(): bool @@ -203,7 +206,7 @@ public static function validate_lay(): void if (!defined("SAFE_TO_INIT_LAY") || !SAFE_TO_INIT_LAY) Exception::throw_exception("This script cannot be accessed this way, please return home", "BadRequest"); - SQL::new()->capture_errors(); + Exception::new()->capture_errors(); } public function dont_compress_html(): self diff --git a/src/Core/View/Domain.php b/src/Core/View/Domain.php index e7b87d9..f889760 100644 --- a/src/Core/View/Domain.php +++ b/src/Core/View/Domain.php @@ -131,9 +131,16 @@ private function activate_domain(string $id, string $pattern, ViewCast|ApiHooks $file = explode("\\", $builder::class); array_pop($file); + $domain_file = $file; + array_shift($domain_file); + + $doc_root = explode(DIRECTORY_SEPARATOR, $_SERVER['DOCUMENT_ROOT']); + $doc_root = end($doc_root); + + $domain_base = $doc_root != end($domain_file) ? implode("/", $domain_file) . "/" : ""; $data = LayConfig::site_data(); - $base = $data->using_domain ? "" : implode("/", $file) . "/"; + self::$current_route_details['route'] = $route ?: "index"; self::$current_route_details['route_as_array'] = $route_as_array; @@ -141,7 +148,7 @@ private function activate_domain(string $id, string $pattern, ViewCast|ApiHooks self::$current_route_details['domain_type'] = $domain_type; self::$current_route_details['domain_id'] = $id; self::$current_route_details['domain_uri'] = $data->domain . ($pattern != '*' ? $pattern . '/' : ''); - self::$current_route_details['domain_base'] = $data->base . $base; + self::$current_route_details['domain_base'] = $data->base . $domain_base; self::$current_route_details['domain_root'] = LayConfig::server_data()->root . implode(DIRECTORY_SEPARATOR, $file) . DIRECTORY_SEPARATOR; $builder->init(); @@ -335,6 +342,7 @@ public static function current_route_data( 'domain_type', 'domain_id', 'domain_uri', + 'domain_base', 'domain_root', 'pattern', '*', diff --git a/src/Core/View/DomainResource.php b/src/Core/View/DomainResource.php index 2563059..dabcb4e 100644 --- a/src/Core/View/DomainResource.php +++ b/src/Core/View/DomainResource.php @@ -48,9 +48,9 @@ public static function init() : void $obj->static = $base . "static/"; $obj->static_env = $obj->static . $env_src . "/"; - $obj->css = $obj->root . "css/"; - $obj->img = $obj->root . "images/"; - $obj->js = $obj->root . "js/"; + $obj->css = $obj->static_env . "css/"; + $obj->img = $obj->static_env . "images/"; + $obj->js = $obj->static_env . "js/"; $shared = $obj->root . "shared/"; $obj->shared = (object) [ diff --git a/src/Core/View/ViewSrc.php b/src/Core/View/ViewSrc.php index d6dadf6..5df8a7b 100644 --- a/src/Core/View/ViewSrc.php +++ b/src/Core/View/ViewSrc.php @@ -23,16 +23,14 @@ public static function gen(string $src) : string $src ); - $base = $client->domain->domain_uri; + $base = $client->domain->domain_base; if(!str_starts_with($src, $base)) return $src; $local_file = str_replace($base, "", $src); - try { - $src .= "?mt=" . @filemtime($local_file); - } catch (\Exception) {} + $src .= "?mt=" . @filemtime($local_file); return $src; } diff --git a/src/Libs/LayUnlinkDir.php b/src/Libs/LayUnlinkDir.php index d3b7ae0..21717df 100644 --- a/src/Libs/LayUnlinkDir.php +++ b/src/Libs/LayUnlinkDir.php @@ -12,6 +12,15 @@ public function __construct(string $dir) { if (!is_dir($dir)) { self::$result = false; + + if(file_exists($dir)) + self::$result = unlink($dir); + + return; + } + + if(is_link($dir)) { + self::$result = unlink($dir); return; } diff --git a/src/Orm/Exception.php b/src/Orm/Exception.php index c4f15de..3509588 100644 --- a/src/Orm/Exception.php +++ b/src/Orm/Exception.php @@ -5,16 +5,22 @@ use BrickLayer\Lay\BobDBuilder\Helper\Console\Console; use BrickLayer\Lay\BobDBuilder\Helper\Console\Format\Foreground; +use BrickLayer\Lay\BobDBuilder\Helper\Console\Format\Style; use BrickLayer\Lay\Core\Enums\LayMode; use BrickLayer\Lay\Core\LayConfig; +use BrickLayer\Lay\Core\Traits\IsSingleton; class Exception { - private static string $ENV = "DEVELOPMENT"; + use IsSingleton; - public function capture_errors() : void { + private static string $ENV = "DEVELOPMENT"; + private static string $message; + private static bool $already_caught = false; - set_error_handler(function (int $err_no, string $err_str, string $err_file, int $err_line) + public function capture_errors(bool $turn_warning_to_errors = false) : void + { + set_error_handler(function (int $err_no, string $err_str, string $err_file, int $err_line) use($turn_warning_to_errors) { if(error_reporting() != E_ALL) return; @@ -26,7 +32,8 @@ public function capture_errors() : void { "LayWarning", $err_str . $eol . "File: " . $err_file . ":$err_line" . $eol, - kill: false + kill: $turn_warning_to_errors, + raw: ["err_code" => $err_no] ); return true; @@ -35,14 +42,14 @@ public function capture_errors() : void { $this->use_exception( "LayError", $err_str . $eol - . "File: " . $err_file . ":$err_line" . $eol + . "File: " . $err_file . ":$err_line" . $eol, + raw: ["err_code" => $err_no] ); return true; }, E_ALL|E_STRICT); } - public function set_env(string $ENV): void { $ENV = strtolower($ENV); @@ -117,12 +124,12 @@ private function container($title, $body, $other = []): string $k++; $last_file = explode("/", $v['file']); - $last_file = end($last_file); + $last_file = $v['class'] ?? end($last_file); $stack .= <<
#$k: {$v['function']}(...)
$last_file ({$v['line']})
- {$v['file']}; {$v['line']} + {$v['file']}:{$v['line']}
STACK; @@ -134,6 +141,8 @@ private function container($title, $body, $other = []): string $stack .= ""; + self::$message = $title . " \n" . strip_tags($body); + if ($display) { $display = << @@ -146,7 +155,7 @@ private function container($title, $body, $other = []): string if($cli_mode) { $body = strip_tags($body); - Console::log(" $title ", Foreground::bold); + Console::log(" $title ", Style::bold); print "---------------------\n"; Console::log($body, $cli_color); print "---------------------\n"; @@ -199,6 +208,9 @@ private function convertRaw($print_val, $replace, &$body): void */ protected function show_exception($type, $opt = []): void { + if(self::$already_caught) + return; + $query = $opt[0] ?? ""; $query_type = $opt[1] ?? ""; $use_lay_error = $opt['use_lay_error'] ?? true; @@ -251,7 +263,11 @@ class_alias(get_class($anon_class), $exception_class); if(LayConfig::get_mode() === LayMode::HTTP) @http_response_code(500); - if ($act == "kill") - die; + if ($act == "kill") { + self::$already_caught = true; + error_reporting(0); + ini_set('error_log', false); + throw new \Exception(self::$message, 914); + } } } From b9deb991b37eeb37d12e59a1a6740e52906033bf Mon Sep 17 00:00:00 2001 From: Osahenrumwen Aigbogun Date: Mon, 18 Dec 2023 18:32:07 +0100 Subject: [PATCH 08/10] Fixed critical error --- src/BobDBuilder/EnginePlug.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/BobDBuilder/EnginePlug.php b/src/BobDBuilder/EnginePlug.php index 21daf96..6b921fb 100644 --- a/src/BobDBuilder/EnginePlug.php +++ b/src/BobDBuilder/EnginePlug.php @@ -107,12 +107,20 @@ private function load_cmd_classes() : void $namespace = implode("\\", $namespace) . "\\Cmd"; foreach (scandir(__DIR__ . $this->s . "Cmd") as $class) { - if ($class == "." || $class == ".." || is_dir($class)) + if ( + $class == "." || + $class == ".." || + is_dir(__DIR__ . $this->s . "Cmd" . $this->s . $class) + ) continue; $cmd_class = $namespace . "\\" . explode(".php", $class)[0]; - $class = new ReflectionClass($cmd_class); + try{ + $class = new ReflectionClass($cmd_class); + } catch (ReflectionException $e){ + Exception::throw_exception($e->getMessage(), "ReflectionException"); + } try { $class = $class->getMethod('new'); From 6994c60ce67764b1993eedc2e842752e4e33caaf Mon Sep 17 00:00:00 2001 From: Osahenrumwen Aigbogun Date: Mon, 18 Dec 2023 21:32:59 +0100 Subject: [PATCH 09/10] More fixes --- src/BobDBuilder/Cmd/Symlink.php | 124 +----------------- .../Cmd/{MakeTraits => Traits/Make}/Brick.php | 2 +- .../{MakeTraits => Traits/Make}/Domain.php | 2 +- src/BobDBuilder/Cmd/Traits/Symlink/Dir.php | 48 +++++++ src/BobDBuilder/Cmd/Traits/Symlink/File.php | 45 +++++++ .../Cmd/Traits/Symlink/Htaccess.php | 45 +++++++ .../Exception.php => Core/CoreException.php} | 56 +++----- src/Core/Exception.php | 4 +- src/Core/Traits/Init.php | 24 +++- src/Core/View/Domain.php | 11 +- src/Orm/Config.php | 59 ++++++--- src/Orm/SQL.php | 32 ++++- src/Orm/StoreResult.php | 3 +- src/Orm/Traits/Clean.php | 3 +- src/Orm/Traits/Controller.php | 3 - 15 files changed, 261 insertions(+), 200 deletions(-) rename src/BobDBuilder/Cmd/{MakeTraits => Traits/Make}/Brick.php (76%) rename src/BobDBuilder/Cmd/{MakeTraits => Traits/Make}/Domain.php (99%) create mode 100644 src/BobDBuilder/Cmd/Traits/Symlink/Dir.php create mode 100644 src/BobDBuilder/Cmd/Traits/Symlink/File.php create mode 100644 src/BobDBuilder/Cmd/Traits/Symlink/Htaccess.php rename src/{Orm/Exception.php => Core/CoreException.php} (74%) diff --git a/src/BobDBuilder/Cmd/Symlink.php b/src/BobDBuilder/Cmd/Symlink.php index 2d2fc83..8a653a5 100644 --- a/src/BobDBuilder/Cmd/Symlink.php +++ b/src/BobDBuilder/Cmd/Symlink.php @@ -2,6 +2,9 @@ namespace BrickLayer\Lay\BobDBuilder\Cmd; +use BrickLayer\Lay\BobDBuilder\Cmd\Traits\Symlink\Dir; +use BrickLayer\Lay\BobDBuilder\Cmd\Traits\Symlink\File; +use BrickLayer\Lay\BobDBuilder\Cmd\Traits\Symlink\Htaccess; use BrickLayer\Lay\BobDBuilder\EnginePlug; use BrickLayer\Lay\BobDBuilder\Interface\CmdLayout; use BrickLayer\Lay\Core\Traits\IsSingleton; @@ -28,124 +31,9 @@ public function _spin(): void $this->file(); } - private function htaccess(): void - { - $plug = $this->plug; - $dest = $plug->tags['link_htaccess'][0] ?? null; - - if (!$dest) - return; - - $dest = $plug->server->domains . rtrim(str_replace(".htaccess", "", $dest), "/") . $plug->s; - - if (!is_dir($dest)) { - if (!$plug->force) - $plug->write_fail( - "Directory $dest does not exist! if you want the directory to be created automatically; " - . "pass the flag --force", - ); - - umask(0); - mkdir($dest, 0777, true); - } - - $dest .= ".htaccess"; - - if (file_exists($dest)) { - if (!$plug->force) - $plug->write_warn( - "htaccess exists already at: $dest" - . "If you want to REPLACE!! it, pass the flag --force\n" - . "***### Take Note:: You will be deleting the former htaccess if you decide to pass the flag --force" - ); - - unlink($dest); - } - - symlink($plug->server->web . ".htaccess", $dest); - - $plug->write_success("htaccess successfully linked to: $dest"); - } - - private function dir(): void - { - $link = $this->plug->tags['link_dir'] ?? null; - - if (!$link) - return; - - if (!isset($link[0])) - $this->plug->write_fail("Source directory not specified!"); - - if (!isset($link[1])) - $this->plug->write_fail("Destination directory not specified!"); - - $src = $this->plug->server->root . $link[0]; - $dest = $this->plug->server->root . $link[1]; - if (!is_dir($src)) - $this->plug->write_fail( - "Source directory *$src* does not exist!\n" - . "You cannot link a directory that doesn't exist" - ); - - if (is_dir($dest)) { - if (!$this->plug->force) - $this->plug->write_warn( - "Destination directory: *$dest* exists already!\n" - . "If you want to REPLACE!! it, pass the flag *--force*\n" - . "***### Take Note:: You will be deleting the former directory if you decide to pass the flag --force" - ); - - unlink($dest); - } - - symlink($src, $dest); - - $this->plug->write_success( - "Directory link created successfully!\n" - . "Source Directory: *$src*\n" - . "Destination Directory: *$dest*" - ); - } - - private function file(): void - { - $link = $this->plug->tags['link_file'] ?? null; - - if (!$link) - return; - - if (!isset($link[0])) - $this->plug->write_fail("Source file not specified!"); - - if (!isset($link[1])) - $this->plug->write_fail("Destination file not specified!"); - - $src = $this->plug->server->root . $link[0]; - $dest = $this->plug->server->root . $link[1]; - - if (!file_exists($src)) - $this->plug->write_fail("Source file $src does not exist! You cannot link a file that doesn't exist"); - - if (file_exists($dest)) { - if (!$this->plug->force) - $this->plug->write_warn( - "Destination file: $dest exists already!\n" - . "If you want to REPLACE!! it, pass the flag --force\n" - . "***### Take Note:: You will be deleting the former file if you decide to pass the flag --force" - ); - - unlink($dest); - } - - symlink($src, $dest); - - $this->plug->write_success( - "Directory link created successfully!\n" - . "Source Directory: $src\n" - . "Destination Directory: $dest" - ); - } + use Htaccess; + use Dir; + use File; } \ No newline at end of file diff --git a/src/BobDBuilder/Cmd/MakeTraits/Brick.php b/src/BobDBuilder/Cmd/Traits/Make/Brick.php similarity index 76% rename from src/BobDBuilder/Cmd/MakeTraits/Brick.php rename to src/BobDBuilder/Cmd/Traits/Make/Brick.php index 23e9880..d87a98e 100644 --- a/src/BobDBuilder/Cmd/MakeTraits/Brick.php +++ b/src/BobDBuilder/Cmd/Traits/Make/Brick.php @@ -1,6 +1,6 @@ plug->tags['link_dir'] ?? null; + + if (!$link) + return; + + if (!isset($link[0])) + $this->plug->write_fail("Source directory not specified!"); + + if (!isset($link[1])) + $this->plug->write_fail("Destination directory not specified!"); + + $src = $this->plug->server->root . $link[0]; + $dest = $this->plug->server->root . $link[1]; + + if (!is_dir($src)) + $this->plug->write_fail( + "Source directory *$src* does not exist!\n" + . "You cannot link a directory that doesn't exist" + ); + + if (is_dir($dest)) { + if (!$this->plug->force) + $this->plug->write_warn( + "Destination directory: *$dest* exists already!\n" + . "If you want to REPLACE!! it, pass the flag *--force*\n" + . "***### Take Note:: You will be deleting the former directory if you decide to pass the flag --force" + ); + + unlink($dest); + } + + symlink($src, $dest); + + $this->plug->write_success( + "Directory link created successfully!\n" + . "Source Directory: *$src*\n" + . "Destination Directory: *$dest*" + ); + } +} \ No newline at end of file diff --git a/src/BobDBuilder/Cmd/Traits/Symlink/File.php b/src/BobDBuilder/Cmd/Traits/Symlink/File.php new file mode 100644 index 0000000..dd4bfaa --- /dev/null +++ b/src/BobDBuilder/Cmd/Traits/Symlink/File.php @@ -0,0 +1,45 @@ +plug->tags['link_file'] ?? null; + + if (!$link) + return; + + if (!isset($link[0])) + $this->plug->write_fail("Source file not specified!"); + + if (!isset($link[1])) + $this->plug->write_fail("Destination file not specified!"); + + $src = $this->plug->server->root . $link[0]; + $dest = $this->plug->server->root . $link[1]; + + if (!file_exists($src)) + $this->plug->write_fail("Source file *$src* does not exist! You cannot link a file that doesn't exist"); + + if (file_exists($dest)) { + if (!$this->plug->force) + $this->plug->write_warn( + "Destination file: *$dest* exists already!\n" + . "If you want to REPLACE!! it, pass the flag *--force*\n" + . "***### Take Note:: You will be deleting the former file if you decide to pass the flag --force" + ); + + unlink($dest); + } + + symlink($src, $dest); + + $this->plug->write_success( + "Directory link created successfully!\n" + . "Source Directory: *$src*\n" + . "Destination Directory: *$dest*" + ); + } +} \ No newline at end of file diff --git a/src/BobDBuilder/Cmd/Traits/Symlink/Htaccess.php b/src/BobDBuilder/Cmd/Traits/Symlink/Htaccess.php new file mode 100644 index 0000000..d3f3489 --- /dev/null +++ b/src/BobDBuilder/Cmd/Traits/Symlink/Htaccess.php @@ -0,0 +1,45 @@ +plug; + $dest = $plug->tags['link_htaccess'][0] ?? null; + + if (!$dest) + return; + + $dest = $plug->server->domains . rtrim(str_replace(".htaccess", "", $dest), "/") . $plug->s; + + if (!is_dir($dest)) { + if (!$plug->force) + $plug->write_fail( + "Directory $dest does not exist! if you want the directory to be created automatically; " + . "pass the flag --force", + ); + + umask(0); + mkdir($dest, 0777, true); + } + + $dest .= ".htaccess"; + + if (file_exists($dest)) { + if (!$plug->force) + $plug->write_warn( + "htaccess exists already at: $dest" + . "If you want to REPLACE!! it, pass the flag --force\n" + . "***### Take Note:: You will be deleting the former htaccess if you decide to pass the flag --force" + ); + + unlink($dest); + } + + symlink($plug->server->web . ".htaccess", $dest); + + $plug->write_success("htaccess successfully linked to: $dest"); + } +} \ No newline at end of file diff --git a/src/Orm/Exception.php b/src/Core/CoreException.php similarity index 74% rename from src/Orm/Exception.php rename to src/Core/CoreException.php index 3509588..1ce0af5 100644 --- a/src/Orm/Exception.php +++ b/src/Core/CoreException.php @@ -1,16 +1,15 @@ " : "\n"; @@ -64,16 +63,16 @@ public function get_env(): string /** * @throws \Exception */ - public function use_exception(string $title, string $body, bool $kill = true, array $trace = [], array $raw = [], bool $use_lay_error = true): void + public function use_exception(string $title, string $body, bool $kill = true, array $trace = [], array $raw = [], bool $use_lay_error = true, array $opts = []): void { - $this->show_exception(-8, - [ + $this->show_exception([ "title" => $title, "body_includes" => $body, "kill" => $kill, "trace" => $trace, "raw" => $raw, "use_lay_error" => $use_lay_error, + "exception_type" => $opts['type'] ?? 'error' ] ); } @@ -206,16 +205,14 @@ private function convertRaw($print_val, $replace, &$body): void /** * @throws \Exception */ - protected function show_exception($type, $opt = []): void + private function show_exception($opt = []): void { if(self::$already_caught) return; - $query = $opt[0] ?? ""; - $query_type = $opt[1] ?? ""; $use_lay_error = $opt['use_lay_error'] ?? true; - $query = (self::$ENV == "DEVELOPMENT" && is_string($query)) ? htmlspecialchars($query) : $query; $trace = [...$opt['trace'] ?? [], ...debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)]; + $type = $opt['exception_type']; if (!$use_lay_error) { if($opt['kill'] ?? true) { @@ -232,33 +229,16 @@ class_alias(get_class($anon_class), $exception_class); return; } - switch ($type) { - default: - $act = $this->container("QueryExecErr", "" . mysqli_error(SQL::new()->get_link()) . "
$query
Statement: __RAW_VALUE_TYPE__
", ["stack" => $trace, "core" => "error", "raw" => ["__RAW_VALUE_TYPE__" => $query_type], "act" => "kill"]); - break; - case -9: - $act = $this->container("QueryReview", "
$query
", ["stack" => $trace, "core" => "view"]); - break; - case -8: - $act = $this->container($opt['title'], $opt['body_includes'], ["stack" => $trace, "core" => "error", "act" => @$opt['kill'] ? "kill" : "allow", "raw" => $opt['raw']]); - break; - - case 0: - $act = $this->container("ConnErr", "No connection detected:
Connection might be closed:
", ["stack" => $trace, "core" => "error"]); - break; - case 1: - $db = $opt[0]; - $usr = $opt[1]; - $host = $opt[2]; - $act = $this->container("ConnTest", "

Connection Established!

Your connection info states:
> Host: " . $host . "
> User: " . $usr . "
> Database: " . $db . "
", ["stack" => $trace, "core" => "success"]); - break; - case 2: - $act = $this->container("ConnErr", "
" . mysqli_connect_error() . "
", ["stack" => $trace, "core" => "error", "act" => "kill"]); - break; - case 3: - $act = $this->container("ConnErr", "
Failed to close connection. No pre-existing DB connection
", ["stack" => $trace, "core" => "error", "act" => "kill"]); - break; - } + $act = $this->container( + $opt['title'], + $opt['body_includes'], + [ + "stack" => $trace, + "core" => $type, + "act" => @$opt['kill'] ? "kill" : "allow", + "raw" => $opt['raw'], + ] + ); if(LayConfig::get_mode() === LayMode::HTTP) @http_response_code(500); diff --git a/src/Core/Exception.php b/src/Core/Exception.php index 88161bf..6cd62b3 100644 --- a/src/Core/Exception.php +++ b/src/Core/Exception.php @@ -11,8 +11,8 @@ public static function throw_exception(string $message, string $title = "Generic self::new()->use_exception("LayExp_$title", $message, $kill, trace: $stack_track, use_lay_error: $use_lay_error); } - public static function new() : \BrickLayer\Lay\Orm\Exception + public static function new() : \BrickLayer\Lay\Core\CoreException { - return \BrickLayer\Lay\Orm\Exception::new(); + return \BrickLayer\Lay\Core\CoreException::new(); } } \ No newline at end of file diff --git a/src/Core/Traits/Init.php b/src/Core/Traits/Init.php index d42374b..35a4ef5 100644 --- a/src/Core/Traits/Init.php +++ b/src/Core/Traits/Init.php @@ -28,11 +28,16 @@ private static function set_web_root(&$options) : void $options['base_no_proto'] = self::$base_no_proto; $options['base_no_proto_no_www'] = self::$base_no_proto_no_www; - $web = $options['using_domain'] ? "" : "/web"; + $web = ""; - $options['domain'] = self::$base . ( $web ? "web/" : "" ); - $options['domain_no_proto'] = self::$base_no_proto . $web; - $options['domain_no_proto_no_www'] = self::$base_no_proto_no_www . $web; + if(!$options['using_domain']) { + $web = $options['using_web'] ? "" : "web/"; + $options['use_domain_file'] = true; + } + + $options['domain'] = self::$base . ( $web ?: "" ); + $options['domain_no_proto'] = self::$base_no_proto . ($web ? "/$web" : ""); + $options['domain_no_proto_no_www'] = self::$base_no_proto_no_www . ($web ? "/$web" : ""); } private static function set_dir() : void { @@ -51,7 +56,7 @@ private static function first_class_citizens() : void { // Don't bother running any process if document root is not set. // This means the framework is being accessed from the cli, - // we don't want run unnecessary compute and waste resources. + // we don't want to run unnecessary compute and waste resources. if(empty($_SERVER['DOCUMENT_ROOT'])) { self::$LAY_MODE = LayMode::CLI; return; @@ -70,12 +75,15 @@ private static function first_class_citizens() : void { $pin = rtrim($pin, "/"); $base = explode($pin, $string); - $options['using_domain'] = str_starts_with($base[1], "/web/domains/"); - if($options['using_domain']) + $options['using_web'] = str_starts_with($base[1], "/web"); + $options['using_domain'] = str_starts_with($base[1], "/web/domain"); + + if($options['using_domain'] || $options['using_web']) $base = [""]; self::$layConfigOptions['header']['using_domain'] = $options['using_domain']; + self::$layConfigOptions['header']['using_web'] = $options['using_web']; $http_host = $_SERVER['HTTP_HOST'] ?? "cli"; $env_host = $_SERVER['REMOTE_ADDR'] ?? "cli"; @@ -120,6 +128,8 @@ private static function initialize() : self { "cache_domains" => $options['switch']['cache_domains'] ?? true, "global_api" => $options['header']['api'] ?? null, "using_domain" => $options['header']['using_domain'] ?? null, + "using_web" => $options['header']['using_web'] ?? null, + "use_domain_file" => null, // this is updated when webroot is created after first class is init "name" => [ "short" => $options['meta']['name']['short'] ?? "Lay - Lite PHP Framework", "long" => $options['meta']['name']['full'] ?? "Lay - Lite PHP Framework | Simple, Light, Quick", diff --git a/src/Core/View/Domain.php b/src/Core/View/Domain.php index f889760..64ebe2e 100644 --- a/src/Core/View/Domain.php +++ b/src/Core/View/Domain.php @@ -134,13 +134,8 @@ private function activate_domain(string $id, string $pattern, ViewCast|ApiHooks $domain_file = $file; array_shift($domain_file); - $doc_root = explode(DIRECTORY_SEPARATOR, $_SERVER['DOCUMENT_ROOT']); - $doc_root = end($doc_root); - - $domain_base = $doc_root != end($domain_file) ? implode("/", $domain_file) . "/" : ""; - $data = LayConfig::site_data(); - + $domain_base = $data->use_domain_file ? implode("/", $domain_file) . "/" : ""; self::$current_route_details['route'] = $route ?: "index"; self::$current_route_details['route_as_array'] = $route_as_array; @@ -148,7 +143,7 @@ private function activate_domain(string $id, string $pattern, ViewCast|ApiHooks self::$current_route_details['domain_type'] = $domain_type; self::$current_route_details['domain_id'] = $id; self::$current_route_details['domain_uri'] = $data->domain . ($pattern != '*' ? $pattern . '/' : ''); - self::$current_route_details['domain_base'] = $data->base . $domain_base; + self::$current_route_details['domain_base'] = $data->domain . $domain_base; self::$current_route_details['domain_root'] = LayConfig::server_data()->root . implode(DIRECTORY_SEPARATOR, $file) . DIRECTORY_SEPARATOR; $builder->init(); @@ -164,7 +159,7 @@ private function activate_domain(string $id, string $pattern, ViewCast|ApiHooks private function check_route_is_static_file(string $view) : string { $ext_array = ["js","css","map","jpeg","jpg","png","gif","jiff","webp","svg","json","xml","yaml","ttf","woff2","woff"]; $x = explode(".",$view); - $ext = strtolower((string) end($x)); + $ext = explode("?", strtolower((string) end($x)))[0]; if(count($x) > 1 && in_array($ext,$ext_array,true)) { header("Content-Type: application/json"); diff --git a/src/Orm/Config.php b/src/Orm/Config.php index fab82d1..7c33cb4 100644 --- a/src/Orm/Config.php +++ b/src/Orm/Config.php @@ -1,6 +1,8 @@ set_env("DEVELOPMENT") : - $me->set_env("PRODUCTION"); + CoreException::new()->set_env(LayConfig::$ENV_IS_PROD ? "PRODUCTION" : "DEVELOPMENT"); - $me->set_db($connection); + self::new()->set_db($connection); } /** @@ -46,7 +41,7 @@ private static function _init(mysqli|array|null $connection) : void { private function connect() : ?mysqli { extract(self::$DB_ARGS); $charset = $charset ?? self::$CHARSET; - $this->set_env($env ?? $this->get_env()); + CoreException::new()->set_env($env ?? $this->get_env()); $cxn = $this->ping(true,null, true); $port = $port ?? null; $socket = $socket ?? null; @@ -81,7 +76,10 @@ private function connect() : ?mysqli { if (filter_var($silent,FILTER_VALIDATE_BOOL)) return null; else - $this->show_exception(2); + $this->exception( + "ConnErr", + "
" . mysqli_connect_error() . "
" + ); } } @@ -118,14 +116,40 @@ public function ping(bool $ignore_msg = false, ?mysqli $link = null, bool $ignor if($cxn){ if(isset($this->get_link()->host_info)) { if (@mysqli_ping($cxn)) { - $x = $this->query("SELECT SUBSTRING_INDEX(host, ':', 1) AS host_short, - USER AS users, db FROM information_schema.processlist", ["fetch_as" => "assoc", "query_type" => "select"]); + $x = $this->query( + "SELECT SUBSTRING_INDEX(host, ':', 1) AS host_short, + USER AS users, db FROM information_schema.processlist", + ["fetch_as" => "assoc", "query_type" => "select"] + ); + $db = $x['db']; $usr = $x['users']; $host = $x['host_short']; - if (!$ignore_msg) $this->show_exception(1, [$db, $usr, $host]); + + if (!$ignore_msg) + $this->exception( + "ConnTest", + <<Connection Established! + Your connection info states: +
+ > Host: $host +
+
+ > User: $usr +
+
+ > Database: $db +
+ CONN, + [ "type" => "success" ] + ); } - else if (!$ignore_no_conn) $this->show_exception(0); + else if (!$ignore_no_conn) + $this->exception( + "ConnErr", + "No connection detected:
Connection might be closed:
", + ); } } return ["host" => $host, "user" => $usr, "db" => $db]; } @@ -135,7 +159,10 @@ public function close(?mysqli $link = null, bool $silent_error = false) : bool { return mysqli_close($link ?? $this->get_link()); }catch (\Exception $e){ if(!$silent_error) - $this->show_exception(3); + $this->exception( + "ConnErr", + "
Failed to close connection. No pre-existing DB connection
" + ); } return false; diff --git a/src/Orm/SQL.php b/src/Orm/SQL.php index 9a19a47..be6e6e7 100644 --- a/src/Orm/SQL.php +++ b/src/Orm/SQL.php @@ -3,6 +3,8 @@ namespace BrickLayer\Lay\Orm; +use BrickLayer\Lay\Core\CoreException; +use BrickLayer\Lay\Core\Traits\IsSingleton; use BrickLayer\Lay\Orm\Traits\Controller; use mysqli; use mysqli_result; @@ -10,8 +12,9 @@ /** * Simple Query Language **/ -class SQL extends Exception +class SQL { + use IsSingleton; use Config; use Controller; @@ -33,6 +36,15 @@ public function switch_db(string $name): bool return mysqli_select_db(self::$link, $name); } + public function exception(string $title, string $message, array $opts = []) : CoreException + { + return CoreException::new()->use_exception( + "OrmExp_" . $title, + $message, + opts: $opts + ); + } + /** * Query Engine * @param string $query @@ -43,7 +55,10 @@ public function switch_db(string $name): bool final public function query(string $query, array $option = []): int|bool|array|null|mysqli_result { if (!isset(self::$link)) - $this->show_exception(0); + $this->exception( + "ConnErr", + "No connection detected:
Connection might be closed!
", + ); $option = $this->array_flatten($option); $debug = $option['debug'] ?? 0; @@ -65,7 +80,11 @@ final public function query(string $query, array $option = []): int|bool|array|n $option['debug'][1] = $query_type; if ($debug) - $this->show_exception(-9, $option['debug']); + $this->exception( + "QueryReview", + "
$query
", + [ "type" => "view" ] + ); // execute query $exec = false; @@ -75,7 +94,12 @@ final public function query(string $query, array $option = []): int|bool|array|n } catch (\Exception) { $has_error = true; if ($exec === false && $catch_error === 0) - $this->show_exception(-10, $option['debug']); + $this->exception( + "QueryExec", + "" . mysqli_error($this->get_link()) . " +
$query
+
Statement: $query_type
" + ); } // init query info structure diff --git a/src/Orm/StoreResult.php b/src/Orm/StoreResult.php index 63db362..23666fb 100644 --- a/src/Orm/StoreResult.php +++ b/src/Orm/StoreResult.php @@ -3,10 +3,11 @@ namespace BrickLayer\Lay\Orm; +use BrickLayer\Lay\Core\CoreException; use Closure; use mysqli_result; -class StoreResult extends Exception +class StoreResult extends CoreException { /** * @param $exec mysqli_result diff --git a/src/Orm/Traits/Clean.php b/src/Orm/Traits/Clean.php index 1d5e603..ee9ff6c 100644 --- a/src/Orm/Traits/Clean.php +++ b/src/Orm/Traits/Clean.php @@ -2,6 +2,7 @@ declare(strict_types=1); namespace BrickLayer\Lay\Orm\Traits; +use BrickLayer\Lay\Core\Exception; use BrickLayer\Lay\Orm\SQL; trait Clean { @@ -176,6 +177,6 @@ private function exceptions(int $level, array $args = []) : void { } - $this->use_exception($title,$body,raw: $option); + Exception::new()->use_exception($title,$body,raw: $option); } } diff --git a/src/Orm/Traits/Controller.php b/src/Orm/Traits/Controller.php index 709a6d8..1d20db6 100644 --- a/src/Orm/Traits/Controller.php +++ b/src/Orm/Traits/Controller.php @@ -2,10 +2,7 @@ declare(strict_types=1); namespace BrickLayer\Lay\Orm\Traits; -use BrickLayer\Lay\Core\Traits\IsSingleton; - trait Controller{ - use IsSingleton; use Clean; use SelectorOOP; } From c284ccb3345e379435566854700fd57d98b58b73 Mon Sep 17 00:00:00 2001 From: Osahenrumwen Aigbogun Date: Mon, 18 Dec 2023 22:06:07 +0100 Subject: [PATCH 10/10] Fixed unneccessary bug in Make Cmd --- src/BobDBuilder/Cmd/Make.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BobDBuilder/Cmd/Make.php b/src/BobDBuilder/Cmd/Make.php index 130357c..6b8a3d9 100644 --- a/src/BobDBuilder/Cmd/Make.php +++ b/src/BobDBuilder/Cmd/Make.php @@ -2,8 +2,8 @@ namespace BrickLayer\Lay\BobDBuilder\Cmd; -use BrickLayer\Lay\BobDBuilder\Cmd\MakeTraits\Brick; -use BrickLayer\Lay\BobDBuilder\Cmd\MakeTraits\Domain; +use BrickLayer\Lay\BobDBuilder\Cmd\Traits\Make\Brick; +use BrickLayer\Lay\BobDBuilder\Cmd\Traits\Make\Domain; use BrickLayer\Lay\BobDBuilder\EnginePlug; use BrickLayer\Lay\BobDBuilder\Interface\CmdLayout; use BrickLayer\Lay\Core\Traits\IsSingleton;