Added book search.

This commit is contained in:
krzysiej
2022-06-03 15:17:46 +02:00
parent b21d213b19
commit 314f4f2a14
10 changed files with 192 additions and 46 deletions

View File

@@ -6,6 +6,7 @@ use App\Entity\Book;
use App\Entity\File;
use App\Form\BookType;
use App\Form\FileType;
use App\Form\SearchType;
use App\Repository\BookRepository;
use App\Repository\FileRepository;
use App\Service\FileService;
@@ -79,6 +80,21 @@ class BookController extends AbstractController
return new JsonResponse($bookFinder->search($phrase));
}
#[Route('/search/', name: 'app_book_search_book', methods: ['GET', 'POST'])]
public function searchBook(BookRepository $bookRepository, Request $request): Response
{
$searchForm = $this->createForm(SearchType::class);
$searchForm->handleRequest($request);
$books = [];
if ($searchForm->isSubmitted() && $searchForm->isValid()) {
$books = $bookRepository->findByTitle($searchForm->get('search')->getData());
}
return $this->renderForm('book/search.html.twig', [
'books' => $books,
'searchTerm' => $searchForm->get('search')->getData()
]);
}
#[Route('/info/{urlInBase64}', name: 'app_book_info', methods: ['GET'])]
public function info(string $urlInBase64): JsonResponse
{

View File

@@ -16,7 +16,7 @@ class Book
private $id;
#[ORM\Column(type: 'string', length: 255)]
private $Title;
private $title;
#[ORM\Column(type: 'string', length: 255)]
private $language;
@@ -72,12 +72,12 @@ class Book
public function getTitle(): ?string
{
return $this->Title;
return $this->title;
}
public function setTitle(string $Title): self
public function setTitle(string $title): self
{
$this->Title = $Title;
$this->title = $title;
return $this;
}

35
src/Form/SearchType.php Normal file
View File

@@ -0,0 +1,35 @@
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class SearchType extends AbstractType
{
private $router;
public function __construct(UrlGeneratorInterface $router)
{
$this->router = $router;
}
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->setAction($this->router->generate('app_book_search_book'))
->add('search', TextType::class, ['attr' => ['placeholder' => 'Book title']])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
// Configure your form options here
'attr' => ['class' => 'd-flex']
]);
}
}

View File

@@ -39,20 +39,18 @@ class BookRepository extends ServiceEntityRepository
}
}
// /**
// * @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()
// ;
// }
/**
* @return Book[] Returns an array of Book objects
*/
public function findByTitle($value): array
{
return $this->createQueryBuilder('b')
->andWhere('LOWER(b.title) LIKE :title')
->setParameter('title', '%' . strtolower($value) . '%')
->orderBy('b.id', 'ASC')
->getQuery()
->getResult();
}
// public function findOneBySomeField($value): ?Book
// {

View File

@@ -60,7 +60,7 @@ class FileService
$file = new File();
$file->setFileName(trim($ebook->getClientOriginalName()));
$file->setFileSize($ebook->getSize());
$file->setExtension($ebook->guessClientExtension());
$file->setExtension($ebook->getClientOriginalExtension());
$file->setBook($book);
$this->fileRepository->add($file, true);

View File

@@ -3,16 +3,27 @@
namespace App\Twig;
use App\Form\SearchType;
use Symfony\Component\Form\FormFactoryInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;
class AppExtension extends AbstractExtension
{
private $formFactory;
public function __construct(FormFactoryInterface $formFactory)
{
$this->formFactory = $formFactory;
}
public function getFunctions()
{
return [
new TwigFunction('file_exists', [$this, 'file_exists']),
new TwigFunction('render_search_form', [$this, 'render_search_form']),
];
}
@@ -34,4 +45,9 @@ class AppExtension extends AbstractExtension
$suffix = array("B", "KB", "MB", "GB", "TB")[floor($base)];
return round(pow(1024, $base - floor($base)), 2) . $suffix;
}
public function render_search_form()
{
return $this->formFactory->create(SearchType::class)->createView();
}
}

View File

@@ -49,10 +49,11 @@
<a href="{{ path('app_book_new') }}" class="btn btn-primary">Add new book</a>
</li>
</ul>
<form class="d-flex">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
{% set search_form = render_search_form() %}
{{ form_start(search_form) }}
{{ form_widget(search_form.search, { 'attr' : { 'class': 'me-2' }}) }}
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
{{ form_end(search_form) }}
</div>
</div>
</nav>

View File

@@ -16,8 +16,7 @@
<table class="table">
<thead>
<tr>
<th>Cover</th>
<th>Id</th>
<th></th>
<th>Title</th>
<th>Language</th>
<th>Description</th>
@@ -29,19 +28,23 @@
<tbody>
{% for book in books %}
<tr>
<td>{% if file_exists(asset('book_covers/cover_' ~ book.id ~ '.jpg')) %}<img class="img-thumbnail"
<td>
{% if file_exists(asset('book_covers/cover_' ~ book.id ~ '.jpg')) %}
<a href="{{ path('app_book_show', {'id': book.id}) }}"><img class="img-thumbnail"
style="max-width: 80px"
src="{{ asset('book_covers/cover_' ~ book.id ~ '.jpg' ) }}" /> {% endif %}
src="{{ asset('book_covers/cover_' ~ book.id ~ '.jpg' ) }}"/>
</a>
{% endif %}
</td>
<td>{{ book.id }}</td>
<td>{{ book.Title }}</td>
<td><a href="{{ path('app_book_show', {'id': book.id}) }}"
class="text-decoration-none">{{ book.title }}</a></td>
<td>{{ book.language }}</td>
<td>{{ book.description | slice(0, 200) }}</td>
<td>{{ book.publisher }}</td>
<td>{{ book.publishDate ? book.publishDate|date('Y-m-d') : '' }}</td>
<td>
<a href="{{ path('app_book_show', {'id': book.id}) }}">show</a>
<a href="{{ path('app_book_edit', {'id': book.id}) }}">edit</a>
<a href="{{ path('app_book_show', {'id': book.id}) }}" class="text-decoration-none">show</a>
<a href="{{ path('app_book_edit', {'id': book.id}) }}" class="text-decoration-none">edit</a>
</td>
</tr>
{% else %}

View File

@@ -0,0 +1,54 @@
{% extends 'base.html.twig' %}
{% block title %}Book search{% endblock %}
{% block body %}
<div class="d-flex flex-row justify-content-between align-items-center">
<div>
<h1>Book search: {{ searchTerm }}</h1>
</div>
</div>
<table class="table">
<thead>
<tr>
<th></th>
<th>Title</th>
<th>Language</th>
<th>Description</th>
<th>Publisher</th>
<th>Publish_date</th>
<th>actions</th>
</tr>
</thead>
<tbody>
{% for book in books %}
<tr>
<td>
{% if file_exists(asset('book_covers/cover_' ~ book.id ~ '.jpg')) %}
<a href="{{ path('app_book_show', {'id': book.id}) }}"><img class="img-thumbnail"
style="max-width: 80px"
src="{{ asset('book_covers/cover_' ~ book.id ~ '.jpg' ) }}"/>
</a>
{% endif %}
</td>
<td><a href="{{ path('app_book_show', {'id': book.id}) }}"
class="text-decoration-none">{{ book.title }}</a></td>
<td>{{ book.language }}</td>
<td>{{ book.description | slice(0, 200) }}</td>
<td>{{ book.publisher }}</td>
<td>{{ book.publishDate ? book.publishDate|date('Y-m-d') : '' }}</td>
<td>
<a href="{{ path('app_book_show', {'id': book.id}) }}" class="text-decoration-none">show</a>
<a href="{{ path('app_book_edit', {'id': book.id}) }}" class="text-decoration-none">edit</a>
</td>
</tr>
{% else %}
<tr>
<td colspan="9">no records found</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@@ -3,33 +3,56 @@
{% block title %}Book{% endblock %}
{% block body %}
<h1>Book</h1>
<div class="d-flex">
<div>
{% if file_exists(asset('book_covers/cover_' ~ book.id ~ '.jpg')) %}
<img class="img-thumbnail"
style="max-width: 80px"
src="{{ asset('book_covers/cover_' ~ book.id ~ '.jpg' ) }}"/> {% endif %}
</div>
<div class="mx-3">
<h1>{{ book.title }}</h1>
<h3>{{ book.subtitle }}</h3>
<p>{{ book.author }}</p>
<p>{% for i in range(1, book.rating) %}{% endfor %}</p>
</div>
</div>
<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>
<th>Category</th>
<td colspan="3">{{ book.category }}</td>
</tr>
<tr>
<th>Description</th>
<td>{{ book.description | nl2br }}</td>
<td colspan="3">{{ book.description | nl2br }}</td>
</tr>
<tr>
<th>Publisher</th>
<td>{{ book.publisher }}</td>
<th>Publish date</th>
<td>{{ book.publishDate ? book.publishDate|date('Y-m-d') : '' }}</td>
</tr>
<tr>
<th>Publish_date</th>
<td>{{ book.publishDate ? book.publishDate|date('Y-m-d') : '' }}</td>
<th>Isbn</th>
<td>{{ book.isbn }}</td>
<th>Pages</th>
<td>{{ book.pages }}</td>
</tr>
<tr>
<th>Tags</th>
<td colspan="3">{{ book.tags }}</td>
</tr>
<tr>
<th>Series</th>
<td colspan="3">{{ book.series }} {{ book.volume }}</td>
</tr>
<tr>
<th>Language</th>
<td colspan="3">{{ book.language }}</td>
</tr>
</tbody>
</table>