CreateLogEntryAction::__invoke()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 20
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 36
rs 9.2888
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Setono\SyliusLogEntryPlugin\Controller\Action;
6
7
use Doctrine\ORM\EntityManagerInterface;
8
use Doctrine\ORM\ORMException;
9
use Doctrine\Persistence\ManagerRegistry;
10
use InvalidArgumentException;
11
use RuntimeException;
12
use function Safe\sprintf;
13
use Setono\SyliusLogEntryPlugin\Model\LogEntriesAwareInterface;
14
use Setono\SyliusLogEntryPlugin\Model\LogEntryInterface;
15
use Symfony\Component\Form\FormFactoryInterface;
16
use Symfony\Component\HttpFoundation\RedirectResponse;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\Response;
19
use Twig\Environment;
20
use Twig\Error\LoaderError;
21
use Twig\Error\RuntimeError;
22
use Twig\Error\SyntaxError;
23
use Webmozart\Assert\Assert;
24
25
final class CreateLogEntryAction
26
{
27
    /** @var Environment */
28
    private $twig;
29
30
    /** @var FormFactoryInterface */
31
    private $formFactory;
32
33
    /** @var ManagerRegistry */
34
    private $managerRegistry;
35
36
    /** @var EntityManagerInterface|null */
37
    private $manager;
38
39
    public function __construct(Environment $twig, FormFactoryInterface $formFactory, ManagerRegistry $managerRegistry)
40
    {
41
        $this->twig = $twig;
42
        $this->formFactory = $formFactory;
43
        $this->managerRegistry = $managerRegistry;
44
    }
45
46
    /**
47
     * @throws ORMException
48
     * @throws LoaderError
49
     * @throws RuntimeError
50
     * @throws SyntaxError
51
     */
52
    public function __invoke(Request $request): Response
53
    {
54
        $config = $request->attributes->get('_setono_sylius_log_entry');
55
        self::assertConfigArray($config);
56
57
        $owningId = $request->get('id');
58
        if (!is_scalar($owningId)) {
59
            throw new InvalidArgumentException('No owning id present in the request. Your path in your route definition should look something like this: /admin/orders/{id}/log-entry');
60
        }
61
62
        $form = $this->formFactory->create($config['form']);
63
        $form->handleRequest($request);
64
65
        if ($form->isSubmitted() && $form->isValid()) {
66
            $obj = $form->getData();
67
68
            if (!$obj instanceof LogEntryInterface) {
69
                throw new InvalidArgumentException(sprintf('The data class of the form is not an instance of %s', LogEntryInterface::class));
70
            }
71
72
            $manager = $this->getManager($obj);
73
74
            /** @var LogEntriesAwareInterface $owner */
75
            $owner = $manager->getReference($config['owner'], $owningId);
76
            $obj->setOwner($owner);
77
78
            $manager->persist($obj);
79
            $manager->flush();
80
81
            return new RedirectResponse($request->headers->get('referer'));
82
        }
83
84
        $template = $config['template'] ?? '@SetonoSyliusLogEntryPlugin/Admin/log_entry.html.twig';
85
86
        return new Response($this->twig->render($template, [
87
            'form' => $form->createView(),
88
        ]));
89
    }
90
91
    private function getManager(object $obj): EntityManagerInterface
92
    {
93
        if (null === $this->manager) {
94
            $em = $this->managerRegistry->getManagerForClass(get_class($obj));
95
96
            if (!$em instanceof EntityManagerInterface) {
97
                throw new RuntimeException('This plugin only works with doctrine/orm');
98
            }
99
100
            $this->manager = $em;
101
        }
102
103
        return $this->manager;
104
    }
105
106
    /**
107
     * @param mixed $config
108
     */
109
    private static function assertConfigArray($config): void
110
    {
111
        Assert::isArray($config, sprintf(
112
            'The controller %s needs a config to be able to resolve the correct classes to use',
113
            __CLASS__
114
        ));
115
116
        Assert::keyExists($config, 'form');
117
        Assert::keyExists($config, 'owner');
118
    }
119
}
120