1 | <?php |
||
14 | use function in_array; |
||
15 | use function is_object; |
||
16 | |||
17 | class AnnotationBuilder extends LaminasAnnotationBuilder |
||
18 | { |
||
19 | public const EVENT_CONFIGURE_FIELD = 'configureField'; |
||
20 | public const EVENT_CONFIGURE_ASSOCIATION = 'configureAssociation'; |
||
21 | public const EVENT_EXCLUDE_FIELD = 'excludeField'; |
||
22 | public const EVENT_EXCLUDE_ASSOCIATION = 'excludeAssociation'; |
||
23 | |||
24 | protected ObjectManager $objectManager; |
||
|
|||
25 | |||
26 | /** |
||
27 | * Constructor. Ensures ObjectManager is present. |
||
28 | */ |
||
29 | public function __construct(ObjectManager $objectManager) |
||
30 | { |
||
31 | 4 | $this->objectManager = $objectManager; |
|
32 | } |
||
33 | 4 | ||
34 | 4 | /** |
|
35 | * {@inheritDoc} |
||
36 | */ |
||
37 | public function setEventManager(EventManagerInterface $events) |
||
38 | { |
||
39 | 4 | parent::setEventManager($events); |
|
40 | |||
41 | 4 | (new ElementAnnotationsListener($this->objectManager))->attach($this->getEventManager()); |
|
42 | |||
43 | 4 | return $this; |
|
44 | } |
||
45 | 4 | ||
46 | /** |
||
47 | * Overrides the base getFormSpecification() to additionally iterate through each |
||
48 | * field/association in the metadata and trigger the associated event. |
||
49 | * |
||
50 | * This allows building of a form from metadata instead of requiring annotations. |
||
51 | * Annotations are still allowed through the ElementAnnotationsListener. |
||
52 | * |
||
53 | * {@inheritDoc} |
||
54 | */ |
||
55 | public function getFormSpecification($entity) |
||
56 | { |
||
57 | 6 | $formSpec = parent::getFormSpecification($entity); |
|
58 | $metadata = $this->objectManager->getClassMetadata(is_object($entity) ? get_class($entity) : $entity); |
||
59 | 6 | $inputFilter = $formSpec['input_filter']; |
|
60 | 6 | ||
61 | 6 | $formElements = [ |
|
62 | Element\ObjectSelect::class, |
||
63 | Element\ObjectMultiCheckbox::class, |
||
64 | 6 | Element\ObjectRadio::class, |
|
65 | ]; |
||
66 | |||
67 | foreach ($formSpec['elements'] as $key => $elementSpec) { |
||
68 | $name = $elementSpec['spec']['name'] ?? null; |
||
69 | 6 | $isFormElement = (isset($elementSpec['spec']['type']) && |
|
70 | 6 | in_array($elementSpec['spec']['type'], $formElements)); |
|
71 | 6 | ||
72 | 6 | if (! $name) { |
|
73 | continue; |
||
74 | 6 | } |
|
75 | |||
76 | if (! isset($inputFilter[$name])) { |
||
77 | $inputFilter[$name] = new ArrayObject(); |
||
78 | 6 | } |
|
79 | 6 | ||
80 | $params = [ |
||
81 | 'metadata' => $metadata, |
||
82 | 'name' => $name, |
||
83 | 6 | 'elementSpec' => $elementSpec, |
|
84 | 6 | 'inputSpec' => $inputFilter[$name], |
|
85 | 6 | ]; |
|
86 | 6 | ||
87 | if ($this->checkForExcludeElementFromMetadata($metadata, $name)) { |
||
88 | $elementSpec = $formSpec['elements']; |
||
89 | 6 | unset($elementSpec[$key]); |
|
90 | 6 | $formSpec['elements'] = $elementSpec; |
|
91 | 6 | ||
92 | 6 | if (isset($inputFilter[$name])) { |
|
93 | unset($inputFilter[$name]); |
||
94 | 6 | } |
|
95 | 6 | ||
96 | $formSpec['input_filter'] = $inputFilter; |
||
97 | continue; |
||
98 | 6 | } |
|
99 | 6 | ||
100 | if ($metadata->hasField($name) || (! $metadata->hasAssociation($name) && $isFormElement)) { |
||
101 | $this->getEventManager()->trigger(self::EVENT_CONFIGURE_FIELD, $this, $params); |
||
102 | 4 | } elseif ($metadata->hasAssociation($name)) { |
|
103 | 4 | $this->getEventManager()->trigger(self::EVENT_CONFIGURE_ASSOCIATION, $this, $params); |
|
104 | 4 | } |
|
105 | 4 | } |
|
106 | |||
107 | $formSpec['options'] = ['prefer_form_input_filter' => true]; |
||
108 | |||
109 | 6 | return $formSpec; |
|
110 | } |
||
111 | 6 | ||
112 | /** |
||
113 | * @return mixed |
||
114 | */ |
||
115 | protected function checkForExcludeElementFromMetadata(ClassMetadata $metadata, string $name) : bool |
||
116 | { |
||
117 | $params = ['metadata' => $metadata, 'name' => $name]; |
||
118 | $result = false; |
||
119 | 4 | ||
120 | if ($metadata->hasField($name)) { |
||
121 | 4 | $result = $this->getEventManager()->trigger(self::EVENT_EXCLUDE_FIELD, $this, $params); |
|
122 | 4 | } elseif ($metadata->hasAssociation($name)) { |
|
123 | $result = $this->getEventManager()->trigger(self::EVENT_EXCLUDE_ASSOCIATION, $this, $params); |
||
124 | 4 | } |
|
125 | 4 | ||
126 | 4 | if ($result) { |
|
127 | 4 | $result = (bool) $result->last(); |
|
128 | } |
||
129 | |||
130 | 4 | return $result; |
|
131 | 4 | } |
|
132 | } |
||
133 |