Jacek Kowalski
4 hours ago 6b9278a5d57091fce636dbb640b380cfb990db6c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<?php
declare(strict_types=1);
 
namespace App\Controller;
 
use App\Entity\Book;
use App\Entity\OustedBook;
use App\Form\BulkOustType;
use App\Form\OustType;
use App\Repository\BookRepository;
use App\Repository\OustedBookRepository;
use App\Service\Library;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Routing\Requirement\Requirement;
use Symfony\Contracts\Translation\TranslatorInterface;
 
class OustedBookController extends AbstractController {
    #[Route('/ousted', name: 'ousted_list', methods: ['GET'])]
    public function list(Request $request, OustedBookRepository $books, PaginatorInterface $paginator): Response {
        return $this->render('ousted/list.html.twig', [
            'pagination' => $paginator->paginate(
                $books->createListQueryBuilder(),
                max(1, $request->query->getInt('page', 1)),
            ),
        ]);
    }
 
    #[Route('/ousted/{id}', name: 'ousted_show', requirements: ['id' => Requirement::DIGITS], methods: ['GET'])]
    public function show(OustedBook $book): Response {
        return $this->render('ousted/show.html.twig', ['book' => $book]);
    }
 
    #[Route('/book/{id}/oust', name: 'book_oust', requirements: ['id' => Requirement::DIGITS], methods: ['POST'])]
    public function oust(Request $request, Book $book, Library $library): Response {
        $form = $this->createForm(OustType::class);
        $form->handleRequest($request);
 
        if ($book->isBorrowed() || !$form->isSubmitted() || !$form->isValid()) {
            $this->addFlash('error', 'action_rejected');
 
            return $this->redirectToRoute('book_show', ['id' => $book->getId()]);
        }
 
        $ousted = $library->oust($book, $form->getData()['reason']);
        $this->addFlash('success', 'ousted_done');
 
        return $this->redirectToRoute('ousted_show', ['id' => $ousted->getId()]);
    }
 
    /**
     * Ousts the books that an inventory did not find: those not seen on or after a date.
     */
    #[Route('/ousted/bulk', name: 'ousted_bulk', methods: ['GET', 'POST'])]
    public function bulk(Request $request, BookRepository $books, Library $library, PaginatorInterface $paginator, TranslatorInterface $translator): Response {
        if ($request->isMethod('POST')) {
            $form = $this->createForm(BulkOustType::class, null, ['confirm' => true]);
            $form->handleRequest($request);
 
            if (!$form->isSubmitted() || !$form->isValid()) {
                $this->addFlash('error', 'action_rejected');
 
                return $this->redirectToRoute('ousted_bulk');
            }
 
            ['notSeenSince' => $since, 'reason' => $reason, 'selection' => $selection] = $form->getData();
            $back = ['bulk_oust' => ['notSeenSince' => $since->format('Y-m-d'), 'reason' => $reason]];
 
            if (!hash_equals($books->notSeenSinceFingerprint($since), (string)$selection)) {
                $this->addFlash('error', 'bulk_oust_changed');
 
                return $this->redirectToRoute('ousted_bulk', $back);
            }
 
            $ousted = $library->oustAll($books->createNotSeenSinceQueryBuilder($since)->getQuery()->getResult(), $reason);
            $this->addFlash('success', $translator->trans('bulk_oust_done', ['%count%' => $ousted]));
 
            return $this->redirectToRoute('ousted_list');
        }
 
        $form = $this->createForm(BulkOustType::class);
        $form->handleRequest($request);
        $parameters = ['form' => $form, 'pagination' => null];
 
        if ($form->isSubmitted() && $form->isValid()) {
            ['notSeenSince' => $since, 'reason' => $reason] = $form->getData();
 
            $parameters['since'] = $since;
            $parameters['borrowed'] = $books->countNotSeenSince($since, borrowed: true);
            $parameters['pagination'] = $paginator->paginate(
                $books->createNotSeenSinceQueryBuilder($since),
                max(1, $request->query->getInt('page', 1)),
            );
            $parameters['confirm_form'] = $this->createForm(BulkOustType::class, [
                'notSeenSince' => $since,
                'reason' => $reason,
                'selection' => $books->notSeenSinceFingerprint($since),
            ], ['confirm' => true, 'action' => $this->generateUrl('ousted_bulk')]);
        }
 
        return $this->render('ousted/bulk.html.twig', $parameters);
    }
 
    #[Route('/ousted/{id}/restore', name: 'ousted_restore', requirements: ['id' => Requirement::DIGITS], methods: ['POST'])]
    public function restore(Request $request, OustedBook $book, Library $library): Response {
        if (!$this->isCsrfTokenValid('restore' . $book->getId(), $request->getPayload()->getString('_token'))) {
            $this->addFlash('error', 'action_rejected');
 
            return $this->redirectToRoute('ousted_show', ['id' => $book->getId()]);
        }
 
        $restored = $library->restore($book);
        $this->addFlash('success', 'ousted_restored');
 
        return $this->redirectToRoute('book_show', ['id' => $restored->getId()]);
    }
}