before recepie upgrade

This commit is contained in:
tracer 2021-06-14 19:20:55 +02:00
parent e273b81925
commit 3fa30dbde4
19 changed files with 284 additions and 88 deletions

View File

@ -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');

View File

@ -11,7 +11,7 @@
/* debug */ /* debug */
* { * {
border: 0 solid gray; border: 1px solid gray;
} }
// customize some Bootstrap variables // customize some Bootstrap variables

View File

@ -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);

View File

@ -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",

15
composer.lock generated
View File

@ -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",

View File

@ -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 }

View File

@ -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']

View File

@ -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'}

View File

@ -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');
}
}

View File

@ -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'),

View File

@ -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;
@ -18,22 +22,76 @@ class BlogController extends AbstractController
public function index(BlogRepository $blogRepository): Response public function index(BlogRepository $blogRepository): Response
{ {
return $this->render('blog/index.html.twig', [ return $this->render('blog/index.html.twig', [
'blogs' => $blogRepository->findAll() 'blogs' => $blogRepository->findAll()
]); ]);
} }
/** /**
* @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(),
]);
}
} }

View File

@ -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);
}
} }

View File

@ -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);
}
}

40
src/Form/BlogFormType.php Normal file
View File

@ -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
]);
}
}

View File

@ -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
*/

View File

@ -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"

View File

@ -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">
<form class="d-flex"> <li>
<input class="form-control me-2 my-2" type="search" placeholder="Search" aria-label="Search"> <form class="d-flex">
<button class="btn" type="submit">Search</button> <input class="form-control me-2 my-2" type="search" placeholder="Search" aria-label="Search">
</form> <button class="btn" type="submit">Search</button>
</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>

View File

@ -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 %}

View File

@ -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>