mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-30 05:58:46 +02:00
poc form SDK (extends to form)
This commit is contained in:
@@ -2,16 +2,18 @@
|
||||
|
||||
namespace Combodo\iTop\DI\Controller;
|
||||
|
||||
use Combodo\iTop\DI\Form\Type\ConfigurationType;
|
||||
use Combodo\iTop\DI\Form\Type\ObjectType;
|
||||
use Combodo\iTop\DI\Form\Type\ObjectSingleAttributeType;
|
||||
use Combodo\iTop\DI\Form\Type\Compound\ConfigurationType;
|
||||
use Combodo\iTop\DI\Form\Type\Compound\ObjectSingleAttributeType;
|
||||
use Combodo\iTop\DI\Form\Type\Compound\ObjectType;
|
||||
use Combodo\iTop\DI\Services\ObjectService;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class Controller extends AbstractController
|
||||
@@ -38,7 +40,7 @@ class Controller extends AbstractController
|
||||
*/
|
||||
public function objectView(string $class, int $id) : Response
|
||||
{
|
||||
// retrieve person
|
||||
// retrieve object
|
||||
try{
|
||||
$oObject = MetaModel::GetObject($class, $id);
|
||||
}
|
||||
@@ -46,7 +48,7 @@ class Controller extends AbstractController
|
||||
throw $this->createNotFoundException("The $class $id does not exist");
|
||||
}
|
||||
|
||||
// return person view
|
||||
// return object view
|
||||
return $this->render('DI/object/view.html.twig', [
|
||||
'id' => $id,
|
||||
'class' => $class,
|
||||
@@ -59,7 +61,7 @@ class Controller extends AbstractController
|
||||
*/
|
||||
public function objectJSon(string $class, int $id) : Response
|
||||
{
|
||||
// retrieve person
|
||||
// retrieve object
|
||||
try{
|
||||
$oObject = MetaModel::GetObject($class, $id);
|
||||
}
|
||||
@@ -67,7 +69,7 @@ class Controller extends AbstractController
|
||||
throw $this->createNotFoundException("The $class $id does not exist");
|
||||
}
|
||||
|
||||
// return person as json response
|
||||
// return object as json response
|
||||
$oResponse = new JsonResponse($oObject->GetValues());
|
||||
$oResponse->setEncodingOptions($oResponse->getEncodingOptions() | JSON_PRETTY_PRINT);
|
||||
return $oResponse;
|
||||
@@ -78,14 +80,9 @@ class Controller extends AbstractController
|
||||
*/
|
||||
public function objectEdit(Request $request, string $class, int $id, ObjectService $oObjectService) : Response
|
||||
{
|
||||
// retrieve person
|
||||
// retrieve object
|
||||
try{
|
||||
if($id !== 0){
|
||||
$oObject = MetaModel::GetObject($class, $id);
|
||||
}
|
||||
else{
|
||||
$oObject = MetaModel::NewObject($class);
|
||||
}
|
||||
$oObject= $oObjectService->getObject($class, $id);
|
||||
}
|
||||
catch(Exception $e){
|
||||
throw $this->createNotFoundException("The $class $id does not exist");
|
||||
@@ -93,7 +90,10 @@ class Controller extends AbstractController
|
||||
|
||||
// create object form
|
||||
$oForm = $this->createForm(ObjectType::class, $oObject, [
|
||||
'object_class' => $class
|
||||
'object_class' => $class,
|
||||
'attr' => [
|
||||
'data-reload-url' => $this->generateUrl('object_reload', ['class' => $class, "id" => $id])
|
||||
]
|
||||
]);
|
||||
|
||||
// handle HTTP request
|
||||
@@ -105,11 +105,16 @@ class Controller extends AbstractController
|
||||
// retrieve object
|
||||
$oObject = $oForm->getData();
|
||||
|
||||
// handle link set (apply DbInsert, DbDelete, DbUpdate) could be automatic ?
|
||||
$oObjectService->handleLinkSetDB($oObject);
|
||||
try {
|
||||
// handle link set (apply DbInsert, DbDelete, DbUpdate) could be automatic ?
|
||||
$oObjectService->handleLinkSetDB($oObject);
|
||||
|
||||
// save object
|
||||
$oObject->DBUpdate();
|
||||
// save object
|
||||
$oObject->DBUpdate();
|
||||
}
|
||||
catch(Exception $e){
|
||||
throw new HttpException(500, 'Error while trying to save object');
|
||||
}
|
||||
|
||||
// redirect to view object
|
||||
return $this->redirectToRoute('object_view', [
|
||||
@@ -118,35 +123,94 @@ class Controller extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
// return person edition form
|
||||
// return object edition form
|
||||
return $this->renderForm('DI/object/edit.html.twig', [
|
||||
'id' => $id,
|
||||
'class' => $class,
|
||||
'form' => $oForm,
|
||||
'reload_url' => $this->generateUrl('object_reload', ['class' => $class, "id" => $id]),
|
||||
'db_host' => $oObjectService->getDbHost(),
|
||||
'db_name' => $oObjectService->getDbName()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{class<\w+>}/{id<\d+>}/{name<\w+>}/form", name="object_form", methods={"POST"})
|
||||
*/
|
||||
public function objectForm(Request $request, string $name, string $class, int $id, ObjectService $oObjectService, FormFactoryInterface $oFormFactory) : Response
|
||||
{
|
||||
// retrieve object
|
||||
try{
|
||||
$oObject= $oObjectService->getObject($class, $id);
|
||||
}
|
||||
catch(Exception $e){
|
||||
throw $this->createNotFoundException("The $class $id does not exist");
|
||||
}
|
||||
|
||||
// decode data
|
||||
$aData = json_decode($request->getContent(), true);
|
||||
|
||||
// create object form
|
||||
$oForm = $oFormFactory->createNamed($name, ObjectType::class, $oObject, [
|
||||
'object_class' => $class,
|
||||
'locked_attributes' => $aData['locked_attributes'],
|
||||
'attr' => [
|
||||
'data-reload-url' => $this->generateUrl('object_reload', [
|
||||
'class' => $class,
|
||||
'id' => $id
|
||||
])
|
||||
]
|
||||
]);
|
||||
|
||||
// handle HTTP request
|
||||
$oForm->handleRequest($request);
|
||||
|
||||
// submitted and valid
|
||||
if ($oForm->isSubmitted() && $oForm->isValid()) {
|
||||
|
||||
// retrieve object
|
||||
$oObject = $oForm->getData();
|
||||
|
||||
try {
|
||||
// handle link set (apply DbInsert, DbDelete, DbUpdate) could be automatic ?
|
||||
$oObjectService->handleLinkSetDB($oObject);
|
||||
|
||||
// save object
|
||||
$oObject->DBUpdate();
|
||||
}
|
||||
catch(Exception $e){
|
||||
throw new HttpException(500, 'Error while trying to save object');
|
||||
}
|
||||
|
||||
// redirect to view object
|
||||
return new JsonResponse();
|
||||
}
|
||||
|
||||
// return object form
|
||||
return new JsonResponse([
|
||||
'template' => $this->renderView('DI/form.html.twig', [
|
||||
'id' => $id,
|
||||
'class' => $class,
|
||||
'form' => $oForm->createView(),
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{class<\w+>}/{id<\d+>}/reload", name="object_reload")
|
||||
*/
|
||||
public function objectReload(Request $request, string $class, int $id) : Response
|
||||
public function objectReload(Request $request, string $class, int $id, ObjectService $oObjectService) : Response
|
||||
{
|
||||
// retrieve person
|
||||
// retrieve object
|
||||
try{
|
||||
$oObject = MetaModel::GetObject($class, $id);
|
||||
$oObject= $oObjectService->getObject($class, $id);
|
||||
}
|
||||
catch(Exception $e){
|
||||
throw $this->createNotFoundException("The $class $id does not exist");
|
||||
}
|
||||
|
||||
// create form with request data (dependent field)
|
||||
$oForm = $this->createForm(ObjectSingleAttributeType::class, $oObject, [
|
||||
$oForm = $this->createForm(ObjectType::class, $oObject, [
|
||||
'object_class' => $class,
|
||||
'att_code' => $request->get('dependency_att_code')
|
||||
]);
|
||||
|
||||
// handle form data
|
||||
@@ -161,8 +225,8 @@ class Controller extends AbstractController
|
||||
'att_code' => $request->get('att_code')
|
||||
]);
|
||||
|
||||
// return person edition form
|
||||
return $this->renderForm('DI/object/object_single_attribute.html.twig', [
|
||||
// return object form
|
||||
return $this->renderForm('DI/form.html.twig', [
|
||||
'form' => $oForm,
|
||||
]);
|
||||
}
|
||||
@@ -178,7 +242,7 @@ class Controller extends AbstractController
|
||||
// handle HTTP request
|
||||
$oForm->handleRequest($request);
|
||||
|
||||
// return person edition form
|
||||
// return object form
|
||||
return $this->renderForm('DI/configuration/edit.html.twig', [
|
||||
'form' => $oForm
|
||||
]);
|
||||
|
||||
195
sources/DI/Form/Builder/AttributeBuilder.php
Normal file
195
sources/DI/Form/Builder/AttributeBuilder.php
Normal file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Form\Builder;
|
||||
|
||||
use AttributeBoolean;
|
||||
use AttributeDate;
|
||||
use AttributeDateTime;
|
||||
use AttributeEmailAddress;
|
||||
use AttributeEnum;
|
||||
use AttributeExternalField;
|
||||
use AttributeExternalKey;
|
||||
use AttributeImage;
|
||||
use AttributeLinkedSet;
|
||||
use AttributePassword;
|
||||
use AttributePhoneNumber;
|
||||
use AttributeText;
|
||||
use Combodo\iTop\DI\Form\Type\Attribute\DocumentType;
|
||||
use Combodo\iTop\DI\Form\Type\Attribute\ExternalFieldType;
|
||||
use Combodo\iTop\DI\Form\Type\Attribute\ExternalKeyType;
|
||||
use Combodo\iTop\DI\Form\Type\Attribute\LinkSetType;
|
||||
use Combodo\iTop\DI\Services\ObjectService;
|
||||
use Combodo\iTop\Service\Links\LinkSetModel;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TelType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
|
||||
class AttributeBuilder
|
||||
{
|
||||
/** @var \Combodo\iTop\DI\Services\ObjectService object service */
|
||||
private ObjectService $oObjectService;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \Combodo\iTop\DI\Services\ObjectService $oObjectService
|
||||
*/
|
||||
public function __construct(ObjectService $oObjectService)
|
||||
{
|
||||
$this->oObjectService = $oObjectService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map AttributeDefinition >> FormType
|
||||
*
|
||||
* @param string $sObjectClass
|
||||
* @param string $sCode
|
||||
* @param array|null $lockedAttributes
|
||||
*
|
||||
* @return array|null
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function createAttribute(string $sObjectClass, string $sCode, ?array $lockedAttributes) : ?array
|
||||
{
|
||||
// load attribute definition
|
||||
try {
|
||||
$oAttributeDefinition = MetaModel::GetAttributeDef($sObjectClass, $sCode);
|
||||
$sLabel = $oAttributeDefinition->GetLabel();
|
||||
}
|
||||
catch(Exception $e){
|
||||
return null;
|
||||
}
|
||||
|
||||
// locked state
|
||||
$bIsLocked = $lockedAttributes !== null && array_key_exists($sCode, $lockedAttributes);
|
||||
|
||||
// create global form type (default as text)
|
||||
$aFormType = [
|
||||
'type' => TextType::class,
|
||||
'label' => $sLabel,
|
||||
'options' => [
|
||||
'required' => !$oAttributeDefinition->IsNullAllowed(),
|
||||
'disabled' => !$oAttributeDefinition->IsWritable() || $bIsLocked,
|
||||
'attr' => [
|
||||
'data-att-code' => $sCode
|
||||
],
|
||||
'row_attr' => [
|
||||
'data-block' => 'container'
|
||||
],
|
||||
'label_attr' => [
|
||||
'class' => $bIsLocked ? 'locked' : ''
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
// register dependencies
|
||||
if(count($oAttributeDefinition->GetPrerequisiteAttributes()) > 0){
|
||||
$dependencies = implode(' ', $oAttributeDefinition->GetPrerequisiteAttributes());
|
||||
$aFormType['options']['attr']['data-depends-on'] = $dependencies;
|
||||
$aFormType['depends_on'] = $dependencies;
|
||||
}
|
||||
|
||||
// inject corresponding configuration
|
||||
if($oAttributeDefinition instanceof AttributeExternalKey){
|
||||
$aFormType['type'] = ExternalKeyType::class;
|
||||
$aFormType['options']['allow_target_creation'] = $oAttributeDefinition->AllowTargetCreation();
|
||||
$aFormType['options']['object_class'] = $oAttributeDefinition->GetTargetClass();
|
||||
$aFormType['options']['att_code'] = $oAttributeDefinition->GetCode();
|
||||
try{
|
||||
$oObjectsSet = MetaModel::GetAllowedValuesAsObjectSet($oAttributeDefinition->GetHostClass(), $oAttributeDefinition->GetCode(), []);
|
||||
$aFormType['options']['choices'] = $this->oObjectService->ToChoices($oObjectsSet);
|
||||
}
|
||||
catch(Exception $e){
|
||||
|
||||
}
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeExternalField){
|
||||
$aFormType['type'] = ExternalFieldType::class;
|
||||
$bIsExternalKey = $oAttributeDefinition->IsExternalKey(EXTKEY_ABSOLUTE);
|
||||
if($bIsExternalKey){
|
||||
$aFormType['options']['is_external_key'] = true;
|
||||
$aFormType['options']['object_class'] = $oAttributeDefinition->GetExtAttDef()->GetTargetClass();
|
||||
}
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeEmailAddress){
|
||||
$aFormType['type'] = EmailType::class;
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributePassword){
|
||||
$aFormType['type'] = PasswordType::class;
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributePhoneNumber){
|
||||
$aFormType['type'] = TelType::class;
|
||||
$aFormType['options']['attr'] = [
|
||||
'pattern' => '\+[0-9]{2}\s[0-9]\s[0-9]{2}\s[0-9]{2}\s[0-9]{2}\s[0-9]{2}',
|
||||
'placeholder' => '+-- - -- -- --'
|
||||
];
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeBoolean){
|
||||
$aFormType['type'] = CheckboxType::class;
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeEnum){
|
||||
$aFormType['type'] = ChoiceType::class;
|
||||
try{
|
||||
$aOptions = array_flip($oAttributeDefinition->GetAllowedValues());
|
||||
}
|
||||
catch(Exception $e){
|
||||
$aOptions = [];
|
||||
}
|
||||
$aFormType['options']['choices'] = $aOptions;
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeImage){
|
||||
$aFormType['type'] = DocumentType::class;
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeLinkedSet){
|
||||
|
||||
$aFormType['type'] = LinkSetType::class;
|
||||
$aFormType['options']['is_indirect'] = $oAttributeDefinition->IsIndirect();
|
||||
$aFormType['options']['is_abstract'] = MetaModel::IsAbstract(LinkSetModel::GetTargetClass($oAttributeDefinition));
|
||||
$aFormType['options']['target_class'] = LinkSetModel::GetTargetClass($oAttributeDefinition);
|
||||
if($aFormType['options']['is_abstract']){
|
||||
$aFormType['options']['object_classes'] = MetaModel::EnumChildClasses(LinkSetModel::GetTargetClass($oAttributeDefinition));
|
||||
}
|
||||
$aFormType['options']['entry_options'] = [
|
||||
'object_class' => $oAttributeDefinition->GetLinkedClass(),
|
||||
'data_class' => $oAttributeDefinition->GetLinkedClass(),
|
||||
'is_link_set' => true,
|
||||
'ext_key_to_me' => $oAttributeDefinition->GetExtKeyToMe(),
|
||||
'z_list' => 'list',
|
||||
'attr' => [
|
||||
'class' => 'z_list_list'
|
||||
]
|
||||
];
|
||||
$aFormType['options']['attr'] = [
|
||||
'class' => 'link_set'
|
||||
];
|
||||
$aFormType['options']['label_attr'] = [
|
||||
'class' => 'combodo-field-set-label'
|
||||
];
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeText){
|
||||
$aFormType['type'] = TextareaType::class;
|
||||
$aFormType['options']['attr']['rows'] = 10;
|
||||
$aFormType['options']['attr']['data-widget'] = 'text_widget';
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeDate){
|
||||
$aFormType['type'] = DateType::class;
|
||||
$aFormType['options']['input'] = 'string';
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeDateTime){
|
||||
$aFormType['type'] = DateTimeType::class;
|
||||
$aFormType['options']['input'] = 'string';
|
||||
$aFormType['options']['widget'] = 'single_text';
|
||||
$aFormType['options']['with_seconds'] = true;
|
||||
}
|
||||
|
||||
return $aFormType;
|
||||
}
|
||||
}
|
||||
79
sources/DI/Form/Builder/LayoutBuilder.php
Normal file
79
sources/DI/Form/Builder/LayoutBuilder.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Form\Builder;
|
||||
|
||||
use Combodo\iTop\DI\Form\Type\Layout\ColumnType;
|
||||
use Combodo\iTop\DI\Form\Type\Layout\FieldSetType;
|
||||
use Combodo\iTop\DI\Form\Type\Layout\RowType;
|
||||
use Dict;
|
||||
|
||||
class LayoutBuilder
|
||||
{
|
||||
/**
|
||||
* createRow.
|
||||
*
|
||||
* @param $key
|
||||
* @param $columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function createRow($key, $columns) : array
|
||||
{
|
||||
return [
|
||||
'type' => RowType::class,
|
||||
'options' => [
|
||||
'items' => $columns,
|
||||
'label' => false,
|
||||
'row_attr' => [
|
||||
'data-block' => 'container'
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* createColumn.
|
||||
*
|
||||
* @param $key
|
||||
* @param $item
|
||||
* @param $dataClass
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function createColumn($key, $items) : array
|
||||
{
|
||||
return [
|
||||
'type' => ColumnType::class,
|
||||
'options' => [
|
||||
'items' => $items,
|
||||
'label' => false,
|
||||
'row_attr' => [
|
||||
'data-block' => 'container'
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* createFieldSet.
|
||||
*
|
||||
* @param $key
|
||||
* @param $item
|
||||
* @param $dataClass
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function createFieldSet($key, $items) : array
|
||||
{
|
||||
return [
|
||||
'type' => FieldSetType::class,
|
||||
'options' => [
|
||||
'items' => $items,
|
||||
'label' => Dict::S(substr($key, 9)),
|
||||
'row_attr' => [
|
||||
'data-block' => 'container'
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,12 @@ use DBObject;
|
||||
interface IFormTypeOptionModifier
|
||||
{
|
||||
/**
|
||||
* @param array $aInitialOptions form type option
|
||||
* Return new form type options for the provided DB object.
|
||||
*
|
||||
* @param array $aInitialOptions initial form type options
|
||||
* @param DBObject $oObject iTop DB object
|
||||
*
|
||||
* @return array
|
||||
* @return array new form type options
|
||||
*/
|
||||
public function getNewOptions(array $aInitialOptions, DBObject $oObject) : array;
|
||||
}
|
||||
@@ -36,7 +36,7 @@ class ObjectFormListener implements EventSubscriberInterface
|
||||
* When form is first initialized, it hasn't data set yet.
|
||||
* So we listen for form PRE_SET_DATA event to modify form with data.
|
||||
*
|
||||
* @param FormEvent $oEvent
|
||||
* @param FormEvent $oEvent form event
|
||||
*
|
||||
* @suppress-unused-warning
|
||||
*/
|
||||
@@ -50,7 +50,7 @@ class ObjectFormListener implements EventSubscriberInterface
|
||||
* Previous preSetData handling doesn't know about form submission data.
|
||||
* So, to allow us to use our DBObject for filters we need to update it before.
|
||||
*
|
||||
* @param FormEvent $oEvent
|
||||
* @param FormEvent $oEvent form event
|
||||
*
|
||||
* @suppress-unused-warning
|
||||
*/
|
||||
@@ -71,6 +71,7 @@ class ObjectFormListener implements EventSubscriberInterface
|
||||
*
|
||||
* We need to reset fields to take into account object values.
|
||||
* The form fields options can't be changed at this time.
|
||||
* All fields are reset to keep fields order.
|
||||
*
|
||||
* @param FormInterface $oForm
|
||||
* @param FormEvent $oEvent
|
||||
@@ -113,6 +114,8 @@ class ObjectFormListener implements EventSubscriberInterface
|
||||
|
||||
/**
|
||||
* Handle posted data.
|
||||
* The data are the view data. We skipped data transformation !!
|
||||
* @todo handle data transformation
|
||||
*
|
||||
* @param FormInterface $form
|
||||
* @param DBObject $oDBObject
|
||||
|
||||
31
sources/DI/Form/Transformer/DocumentTransformer.php
Normal file
31
sources/DI/Form/Transformer/DocumentTransformer.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Form\Transformer;
|
||||
|
||||
use ormDocument;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
|
||||
/**
|
||||
* Perform transformation between ormDocument and UploadedFile.
|
||||
*/
|
||||
class DocumentTransformer implements DataTransformerInterface
|
||||
{
|
||||
|
||||
/** @inheritdoc */
|
||||
public function transform($value)
|
||||
{
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function reverseTransform($value)
|
||||
{
|
||||
if($value === null){
|
||||
return null;
|
||||
}
|
||||
|
||||
$doc_content = file_get_contents($value->getRealPath());
|
||||
return new ormDocument($doc_content, $value->getClientMimeType(), $value->getRealPath());
|
||||
}
|
||||
}
|
||||
42
sources/DI/Form/Transformer/ExternalKeyTransformer.php
Normal file
42
sources/DI/Form/Transformer/ExternalKeyTransformer.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Form\Transformer;
|
||||
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
|
||||
/**
|
||||
* Transform external key ref to external key name representation.
|
||||
*/
|
||||
class ExternalKeyTransformer implements DataTransformerInterface
|
||||
{
|
||||
|
||||
/** @var string $sObjectClass */
|
||||
private string $sObjectClass;
|
||||
|
||||
/**
|
||||
* @param string $sObjectClass
|
||||
*/
|
||||
public function __construct(string $sObjectClass)
|
||||
{
|
||||
$this->sObjectClass = $sObjectClass;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function transform($value)
|
||||
{
|
||||
try{
|
||||
return MetaModel::GetObject($this->sObjectClass, $value)->GetName();
|
||||
}
|
||||
catch(Exception $e){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function reverseTransform($value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Form\Type\Simple;
|
||||
namespace Combodo\iTop\DI\Form\Type\Attribute;
|
||||
|
||||
use Combodo\iTop\DI\Form\Transformer\DocumentTransformer;
|
||||
use ormDocument;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\CallbackTransformer;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
/**
|
||||
* Example of type with data transformer.
|
||||
@@ -23,23 +22,7 @@ class DocumentType extends AbstractType
|
||||
{
|
||||
parent::buildForm($builder, $options);
|
||||
|
||||
$builder->addModelTransformer(new CallbackTransformer(
|
||||
|
||||
// transform
|
||||
function (?ormDocument $oDocument){
|
||||
return null;
|
||||
},
|
||||
|
||||
// reverse
|
||||
function (?UploadedFile $oFileData){
|
||||
if($oFileData === null){
|
||||
return null;
|
||||
}
|
||||
|
||||
$doc_content = file_get_contents($oFileData->getRealPath());
|
||||
return new ormDocument($doc_content, $oFileData->getClientMimeType(), $oFileData->getRealPath());
|
||||
},
|
||||
));
|
||||
$builder->addModelTransformer(new DocumentTransformer());
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@@ -47,7 +30,7 @@ class DocumentType extends AbstractType
|
||||
{
|
||||
/** @var ormDocument $oOrmDocument */
|
||||
$oOrmDocument = $form->getData();
|
||||
$view->vars['data'] = 'data:image/' . $oOrmDocument->GetMimeType() . ';base64,' . base64_encode($oOrmDocument->GetData());;
|
||||
$view->vars['data'] = 'data:image/' . $oOrmDocument->GetMimeType() . ';base64,' . base64_encode($oOrmDocument->GetData());
|
||||
$view->vars['mime_type'] = $oOrmDocument->GetMimeType();
|
||||
$view->vars['filename'] = $oOrmDocument->GetFileName();
|
||||
}
|
||||
38
sources/DI/Form/Type/Attribute/ExternalFieldType.php
Normal file
38
sources/DI/Form/Type/Attribute/ExternalFieldType.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Form\Type\Attribute;
|
||||
|
||||
use Combodo\iTop\DI\Form\Transformer\ExternalKeyTransformer;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class ExternalFieldType extends AbstractType
|
||||
{
|
||||
|
||||
/** @inheritdoc */
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'object_class' => null,
|
||||
'is_external_key' => false,
|
||||
]);
|
||||
|
||||
}
|
||||
/** @inheritdoc */
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
if($options['is_external_key']){
|
||||
$builder->addViewTransformer(new ExternalKeyTransformer($options['object_class']));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function getParent(): string
|
||||
{
|
||||
return TextType::class;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Form\Type\Simple;
|
||||
namespace Combodo\iTop\DI\Form\Type\Attribute;
|
||||
|
||||
use Combodo\iTop\DI\Form\Listener\IFormTypeOptionModifier;
|
||||
use Combodo\iTop\DI\Services\ObjectService;
|
||||
@@ -32,14 +32,10 @@ class ExternalKeyType extends AbstractType implements IFormTypeOptionModifier
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'display_style' => 'list',
|
||||
'allow_target_creation' => false,
|
||||
'object_class' => null,
|
||||
'att_code' => null,
|
||||
]);
|
||||
|
||||
$resolver->setAllowedTypes('display_style', 'string');
|
||||
$resolver->setAllowedValues('display_style', ['radio', 'radio_horizontal', 'radio_vertical', 'select', 'list']);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@@ -58,7 +54,8 @@ class ExternalKeyType extends AbstractType implements IFormTypeOptionModifier
|
||||
public function getNewOptions(array $aInitialOptions, DBObject $oObject) : array
|
||||
{
|
||||
try{
|
||||
$oObjectsSet = MetaModel::GetAllowedValuesAsObjectSet(get_class($oObject), $aInitialOptions['att_code'], ['this' => $oObject]);
|
||||
// $iVal = $oObject->Get($aInitialOptions['att_code']); // because we can't list all items du to performance, we want to force current value to be present, even if it's not part of the result
|
||||
$oObjectsSet = MetaModel::GetAllowedValuesAsObjectSet(get_class($oObject), $aInitialOptions['att_code'], ['this' => $oObject]/*, null, $iVal*/);
|
||||
$aInitialOptions['choices'] = $this->oObjectService->ToChoices($oObjectsSet);
|
||||
}
|
||||
catch(Exception $e){
|
||||
@@ -1,10 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Form\Type\Simple;
|
||||
namespace Combodo\iTop\DI\Form\Type\Attribute;
|
||||
|
||||
use Combodo\iTop\DI\Form\Type\ObjectType;
|
||||
use Combodo\iTop\DI\Form\Type\Compound\ObjectType;
|
||||
use Combodo\iTop\DI\Services\ObjectPresentationService;
|
||||
use Combodo\iTop\DI\Services\ObjectService;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
@@ -35,9 +34,11 @@ class LinkSetType extends AbstractType
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'entry_type' => ObjectType::class,
|
||||
'entry_options' => [
|
||||
'object_class' => null
|
||||
],
|
||||
'is_indirect' => false,
|
||||
'is_abstract' => false,
|
||||
'object_classes' => null,
|
||||
'target_class' => null,
|
||||
'entry_options' => null,
|
||||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
]);
|
||||
@@ -53,6 +54,12 @@ class LinkSetType extends AbstractType
|
||||
/** @inheritdoc */
|
||||
public function buildView(FormView $view, FormInterface $form, array $options): void
|
||||
{
|
||||
$view->vars['labels'] = $this->oObjectService->getFormPresentationLabels($options['entry_options']['object_class'], 'list', $options['entry_options']['ext_key_to_me']);;
|
||||
$view->vars['labels'] = $this->oObjectService->getFormPresentationLabels($options['entry_options']['object_class'], 'list', $options['entry_options']['ext_key_to_me']);
|
||||
$view->vars['object_class'] = $options['entry_options']['object_class'];
|
||||
$view->vars['ext_key_to_me'] = $options['entry_options']['ext_key_to_me'];
|
||||
$view->vars['target_class'] = $options['target_class'];
|
||||
$view->vars['is_indirect'] = $options['is_indirect'];
|
||||
$view->vars['is_abstract'] = $options['is_abstract'];
|
||||
$view->vars['object_classes'] = $options['object_classes'];
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Form\Type;
|
||||
namespace Combodo\iTop\DI\Form\Type\Compound;
|
||||
|
||||
use Combodo\iTop\DI\Form\Type\Layout\FieldSetType;
|
||||
use MetaModel;
|
||||
@@ -95,13 +95,13 @@ class ConfigurationType extends AbstractType
|
||||
/**
|
||||
* Handle category.
|
||||
*
|
||||
* @param $aCategories
|
||||
* @param $aSettings
|
||||
* @param $builder
|
||||
* @param array $aCategories
|
||||
* @param array $aSettings
|
||||
* @param FormBuilderInterface $builder
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function handleCategories($aCategories, $aSettings, $builder)
|
||||
private function handleCategories(array $aCategories, array $aSettings, FormBuilderInterface $builder)
|
||||
{
|
||||
// iterate throw categories...
|
||||
foreach ($aCategories as $sKey => $sValue) {
|
||||
@@ -145,12 +145,12 @@ class ConfigurationType extends AbstractType
|
||||
* Handle array of entries.
|
||||
*
|
||||
* @param array $aEntries
|
||||
* @param $aSettings
|
||||
* @param $builder
|
||||
* @param array $aSettings
|
||||
* @param FormBuilderInterface $builder
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function handleEntries(array $aEntries, $aSettings, $builder)
|
||||
private function handleEntries(array $aEntries, array $aSettings, FormBuilderInterface $builder)
|
||||
{
|
||||
// iterate throw entries...
|
||||
foreach ($aEntries as $sKey => $aValue){
|
||||
@@ -168,12 +168,12 @@ class ConfigurationType extends AbstractType
|
||||
/**
|
||||
* Return form type depending on settings definition.
|
||||
*
|
||||
* @param $aSettings
|
||||
* @param $sKey
|
||||
* @param array $aSettings
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getFormType($aSettings, $sKey) : string{
|
||||
private function getFormType(array $aSettings, string $sKey) : string{
|
||||
|
||||
if(!array_key_exists($sKey, $aSettings)){
|
||||
return TextType::class;
|
||||
@@ -190,13 +190,16 @@ class ConfigurationType extends AbstractType
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $aSettings
|
||||
* @param $sKey
|
||||
* @param $sTopic
|
||||
* Get parameter setting topic.
|
||||
*
|
||||
* @return string
|
||||
* @param array $aSettings
|
||||
* @param string $sKey
|
||||
* @param string $sTopic
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function getTopic($aSettings, $sKey, $sTopic) : ?string{
|
||||
private function getTopic(array $aSettings, string $sKey, string $sTopic) : ?string
|
||||
{
|
||||
|
||||
if(!array_key_exists($sKey, $aSettings)){
|
||||
return null;
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Form\Type;
|
||||
namespace Combodo\iTop\DI\Form\Type\Compound;
|
||||
|
||||
use Combodo\iTop\DI\Form\Builder\AttributeBuilder;
|
||||
use Combodo\iTop\DI\Form\Listener\ObjectFormListener;
|
||||
use Combodo\iTop\DI\Services\ObjectPresentationService;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
@@ -17,19 +17,19 @@ class ObjectSingleAttributeType extends AbstractType
|
||||
/** @var ObjectFormListener object form modifier */
|
||||
private ObjectFormListener $oObjectFormModifier;
|
||||
|
||||
/** @var ObjectPresentationService object presentation service */
|
||||
private ObjectPresentationService $objectPresentationService;
|
||||
/** @var AttributeBuilder attribute builder */
|
||||
private AttributeBuilder $oAttributeBuilder;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ObjectFormListener $oObjectFormModifier
|
||||
* @param ObjectPresentationService $objectPresentationService
|
||||
* @param AttributeBuilder $oAttributeBuilder
|
||||
*/
|
||||
public function __construct(ObjectFormListener $oObjectFormModifier, ObjectPresentationService $objectPresentationService)
|
||||
public function __construct(ObjectFormListener $oObjectFormModifier, AttributeBuilder $oAttributeBuilder)
|
||||
{
|
||||
$this->oObjectFormModifier = $oObjectFormModifier;
|
||||
$this->objectPresentationService = $objectPresentationService;
|
||||
$this->oAttributeBuilder = $oAttributeBuilder;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@@ -41,11 +41,13 @@ class ObjectSingleAttributeType extends AbstractType
|
||||
]);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
/** @inheritdoc
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
// build form from options
|
||||
$sFormType = $this->objectPresentationService->GetAttributeFormType($options['object_class'], $options['att_code']);
|
||||
$sFormType = $this->oAttributeBuilder->createAttribute($options['object_class'], $options['att_code']);
|
||||
|
||||
// add form field
|
||||
$builder->add($options['att_code'], $sFormType['type'], $sFormType['options']);
|
||||
@@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\DI\Form\Type;
|
||||
namespace Combodo\iTop\DI\Form\Type\Compound;
|
||||
|
||||
use cmdbAbstractObject;
|
||||
use Combodo\iTop\DI\Form\Builder\AttributeBuilder;
|
||||
use Combodo\iTop\DI\Form\Builder\LayoutBuilder;
|
||||
use Combodo\iTop\DI\Form\Listener\ObjectFormListener;
|
||||
use Combodo\iTop\DI\Services\ObjectPresentationService;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
@@ -25,16 +27,26 @@ class ObjectType extends AbstractType
|
||||
/** @var ObjectPresentationService object presentation service */
|
||||
private ObjectPresentationService $objectPresentationService;
|
||||
|
||||
/** @var \Combodo\iTop\DI\Form\Builder\AttributeBuilder attribute builder */
|
||||
private AttributeBuilder $oAttributeBuilder;
|
||||
|
||||
/** @var \Combodo\iTop\DI\Form\Builder\LayoutBuilder layout builder */
|
||||
private LayoutBuilder $oLayoutBuilder;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ObjectFormListener $oObjectFormModifier
|
||||
* @param ObjectPresentationService $objectPresentationService
|
||||
* @param \Combodo\iTop\DI\Form\Builder\AttributeBuilder $oAttributeBuilder
|
||||
* @param \Combodo\iTop\DI\Form\Builder\LayoutBuilder $oLayoutBuilder
|
||||
*/
|
||||
public function __construct(ObjectFormListener $oObjectFormModifier, ObjectPresentationService $objectPresentationService)
|
||||
public function __construct(ObjectFormListener $oObjectFormModifier, ObjectPresentationService $objectPresentationService, AttributeBuilder $oAttributeBuilder, LayoutBuilder $oLayoutBuilder)
|
||||
{
|
||||
$this->oObjectFormModifier = $oObjectFormModifier;
|
||||
$this->objectPresentationService = $objectPresentationService;
|
||||
$this->oAttributeBuilder = $oAttributeBuilder;
|
||||
$this->oLayoutBuilder = $oLayoutBuilder;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@@ -48,24 +60,29 @@ class ObjectType extends AbstractType
|
||||
'class' => 'z_list_details'
|
||||
],
|
||||
'object_class' => null,
|
||||
'locked_attributes' => null,
|
||||
'data_class' => cmdbAbstractObject::class,
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
/** @inheritdoc */
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
// build form from presentation
|
||||
$this->objectPresentationService->buildFormFromPresentation($options['object_class'], $options['z_list'], $options['is_link_set'], $options['ext_key_to_me'], $builder);
|
||||
$this->objectPresentationService->buildFormFromPresentation(
|
||||
$options['object_class'],
|
||||
$options['z_list'],
|
||||
$options['is_link_set'],
|
||||
$options['ext_key_to_me'],
|
||||
$options['locked_attributes'],
|
||||
$builder);
|
||||
|
||||
// dynamic form handling
|
||||
$builder->addEventSubscriber($this->oObjectFormModifier);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function buildView(FormView $view, FormInterface $form, array $options)
|
||||
{
|
||||
parent::buildView($view, $form, $options);
|
||||
@@ -40,6 +40,8 @@ class ITopKernel extends BaseKernel
|
||||
* @param \Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator $container
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @suppress-unused-warning
|
||||
*/
|
||||
protected function configureContainer(ContainerConfigurator $container): void
|
||||
{
|
||||
|
||||
@@ -2,35 +2,10 @@
|
||||
|
||||
namespace Combodo\iTop\DI\Services;
|
||||
|
||||
use AttributeBoolean;
|
||||
use AttributeDate;
|
||||
use AttributeDateTime;
|
||||
use AttributeEmailAddress;
|
||||
use AttributeEnum;
|
||||
use AttributeExternalKey;
|
||||
use AttributeImage;
|
||||
use AttributeLinkedSet;
|
||||
use AttributePassword;
|
||||
use AttributePhoneNumber;
|
||||
use AttributeText;
|
||||
use Combodo\iTop\DI\Form\Type\Layout\ColumnType;
|
||||
use Combodo\iTop\DI\Form\Type\Simple\ExternalKeyType;
|
||||
use Combodo\iTop\DI\Form\Type\Layout\FieldSetType;
|
||||
use Combodo\iTop\DI\Form\Type\Layout\RowType;
|
||||
use Combodo\iTop\DI\Form\Type\Simple\DocumentType;
|
||||
use Combodo\iTop\DI\Form\Type\Simple\LinkSetType;
|
||||
use Combodo\iTop\DI\Form\Builder\AttributeBuilder;
|
||||
use Combodo\iTop\DI\Form\Builder\LayoutBuilder;
|
||||
use Dict;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TelType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
/**
|
||||
@@ -39,54 +14,71 @@ use Symfony\Component\Form\FormBuilderInterface;
|
||||
*/
|
||||
class ObjectPresentationService
|
||||
{
|
||||
/** @var \Combodo\iTop\DI\Form\Builder\LayoutBuilder $oLayoutBuilder */
|
||||
private LayoutBuilder $oLayoutBuilder;
|
||||
|
||||
/** @var \Combodo\iTop\DI\Form\Builder\AttributeBuilder $oAttributeBuilder */
|
||||
private AttributeBuilder $oAttributeBuilder;
|
||||
|
||||
/**
|
||||
* @param \Combodo\iTop\DI\Form\Builder\LayoutBuilder $oLayoutBuilder
|
||||
* @param \Combodo\iTop\DI\Form\Builder\AttributeBuilder $oAttributeBuilder
|
||||
*/
|
||||
public function __construct(LayoutBuilder $oLayoutBuilder, AttributeBuilder $oAttributeBuilder)
|
||||
{
|
||||
$this->oLayoutBuilder = $oLayoutBuilder;
|
||||
$this->oAttributeBuilder = $oAttributeBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* buildFormFromPresentation.
|
||||
*
|
||||
* @param $class
|
||||
* @param $zList
|
||||
* @param $isLinkSet
|
||||
* @param $sExtKeyToMe
|
||||
* @param string $class
|
||||
* @param string $sZList
|
||||
* @param bool $isLinkSet
|
||||
* @param string|null $sExtKeyToMe
|
||||
* @param array|null $lockedAttributes
|
||||
* @param \Symfony\Component\Form\FormBuilderInterface $builder
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function buildFormFromPresentation($class, $zList, $isLinkSet, $sExtKeyToMe, FormBuilderInterface $builder)
|
||||
public function buildFormFromPresentation(string $class, string $sZList, bool $isLinkSet, ?string $sExtKeyToMe, ?array $lockedAttributes, FormBuilderInterface $builder)
|
||||
{
|
||||
// retrieve presentation
|
||||
$aPresentation = MetaModel::GetZListItems($class, $zList);
|
||||
$aPresentation = MetaModel::GetZListItems($class, $sZList);
|
||||
|
||||
// filter zList for links set
|
||||
if($isLinkSet){
|
||||
$aPresentation = $this->filterLinkSetpresentation($aPresentation, $class, $sExtKeyToMe);
|
||||
$aPresentation = $this->filterLinkSetPresentation($aPresentation, $class, $sExtKeyToMe);
|
||||
}
|
||||
|
||||
$level = $this->handleLevel($aPresentation, $class);
|
||||
|
||||
// handle level
|
||||
$level = $this->handleLevel($aPresentation, $class, $lockedAttributes);
|
||||
foreach ($level as $key => $value) {
|
||||
$value['options']['attr']['data-att-code'] = $key;
|
||||
$builder->add($key, $value['type'], $value['options']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* filterLinkSetpresentation.
|
||||
* filterLinkSetPresentation.
|
||||
*
|
||||
* @param $aPresentation
|
||||
* @param $class
|
||||
* @param $sExtKeyToMe
|
||||
* @param array $aPresentation
|
||||
* @param string $sClass
|
||||
* @param string|null $sExtKeyToMe
|
||||
*
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function filterLinkSetpresentation($aPresentation, $class, $sExtKeyToMe){
|
||||
private function filterLinkSetPresentation(array $aPresentation, string $sClass, ?string $sExtKeyToMe) : array
|
||||
{
|
||||
|
||||
$aNewPresentation = [];
|
||||
foreach($aPresentation as $sLinkedAttCode)
|
||||
{
|
||||
if ($sLinkedAttCode != $sExtKeyToMe)
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($class, $sLinkedAttCode);
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sLinkedAttCode);
|
||||
|
||||
if ((!$oAttDef->IsExternalField() || ($oAttDef->GetKeyAttCode() != $sExtKeyToMe)) &&
|
||||
(!$oAttDef->IsLinkSet()) )
|
||||
@@ -101,20 +93,34 @@ class ObjectPresentationService
|
||||
return $aNewPresentation;
|
||||
}
|
||||
|
||||
|
||||
public function getFormPresentationLabels($class, $zList, $sExtKeyToMe)
|
||||
/**
|
||||
* @param $class
|
||||
* @param $zList
|
||||
* @param $sExtKeyToMe
|
||||
*
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getFormPresentationLabels($class, $zList, $sExtKeyToMe) : array
|
||||
{
|
||||
// retrieve presentation
|
||||
$aPresentation = MetaModel::GetZListItems($class, $zList);
|
||||
$aPresentation = $this->filterLinkSetpresentation($aPresentation, $class, $sExtKeyToMe);
|
||||
|
||||
$level = $this->handleLevel($aPresentation, $class);
|
||||
$labels = [];
|
||||
$level = $this->handleLevel($aPresentation, $class, null, null);
|
||||
$aLabels = [];
|
||||
foreach ($level as $key => $value) {
|
||||
$value['options']['attr']['data-att-code'] = $key;
|
||||
$labels[] = $key;
|
||||
|
||||
$sKey = "Class:$class/Attribute:$key";
|
||||
if(Dict::Exists($sKey)){
|
||||
$aLabels[] = Dict::S($sKey);
|
||||
}
|
||||
else{
|
||||
$aLabels[] = $key;
|
||||
}
|
||||
}
|
||||
return $labels;
|
||||
return $aLabels;
|
||||
}
|
||||
|
||||
|
||||
@@ -122,26 +128,30 @@ class ObjectPresentationService
|
||||
* handleLevel.
|
||||
*
|
||||
* @param array $aElement
|
||||
* @param $dataClass
|
||||
* @param string $sDataClass
|
||||
* @param array|null $lockedAttributes
|
||||
*
|
||||
* @return array
|
||||
* @throws \CoreException
|
||||
*/
|
||||
private function handleLevel(array $aElement, $dataClass) : array
|
||||
private function handleLevel(array $aElement, string $sDataClass, ?array $lockedAttributes) : array
|
||||
{
|
||||
$aChildren = [];
|
||||
$aRowCol = [];
|
||||
$aRowCols = [];
|
||||
|
||||
// iterate trow level entries...
|
||||
foreach ($aElement as $key => $item){
|
||||
|
||||
// column
|
||||
if(str_starts_with($key, 'col')){
|
||||
$aRowCol[$key] = $this->createColumn($key, $item, $dataClass);
|
||||
$this->handleDynamics($key, $aRowCol[$key]);
|
||||
$aItems = $this->handleLevel($item, $sDataClass, $lockedAttributes);
|
||||
$aRowCols[$key] = $this->oLayoutBuilder->createColumn($key, $aItems);
|
||||
$this->handleDynamics($key, $aRowCols[$key]);
|
||||
}
|
||||
// field set
|
||||
else if(str_starts_with($key, 'fieldset')){
|
||||
$aChildren[$key] =$this->createFieldSet($key, $item, $dataClass);
|
||||
$aItems = $this->handleLevel($item, $sDataClass, $lockedAttributes);
|
||||
$aChildren[$key] = $this->oLayoutBuilder->createFieldSet($key, $aItems);
|
||||
$this->handleDynamics($key, $aChildren[$key]);
|
||||
}
|
||||
// logs
|
||||
@@ -150,7 +160,7 @@ class ObjectPresentationService
|
||||
}
|
||||
// others
|
||||
else{
|
||||
$sFormType = $this->GetAttributeFormType($dataClass, $item);
|
||||
$sFormType = $this->oAttributeBuilder->createAttribute($sDataClass, $item, $lockedAttributes);
|
||||
if($sFormType !== null){
|
||||
$sFormType['options']['attr']['data-att-code'] = $item;
|
||||
$aChildren[$item] = $sFormType;
|
||||
@@ -159,8 +169,8 @@ class ObjectPresentationService
|
||||
}
|
||||
}
|
||||
|
||||
if(count($aRowCol)){
|
||||
$aChildren['row'] = $this->createRow('row', $aRowCol, $dataClass);
|
||||
if(count($aRowCols)){
|
||||
$aChildren['row'] = $this->oLayoutBuilder->createRow('row', $aRowCols);
|
||||
}
|
||||
|
||||
return $aChildren;
|
||||
@@ -201,207 +211,4 @@ class ObjectPresentationService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* createRow.
|
||||
*
|
||||
* @param $key
|
||||
* @param $columns
|
||||
* @param $dataClass
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function createRow($key, $columns, $dataClass) : array
|
||||
{
|
||||
return [
|
||||
'type' => RowType::class,
|
||||
'options' => [
|
||||
'items' => $columns,
|
||||
'label' => false,
|
||||
'row_attr' => [
|
||||
'data-block' => 'container'
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* createColumn.
|
||||
*
|
||||
* @param $key
|
||||
* @param $item
|
||||
* @param $dataClass
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function createColumn($key, $item, $dataClass) : array
|
||||
{
|
||||
return [
|
||||
'type' => ColumnType::class,
|
||||
'options' => [
|
||||
'items' => $this->handleLevel($item, $dataClass),
|
||||
'label' => false,
|
||||
'row_attr' => [
|
||||
'data-block' => 'container'
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* createFieldSet.
|
||||
*
|
||||
* @param $key
|
||||
* @param $item
|
||||
* @param $dataClass
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function createFieldSet($key, $item, $dataClass) : array
|
||||
{
|
||||
return [
|
||||
'type' => FieldSetType::class,
|
||||
'options' => [
|
||||
'items' => $this->handleLevel($item, $dataClass),
|
||||
'label' => Dict::S(substr($key, 9)),
|
||||
'row_attr' => [
|
||||
'data-block' => 'container'
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Map AttributeDefinition >> FormType
|
||||
*
|
||||
* @param string $sObjectClass
|
||||
* @param string $sCode
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function GetAttributeFormType(string $sObjectClass, string $sCode) : ?array
|
||||
{
|
||||
// load attribute definition
|
||||
try {
|
||||
$oAttributeDefinition = MetaModel::GetAttributeDef($sObjectClass, $sCode);
|
||||
$sLabel = $oAttributeDefinition->GetLabel();
|
||||
}
|
||||
catch(Exception $e){
|
||||
return null;
|
||||
}
|
||||
|
||||
// create global form type
|
||||
$aFormType = [
|
||||
'type' => TextType::class,
|
||||
'label' => $sLabel,
|
||||
'options' => [
|
||||
'required' => !$oAttributeDefinition->IsNullAllowed(),
|
||||
'disabled' => !$oAttributeDefinition->IsWritable(),
|
||||
]
|
||||
];
|
||||
|
||||
// inject corresponding configuration
|
||||
if($oAttributeDefinition instanceof AttributeExternalKey){
|
||||
$aFormType['type'] = ExternalKeyType::class;
|
||||
$aFormType['options']['display_style'] = 'list';
|
||||
$aFormType['options']['allow_target_creation'] = true;
|
||||
$aFormType['options']['object_class'] = $oAttributeDefinition->GetTargetClass();
|
||||
$aFormType['options']['att_code'] = $oAttributeDefinition->GetCode();
|
||||
|
||||
try{
|
||||
$oObjectsSet = MetaModel::GetAllowedValuesAsObjectSet($oAttributeDefinition->GetHostClass(), $oAttributeDefinition->GetCode(), []);
|
||||
$aFormType['options']['choices'] = $this->ToChoices($oObjectsSet);
|
||||
}
|
||||
catch(Exception $e){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeEmailAddress){
|
||||
$aFormType['type'] = EmailType::class;
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributePassword){
|
||||
$aFormType['type'] = PasswordType::class;
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributePhoneNumber){
|
||||
$aFormType['type'] = TelType::class;
|
||||
$aFormType['options']['attr'] = [
|
||||
'pattern' => '\+[0-9]{2}\s[0-9]\s[0-9]{2}\s[0-9]{2}\s[0-9]{2}\s[0-9]{2}',
|
||||
'placeholder' => '+-- - -- -- --'
|
||||
];
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeBoolean){
|
||||
$aFormType['type'] = CheckboxType::class;
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeEnum){
|
||||
$aFormType['type'] = ChoiceType::class;
|
||||
try{
|
||||
$aOptions = array_flip($oAttributeDefinition->GetAllowedValues());
|
||||
}
|
||||
catch(Exception $e){
|
||||
$aOptions = [];
|
||||
}
|
||||
$aFormType['options']['choices'] = $aOptions;
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeImage){
|
||||
$aFormType['type'] = DocumentType::class;
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeLinkedSet){
|
||||
$aFormType['type'] = LinkSetType::class;
|
||||
$aFormType['options']['entry_options'] = [
|
||||
'object_class' => $oAttributeDefinition->GetLinkedClass(),
|
||||
'data_class' => $oAttributeDefinition->GetLinkedClass(),
|
||||
'is_link_set' => true,
|
||||
'ext_key_to_me' => $oAttributeDefinition->GetExtKeyToMe(),
|
||||
'z_list' => 'list',
|
||||
'attr' => [
|
||||
'class' => 'z_list_list'
|
||||
]
|
||||
];
|
||||
$aFormType['options']['attr'] = [
|
||||
'class' => 'link_set'
|
||||
];
|
||||
$aFormType['options']['label_attr'] = [
|
||||
'class' => 'combodo-field-set-label'
|
||||
];
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeText){
|
||||
$aFormType['type'] = TextareaType::class;
|
||||
$aFormType['options']['attr']['rows'] = 10;
|
||||
$aFormType['options']['attr']['data-widget'] = 'text_widget';
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeDate){
|
||||
$aFormType['type'] = DateType::class;
|
||||
$aFormType['options']['input'] = 'string';
|
||||
}
|
||||
else if($oAttributeDefinition instanceof AttributeDateTime){
|
||||
$aFormType['type'] = DateTimeType::class;
|
||||
$aFormType['options']['input'] = 'string';
|
||||
$aFormType['options']['widget'] = 'single_text';
|
||||
$aFormType['options']['with_seconds'] = true;
|
||||
}
|
||||
|
||||
if(count($oAttributeDefinition->GetPrerequisiteAttributes()) > 0){
|
||||
$dependencies = implode(' ', $oAttributeDefinition->GetPrerequisiteAttributes());
|
||||
$aFormType['options']['attr']['data-depends-on'] = $dependencies;
|
||||
$aFormType['depends_on'] = $dependencies;
|
||||
}
|
||||
|
||||
$aFormType['options']['row_attr']['data-block'] = 'container';
|
||||
|
||||
return $aFormType;
|
||||
}
|
||||
|
||||
public function ToChoices($oObjectsSet) : array
|
||||
{
|
||||
$aChoices = [];
|
||||
|
||||
$i = 0;
|
||||
|
||||
while ($i < 100 && $oObj = $oObjectsSet->Fetch()) {
|
||||
$aChoices[$oObj->GetName()] = $oObj->GetKey();
|
||||
$i++;
|
||||
}
|
||||
|
||||
return $aChoices;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,10 @@
|
||||
namespace Combodo\iTop\DI\Services;
|
||||
|
||||
use AttributeLinkedSet;
|
||||
use Combodo\iTop\Core\MetaModel\FriendlyNameType;
|
||||
use Combodo\iTop\Service\Base\ObjectRepository;
|
||||
use DBObject;
|
||||
use DBObjectSet;
|
||||
use MetaModel;
|
||||
use ormLinkSet;
|
||||
|
||||
@@ -27,20 +30,52 @@ class ObjectService
|
||||
$this->sDbName = $sDbName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param $sRef
|
||||
*
|
||||
* @return DBObject
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function getObject(string $sClass, $sRef) : DBObject
|
||||
{
|
||||
if($sRef !== 0){
|
||||
return MetaModel::GetObject($sClass, $sRef);
|
||||
}
|
||||
else{
|
||||
return MetaModel::NewObject($sClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert object set to array of choices.
|
||||
*
|
||||
* @param $oObjectsSet
|
||||
* @param DBObjectSet $oObjectsSet
|
||||
*
|
||||
* @return array
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
public function ToChoices($oObjectsSet) : array
|
||||
public function ToChoices(DBObjectSet $oObjectsSet) : array
|
||||
{
|
||||
$aChoices = [];
|
||||
|
||||
$i = 0;
|
||||
// Retrieve friendly name complementary specification
|
||||
$aComplementAttributeSpec = MetaModel::GetNameSpec($oObjectsSet->GetClass(), FriendlyNameType::COMPLEMENTARY);
|
||||
|
||||
while ($i < 100 && $oObj = $oObjectsSet->Fetch()) {
|
||||
// Retrieve image attribute code
|
||||
$sObjectImageAttCode = MetaModel::GetImageAttributeCode($oObjectsSet->GetClass());
|
||||
|
||||
// Prepare fields to load
|
||||
$aDefaultFieldsToLoad = ObjectRepository::GetDefaultFieldsToLoad($aComplementAttributeSpec, $sObjectImageAttCode);
|
||||
|
||||
$oObjectsSet->OptimizeColumnLoad([$oObjectsSet->GetClassAlias() => $aDefaultFieldsToLoad]);
|
||||
|
||||
$i = 0;
|
||||
while ($i < 30 && $oObj = $oObjectsSet->Fetch()) {
|
||||
$aChoices[$oObj->GetName()] = $oObj->GetKey();
|
||||
$i++;
|
||||
}
|
||||
@@ -64,12 +99,27 @@ class ObjectService
|
||||
return $this->sDbName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DBObject $object
|
||||
*
|
||||
* @return void
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreCannotSaveObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \CoreWarning
|
||||
* @throws \DeleteException
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function handleLinkSetDB(DBObject $object){
|
||||
foreach($object->GetValues() as $key => $value){
|
||||
if($value instanceof ormLinkSet){
|
||||
|
||||
/** @var AttributeLinkedSet $a */
|
||||
$a = MetaModel::GetAttributeDef(get_class($object), $key);
|
||||
/** @var AttributeLinkedSet $a */
|
||||
$a = MetaModel::GetAttributeDef(get_class($object), $key);
|
||||
|
||||
/** @var DBObject $link */
|
||||
foreach($value->ListModifiedLinks() as $link){
|
||||
@@ -78,7 +128,6 @@ class ObjectService
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @var DBObject $link */
|
||||
foreach($value->ListModifiedLinks() as $link){
|
||||
if($link->IsNew()){
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Combodo\iTop\DI\Services;
|
||||
|
||||
use MetaModel;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
@@ -11,7 +12,8 @@ use Twig\TwigFunction;
|
||||
*/
|
||||
class TwigHelper extends AbstractExtension
|
||||
{
|
||||
private string $sAppRoot = '';
|
||||
/** @var string|mixed application root */
|
||||
private string $sAppRoot;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -19,7 +21,7 @@ class TwigHelper extends AbstractExtension
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->sAppRoot = \MetaModel::GetConfig()->Get('app_root_url');
|
||||
$this->sAppRoot = MetaModel::GetConfig()->Get('app_root_url');
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@@ -37,7 +39,7 @@ class TwigHelper extends AbstractExtension
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function asset_js($name)
|
||||
public function asset_js($name) : string
|
||||
{
|
||||
return $this->sAppRoot . 'js/' . $name;
|
||||
}
|
||||
@@ -47,7 +49,7 @@ class TwigHelper extends AbstractExtension
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function asset_css($name)
|
||||
public function asset_css($name) : string
|
||||
{
|
||||
return $this->sAppRoot . 'css/' . $name;
|
||||
}
|
||||
@@ -57,7 +59,7 @@ class TwigHelper extends AbstractExtension
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function asset_image($name)
|
||||
public function asset_image($name) : string
|
||||
{
|
||||
return $this->sAppRoot . 'images/' . $name;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user