Passed
Pull Request — master (#77)
by Romain
03:38
created

PropertyFactory::getProperties()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 2
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * Copyright (C) 2018
5
 * Nathan Boiron <[email protected]>
6
 * Romain Canon <[email protected]>
7
 *
8
 * This file is part of the TYPO3 NotiZ project.
9
 * It is free software; you can redistribute it and/or modify it
10
 * under the terms of the GNU General Public License, either
11
 * version 3 of the License, or any later version.
12
 *
13
 * For the full copyright and license information, see:
14
 * http://www.gnu.org/licenses/gpl-3.0.html
15
 */
16
17
namespace CuyZ\Notiz\Core\Property\Factory;
18
19
use CuyZ\Notiz\Core\Definition\Tree\EventGroup\Event\EventDefinition;
20
use CuyZ\Notiz\Core\Event\Event;
21
use CuyZ\Notiz\Core\Event\Support\HasProperties;
22
use CuyZ\Notiz\Core\Notification\Notification;
23
use CuyZ\Notiz\Service\Traits\ExtendedSelfInstantiateTrait;
24
use TYPO3\CMS\Core\SingletonInterface;
25
use TYPO3\CMS\Core\Utility\GeneralUtility;
26
use TYPO3\CMS\Extbase\Object\Container\Container;
27
use TYPO3\CMS\Extbase\Object\ObjectManager;
28
29
/**
30
 * Factory for getting both properties definitions and values, that are defined
31
 * by events and used by notifications.
32
 */
33
class PropertyFactory implements SingletonInterface
34
{
35
    use ExtendedSelfInstantiateTrait;
36
37
    /**
38
     * @var PropertyDefinition[]
39
     */
40
    protected $propertyDefinition = [];
41
42
    /**
43
     * @var PropertyContainer[]
44
     */
45
    protected $properties = [];
46
47
    /**
48
     * @var ObjectManager
49
     */
50
    protected $objectManager;
51
52
    /**
53
     * @var Container
54
     */
55
    protected $objectContainer;
56
57
    /**
58
     * @param ObjectManager $objectManager
59
     * @param Container $objectContainer
60
     */
61
    public function __construct(ObjectManager $objectManager, Container $objectContainer)
62
    {
63
        $this->objectManager = $objectManager;
64
        $this->objectContainer = $objectContainer;
65
    }
66
67
    /**
68
     * Return property definition from given event definition and notification.
69
     *
70
     * The definition is built only once for the given parameters, memoization
71
     * is used to serve the same definition later in a same run time.
72
     *
73
     * Entries have not been processed by any event instance yet. This means all
74
     * their data can not be accessed yet (mainly their values, but also
75
     * arbitrary data the property can have).
76
     *
77
     * @param string $propertyClassName
78
     * @param EventDefinition $eventDefinition
79
     * @param Notification $notification
80
     * @return PropertyDefinition
81
     */
82
    public function getPropertyDefinition($propertyClassName, EventDefinition $eventDefinition, Notification $notification)
83
    {
84
        $propertyClassName = $this->objectContainer->getImplementationClassName($propertyClassName);
85
86
        $identifier = $eventDefinition->getClassName() . '::' . $propertyClassName;
87
88
        if (false === isset($this->propertyDefinition[$identifier])) {
89
            $this->propertyDefinition[$identifier] = $this->buildPropertyDefinition($propertyClassName, $eventDefinition, $notification);
90
        }
91
92
        return $this->propertyDefinition[$identifier];
93
    }
94
95
    /**
96
     * Returns a list of property entries that have been processed by the given
97
     * event. This means all their data can be accessed properly.
98
     *
99
     * Note that each property type for each event is processed only once,
100
     * memoization is used to serve the same properties later in a same run
101
     * time.
102
     *
103
     * @param string $propertyClassName
104
     * @param Event $event
105
     * @return PropertyContainer
106
     */
107
    public function getProperties($propertyClassName, Event $event)
108
    {
109
        $propertyClassName = $this->objectContainer->getImplementationClassName($propertyClassName);
110
111
        $hash = spl_object_hash($event) . '::' . $propertyClassName;
112
113
        if (false === isset($this->properties[$hash])) {
114
            $this->properties[$hash] = $this->buildPropertyContainer($propertyClassName, $event);
115
        }
116
117
        return $this->properties[$hash];
118
    }
119
120
    /**
121
     * @param string $propertyClassName
122
     * @param EventDefinition $eventDefinition
123
     * @param Notification $notification
124
     * @return PropertyDefinition
125
     */
126
    protected function buildPropertyDefinition($propertyClassName, EventDefinition $eventDefinition, Notification $notification)
127
    {
128
        /** @var PropertyDefinition $propertyDefinition */
129
        $propertyDefinition = $this->objectManager->get(PropertyDefinition::class, $eventDefinition->getClassName(), $propertyClassName);
130
131
        if ($this->eventHasProperties($eventDefinition)) {
132
            /** @var HasProperties $eventClassName */
133
            $eventClassName = $eventDefinition->getClassName();
134
135
            $propertyBuilder = $eventClassName::getPropertyBuilder();
136
137
            $propertyBuilder->build($propertyDefinition, $notification);
138
        }
139
140
        return $propertyDefinition;
141
    }
142
143
    /**
144
     * @param string $propertyClassName
145
     * @param Event|HasProperties $event
146
     * @return PropertyContainer
147
     */
148
    protected function buildPropertyContainer($propertyClassName, Event $event)
149
    {
150
        $propertyDefinition = $this->getPropertyDefinition($propertyClassName, $event->getDefinition(), $event->getNotification());
151
152
        /** @var PropertyContainer $propertyContainer */
153
        $propertyContainer = GeneralUtility::makeInstance(PropertyContainer::class, $propertyDefinition);
154
155
        if ($this->eventHasProperties($event->getDefinition())) {
156
            $event->fillPropertyEntries($propertyContainer);
0 ignored issues
show
Bug introduced by
The method fillPropertyEntries() does not exist on CuyZ\Notiz\Core\Event\Event. Since it exists in all sub-types, consider adding an abstract or default implementation to CuyZ\Notiz\Core\Event\Event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

156
            $event->/** @scrutinizer ignore-call */ 
157
                    fillPropertyEntries($propertyContainer);
Loading history...
157
158
            $propertyContainer->freeze();
159
        }
160
161
        return $propertyContainer;
162
    }
163
164
    /**
165
     * @param EventDefinition $eventDefinition
166
     * @return bool
167
     */
168
    protected function eventHasProperties(EventDefinition $eventDefinition)
169
    {
170
        return in_array(HasProperties::class, class_implements($eventDefinition->getClassName()));
171
    }
172
}
173