From c2d2ad9177da361a683a4dc710a46c16828e3614 Mon Sep 17 00:00:00 2001 From: User Date: Fri, 12 Apr 2024 03:18:04 +0300 Subject: [PATCH] 20240412#1 --- composer.json | 4 +- config/container/services.php | 2 +- config/factories/templateFactory.php | 2 +- config/nodes.php | 5 +- config/routes/main.yaml | 12 --- config/routes/main/09-main.yaml | 2 +- public/index.php | 4 +- src/Common/Controllers/AbstractController.php | 54 ++++++------ .../Controllers/AbstractPageController.php | 35 ++++++++ src/Common/Domain/AbstractObject.php | 82 +++++++++++++++++++ .../Repository/AbstractMysqlRepository.php | 35 ++++++++ src/Common/Services/AbstractDTO.php | 81 ++++++++++++++++++ src/Common/Services/AbstractService.php | 2 +- src/Common/Services/DTOException.php | 16 ++++ src/Main/Controllers/IndexController.php | 6 +- .../Domain => Main/Domain/Entity}/.gitkeep | 0 .../ValueObject}/.gitkeep | 0 src/Main/{Domain/DTO => Repository}/.gitkeep | 0 .../{Repository/DTO => Services}/.gitkeep | 0 src/Main/Services/DTO/.gitkeep | 0 20 files changed, 292 insertions(+), 50 deletions(-) delete mode 100644 config/routes/main.yaml create mode 100644 src/Common/Controllers/AbstractPageController.php create mode 100644 src/Common/Domain/AbstractObject.php create mode 100644 src/Common/Repository/AbstractMysqlRepository.php create mode 100644 src/Common/Services/AbstractDTO.php create mode 100644 src/Common/Services/DTOException.php rename src/{Common/Domain => Main/Domain/Entity}/.gitkeep (100%) rename src/Main/{Components => Domain/ValueObject}/.gitkeep (100%) rename src/Main/{Domain/DTO => Repository}/.gitkeep (100%) rename src/Main/{Repository/DTO => Services}/.gitkeep (100%) delete mode 100644 src/Main/Services/DTO/.gitkeep diff --git a/composer.json b/composer.json index 6a0545f..ecca903 100644 --- a/composer.json +++ b/composer.json @@ -14,8 +14,8 @@ "symfony/dotenv": "^6.2", "rmphp/kernel": "^3.0", "rmphp/router": "^1.0", - "rmphp/content": "^2.0", - "rmphp/storage": "^2.0", + "rmphp/content": "^3.0", + "rmphp/storage": "^3.0", "rmphp/session": "^1.0", "rmphp/cache-file": "^1.0" }, diff --git a/config/container/services.php b/config/container/services.php index 06437a9..1dc2fdb 100644 --- a/config/container/services.php +++ b/config/container/services.php @@ -11,5 +11,5 @@ return [ MysqlStorageInterface::class => DI\create(MysqlStorage::class)->constructor(json_decode(getenv("MYSQL_PARAM"), true)), SessionInterface::class => DI\create(Session::class)->constructor(), CacheInterface::class => DI\create(Cache::class)->constructor("../var/cache"), - 'App\*\Domain\Repository\*RepositoryInterface' => DI\autowire('App\*\Repository\Mysql\*Repository'), + 'App\*\Domain\Repository\*Repository\*RepositoryInterface' => DI\autowire('App\*\Repository\Mysql\*Repository'), ]; \ No newline at end of file diff --git a/config/factories/templateFactory.php b/config/factories/templateFactory.php index 79be0ff..d025a55 100644 --- a/config/factories/templateFactory.php +++ b/config/factories/templateFactory.php @@ -1,2 +1,2 @@ setSubtemplePath('templates'); \ No newline at end of file +return (new \Rmphp\Content\Content('/templates/base.tpl'))->setSubtemplatePath('/templates'); \ No newline at end of file diff --git a/config/nodes.php b/config/nodes.php index 696fdf0..7435b01 100644 --- a/config/nodes.php +++ b/config/nodes.php @@ -2,15 +2,14 @@ /** * Правила для точек монтирования модулей - * Каждый массив определяет порядок срабатывания, часть url с которого */ # Example: # ['key'=>'/', "action"=>"App\\Main\\Controllers\\IndexController", "method"=>"index"], # ['key'=>'/', 'router'=>'config/routes/main/routes.php'], -# ['key'=>'/', 'router'=>'config/routes/main.yaml'], +# ['key'=>'/', 'router'=>[]], return [ - ['key'=>'/', 'router'=>'config/routes/main.yaml'], + ['key'=>'/', 'router'=>'config/routes/main/routes.php'], ]; \ No newline at end of file diff --git a/config/routes/main.yaml b/config/routes/main.yaml deleted file mode 100644 index b1f8e52..0000000 --- a/config/routes/main.yaml +++ /dev/null @@ -1,12 +0,0 @@ -- key: "/" - routes: - - action: "App\\Main\\Controllers\\IndexController" - method: "index" - params: "" - -# Empty -- key: "[any]" - routes: - - action: "App\\Main\\Controllers\\IndexController" - method: "emptyAction" - params: "" \ No newline at end of file diff --git a/config/routes/main/09-main.yaml b/config/routes/main/09-main.yaml index 79ba360..52bd3ee 100644 --- a/config/routes/main/09-main.yaml +++ b/config/routes/main/09-main.yaml @@ -6,7 +6,7 @@ params: "" # Empty -- key: "[any]" +- key: "<@any>" routes: - action: "App\\Main\\Controllers\\IndexController" method: "emptyAction" diff --git a/public/index.php b/public/index.php index 427eb1d..44034a6 100644 --- a/public/index.php +++ b/public/index.php @@ -12,7 +12,7 @@ require_once dirname(__DIR__).'/vendor/autoload.php'; (new Symfony\Component\Dotenv\Dotenv())->usePutenv()->loadEnv(dirname(__DIR__).'/.env'); error_reporting(0); ini_set('display_errors','Off'); -if(getenv("APP_MODE") == 'DEV'){ +if(getenv("APP_MODE") == 'ERR'){ error_reporting(E_ALL); ini_set('display_errors','On'); } @@ -23,7 +23,7 @@ $response = $app->handler($request, (new Response())->withHeader("Content-Type", (new ResponseEmitter())->emit($response); -if(getenv("APP_MODE") == 'DEV' && in_array("Dev", $response->getHeader("App-Mode"))){ +if(in_array("Dev", $response->getHeader("App-Mode"))){ $app->syslogger()->dump("Response", $response); addShutdownInfo($app->syslogger()->getLogs()); } \ No newline at end of file diff --git a/src/Common/Controllers/AbstractController.php b/src/Common/Controllers/AbstractController.php index ca6d9f1..21e6499 100644 --- a/src/Common/Controllers/AbstractController.php +++ b/src/Common/Controllers/AbstractController.php @@ -7,7 +7,6 @@ use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\Response\RedirectResponse; use Laminas\Diactoros\Response\TextResponse; use Psr\Http\Message\ResponseInterface; -use Rmphp\Foundation\Exceptions\AppException; use Rmphp\Kernel\Main; use Throwable; @@ -81,11 +80,24 @@ abstract class AbstractController extends Main { } /** + * @param string $point + * @param string $subtemplate + * @param array $data * @param int $status * @param array $headers * @return ResponseInterface */ - public function renderResponse(int $status = 200, array $headers = []) : ResponseInterface { + public function renderResponse(string $point, string $subtemplate, array $data = [], int $status = 200, array $headers = []) : ResponseInterface { + $this->template()->setSubtemplate($point, $this->getTemplatePath($subtemplate), $data); + return new HtmlResponse($this->template()->getResponse(), $status, array_merge($this->globals()->response()->getHeaders(), $headers)); + } + + /** + * @param int $status + * @param array $headers + * @return ResponseInterface + */ + public function render(int $status = 200, array $headers = []) : ResponseInterface { return new HtmlResponse($this->template()->getResponse(), $status, array_merge($this->globals()->response()->getHeaders(), $headers)); } @@ -94,7 +106,7 @@ abstract class AbstractController extends Main { * @param string $string * @return void */ - public function setTemplateValue(string $point, string $string) : void { + public function templSetValue(string $point, string $string) : void { $this->template()->setValue($point, $string); } @@ -103,41 +115,35 @@ abstract class AbstractController extends Main { * @param string $string * @return void */ - public function addTemplateValue(string $point, string $string) : void { + public function templAddValue(string $point, string $string) : void { $this->template()->addValue($point, $string); } /** * @param string $point - * @param string $subTempl + * @param string $subtemplate * @param array $resource * @return void */ - public function setSubtemplate(string $point, string $subTempl, array $resource = []) : void { - $this->template()->setSubtemple($point, $subTempl, $resource); - } - - /** - * @param string $point - * @param string $subTempl - * @param array $resource - * @return void - */ - public function addSubtemplate(string $point, string $subTempl, array $resource = []) : void { - $this->template()->addSubtemple($point, $subTempl, $resource); + public function templSetSubtemplate(string $point, string $subtemplate, array $resource = []) : void { + $this->template()->setSubtemplate($point, $this->getTemplatePath($subtemplate), $resource); } /** * @param string $point * @param string $subtemplate - * @param array $data - * @param int $status - * @param array $headers - * @return ResponseInterface + * @param array $resource + * @return void */ - public function render(string $point, string $subtemplate, array $data = [], int $status = 200, array $headers = []) : ResponseInterface { - $this->template()->setSubtemple($point, $subtemplate, $data); - return new HtmlResponse($this->template()->getResponse(), $status, array_merge($this->globals()->response()->getHeaders(), $headers)); + public function templAddSubtemplate(string $point, string $subtemplate, array $resource = []) : void { + $this->template()->addSubtemplate($point, $this->getTemplatePath($subtemplate), $resource); } + /** + * @param string $path + * @return string + */ + public function getTemplatePath(string $path) : string { + return $path; + } } \ No newline at end of file diff --git a/src/Common/Controllers/AbstractPageController.php b/src/Common/Controllers/AbstractPageController.php new file mode 100644 index 0000000..4cdd662 --- /dev/null +++ b/src/Common/Controllers/AbstractPageController.php @@ -0,0 +1,35 @@ +logException($exception, $data); + $this->syslogger()->warning($exception->getMessage()." on ".$exception->getFile().":".$exception->getLine(), $data); + $this->template()->setSubtemplate("main", "/templates/error/errpage.tpl", [ + "errorText" => "Error: ".$exception->getMessage()." (".$exception->getCode().")"."" + ]); + } + + /** + * @param Throwable $e + * @return string + */ + public function checkError(Throwable $e) : string { + if($e instanceof DTOException || $e instanceof ServiceException || $e instanceof RepositoryException) return $e->getMessage(); + ($e instanceof Exception) ? $this->logException($e) : $this->logError($e); + return "Ошибка. Дата и время: ".date("d-m-Y H:i:s"); + } +} \ No newline at end of file diff --git a/src/Common/Domain/AbstractObject.php b/src/Common/Domain/AbstractObject.php new file mode 100644 index 0000000..726f75f --- /dev/null +++ b/src/Common/Domain/AbstractObject.php @@ -0,0 +1,82 @@ +setProperties($data); + return $self; + } + + /** + * @param array $data + * @return $this + */ + public function setProperties(array $data) : self { + $propArray = array_keys(get_class_vars(get_class($this))); + foreach ($propArray as $propName) + { + $propNameSnakeCase = strtolower(preg_replace("'([A-Z])'", "_$1", $propName)); + + // если в переданном массиве ключ и свойство совпадают optionId = optionId + if(isset($data[$propName])) { + $this->{$propName} = (method_exists($this, 'set'.ucfirst($propName))) ? $this->{'set'.ucfirst($propName)}($data[$propName]) : $data[$propName]; + } + // если свойство в снэйккесе совподает с ключем в массиве option_id = optionId + elseif(isset($data[$propNameSnakeCase])) { + $this->{$propName} = (method_exists($this, 'set'.ucfirst($propName))) ? $this->{'set'.ucfirst($propName)}($data[$propNameSnakeCase]) : $data[$propNameSnakeCase]; + } + } + return $this; + } + + /** + * @param callable|null $method + * @return array + */ + public function getProperties(callable $method = null) : array { + $objectData = get_object_vars($this); + foreach ($objectData as $fieldName => $value) + { + $fieldNameSnakeCase = strtolower(preg_replace("'([A-Z])'", "_$1", $fieldName)); + + // если есть внутренний метод + if(method_exists($this, 'get'.ucfirst($fieldName))) { + $out[$fieldNameSnakeCase] = $this->{'get'.ucfirst($fieldName)}($value); + } + // если есть callable функция + elseif(isset($method) && !is_array($value)) { + $out[$fieldNameSnakeCase] = $method($value); + } + // если это логическое значение + elseif(is_bool($value)){ + $out[$fieldNameSnakeCase] = (int) $value; + } + // если это дробное число + elseif(is_float($value)) { + $out[$fieldNameSnakeCase] = $value; + } + // если это целое число + elseif(is_int($value)) { + $out[$fieldNameSnakeCase] = $value; + } + // если это строка + elseif(is_string($value)) { + $out[$fieldNameSnakeCase] = $value; + } + + } + return $out ?? []; + } + +} \ No newline at end of file diff --git a/src/Common/Repository/AbstractMysqlRepository.php b/src/Common/Repository/AbstractMysqlRepository.php new file mode 100644 index 0000000..cff7df7 --- /dev/null +++ b/src/Common/Repository/AbstractMysqlRepository.php @@ -0,0 +1,35 @@ +getProperties(function ($value){ + return (is_string($value)) ? $this->mysql->escapeStr($value) : $value; + }); + try { + if (!empty($object->id) && !empty($this->mysql->findById($table, $object->id))) { + $this->mysql->updateById($table, $in, $object->id); + } else { + $this->mysql->insert($table, $in); + $object->id = $this->mysql->mysql()->insert_id; + } + } catch (\Throwable $throwable) {throw new RepositoryException($throwable->getMessage());} + return $object; + } + + + + +} \ No newline at end of file diff --git a/src/Common/Services/AbstractDTO.php b/src/Common/Services/AbstractDTO.php new file mode 100644 index 0000000..ebed9f8 --- /dev/null +++ b/src/Common/Services/AbstractDTO.php @@ -0,0 +1,81 @@ +{"requireAssert".ucfirst($propName)}($data[$propName]); + } + elseif(isset($data[$propNameSnakeCase])) { + $self->{"requireAssert".ucfirst($propName)}($data[$propNameSnakeCase]); + } + else{ + throw new DTOException("Отсутствует обязательное значение"); + } + } + } + foreach($data as $key => $item){ + try { + $camelCaseKey = str_replace('_', '', ucwords($key, "_")); + if(method_exists($self, "assert".$camelCaseKey)) { + $self->{'assert'.$camelCaseKey}($item); + } elseif(in_array(lcfirst($camelCaseKey), $propArray)) { + $self->{lcfirst($camelCaseKey)} = $item; + } + } + catch (\Error $error) { + $errorKey[$key] = $error->getMessage(); + } + if(!empty($errorKey)) throw new Exception(json_encode(["data"=>$data, "error"=>$errorKey])); + } + return $self; + } + + /** + * @param $value + * @return bool + */ + public function validateInt($value) : bool { + return (is_numeric($value)); + } + + /** + * @param $value + * @return bool + */ + public function validateFloat($value) : bool { + return (is_float((float) $value)); + } + + /** + * @param $value + * @return bool + */ + public function validateBoolean($value) : bool { + return (is_bool($value)); + } + + /** + * @param $value + * @return bool + */ + public function validateEmail($value) : bool { + return (filter_var($value, FILTER_VALIDATE_EMAIL)); + } +} \ No newline at end of file diff --git a/src/Common/Services/AbstractService.php b/src/Common/Services/AbstractService.php index f9ebcd9..aec0375 100644 --- a/src/Common/Services/AbstractService.php +++ b/src/Common/Services/AbstractService.php @@ -4,7 +4,7 @@ namespace App\Common\Services; use Rmphp\Kernel\Main; -class AbstractService extends Main { +abstract class AbstractService extends Main { } \ No newline at end of file diff --git a/src/Common/Services/DTOException.php b/src/Common/Services/DTOException.php new file mode 100644 index 0000000..24eb77b --- /dev/null +++ b/src/Common/Services/DTOException.php @@ -0,0 +1,16 @@ +data = $data; + } +} \ No newline at end of file diff --git a/src/Main/Controllers/IndexController.php b/src/Main/Controllers/IndexController.php index 4d4b2cc..e6b387c 100644 --- a/src/Main/Controllers/IndexController.php +++ b/src/Main/Controllers/IndexController.php @@ -13,12 +13,12 @@ class IndexController extends AbstractController { */ public function index() : bool|ResponseInterface { try { - $this->addHeader("App-Mode", "Dev"); + //$this->addHeader("App-Mode", "Dev"); $this->template()->setValue("title", "Главная"); - $this->template()->setSubtemple("main", "main/index.tpl", [ + $this->template()->setSubtemplate("main", "/main/index.tpl", [ "date" => (new \DateTime())->format('Y-m-d H:i:s') ]); - return $this->renderResponse(); + return $this->render(); } catch(ServiceException $exception){} return true; diff --git a/src/Common/Domain/.gitkeep b/src/Main/Domain/Entity/.gitkeep similarity index 100% rename from src/Common/Domain/.gitkeep rename to src/Main/Domain/Entity/.gitkeep diff --git a/src/Main/Components/.gitkeep b/src/Main/Domain/ValueObject/.gitkeep similarity index 100% rename from src/Main/Components/.gitkeep rename to src/Main/Domain/ValueObject/.gitkeep diff --git a/src/Main/Domain/DTO/.gitkeep b/src/Main/Repository/.gitkeep similarity index 100% rename from src/Main/Domain/DTO/.gitkeep rename to src/Main/Repository/.gitkeep diff --git a/src/Main/Repository/DTO/.gitkeep b/src/Main/Services/.gitkeep similarity index 100% rename from src/Main/Repository/DTO/.gitkeep rename to src/Main/Services/.gitkeep diff --git a/src/Main/Services/DTO/.gitkeep b/src/Main/Services/DTO/.gitkeep deleted file mode 100644 index e69de29..0000000