Removed encore added books crud
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -69,3 +69,5 @@ npm-debug.log
|
||||
yarn-error.log
|
||||
###< symfony/webpack-encore-bundle ###
|
||||
|
||||
/public/book_covers/
|
||||
/public/book_files/
|
||||
|
||||
2
.idea/biblio.iml
generated
2
.idea/biblio.iml
generated
@@ -62,7 +62,6 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-foundation" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-dumper" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/webpack-encore-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/options-resolver" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/flex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/password-hasher" />
|
||||
@@ -105,6 +104,7 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/annotations" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/inflector" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/migrations" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/apache-pack" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
||||
1
.idea/php.xml
generated
1
.idea/php.xml
generated
@@ -59,7 +59,6 @@
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/webpack-encore-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/flex" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/password-hasher" />
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
/*
|
||||
* Welcome to your app's main JavaScript file!
|
||||
*
|
||||
* We recommend including the built version of this JavaScript file
|
||||
* (and its CSS file) in your base layout (base.html.twig).
|
||||
*/
|
||||
|
||||
// any CSS you import will output into a single css file (app.css in this case)
|
||||
import './styles/app.css';
|
||||
|
||||
// start the Stimulus application
|
||||
import './bootstrap';
|
||||
11
assets/bootstrap.js
vendored
11
assets/bootstrap.js
vendored
@@ -1,11 +0,0 @@
|
||||
import { startStimulusApp } from '@symfony/stimulus-bridge';
|
||||
|
||||
// Registers Stimulus controllers from controllers.json and in the controllers/ directory
|
||||
export const app = startStimulusApp(require.context(
|
||||
'@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
|
||||
true,
|
||||
/\.[jt]sx?$/
|
||||
));
|
||||
|
||||
// register any custom, 3rd party controllers here
|
||||
// app.register('some_controller_name', SomeImportedController);
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"controllers": [],
|
||||
"entrypoints": []
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Controller } from '@hotwired/stimulus';
|
||||
|
||||
/*
|
||||
* This is an example Stimulus controller!
|
||||
*
|
||||
* Any element with a data-controller="hello" attribute will cause
|
||||
* this controller to be executed. The name "hello" comes from the filename:
|
||||
* hello_controller.js -> "hello"
|
||||
*
|
||||
* Delete this file or adapt it for your use!
|
||||
*/
|
||||
export default class extends Controller {
|
||||
connect() {
|
||||
this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
body {
|
||||
background-color: lightgray;
|
||||
}
|
||||
@@ -42,7 +42,6 @@
|
||||
"symfony/validator": "6.0.*",
|
||||
"symfony/web-link": "6.0.*",
|
||||
"symfony/webapp-meta": "^1.0",
|
||||
"symfony/webpack-encore-bundle": "^1.12",
|
||||
"symfony/yaml": "6.0.*",
|
||||
"twig/extra-bundle": "^2.12|^3.0",
|
||||
"twig/twig": "^2.12|^3.0"
|
||||
|
||||
73
composer.lock
generated
73
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "9e2f5ddba7a9c27abf3decbe843a4160",
|
||||
"content-hash": "bfe2f245934ec051aa999bacee2521d8",
|
||||
"packages": [
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
@@ -7281,77 +7281,6 @@
|
||||
],
|
||||
"time": "2021-10-20T16:02:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/webpack-encore-bundle",
|
||||
"version": "v1.14.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/webpack-encore-bundle.git",
|
||||
"reference": "6b18be99bf2a5a402b80a2c00043fe0b365fe836"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/webpack-encore-bundle/zipball/6b18be99bf2a5a402b80a2c00043fe0b365fe836",
|
||||
"reference": "6b18be99bf2a5a402b80a2c00043fe0b365fe836",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.3",
|
||||
"symfony/asset": "^4.4 || ^5.0 || ^6.0",
|
||||
"symfony/config": "^4.4 || ^5.0 || ^6.0",
|
||||
"symfony/dependency-injection": "^4.4 || ^5.0 || ^6.0",
|
||||
"symfony/http-kernel": "^4.4 || ^5.0 || ^6.0",
|
||||
"symfony/service-contracts": "^1.0 || ^2.0 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/framework-bundle": "^4.4 || ^5.0 || ^6.0",
|
||||
"symfony/phpunit-bridge": "^5.3 || ^6.0",
|
||||
"symfony/twig-bundle": "^4.4 || ^5.0 || ^6.0",
|
||||
"symfony/web-link": "^4.4 || ^5.0 || ^6.0"
|
||||
},
|
||||
"type": "symfony-bundle",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/webpack-encore",
|
||||
"url": "https://github.com/symfony/webpack-encore"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\WebpackEncoreBundle\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Integration with your Symfony app & Webpack Encore!",
|
||||
"support": {
|
||||
"issues": "https://github.com/symfony/webpack-encore-bundle/issues",
|
||||
"source": "https://github.com/symfony/webpack-encore-bundle/tree/v1.14.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-03T17:55:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v6.0.3",
|
||||
|
||||
@@ -7,7 +7,6 @@ return [
|
||||
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
|
||||
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
twig:
|
||||
default_path: '%kernel.project_dir%/templates'
|
||||
|
||||
form_theme: 'bootstrap_5_layout.html.twig'
|
||||
when@test:
|
||||
twig:
|
||||
strict_variables: true
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
webpack_encore:
|
||||
# The path where Encore is building the assets - i.e. Encore.setOutputPath()
|
||||
output_path: '%kernel.project_dir%/public/build'
|
||||
# If multiple builds are defined (as shown below), you can disable the default build:
|
||||
# output_path: false
|
||||
|
||||
# Set attributes that will be rendered on all script and link tags
|
||||
script_attributes:
|
||||
defer: true
|
||||
# Uncomment (also under link_attributes) if using Turbo Drive
|
||||
# https://turbo.hotwired.dev/handbook/drive#reloading-when-assets-change
|
||||
# 'data-turbo-track': reload
|
||||
# link_attributes:
|
||||
# Uncomment if using Turbo Drive
|
||||
# 'data-turbo-track': reload
|
||||
|
||||
# If using Encore.enableIntegrityHashes() and need the crossorigin attribute (default: false, or use 'anonymous' or 'use-credentials')
|
||||
# crossorigin: 'anonymous'
|
||||
|
||||
# Preload all rendered script and link tags automatically via the HTTP/2 Link header
|
||||
# preload: true
|
||||
|
||||
# Throw an exception if the entrypoints.json file is missing or an entry is missing from the data
|
||||
# strict_mode: false
|
||||
|
||||
# If you have multiple builds:
|
||||
# builds:
|
||||
# pass "frontend" as the 3rg arg to the Twig functions
|
||||
# {{ encore_entry_script_tags('entry1', null, 'frontend') }}
|
||||
|
||||
# frontend: '%kernel.project_dir%/public/frontend/build'
|
||||
|
||||
# Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes)
|
||||
# Put in config/packages/prod/webpack_encore.yaml
|
||||
# cache: true
|
||||
|
||||
framework:
|
||||
assets:
|
||||
json_manifest_path: '%kernel.project_dir%/public/build/manifest.json'
|
||||
|
||||
#when@prod:
|
||||
# webpack_encore:
|
||||
# # Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes)
|
||||
# # Available in version 1.2
|
||||
# cache: true
|
||||
|
||||
#when@test:
|
||||
# webpack_encore:
|
||||
# strict_mode: false
|
||||
@@ -4,6 +4,8 @@
|
||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
||||
parameters:
|
||||
book_covers: '%kernel.project_dir%/public/book_covers/'
|
||||
book_files: '%kernel.project_dir%/public/book_files/'
|
||||
|
||||
services:
|
||||
# default configuration for services in *this* file
|
||||
|
||||
35
migrations/Version20220520082729.php
Normal file
35
migrations/Version20220520082729.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?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 Version20220520082729 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 TABLE book (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) NOT NULL, language VARCHAR(255) NOT NULL, description LONGTEXT DEFAULT NULL, publisher VARCHAR(255) DEFAULT NULL, publish_date DATE DEFAULT NULL, filename VARCHAR(255) DEFAULT NULL, original_filename VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||
$this->addSql('CREATE TABLE `user` (id INT AUTO_INCREMENT NOT NULL, email VARCHAR(180) NOT NULL, roles JSON NOT NULL, password VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_8D93D649E7927C74 (email), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||
$this->addSql('CREATE TABLE messenger_messages (id BIGINT AUTO_INCREMENT NOT NULL, body LONGTEXT NOT NULL, headers LONGTEXT NOT NULL, queue_name VARCHAR(190) NOT NULL, created_at DATETIME NOT NULL, available_at DATETIME NOT NULL, delivered_at DATETIME DEFAULT NULL, INDEX IDX_75EA56E0FB7336F0 (queue_name), INDEX IDX_75EA56E0E3BD61CE (available_at), INDEX IDX_75EA56E016BA31DB (delivered_at), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('DROP TABLE book');
|
||||
$this->addSql('DROP TABLE `user`');
|
||||
$this->addSql('DROP TABLE messenger_messages');
|
||||
}
|
||||
}
|
||||
31
migrations/Version20220520124026.php
Normal file
31
migrations/Version20220520124026.php
Normal 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 Version20220520124026 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('ALTER TABLE book ADD subtitle VARCHAR(255) DEFAULT NULL');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE book DROP subtitle');
|
||||
}
|
||||
}
|
||||
18
package.json
18
package.json
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@hotwired/stimulus": "^3.0.0",
|
||||
"@symfony/stimulus-bridge": "^3.0.0",
|
||||
"@symfony/webpack-encore": "^2.0.0",
|
||||
"core-js": "^3.0.0",
|
||||
"regenerator-runtime": "^0.13.2",
|
||||
"webpack-notifier": "^1.6.0"
|
||||
},
|
||||
"license": "UNLICENSED",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev-server": "encore dev-server",
|
||||
"dev": "encore dev",
|
||||
"watch": "encore dev --watch",
|
||||
"build": "encore production --progress"
|
||||
}
|
||||
}
|
||||
126
src/Controller/BookController.php
Normal file
126
src/Controller/BookController.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Book;
|
||||
use App\Form\BookType;
|
||||
use App\Repository\BookRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/book')]
|
||||
class BookController extends AbstractController
|
||||
{
|
||||
#[Route('/', name: 'app_book_index', methods: ['GET'])]
|
||||
public function index(BookRepository $bookRepository): Response
|
||||
{
|
||||
return $this->render('book/index.html.twig', [
|
||||
'books' => $bookRepository->findAll(),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/new', name: 'app_book_new', methods: ['GET', 'POST'])]
|
||||
public function new(Request $request, BookRepository $bookRepository): Response
|
||||
{
|
||||
$book = new Book();
|
||||
$form = $this->createForm(BookType::class, $book);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$bookRepository->add($book, true);
|
||||
|
||||
$cover = $request->files->get('book')['cover'];
|
||||
if ($cover) {
|
||||
$cover->move(
|
||||
$this->getParameter('book_covers'),
|
||||
'cover_' . $book->getId() . '.' . $cover->guessClientExtension()
|
||||
);
|
||||
}
|
||||
|
||||
$ebook = $request->files->get('book')['ebook'];
|
||||
if ($ebook) {
|
||||
$ebook->move(
|
||||
$this->getParameter('book_files'),
|
||||
'ebook_' . $book->getId() . '.' . $ebook->guessClientExtension()
|
||||
);
|
||||
}
|
||||
|
||||
dd($book->getId());
|
||||
|
||||
return $this->redirectToRoute('app_book_index', [], Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
|
||||
return $this->renderForm('book/new.html.twig', [
|
||||
'book' => $book,
|
||||
'form' => $form,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/{id}', name: 'app_book_show', methods: ['GET'])]
|
||||
public function show(Book $book): Response
|
||||
{
|
||||
return $this->render('book/show.html.twig', [
|
||||
'book' => $book,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/{id}/edit', name: 'app_book_edit', methods: ['GET', 'POST'])]
|
||||
public function edit(Request $request, Book $book, BookRepository $bookRepository): Response
|
||||
{
|
||||
$form = $this->createForm(BookType::class, $book);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$cover = $request->files->get('book')['cover'];
|
||||
if ($cover) {
|
||||
$cover->move(
|
||||
$this->getParameter('book_covers'),
|
||||
'cover_' . $book->getId() . '.jpg'
|
||||
);
|
||||
}
|
||||
|
||||
/** @var \Symfony\Component\HttpFoundation\File\UploadedFile $ebook */
|
||||
$ebook = $request->files->get('book')['ebook'];
|
||||
if ($ebook) {
|
||||
$ebook->move(
|
||||
$this->getParameter('book_files'),
|
||||
'ebook_' . $book->getId() . '.' . $ebook->guessClientExtension()
|
||||
);
|
||||
}
|
||||
|
||||
$book->setOriginalFilename($ebook->getClientOriginalName());
|
||||
$bookRepository->add($book, true);
|
||||
|
||||
|
||||
return $this->redirectToRoute('app_book_index', [], Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
|
||||
return $this->renderForm('book/edit.html.twig', [
|
||||
'book' => $book,
|
||||
'form' => $form,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/{id}', name: 'app_book_delete', methods: ['POST'])]
|
||||
public function delete(Request $request, Book $book, BookRepository $bookRepository): Response
|
||||
{
|
||||
if ($this->isCsrfTokenValid('delete' . $book->getId(), $request->request->get('_token'))) {
|
||||
$bookRepository->remove($book, true);
|
||||
}
|
||||
|
||||
return $this->redirectToRoute('app_book_index', [], Response::HTTP_SEE_OTHER);
|
||||
}
|
||||
|
||||
#[Route('/download/{id}', name: 'app_book_download', methods: ['GET'])]
|
||||
public function downloadBook(Book $book): BinaryFileResponse
|
||||
{
|
||||
return $this->file(
|
||||
$this->getParameter('book_files') . '/' . 'ebook_' . $book->getId() . '.'.pathinfo($book->getOriginalFilename(), PATHINFO_EXTENSION),
|
||||
$book->getOriginalFilename()
|
||||
);
|
||||
}
|
||||
}
|
||||
140
src/Entity/Book.php
Normal file
140
src/Entity/Book.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\BookRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: BookRepository::class)]
|
||||
class Book
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private $id;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 255)]
|
||||
private $Title;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 255)]
|
||||
private $language;
|
||||
|
||||
#[ORM\Column(type: 'text', nullable: true)]
|
||||
private $description;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 255, nullable: true)]
|
||||
private $publisher;
|
||||
|
||||
#[ORM\Column(type: 'date', nullable: true)]
|
||||
private $publish_date;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 255, nullable: true)]
|
||||
private $filename;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 255, nullable: true)]
|
||||
private $original_filename;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 255, nullable: true)]
|
||||
private $subtitle;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getTitle(): ?string
|
||||
{
|
||||
return $this->Title;
|
||||
}
|
||||
|
||||
public function setTitle(string $Title): self
|
||||
{
|
||||
$this->Title = $Title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLanguage(): ?string
|
||||
{
|
||||
return $this->language;
|
||||
}
|
||||
|
||||
public function setLanguage(string $language): self
|
||||
{
|
||||
$this->language = $language;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(?string $description): self
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPublisher(): ?string
|
||||
{
|
||||
return $this->publisher;
|
||||
}
|
||||
|
||||
public function setPublisher(?string $publisher): self
|
||||
{
|
||||
$this->publisher = $publisher;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPublishDate(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->publish_date;
|
||||
}
|
||||
|
||||
public function setPublishDate(?\DateTimeInterface $publish_date): self
|
||||
{
|
||||
$this->publish_date = $publish_date;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFilename(): ?string
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
public function setFilename(?string $filename): self
|
||||
{
|
||||
$this->filename = $filename;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOriginalFilename(): ?string
|
||||
{
|
||||
return $this->original_filename;
|
||||
}
|
||||
|
||||
public function setOriginalFilename(?string $original_filename): self
|
||||
{
|
||||
$this->original_filename = $original_filename;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSubtitle(): ?string
|
||||
{
|
||||
return $this->subtitle;
|
||||
}
|
||||
|
||||
public function setSubtitle(?string $subtitle): self
|
||||
{
|
||||
$this->subtitle = $subtitle;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
32
src/Form/BookType.php
Normal file
32
src/Form/BookType.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Book;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class BookType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('Title')
|
||||
->add('language')
|
||||
->add('description')
|
||||
->add('publisher')
|
||||
->add('publish_date')
|
||||
->add('ebook', FileType::class, ['mapped' => false, 'data_class' => null, 'required' => false])
|
||||
->add('cover', FileType::class, ['mapped' => false, 'data_class' => null, 'required' => false])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Book::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
66
src/Repository/BookRepository.php
Normal file
66
src/Repository/BookRepository.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Book;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Book>
|
||||
*
|
||||
* @method Book|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Book|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Book[] findAll()
|
||||
* @method Book[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class BookRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Book::class);
|
||||
}
|
||||
|
||||
public function add(Book $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->persist($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(Book $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->remove($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Book[] Returns an array of Book objects
|
||||
// */
|
||||
// public function findByExampleField($value): array
|
||||
// {
|
||||
// return $this->createQueryBuilder('b')
|
||||
// ->andWhere('b.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->orderBy('b.id', 'ASC')
|
||||
// ->setMaxResults(10)
|
||||
// ->getQuery()
|
||||
// ->getResult()
|
||||
// ;
|
||||
// }
|
||||
|
||||
// public function findOneBySomeField($value): ?Book
|
||||
// {
|
||||
// return $this->createQueryBuilder('b')
|
||||
// ->andWhere('b.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->getQuery()
|
||||
// ->getOneOrNullResult()
|
||||
// ;
|
||||
// }
|
||||
}
|
||||
22
src/Twig/AppExtension.php
Normal file
22
src/Twig/AppExtension.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Twig;
|
||||
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
class AppExtension extends AbstractExtension
|
||||
{
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new TwigFunction('file_exists', [$this, 'file_exists']),
|
||||
];
|
||||
}
|
||||
|
||||
public function file_exists(string $file): bool
|
||||
{
|
||||
return file_exists(ltrim($file, '/'));
|
||||
}
|
||||
}
|
||||
19
symfony.lock
19
symfony.lock
@@ -484,25 +484,6 @@
|
||||
"./config/packages/messenger.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/webpack-encore-bundle": {
|
||||
"version": "1.14",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "1.10",
|
||||
"ref": "91f4d29f5ebbd2fcccc71ca55a17d14a17b308e8"
|
||||
},
|
||||
"files": [
|
||||
"./assets/app.js",
|
||||
"./assets/bootstrap.js",
|
||||
"./assets/controllers.json",
|
||||
"./assets/controllers/hello_controller.js",
|
||||
"./assets/styles/app.css",
|
||||
"./config/packages/webpack_encore.yaml",
|
||||
"./package.json",
|
||||
"./webpack.config.js"
|
||||
]
|
||||
},
|
||||
"symfony/yaml": {
|
||||
"version": "v6.0.3"
|
||||
},
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}Welcome!{% endblock %}</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text></svg>">
|
||||
<link rel="icon"
|
||||
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text></svg>">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
||||
|
||||
{# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
|
||||
{% block stylesheets %}
|
||||
{{ encore_entry_link_tags('app') }}
|
||||
{# {{ encore_entry_link_tags('app') }} #}
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ encore_entry_script_tags('app') }}
|
||||
{# {{ encore_entry_script_tags('app') }} #}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
{% block body %}{% endblock %}
|
||||
</body>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
4
templates/book/_delete_form.html.twig
Normal file
4
templates/book/_delete_form.html.twig
Normal file
@@ -0,0 +1,4 @@
|
||||
<form method="post" action="{{ path('app_book_delete', {'id': book.id}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ book.id) }}">
|
||||
<button class="btn btn-danger">Delete</button>
|
||||
</form>
|
||||
4
templates/book/_form.html.twig
Normal file
4
templates/book/_form.html.twig
Normal file
@@ -0,0 +1,4 @@
|
||||
{{ form_start(form) }}
|
||||
{{ form_widget(form) }}
|
||||
<button class="btn btn-primary">{{ button_label|default('Save') }}</button>
|
||||
{{ form_end(form) }}
|
||||
13
templates/book/edit.html.twig
Normal file
13
templates/book/edit.html.twig
Normal file
@@ -0,0 +1,13 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Edit Book{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Edit Book</h1>
|
||||
|
||||
{{ include('book/_form.html.twig', {'button_label': 'Update'}) }}
|
||||
|
||||
<a href="{{ path('app_book_index') }}">back to list</a>
|
||||
|
||||
{{ include('book/_delete_form.html.twig') }}
|
||||
{% endblock %}
|
||||
49
templates/book/index.html.twig
Normal file
49
templates/book/index.html.twig
Normal file
@@ -0,0 +1,49 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Book index{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Book index</h1>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Cover</th>
|
||||
<th>Id</th>
|
||||
<th>Title</th>
|
||||
<th>Language</th>
|
||||
<th>Description</th>
|
||||
<th>Publisher</th>
|
||||
<th>Publish_date</th>
|
||||
<th>Filename</th>
|
||||
<th>Original_filename</th>
|
||||
<th>actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for book in books %}
|
||||
<tr>
|
||||
<td>{% if file_exists(asset('book_covers/cover_' ~ book.id ~ '.jpg')) %}<img class="img-thumbnail" src="{{ asset('book_covers/cover_' ~ book.id ~ '.jpg' ) }}" /> {% endif %}</td>
|
||||
<td>{{ book.id }}</td>
|
||||
<td>{{ book.Title }}</td>
|
||||
<td>{{ book.language }}</td>
|
||||
<td>{{ book.description }}</td>
|
||||
<td>{{ book.publisher }}</td>
|
||||
<td>{{ book.publishDate ? book.publishDate|date('Y-m-d') : '' }}</td>
|
||||
<td>{{ book.filename }}</td>
|
||||
<td><a href="{{ path('app_book_download', {'id': book.id}) }} ">{{ book.originalFilename }}</a></td>
|
||||
<td>
|
||||
<a href="{{ path('app_book_show', {'id': book.id}) }}">show</a>
|
||||
<a href="{{ path('app_book_edit', {'id': book.id}) }}">edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="9">no records found</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_book_new') }}">Create new</a>
|
||||
{% endblock %}
|
||||
11
templates/book/new.html.twig
Normal file
11
templates/book/new.html.twig
Normal file
@@ -0,0 +1,11 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}New Book{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Create new Book</h1>
|
||||
|
||||
{{ include('book/_form.html.twig') }}
|
||||
|
||||
<a href="{{ path('app_book_index') }}">back to list</a>
|
||||
{% endblock %}
|
||||
50
templates/book/show.html.twig
Normal file
50
templates/book/show.html.twig
Normal file
@@ -0,0 +1,50 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Book{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Book</h1>
|
||||
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td>{{ book.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<td>{{ book.Title }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Language</th>
|
||||
<td>{{ book.language }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<td>{{ book.description }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Publisher</th>
|
||||
<td>{{ book.publisher }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Publish_date</th>
|
||||
<td>{{ book.publishDate ? book.publishDate|date('Y-m-d') : '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Filename</th>
|
||||
<td>{{ book.filename }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Original_filename</th>
|
||||
<td>{{ book.originalFilename }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('app_book_index') }}">back to list</a>
|
||||
|
||||
<a href="{{ path('app_book_edit', {'id': book.id}) }}">edit</a>
|
||||
|
||||
{{ include('book/_delete_form.html.twig') }}
|
||||
{% endblock %}
|
||||
@@ -1,75 +0,0 @@
|
||||
const Encore = require('@symfony/webpack-encore');
|
||||
|
||||
// Manually configure the runtime environment if not already configured yet by the "encore" command.
|
||||
// It's useful when you use tools that rely on webpack.config.js file.
|
||||
if (!Encore.isRuntimeEnvironmentConfigured()) {
|
||||
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
|
||||
}
|
||||
|
||||
Encore
|
||||
// directory where compiled assets will be stored
|
||||
.setOutputPath('public/build/')
|
||||
// public path used by the web server to access the output path
|
||||
.setPublicPath('/build')
|
||||
// only needed for CDN's or sub-directory deploy
|
||||
//.setManifestKeyPrefix('build/')
|
||||
|
||||
/*
|
||||
* ENTRY CONFIG
|
||||
*
|
||||
* Each entry will result in one JavaScript file (e.g. app.js)
|
||||
* and one CSS file (e.g. app.css) if your JavaScript imports CSS.
|
||||
*/
|
||||
.addEntry('app', './assets/app.js')
|
||||
|
||||
// enables the Symfony UX Stimulus bridge (used in assets/bootstrap.js)
|
||||
.enableStimulusBridge('./assets/controllers.json')
|
||||
|
||||
// When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
|
||||
.splitEntryChunks()
|
||||
|
||||
// will require an extra script tag for runtime.js
|
||||
// but, you probably want this, unless you're building a single-page app
|
||||
.enableSingleRuntimeChunk()
|
||||
|
||||
/*
|
||||
* FEATURE CONFIG
|
||||
*
|
||||
* Enable & configure other features below. For a full
|
||||
* list of features, see:
|
||||
* https://symfony.com/doc/current/frontend.html#adding-more-features
|
||||
*/
|
||||
.cleanupOutputBeforeBuild()
|
||||
.enableBuildNotifications()
|
||||
.enableSourceMaps(!Encore.isProduction())
|
||||
// enables hashed filenames (e.g. app.abc123.css)
|
||||
.enableVersioning(Encore.isProduction())
|
||||
|
||||
.configureBabel((config) => {
|
||||
config.plugins.push('@babel/plugin-proposal-class-properties');
|
||||
})
|
||||
|
||||
// enables @babel/preset-env polyfills
|
||||
.configureBabelPresetEnv((config) => {
|
||||
config.useBuiltIns = 'usage';
|
||||
config.corejs = 3;
|
||||
})
|
||||
|
||||
// enables Sass/SCSS support
|
||||
//.enableSassLoader()
|
||||
|
||||
// uncomment if you use TypeScript
|
||||
//.enableTypeScriptLoader()
|
||||
|
||||
// uncomment if you use React
|
||||
//.enableReactPreset()
|
||||
|
||||
// uncomment to get integrity="..." attributes on your script & link tags
|
||||
// requires WebpackEncoreBundle 1.4 or higher
|
||||
//.enableIntegrityHashes(Encore.isProduction())
|
||||
|
||||
// uncomment if you're having problems with a jQuery plugin
|
||||
//.autoProvidejQuery()
|
||||
;
|
||||
|
||||
module.exports = Encore.getWebpackConfig();
|
||||
Reference in New Issue
Block a user