<?php /** * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; under version 2 * of the License (non-upgradable). * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Copyright (c) 2020-2021 (original work) Open Assessment Technologies SA; */ declare(strict_types=1); namespace oat\tao\helpers\form; use common_Logger; use core_kernel_classes_Class; use core_kernel_classes_Literal; use core_kernel_classes_Property; use core_kernel_classes_Resource; use oat\generis\model\OntologyRdfs; use oat\oatbox\service\ConfigurableService; use oat\tao\helpers\form\elements\TreeAware; use oat\tao\model\Lists\Business\Domain\ValueCollection; use oat\tao\model\Lists\Business\Domain\ValueCollectionSearchRequest; use oat\tao\model\Lists\Business\Input\ValueCollectionSearchInput; use oat\tao\model\Lists\Business\Service\ValueCollectionService; use oat\tao\model\TaoOntology; use tao_helpers_Context; use tao_helpers_form_elements_AsyncFile as AsyncFile; use tao_helpers_form_elements_Authoring as Authoring; use tao_helpers_form_elements_GenerisAsyncFile as GenerisAsyncFile; use tao_helpers_form_FormElement; use tao_helpers_form_FormFactory; use tao_helpers_Uri; class ElementMapFactory extends ConfigurableService { public const SERVICE_ID = 'tao/ElementMapFactory'; /** @var core_kernel_classes_Resource */ private $instance; public function withInstance(core_kernel_classes_Resource $instance): self { $this->instance = $instance; return $this; } public function create(core_kernel_classes_Property $property): ?tao_helpers_form_FormElement { //create the element from the right widget $property->feed(); $widgetResource = $property->getWidget(); if (null === $widgetResource) { return null; } $widgetUri = $widgetResource->getUri(); $propertyUri = $property->getUri(); //authoring widget is not used in standalone mode if ( $widgetUri === Authoring::WIDGET_ID && tao_helpers_Context::check('STANDALONE_MODE') ) { return null; } // horrible hack to fix file widget if ($widgetUri === AsyncFile::WIDGET_ID) { $widgetResource = new core_kernel_classes_Resource(GenerisAsyncFile::WIDGET_ID); } $element = tao_helpers_form_FormFactory::getElementByWidget( tao_helpers_Uri::encode($propertyUri), $widgetResource ); if (null === $element) { return null; } $parentProperty = $this->getParentProperty($property); if ($parentProperty) { $element->addAttribute('data-depends-on-property', tao_helpers_Uri::encode($parentProperty->getUri())); } if ($element->getWidget() !== $widgetUri) { common_Logger::w(sprintf( 'Widget definition differs from implementation: %s != %s', $element->getWidget(), $widgetUri )); return null; } //use the property label as element description $propDesc = (trim($property->getLabel()) !== '') ? $property->getLabel() : str_replace(LOCAL_NAMESPACE, '', $propertyUri); $element->setDescription($propDesc); //multi elements use the property range as options if (method_exists($element, 'setOptions')) { $range = $property->getRange(); if ($range !== null) { $options = []; if ($element instanceof TreeAware) { $sortedOptions = $element->rangeToTree( $propertyUri === OntologyRdfs::RDFS_RANGE ? new core_kernel_classes_Class(OntologyRdfs::RDFS_RESOURCE) : $range ); } else { if ($this->isList($range)) { $values = $this->getListValues($property, $range, $parentProperty); foreach ($values as $value) { $encodedUri = tao_helpers_Uri::encode($value->getUri()); $options[$encodedUri] = [$encodedUri, $value->getLabel()]; } } else { foreach ($range->getInstances(true) as $rangeInstance) { $level = $rangeInstance->getOnePropertyValue( new core_kernel_classes_Property(TaoOntology::PROPERTY_LIST_LEVEL) ); if (null === $level) { $encodedUri = tao_helpers_Uri::encode($rangeInstance->getUri()); $options[$encodedUri] = [$encodedUri, $rangeInstance->getLabel()]; } else { $level = ($level instanceof core_kernel_classes_Resource) ? $level->getUri() : (string)$level; $options[$level] = [ tao_helpers_Uri::encode($rangeInstance->getUri()), $rangeInstance->getLabel() ]; } } } ksort($options); $sortedOptions = []; foreach ($options as $id => $values) { $sortedOptions[$values[0]] = $values[1]; } //set the default value to an empty space if (method_exists($element, 'setEmptyOption')) { $element->setEmptyOption(' '); } } //complete the options listing $element->setOptions($sortedOptions); } } foreach (ValidationRuleRegistry::getRegistry()->getValidators($property) as $validator) { $element->addValidator($validator); } return $element; } private function isList($range): bool { if (!$range->isClass()) { return false; } return $range->isSubClassOf( new core_kernel_classes_Class(TaoOntology::CLASS_URI_LIST) ); } private function getValueCollectionService(): ValueCollectionService { /** @noinspection PhpIncompatibleReturnTypeInspection */ return $this->getServiceLocator()->get(ValueCollectionService::class); } private function getParentProperty(core_kernel_classes_Property $property): ?core_kernel_classes_Property { $collection = $property->getDependsOnPropertyCollection(); return $collection->offsetExists(0) ? $collection->offsetGet(0) : null; } private function getListValues( core_kernel_classes_Property $property, core_kernel_classes_Resource $range, core_kernel_classes_Property $parentProperty = null ): ValueCollection { $searchRequest = (new ValueCollectionSearchRequest())->setValueCollectionUri($range->getUri()); if ($this->instance instanceof core_kernel_classes_Resource) { $selectedValue = $this->instance->getOnePropertyValue($property); if ($selectedValue instanceof core_kernel_classes_Literal && !empty($selectedValue->literal)) { $searchRequest->setSelectedValues($selectedValue->literal); } if ($parentProperty) { $parentPropertyValues = []; foreach ($this->instance->getPropertyValuesCollection($parentProperty) as $parentPropertyValue) { $parentPropertyValues[] = (string)$parentPropertyValue; } $searchRequest->setPropertyUri($property->getUri()); $searchRequest->setParentListValues(...$parentPropertyValues); } } return $this->getValueCollectionService() ->findAll(new ValueCollectionSearchInput($searchRequest)); } }