Completed
Push — wip/steps ( 47ee47 )
by Romain
03:13
created

injectMetadataRepository()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
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\Middleware\Argument\Arguments;
19
use Romm\Formz\Middleware\Item\AbstractMiddleware;
20
use Romm\Formz\Middleware\Item\FormInjection\FormInjectionSignal;
21
use Romm\Formz\Middleware\Processor\PresetMiddlewareInterface;
22
use Romm\Formz\Middleware\Signal\Before;
23
use Romm\Formz\Middleware\Signal\SendsMiddlewareSignal;
24
25
/**
26
 * This middleware will try to fetch a form instance using the persistence
27
 * manager.
28
 *
29
 * If a form hash is found, it is used to fetch for a form metadata instance in
30
 * database. If the metadata if found, its data are used to search for a form
31
 * instance in every persistence service bound to the form object.
32
 *
33
 * The form hash can be retrieved either in the request arguments, or in the
34
 * option object of this middleware: @see PersistenceFetchingMiddlewareOption::setFormHash()
35
 */
36
class PersistenceFetchingMiddleware extends AbstractMiddleware implements Before, FormInjectionSignal, SendsMiddlewareSignal, PresetMiddlewareInterface
37
{
38
    /**
39
     * @var \Romm\Formz\Middleware\Item\Persistence\PersistenceFetchingMiddlewareOption
40
     */
41
    protected $options;
42
43
    /**
44
     * @var FormMetadataRepository
45
     */
46
    protected $metadataRepository;
47
48
    /**
49
     * @see PersistenceFetchingMiddleware
50
     *
51
     * @param Arguments $arguments
52
     */
53
    public function before(Arguments $arguments)
54
    {
55
        $formObject = $this->getFormObject();
56
57
        if (false === $formObject->getDefinition()->hasPersistence()) {
58
            return;
59
        }
60
61
        $this->beforeSignal()->dispatch();
62
63
        /*
64
         * If the form has already been injected in the form object, we do not
65
         * need to try to fetch it from persistence.
66
         */
67
        if ($formObject->hasForm()) {
68
            return;
69
        }
70
71
        $hash = $this->getFormHash();
72
        $metadata = null;
73
        $form = null;
74
75
        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...
76
            $metadata = $this->getMetadata($hash);
77
78
            if ($metadata) {
79
                $form = $formObject->getPersistenceManager()->fetchFirst($metadata);
80
            }
81
        }
82
83
        $this->afterSignal()
84
            ->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...
85
            ->dispatch();
86
    }
87
88
    /**
89
     * This function tries to fetch the form hash for the current form:
90
     * - First, in the options of this middleware;
91
     * - Then, in the arguments of the request.
92
     *
93
     * If no hash is found, `null` is returned.
94
     *
95
     * @return string|null
96
     */
97
    protected function getFormHash()
98
    {
99
        if (null !== $this->options->getFormHash()) {
100
            return $this->options->getFormHash();
101
        }
102
103
        if ($this->getRequest()->hasArgument('fz-hash')) {
104
            $formName = $this->getFormObject()->getName();
105
            $identifierList = $this->getRequest()->getArgument('fz-hash');
106
107
            if (is_array($identifierList)
108
                && isset($identifierList[$formName])
109
            ) {
110
                return (string)$identifierList[$formName];
111
            }
112
        }
113
114
        return null;
115
    }
116
117
    /**
118
     * Fetches the metadata bound to the given hash.
119
     *
120
     * if the metadata is not found, or if the metadata class name does not
121
     * match the form object class name, `null` is returned.
122
     *
123
     * @param string $hash
124
     * @return FormMetadata|null
125
     */
126
    protected function getMetadata($hash)
127
    {
128
        $metadata = $this->metadataRepository->findOneByHash($hash);
129
130
        if ($metadata
131
            && $metadata->getClassName() !== $this->getFormObject()->getClassName()
132
        ) {
133
            $metadata = null;
134
        }
135
136
        return $metadata;
137
    }
138
139
    /**
140
     * @param FormMetadataRepository $metadataRepository
141
     */
142
    public function injectMetadataRepository(FormMetadataRepository $metadataRepository)
143
    {
144
        $this->metadataRepository = $metadataRepository;
145
    }
146
147
    /**
148
     * @return array
149
     */
150
    public function getAllowedSignals()
151
    {
152
        return [PersistenceFetchingSignal::class];
153
    }
154
}
155