Completed
Push — feature/middleware ( 864c18 )
by Romain
03:21
created

PersistenceFetchingMiddleware::before()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 41
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 41
rs 8.439
c 0
b 0
f 0
cc 6
eloc 21
nc 6
nop 1
1
<?php
2
/*
3
 * 2017 Romain CANON <[email protected]>
4
 *
5
 * This file is part of the TYPO3 FormZ project.
6
 * It is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License, either
8
 * version 3 of the License, or any later version.
9
 *
10
 * For the full copyright and license information, see:
11
 * http://www.gnu.org/licenses/gpl-3.0.html
12
 */
13
14
namespace Romm\Formz\Middleware\Item\Persistence;
15
16
use Romm\Formz\Domain\Model\FormMetadata;
17
use Romm\Formz\Domain\Repository\FormMetadataRepository;
18
use Romm\Formz\Form\FormObject\FormObjectFactory;
19
use Romm\Formz\Middleware\Argument\Arguments;
20
use Romm\Formz\Middleware\Item\AbstractMiddleware;
21
use Romm\Formz\Middleware\Item\FormInjection\FormInjectionSignal;
22
use Romm\Formz\Middleware\Processor\PresetMiddlewareInterface;
23
use Romm\Formz\Middleware\Signal\Before;
24
use Romm\Formz\Middleware\Signal\SendsMiddlewareSignal;
25
26
/**
27
 * This middleware will try to fetch a form instance using the persistence
28
 * manager.
29
 *
30
 * If a form hash is found, it is used to fetch for a form metadata instance in
31
 * database. If the metadata if found, its data are used to search for a form
32
 * instance in every persistence service bound to the form object.
33
 *
34
 * The form hash can be retrieved either in the request arguments, or in the
35
 * option object of this middleware: @see PersistenceFetchingMiddlewareOption::setFormHash()
36
 */
37
class PersistenceFetchingMiddleware extends AbstractMiddleware implements Before, FormInjectionSignal, SendsMiddlewareSignal, PresetMiddlewareInterface
38
{
39
    /**
40
     * @var \Romm\Formz\Middleware\Item\Persistence\PersistenceFetchingMiddlewareOption
41
     */
42
    protected $options;
43
44
    /**
45
     * @var FormMetadataRepository
46
     */
47
    protected $metadataRepository;
48
49
    /**
50
     * @see PersistenceFetchingMiddleware
51
     *
52
     * @param Arguments $arguments
53
     */
54
    public function before(Arguments $arguments)
55
    {
56
        $formObject = $this->getFormObject();
57
58
        if (false === $formObject->getDefinition()->hasPersistence()) {
59
            return;
60
        }
61
62
        $this->beforeSignal()->dispatch();
63
64
        /*
65
         * If the form has already been injected in the form object, we do not
66
         * need to try to fetch it from persistence.
67
         */
68
        if ($formObject->hasForm()) {
69
            return;
70
        }
71
72
        $hash = $this->getFormHash();
73
        $metadata = null;
74
        $form = null;
75
76
        if ($hash) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $hash of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
77
            $metadata = $this->getMetadata($hash);
78
79
            if ($metadata) {
80
                $form = $formObject->getPersistenceManager()->fetchFirst($metadata);
81
82
                if ($form) {
83
                    $formObject->setForm($form);
84
85
                    $proxy = FormObjectFactory::get()->getProxy($form);
86
                    $proxy->setFormHash($metadata->getHash());
87
                }
88
            }
89
        }
90
91
        $this->afterSignal()
92
            ->withArguments(new PersistenceFetchingArguments($hash, $metadata, $form))
0 ignored issues
show
Bug introduced by
It seems like $metadata can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
Bug introduced by
It seems like $form can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
93
            ->dispatch();
94
    }
95
96
    /**
97
     * This function tries to fetch the form hash for the current form:
98
     * - First, in the options of this middleware;
99
     * - Then, in the arguments of the request.
100
     *
101
     * If no hash is found, `null` is returned.
102
     *
103
     * @return string|null
104
     */
105
    protected function getFormHash()
106
    {
107
        if (null !== $this->options->getFormHash()) {
108
            return $this->options->getFormHash();
109
        }
110
111
        if ($this->getRequest()->hasArgument('fz-hash')) {
112
            $formName = $this->getFormObject()->getName();
113
            $identifierList = $this->getRequest()->getArgument('fz-hash');
114
115
            if (is_array($identifierList)
116
                && isset($identifierList[$formName])
117
            ) {
118
                return (string)$identifierList[$formName];
119
            }
120
        }
121
122
        return null;
123
    }
124
125
    /**
126
     * Fetches the metadata bound to the given hash.
127
     *
128
     * if the metadata is not found, or if the metadata class name does not
129
     * match the form object class name, `null` is returned.
130
     *
131
     * @param string $hash
132
     * @return FormMetadata|null
133
     */
134
    protected function getMetadata($hash)
135
    {
136
        $metadata = $this->metadataRepository->findOneByHash($hash);
137
138
        if ($metadata
139
            && $metadata->getClassName() !== $this->getFormObject()->getClassName()
140
        ) {
141
            $metadata = null;
142
        }
143
144
        return $metadata;
145
    }
146
147
    /**
148
     * @param FormMetadataRepository $metadataRepository
149
     */
150
    public function injectMetadataRepository(FormMetadataRepository $metadataRepository)
151
    {
152
        $this->metadataRepository = $metadataRepository;
153
    }
154
155
    /**
156
     * @return array
157
     */
158
    public function getAllowedSignals()
159
    {
160
        return [PersistenceFetchingSignal::class];
161
    }
162
}
163