Premiere mouture application - Suppression fichiers inutiles
|
@ -0,0 +1,4 @@
|
|||
config/config.php
|
||||
.idea
|
||||
tmp
|
||||
composer.lock
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "nox/gmarche",
|
||||
"authors": [
|
||||
{
|
||||
"name": "nox",
|
||||
"email": "nox@axiom-team.fr"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Framework\\": "src/Framework",
|
||||
"App\\": "src",
|
||||
"Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/psr7": "^1.4",
|
||||
"http-interop/response-sender": "^1.0",
|
||||
"zendframework/zend-expressive-fastroute": "^2.0",
|
||||
"twig/twig": "^2.4",
|
||||
"php-di/php-di": "^5.4",
|
||||
"pagerfanta/pagerfanta": "^2.1",
|
||||
"middlewares/whoops": "0.4.1",
|
||||
"doctrine/cache": "1.4",
|
||||
"intervention/image": "2.4",
|
||||
"swiftmailer/swiftmailer": "^6.0",
|
||||
"ramsey/uuid": "^3.7"
|
||||
},
|
||||
"require-dev": {
|
||||
"squizlabs/php_codesniffer": "^3.0",
|
||||
"phpunit/phpunit": "^6.2",
|
||||
"robmorgan/phinx": "0.8.1",
|
||||
"fzaninotto/faker": "^1.8"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
return [
|
||||
'gmarche.prefix' => '/news'
|
||||
];
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
use App\Framework\Twig\UrlExtension;
|
||||
use Framework\Middleware\CsrfMiddleware;
|
||||
use Framework\Renderer\RendererInterface;
|
||||
use Framework\Renderer\TwigRendererFactory;
|
||||
use Framework\Router;
|
||||
use Framework\Router\RouterFactory;
|
||||
use Framework\Router\RouterTwigExtension;
|
||||
use Framework\Session\PHPSession;
|
||||
use Framework\Session\SessionInterface;
|
||||
use Framework\Twig\{
|
||||
CsrfExtension, FlashExtension, FormExtension, PagerFantaExtension, TextExtension, TimeExtension
|
||||
};
|
||||
|
||||
return [
|
||||
'env' => \DI\env('ENV', 'production'),
|
||||
/*'env' => \DI\env('ENV', 'development'),*/
|
||||
'database.host' => 'localhost',
|
||||
'database.username' => 'root',
|
||||
'database.password' => '',
|
||||
'database.name' => 'gmarche',
|
||||
'views.path' => dirname(__DIR__) . '/views',
|
||||
'twig.extensions' => [
|
||||
\DI\get(RouterTwigExtension::class),
|
||||
\DI\get(PagerFantaExtension::class),
|
||||
\DI\get(TextExtension::class),
|
||||
\DI\get(TimeExtension::class),
|
||||
\DI\get(FlashExtension::class),
|
||||
\DI\get(FormExtension::class),
|
||||
\DI\get(CsrfExtension::class),
|
||||
\DI\get(UrlExtension::class)
|
||||
],
|
||||
SessionInterface::class => \DI\object(PHPSession::class),
|
||||
CsrfMiddleware::class => \DI\object()->constructor(\DI\get(SessionInterface::class)),
|
||||
Router::class => \DI\factory(RouterFactory::class),
|
||||
RendererInterface::class => \DI\factory(TwigRendererFactory::class),
|
||||
\PDO::class => function (\Psr\Container\ContainerInterface $c) {
|
||||
return new PDO(
|
||||
'mysql:host='. $c->get('database.host') . ';dbname=' . $c->get('database.name'),
|
||||
$c->get('database.username'),
|
||||
$c->get('database.password'),
|
||||
[
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
|
||||
]
|
||||
);
|
||||
},
|
||||
// MAILER
|
||||
'mail.to' => 'admin@gmarche-testmail.com',
|
||||
'mail.from' => 'no-reply@admin.fr',
|
||||
Swift_Mailer::class => \DI\factory(\Framework\SwiftMailerFactory::class)
|
||||
];
|
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="App\" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="false" packagePrefix="Tests\" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/Framework" isTestSource="false" packagePrefix="Framework\" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/container-interop/container-interop" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/instantiator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/lexer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/egulias/email-validator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/fig/http-message-util" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/filp/whoops" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/fzaninotto/faker" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/psr7" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/http-interop/http-factory" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/http-interop/http-middleware" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/http-interop/response-sender" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/intervention/image" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/middlewares/utils" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/middlewares/whoops" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/myclabs/deep-copy" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/nikic/fast-route" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/pagerfanta/pagerfanta" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/paragonie/random_compat" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/manifest" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/version" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/php-di/invoker" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/php-di/php-di" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/php-di/phpdoc-reader" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/reflection-common" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/reflection-docblock" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/type-resolver" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpspec/prophecy" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-code-coverage" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-file-iterator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-text-template" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-timer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-token-stream" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/phpunit" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/phpunit-mock-objects" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/container" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-message" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/log" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/ralouphie/getallheaders" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/ramsey/uuid" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/robmorgan/phinx" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/comparator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/diff" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/environment" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/exporter" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/global-state" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-enumerator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-reflector" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/recursion-context" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/resource-operations" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/version" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/squizlabs/php_codesniffer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/swiftmailer/swiftmailer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/config" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/debug" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/filesystem" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-ctype" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-iconv" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-idn" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-mbstring" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php72" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/yaml" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/theseer/tokenizer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/twig/twig" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/webimpress/composer-extra-dependency" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/webimpress/http-middleware-compatibility" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/webmozart/assert" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/zendframework/zend-expressive-fastroute" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/zendframework/zend-expressive-router" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/zendframework/zend-stdlib" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
require 'public/index.php';
|
||||
$migrations = [];
|
||||
$seeds = [];
|
||||
foreach ($app->getModules() as $module) {
|
||||
if ($module::MIGRATIONS) {
|
||||
$migrations[] = $module::MIGRATIONS;
|
||||
}
|
||||
if ($module::SEEDS) {
|
||||
$seeds[] = $module::SEEDS;
|
||||
}
|
||||
}
|
||||
return [
|
||||
'paths' => [
|
||||
'migrations' => $migrations,
|
||||
'seeds' => $seeds
|
||||
],
|
||||
'environments' => [
|
||||
'default_database' => 'development',
|
||||
'development' => [
|
||||
'adapter' => 'mysql',
|
||||
'host' => $app->getContainer()->get('database.host'),
|
||||
'name' => $app->getContainer()->get('database.name'),
|
||||
'user' => $app->getContainer()->get('database.username'),
|
||||
'pass' => $app->getContainer()->get('database.password')
|
||||
]
|
||||
]
|
||||
];
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" ?>
|
||||
<ruleset name="MonFramework">
|
||||
<description>Mes règles de formattage</description>
|
||||
|
||||
<arg name="colors"/>
|
||||
<arg value="p"/>
|
||||
|
||||
<file>src</file>
|
||||
<file>public/index.php</file>
|
||||
|
||||
<rule ref="PSR2">
|
||||
<exclude name="PSR1.Classes.ClassDeclaration.MissingNamespace"/>
|
||||
</rule>
|
||||
</ruleset>
|
|
@ -0,0 +1,7 @@
|
|||
<phpunit bootstrap="./vendor/autoload.php">
|
||||
<testsuites>
|
||||
<testsuite name="Framework">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
After Width: | Height: | Size: 704 B |
|
@ -0,0 +1,199 @@
|
|||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
btn-custom {
|
||||
background-color: hsl(0, 0%, 79%) !important;
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#134134134", endColorstr="#c9c9c9");
|
||||
background-image: -khtml-gradient(linear, left top, left bottom, from(#134134134), to(#c9c9c9));
|
||||
background-image: -moz-linear-gradient(top, #134134134, #c9c9c9);
|
||||
background-image: -ms-linear-gradient(top, #134134134, #c9c9c9);
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #134134134), color-stop(100%, #c9c9c9));
|
||||
background-image: -webkit-linear-gradient(top, #134134134, #c9c9c9);
|
||||
background-image: -o-linear-gradient(top, #134134134, #c9c9c9);
|
||||
background-image: linear-gradient(#134134134, #c9c9c9);
|
||||
border-color: #c9c9c9 #c9c9c9 hsl(0, 0%, 68.5%);
|
||||
color: #333 !important;
|
||||
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.69);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
a :hover {
|
||||
background-color: lightgreen;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style-type: none;
|
||||
text-color: black;
|
||||
}
|
||||
.liste_regions, .liste_antennes {
|
||||
background-color: lightblue;
|
||||
}
|
||||
|
||||
.fond {
|
||||
background-image: url("../images/bildreich_1275.jpg");
|
||||
background-repeat: no-repeat;
|
||||
background-attachment:fixed;
|
||||
background-position: center;
|
||||
background-size: 100% auto;
|
||||
font-family: Bree serif,"Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 18px;
|
||||
}
|
||||
header.header {
|
||||
width: 389px;
|
||||
height: 259px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
header.header img {
|
||||
width: 389px;
|
||||
height: 259px;
|
||||
}
|
||||
.logo_toile img, .logo_june img {
|
||||
transition: transform .5s;
|
||||
}
|
||||
.logo_toile img:hover, .logo_june img:hover {
|
||||
transform: scale(1.1) rotate(10deg);
|
||||
}
|
||||
.post-header {
|
||||
width: 820px;
|
||||
height: 80px;
|
||||
margin: 0 auto;
|
||||
color: white;
|
||||
opacity: 0.9;
|
||||
font-family: Bree serif, Arial;
|
||||
font-size: 26px;
|
||||
}
|
||||
#la_page {
|
||||
text-align: center;
|
||||
width: 1174px;
|
||||
min-height: 901px;
|
||||
height:auto;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.article {
|
||||
width:auto;
|
||||
height:auto;
|
||||
font-size: 24px;
|
||||
}
|
||||
.article2 {
|
||||
width:auto;
|
||||
height:auto;
|
||||
font-size: 24px;
|
||||
}
|
||||
.container {
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
.records_content th, .records_content2 th{
|
||||
background-color: lightgray;
|
||||
color: rgba(0,0,0,0.85);
|
||||
}
|
||||
.footer {
|
||||
width:105px;
|
||||
margin: 5px auto;
|
||||
text-align: center;
|
||||
}
|
||||
/******************************************************************/
|
||||
/* POUR MOBILES */
|
||||
/******************************************************************/
|
||||
@media only screen and (max-width:560px) {
|
||||
|
||||
.fond {
|
||||
background-color: black;
|
||||
background-image: url("../toureiffel.jpeg");
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-position: left;
|
||||
background-size: cover;
|
||||
}
|
||||
.post-header {
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin-left: 10px;
|
||||
}
|
||||
#la_page {
|
||||
width: auto;
|
||||
height:auto;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.article {
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.article2 {
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.container button{
|
||||
float: left;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
/* Tableaux responsives */
|
||||
/**************************************/
|
||||
.table-responsive table,
|
||||
.table-responsive thead,
|
||||
.table-responsive tbody,
|
||||
.table-responsive tr,
|
||||
.table-responsive th,
|
||||
.table-responsive td {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.table-responsive thead {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.table-responsive td {
|
||||
padding-left: 95px !important;
|
||||
position: relative;
|
||||
margin-top: -1px;
|
||||
background: #FFF;
|
||||
}
|
||||
.table-responsive td button{
|
||||
margin-top:-7px;
|
||||
max-height: 30px;
|
||||
}
|
||||
.table-responsive td:nth-child(odd) {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.table-responsive td::before {
|
||||
padding: 10px;
|
||||
content: attr(data-label);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 85px;
|
||||
bottom: 0;
|
||||
background-color: #000;
|
||||
color: #FFF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.table-responsive tr {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.table-responsive th + td {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
}
|
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 377 KiB |
After Width: | Height: | Size: 110 KiB |
After Width: | Height: | Size: 211 KiB |
After Width: | Height: | Size: 203 KiB |
After Width: | Height: | Size: 171 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 248 KiB |
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
ini_set('display_errors',0);
|
||||
use App\Account\AccountModule;
|
||||
use App\Admin\AdminModule;
|
||||
use App\Auth\AuthModule;
|
||||
use App\Contact\ContactModule;
|
||||
use App\Gmarche\GmarcheModule;
|
||||
use App\Product\ProductModule;
|
||||
use Framework\Auth\RoleMiddlewareFactory;
|
||||
use Framework\Middleware\{
|
||||
CsrfMiddleware,
|
||||
DispatcherMiddleware,
|
||||
MethodMiddleware,
|
||||
RendererRequestMiddleware,
|
||||
RouterMiddleware,
|
||||
TrailingSlashMiddleware,
|
||||
NotFoundMiddleware
|
||||
};
|
||||
use GuzzleHttp\Psr7\ServerRequest;
|
||||
use Middlewares\Whoops;
|
||||
|
||||
chdir(dirname(__DIR__));
|
||||
require 'vendor/autoload.php';
|
||||
$chemin = $_SERVER['DOCUMENT_ROOT'];
|
||||
$chemin_new = substr($chemin,0,-7);
|
||||
$app = (new \Framework\App( $chemin_new .'/config/config.php'))
|
||||
//$app = (new \Framework\App( '../config/config.php'))
|
||||
->addModule(AdminModule::class)
|
||||
->addModule(ContactModule::class)
|
||||
->addModule(ProductModule::class)
|
||||
->addModule(GmarcheModule::class)
|
||||
->addModule(AuthModule::class)
|
||||
->addModule(AccountModule::class);
|
||||
|
||||
|
||||
$container = $app->getContainer();
|
||||
|
||||
// Pose problème
|
||||
$container->get(\Framework\Router::class)->get('/', \App\Gmarche\Actions\RegionIndexAction::class, 'home');
|
||||
|
||||
$app->pipe(Whoops::class);
|
||||
$app->pipe(TrailingSlashMiddleware::class);
|
||||
$app->pipe(\App\Auth\ForbiddenMiddleware::class);
|
||||
|
||||
// admin pose problème
|
||||
//$app->pipe(
|
||||
// $container->get('admin.prefix'),
|
||||
// $container->get(RoleMiddlewareFactory::class)->makeForRole('admin')
|
||||
// );
|
||||
|
||||
$app->pipe(MethodMiddleware::class)
|
||||
->pipe(RendererRequestMiddleware::class)
|
||||
// ->pipe(CsrfMiddleware::class)
|
||||
->pipe(RouterMiddleware::class)
|
||||
->pipe(DispatcherMiddleware::class)
|
||||
->pipe(NotFoundMiddleware::class);
|
||||
|
||||
|
||||
if (php_sapi_name() !== "cli") {
|
||||
$response = $app->run(ServerRequest::fromGlobals());
|
||||
\Http\Response\send($response);
|
||||
}
|
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 106 KiB |
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
namespace App\Account;
|
||||
|
||||
use App\Account\Action\AccountAction;
|
||||
use App\Account\Action\AccountEditAction;
|
||||
use App\Account\Action\SignupAction;
|
||||
use Framework\Auth\LoggedInMiddleware;
|
||||
use Framework\Module;
|
||||
use Framework\Renderer\RendererInterface;
|
||||
use Framework\Router;
|
||||
|
||||
class AccountModule extends Module
|
||||
{
|
||||
|
||||
const MIGRATIONS = __DIR__ . '/migrations';
|
||||
|
||||
const DEFINITIONS = __DIR__ . '/definitions.php';
|
||||
|
||||
public function __construct(Router $router, RendererInterface $renderer)
|
||||
{
|
||||
$renderer->addPath('account', __DIR__ . '/views');
|
||||
$router->get('/inscription', SignupAction::class, 'account.signup');
|
||||
$router->post('/inscription', SignupAction::class);
|
||||
$router->get('/mon-profil', [LoggedInMiddleware::class, AccountAction::class], 'account');
|
||||
$router->post('/mon-profil', [LoggedInMiddleware::class, AccountEditAction::class]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
namespace App\Account\Action;
|
||||
|
||||
use Framework\Auth;
|
||||
use Framework\Renderer\RendererInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class AccountAction
|
||||
{
|
||||
|
||||
/**
|
||||
* @var RendererInterface
|
||||
*/
|
||||
private $renderer;
|
||||
/**
|
||||
* @var Auth
|
||||
*/
|
||||
private $auth;
|
||||
|
||||
public function __construct(
|
||||
RendererInterface $renderer,
|
||||
Auth $auth
|
||||
) {
|
||||
|
||||
$this->renderer = $renderer;
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request)
|
||||
{
|
||||
$user = $this->auth->getUser();
|
||||
return $this->renderer->render('@account/account', compact('user'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
namespace App\Account\Action;
|
||||
|
||||
use App\Auth\UserTable;
|
||||
use Framework\Auth;
|
||||
use Framework\Renderer\RendererInterface;
|
||||
use Framework\Response\RedirectResponse;
|
||||
use Framework\Session\FlashService;
|
||||
use Framework\Validator;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class AccountEditAction
|
||||
{
|
||||
|
||||
/**
|
||||
* @var RendererInterface
|
||||
*/
|
||||
private $renderer;
|
||||
/**
|
||||
* @var Auth
|
||||
*/
|
||||
private $auth;
|
||||
/**
|
||||
* @var FlashService
|
||||
*/
|
||||
private $flashService;
|
||||
/**
|
||||
* @var UserTable
|
||||
*/
|
||||
private $userTable;
|
||||
|
||||
public function __construct(
|
||||
RendererInterface $renderer,
|
||||
Auth $auth,
|
||||
FlashService $flashService,
|
||||
UserTable $userTable
|
||||
) {
|
||||
|
||||
$this->renderer = $renderer;
|
||||
$this->auth = $auth;
|
||||
$this->flashService = $flashService;
|
||||
$this->userTable = $userTable;
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request)
|
||||
{
|
||||
$user = $this->auth->getUser();
|
||||
$params = $request->getParsedBody();
|
||||
$validator = (new Validator($params))
|
||||
->confirm('password')
|
||||
->required('firstname', 'lastname');
|
||||
if ($validator->isValid()) {
|
||||
$userParams = [
|
||||
'firstname' => $params['firstname'],
|
||||
'lastname' => $params['lastname']
|
||||
];
|
||||
if (!empty($params['password'])) {
|
||||
$userParams['password'] = password_hash($params['password'], PASSWORD_DEFAULT);
|
||||
}
|
||||
$this->userTable->update($user->id, $userParams);
|
||||
$this->flashService->success('Votre compte a bien été mis à jour');
|
||||
return new RedirectResponse($request->getUri()->getPath());
|
||||
}
|
||||
$errors = $validator->getErrors();
|
||||
return $this->renderer->render('@account/account', compact('user', 'errors'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
namespace App\Account\Action;
|
||||
|
||||
use App\Auth\DatabaseAuth;
|
||||
use App\Auth\User;
|
||||
use App\Auth\UserTable;
|
||||
use Framework\Database\Hydrator;
|
||||
use Framework\Renderer\RendererInterface;
|
||||
use Framework\Response\RedirectResponse;
|
||||
use Framework\Router;
|
||||
use Framework\Session\FlashService;
|
||||
use Framework\Validator;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class SignupAction
|
||||
{
|
||||
|
||||
/**
|
||||
* @var RendererInterface
|
||||
*/
|
||||
private $renderer;
|
||||
/**
|
||||
* @var UserTable
|
||||
*/
|
||||
private $userTable;
|
||||
/**
|
||||
* @var Router
|
||||
*/
|
||||
private $router;
|
||||
/**
|
||||
* @var DatabaseAuth
|
||||
*/
|
||||
private $auth;
|
||||
/**
|
||||
* @var FlashService
|
||||
*/
|
||||
private $flashService;
|
||||
|
||||
public function __construct(
|
||||
RendererInterface $renderer,
|
||||
UserTable $userTable,
|
||||
Router $router,
|
||||
DatabaseAuth $auth,
|
||||
FlashService $flashService
|
||||
) {
|
||||
$this->renderer = $renderer;
|
||||
$this->userTable = $userTable;
|
||||
$this->router = $router;
|
||||
$this->auth = $auth;
|
||||
$this->flashService = $flashService;
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request)
|
||||
{
|
||||
if ($request->getMethod() === 'GET') {
|
||||
return $this->renderer->render('@account/signup');
|
||||
}
|
||||
$params = $request->getParsedBody();
|
||||
$validator = (new Validator($params))
|
||||
->required('username', 'email', 'password', 'password_confirm', 'firstname', 'lastname', 'created_at')
|
||||
->length('username', 3)
|
||||
->length('firstname', 2)
|
||||
->length('lastname', 2)
|
||||
->email('email')
|
||||
->confirm('password')
|
||||
->length('password', 4)
|
||||
->unique('username', $this->userTable)
|
||||
->unique('email', $this->userTable);
|
||||
if ($validator->isValid()) {
|
||||
$userParams = [
|
||||
'username' => $params['username'],
|
||||
'firstname'=> $params['firstname'],
|
||||
'lastname'=> $params['lastname'],
|
||||
'email' => $params['email'],
|
||||
'password' => password_hash($params['password'], PASSWORD_DEFAULT),
|
||||
'created_at' => $params['created_at'],
|
||||
'role' => 'user'
|
||||
];
|
||||
$this->userTable->insert($userParams);
|
||||
$user = Hydrator::hydrate($userParams, User::class);
|
||||
$user->id = $this->userTable->getPdo()->lastInsertId();
|
||||
$this->auth->setUser($user);
|
||||
$this->flashService->success('Votre compte a bien été créé');
|
||||
return new RedirectResponse($this->router->generateUri('account'));
|
||||
}
|
||||
$errors = $validator->getErrors();
|
||||
return $this->renderer->render('@account/signup', [
|
||||
'errors' => $errors,
|
||||
'user' => [
|
||||
'username' => $params['username'],
|
||||
'email' => $params['email'],
|
||||
'firstname'=> $params['firstname'],
|
||||
'lastname'=> $params['lastname'],
|
||||
'created_at' => $params['created_at']
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
namespace App\Account;
|
||||
|
||||
class User extends \App\Auth\User
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $firstname;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $lastname;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $role;
|
||||
|
||||
public function getRoles(): array
|
||||
{
|
||||
return [$this->role];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFirstname(): string
|
||||
{
|
||||
return $this->firstname;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $firstname
|
||||
*/
|
||||
public function setFirstname(string $firstname)
|
||||
{
|
||||
$this->firstname = $firstname;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLastname(): string
|
||||
{
|
||||
return $this->lastname;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $lastname
|
||||
*/
|
||||
public function setLastname(string $lastname)
|
||||
{
|
||||
$this->lastname = $lastname;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRole()
|
||||
{
|
||||
return $this->role;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $role
|
||||
*/
|
||||
public function setRole($role)
|
||||
{
|
||||
$this->role = $role;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
return [
|
||||
'auth.entity' => \App\Account\User::class
|
||||
];
|
|
@ -0,0 +1,18 @@
|
|||
{% extends 'layout.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<div class="container" style="background-color: lightgray;opacity: 0.9;margin: 1rem;padding:1rem;">
|
||||
<h2>Mon compte</h2>
|
||||
<form action="" method="post">
|
||||
{{ csrf_input() }}
|
||||
{{ field('firstname', user.firstname, 'Prénom') }}
|
||||
{{ field('lastname', user.lastname, 'Nom') }}
|
||||
<h2>Changer de mot de passe</h2>
|
||||
<p>Laissez vide pour ne rien changer</p>
|
||||
{{ field('password', null, 'Mot de passe', {type: 'password'}) }}
|
||||
{{ field('password_confirm', null, 'Confirmer le mot de passe', {type: 'password'}) }}
|
||||
<button class="btn btn-primary">Modifier mes informations</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,16 @@
|
|||
{% extends 'layout.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<div class="container" style="background-color: lightgray;opacity: 0.9;margin: 1rem;padding:1rem;">
|
||||
<form action="{{ path('account.signup') }}" method="post">
|
||||
{{ csrf_input() }}
|
||||
{{ field('username', user.username, "Pseudo") }}
|
||||
{{ field('firstname', user.firstname, "Prénom") }} {{ field('lastname', user.lastname, "Nom") }}
|
||||
{{ field('email', user.email, "Email", {type: 'email'}) }}
|
||||
{{ field('password', null, "Mot de passe", {type: 'password'}) }}
|
||||
{{ field('password_confirm', null, "Confirmez le mot de passe", {type: 'password'}) }}
|
||||
{{ field('created_at', date(), null, {type: 'hidden'}) }}
|
||||
<button class="btn btn-primary">S'inscrire</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin;
|
||||
|
||||
use App\Product\Actions\ProductIndexAction;
|
||||
use App\Product\Actions\ProductCrudAction;
|
||||
use Framework\Module;
|
||||
use Framework\Renderer\RendererInterface;
|
||||
use Framework\Renderer\TwigRenderer;
|
||||
use Framework\Router;
|
||||
|
||||
class AdminModule extends Module
|
||||
{
|
||||
|
||||
const DEFINITIONS = __DIR__ . '/config.php';
|
||||
|
||||
public function __construct(
|
||||
RendererInterface $renderer,
|
||||
Router $router,
|
||||
AdminTwigExtension $adminTwigExtension,
|
||||
string $prefix
|
||||
) {
|
||||
|
||||
$renderer->addPath('admin', __DIR__ . '/views');
|
||||
|
||||
//$router->get('/machin', ProductCrudAction::class, 'machin.bidule'); // ProductIndexAction
|
||||
/*if ($renderer instanceof TwigRenderer) {
|
||||
$renderer->getTwig()->addExtension($adminTwigExtension);
|
||||
}*/
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
namespace App\Admin;
|
||||
|
||||
class AdminTwigExtension extends \Twig_Extension
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $widgets;
|
||||
|
||||
public function __construct(array $widgets)
|
||||
{
|
||||
$this->widgets = $widgets;
|
||||
}
|
||||
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFunction('admin_menu', [$this, 'renderMenu'], ['is_safe' => ['html']])
|
||||
];
|
||||
}
|
||||
|
||||
public function renderMenu(): string
|
||||
{
|
||||
return array_reduce($this->widgets, function (string $html, AdminWidgetInterface $widget) {
|
||||
return $html . $widget->renderMenu();
|
||||
}, '');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
namespace App\Admin;
|
||||
|
||||
interface AdminWidgetInterface
|
||||
{
|
||||
|
||||
public function render(): string;
|
||||
|
||||
public function renderMenu(): string;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
use App\Admin\AdminModule;
|
||||
use App\Admin\DashboardAction;
|
||||
|
||||
return [
|
||||
'admin.prefix' => '/admin',
|
||||
'admin.widgets' => [],
|
||||
\App\Admin\AdminTwigExtension::class => \DI\object()->constructor(\DI\get('admin.widgets')),
|
||||
AdminModule::class => \DI\object()->constructorParameter('prefix', \DI\get('admin.prefix'))
|
||||
//DashboardAction::class => \DI\object()->constructorParameter('widgets', \DI\get('admin.widgets'))
|
||||
];
|
|
@ -0,0 +1,60 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{% block title "Mon site " %}</title>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/3.0.7/flatpickr.css">
|
||||
<style>
|
||||
body {
|
||||
padding-top: 5rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="navbar fixed-top navbar-expand-sm navbar-dark bg-dark">
|
||||
<a class="navbar-brand" href="{{ path(routePrefix) }}">Ğ1-Marché</a>
|
||||
|
||||
<ul class="navbar-nav mr-auto">
|
||||
{{ admin_menu() }}
|
||||
</ul>
|
||||
<div class="navbar-nav">
|
||||
<form class="nav-item active" method="post" action="{{ path('auth.logout') }}">
|
||||
{{ csrf_input() }}
|
||||
<button class="btn-primary btn-danger">Se déconnecter</button>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
|
||||
{% if flash('success') %}
|
||||
<div class="alert alert-success">
|
||||
{{ flash('success') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if flash('error') %}
|
||||
<div class="alert alert-danger">
|
||||
{{ flash('error') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% block body %}{% endblock %}
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/3.0.7/flatpickr.js"></script>
|
||||
<script>
|
||||
flatpickr('.datepicker', {
|
||||
enableTime: true,
|
||||
altInput: true,
|
||||
altFormat: 'j F Y, H:i',
|
||||
dateFormat: 'Y-m-d H:i:S'
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
namespace App\Auth\Action;
|
||||
|
||||
use Framework\Renderer\RendererInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class LoginAction
|
||||
{
|
||||
|
||||
/**
|
||||
* @var RendererInterface
|
||||
*/
|
||||
private $renderer;
|
||||
|
||||
public function __construct(RendererInterface $renderer)
|
||||
{
|
||||
$this->renderer = $renderer;
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request)
|
||||
{
|
||||
return $this->renderer->render('@auth/login');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
namespace App\Auth\Action;
|
||||
|
||||
use App\Auth\DatabaseAuth;
|
||||
use Framework\Actions\RouterAwareAction;
|
||||
use Framework\Renderer\RendererInterface;
|
||||
use Framework\Response\RedirectResponse;
|
||||
use Framework\Router;
|
||||
use Framework\Session\FlashService;
|
||||
use Framework\Session\SessionInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Zend\Expressive\Router\RouterInterface;
|
||||
|
||||
class LoginAttemptAction
|
||||
{
|
||||
|
||||
/**
|
||||
* @var RendererInterface
|
||||
*/
|
||||
private $renderer;
|
||||
/**
|
||||
* @var DatabaseAuth
|
||||
*/
|
||||
private $auth;
|
||||
/**
|
||||
* @var SessionInterface
|
||||
*/
|
||||
private $session;
|
||||
/**
|
||||
* @var RouterInterface
|
||||
*/
|
||||
private $router;
|
||||
|
||||
use RouterAwareAction;
|
||||
|
||||
public function __construct(
|
||||
RendererInterface $renderer,
|
||||
DatabaseAuth $auth,
|
||||
Router $router,
|
||||
SessionInterface $session
|
||||
) {
|
||||
|
||||
$this->renderer = $renderer;
|
||||
$this->auth = $auth;
|
||||
$this->router = $router;
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request)
|
||||
{
|
||||
$params = $request->getParsedBody();
|
||||
$user = $this->auth->login($params['username'], $params['password']);
|
||||
if ($user) {
|
||||
$path = $this->session->get('auth.redirect') ?: $this->router->generateUri('gmarche.index');
|
||||
$this->session->delete('auth.redirect');
|
||||
return new RedirectResponse($path);
|
||||
} else {
|
||||
(new FlashService($this->session))->error('Identifiant ou mot de passe incorrect');
|
||||
return $this->redirect('auth.login');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
namespace App\Auth\Action;
|
||||
|
||||
use App\Auth\DatabaseAuth;
|
||||
use Framework\Renderer\RendererInterface;
|
||||
use Framework\Response\RedirectResponse;
|
||||
use Framework\Session\FlashService;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class LogoutAction
|
||||
{
|
||||
|
||||
/**
|
||||
* @var RendererInterface
|
||||
*/
|
||||
private $renderer;
|
||||
/**
|
||||
* @var DatabaseAuth
|
||||
*/
|
||||
private $auth;
|
||||
/**
|
||||
* @var FlashService
|
||||
*/
|
||||
private $flashService;
|
||||
|
||||
public function __construct(RendererInterface $renderer, DatabaseAuth $auth, FlashService $flashService)
|
||||
{
|
||||
$this->renderer = $renderer;
|
||||
$this->auth = $auth;
|
||||
$this->flashService = $flashService;
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request)
|
||||
{
|
||||
$this->auth->logout();
|
||||
$this->flashService->success('Vous êtes maintenant déconnecté');
|
||||
return new RedirectResponse('/gmarche');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
namespace App\Auth\Action;
|
||||
|
||||
use App\Auth\Mailer\PasswordResetMailer;
|
||||
use App\Auth\UserTable;
|
||||
use Framework\Database\NoRecordException;
|
||||
use Framework\Renderer\RendererInterface;
|
||||
use Framework\Response\RedirectResponse;
|
||||
use Framework\Session\FlashService;
|
||||
use Framework\Validator;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class PasswordForgetAction
|
||||
{
|
||||
|
||||
/**
|
||||
* @var RendererInterface
|
||||
*/
|
||||
private $renderer;
|
||||
/**
|
||||
* @var UserTable
|
||||
*/
|
||||
private $userTable;
|
||||
/**
|
||||
* @var PasswordResetMailer
|
||||
*/
|
||||
private $mailer;
|
||||
/**
|
||||
* @var FlashService
|
||||
*/
|
||||
private $flashService;
|
||||
|
||||
public function __construct(
|
||||
RendererInterface $renderer,
|
||||
UserTable $userTable,
|
||||
PasswordResetMailer $mailer,
|
||||
FlashService $flashService
|
||||
) {
|
||||
|
||||
$this->renderer = $renderer;
|
||||
$this->userTable = $userTable;
|
||||
$this->mailer = $mailer;
|
||||
$this->flashService = $flashService;
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request)
|
||||
{
|
||||
if ($request->getMethod() === 'GET') {
|
||||
return $this->renderer->render('@auth/password');
|
||||
}
|
||||
$params = $request->getParsedBody();
|
||||
$validator = (new Validator($params))
|
||||
->notEmpty('email')
|
||||
->email('email');
|
||||
if ($validator->isValid()) {
|
||||
try {
|
||||
$user = $this->userTable->findBy('email', $params['email']);
|
||||
$token = $this->userTable->resetPassword($user->id);
|
||||
$this->mailer->send($user->email, [
|
||||
'id' => $user->id,
|
||||
'token' => $token
|
||||
]);
|
||||
$this->flashService->success('Un email vous a été envoyé');
|
||||
return new RedirectResponse($request->getUri()->getPath());
|
||||
} catch (NoRecordException $e) {
|
||||
$errors = ['email' => 'Aucun utilisateur ne correspon à cet email'];
|
||||
}
|
||||
} else {
|
||||
$errors = $validator->getErrors();
|
||||
}
|
||||
return $this->renderer->render('@auth/password', compact('errors'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
namespace App\Auth\Action;
|
||||
|
||||
use App\Auth\User;
|
||||
use App\Auth\UserTable;
|
||||
use Framework\Renderer\RendererInterface;
|
||||
use Framework\Response\RedirectResponse;
|
||||
use Framework\Router;
|
||||
use Framework\Session\FlashService;
|
||||
use Framework\Validator;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class PasswordResetAction
|
||||
{
|
||||
|
||||
/**
|
||||
* @var RendererInterface
|
||||
*/
|
||||
private $renderer;
|
||||
/**
|
||||
* @var UserTable
|
||||
*/
|
||||
private $userTable;
|
||||
/**
|
||||
* @var Router
|
||||
*/
|
||||
private $router;
|
||||
/**
|
||||
* @var FlashService
|
||||
*/
|
||||
private $flashService;
|
||||
|
||||
public function __construct(
|
||||
RendererInterface $renderer,
|
||||
UserTable $userTable,
|
||||
FlashService $flashService,
|
||||
Router $router
|
||||
) {
|
||||
|
||||
$this->renderer = $renderer;
|
||||
$this->userTable = $userTable;
|
||||
$this->router = $router;
|
||||
$this->flashService = $flashService;
|
||||
}
|
||||
|
||||
public function __invoke(ServerRequestInterface $request)
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->userTable->find($request->getAttribute('id'));
|
||||
if ($user->getPasswordReset() !== null &&
|
||||
$user->getPasswordReset() === $request->getAttribute('token') &&
|
||||
time() - $user->getPasswordResetAt()->getTimestamp() < 600
|
||||
) {
|
||||
if ($request->getMethod() === 'GET') {
|
||||
return $this->renderer->render('@auth/reset');
|
||||
} else {
|
||||
$params = $request->getParsedBody();
|
||||
$validator = (new Validator($params))
|
||||
->length('password', 4)
|
||||
->confirm('password');
|
||||
if ($validator->isValid()) {
|
||||
$this->userTable->updatePassword($user->getId(), $params['password']);
|
||||
$this->flashService->success('Votre mot de passe a bien été changé');
|
||||
return new RedirectResponse($this->router->generateUri('auth.login'));
|
||||
} else {
|
||||
$errors = $validator->getErrors();
|
||||
return $this->renderer->render('@auth/reset', compact('errors'));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->flashService->error('Token invalid');
|
||||
return new RedirectResponse($this->router->generateUri('auth.password'));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
namespace App\Auth;
|
||||
|
||||
use App\Auth\Action\LoginAction;
|
||||
use App\Auth\Action\LoginAttemptAction;
|
||||
use App\Auth\Action\LogoutAction;
|
||||
use App\Auth\Action\PasswordForgetAction;
|
||||
use App\Auth\Action\PasswordResetAction;
|
||||
use Framework\Module;
|
||||
use Framework\Renderer\RendererInterface;
|
||||
use Framework\Router;
|
||||
use Framework\Router\Route;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
class AuthModule extends Module
|
||||
{
|
||||
|
||||
const DEFINITIONS = __DIR__ . '/config.php';
|
||||
|
||||
const MIGRATIONS = __DIR__ . '/db/migrations';
|
||||
|
||||
const SEEDS = __DIR__ . '/db/seeds';
|
||||
|
||||
public function __construct(ContainerInterface $container, Router $router, RendererInterface $renderer)
|
||||
{
|
||||
$renderer->addPath('auth', __DIR__ . '/views');
|
||||
$router->get($container->get('auth.login'), LoginAction::class, 'auth.login');
|
||||
$router->post($container->get('auth.login'), LoginAttemptAction::class);
|
||||
$router->post('/logout', LogoutAction::class, 'auth.logout');
|
||||
$router->any('/password', PasswordForgetAction::class, 'auth.password');
|
||||
$router->any('/password/reset/{id:\d+}/{token}', PasswordResetAction::class, 'auth.reset');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
namespace App\Auth;
|
||||
|
||||
use Framework\Auth;
|
||||
|
||||
class AuthTwigExtension extends \Twig_Extension
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Auth
|
||||
*/
|
||||
private $auth;
|
||||
|
||||
public function __construct(Auth $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new \Twig_SimpleFunction('current_user', [$this->auth, 'getUser'])
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace App\Auth;
|
||||
|
||||
use Framework\Auth;
|
||||
use Framework\Auth\User;
|
||||
use Framework\Database\NoRecordException;
|
||||
use Framework\Session\SessionInterface;
|
||||
|
||||
class DatabaseAuth implements Auth
|
||||
{
|
||||
|
||||
/**
|
||||
* @var UserTable
|
||||
*/
|
||||
private $userTable;
|
||||
/**
|
||||
* @var SessionInterface
|
||||
*/
|
||||
private $session;
|
||||
|
||||
/**
|
||||
* @var \App\Auth\User
|
||||
*/
|
||||
private $user;
|
||||
|
||||
public function __construct(UserTable $userTable, SessionInterface $session)
|
||||
{
|
||||
$this->userTable = $userTable;
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
public function login(string $username, string $password): ?User
|
||||
{
|
||||
if (empty($username) || empty($password)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var \App\Auth\User $user */
|
||||
$user = $this->userTable->findBy('username', $username);
|
||||
if ($user && password_verify($password, $user->password)) {
|
||||
$this->setUser($user);
|
||||
return $user;
|
||||
}
|
||||