Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 96
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
tao_actions_form_Instance
0.00% covered (danger)
0.00%
0 / 96
0.00% covered (danger)
0.00%
0 / 8
1482
0.00% covered (danger)
0.00%
0 / 1
 initForm
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 initElements
0.00% covered (danger)
0.00%
0 / 78
0.00% covered (danger)
0.00%
0 / 1
812
 getElementFactory
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getServiceLocator
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFormDataProvider
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isEmptyLabel
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 isPropertyRestricted
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getRestrictionPropertyGuard
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2008-2010 (original work) Deutsche Institut für Internationale Pädagogische Forschung
19 *                         (under the project TAO-TRANSFER);
20 *               2009-2012 (update and modification) Public Research Centre Henri Tudor
21 *                         (under the project TAO-SUSTAIN & TAO-DEV);
22 *               2017-2021 (update and modification) Open Assessment Technologies SA;
23 */
24
25use oat\generis\model\OntologyAwareTrait;
26use oat\generis\model\OntologyRdfs;
27use oat\oatbox\service\ServiceManager;
28use oat\tao\helpers\form\ElementMapFactory;
29use oat\tao\helpers\form\elements\ElementValue;
30use oat\tao\model\ClassProperty\PropertyRestrictionGuard;
31use oat\tao\model\form\DataProvider\FormDataProviderInterface;
32use oat\tao\model\form\DataProvider\ProxyFormDataProvider;
33use core_kernel_classes_Property as Property;
34use Zend\ServiceManager\ServiceLocatorInterface;
35use core_kernel_classes_Resource as Resource;
36
37/**
38 * Create a form from a  resource of your ontology.
39 * Each property will be a field, regarding it's widget.
40 *
41 * @access public
42 * @author Bertrand Chevrier, <bertrand.chevrier@tudor.lu>
43 * @package tao
44 */
45class tao_actions_form_Instance extends tao_actions_form_Generis
46{
47    use OntologyAwareTrait;
48
49    public const EXCLUDED_PROPERTIES = 'excludedProperties';
50    public const RESTRICTED_PROPERTIES = 'restrictedProperties';
51
52    /**
53     * Initialize the form
54     *
55     * @author Bertrand Chevrier, <bertrand.chevrier@tudor.lu>
56     *
57     * @throws common_Exception
58     */
59    protected function initForm()
60    {
61        $name = isset($this->options['name']) ? $this->options['name'] : '';
62        if (empty($name)) {
63            $name = 'form_' . (count(self::$forms) + 1);
64        }
65        unset($this->options['name']);
66
67        $this->form = tao_helpers_form_FormFactory::getForm($name, $this->options);
68
69        //add translate action in toolbar
70        $actions = tao_helpers_form_FormFactory::getCommonActions();
71
72        //add a hidden form element that states that it is an Instance Form.
73        $instanceElt = tao_helpers_form_FormFactory::getElement('tao.forms.instance', 'Hidden');
74        $instanceElt->setValue('1');
75        $this->form->addElement($instanceElt, true);
76
77        $this->form->setActions($actions, 'top');
78        $this->form->setActions($actions, 'bottom');
79    }
80
81    /**
82     * Initialize the form elements
83     *
84     * @access protected
85     * @author Bertrand Chevrier, <bertrand.chevrier@tudor.lu>
86     */
87    protected function initElements()
88    {
89        $class = $this->getClazz();
90        $instance = $this->getInstance();
91
92        // Guess language
93        try {
94            $language = $this->options['lang'] ?? common_session_SessionManager::getSession()->getInterfaceLanguage();
95        } catch (common_exception_Error $exception) {
96            $language = DEFAULT_LANG;
97        }
98
99        $topClass = $this->getTopClazz();
100
101        if ($instance) {
102            $this->getFormDataProvider()->preloadFormData(
103                $class->getUri(),
104                $topClass->getUri(),
105                $instance->getUri(),
106                $language
107            );
108        }
109
110        //get the list of properties to set in the form
111        $propertyCandidates = tao_helpers_form_GenerisFormFactory::getDefaultProperties();
112        $classProperties = $this->getFormDataProvider()->getClassProperties($class, $topClass);
113
114        $propertyCandidates = array_merge($propertyCandidates, $classProperties);
115
116        $additionalProperties = (isset($this->options['additionalProperties'])
117            && is_array($this->options['additionalProperties']))
118                ? $this->options['additionalProperties']
119                : [];
120        if (!empty($additionalProperties)) {
121            $propertyCandidates = array_merge($propertyCandidates, $additionalProperties);
122        }
123
124        $excludedProperties = (isset($this->options[self::EXCLUDED_PROPERTIES])
125            && is_array($this->options[self::EXCLUDED_PROPERTIES]))
126                ? $this->options[self::EXCLUDED_PROPERTIES]
127                : [];
128        $editedProperties = [];
129        foreach ($propertyCandidates as $property) {
130            // Using restricted properties passed when creating editInstanceForm
131            // we can hide properties base on other resource properties
132            $restrictedProperties = $this->options[self::RESTRICTED_PROPERTIES] ?? [];
133            if ($this->isPropertyRestricted($instance, $property, $restrictedProperties)) {
134                continue;
135            }
136
137            if (!isset($editedProperties[$property->getUri()]) && !in_array($property->getUri(), $excludedProperties)) {
138                $editedProperties[$property->getUri()] = $property;
139            }
140        }
141
142        $finalElements = [];
143        foreach ($editedProperties as $property) {
144            $property->feedFromData(...$this->getFormDataProvider()->getDataToFeedProperty($property));
145
146            $widget = $property->getWidget();
147            if ($widget === null || $widget instanceof core_kernel_classes_Literal) {
148                continue;
149            }
150
151            //map properties widgets to form elements
152            $elementFactory = $this->getElementFactory();
153
154            if ($instance instanceof Resource) {
155                $elementFactory->withInstance($instance);
156            }
157
158            $element = $elementFactory->create($property, $language);
159
160            if ($element !== null) {
161                if ($instance) {
162                    $propertyInstanceValues = $this
163                        ->getFormDataProvider()
164                        ->getPropertyInstanceValues($property, $instance, $element);
165                    foreach ($propertyInstanceValues as $valueData) {
166                        if ($this->getFormDataProvider()->isPropertyList($property)) {
167                            $element->setValue(
168                                new ElementValue(tao_helpers_Uri::encode($valueData[0]), $valueData[1])
169                            );
170                        } else {
171                            $element->setValue($valueData[0]);
172                        }
173                    }
174                }
175
176                if ($this->isEmptyLabel($element)) {
177                    continue;
178                }
179
180                if ($property->getUri() === OntologyRdfs::RDFS_LABEL) {
181                    // Label will not be a TAO Property. However, it should be always first.
182                    array_splice($finalElements, 0, 0, [[$element, 1]]);
183                } elseif (count($guiOrder = $this->getFormDataProvider()->getPropertyGUIOrder($property))) {
184                    // get position of this property if it has one.
185                    $position = (int) $guiOrder[0];
186
187                    // insert the element at the right place.
188                    $i = 0;
189                    while (
190                        $i < count($finalElements)
191                        && ($position >= $finalElements[$i][1] && $finalElements[$i][1] !== null)
192                    ) {
193                        $i++;
194                    }
195
196                    array_splice($finalElements, $i, 0, [[$element, $position]]);
197                } else {
198                    // Unordered properties will go at the end of the form.
199                    $finalElements[] = [$element, null];
200                }
201            }
202        }
203
204        // Add elements related to class properties to the form.
205        foreach ($finalElements as $element) {
206            $this->form->addElement($element[0]);
207        }
208
209        //add a hidden elt for the class uri
210        $classUriElt = tao_helpers_form_FormFactory::getElement('classUri', 'Hidden');
211        $classUriElt->setValue(tao_helpers_Uri::encode($class->getUri()));
212        $this->form->addElement($classUriElt, true);
213
214        if ($instance) {
215            //add a hidden elt for the instance Uri
216            $instanceUriElt = tao_helpers_form_FormFactory::getElement('uri', 'Hidden');
217            $instanceUriElt->setValue(tao_helpers_Uri::encode($instance->getUri()));
218            $this->form->addElement($instanceUriElt, true);
219
220            $hiddenId = tao_helpers_form_FormFactory::getElement('id', 'Hidden');
221            $hiddenId->setValue($instance->getUri());
222            $this->form->addElement($hiddenId, true);
223        }
224    }
225
226    private function getElementFactory(): ElementMapFactory
227    {
228        /** @noinspection PhpIncompatibleReturnTypeInspection */
229        return $this->getServiceLocator()->get(ElementMapFactory::class);
230    }
231
232    private function getServiceLocator(): ServiceLocatorInterface
233    {
234        return ServiceManager::getServiceManager();
235    }
236
237    private function getFormDataProvider(): FormDataProviderInterface
238    {
239        return $this->getServiceLocator()->getContainer()->get(ProxyFormDataProvider::class)->getProvider();
240    }
241
242    private function isEmptyLabel($element): bool
243    {
244        return $element instanceof tao_helpers_form_elements_Label
245            && empty($element->getRawValue());
246    }
247
248    private function isPropertyRestricted(Resource $instance, Property $property, array $restrictedProperties): bool
249    {
250        return $this->getRestrictionPropertyGuard()->isPropertyRestricted($instance, $property, $restrictedProperties);
251    }
252
253    private function getRestrictionPropertyGuard(): PropertyRestrictionGuard
254    {
255        return $this->getServiceLocator()->getContainer()->get(PropertyRestrictionGuard::class);
256    }
257}