poc form SDK (extends to form)

This commit is contained in:
Benjamin Dalsass
2023-08-24 14:29:31 +02:00
parent 245c1d0be5
commit 20ae64706a
3325 changed files with 1500 additions and 547966 deletions

View File

@@ -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;
}
}