before recepie upgrade
This commit is contained in:
parent
e273b81925
commit
3fa30dbde4
|
@ -5,9 +5,5 @@ require('bootstrap');
|
||||||
|
|
||||||
import '../styles/app.scss';
|
import '../styles/app.scss';
|
||||||
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('.navbarDropdown').dropdown();
|
|
||||||
});
|
|
||||||
|
|
||||||
require('@fortawesome/fontawesome-free/css/all.min.css');
|
require('@fortawesome/fontawesome-free/css/all.min.css');
|
||||||
require('@fortawesome/fontawesome-free/js/all.js');
|
require('@fortawesome/fontawesome-free/js/all.js');
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
/* debug */
|
/* debug */
|
||||||
* {
|
* {
|
||||||
border: 0 solid gray;
|
border: 1px solid gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
// customize some Bootstrap variables
|
// customize some Bootstrap variables
|
||||||
|
|
40
bin/console
40
bin/console
|
@ -3,41 +3,15 @@
|
||||||
|
|
||||||
use App\Kernel;
|
use App\Kernel;
|
||||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||||
use Symfony\Component\Console\Input\ArgvInput;
|
|
||||||
use Symfony\Component\Dotenv\Dotenv;
|
|
||||||
use Symfony\Component\ErrorHandler\Debug;
|
|
||||||
|
|
||||||
if (!in_array(PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) {
|
if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
|
||||||
echo 'Warning: The console should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
|
throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
|
||||||
}
|
}
|
||||||
|
|
||||||
set_time_limit(0);
|
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
|
||||||
|
|
||||||
require dirname(__DIR__).'/vendor/autoload.php';
|
return function (array $context) {
|
||||||
|
$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||||
|
|
||||||
if (!class_exists(Application::class) || !class_exists(Dotenv::class)) {
|
return new Application($kernel);
|
||||||
throw new LogicException('You need to add "symfony/framework-bundle" and "symfony/dotenv" as Composer dependencies.');
|
};
|
||||||
}
|
|
||||||
|
|
||||||
$input = new ArgvInput();
|
|
||||||
if (null !== $env = $input->getParameterOption(['--env', '-e'], null, true)) {
|
|
||||||
putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($input->hasParameterOption('--no-debug', true)) {
|
|
||||||
putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
|
|
||||||
}
|
|
||||||
|
|
||||||
(new Dotenv())->bootEnv(dirname(__DIR__).'/.env');
|
|
||||||
|
|
||||||
if ($_SERVER['APP_DEBUG']) {
|
|
||||||
umask(0000);
|
|
||||||
|
|
||||||
if (class_exists(Debug::class)) {
|
|
||||||
Debug::enable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
|
|
||||||
$application = new Application($kernel);
|
|
||||||
$application->run($input);
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
"symfony/monolog-bundle": "^3.7",
|
"symfony/monolog-bundle": "^3.7",
|
||||||
"symfony/proxy-manager-bridge": "5.3.*",
|
"symfony/proxy-manager-bridge": "5.3.*",
|
||||||
"symfony/security-bundle": "5.3.*",
|
"symfony/security-bundle": "5.3.*",
|
||||||
|
"symfony/string": "5.3.*",
|
||||||
"symfony/twig-bundle": "^5.2",
|
"symfony/twig-bundle": "^5.2",
|
||||||
"symfony/validator": "5.3.*",
|
"symfony/validator": "5.3.*",
|
||||||
"symfony/webpack-encore-bundle": "^1.11",
|
"symfony/webpack-encore-bundle": "^1.11",
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "34381deb043c87393a1f92bbeab2aaff",
|
"content-hash": "f801003bc6731e7d38ee4787d3a9489a",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "composer/package-versions-deprecated",
|
"name": "composer/package-versions-deprecated",
|
||||||
|
@ -6750,16 +6750,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/validator",
|
"name": "symfony/validator",
|
||||||
"version": "v5.3.0",
|
"version": "v5.3.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/validator.git",
|
"url": "https://github.com/symfony/validator.git",
|
||||||
"reference": "14337bdf9e2e0b2e3385c9e90f13325f0c95a4f9"
|
"reference": "111e71ac585a47358e808bc687dcaf66e568470a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/validator/zipball/14337bdf9e2e0b2e3385c9e90f13325f0c95a4f9",
|
"url": "https://api.github.com/repos/symfony/validator/zipball/111e71ac585a47358e808bc687dcaf66e568470a",
|
||||||
"reference": "14337bdf9e2e0b2e3385c9e90f13325f0c95a4f9",
|
"reference": "111e71ac585a47358e808bc687dcaf66e568470a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -6778,6 +6778,7 @@
|
||||||
"symfony/expression-language": "<5.1",
|
"symfony/expression-language": "<5.1",
|
||||||
"symfony/http-kernel": "<4.4",
|
"symfony/http-kernel": "<4.4",
|
||||||
"symfony/intl": "<4.4",
|
"symfony/intl": "<4.4",
|
||||||
|
"symfony/property-info": "<5.3",
|
||||||
"symfony/translation": "<4.4",
|
"symfony/translation": "<4.4",
|
||||||
"symfony/yaml": "<4.4"
|
"symfony/yaml": "<4.4"
|
||||||
},
|
},
|
||||||
|
@ -6839,7 +6840,7 @@
|
||||||
"description": "Provides tools to validate values",
|
"description": "Provides tools to validate values",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/validator/tree/v5.3.0"
|
"source": "https://github.com/symfony/validator/tree/v5.3.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -6855,7 +6856,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-05-26T17:43:10+00:00"
|
"time": "2021-06-02T09:36:17+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-dumper",
|
"name": "symfony/var-dumper",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
security:
|
security:
|
||||||
encoders:
|
password_hashers:
|
||||||
App\Entity\User:
|
App\Entity\User:
|
||||||
algorithm: auto
|
algorithm: auto
|
||||||
|
|
||||||
|
@ -10,12 +10,14 @@ security:
|
||||||
entity:
|
entity:
|
||||||
class: App\Entity\User
|
class: App\Entity\User
|
||||||
property: username
|
property: username
|
||||||
|
|
||||||
|
enable_authenticator_manager: true
|
||||||
|
|
||||||
firewalls:
|
firewalls:
|
||||||
dev:
|
dev:
|
||||||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||||
security: false
|
security: false
|
||||||
main:
|
main:
|
||||||
anonymous: true
|
|
||||||
lazy: true
|
lazy: true
|
||||||
provider: app_user_provider
|
provider: app_user_provider
|
||||||
guard:
|
guard:
|
||||||
|
@ -35,5 +37,6 @@ security:
|
||||||
# Easy way to control access for large sections of your site
|
# Easy way to control access for large sections of your site
|
||||||
# Note: Only the *first* access control that matches will be used
|
# Note: Only the *first* access control that matches will be used
|
||||||
access_control:
|
access_control:
|
||||||
|
# - { path: ^/admin/login, roles: PUBLIC_ACCESS }
|
||||||
# - { path: ^/admin, roles: ROLE_ADMIN }
|
# - { path: ^/admin, roles: ROLE_ADMIN }
|
||||||
# - { path: ^/profile, roles: ROLE_USER }
|
# - { path: ^/profile, roles: ROLE_USER }
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
twig:
|
twig:
|
||||||
default_path: '%kernel.project_dir%/templates'
|
default_path: '%kernel.project_dir%/templates'
|
||||||
form_themes: ['bootstrap_4_layout.html.twig']
|
form_themes: ['bootstrap_5_layout.html.twig']
|
||||||
|
|
|
@ -33,3 +33,7 @@ services:
|
||||||
- '%env(DATABASE_URL)%'
|
- '%env(DATABASE_URL)%'
|
||||||
# add more service definitions when explicit configuration is needed
|
# add more service definitions when explicit configuration is needed
|
||||||
# please note that last definitions always *replace* previous ones
|
# please note that last definitions always *replace* previous ones
|
||||||
|
App\EntityListener\BlogEntityListener:
|
||||||
|
tags:
|
||||||
|
- { name: 'doctrine.orm.entity_listener', event: 'prePersist', entity: 'App\Entity\Blog'}
|
||||||
|
- { name: 'doctrine.orm.entity_listener', event: 'preUpdate', entity: 'App\Entity\Blog'}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20210614155532 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX UNIQ_C0155143989D9B62 ON blog (slug)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('DROP INDEX UNIQ_C0155143989D9B62 ON blog');
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ use App\Entity\Blog;
|
||||||
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
|
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
|
||||||
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
|
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
|
||||||
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
|
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
|
||||||
|
use EasyCorp\Bundle\EasyAdminBundle\Field\SlugField;
|
||||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
|
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
|
||||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
|
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
|
||||||
|
|
||||||
|
@ -26,7 +27,8 @@ class BlogCrudController extends AbstractCrudController
|
||||||
AssociationField::new('author')
|
AssociationField::new('author')
|
||||||
->autocomplete(),
|
->autocomplete(),
|
||||||
TextField::new('title'),
|
TextField::new('title'),
|
||||||
TextField::new('slug'),
|
SlugField::new('slug')
|
||||||
|
->setTargetFieldName('title'),
|
||||||
TextEditorField::new('teaser'),
|
TextEditorField::new('teaser'),
|
||||||
TextEditorField::new('content'),
|
TextEditorField::new('content'),
|
||||||
DateTimeField::new('createdAt'),
|
DateTimeField::new('createdAt'),
|
||||||
|
|
|
@ -3,8 +3,12 @@
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Entity\Blog;
|
use App\Entity\Blog;
|
||||||
|
use App\Form\BlogFormType;
|
||||||
use App\Repository\BlogRepository;
|
use App\Repository\BlogRepository;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
@ -24,16 +28,70 @@ class BlogController extends AbstractController
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $id
|
* @param $slug
|
||||||
* @param \App\Repository\BlogRepository $blogRepository
|
* @param \App\Repository\BlogRepository $blogRepository
|
||||||
*
|
*
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
*/
|
*/
|
||||||
#[Route('/blog/{slug}', name: 'blog')]
|
#[Route('/blog_show/{slug}', name: 'blog')]
|
||||||
public function show($slug, BlogRepository $blogRepository): Response
|
public function show($slug, BlogRepository $blogRepository): Response
|
||||||
{
|
{
|
||||||
return $this->render('blog/show.html.twig', [
|
return $this->render('blog/show.html.twig', [
|
||||||
'blog' => $blogRepository->findOneBy(['slug' => $slug])
|
'blog' => $blogRepository->findOneBy(['slug' => $slug])
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Doctrine\ORM\EntityManagerInterface $entityManager
|
||||||
|
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
|
||||||
|
*/
|
||||||
|
#[Route('/blog/new', name: 'blog_new')]
|
||||||
|
public function new(EntityManagerInterface $entityManager, Request $request): RedirectResponse|Response
|
||||||
|
{
|
||||||
|
$form = $this->createForm(BlogFormType::class);
|
||||||
|
|
||||||
|
$form->handleRequest($request);
|
||||||
|
|
||||||
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
|
$blog = $form->getData();
|
||||||
|
$entityManager->persist($blog);
|
||||||
|
$entityManager->flush();
|
||||||
|
|
||||||
|
return $this->redirectToRoute('blogs');
|
||||||
|
}
|
||||||
|
return $this->render('blog/new.html.twig', [
|
||||||
|
'blogForm' => $form->createView(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \App\Entity\Blog $blog
|
||||||
|
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
|
||||||
|
*/
|
||||||
|
#[Route('/blog/edit/{id}', name: 'blog_edit')]
|
||||||
|
public function edit(Blog $blog, Request $request): Response|RedirectResponse
|
||||||
|
{
|
||||||
|
$form = $this->createForm(BlogFormType::class, $blog);
|
||||||
|
|
||||||
|
$form->handleRequest($request);
|
||||||
|
|
||||||
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
|
$blog = $form->getData();
|
||||||
|
//$blog->setAuthor($this->getUser());
|
||||||
|
|
||||||
|
$entityManager = $this->getDoctrine()->getManager();
|
||||||
|
$entityManager->persist($blog);
|
||||||
|
$entityManager->flush();
|
||||||
|
|
||||||
|
return $this->redirectToRoute('blogs');
|
||||||
|
}
|
||||||
|
return $this->render('blog/new.html.twig', [
|
||||||
|
'blogForm' => $form->createView(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,13 @@ use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use JetBrains\PhpStorm\Pure;
|
use JetBrains\PhpStorm\Pure;
|
||||||
use App\Repository\SectionRepository;
|
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||||
|
use Symfony\Component\String\Slugger\SluggerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Entity(repositoryClass=BlogRepository::class)
|
* @ORM\Entity(repositoryClass=BlogRepository::class)
|
||||||
* @ORM\HasLifecycleCallbacks()
|
* @ORM\HasLifecycleCallbacks()
|
||||||
|
* @UniqueEntity("slug")
|
||||||
*/
|
*/
|
||||||
class Blog
|
class Blog
|
||||||
{
|
{
|
||||||
|
@ -79,7 +81,7 @@ class Blog
|
||||||
private $comments;
|
private $comments;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=255)
|
* @ORM\Column(type="string", length=255, unique=true)
|
||||||
*/
|
*/
|
||||||
private $slug;
|
private $slug;
|
||||||
|
|
||||||
|
@ -274,7 +276,24 @@ class Blog
|
||||||
public function setSlug(string $slug): self
|
public function setSlug(string $slug): self
|
||||||
{
|
{
|
||||||
$this->slug = $slug;
|
$this->slug = $slug;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\PrePersist
|
||||||
|
*/
|
||||||
|
public function onPrePersist()
|
||||||
|
{
|
||||||
|
$this->createdAt = new \DateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SluggerInterface $slugger
|
||||||
|
*/
|
||||||
|
public function computeSlug(SluggerInterface $slugger)
|
||||||
|
{
|
||||||
|
$this->slug = $slugger->slug($this->title);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\EntityListener;
|
||||||
|
|
||||||
|
use App\Entity\Blog;
|
||||||
|
use Doctrine\ORM\Event\LifecycleEventArgs;
|
||||||
|
use JetBrains\PhpStorm\NoReturn;
|
||||||
|
use Symfony\Component\String\Slugger\SluggerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BlogEntityListener
|
||||||
|
* @package App\EntityListener
|
||||||
|
*/
|
||||||
|
class BlogEntityListener
|
||||||
|
{
|
||||||
|
private SluggerInterface $slugger;
|
||||||
|
|
||||||
|
public function __construct(SluggerInterface $slugger)
|
||||||
|
{
|
||||||
|
$this->slugger = $slugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \App\Entity\Blog $blog
|
||||||
|
* @param \Doctrine\ORM\Event\LifecycleEventArgs $title
|
||||||
|
*/
|
||||||
|
#[NoReturn]
|
||||||
|
public function prePersist(Blog $blog, LifecycleEventArgs $title)
|
||||||
|
{
|
||||||
|
$blog->computeSlug($this->slugger);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \App\Entity\Blog $blog
|
||||||
|
* @param \Doctrine\ORM\Event\LifecycleEventArgs $title
|
||||||
|
*/
|
||||||
|
#[NoReturn]
|
||||||
|
public function preUpdate(Blog $blog, LifecycleEventArgs $title)
|
||||||
|
{
|
||||||
|
//dd($title);
|
||||||
|
$blog->computeSlug($this->slugger);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace App\Form;
|
||||||
|
|
||||||
|
|
||||||
|
use App\Entity\Blog;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BlogFormType
|
||||||
|
* @package App\Form
|
||||||
|
*/
|
||||||
|
class BlogFormType extends \Symfony\Component\Form\AbstractType
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
|
{
|
||||||
|
$builder
|
||||||
|
->add('title')
|
||||||
|
->add('teaser')
|
||||||
|
->add('content')
|
||||||
|
->add('author');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'data_class' => Blog::class
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -7,12 +7,12 @@ use Doctrine\ORM\EntityManagerInterface;
|
||||||
use JetBrains\PhpStorm\ArrayShape;
|
use JetBrains\PhpStorm\ArrayShape;
|
||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
|
|
||||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||||
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
|
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
|
||||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
||||||
use Symfony\Component\Security\Core\Security;
|
use Symfony\Component\Security\Core\Security;
|
||||||
use Symfony\Component\Security\Core\User\UserInterface;
|
use Symfony\Component\Security\Core\User\UserInterface;
|
||||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||||
|
@ -22,23 +22,27 @@ use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticato
|
||||||
use Symfony\Component\Security\Guard\PasswordAuthenticatedInterface;
|
use Symfony\Component\Security\Guard\PasswordAuthenticatedInterface;
|
||||||
use Symfony\Component\Security\Http\Util\TargetPathTrait;
|
use Symfony\Component\Security\Http\Util\TargetPathTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class AppAuthenticator
|
||||||
|
* @package App\Security
|
||||||
|
*/
|
||||||
class AppAuthenticator extends AbstractFormLoginAuthenticator implements PasswordAuthenticatedInterface
|
class AppAuthenticator extends AbstractFormLoginAuthenticator implements PasswordAuthenticatedInterface
|
||||||
{
|
{
|
||||||
use TargetPathTrait;
|
use TargetPathTrait;
|
||||||
|
|
||||||
public const LOGIN_ROUTE = 'app_login';
|
public const LOGIN_ROUTE = 'app_login';
|
||||||
|
|
||||||
private $entityManager;
|
private EntityManagerInterface $entityManager;
|
||||||
private $urlGenerator;
|
private UrlGeneratorInterface $urlGenerator;
|
||||||
private $csrfTokenManager;
|
private CsrfTokenManagerInterface $csrfTokenManager;
|
||||||
private $passwordEncoder;
|
private UserPasswordHasherInterface $passwordHasher;
|
||||||
|
|
||||||
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder)
|
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordHasherInterface $passwordHasher)
|
||||||
{
|
{
|
||||||
$this->entityManager = $entityManager;
|
$this->entityManager = $entityManager;
|
||||||
$this->urlGenerator = $urlGenerator;
|
$this->urlGenerator = $urlGenerator;
|
||||||
$this->csrfTokenManager = $csrfTokenManager;
|
$this->csrfTokenManager = $csrfTokenManager;
|
||||||
$this->passwordEncoder = $passwordEncoder;
|
$this->passwordHasher = $passwordHasher;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,7 +113,7 @@ class AppAuthenticator extends AbstractFormLoginAuthenticator implements Passwor
|
||||||
* @throws AuthenticationException
|
* @throws AuthenticationException
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function getUser($credentials, UserProviderInterface $userProvider)
|
public function getUser($credentials, UserProviderInterface $userProvider): ?UserInterface
|
||||||
{
|
{
|
||||||
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
|
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
|
||||||
if (!$this->csrfTokenManager->isTokenValid($token)) {
|
if (!$this->csrfTokenManager->isTokenValid($token)) {
|
||||||
|
@ -125,7 +129,7 @@ class AppAuthenticator extends AbstractFormLoginAuthenticator implements Passwor
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
throw new UsernameNotFoundException('Username or email could not be found.');
|
throw new UserNotFoundException('Username or email could not be found.');
|
||||||
} else {
|
} else {
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
@ -149,7 +153,7 @@ class AppAuthenticator extends AbstractFormLoginAuthenticator implements Passwor
|
||||||
public function checkCredentials($credentials, UserInterface $user): bool
|
public function checkCredentials($credentials, UserInterface $user): bool
|
||||||
{
|
{
|
||||||
//return true;
|
//return true;
|
||||||
return $this->passwordEncoder->isPasswordValid($user, $credentials['password']);
|
return $this->passwordHasher->isPasswordValid($user, $credentials['password']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,6 +164,17 @@ class AppAuthenticator extends AbstractFormLoginAuthenticator implements Passwor
|
||||||
return $credentials['password'];
|
return $credentials['password'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when authentication executed and was successful!
|
||||||
|
*
|
||||||
|
* This should return the Response sent back to the user, like a
|
||||||
|
* RedirectResponse to the last page they visited.
|
||||||
|
*
|
||||||
|
* If you return null, the current request will continue, and the user
|
||||||
|
* will be authenticated. This makes sense, for example, with an API.
|
||||||
|
*
|
||||||
|
* @return Response|null
|
||||||
|
*/
|
||||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey)
|
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey)
|
||||||
{
|
{
|
||||||
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
|
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
|
||||||
|
@ -174,15 +189,3 @@ class AppAuthenticator extends AbstractFormLoginAuthenticator implements Passwor
|
||||||
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
|
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
comment:
|
|
||||||
author => user,
|
|
||||||
createdAt,
|
|
||||||
editedAt,
|
|
||||||
editedby => user,
|
|
||||||
editreason
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
|
@ -140,12 +140,12 @@
|
||||||
"version": "v5.2.8"
|
"version": "v5.2.8"
|
||||||
},
|
},
|
||||||
"symfony/console": {
|
"symfony/console": {
|
||||||
"version": "5.1",
|
"version": "5.3",
|
||||||
"recipe": {
|
"recipe": {
|
||||||
"repo": "github.com/symfony/recipes",
|
"repo": "github.com/symfony/recipes",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"version": "5.1",
|
"version": "5.3",
|
||||||
"ref": "c6d02bdfba9da13c22157520e32a602dbee8a75c"
|
"ref": "da0c8be8157600ad34f10ff0c9cc91232522e047"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"bin/console"
|
"bin/console"
|
||||||
|
|
|
@ -10,14 +10,16 @@
|
||||||
|
|
||||||
<div class="collapse navbar-collapse" id="CollapsingNavbar">
|
<div class="collapse navbar-collapse" id="CollapsingNavbar">
|
||||||
<ul class="navbar-nav ms-auto">
|
<ul class="navbar-nav ms-auto">
|
||||||
|
<li>
|
||||||
<form class="d-flex">
|
<form class="d-flex">
|
||||||
<input class="form-control me-2 my-2" type="search" placeholder="Search" aria-label="Search">
|
<input class="form-control me-2 my-2" type="search" placeholder="Search" aria-label="Search">
|
||||||
<button class="btn" type="submit">Search</button>
|
<button class="btn" type="submit">Search</button>
|
||||||
</form>
|
</form>
|
||||||
|
</li>
|
||||||
{% if is_granted('ROLE_USER') %}
|
{% if is_granted('ROLE_USER') %}
|
||||||
<li class="nav-item dropdown me-auto my-2 my-lg-0">
|
<li class="nav-item dropdown me-auto">
|
||||||
<button type="button" id="navbar-dropdown" data-bs-target="#dropdown-menu" data-bs-toggle="dropdown"
|
<button type="button" id="navbar-dropdown" data-bs-target="#dropdown-menu" data-bs-toggle="dropdown"
|
||||||
class="btn btn-primary dropdown-toggle ml-auto button-login">
|
class="btn btn-primary dropdown-toggle ml-auto mb-2 button-login">
|
||||||
{{ app.user.username }}
|
{{ app.user.username }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
Create new Blog
|
||||||
|
|
||||||
|
{{ form_start(blogForm) }}
|
||||||
|
{{ form_widget(blogForm) }}
|
||||||
|
<button type="submit" class="btn btn-primary">Create</button>
|
||||||
|
{{ form_end(blogForm) }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
New Blog
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
<div class="show-article-container p-3 mt-4">
|
<div class="show-article-container p-3 mt-4">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
|
<div class="">
|
||||||
|
<a href="{{ path('blog_edit', { id : blog.id }) }}"><i class="fas fa-edit"></i></a>
|
||||||
|
<a href="{{ path('blogs') }}"><i class="fas fa-trash-alt"></i></a>
|
||||||
|
</div>
|
||||||
<img class="show-article-img" src="{{ asset('build/images/asteroid.jpeg') }}" alt="asteroid">
|
<img class="show-article-img" src="{{ asset('build/images/asteroid.jpeg') }}" alt="asteroid">
|
||||||
<div class="show-article-title-container d-inline-block pl-3 align-middle">
|
<div class="show-article-title-container d-inline-block pl-3 align-middle">
|
||||||
<span class="show-article-title ">{{ blog.title }}</span>
|
<span class="show-article-title ">{{ blog.title }}</span>
|
||||||
|
|
Loading…
Reference in New Issue