Completed
Push — middleware-wip ( a395c5...d52214 )
by Romain
03:54
created

PersistenceFetchingMiddleware::before()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 37
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 37
rs 8.439
c 1
b 0
f 0
cc 5
eloc 19
nc 5
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\Signal\Before;
23
use Romm\Formz\Middleware\Signal\SendsMiddlewareSignal;
24
use Romm\Formz\Middleware\Processor\PresetMiddlewareInterface;
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
        $this->beforeSignal()->dispatch();
57
58
        $formObject = $this->getFormObject();
59
60
        /*
61
         * If the form has already been injected in the form object, we do not
62
         * need to try to fetch it from persistence.
63
         */
64
        if ($formObject->hasForm()) {
65
            return;
66
        }
67
68
        $hash = $this->getFormHash();
69
        $metadata = null;
70
        $form = null;
71
72
        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...
73
            $metadata = $this->getMetadata($hash);
74
75
            if ($metadata) {
76
                $form = $formObject->getPersistenceManager()->fetchFirst($metadata);
77
78
                if ($form) {
79
                    $formObject->setForm($form);
80
81
                    $proxy = FormObjectFactory::get()->getProxy($form);
82
                    $proxy->setFormHash($metadata->getHash());
83
                }
84
            }
85
        }
86
87
        $this->afterSignal()
88
            ->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...
89
            ->dispatch();
90
    }
91
92
    /**
93
     * This function tries to fetch the form hash for the current form:
94
     * - First, in the options of this middleware;
95
     * - Then, in the arguments of the request.
96
     *
97
     * If no hash is found, `null` is returned.
98
     *
99
     * @return string|null
100
     */
101
    protected function getFormHash()
102
    {
103
        if (null !== $this->options->getFormHash()) {
104
            return $this->options->getFormHash();
105
        }
106
107
        $formObject = $this->getFormObject();
108
109
        if ($this->getRequest()->hasArgument('fz-hash')) {
110
            $formName = $formObject->getName();
111
            $identifierList = $this->getRequest()->getArgument('fz-hash');
112
113
            if (is_array($identifierList)
114
                && isset($identifierList[$formName])
115
            ) {
116
                return (string)$identifierList[$formName];
117
            }
118
        }
119
120
        return null;
121
    }
122
123
    /**
124
     * Fetches the metadata bound to the given hash.
125
     *
126
     * if the metadata is not* found, or if the metadata class name does not
127
     * match the form object class name, `null` is returned.
128
     *
129
     * @param string $hash
130
     * @return FormMetadata|null
131
     */
132
    protected function getMetadata($hash)
133
    {
134
        $metadata = $this->metadataRepository->findOneByHash($hash);
135
136
        if ($metadata
137
            && $metadata->getClassName() !== $this->getFormObject()->getClassName()
138
        ) {
139
            $metadata = null;
140
        }
141
142
        return $metadata;
143
    }
144
145
    /**
146
     * @param FormMetadataRepository $metadataRepository
147
     */
148
    public function injectMetadataRepository(FormMetadataRepository $metadataRepository)
149
    {
150
        $this->metadataRepository = $metadataRepository;
151
    }
152
153
    /**
154
     * @return array
155
     */
156
    public function getAllowedSignals()
157
    {
158
        return [PersistenceFetchingSignal::class];
159
    }
160
}
161