This commit is contained in:
User
2023-05-29 03:04:33 +03:00
commit 67221e0d93
41 changed files with 516 additions and 0 deletions

31
.env.dist Normal file
View File

@@ -0,0 +1,31 @@
# In all environments, the following files are loaded if they exist,
# the latter taking precedence over the former:
#
# * .env contains default values for the environment variables needed by the app
# * .env.local uncommitted file with local overrides
# * .env.$APP_ENV committed environment-specific defaults
# * .env.$APP_ENV.local uncommitted environment-specific overrides
#
# Real environment variables win over .env files.
# App mode (DEV, TEST, PROD)
APP_MODE=DEV
# Including file with array of componens
APP_COMPONENTS_FILE="config/components.php"
# Including file with array of app nodes
APP_NODES_FILE="config/appnodes.php"
# Define app nodes
#APP_NODE1='{"key":"/","action":"App\\Auth\\Controllers\\UserController","method":"index"}'
#APP_NODE2='{"key":"/","router":"config/routes/main/collection.php"}'
# Default page
PAGE404="public/web/404.html"
PAGE501="public/web/501.html"
# Users environment
CONTAINER_DIR="config/container"
MYSQL_PARAM='{"host":"host.docker.internal", "user":"***user***", "pass":"***password***","base":"***basename***", "logsEnable":true}'

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
.idea/
/vendor
/var
composer.lock
.env
.env.local

2
README.md Normal file
View File

@@ -0,0 +1,2 @@
## Rmphp/Skeleton

35
composer.json Normal file
View File

@@ -0,0 +1,35 @@
{
"name": "rmphp/skeleton",
"type": "project",
"license": "proprietary",
"minimum-stability": "dev",
"prefer-stable" : true,
"require": {
"php": "^8.1",
"ext-json": "*",
"ext-yaml": "*",
"laminas/laminas-diactoros": "^2.5",
"monolog/monolog": "^2.3",
"php-di/php-di": "^6.3",
"symfony/dotenv": "^6.2",
"rmphp/kernel": "1.0.x-dev",
"rmphp/router": "1.0.x-dev",
"rmphp/content": "1.0.x-dev",
"rmphp/storage": "1.0.x-dev"
},
"autoload": {
"psr-4": {
"App\\": "src"
}
},
"scripts": {
"start": "php -S localhost:8080 -t public"
},
"config": {
"sort-packages": true,
"process-timeout":0
},
"require-dev": {
}
}

17
config/appnodes.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
/**
* Правила для точек монтирования модулей
* Каждый массив определяет порядок срабатывания, часть url с которого
*/
# Example:
# ['key'=>'/', "action"=>"App\\Main\\Controllers\\IndexController", "method"=>"index"],
# ['key'=>'/', 'router'=>'config/routes/main/collection.php'],
# ['key'=>'/', 'router'=>'config/routes/main.json']
# ['key'=>'/', 'router'=>'config/routes/main.yaml'],
return [
['key'=>'/', 'router'=>'config/routes/main.yaml'],
];

21
config/components.php Normal file
View File

@@ -0,0 +1,21 @@
<?php
return [
/**
* Путь к файлу фабрики возвращающий реализацию RouterInterface или сам экземпляр класса
*/
\Rmphp\Foundation\RouterInterface::class => 'config/factories/routerFactory.php',
/**
* Путь к файлу фабрики возвращающий реализацию TemplateInterface или сам экземпляр класса
*/
\Rmphp\Foundation\TemplateInterface::class => 'config/factories/templateFactory.php',
/**
* Путь к файлу фабрики возвращающий реализацию PSR-3 LoggerInterface или сам экземпляр класса
*/
\Psr\Log\LoggerInterface::class => 'config/factories/loggerFactory.php',
/**
* Путь к файлу фабрики возвращающий реализацию PSR-11 ContainerInterface или сам экземпляр класса
*/
\Psr\Container\ContainerInterface::class => 'config/factories/containerFactory.php',
];

View File

@@ -0,0 +1,11 @@
<?php
use Rmphp\Storage\MysqlStorage;
use Rmphp\Storage\MysqlStorageInterface;
return [
MysqlStorageInterface::class => DI\create(MysqlStorage::class)->constructor(json_decode(getenv("MYSQL_PARAM"), true)),
'App\*\Domain\Repository\*RepositoryInterface' => DI\autowire('App\*\Repository\Mysql\*Repository'),
'App\*\Services\*\*Service' => DI\autowire('App\*\Services\*\*Service'),
'App\*\Services\*Service' => DI\autowire('App\*\Services\*Service'),
];

View File

@@ -0,0 +1,5 @@
<?php
return [
//"container key"=>value
];

View File

@@ -0,0 +1,18 @@
<?php
use DI\ContainerBuilder;
$containerDir = (getenv("CONTAINER_DIR"))?:"config/container/";
$dependencies = glob(dirname(__DIR__,2)."/".$containerDir."/*.php");
$dependenciesCollection = array_map(function ($dependenciesFile){
return require $dependenciesFile;
}, $dependencies);
try {
$builder = new ContainerBuilder();
$builder->enableCompilation(__DIR__ . '/../../var/cache/container');
$builder->addDefinitions(array_replace_recursive(...$dependenciesCollection));
return $builder->build();
} catch (Exception $e) {echo $e->getMessage();}

View File

@@ -0,0 +1,2 @@
<?php
return (new \Monolog\Logger('system'))->pushHandler(new \Monolog\Handler\StreamHandler(__DIR__.'/../../var/logs/log'.date('Ymd').'.log'));

View File

@@ -0,0 +1,2 @@
<?php
return new \Rmphp\Router\Router();

View File

@@ -0,0 +1,2 @@
<?php
return (new \Rmphp\Content\Content('public/web/main/sheet.html'))->setSubtemplePath('templates');

14
config/routes/main.json Normal file
View File

@@ -0,0 +1,14 @@
[
{
"key": "/",
"routes": [
{"action": "App\\Main\\Controllers\\IndexController", "method": "index", "params": ""}
]
},
{
"key": "[any]",
"routes": [
{"action": "App\\Main\\Controllers\\IndexController", "method": "emptyAction", "params": ""}
]
}
]

12
config/routes/main.yaml Normal file
View File

@@ -0,0 +1,12 @@
- key: "/"
routes:
- action: "App\\Main\\Controllers\\IndexController"
method: "index"
params: ""
# Empty
- key: "[any]"
routes:
- action: "App\\Main\\Controllers\\IndexController"
method: "emptyAction"
params: ""

View File

@@ -0,0 +1,13 @@
# Index
- key: "/"
routes:
- action: "App\\Main\\Controllers\\IndexController"
method: "index"
params: ""
# Empty
- key: "[any]"
routes:
- action: "App\\Main\\Controllers\\IndexController"
method: "emptyAction"
params: ""

View File

@@ -0,0 +1,9 @@
<?php
$routes = glob(__DIR__."/{*.yaml}", GLOB_BRACE);
$routesCollection = array_map(function ($routesFile){
return file_get_contents($routesFile).PHP_EOL;
}, $routes);
return yaml_parse(implode($routesCollection));

40
public/index.php Normal file
View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types = 1);
use Laminas\Diactoros\Response;
use Laminas\Diactoros\ServerRequestFactory;
use Rmphp\Kernel\App;
use Rmphp\Kernel\ResponseEmitter;
use Rmphp\Kernel\Utils;
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'){
error_reporting(E_ALL); ini_set('display_errors','On');
}
$request = ServerRequestFactory::fromGlobals();
$app = new App();
$response = $app->handler($request, (new Response())->withHeader("Content-Type", "text/html; charset=utf-8"));
(new ResponseEmitter())->emit($response);
if(getenv("APP_MODE") == 'DEV' && in_array("Dev", $response->getHeader("App-Mode"))){
$app->syslogger()->dump("request", $request);
$app->syslogger()->dump("response", $response);
$app->syslogger()->dump("globals", [
"ENV"=>$_ENV,
"GET"=>$request->getQueryParams(),
"POST"=>$request->getParsedBody(),
"COOKIE"=>$request->getCookieParams(),
"SESSION"=>$_SESSION ?? [],
"SERVER"=>$request->getServerParams()
]);
$app->syslogger()->dump("kernel", $app);
Utils::addShutdownInfo($app->syslogger()->getLogs());
}

10
public/web/404.html Normal file
View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>404</title>
</head>
<body>
<h1>Error 404</h1>
</body>
</html>

10
public/web/500.html Normal file
View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>500</title>
</head>
<body>
<h1>Error 500</h1>
</body>
</html>

View File

@@ -0,0 +1,18 @@
body{font-family: Arimo, sans-serif; font-size: 15px; margin: 0; padding: 0;}
* {
scrollbar-width: thin;
scrollbar-color: #CCC #FFF
}
*::-webkit-scrollbar {
width: 10px;
}
*::-webkit-scrollbar-track {
background: #FFF;
}
*::-webkit-scrollbar-thumb {
background-color: #AAA;
border-radius: 20px;
border: 3px solid #FFF;
}
h1{padding: 0 30px}

View File

View File

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Rmphp - <?=$this->getPoint('title')?></title>
<link href="/web/main/css/style.css?1" rel="stylesheet">
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<?=$this->getPoint('main')?>
<script type="text/javascript" src="/web/main/js/script.js?1"></script>
<?=$this->getPoint('jsscript')?>
</body>
</html>

View File

View File

View File

@@ -0,0 +1,94 @@
<?php
namespace App\Common\Controllers;
use Laminas\Diactoros\Response\HtmlResponse;
use Laminas\Diactoros\Response\JsonResponse;
use Laminas\Diactoros\Response\RedirectResponse;
use Laminas\Diactoros\Response\TextResponse;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Http\Message\ResponseInterface;
use Rmphp\Kernel\Main;
abstract class AbstractController extends Main {
/**
* @param string $name
* @return mixed|void
*/
public function containerGet(string $name) {
try {
return $this->container()->get($name);
}
catch (NotFoundExceptionInterface $notFoundException){
$this->syslogger()->error($notFoundException->getMessage());
}
catch (ContainerExceptionInterface $containerException){
$this->syslogger()->error($containerException->getMessage());
}
}
/**
* @param \Throwable $throwable
* @param array $data
* @return void
*/
public function logException(\Throwable $throwable, array $data = []) : void {
$this->logger()->warning($throwable->getMessage()." on ".$throwable->getFile().":".$throwable->getLine(), $data);
}
/**
* @param string $name
* @param string $value
* @return void
*/
public function addHeader(string $name, string $value) : void {
$this->globals()->addHeader($name, $value);
}
/**
* @param $html
* @param int $status
* @param array $headers
* @return ResponseInterface
*/
public function htmlResponse($html, int $status = 200, array $headers = []) : ResponseInterface {
return new HtmlResponse($html, $status, array_merge($this->globals()->response()->getHeaders(), $headers));
}
/**
* @param $text
* @param int $status
* @param array $headers
* @return ResponseInterface
*/
public function textResponse($text, int $status = 200, array $headers = []) : ResponseInterface {
$this->container()->set("showDebugLogs", false);
return new TextResponse($text, $status, array_merge($this->globals()->response()->getHeaders(), $headers));
}
/**
* @param array $array
* @param int $status
* @param array $headers
* @return ResponseInterface
*/
public function jsonResponse(array $array, int $status = 200, array $headers = []) : ResponseInterface {
$this->container()->set("showDebugLogs", false);
return new JsonResponse($array, $status, array_merge($this->globals()->response()->getHeaders(), $headers), JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
}
/**
* @param string $url
* @param int $status
* @param array $headers
* @return ResponseInterface
*/
public function redirectResponse(string $url, int $status = 302, array $headers = []) : ResponseInterface {
$this->container()->set("showDebugLogs", false);
return new RedirectResponse($url, $status, array_merge($this->globals()->response()->getHeaders(), $headers));
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace App\Common\Controllers;
use Psr\Http\Message\ResponseInterface;
abstract class AbstractPageController extends AbstractController {
/**
* @param string $point
* @param string $string
*/
public function templateAddValue(string $point, string $string) : void {
$this->template()->addValue($point, $string);
}
/**
* @param string $point
* @param string $subTempl
* @param array $resource
*/
public function templateSetSubtemple(string $point, string $subTempl, array $resource = []) : void {
$this->template()->setSubtemple($point, $subTempl, $resource);
}
/**
* @param \Exception $exception
* @param array $data
* @return void
*/
public function exceptionPage(\Exception $exception, array $data = []) : void {
$this->logException($exception, $data);
$this->syslogger()->warning($exception->getMessage()." on ".$exception->getFile().":".$exception->getLine(), $data);
$this->templateSetSubtemple("main", "/main/errpage.tpl", [
"errorText" => "<span style='color:red'>Error: ".$exception->getMessage()." (".$exception->getCode().")"."</span>"
]);
}
}

View File

@@ -0,0 +1,7 @@
<?php
namespace App\Common\Controllers;
class NotFoundException extends \Exception {
}

View File

View File

@@ -0,0 +1,15 @@
<?php
namespace App\Common\Repository;
use Throwable;
class RepositoryException extends \Exception {
public array $data;
public function __construct($message="", $code=0, array $data = [], Throwable $previous=null) {
parent::__construct($message, $code, $previous);
$this->data = $data;
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace App\Common\Services;
use Rmphp\Kernel\Main;
class AbstractService extends Main {
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Common\Services;
use Throwable;
class ServiceException extends \Exception {
public array $data;
public function __construct($message="", $code=0, array $data = [], Throwable $previous=null) {
parent::__construct($message, $code, $previous);
$this->data = $data;
}
}

View File

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Main\Controllers;
use App\Common\Controllers\AbstractPageController;
use App\Common\Services\ServiceException;
use Psr\Http\Message\ResponseInterface;
class IndexController extends AbstractPageController {
/**
* @return bool|ResponseInterface
*/
public function index() : bool|ResponseInterface {
try {
$this->addHeader("App-Mode", "Dev");
$this->template()->setValue("title", "Главная");
$this->template()->setSubtemple("main", "main/index.tpl", [
]);
}
catch(ServiceException $exception){}
return true;
}
}

0
src/Main/Domain/.gitkeep Normal file
View File

View File

View File

View File

View File

View File

@@ -0,0 +1,9 @@
<main>
<div class="main-section">
<div class="errBlock">
<div class="center">
<?=(!empty($this->data->errorText))?$this->data->errorText:""?>
</div>
</div>
</div>
</main>

5
templates/main/index.tpl Normal file
View File

@@ -0,0 +1,5 @@
<article>
<main>
<h1>Hellow</h1>
</main>
</article>