Compare commits
42 Commits
Author | SHA1 | Date |
---|---|---|
Dave Mc Nicoll | cebb213830 | |
Dave M. | 8e29b0513a | |
Dave M. | 7f549a377a | |
Dave M. | f87bccb3ab | |
Dave M. | 212dbd17c0 | |
Dave M. | f462fcc597 | |
Dave M. | 13d306aec9 | |
Dave M. | 07613bf1cb | |
Dave Mc Nicoll | 4e28917b96 | |
Dave Mc Nicoll | 163df3f4ba | |
Dave M. | 3320dc47c1 | |
Dave M. | 4484dc8985 | |
Dave M. | 1d61ff87e4 | |
Dave Mc Nicoll | 0cc9a8a893 | |
Dave Mc Nicoll | fd8fa7695e | |
Dave M. | 0581f378a5 | |
Dave M. | 708af80fa2 | |
Dave M. | 1f828eb022 | |
Dave M. | 959a182d16 | |
Dave M. | ffe66e522c | |
Dave M. | 730ce7474e | |
Dave Mc Nicoll | 97dac9ddc4 | |
Dave Mc Nicoll | d9f9c053c3 | |
Dave Mc Nicoll | 63fde92b68 | |
Dave Mc Nicoll | 8190d3483b | |
Dave Mc Nicoll | 38b540bbd8 | |
Dave Mc Nicoll | f9c081ff26 | |
Dave M. | 34ca18f34c | |
Dave M. | 45ffc6e128 | |
Dave Mc Nicoll | a9db9cd846 | |
Dave Mc Nicoll | 2a18e0cb9a | |
Dave M. | ff4c94f820 | |
Dave M. | 30d0e8a14d | |
Dave M. | 6c58586823 | |
Dave M. | 9b795b857a | |
Dave M. | bc55a2ab89 | |
Dave M. | 5f0deef7f8 | |
Dave M. | e8c3cf01c9 | |
Dave M. | 06741d09c0 | |
Dave M. | 70e7b54c65 | |
Dave M. | 7b0a0cf333 | |
Dave M. | f3c4cbd95a |
|
@ -21,37 +21,18 @@
|
|||
"laminas/laminas-httphandlerrunner": "2.5.x-dev",
|
||||
"vlucas/phpdotenv": "^3.4@dev",
|
||||
"middlewares/whoops": "dev-master",
|
||||
"guzzlehttp/guzzle": "^7@dev",
|
||||
"swiftmailer/swiftmailer": "^6.2@dev",
|
||||
"mcnd/storage": "dev-master",
|
||||
"mcnd/lean-console": "dev-master",
|
||||
"mcnd/ulmus": "dev-master",
|
||||
"mcnd/picea": "dev-master",
|
||||
"mcnd/picea-ui": "dev-master",
|
||||
"mcnd/cronard": "dev-master",
|
||||
"mcnd/tell": "dev-master",
|
||||
"mcnd/dump": "dev-master",
|
||||
"mcnd/event": "dev-master",
|
||||
"mcnd/notes-breadcrumb": "dev-master",
|
||||
"mcnd/notes-cronard": "dev-master",
|
||||
"mcnd/notes-event": "dev-master",
|
||||
"mcnd/notes-tell": "dev-master",
|
||||
"mcnd/notes-route": "dev-master",
|
||||
"mcnd/notes-security": "dev-master",
|
||||
"mcnd/ulmus-user": "dev-master",
|
||||
"mcnd/thebugs": "dev-master",
|
||||
"mcnd/taxus": "dev-master",
|
||||
"mcnd/notes": "dev-master",
|
||||
"psr/simple-cache": "*"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/lean-console.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/cronard.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/event.git"
|
||||
|
@ -68,46 +49,10 @@
|
|||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/ulmus.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/ulmus-user.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/picea.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/picea-ui.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/notes.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/notes-route.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/notes-cronard.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/notes-security.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/notes-breadcrumb.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/notes-event.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/notes-tell.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/tell.git"
|
||||
|
@ -138,18 +83,14 @@
|
|||
"lean" : {
|
||||
"autoload": {
|
||||
"definitions" : [
|
||||
"meta/definitions/software.php",
|
||||
"meta/definitions/authorize.php",
|
||||
"meta/definitions/cli.php",
|
||||
"meta/definitions/cronard.php",
|
||||
"meta/definitions/email.php",
|
||||
"meta/definitions/event.php",
|
||||
"meta/definitions/http.php",
|
||||
"meta/definitions/orm.php",
|
||||
"meta/definitions/language.php",
|
||||
"meta/definitions/negundo.php",
|
||||
"meta/definitions/routes.php",
|
||||
"meta/definitions/software.php",
|
||||
"meta/definitions/storage.php",
|
||||
"meta/definitions/template.php"
|
||||
],
|
||||
"config": [
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'ulmus' => [
|
||||
'connections' => [
|
||||
'sqlite' => [
|
||||
'adapter' => 'SQLite',
|
||||
'path' => getenv('PROJECT_PATH') . DIRECTORY_SEPARATOR . "var/lean.sqlite3",
|
||||
'pragma_begin' => "journal_mode=WAL",
|
||||
'pragma_close' => "analysis_limit=500,optimize",
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
return [];
|
|
@ -29,8 +29,8 @@ return [
|
|||
return function(array $errorData) {
|
||||
return HttpFactory::createJsonResponse($errorData + [
|
||||
'api.error' => "Authorization failed",
|
||||
'api.datetime' => (new \DateTime)->format(\DateTime::ATOM),
|
||||
]);
|
||||
'api.datetime' => (new \DateTime)->format(\DateTime::ISO8601),
|
||||
], 403);
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -40,7 +40,7 @@ return [
|
|||
'title' => "Authentication failed",
|
||||
'subtitle' => "",
|
||||
'message' => $message,
|
||||
]));
|
||||
]), 401);
|
||||
};
|
||||
},
|
||||
];
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
use Mcnd\CLI\CliMiddleware;
|
||||
|
||||
use Notes\CLI\CommandFetcher;
|
||||
|
||||
use Lean\{ Factory, Lean };
|
||||
|
||||
return [
|
||||
CommandFetcher::class => function($c) {
|
||||
$fetcher = new CommandFetcher(null, null, $c->get('cli.caching'));
|
||||
|
||||
$fetcher->setFolderList(array_map(function($item) {
|
||||
return $item;
|
||||
}, $c->get(Lean::class)->getCli()));
|
||||
|
||||
return $fetcher;
|
||||
},
|
||||
|
||||
CliMiddleware::class => function($c) {
|
||||
return new CliMiddleware($c, $c->get('cli.response:default'), $c->get(CommandFetcher::class));
|
||||
},
|
||||
|
||||
'cli.response:default' => function($c) {
|
||||
return function() {
|
||||
return Factory\HttpFactory::createTextResponse("This is the default response from CLI middleware which indicates that no command were registered for this application.\n");
|
||||
};
|
||||
},
|
||||
];
|
|
@ -1,30 +0,0 @@
|
|||
<?php
|
||||
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
|
||||
use Cronard\CronardMiddleware,
|
||||
Notes\Cronard\TaskFetcher;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
use Lean\{ Factory, Lean };
|
||||
|
||||
return [
|
||||
CronardMiddleware::class => function($c) {
|
||||
$cronardMiddleware = new CronardMiddleware($c, getenv('CRON_KEY'), function() : ResponseInterface {
|
||||
return Factory\HttpFactory::createHtmlResponse(sprintf("%s - cron task begin...", date('Y-m-d H:i:s')));
|
||||
}, []);
|
||||
|
||||
return $cronardMiddleware->fromFile(getenv("META_PATH")."/crontab.php")->fromAnnotations($c->get(TaskFetcher::class));
|
||||
},
|
||||
|
||||
TaskFetcher::class => function($c) {
|
||||
$fetcher = new TaskFetcher(null, null, $c->get('cronard.caching'));
|
||||
|
||||
$fetcher->setFolderList(array_map(function($item) {
|
||||
return $item;
|
||||
}, $c->get(Lean::class)->getCronard()));
|
||||
|
||||
return $fetcher;
|
||||
},
|
||||
];
|
|
@ -24,12 +24,18 @@ return [
|
|||
},
|
||||
|
||||
Event\EventDefinition::class => function($c) {
|
||||
$extension = $c->has(\Picea\Extension\UrlExtension::class) ? $c->get(\Picea\Extension\UrlExtension::class) : null;
|
||||
|
||||
return new Event\EventDefinition([
|
||||
new class() implements RoutingCompileRoutes {
|
||||
new class($extension) implements RoutingCompileRoutes {
|
||||
public function __construct(
|
||||
protected ? \Picea\Extension\UrlExtension $extension,
|
||||
) {}
|
||||
|
||||
public function execute(Routing $routing, Route $attribute) : void
|
||||
{
|
||||
if (null !== ($name = $attribute->name ?? null)) {
|
||||
$routing->extension->registerRoute($name, $attribute->getRoute(), $attribute->class, $attribute->classMethod, $attribute->methods ?? (array)$attribute->method);
|
||||
$this->extension->registerRoute($name, $attribute->getRoute(), $attribute->class, $attribute->classMethod, (array) ( $attribute->method ?? $attribute->methods ));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -45,16 +51,20 @@ return [
|
|||
|
||||
# Checking if user needs to be logged
|
||||
if ( $container->has(SecurityHandler::class) ){
|
||||
if ( $redirect = $container->get(SecurityHandler::class)->verify($class, $method) ) {
|
||||
if ( empty($object->user) || ! $object->user->logged ) {
|
||||
$routing->session->set('redirectedFrom', (string) $request->getUri());
|
||||
$routing->response = $redirect;
|
||||
$securityHandler = $container->get(SecurityHandler::class);
|
||||
|
||||
if ( $redirect = $securityHandler->verify($class, $method) ) {
|
||||
if ( empty($object->user) || ! $object->user->logged ) {
|
||||
if ($container->has(Session::class)) {
|
||||
$container->get(Session::class)->set('redirectedFrom', (string)$request->getUri());
|
||||
}
|
||||
|
||||
$routing->response = $redirect;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $container->has(Taxus::class) ) {
|
||||
if ( $securityHandler->isLocked($class, $method) && $container->has(Taxus::class) && $container->has(SecurityHandler::class) ) {
|
||||
if ( $forbidden = $container->get(SecurityHandler::class)->taxus($class, $method, $object->user ?? null) ) {
|
||||
$routing->response = $forbidden;
|
||||
|
||||
|
|
|
@ -1,32 +1,37 @@
|
|||
<?php
|
||||
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
|
||||
use Tell\I18n;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Notes\Tell\LanguageHandler;
|
||||
|
||||
return [
|
||||
Tell\I18n::class => create( Tell\I18n::class ) ->constructor(
|
||||
get(Tell\Reader\JsonReader::class),
|
||||
get(Tell\Reader\PhpReader::class),
|
||||
get('tell.fallback') /* getenv("DEBUG") ? create(Tell\PrintMissingKey::class) : get('tell.fallback') */
|
||||
),
|
||||
use function DI\autowire, DI\create, DI\get, DI\add;
|
||||
|
||||
'tell.fallback' => function($c) {
|
||||
$i18n = new Tell\I18n( $c->get(Tell\Reader\JsonReader::class), $c->get(Tell\Reader\PhpReader::class), new Tell\PrintMissingKey() );
|
||||
return [
|
||||
I18n::class => function(ContainerInterface $container) {
|
||||
$i18n = new I18n($container->get(Tell\Reader\JsonReader::class), $container->get(Tell\Reader\PhpReader::class), $container->get('tell.fallback'));
|
||||
$i18n->locale(getenv('DEFAULT_LOCAL'));
|
||||
$i18n->initialize(! getenv("DEBUG"));
|
||||
|
||||
return $i18n;
|
||||
},
|
||||
|
||||
'tell.fallback' => function(ContainerInterface $container) {
|
||||
$i18n = new Tell\I18n( $container->get(Tell\Reader\JsonReader::class), $container->get(Tell\Reader\PhpReader::class), new Tell\PrintMissingKey() );
|
||||
$i18n->locale(getenv('DEFAULT_LOCAL_FALLBACK') ?: "en_US");
|
||||
$i18n->initialize(true);
|
||||
|
||||
return $i18n;
|
||||
},
|
||||
|
||||
# TODO -- accept folders from Lean Apps
|
||||
Tell\Reader\PhpReader::class => function($c) {
|
||||
return new Tell\Reader\PhpReader($c->get(Lean\Lean::class)->getI18n('php'), false);
|
||||
Tell\Reader\PhpReader::class => function(ContainerInterface $container) {
|
||||
return new Tell\Reader\PhpReader($container->get(Lean\Lean::class)->getI18n('php'), false);
|
||||
},
|
||||
|
||||
Tell\Reader\JsonReader::class => function($c) {
|
||||
return new Tell\Reader\JsonReader($c->get(Lean\Lean::class)->getI18n('json'), true, \JSON_PRETTY_PRINT);
|
||||
Tell\Reader\JsonReader::class => function(ContainerInterface $container) {
|
||||
return new Tell\Reader\JsonReader($container->get(Lean\Lean::class)->getI18n('json'), true, \JSON_PRETTY_PRINT);
|
||||
},
|
||||
|
||||
LanguageHandler::class => autowire(LanguageHandler::class),
|
||||
'lean.autoload' => add([
|
||||
I18n::class,
|
||||
]),
|
||||
];
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
<?php
|
||||
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
|
||||
use Negundo\Client\{ SoftwareConfig, Dump, Task, NegundoMiddleware };
|
||||
|
||||
return [
|
||||
SoftwareConfig::class => create(SoftwareConfig::class)->constructor(getenv('NEGUNDO_HASH'), getenv('NEGUNDO_SERVER')),
|
||||
NegundoMiddleware::class => autowire(NegundoMiddleware::class),
|
||||
Dump::class => autowire(Dump::class),
|
||||
Task::class => autowire(Task::class),
|
||||
];
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
use Ulmus\Container\AdapterProxy;
|
||||
use Ulmus\ConnectionAdapter;
|
||||
|
||||
use function DI\autowire, DI\create, DI\get, DI\add;
|
||||
|
||||
return [
|
||||
'lean.autoload' => add([
|
||||
AdapterProxy::class,
|
||||
]),
|
||||
|
||||
AdapterProxy::class => function (Psr\Container\ContainerInterface $c) {
|
||||
return new AdapterProxy(
|
||||
$c->get(ConnectionAdapter::class),
|
||||
);
|
||||
},
|
||||
];
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
use function DI\autowire, DI\create, DI\get, DI\add;
|
||||
|
||||
use League\Route\Strategy\ApplicationStrategy,
|
||||
League\Route\Router;
|
||||
|
@ -49,12 +49,12 @@ return [
|
|||
"dump", "errorHandler", SessionMiddleware::class, CronardMiddleware::class, Mcnd\Event\EventMiddleware::class, Mcnd\CLI\CliMiddleware::class,
|
||||
],
|
||||
|
||||
'app.middlewares' => [
|
||||
HeaderAuthenticationMiddleware::class,
|
||||
PostRequestAuthenticationMiddleware::class,
|
||||
],
|
||||
'app.middlewares' => add([
|
||||
# HeaderAuthenticationMiddleware::class,
|
||||
# PostRequestAuthenticationMiddleware::class,
|
||||
]),
|
||||
|
||||
'routes.list' => function($c) {
|
||||
Lean\Routing\RouteDefinitionInterface::class => function($c) {
|
||||
return function (ContainerInterface $container) {
|
||||
$router = $container->get(Router::class);
|
||||
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
|
||||
use Storage\Session;
|
||||
|
||||
use Taxus\{ Privilege, Taxus, PermissionGrantInterface, DefaultPermissionGrant };
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
return [
|
||||
Taxus::class => function ($c) {
|
||||
return ( new Taxus( $c->get(PermissionGrantInterface::class) ) )->add(
|
||||
[ new Privilege("dev", "Is a developper of this application."), "is_dev" ],
|
||||
[ new Privilege("admin", "Can manage mostly everything from this application."), "is_admin" ],
|
||||
[ new Privilege("user", "Is an authenticated user."), "is_user" ],
|
||||
[ new Privilege("anonymous", "Is an anonymous (unauthenticated) user."), "is_anonymous" ],
|
||||
);
|
||||
},
|
||||
|
||||
PermissionGrantInterface::class => create(DefaultPermissionGrant::class)->constructor(get(ServerRequestInterface::class), get(Session::class)),
|
||||
];
|
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
|
||||
use Taxus\Privilege;
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
use Tell\I18n;
|
||||
|
||||
use TheBugs\JavascriptMiddleware;
|
||||
|
||||
|
@ -11,12 +10,14 @@ use Storage\Cookie,
|
|||
Storage\Session,
|
||||
Storage\SessionMiddleware;
|
||||
|
||||
use function DI\autowire, DI\create, DI\get, DI\add;
|
||||
|
||||
$dir = dirname(__DIR__, 2);
|
||||
|
||||
return [
|
||||
'lean.default' => [
|
||||
'picea' => [
|
||||
'context' => "Lean\\View",
|
||||
'context' => \Lean\View::class,
|
||||
|
||||
'view' => [
|
||||
[
|
||||
|
@ -67,13 +68,18 @@ return [
|
|||
'cronard' => [],
|
||||
|
||||
'taxus' => [
|
||||
[ new Privilege("dev", "Is a developper of this application."), "is_dev" ],
|
||||
[ new Privilege("admin", "Can manage mostly everything from this application."), "is_admin" ],
|
||||
[ new Privilege("user", "Is an authenticated user."), "is_user" ],
|
||||
[ new Privilege("anonymous", "Is an anonymous (unauthenticated) user."), "is_anonymous" ],
|
||||
]
|
||||
'is_dev' => [ ' dev' => "Is a developper of this application or has the same rights" ],
|
||||
'is_admin' => [ 'admin' => "Can manage almost everything in this application."],
|
||||
'is_moderator' => [ 'moderator' => "Can moderate this application."],
|
||||
'is_user' => [ 'user' => "Is an authenticated user."],
|
||||
'is_anonymous' => [ 'anonymous' => "Is an anonymous user."],
|
||||
],
|
||||
],
|
||||
|
||||
'lean.autoload' => add([
|
||||
Lean::class,
|
||||
]),
|
||||
|
||||
Lean::class => autowire(Lean::class),
|
||||
|
||||
JavascriptMiddleware::class => create(JavascriptMiddleware::class),
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
use Ulmus\ConnectionAdapter,
|
||||
Ulmus\Container\AdapterProxy;
|
||||
|
||||
use Storage\Session;
|
||||
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
use Ulmus\{ ConnectionAdapter, Container\AdapterProxy };
|
||||
use Lean\Lean;
|
||||
|
||||
return [
|
||||
'lean:adapter.sqlite' => function($c) {
|
||||
|
|
|
@ -2,68 +2,13 @@
|
|||
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
|
||||
use Picea\{
|
||||
Language\LanguageRegistration,
|
||||
Caching\Cache,
|
||||
Caching\Opcache,
|
||||
Compiler,
|
||||
Compiler\Context,
|
||||
Compiler\BaseContext,
|
||||
FileFetcher,
|
||||
Method\Request};
|
||||
use Picea\{ Language\LanguageRegistration, };
|
||||
|
||||
use Picea\Extension\{ LanguageHandlerInterface, LanguageExtension, TitleExtension, NumberExtension, UrlExtension };
|
||||
use Picea\Extension\{ LanguageHandlerInterface, };
|
||||
|
||||
use Picea\Ui\{ Method, Ui };
|
||||
use Picea\Ui\{ Ui };
|
||||
|
||||
return [
|
||||
Picea\Picea::class => function($c) {
|
||||
return new Picea\Picea($c->get(Context::class), $c->get(Cache::class), $c->get(Compiler::class), null, $c->get(FileFetcher::class), null, getenv("DEBUG"));
|
||||
},
|
||||
|
||||
Context::class => function($c) {
|
||||
return new BaseContext($c->get(Lean\Lean::class)->getPiceaContext());
|
||||
},
|
||||
|
||||
Ui::class => autowire(Ui::class),
|
||||
|
||||
Compiler::class => autowire(Compiler::class),
|
||||
|
||||
Request::class => autowire(Request::class),
|
||||
|
||||
Method\Form::class => autowire(Method\Form::class),
|
||||
|
||||
Method\Pagination::class => autowire(Method\Pagination::class),
|
||||
|
||||
LanguageExtension::class => create(LanguageExtension::class)->constructor(get(LanguageHandlerInterface::class)),
|
||||
|
||||
LanguageHandlerInterface::class => autowire(\Lean\LanguageHandler::class),
|
||||
|
||||
LanguageRegistration::class => create(\Lean\PiceaDefaultRegistration::class)->constructor(get('picea.extensions'), [], [], get(Ui::class), null),
|
||||
|
||||
'picea.extensions' => function(\Psr\Container\ContainerInterface $c) {
|
||||
return array_merge([
|
||||
$c->get(LanguageExtension::class),
|
||||
$c->get(TitleExtension::class),
|
||||
$c->get(NumberExtension::class),
|
||||
$c->get(UrlExtension::class),
|
||||
$c->get(Method\Form::class),
|
||||
$c->get(Method\Pagination::class),
|
||||
$c->get(Request::class),
|
||||
], class_exists(\Taxus\Picea\Extension::class) ? [ $c->get(\Taxus\Picea\Extension::class) ] : [],
|
||||
array_map(fn($class) => $c->get($class), $c->get(Lean\Lean::class)->getPiceaExtensions())
|
||||
);
|
||||
},
|
||||
|
||||
TitleExtension::class => autowire(TitleExtension::class),
|
||||
|
||||
NumberExtension::class => autowire(NumberExtension::class),
|
||||
|
||||
UrlExtension::class => create(UrlExtension::class)->constructor(getenv("URL_BASE"), get('git.commit'), explode(',', getenv('APP_URL')), (bool) getenv('FORCE_SSL')),
|
||||
|
||||
Cache::class => create(Opcache::class)->constructor(getenv("CACHE_PATH"), get(Context::class)),
|
||||
|
||||
FileFetcher::class => function($c) {
|
||||
return new FileFetcher($c->get(Lean\Lean::class)->getViewPaths());
|
||||
},
|
||||
];
|
|
@ -23,6 +23,12 @@ DEFAULT_TIME = "fr.UTF-8"
|
|||
DEFAULT_TIME_FALLBACK = "french.UTF-8"
|
||||
|
||||
# Database
|
||||
#SQLITE_PATH = "var/home.sqlite3"
|
||||
#SQLITE_ADAPTER = "SQLite"
|
||||
#SQLITE_PRAGMA_BEGIN = "foreign_keys=ON,synchronous=NORMAL"
|
||||
#SQLITE_PRAGMA_DEBUG_BEGIN = "journal_mode=WAL"
|
||||
#SQLITE_PRAGMA_CLOSE = "analysis_limit=500,optimize"
|
||||
|
||||
DATABASE_PORT = ""
|
||||
DATABASE_HOST = ""
|
||||
DATABASE_NAME = ""
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
.idea
|
||||
.env
|
||||
composer.lock
|
||||
/private/
|
||||
/public/static/
|
||||
/public/.htaccess
|
||||
/vendor/
|
||||
/var/
|
|
@ -0,0 +1,152 @@
|
|||
{
|
||||
"name": "my_namespace/my_project",
|
||||
"description": "",
|
||||
"type": "app",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
|
||||
],
|
||||
"minimum-stability": "dev",
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"ext-apcu": "*",
|
||||
"ext-json": "*",
|
||||
"league/route": "^5.0.0-dev",
|
||||
"laminas/laminas-diactoros": "2.24.x-dev",
|
||||
"laminas/laminas-httphandlerrunner": "2.5.x-dev",
|
||||
"vlucas/phpdotenv": "^3.4@dev",
|
||||
"middlewares/whoops": "dev-master",
|
||||
"ralouphie/getallheaders": "dev-master",
|
||||
"mcnd/dump": "dev-master",
|
||||
"mcnd/storage": "dev-master",
|
||||
"mcnd/event": "dev-master",
|
||||
"mcnd/ulmus": "dev-master",
|
||||
"mcnd/ulmus-api": "dev-master",
|
||||
"mcnd/ulmus-user": "dev-master",
|
||||
"mcnd/picea": "dev-master",
|
||||
"mcnd/picea-ui": "dev-master",
|
||||
"mcnd/picea-asset": "dev-master",
|
||||
"mcnd/cronard": "dev-master",
|
||||
"mcnd/lean-console": "dev-master",
|
||||
"mcnd/kash": "dev-master",
|
||||
"mcnd/taxus": "dev-master",
|
||||
"mcnd/notes": "dev-master",
|
||||
"mcnd/thebugs": "dev-master",
|
||||
"mcnd/negundo-client": "dev-master"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/cronard.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/dump.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/storage.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/lean.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/lean-console.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/ulmus.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/ulmus-api.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/ulmus-user.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/ulmus-api-gitea.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/picea.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/storage.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/picea-ui.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/picea-asset.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/notes.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/the-bugs.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/tell.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/taxus.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/dump.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/kash.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/event.git"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.mcnd.ca/mcndave/negundo-client.git"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MyProject\\Namespace": "src/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": [
|
||||
"Lean\\Composer::postInstall"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"Lean\\Composer::postUpdate"
|
||||
]
|
||||
},
|
||||
"extra" : {
|
||||
"lean" : {
|
||||
"autoload": {
|
||||
"definitions" : [
|
||||
"meta/definitions/definitions.php",
|
||||
"meta/definitions/storage.php",
|
||||
"meta/definitions/security.php",
|
||||
"meta/definitions/auth.php",
|
||||
"meta/definitions/env.php"
|
||||
],
|
||||
"config" : [
|
||||
"meta/config.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,57 +1,49 @@
|
|||
<?php
|
||||
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
use Taxus\Privilege;
|
||||
|
||||
$dir = getenv("META_PATH") . "/definitions";
|
||||
use function DI\{ autowire, add, create, get };
|
||||
|
||||
return array_merge(
|
||||
Lean\Lean::definitions(),
|
||||
$dir = dirname(__DIR__, 2);
|
||||
|
||||
Lean\Lean::autoloadDefinitionsFromComposerExtra(),
|
||||
|
||||
[
|
||||
'%APPKEY%' => [
|
||||
'picea' => [
|
||||
'context' => "%ESCAPED_NAMESPACE%\\View",
|
||||
'asset' => [],
|
||||
'extensions' => [],
|
||||
|
||||
],
|
||||
|
||||
'ulmus' => [
|
||||
'entities' => [ '%ESCAPED_NAMESPACE%\\Entity' => getenv("PROJECT_PATH") . '/src/Entity/' ],
|
||||
],
|
||||
|
||||
'routes' => [
|
||||
'%ESCAPED_NAMESPACE%\\Controller' => getenv("PROJECT_PATH") . '/src/Controller/',
|
||||
],
|
||||
|
||||
'events' => [
|
||||
'%ESCAPED_NAMESPACE%\\Controller' => implode(DIRECTORY_SEPARATOR, [ getenv("PROJECT_PATH"), 'src', 'Controller', '' ]),
|
||||
],
|
||||
|
||||
'cronard' => [
|
||||
'%ESCAPED_NAMESPACE%\\Controller' => implode(DIRECTORY_SEPARATOR, [ getenv("PROJECT_PATH"), 'src', 'Controller', '' ]),
|
||||
],
|
||||
|
||||
'cli' => [
|
||||
'%ESCAPED_NAMESPACE%\\Controller' => implode(DIRECTORY_SEPARATOR, [ getenv("PROJECT_PATH"), 'src', 'Controller', '' ]),
|
||||
],
|
||||
return [
|
||||
'%APPKEY%' => [
|
||||
'picea' => [
|
||||
'context' => "%ESCAPED_NAMESPACE%\\View",
|
||||
'asset' => [],
|
||||
'extensions' => [],
|
||||
],
|
||||
|
||||
'app.middlewares' => [],
|
||||
'ulmus' => [
|
||||
'entities' => [ '%ESCAPED_NAMESPACE%\\Entity' => implode(DIRECTORY_SEPARATOR, [ $dir, 'src', 'Entity', '' ]) ],
|
||||
],
|
||||
|
||||
'routes' => [
|
||||
'%ESCAPED_NAMESPACE%\\Controller' => implode(DIRECTORY_SEPARATOR, [ $dir, 'src', 'Controller', '' ]),
|
||||
],
|
||||
|
||||
'events' => [
|
||||
'%ESCAPED_NAMESPACE%\\Controller' => implode(DIRECTORY_SEPARATOR, [ $dir, 'src', 'Controller', '' ]),
|
||||
],
|
||||
|
||||
'cronard' => [
|
||||
'%ESCAPED_NAMESPACE%\\Controller' => implode(DIRECTORY_SEPARATOR, [ $dir, 'src', 'Controller', '' ]),
|
||||
],
|
||||
|
||||
'cli' => [
|
||||
'%ESCAPED_NAMESPACE%\\Controller' => implode(DIRECTORY_SEPARATOR, [ $dir, 'src', 'Controller', '' ]),
|
||||
],
|
||||
|
||||
'taxus' => [
|
||||
'is_dev' => [ 'dev' => "Can manage almost everything in this application."],
|
||||
'is_admin' => [ 'admin' => "Can manage almost everything in this application."],
|
||||
'is_moderator' => [ 'moderator' => "Can moderate this application."],
|
||||
'is_user' => [ 'user' => "Is an authenticated user."],
|
||||
'is_anonymous' => [ 'anonymous' => "Is an anonymous (unauthenticated) user."],
|
||||
]
|
||||
],
|
||||
|
||||
require("$dir/auth.php"),
|
||||
require("$dir/storage.php"),
|
||||
require("$dir/security.php"),
|
||||
require("$dir/env/" . getenv('APP_ENV') . ".php"),
|
||||
[
|
||||
'config' => function () {
|
||||
return array_merge_recursive(
|
||||
Lean\Lean::autoloadConfigFromComposerExtra(),
|
||||
require(getenv("META_PATH")."/config.php")
|
||||
);
|
||||
}
|
||||
]
|
||||
);
|
||||
'app.middlewares' => \DI\add([
|
||||
Ulmus\User\Middleware\RememberMeMiddleware::class,
|
||||
]),
|
||||
];
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
return require("env/" . ( getenv('APP_ENV') ?? 'prod' ) . ".php");
|
|
@ -4,7 +4,7 @@ use Picea\Picea;
|
|||
|
||||
use Negundo\Client\{ NegundoMiddleware, SoftwareConfig };
|
||||
|
||||
use Laminas\Diactoros\Response\HtmlResponse;
|
||||
use Lean\Factory\HttpFactory;
|
||||
|
||||
use Psr\Http\Server\MiddlewareInterface,
|
||||
Psr\Http\Message\ServerRequestInterface,
|
||||
|
@ -35,7 +35,7 @@ return [
|
|||
return function(\Throwable $exception) use ($picea) {
|
||||
error_log($exception->getMessage());
|
||||
|
||||
return new HtmlResponse($picea->renderHtml('lean/error/500', [
|
||||
return HttpFactory::createHtmlResponse($picea->renderHtml('lean/error/500', [
|
||||
'title' => "Une erreur s'est produite lors de l'exécution du script.",
|
||||
'subtitle' => "Êtes-vous connecté avec le bon compte ?",
|
||||
'message' => $exception->getMessage(),
|
||||
|
|
|
@ -6,17 +6,28 @@ use Taxus\{ Privilege, Taxus, PermissionGrantInterface, DefaultPermissionGrant }
|
|||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
use function DI\autowire, DI\create, DI\get;
|
||||
use function DI\{ create, get, add };
|
||||
|
||||
return [
|
||||
Taxus::class => function ($c) {
|
||||
return ( new Taxus( $c->get(PermissionGrantInterface::class) ) )->add(
|
||||
[ new Privilege("dev", "Is a developper of this application."), "is_dev" ],
|
||||
[ new Privilege("admin", "Can manage mostly everything from this application."), "is_admin" ],
|
||||
[ new Privilege("user", "Is an authenticated user."), "is_user" ],
|
||||
[ new Privilege("anonymous", "Is an anonymous (unauthenticated) user."), "is_anonymous" ],
|
||||
);
|
||||
$taxus = new Taxus( ... $c->get('taxus.gates') );
|
||||
|
||||
$list = [];
|
||||
|
||||
foreach($c->get(Lean\Lean::class)->getTaxusPrivileges() as $key => $privilege) {
|
||||
foreach($privilege as $name => $description) {
|
||||
$list[] = [ new Privilege($name, $description), $key ];
|
||||
}
|
||||
}
|
||||
|
||||
$taxus->add(... $list);
|
||||
|
||||
return $taxus;
|
||||
},
|
||||
|
||||
'taxus.gates' => add([
|
||||
get(PermissionGrantInterface::class),
|
||||
]),
|
||||
|
||||
PermissionGrantInterface::class => create(%NAMESPACE%\PrivilegeGrantAccess::class)->constructor(get(ServerRequestInterface::class), get(Session::class)),
|
||||
];
|
||||
|
|
|
@ -16,10 +16,4 @@ return [
|
|||
|
||||
return $adapter;
|
||||
},
|
||||
|
||||
AdapterProxy::class => function (ContainerInterface $c) {
|
||||
return new AdapterProxy(
|
||||
$c->get(ConnectionAdapter::class)
|
||||
);
|
||||
},
|
||||
];
|
||||
|
|
|
@ -1,12 +1,22 @@
|
|||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
# RewriteBase /
|
||||
|
||||
# Force HTTPS (disabled by default)
|
||||
# RewriteCond %{HTTPS} off
|
||||
# RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# Reverse Proxy ; Force HTTPS (disabled by default)
|
||||
# RewriteCond %{HTTP:X-Forwarded-SSL} off
|
||||
# RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# Remove trailing slashes from request URL
|
||||
#RewriteCond %{REQUEST_FILENAME} !-d
|
||||
#RewriteCond %{REQUEST_URI} (.+)/$
|
||||
#RewriteRule ^ %1 [R=301,L]
|
||||
|
||||
# Redirect everything into app
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} (.+)/$
|
||||
RewriteRule ^ %1 [R=301,L]
|
||||
RewriteRule ^([^?]*)$ %1 [NC,L,QSA]
|
||||
</IfModule>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
try {
|
||||
require_once("../src/Kernel.php");
|
||||
require_once(dirname(__DIR__)."/src/Kernel.php");
|
||||
}
|
||||
catch(\Throwable $t) {
|
||||
echo $t->getMessage();
|
||||
echo sprintf("%s in <strong>%s</strong> <pre>%s</pre>", $t->getMessage(), $t->getFile() . ":" . $t->getLine(), $t->getTraceAsString());
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="Remove trailing slash" stopProcessing="true">
|
||||
<match url="(.*)/$" />
|
||||
<conditions>
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
|
||||
</conditions>
|
||||
<action type="Redirect" redirectType="Permanent" url="{R:1}" />
|
||||
</rule>
|
||||
<rule name="Framework Routing" stopProcessing="true">
|
||||
<match url="." ignoreCase="false" />
|
||||
<conditions logicalGrouping="MatchAll">
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
|
||||
</conditions>
|
||||
<action type="Rewrite" url="index.php" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
<staticContent>
|
||||
<remove fileExtension=".js" />
|
||||
<mimeMap fileExtension=".js" mimeType="application/x-javascript; charset=UTF-8" />
|
||||
<remove fileExtension=".css" />
|
||||
<mimeMap fileExtension=".css" mimeType="text/css; charset=UTF-8" />
|
||||
<remove fileExtension=".woff" />
|
||||
<remove fileExtension=".eot" />
|
||||
<remove fileExtension=".ttf" />
|
||||
<remove fileExtension=".svg" />
|
||||
|
||||
<mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
|
||||
<mimeMap fileExtension=".ttf" mimeType="application/font-sfnt" />
|
||||
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
|
||||
<mimeMap fileExtension=".woff" mimeType="application/font-woff" />
|
||||
</staticContent>
|
||||
<handlers>
|
||||
<remove name="PHP7.3" />
|
||||
<add name="PHP7.3" path="*.php" verb="*" modules="FastCgiModule" scriptProcessor="C:\php\7.4.0\php-cgi.exe" resourceType="File" requireAccess="Script" />
|
||||
</handlers>
|
||||
<httpErrors errorMode="Detailed" />
|
||||
</system.webServer>
|
||||
</configuration>
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace %NAMESPACE%;
|
||||
|
||||
use Lean\Lean;
|
||||
use Ulmus\ConnectionAdapter;
|
||||
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
@ -22,8 +23,6 @@ new class(dirname(__DIR__)) extends \Lean\Kernel {
|
|||
{
|
||||
$this->errorLogPath = getenv("LOGS_PATH") . DIRECTORY_SEPARATOR. date("Y-m").".log";
|
||||
|
||||
$this->definitionFilePath = implode(DIRECTORY_SEPARATOR, [ getenv('META_PATH'), 'definitions', 'definitions.php' ]);
|
||||
|
||||
return parent::initializeEngine();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,21 +11,25 @@ use Notes\Security\Attribute\Security;
|
|||
use %NAMESPACE%\{ Entity, Lib, Form };
|
||||
|
||||
use Mcnd\Event\EventManager;
|
||||
use Ulmus\User\Entity\UserInterface;
|
||||
use Notes\Attribute\Ignore;use Ulmus\User\Entity\UserInterface;
|
||||
|
||||
#[Security(locked: false)]
|
||||
#[Route(method: ['GET', 'POST', ])]
|
||||
trait ControllerTrait {
|
||||
use \Lean\ControllerTrait;
|
||||
|
||||
#[Ignore]
|
||||
public ? UserInterface $user;
|
||||
|
||||
#[Ignore]
|
||||
protected EventManager $eventManager;
|
||||
|
||||
#[Ignore]
|
||||
public function __construct(Picea $picea, Session $session, UserInterface $user, \Notes\Breadcrumb\Breadcrumb $breadcrumb, EventManager $eventManager) {
|
||||
$this->initializeController($picea, $session, $user, $breadcrumb, $eventManager);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function initializeController(Picea $picea, Session $session, UserInterface $user, \Notes\Breadcrumb\Breadcrumb $breadcrumb, EventManager $eventManager) {
|
||||
$this->picea = $picea;
|
||||
$this->session = $session;
|
||||
|
|
|
@ -28,6 +28,8 @@ class Application
|
|||
|
||||
public array $tellPhp;
|
||||
|
||||
public array $taxus;
|
||||
|
||||
public array $data = [];
|
||||
|
||||
public function __construct(string $name) {
|
||||
|
@ -38,7 +40,14 @@ class Application
|
|||
{
|
||||
$this->data = array_replace($this->data, $data);
|
||||
|
||||
if (is_array($picea = $data['picea'] ?? false)) {
|
||||
$this->loadData();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function loadData() : static
|
||||
{
|
||||
if (is_array($picea = $this->data['picea'] ?? false)) {
|
||||
if ($picea['context'] ?? false ) {
|
||||
$this->piceaContext = $picea['context'];
|
||||
}
|
||||
|
@ -56,13 +65,13 @@ class Application
|
|||
}
|
||||
}
|
||||
|
||||
if (is_array($ulmus = $data['ulmus'] ?? false)) {
|
||||
if (is_array($ulmus = $this->data['ulmus'] ?? false)) {
|
||||
if ($ulmus['entities'] ?? false) {
|
||||
$this->entities = $ulmus['entities'];
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($tell = $data['tell'] ?? false)) {
|
||||
if (is_array($tell = $this->data['tell'] ?? false)) {
|
||||
if ($tell['json'] ?? false) {
|
||||
$this->tellJson = $tell['json'];
|
||||
}
|
||||
|
@ -72,20 +81,24 @@ class Application
|
|||
}
|
||||
}
|
||||
|
||||
if (is_array($data['routes'] ?? false)) {
|
||||
$this->routes = $data['routes'];
|
||||
if (is_array($this->data['routes'] ?? false)) {
|
||||
$this->routes = $this->data['routes'];
|
||||
}
|
||||
|
||||
if (is_array($data['cronard'] ?? false)) {
|
||||
$this->cronard = $data['cronard'];
|
||||
if (is_array($this->data['cronard'] ?? false)) {
|
||||
$this->cronard = $this->data['cronard'];
|
||||
}
|
||||
|
||||
if (is_array($data['events'] ?? false)) {
|
||||
$this->events = $data['events'];
|
||||
if (is_array($this->data['events'] ?? false)) {
|
||||
$this->events = $this->data['events'];
|
||||
}
|
||||
|
||||
if (is_array($data['cli'] ?? false)) {
|
||||
$this->cli = $data['cli'];
|
||||
if (is_array($this->data['cli'] ?? false)) {
|
||||
$this->cli = $this->data['cli'];
|
||||
}
|
||||
|
||||
if (is_array($this->data['taxus'] ?? false)) {
|
||||
$this->taxus = $this->data['taxus'];
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
|
|
@ -38,7 +38,11 @@ class ApplicationStrategy extends Strategy\ApplicationStrategy {
|
|||
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
return $this->throw404($request);
|
||||
if (php_sapi_name() !== 'cli' and ! defined('STDIN')) {
|
||||
return $this->throw404($request);
|
||||
}
|
||||
|
||||
return $handler->handle($request);;
|
||||
}
|
||||
|
||||
public function throw404(ServerRequestInterface $request) : ResponseInterface
|
||||
|
|
|
@ -73,6 +73,10 @@ class Composer
|
|||
if ( file_exists($container = static::createPath('var/cache/di/CompiledContainer.php')) ) {
|
||||
unlink($container);
|
||||
}
|
||||
|
||||
if (function_exists("apcu_clear_cache")) {
|
||||
apcu_clear_cache();
|
||||
}
|
||||
}
|
||||
|
||||
public static function readComposerLock() : false|array
|
||||
|
|
|
@ -2,30 +2,42 @@
|
|||
|
||||
namespace Lean;
|
||||
|
||||
use DI\Attribute\Inject;
|
||||
use Lean\Factory\HttpFactory;
|
||||
use Notes\Attribute\Ignore;
|
||||
use Notes\Route\Attribute\Object\Route;
|
||||
use Notes\Security\Attribute\Security;
|
||||
use Picea, Picea\Ui\Method\FormContext;
|
||||
use TheBugs\Email\MailerInterface;
|
||||
use Storage\Session;
|
||||
use Storage\{ Cookie, Session };
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
|
||||
use Psr\Http\Message\{ ServerRequestInterface, ResponseInterface };
|
||||
|
||||
use function file_get_contents;
|
||||
|
||||
#[Security(locked: true)]
|
||||
#[Route(method: [ "GET", "POST", "DELETE" ])]
|
||||
#[Security(locked: false, realm: "Protected Area")]
|
||||
#[Route(method: [ "GET", "POST" ])]
|
||||
trait ControllerTrait {
|
||||
public ? \Notes\Breadcrumb\Breadcrumb $breadcrumb;
|
||||
|
||||
public ? Session $session;
|
||||
#[Inject]
|
||||
public \Notes\Breadcrumb\Breadcrumb $breadcrumb;
|
||||
|
||||
public ? Picea\Picea $picea;
|
||||
#[Inject]
|
||||
public Session $session;
|
||||
|
||||
public ? MailerInterface $mailer;
|
||||
#[Inject]
|
||||
public Cookie $cookie;
|
||||
|
||||
#[Inject]
|
||||
public Picea\Picea $picea;
|
||||
|
||||
#[Inject]
|
||||
public MailerInterface $mailer;
|
||||
|
||||
public array $contextList = [];
|
||||
|
||||
#[Ignore]
|
||||
public function exportJson(ServerRequestInterface $request, string $entityClass, bool $includeRelations = true, ? callable $callback = null) : ResponseInterface
|
||||
{
|
||||
foreach($entityClass::repository()->filterServerRequest( $entityClass::searchRequest()->fromRequest($request->withQueryParams($request->getQueryParams() + ['limit' => PHP_INT_MAX,])) )->loadAll() as $entity) {
|
||||
|
@ -35,6 +47,7 @@ trait ControllerTrait {
|
|||
return $this->renderJson( array_filter($data ?? [], function($row) { return $row !== null; }));
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function renderRawView(string $view, ?array $variables = null) : string
|
||||
{
|
||||
if ( null === $content = $this->picea->renderHtml($view, $variables ?? [], $this) ) {
|
||||
|
@ -44,6 +57,7 @@ trait ControllerTrait {
|
|||
return $content;
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function renderView(string $view, ?array $variables = null) : ResponseInterface
|
||||
{
|
||||
return static::renderHtml(
|
||||
|
@ -51,6 +65,7 @@ trait ControllerTrait {
|
|||
);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function renderError(string $errorCode, ?array $variables = null) : ResponseInterface
|
||||
{
|
||||
return static::renderHtml(
|
||||
|
@ -58,66 +73,78 @@ trait ControllerTrait {
|
|||
);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function renderDocumentation(string $filename) : ResponseInterface
|
||||
{
|
||||
return $this->renderMarkdown( file_get_contents(getenv("PROJECT_PATH") . "/meta/doc/$filename.md") );
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
protected function redirect(string $url, int $code = 302, array $headers = []) {
|
||||
return HttpFactory::createRedirectResponse($url, $code, $headers);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public static function renderNothing(int $code = 204, array $headers = []) : ResponseInterface
|
||||
{
|
||||
return HttpFactory::createEmptyResponse($code, $headers);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public static function renderText(string $text, int $code = 200, array $headers = []) : ResponseInterface
|
||||
{
|
||||
return HttpFactory::createTextResponse($text, $code, $headers);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public static function renderHtml(string $html, int $code = 200, array $headers = []) : ResponseInterface
|
||||
{
|
||||
return HttpFactory::createHtmlResponse($html, $code, $headers);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public static function renderJson(mixed $data, int $code = 200, array $headers = []) : ResponseInterface
|
||||
{
|
||||
return HttpFactory::createJsonResponse($data, $code, $headers);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function renderPdf($rawdata, int $status = 200, array $headers = []) : ResponseInterface
|
||||
{
|
||||
return HttpFactory::createPdfResponse($rawdata, $status, $headers);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public static function renderDownloadable(string $data, string $filename, int $code = 200, array $headers = []) : ResponseInterface
|
||||
{
|
||||
return HttpFactory::createDownloadableResponse($data, $filename, $code, $headers);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public static function renderImage(string $data, int $code = 200, array $headers = []) : ResponseInterface
|
||||
{
|
||||
return HttpFactory::createImageResponse($data, $code, $headers);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public static function renderAsset(string $path, int $code = 200, array $headers = []) : ResponseInterface
|
||||
{
|
||||
return HttpFactory::createFileDownloadResponse($path, $code, $headers);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function renderMarkdown(string $filepath, int $code = 200, array $headers = []) : ResponseInterface
|
||||
{
|
||||
if ( ! class_exists(CommonMarkConverter::class)) {
|
||||
throw new \BadFunctionCallException("League\CommonMark seems to be missing, please install dependency before trying to render Markdown content");
|
||||
}
|
||||
|
||||
$markdown = ( new CommonMarkConverter() )->convertToHtml(file_get_contents($filepath));
|
||||
$markdown = ( new CommonMarkConverter() )->convert(file_get_contents($filepath));
|
||||
|
||||
return $this->renderView("docs", get_defined_vars());
|
||||
return $this->renderView("lean/layout/docs", get_defined_vars());
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function renderCLI(ServerRequestInterface $request, mixed $data) : ResponseInterface
|
||||
{
|
||||
if ($data instanceof \JsonSerializable ) {
|
||||
|
@ -134,6 +161,7 @@ trait ControllerTrait {
|
|||
);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function fromResponse(ResponseInterface $response)
|
||||
{
|
||||
if ( $response->getStatusCode() === 200 ) {
|
||||
|
@ -145,6 +173,7 @@ trait ControllerTrait {
|
|||
return null;
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function asset(string $url, array $parameters = []) : string
|
||||
{
|
||||
if (! $this->picea ) {
|
||||
|
@ -154,6 +183,7 @@ trait ControllerTrait {
|
|||
return $this->picea->compiler->getExtensionFromToken('asset')->buildAssetUrl($url, $parameters);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function url(string $url, array $parameters = []) : string
|
||||
{
|
||||
if (! $this->picea ) {
|
||||
|
@ -163,6 +193,7 @@ trait ControllerTrait {
|
|||
return $this->picea->compiler->getExtensionFromToken('url')->buildUrl($url, $parameters);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function route(string $name, array $parameters = []) : string
|
||||
{
|
||||
if (! $this->picea ) {
|
||||
|
@ -172,11 +203,13 @@ trait ControllerTrait {
|
|||
return $this->picea->compiler->getExtensionFromToken('route')->buildRouteUrl($name, $parameters);
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function json($data, int $flags = 0) : string
|
||||
{
|
||||
return htmlentities(json_encode($data, $flags), ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function pushContext(FormContext $context) : FormContext
|
||||
{
|
||||
$this->contextList[$context->formName ?? uniqid("context_")] = $context;
|
||||
|
@ -184,11 +217,13 @@ trait ControllerTrait {
|
|||
return $context;
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function context(? string $name = null) : ? FormContext
|
||||
{
|
||||
return $name ? $this->contextList[$name] : array_values($this->contextList)[0] ?? null;
|
||||
}
|
||||
|
||||
#[Ignore]
|
||||
public function isRoute(mixed $name, ServerRequestInterface $request) : bool
|
||||
{
|
||||
foreach((array) $name as $item) {
|
||||
|
|
|
@ -4,10 +4,16 @@ namespace Lean\Factory;
|
|||
|
||||
use Laminas\Diactoros\Response\{EmptyResponse, HtmlResponse, JsonResponse, RedirectResponse, TextResponse};
|
||||
use Lean\Response\{ DownloadResponse, ImageResponse, FileDownloadResponse, PdfResponse };
|
||||
use Laminas\Diactoros\Response;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class HttpFactory
|
||||
{
|
||||
public static function createResponse(string $url, int $code = 302, array $headers = []) : ResponseInterface
|
||||
{
|
||||
return new Response($url, $code, $headers);
|
||||
}
|
||||
|
||||
public static function createRedirectResponse(string $url, int $code = 302, array $headers = []) : ResponseInterface
|
||||
{
|
||||
return new RedirectResponse($url, $code, $headers);
|
||||
|
@ -33,7 +39,7 @@ class HttpFactory
|
|||
return new EmptyResponse($code, $headers);
|
||||
}
|
||||
|
||||
public static function createPdfResponse(\Stringable $binary, int $code = 200, array $headers = []) : ResponseInterface
|
||||
public static function createPdfResponse(\Stringable|string $binary, int $code = 200, array $headers = []) : ResponseInterface
|
||||
{
|
||||
return new PdfResponse((string) $binary, $code, $headers);
|
||||
}
|
||||
|
|
|
@ -29,14 +29,12 @@ class Kernel {
|
|||
|
||||
public int $errorReporting = E_ALL & ~E_USER_DEPRECATED & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE;
|
||||
|
||||
public string $definitionFilePath;
|
||||
public array $definitionFilePaths;
|
||||
|
||||
public string $errorLogPath;
|
||||
|
||||
public string $projectPath;
|
||||
|
||||
public string $routeDefinitionList = 'routes.list';
|
||||
|
||||
public function __construct(string $projectPath)
|
||||
{
|
||||
$this->projectPath = $projectPath;
|
||||
|
@ -108,6 +106,8 @@ class Kernel {
|
|||
{
|
||||
$containerBuilder = new ContainerBuilder();
|
||||
|
||||
$containerBuilder->useAttributes(true);
|
||||
|
||||
if (getenv("APP_ENV") === "prod") {
|
||||
if (getenv("CACHE_PATH")) {
|
||||
# check if ACPU is there first, $containerBuilder->enableDefinitionCache();
|
||||
|
@ -124,12 +124,22 @@ class Kernel {
|
|||
}
|
||||
}
|
||||
|
||||
# $containerBuilder->useAnnotations(false);
|
||||
|
||||
if ($this->definitionFilePath ?? false) {
|
||||
$containerBuilder->addDefinitions(require($this->definitionFilePath));
|
||||
foreach(Lean::getDefinitionsPathsFromComposer() as $path) {
|
||||
$containerBuilder->addDefinitions($path);
|
||||
}
|
||||
|
||||
foreach($this->definitionFilePaths ?? [] as $path) {
|
||||
$containerBuilder->addDefinitions($path);
|
||||
}
|
||||
|
||||
$containerBuilder->addDefinitions([
|
||||
'config' => function () {
|
||||
return array_merge_recursive(
|
||||
Lean::autoloadConfigFromComposerExtra(), []
|
||||
);
|
||||
}
|
||||
]);
|
||||
|
||||
$this->container = $containerBuilder->build();
|
||||
|
||||
return $this;
|
||||
|
@ -137,16 +147,15 @@ class Kernel {
|
|||
|
||||
protected function serviceContainer() : self
|
||||
{
|
||||
$this->container->has(AdapterProxy::class) and $this->container->get(AdapterProxy::class);
|
||||
$this->container->has('ulmus.caching') and ( Ulmus::$cache = $this->container->get('ulmus.caching') );
|
||||
$this->container->has(Lean::class) and $this->container->get(Lean::class);
|
||||
|
||||
if ($this->container->has(I18n::class)) {
|
||||
$i18n = $this->container->get(I18n::class);
|
||||
$i18n->locale($this->locale);
|
||||
$i18n->initialize(!getenv("DEBUG"));
|
||||
if ($this->container->has('lean.autoload')) {
|
||||
foreach($this->container->get('lean.autoload') as $class) {
|
||||
$this->container->get($class);
|
||||
}
|
||||
}
|
||||
|
||||
# Must be removed from KERNEL !
|
||||
$this->container->has('ulmus.caching') and ( Ulmus::$cache = $this->container->get('ulmus.caching') );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -154,8 +163,7 @@ class Kernel {
|
|||
{
|
||||
ServerRequestFactory::fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);
|
||||
|
||||
// Router
|
||||
$routeFactory = $this->container->get($this->routeDefinitionList);
|
||||
$routeFactory = $this->container->get(Routing\RouteDefinitionInterface::class);
|
||||
|
||||
$router = $routeFactory($this->container);
|
||||
|
||||
|
|
81
src/Lean.php
81
src/Lean.php
|
@ -22,13 +22,16 @@ class Lean
|
|||
|
||||
protected function loadApplications() : void
|
||||
{
|
||||
$list = $this->container->get('config')['lean']['autoload'] ?? [];
|
||||
$list = array_filter($this->container->get('config')['lean']['autoload'] ?? []);
|
||||
|
||||
if (! $list ) {
|
||||
throw new \Exception("You must provide at least one application to autoload within your config file ( 'lean' => 'autoload' => [] )");
|
||||
}
|
||||
|
||||
foreach(array_filter($list) as $application) {
|
||||
# Allows 'lean.default' and [ 'lean.default', 100 ] which allows ordering of apps loading.
|
||||
usort($list, fn($e1, $e2) => ( is_array($e1) ? $e1[1] : 0 ) <=> ( is_array($e2) ? $e2[1] : 0 ));
|
||||
|
||||
foreach(array_map(fn($item) => is_array($item) ? $item[0] : $item, $list) as $application) {
|
||||
if ( $this->container->has($application) ) {
|
||||
$this->applications[] = ( new Application($application) )->fromArray($this->container->get($application));
|
||||
}
|
||||
|
@ -139,11 +142,11 @@ class Lean
|
|||
switch($reader) {
|
||||
case "php":
|
||||
$list = array_merge(...array_map(fn($app) => $app->tellPhp ?? [], $this->applications));
|
||||
break;
|
||||
break;
|
||||
|
||||
case "json":
|
||||
$list = array_merge(...array_map(fn($app) => $app->tellJson ?? [], $this->applications));
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( $list ?? false ) {
|
||||
|
@ -155,39 +158,34 @@ class Lean
|
|||
return null;
|
||||
}
|
||||
|
||||
#[\Deprecated("Definitions are now loaded automatically from composer extra array.")]
|
||||
public static function definitions() : array
|
||||
{
|
||||
return [];
|
||||
|
||||
$path = dirname(__DIR__) . "/meta/definitions/";
|
||||
|
||||
return array_replace(
|
||||
require($path . "authorize.php"),
|
||||
class_exists(\Mcnd\CLI\CliMiddleware::class) ? require($path . "cli.php") : [],
|
||||
class_exists(\Cronard\CronardMiddleware::class) ? require($path . "cronard.php") : [],
|
||||
require($path . "email.php"),
|
||||
require($path . "event.php"),
|
||||
require($path . "http.php"),
|
||||
require($path . "language.php"),
|
||||
class_exists(\Negundo\Client\NegundoMiddleware::class) ? require($path . "negundo.php") : [],
|
||||
require($path . "routes.php"),
|
||||
require($path . "software.php"),
|
||||
require($path . "storage.php"),
|
||||
class_exists(\Picea\Picea::class) ? require($path . "template.php") : [],
|
||||
);
|
||||
}
|
||||
|
||||
public static function autoloadDefinitionsFromComposerExtra() : array
|
||||
public static function getDefinitionsPathsFromComposer() : array
|
||||
{
|
||||
$list = [];
|
||||
|
||||
foreach(Composer::readComposerLock()['packages'] as $package) {
|
||||
$order = $package['extra']['lean']['autoload']['order'] ?? 0;
|
||||
|
||||
foreach($package['extra']['lean']['autoload']['definitions'] ?? [] as $autoload) {
|
||||
$list = array_replace($list, static::loadFromPackage($package, $autoload));
|
||||
$list[] = [ static::pathFromPackage($package, $autoload), $order ];
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
foreach(Composer::readComposerJson()['extra']['lean']['autoload']['definitions'] ?? [] as $autoload) {
|
||||
$order = $package['extra']['lean']['autoload']['order'] ?? 1000;
|
||||
|
||||
$list[] = [ getenv('PROJECT_PATH') . DIRECTORY_SEPARATOR . $autoload, $order ];
|
||||
}
|
||||
|
||||
# Allows 'lean.default' and [ 'lean.default', 100 ] which allows ordering of apps loading.
|
||||
usort($list, fn($e1, $e2) => $e1[1] <=> $e2[1]);
|
||||
|
||||
return array_column($list, 0);
|
||||
}
|
||||
|
||||
public static function autoloadConfigFromComposerExtra() : array
|
||||
|
@ -200,16 +198,36 @@ class Lean
|
|||
}
|
||||
}
|
||||
|
||||
foreach(Composer::readComposerJson()['extra']['lean']['autoload']['config'] ?? [] as $autoload) {
|
||||
$list = array_merge_recursive($list, static::loadFromPackage(null, $autoload));
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
protected static function loadFromPackage(array $package, array|string $autoload) : false|array
|
||||
protected static function pathFromPackage(?array $package, array|string $autoload) : string
|
||||
{
|
||||
if ($package === null) {
|
||||
$filepath = getenv('PROJECT_PATH') . DIRECTORY_SEPARATOR . $autoload;
|
||||
}
|
||||
else {
|
||||
$vendor = getenv('VENDOR_DIR') ? getenv('VENDOR_PATH') : dirname(__DIR__, 3);
|
||||
$filepath = $vendor . DIRECTORY_SEPARATOR . $package['name'] . DIRECTORY_SEPARATOR . $autoload;
|
||||
}
|
||||
|
||||
if (! file_exists($filepath)) {
|
||||
throw new \InvalidArgumentException("Given definition filepath do not exists '$filepath'");
|
||||
}
|
||||
|
||||
return $filepath;
|
||||
}
|
||||
|
||||
protected static function loadFromPackage(? array $package, array|string $autoload) : false|array
|
||||
{
|
||||
$list = [];
|
||||
|
||||
if (is_string($autoload)) {
|
||||
$vendor = getenv('VENDOR_DIR') ? getenv('VENDOR_PATH') : dirname(__DIR__, 3);
|
||||
$file = $vendor . DIRECTORY_SEPARATOR . $package['name'] . DIRECTORY_SEPARATOR . $autoload;
|
||||
$file = static::pathFromPackage($package, $autoload);
|
||||
|
||||
if ( ! file_exists($file) ) {
|
||||
throw new \InvalidArgumentException(sprintf("Given autoload file `%s` from package `%s` was not found or is unreachable", $autoload, $package['name']));
|
||||
|
@ -217,12 +235,9 @@ class Lean
|
|||
|
||||
return require($file);
|
||||
}
|
||||
else {
|
||||
$func = implode('::', array_merge([ key($autoload) ], $autoload));
|
||||
|
||||
return call_user_func($func);
|
||||
}
|
||||
$func = implode('::', array_merge([ key($autoload) ], $autoload));
|
||||
|
||||
return false;
|
||||
return call_user_func($func);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,67 +2,45 @@
|
|||
|
||||
namespace Lean;
|
||||
|
||||
use Notes\Annotation;
|
||||
use Taxus\Taxus;
|
||||
|
||||
use League\Route\RouteGroup,
|
||||
League\Route\Router;
|
||||
|
||||
use Notes\Route\Attribute\Method\Route;
|
||||
use Psr\Http\Message\ServerRequestInterface,
|
||||
Psr\Http\Message\ResponseInterface,
|
||||
Psr\Container\ContainerInterface;
|
||||
|
||||
use Notes\Route\RouteFetcher;
|
||||
|
||||
use Notes\Security\SecurityHandler;
|
||||
|
||||
use Notes\Tell\LanguageHandler;
|
||||
|
||||
use Picea\Picea,
|
||||
Picea\Extension\UrlExtension;
|
||||
|
||||
use Storage\Cookie,
|
||||
Storage\Session;
|
||||
|
||||
use Mcnd\Event\EventManager;
|
||||
|
||||
use function DI\autowire, DI\create;
|
||||
|
||||
class Routing {
|
||||
|
||||
public Annotation $selectedRoute;
|
||||
|
||||
public ResponseInterface $response;
|
||||
|
||||
public array $overriddenRoutes = [];
|
||||
|
||||
public function __construct(
|
||||
public Session $session,
|
||||
public Cookie $cookie,
|
||||
public UrlExtension $extension,
|
||||
public Router $router,
|
||||
public RouteFetcher $fetcher,
|
||||
public SecurityHandler $security,
|
||||
public LanguageHandler $language,
|
||||
public Taxus $taxus,
|
||||
public EventManager $eventManager,
|
||||
) { }
|
||||
|
||||
public function registerRoute(ContainerInterface $container, string $urlBase) {
|
||||
$this->router->group(rtrim($urlBase, "/"), function (RouteGroup $route) use ($container) {
|
||||
foreach($this->fetcher->compile() as $annotation) {
|
||||
$this->eventManager->execute(Event\RoutingCompileRoutes::class, $this, $annotation);
|
||||
foreach($this->fetchRoutesAttributes() as $attribute) {
|
||||
$this->eventManager->execute(Event\RoutingCompileRoutes::class, $this, $attribute);
|
||||
|
||||
/* @deprecated annotation->method will become standard when using native attributes */
|
||||
foreach((array) ( $annotation->method ?? $annotation->methods ) as $method) {
|
||||
# Mapping every URLs from annotations in searched folders (Api, Controller, etc...)
|
||||
$route->map(strtoupper($method), $annotation->getRoute(), function (ServerRequestInterface $request, array $arguments) use (
|
||||
$container, $route, $annotation
|
||||
) : ResponseInterface
|
||||
{
|
||||
$class = $annotation->class;
|
||||
$method = $annotation->classMethod;
|
||||
# Mapping every URLs from attributes in searched folders (Api, Controller, etc...)
|
||||
foreach((array) $attribute->method as $method) {
|
||||
$route->map(strtoupper($method), $attribute->getRegistrableRoute(), function (ServerRequestInterface $request, array $arguments) use (
|
||||
$container, $route, $attribute
|
||||
) : ResponseInterface {
|
||||
$class = $attribute->class;
|
||||
$method = $attribute->classMethod;
|
||||
$object = $container->get($class);
|
||||
|
||||
$this->eventManager->execute(Event\RoutingMapRoutes::class, $this, $container, $request, $annotation);
|
||||
$this->eventManager->execute(Event\RoutingMapRoutes::class, $this, $container, $request, $attribute);
|
||||
|
||||
$container->set(ServerRequestInterface::class, $request);
|
||||
|
||||
|
@ -72,4 +50,40 @@ class Routing {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function fetchRoutesAttributes() : iterable
|
||||
{
|
||||
static $list = [];
|
||||
|
||||
if ($list) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
foreach($this->fetcher->compile() as $routeAttribute) {
|
||||
# Routes with differents methods can have the same name
|
||||
$key = sprintf('{%s}~{%s}', $routeAttribute->name, $this->serializeMethods((array) $routeAttribute->method));
|
||||
|
||||
if ( isset($list[$key]) ) {
|
||||
$this->overriddenRoutes[$key] = $list[$key];
|
||||
}
|
||||
|
||||
$list[$key] = $routeAttribute;
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function findOverriddenRoute(Route $route) : false|iterable
|
||||
{
|
||||
return array_filter($this->overriddenRoutes, fn($e) => $route->name === $e->name);
|
||||
}
|
||||
|
||||
protected function serializeMethods(array $methods) : string
|
||||
{
|
||||
$methods = array_map('strtolower', $methods);
|
||||
|
||||
sort($methods);
|
||||
|
||||
return implode(':', $methods);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace Lean\Routing;
|
||||
|
||||
interface RouteDefinitionInterface {}
|
|
@ -0,0 +1,53 @@
|
|||
{% title "Documentation" %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
{% section "head" %}
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<title>{% section "head.title" %}{{ title() }}{% endsection %}</title>
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{% asset 'static/favicon/apple-touch-icon.png' %}">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="{% asset 'static/favicon/favicon-32x32.png' %}">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="{% asset 'static/favicon/favicon-16x16.png' %}">
|
||||
<link rel="manifest" href="{% asset 'static/favicon/site.webmanifest' %}">
|
||||
<link rel="mask-icon" href="{% asset 'static/favicon/safari-pinned-tab.svg' %}" color="#5bbad5">
|
||||
<meta name="msapplication-TileColor" content="#2d89ef">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<style>
|
||||
a{color:#e44a00}h3{background:#e1e1e1;padding:6px 12px}ul{background:#e9e9fd;padding-top:20px;padding-bottom:20px;border:1px solid #e3e3ec}ul li + li{margin-top:8px}li > em{font-size:0.75rem;color:gray}body{font-family:Helvetica, 'Helvetica Neuve', Arial, Tahoma, sans-serif;font-size:17px;color:#333}h1,h2,h3,h4,h5,h6{color:#222;margin:0 0 20px}dl,ol,p,pre,table,ul{margin:0 0 20px}h1,h2,h3{line-height:1.1}h1{font-size:20px;text-align:right;color:#387eea;font-weight:bold}h2{color:#393939}h3,h4,h5,h6{color:#494949}h3{display:flex}h3 > code{margin-right:5px;color:#b52dac}h3 > strong{margin-left:auto}a{color:#39c;font-weight:400;text-decoration:none}a small{font-size:11px;color:#777;margin-top:-0.6em;display:block}.wrapper{width:860px;margin:0 auto}blockquote{border-left:1px solid #e5e5e5;margin:0;padding:0 0 0 20px;font-style:italic}code,pre{font-size:12px}pre{padding:8px 15px;background:#f8f8f8;border-radius:5px;border:1px solid #e5e5e5;overflow-x:auto}table{width:100%;border-collapse:collapse}td,th{text-align:left;padding:5px 10px;border-bottom:1px solid #e5e5e5}dt{color:#444;font-weight:700}th{color:#444}img{max-width:100%}header{width:270px;float:left;position:fixed}header ul{list-style:none;height:40px;padding:0;background:#eee;background:-moz-linear-gradient(top, #f8f8f8 0%, #dddddd 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd));background:-webkit-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);background:-o-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);background:-ms-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);background:linear-gradient(top, #f8f8f8 0%,#dddddd 100%);border-radius:5px;border:1px solid #d2d2d2;box-shadow:inset #fff 0 1px 0, inset rgba(0,0,0,0.03) 0 -1px 0;width:270px}header li{width:89px;float:left;border-right:1px solid #d2d2d2;height:40px}header ul a{line-height:1;font-size:11px;color:#999;display:block;text-align:center;padding-top:6px;height:40px}strong{color:#222;font-weight:700}header ul li + li{width:88px;border-left:1px solid #fff}header ul li + li + li{border-right:none;width:89px}header ul a strong{font-size:14px;display:block;color:#222}section{width:500px;float:right;padding-bottom:50px}small{font-size:11px}hr{border:0;background:#e5e5e5;height:1px;margin:0 0 20px}footer{width:270px;float:left;position:fixed;bottom:50px}@media print, screen and (max-width: 960px){div.wrapper{width:auto;margin:0}footer,header,section{float:none;position:static;width:auto}header{padding-right:320px}section{border:1px solid #e5e5e5;border-width:1px 0;padding:20px 0;margin:0 0 20px}header a small{display:inline}header ul{position:absolute;right:50px;top:52px}}@media print, screen and (max-width: 720px){body{word-wrap:break-word}header{padding:0}header p.view,header ul{position:static}code,pre{word-wrap:normal}}@media print, screen and (max-width: 480px){body{padding:15px}header ul{display:none}}@media print{body{padding:0.4in;font-size:12pt;color:#444}}#wrapper{margin-left:auto;margin-right:auto;background-color:white}.ca-menu{list-style:none;padding:0;margin:20px auto}#navi{padding-top:15px;padding-right:15px;float:right;width:420px}#title{padding-left:15px;width:460px;float:left}div.clear{clear:both}h2{font-size:2em}h3{font-size:1.5em}h4{font-size:1.2em}h5{font-size:1em;font-weight:bold}h6{font-size:1em;font-weight:bold}h1,h2,h3,h4,h5,h6{font-weight:normal;line-height:2.5rem;margin:1rem 0}.post p{max-width:580px}ol.list,ul.list{padding-left:3.333em;max-width:580px}.post h2{border-bottom:1px solid #EDEDED}h1:nth-child(1),h2:nth-child(1),h3:nth-child(1),h4:nth-child(1),h5:nth-child(1),h6:nth-child(1){margin-top:0}body{padding:1em}#wrapper{padding:1em}@media (min-width: 43.75em){body{padding:2em}#wrapper{padding:2em}}@media (min-width: 62em){body{padding:3em}#wrapper{max-width:740px;padding:3em}}
|
||||
ol{background: #eff4f2;padding-top:20px;padding-bottom:20px;border:1px solid #e3e3ec}
|
||||
h4{background:#e0f7ed;padding:6px 12px; font-weight: bold!important;font-size:100%;margin-top:0}
|
||||
h5{text-decoration: underline}
|
||||
li.odd-even{border-top:1px solid #ccc;margin:10px 0;padding:15px 15px 10px 5px}
|
||||
li.odd-even:first-child{border:0}
|
||||
input, button {padding:5px; font-size:1em;margin-top:10px}
|
||||
ul ul {margin: 0;border: 0;padding: 5px 30px;}
|
||||
</style>
|
||||
</head>
|
||||
{% endsection %}
|
||||
|
||||
{% section "body" %}
|
||||
<body>
|
||||
{% section "body.header" %}{% endsection %}
|
||||
|
||||
{% section "header" %}{% endsection %}
|
||||
|
||||
{% section "message" %}
|
||||
{% view "lean/widget/message" %}
|
||||
{% endsection %}
|
||||
|
||||
<main role="main" class="content">
|
||||
{% section "main" %}
|
||||
<div>{{= $markdown }}</div>
|
||||
{% endsection %}
|
||||
</main>
|
||||
|
||||
<footer>{% section "footer" %}{% endsection %}</footer>
|
||||
|
||||
{% section "body.footer" %}{% endsection %}
|
||||
</body>
|
||||
{% endsection %}
|
||||
</html>
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 32 KiB |
|
@ -1,28 +1,33 @@
|
|||
<ol class="breadcrumb ">
|
||||
<li class="breadcrumb-item"><a href="{% url '' %}"><i class="fas fa-fw fa-tachometer-alt"></i> Tableau de bord</a></li>
|
||||
{% if isset($this->breadcrumb) %}
|
||||
{% php $routeTree = $this->breadcrumb->getRouteTree($this->session->get('lean.route')) %}
|
||||
|
||||
{% foreach $this->breadcrumb ?? [] as $crumb %}
|
||||
<li class="breadcrumb-item {{ ( $crumb['active'] ?? false ) ? 'active' : '' }}">
|
||||
{% if ! ($crumb['active'] ?? false) %}
|
||||
{? $last = $crumb ?}
|
||||
{% if count($routeTree) %}
|
||||
<ol class="breadcrumb mb-4 px-3 py-2">
|
||||
{% foreach $routeTree as $index => $crumb %}
|
||||
<li class="breadcrumb-item {% if $crumb->current %}active{% endif %}">
|
||||
{% if ! $crumb->current %}
|
||||
{% php $last = $crumb %}
|
||||
|
||||
<a href="{% url $crumb['url'] %}">
|
||||
{% if $crumb['icon'] ?? false %}
|
||||
<i class="fa fa-{{ $crumb['icon'] }}"></i>
|
||||
{% endif %}
|
||||
<a href="{% route $crumb->routeAnnotation->name %}">
|
||||
{% if $crumb->icon ?? false %}
|
||||
<i class="fa fa-{{ $crumb->icon }}"></i>
|
||||
{% endif %}
|
||||
|
||||
{{ $crumb['title'] }}
|
||||
</a>
|
||||
{% else %}
|
||||
{% if $crumb['icon'] ?? false %}
|
||||
<i class="fa fa-{{ $crumb['icon'] }}"></i>
|
||||
{% endif %}
|
||||
<span>{{ $crumb['title'] }}</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endforeach %}
|
||||
<span>{{ lang($crumb->lang, get_defined_vars()) }}</span>
|
||||
</a>
|
||||
{% else %}
|
||||
{% if $crumb->icon ?? false %}
|
||||
<i class="fa fa-{{ $crumb->icon }}"></i>
|
||||
{% endif %}
|
||||
|
||||
{% if $last ?? false %}
|
||||
<li class="breadcrumb-last-item ml-auto"><a href="{{ url( $last['url']) }}"><i class="fas fa-chevron-circle-left"></i> Retour</a></li>
|
||||
<span>{{ lang($crumb->lang, get_defined_vars()) }}</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endforeach %}
|
||||
|
||||
{# if $last ?? false %}
|
||||
<li class="breadcrumb-last-item ml-auto"><a href="{{ ( $last['route'] ?? false ) ? $last['route'] : url($last['url']) }}"><i class="fas fa-chevron-circle-left"></i> Retour</a></li>
|
||||
{% endif #}
|
||||
</ol>
|
||||
{% endif %}
|
||||
</ol>
|
||||
{% endif %}
|
|
@ -31,15 +31,17 @@
|
|||
{% foreach range(0, 5) as $week %}
|
||||
<div class="week">
|
||||
{% foreach range(0, 6) as $day %}
|
||||
{% php $dayType = in_array($day, [0, 6]) ? 'week-end' : 'week-day' %}
|
||||
|
||||
{% if ( $week * 6 + $day >= $index ) && ( $currentDay < $dayCount ) %}
|
||||
{% php $currentDay++; %}
|
||||
|
||||
{% slot "day.content", new \DateTime("$year-$month-$currentDay"), date("$year-$month-$currentDay") === date('Y-n-j') %}
|
||||
<div class="day-box {{ $today ? 'today' : '' }}">{{ $date->format('d') }}</div>
|
||||
<div class="day-box {{ $today ? 'today' : '' }} {{ $dayType }}">{{ $date->format('d') }}</div>
|
||||
{% endslot %}
|
||||
{% else %}
|
||||
{% slot "day.empty", $day, $month, $year %}
|
||||
<div class="day-box"></div>
|
||||
<div class="day-box {{ $dayType }}"></div>
|
||||
{% endslot %}
|
||||
{% endif %}
|
||||
{% endforeach %}
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
|
||||
<li class="page-item {{ $page === 1 ? 'active' : '' }}"><a class="page-link" href="{% url.parameters $url, [ 'page' => 1 ] + get() %}">1</a></li>
|
||||
|
||||
{% foreach range(2, $pageCount < $maxPage ? $pageCount : $maxPage) as $pageIndex %}
|
||||
<li class="page-item {{ $page === $pageIndex ? 'active' : '' }}"><a class="page-link" href="{% url.parameters $url, [ 'page' => $pageIndex ] + get() %}">{{ $pageIndex }}</a></li>
|
||||
{% endforeach %}
|
||||
{% if $pageCount > 1%}
|
||||
{% foreach range(2, $pageCount < $maxPage ? $pageCount : $maxPage) as $pageIndex %}
|
||||
<li class="page-item {{ $page === $pageIndex ? 'active' : '' }}"><a class="page-link" href="{% url.parameters $url, [ 'page' => $pageIndex ] + get() %}">{{ $pageIndex }}</a></li>
|
||||
{% endforeach %}
|
||||
{% endif %}
|
||||
|
||||
<li class="page-item {{ $page === $pageCount ? 'disabled' : '' }}"><a class="page-link" href="{% url.parameters $url, [ 'page' => $page + 1 ] + get() %}">{% lang "lean.widget.pagination.next" %}</a></li>
|
||||
</ul>
|
||||
|
|
Loading…
Reference in New Issue