The actual field will be added when the form is built. This approach makes it easier to set up dependencies at the same time when creating the form field object.
<?php
namespace wcf\system\form\builder;
use wcf\system\form\builder\field\dependency\IFormFieldDependency;
+use wcf\system\form\builder\field\IFormField;
/**
* Provides default implementations of `IFormNode` methods.
$this->isPopulated = true;
+ // add dependent fields
+ foreach ($this->getDependencies() as $dependency) {
+ if ($dependency->getField() === null) {
+ if ($dependency->getFieldId() === null) {
+ throw new \UnexpectedValueException("Dependency '{$dependency->getId()}' for node '{$this->getId()}' has no field.");
+ }
+
+ /** @var IFormField $field */
+ $field = $this->getDocument()->getNodeById($dependency->getFieldId());
+ if ($field === null) {
+ throw new \UnexpectedValueException("Unknown field with id '{$dependency->getFieldId()}' for dependency '{$dependency->getId()}'.");
+ }
+
+ $dependency->field($field);
+ }
+ }
+
return $this;
}
<?php
namespace wcf\system\form\builder\field\dependency;
+use http\Exception\BadMethodCallException;
use wcf\system\form\builder\field\IFormField;
use wcf\system\form\builder\IFormNode;
use wcf\system\WCF;
*/
protected $field;
+ /**
+ * id of the field the availability of the node dependents on
+ * @var string
+ */
+ protected $fieldId;
+
/**
* id of the dependency
* @var string
return $this;
}
+ /**
+ * @inheritDoc
+ */
+ public function fieldId($fieldId) {
+ if ($this->getField() !== null) {
+ throw new \BadMethodCallException("Cannot set field id after field has been set.");
+ }
+
+ $this->fieldId = $fieldId;
+
+ return $this;
+ }
+
/**
* @inheritDoc
*/
* @inheritDoc
*/
public function getField() {
- if ($this->field === null) {
- throw new \BadMethodCallException("Field has not been set.");
+ return $this->field;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getFieldId() {
+ if ($this->getField() !== null) {
+ return $this->getField()->getId();
}
- return $this->field;
+ if ($this->fieldId === null) {
+ throw new \BadMethodCallException("Neither the field nor the field id has been set.");
+ }
+
+ return $this->fieldId;
}
/**
*/
public function field(IFormField $field);
+ /**
+ * Sets the id of the field the availability of the node dependents on.
+ *
+ * This method should only be used before building the form as afterwards,
+ * the actual field is no automatically set.
+ *
+ * @param string $fieldId field id
+ * @return static this dependency
+ *
+ * @throws \BadMethodCallException if the field has already been set
+ */
+ public function fieldId($fieldId);
+
/**
* Returns the node whose availability depends on the value of a field.
*
public function getDependentNode();
/**
- * Returns the field the availability of the element dependents on.
+ * Returns the field the availability of the element dependents on or `null` if the field has
+ * not been set yet.
*
* @return IFormField field controlling element availability
*/
public function getField();
+ /**
+ * Returns the id of the field the availability of the node dependents on;
+ *
+ * @return string
+ * @throws \BadMethodCallException if neither field not field id has been set
+ */
+ public function getFieldId();
+
/**
* Returns the JavaScript code required to ensure this dependency in the template.
*
->objectProperty('categoryname')
->label('wcf.acp.pip.aclOption.options.categoryName')
->description('wcf.acp.pip.aclOption.options.categoryName.description')
- ->options(['' => 'wcf.global.noSelection'] + $categories[$objectTypeID]);
-
- $categoryNameField->addDependency(
- ValueFormFieldDependency::create('objectType')
- ->field($objectTypeFormField)
- ->values([$objectType])
- );
+ ->options(['' => 'wcf.global.noSelection'] + $categories[$objectTypeID])
+ ->addDependency(
+ ValueFormFieldDependency::create('objectType')
+ ->field($objectTypeFormField)
+ ->values([$objectType])
+ );
$dataContainer->appendChild($categoryNameField);
}
return $value === 0 || $value == 3;
}));
- $dataContainer->appendChild(IconFormField::create('icon')
+ $dataContainer->appendChild(
+ IconFormField::create('icon')
->label('wcf.acp.pip.acpMenu.icon')
- ->description('wcf.acp.pip.acpMenu.icon.description')
- ->required()
- ->addDependency(
- ValueFormFieldDependency::create('parentMenuItem')
- ->field($parentMenuItemFormField)
- ->values($iconParentMenuItems)
- ));
+ ->description('wcf.acp.pip.acpMenu.icon.description')
+ ->required()
+ ->addDependency(
+ ValueFormFieldDependency::create('parentMenuItem')
+ ->field($parentMenuItemFormField)
+ ->values($iconParentMenuItems)
+ )
+ );
// add additional data to default fields
->label('wcf.acp.pip.bbcode.buttonLabel')
->description('wcf.acp.pip.bbcode.buttonLabel.description')
->required()
- ->maximumLength(255),
+ ->maximumLength(255)
+ ->addDependency(
+ NonEmptyFormFieldDependency::create('showButton')
+ ->fieldId('showButton')
+ ),
RadioButtonFormField::create('iconType')
->label('wcf.acp.pip.bbcode.iconType')
'fontAwesome' => 'wcf.acp.pip.bbcode.iconType.fontAwesome',
])
->required()
- ->value('fontAwesome'),
+ ->value('fontAwesome')
+ ->addDependency(
+ NonEmptyFormFieldDependency::create('showButton')
+ ->fieldId('showButton')
+ ),
TextFormField::create('iconPath')
->objectProperty('wysiwygicon')
)
);
}
- })),
+ }))
+ ->addDependency(
+ ValueFormFieldDependency::create('iconType')
+ ->fieldId('iconType')
+ ->values(['filePath'])
+ ),
IconFormField::create('fontAwesomeIcon')
->objectProperty('wysiwygicon')
->label('wcf.acp.pip.bbcode.wysiwygIcon')
->required()
+ ->addDependency(
+ ValueFormFieldDependency::create('iconType')
+ ->fieldId('iconType')
+ ->values(['fontAwesome'])
+ )
]);
$form->appendChild(
// discard the `iconType` value as it is only used to distinguish the two icon input fields
$form->getDataHandler()->add(new VoidFormFieldDataProcessor('iconType'));
-
- // add dependencies
- /** @var BooleanFormField $showButton */
- $showButton = $dataContainer->getNodeById('showButton');
-
- /** @var RadioButtonFormField $iconType */
- $iconType = $dataContainer->getNodeById('iconType');
-
- $dataContainer->getNodeById('buttonLabel')->addDependency(
- NonEmptyFormFieldDependency::create('showButton')
- ->field($showButton)
- );
- $iconType->addDependency(
- NonEmptyFormFieldDependency::create('showButton')
- ->field($showButton)
- );
- $dataContainer->getNodeById('iconPath')->addDependency(
- ValueFormFieldDependency::create('iconType')
- ->field($iconType)
- ->values(['filePath'])
- );
- $dataContainer->getNodeById('fontAwesomeIcon')->addDependency(
- ValueFormFieldDependency::create('iconType')
- ->field($iconType)
- ->values(['fontAwesome'])
- );
}
/**
asort($options);
return $options;
- }),
+ })
+ ->addDependency(
+ ValueFormFieldDependency::create('boxType')
+ ->fieldId('boxType')
+ ->values(['system'])
+ ),
SingleSelectionFormField::create('position')
->label('wcf.acp.pip.box.position')
->i18n()
->i18nRequired()
->languageItemPattern('__NONE__')
+ ->addDependency(
+ ValueFormFieldDependency::create('boxType')
+ ->fieldId('boxType')
+ ->values(['system'])
+ ->negate()
+ )
]);
// add box controller-specific form fields
$boxController->addPipGuiFormFields($form, $objectType->objectType);
}
}
-
- // add dependencies
-
- /** @var SingleSelectionFormField $boxType */
- $boxType = $dataContainer->getNodeById('boxType');
-
- $dataContainer->getNodeById('objectType')->addDependency(
- ValueFormFieldDependency::create('boxType')
- ->field($boxType)
- ->values(['system'])
- );
-
- $contentContainer->getNodeById('contentContent')->addDependency(
- ValueFormFieldDependency::create('pageType')
- ->field($boxType)
- ->values(['system'])
- ->negate()
- );
}
/**
return $categories;
}, false, false)
- ->filterable(),
+ ->filterable()
+ ->addDependency(
+ ValueFormFieldDependency::create('languageCategoryIDMode')
+ ->fieldId('languageCategoryIDMode')
+ ->values(['selection'])
+ ),
TextFormField::create('languageCategory')
->label('wcf.acp.language.item.languageCategoryID')
)
);
}
- })),
+ }))
+ ->addDependency(
+ ValueFormFieldDependency::create('languageCategoryIDMode')
+ ->fieldId('languageCategoryIDMode')
+ ->values(['new'])
+ ),
TextFormField::create('languageItem')
->label('wcf.acp.language.item.languageItem')
->description($description)
);
}
-
- // add dependencies
- /** @var SingleSelectionFormField $languageCategoryIDMode */
- $languageCategoryIDMode = $dataContainer->getNodeById('languageCategoryIDMode');
-
- $dataContainer->getNodeById('languageCategoryID')->addDependency(
- ValueFormFieldDependency::create('languageCategoryIDMode')
- ->field($languageCategoryIDMode)
- ->values(['selection'])
- );
- $dataContainer->getNodeById('languageCategory')->addDependency(
- ValueFormFieldDependency::create('languageCategoryIDMode')
- ->field($languageCategoryIDMode)
- ->values(['new'])
- );
}
/**
}
return $nestedOptions;
- }, true),
+ }, true)
+ ->addDependency(
+ ValueFormFieldDependency::create('linkType')
+ ->fieldId('linkType')
+ ->values(['internal'])
+ ),
TextFormField::create('externalURL')
->label('wcf.acp.pip.menuItem.externalURL')
->description('wcf.acp.pip.menuItem.externalURL.description')
->required()
->i18n()
+ ->addDependency(
+ ValueFormFieldDependency::create('linkType')
+ ->fieldId('linkType')
+ ->values(['external'])
+ )
]);
/** @var SingleSelectionFormField $menuField */
'linkType'
);
}
-
- // dependencies
-
- /** @var RadioButtonFormField $linkType */
- $linkType = $form->getNodeById('linkType');
- $form->getNodeById('menuItemPage')->addDependency(
- ValueFormFieldDependency::create('linkType')
- ->field($linkType)
- ->values(['internal'])
- );
-
- $form->getNodeById('externalURL')->addDependency(
- ValueFormFieldDependency::create('linkType')
- ->field($linkType)
- ->values(['external'])
- );
}
/**
SingleSelectionFormField::create('boxPosition')
->label('wcf.acp.pip.menu.boxPosition')
->description('wcf.acp.pip.menu.boxPosition.description')
- ->options(array_combine(Box::$availablePositions, Box::$availablePositions)),
+ ->options(array_combine(Box::$availablePositions, Box::$availablePositions))
+ ->addDependency(
+ ValueFormFieldDependency::create('identifier')
+ ->fieldId('identifier')
+ ->values(['com.woltlab.wcf.MainMenu'])
+ ->negate()
+ ),
BooleanFormField::create('boxShowHeader')
->label('wcf.acp.pip.menu.boxShowHeader'),
->field($createBox)
);
}
-
- /** @var TextFormField $identifier */
- $identifier = $form->getNodeById('identifier');
- $form->getNodeById('boxPosition')->addDependency(
- ValueFormFieldDependency::create('identifier')
- ->field($identifier)
- ->values(['com.woltlab.wcf.MainMenu'])
- ->negate()
- );
}
/**
);
}
}
- })),
+ }))
+ ->addDependency(
+ ValueFormFieldDependency::create('definitionID')
+ ->fieldId('definitionID')
+ ->values(array_keys($this->definitionInterfaces))
+ ),
]);
- /** @var SingleSelectionFormField $definitionID */
- $definitionID = $form->getNodeById('definitionID');
-
- // add general field dependencies
- $form->getNodeById('className')->addDependency(
- ValueFormFieldDependency::create('definitionID')
- ->field($definitionID)
- ->values(array_keys($this->definitionInterfaces))
- );
-
// add object type-specific fields
// com.woltlab.wcf.adLocation
switch ($this->entryType) {
case 'options':
+ /** @var SingleSelectionFormField $optionType */
+ $optionType = $form->getNodeById('optionType');
+
/** @var TextFormField $optionNameField */
$optionNameField = $dataContainer->getNodeById('optionName');
$optionNameField->addValidator(new FormFieldValidator('uniqueness', function(TextFormField $formField) {
->objectProperty('selectoptions')
->label('wcf.acp.pip.abstractOption.options.selectOptions')
->description('wcf.acp.pip.option.abstractOption.selectOptions.description')
- ->rows(5);
+ ->rows(5)
+ ->addDependency(
+ ValueFormFieldDependency::create('optionType')
+ ->field($optionType)
+ ->values($this->selectOptionOptionTypes)
+ );
$dataContainer->insertBefore($selectOptions, 'enableOptions');
BooleanFormField::create('supportI18n')
->objectProperty('supporti18n')
->label('wcf.acp.pip.option.options.supportI18n')
- ->description('wcf.acp.pip.option.options.supportI18n.description'),
+ ->description('wcf.acp.pip.option.options.supportI18n.description')
+ ->addDependency(
+ ValueFormFieldDependency::create('optionType')
+ ->field($optionType)
+ ->values($this->i18nOptionTypes)
+ ),
BooleanFormField::create('requireI18n')
->objectProperty('requirei18n')
->label('wcf.acp.pip.option.options.requireI18n')
- ->description('wcf.acp.pip.option.options.requireI18n.description'),
+ ->description('wcf.acp.pip.option.options.requireI18n.description')
+ ->addDependency(
+ NonEmptyFormFieldDependency::create('supportI18n')
+ ->fieldId('supportI18n')
+ ),
]);
- /** @var SingleSelectionFormField $optionType */
- $optionType = $form->getNodeById('optionType');
-
- /** @var BooleanFormField $supportI18n */
- $supportI18n = $form->getNodeById('supportI18n');
-
- $selectOptions->addDependency(
- ValueFormFieldDependency::create('optionType')
- ->field($optionType)
- ->values($this->selectOptionOptionTypes)
- );
-
- $supportI18n->addDependency(
- ValueFormFieldDependency::create('optionType')
- ->field($optionType)
- ->values($this->i18nOptionTypes)
- );
-
- $form->getNodeById('requireI18n')->addDependency(
- NonEmptyFormFieldDependency::create('supportI18n')
- ->field($supportI18n)
- );
-
// ensure proper normalization of select options
$form->getDataHandler()->add(new CustomFormFieldDataProcessor('selectOptions', function(IFormDocument $document, array $parameters) {
if (isset($parameters['data']['selectoptions'])) {
->description('wcf.acp.pip.templateListener.templateName.description')
->required()
->options(array_combine(array_keys($templateEvents), array_keys($templateEvents)))
- ->filterable(),
+ ->filterable()
+ ->addDependency(
+ ValueFormFieldDependency::create('environment')
+ ->fieldId('environment')
+ ->values(['user'])
+ ),
SingleSelectionFormField::create('acpTemplateName')
->objectProperty('templatename')
->required()
->options(array_combine(array_keys($acpTemplateEvents), array_keys($acpTemplateEvents)))
->filterable()
+ ->addDependency(
+ ValueFormFieldDependency::create('environment')
+ ->fieldId('environment')
+ ->values(['admin'])
+ )
]);
/** @var SingleSelectionFormField $frontendTemplateName */
))
]);
- /** @var SingleSelectionFormField $environment */
- $environment = $form->getNodeById('environment');
-
- $form->getNodeById('frontendTemplateName')->addDependency(
- ValueFormFieldDependency::create('environment')
- ->field($environment)
- ->values(['user'])
- );
- $form->getNodeById('acpTemplateName')->addDependency(
- ValueFormFieldDependency::create('environment')
- ->field($environment)
- ->values(['admin'])
- );
-
// ensure proper normalization of template code
$form->getDataHandler()->add(new CustomFormFieldDataProcessor('templateCode', function(IFormDocument $document, array $parameters) {
$parameters['data']['templatecode'] = StringUtil::unifyNewlines(StringUtil::escapeCDATA($parameters['data']['templatecode']));
->objectProperty('selectoptions')
->label('wcf.acp.pip.abstractOption.options.selectOptions')
->description('wcf.acp.pip.abstractOption.options.selectOptions.description')
- ->rows(5);
+ ->rows(5)
+ ->addDependency(
+ ValueFormFieldDependency::create('optionType')
+ ->field($optionType)
+ ->values($this->selectOptionOptionTypes)
+ );
$dataContainer->insertBefore($selectOptions, 'enableOptions');
),
]);
- $selectOptions->addDependency(
- ValueFormFieldDependency::create('optionType')
- ->field($optionType)
- ->values($this->selectOptionOptionTypes)
- );
-
// ensure proper normalization of select options
$form->getDataHandler()->add(new CustomFormFieldDataProcessor('selectOptions', function(IFormDocument $document, array $parameters) {
if (isset($parameters['data']['selectoptions'])) {