Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Form.php
Go to the documentation of this file.
1 <?php
7 
16 
25 class Form extends \Magento\Backend\Block\Widget\Form\Generic
26 {
27  const SCOPE_DEFAULT = 'default';
28 
29  const SCOPE_WEBSITES = 'websites';
30 
31  const SCOPE_STORES = 'stores';
32 
38  protected $_configData;
39 
45  protected $_configDataObject;
46 
52  protected $_fieldsetRenderer;
53 
59  protected $_fieldRenderer;
60 
66  protected $_fieldsets = [];
67 
73  protected $_scopeLabels = [];
74 
80  protected $_configFactory;
81 
87  protected $_formFactory;
88 
94  protected $_configStructure;
95 
101  protected $_fieldsetFactory;
102 
108  protected $_fieldFactory;
109 
113  private $settingChecker;
114 
118  private $appConfig;
119 
126  private $elementVisibility;
127 
138  public function __construct(
139  \Magento\Backend\Block\Template\Context $context,
140  \Magento\Framework\Registry $registry,
141  \Magento\Framework\Data\FormFactory $formFactory,
142  \Magento\Config\Model\Config\Factory $configFactory,
143  \Magento\Config\Model\Config\Structure $configStructure,
144  \Magento\Config\Block\System\Config\Form\Fieldset\Factory $fieldsetFactory,
145  \Magento\Config\Block\System\Config\Form\Field\Factory $fieldFactory,
146  array $data = []
147  ) {
148  parent::__construct($context, $registry, $formFactory, $data);
149  $this->_configFactory = $configFactory;
150  $this->_configStructure = $configStructure;
151  $this->_fieldsetFactory = $fieldsetFactory;
152  $this->_fieldFactory = $fieldFactory;
153 
154  $this->_scopeLabels = [
155  self::SCOPE_DEFAULT => __('[GLOBAL]'),
156  self::SCOPE_WEBSITES => __('[WEBSITE]'),
157  self::SCOPE_STORES => __('[STORE VIEW]'),
158  ];
159  }
160 
165  private function getSettingChecker()
166  {
167  if ($this->settingChecker === null) {
168  $this->settingChecker = ObjectManager::getInstance()->get(SettingChecker::class);
169  }
170  return $this->settingChecker;
171  }
172 
178  protected function _initObjects()
179  {
180  $this->_configDataObject = $this->_configFactory->create(
181  [
182  'data' => [
183  'section' => $this->getSectionCode(),
184  'website' => $this->getWebsiteCode(),
185  'store' => $this->getStoreCode(),
186  ],
187  ]
188  );
189 
190  $this->_configData = $this->_configDataObject->load();
191  $this->_fieldsetRenderer = $this->_fieldsetFactory->create();
192  $this->_fieldRenderer = $this->_fieldFactory->create();
193  return $this;
194  }
195 
201  public function initForm()
202  {
203  $this->_initObjects();
204 
206  $form = $this->_formFactory->create();
208  $section = $this->_configStructure->getElement($this->getSectionCode());
209  if ($section && $section->isVisible($this->getWebsiteCode(), $this->getStoreCode())) {
210  foreach ($section->getChildren() as $group) {
211  $this->_initGroup($group, $section, $form);
212  }
213  }
214 
215  $this->setForm($form);
216  return $this;
217  }
218 
227  protected function _initGroup(
228  \Magento\Config\Model\Config\Structure\Element\Group $group,
229  \Magento\Config\Model\Config\Structure\Element\Section $section,
230  \Magento\Framework\Data\Form\AbstractForm $form
231  ) {
232  $frontendModelClass = $group->getFrontendModel();
233  $fieldsetRenderer = $frontendModelClass ? $this->_layout->getBlockSingleton(
234  $frontendModelClass
236 
237  $fieldsetRenderer->setForm($this);
238  $fieldsetRenderer->setConfigData($this->_configData);
239  $fieldsetRenderer->setGroup($group);
240 
241  $fieldsetConfig = [
242  'legend' => $group->getLabel(),
243  'comment' => $group->getComment(),
244  'expanded' => $group->isExpanded(),
245  'group' => $group->getData(),
246  ];
247 
248  $fieldset = $form->addFieldset($this->_generateElementId($group->getPath()), $fieldsetConfig);
249  $fieldset->setRenderer($fieldsetRenderer);
250  $group->populateFieldset($fieldset);
251  $this->_addElementTypes($fieldset);
252 
253  $dependencies = $group->getDependencies($this->getStoreCode());
254  $elementName = $this->_generateElementName($group->getPath());
255  $elementId = $this->_generateElementId($group->getPath());
256 
257  $this->_populateDependenciesBlock($dependencies, $elementId, $elementName);
258 
259  if ($group->shouldCloneFields()) {
260  $cloneModel = $group->getCloneModel();
261  foreach ($cloneModel->getPrefixes() as $prefix) {
262  $this->initFields($fieldset, $group, $section, $prefix['field'], $prefix['label']);
263  }
264  } else {
265  $this->initFields($fieldset, $group, $section);
266  }
267 
268  $this->_fieldsets[$group->getId()] = $fieldset;
269  }
270 
276  protected function _getDependence()
277  {
278  if (!$this->getChildBlock('element_dependence')) {
279  $this->addChild('element_dependence', \Magento\Backend\Block\Widget\Form\Element\Dependence::class);
280  }
281  return $this->getChildBlock('element_dependence');
282  }
283 
294  public function initFields(
295  \Magento\Framework\Data\Form\Element\Fieldset $fieldset,
296  \Magento\Config\Model\Config\Structure\Element\Group $group,
297  \Magento\Config\Model\Config\Structure\Element\Section $section,
298  $fieldPrefix = '',
299  $labelPrefix = ''
300  ) {
301  if (!$this->_configDataObject) {
302  $this->_initObjects();
303  }
304 
305  // Extends for config data
306  $extraConfigGroups = [];
307 
309  foreach ($group->getChildren() as $element) {
310  if ($element instanceof \Magento\Config\Model\Config\Structure\Element\Group) {
311  $this->_initGroup($element, $section, $fieldset);
312  } else {
313  $path = $element->getConfigPath() ?: $element->getPath($fieldPrefix);
314  if ($element->getSectionId() != $section->getId()) {
315  $groupPath = $element->getGroupPath();
316  if (!isset($extraConfigGroups[$groupPath])) {
317  $this->_configData = $this->_configDataObject->extendConfig(
318  $groupPath,
319  false,
320  $this->_configData
321  );
322  $extraConfigGroups[$groupPath] = true;
323  }
324  }
325  $this->_initElement($element, $fieldset, $path, $fieldPrefix, $labelPrefix);
326  }
327  }
328  return $this;
329  }
330 
341  protected function _initElement(
342  \Magento\Config\Model\Config\Structure\Element\Field $field,
343  \Magento\Framework\Data\Form\Element\Fieldset $fieldset,
344  $path,
345  $fieldPrefix = '',
346  $labelPrefix = ''
347  ) {
348  $inherit = !array_key_exists($path, $this->_configData);
349  $data = $this->getFieldData($field, $path);
350 
351  $fieldRendererClass = $field->getFrontendModel();
352  if ($fieldRendererClass) {
353  $fieldRenderer = $this->_layout->getBlockSingleton($fieldRendererClass);
354  } else {
355  $fieldRenderer = $this->_fieldRenderer;
356  }
357 
358  $fieldRenderer->setForm($this);
359  $fieldRenderer->setConfigData($this->_configData);
360 
361  $elementName = $this->_generateElementName($field->getPath(), $fieldPrefix);
362  $elementId = $this->_generateElementId($field->getPath($fieldPrefix));
363 
364  $dependencies = $field->getDependencies($fieldPrefix, $this->getStoreCode());
365  $this->_populateDependenciesBlock($dependencies, $elementId, $elementName);
366 
367  $sharedClass = $this->_getSharedCssClass($field);
368  $requiresClass = $this->_getRequiresCssClass($field, $fieldPrefix);
369 
370  $isReadOnly = $this->getElementVisibility()->isDisabled($field->getPath())
371  ?: $this->getSettingChecker()->isReadOnly($path, $this->getScope(), $this->getStringScopeCode());
372  $formField = $fieldset->addField(
373  $elementId,
374  $field->getType(),
375  [
376  'name' => $elementName,
377  'label' => $field->getLabel($labelPrefix),
378  'comment' => $field->getComment($data),
379  'tooltip' => $field->getTooltip(),
380  'hint' => $field->getHint(),
381  'value' => $data,
382  'inherit' => $inherit,
383  'class' => $field->getFrontendClass() . $sharedClass . $requiresClass,
384  'field_config' => $field->getData(),
385  'scope' => $this->getScope(),
386  'scope_id' => $this->getScopeId(),
387  'scope_label' => $this->getScopeLabel($field),
388  'can_use_default_value' => $this->canUseDefaultValue($field->showInDefault()),
389  'can_use_website_value' => $this->canUseWebsiteValue($field->showInWebsite()),
390  'can_restore_to_default' => $this->isCanRestoreToDefault($field->canRestore()),
391  'disabled' => $isReadOnly,
392  'is_disable_inheritance' => $isReadOnly
393  ]
394  );
395  $field->populateInput($formField);
396 
397  if ($field->hasValidation()) {
398  $formField->addClass($field->getValidation());
399  }
400  if ($field->getType() == 'multiselect') {
401  $formField->setCanBeEmpty($field->canBeEmpty());
402  }
403  if ($field->hasOptions()) {
404  $formField->setValues($field->getOptions());
405  }
406  $formField->setRenderer($fieldRenderer);
407  }
408 
416  private function getFieldData(\Magento\Config\Model\Config\Structure\Element\Field $field, $path)
417  {
418  $data = $this->getAppConfigDataValue($path);
419 
420  $placeholderValue = $this->getSettingChecker()->getPlaceholderValue(
421  $path,
422  $this->getScope(),
423  $this->getStringScopeCode()
424  );
425 
426  if ($placeholderValue) {
427  $data = $placeholderValue;
428  }
429 
430  if ($data === null) {
431  $path = $field->getConfigPath() !== null ? $field->getConfigPath() : $path;
432  $data = $this->getConfigValue($path);
433  if ($field->hasBackendModel()) {
434  $backendModel = $field->getBackendModel();
435  // Backend models which implement ProcessorInterface are processed by ScopeConfigInterface
436  if (!$backendModel instanceof ProcessorInterface) {
437  $backendModel->setPath($path)
438  ->setValue($data)
439  ->setWebsite($this->getWebsiteCode())
440  ->setStore($this->getStoreCode())
441  ->afterLoad();
442  $data = $backendModel->getValue();
443  }
444  }
445  }
446 
447  return $data;
448  }
449 
455  private function getStringScopeCode()
456  {
457  $scopeCode = $this->getData('scope_string_code');
458 
459  if (null === $scopeCode) {
460  if ($this->getStoreCode()) {
461  $scopeCode = $this->_storeManager->getStore($this->getStoreCode())->getCode();
462  } elseif ($this->getWebsiteCode()) {
463  $scopeCode = $this->_storeManager->getWebsite($this->getWebsiteCode())->getCode();
464  } else {
465  $scopeCode = '';
466  }
467 
468  $this->setData('scope_string_code', $scopeCode);
469  }
470 
471  return $scopeCode;
472  }
473 
482  protected function _populateDependenciesBlock(array $dependencies, $elementId, $elementName)
483  {
484  foreach ($dependencies as $dependentField) {
486  $fieldNameFrom = $this->_generateElementName($dependentField->getId(), null, '_');
487  $this->_getDependence()->addFieldMap(
488  $elementId,
490  )->addFieldMap(
491  $this->_generateElementId($dependentField->getId()),
492  $fieldNameFrom
493  )->addFieldDependence(
494  $elementName,
495  $fieldNameFrom,
496  $dependentField
497  );
498  }
499  }
500 
509  protected function _generateElementName($elementPath, $fieldPrefix = '', $separator = '/')
510  {
511  $part = explode($separator, $elementPath);
512  array_shift($part);
513  //shift section name
514  $fieldId = array_pop($part);
515  //shift filed id
516  $groupName = implode('][groups][', $part);
517  $name = 'groups[' . $groupName . '][fields][' . $fieldPrefix . $fieldId . '][value]';
518  return $name;
519  }
520 
527  protected function _generateElementId($path)
528  {
529  return str_replace('/', '_', $path);
530  }
531 
538  public function getConfigValue($path)
539  {
540  return $this->_scopeConfig->getValue($path, $this->getScope(), $this->getScopeCode());
541  }
542 
546  protected function _beforeToHtml()
547  {
548  $this->initForm();
549  return parent::_beforeToHtml();
550  }
551 
558  protected function _afterToHtml($html)
559  {
560  if ($this->_getDependence()) {
561  $html .= $this->_getDependence()->toHtml();
562  }
563  $html = parent::_afterToHtml($html);
564  return $html;
565  }
566 
573  public function canUseDefaultValue($fieldValue)
574  {
575  if ($this->getScope() == self::SCOPE_STORES && $fieldValue) {
576  return true;
577  }
578  if ($this->getScope() == self::SCOPE_WEBSITES && $fieldValue) {
579  return true;
580  }
581  return false;
582  }
583 
590  public function canUseWebsiteValue($fieldValue)
591  {
592  if ($this->getScope() == self::SCOPE_STORES && $fieldValue) {
593  return true;
594  }
595  return false;
596  }
597 
605  public function isCanRestoreToDefault($fieldValue)
606  {
607  if ($this->getScope() == self::SCOPE_DEFAULT && $fieldValue) {
608  return true;
609  }
610  return false;
611  }
612 
618  public function getScope()
619  {
620  $scope = $this->getData('scope');
621  if ($scope === null) {
622  if ($this->getStoreCode()) {
623  $scope = self::SCOPE_STORES;
624  } elseif ($this->getWebsiteCode()) {
625  $scope = self::SCOPE_WEBSITES;
626  } else {
627  $scope = self::SCOPE_DEFAULT;
628  }
629  $this->setScope($scope);
630  }
631 
632  return $scope;
633  }
634 
641  public function getScopeLabel(\Magento\Config\Model\Config\Structure\Element\Field $field)
642  {
643  $showInStore = $field->showInStore();
644  $showInWebsite = $field->showInWebsite();
645 
646  if ($showInStore == 1) {
647  return $this->_scopeLabels[self::SCOPE_STORES];
648  } elseif ($showInWebsite == 1) {
649  return $this->_scopeLabels[self::SCOPE_WEBSITES];
650  }
651  return $this->_scopeLabels[self::SCOPE_DEFAULT];
652  }
653 
659  public function getScopeCode()
660  {
661  $scopeCode = $this->getData('scope_code');
662  if ($scopeCode === null) {
663  if ($this->getStoreCode()) {
664  $scopeCode = $this->getStoreCode();
665  } elseif ($this->getWebsiteCode()) {
666  $scopeCode = $this->getWebsiteCode();
667  } else {
668  $scopeCode = '';
669  }
670  $this->setScopeCode($scopeCode);
671  }
672 
673  return $scopeCode;
674  }
675 
681  public function getScopeId()
682  {
683  $scopeId = $this->getData('scope_id');
684  if ($scopeId === null) {
685  if ($this->getStoreCode()) {
686  $scopeId = $this->_storeManager->getStore($this->getStoreCode())->getId();
687  } elseif ($this->getWebsiteCode()) {
688  $scopeId = $this->_storeManager->getWebsite($this->getWebsiteCode())->getId();
689  } else {
690  $scopeId = '';
691  }
692  $this->setScopeId($scopeId);
693  }
694  return $scopeId;
695  }
696 
702  protected function _getAdditionalElementTypes()
703  {
704  return [
705  'allowspecific' => \Magento\Config\Block\System\Config\Form\Field\Select\Allowspecific::class,
706  'image' => \Magento\Config\Block\System\Config\Form\Field\Image::class,
707  'file' => \Magento\Config\Block\System\Config\Form\Field\File::class
708  ];
709  }
710 
722  public function getSectionCode()
723  {
724  return $this->getRequest()->getParam('section', '');
725  }
726 
733  public function getWebsiteCode()
734  {
735  return $this->getRequest()->getParam('website', '');
736  }
737 
744  public function getStoreCode()
745  {
746  return $this->getRequest()->getParam('store', '');
747  }
748 
755  protected function _getSharedCssClass(\Magento\Config\Model\Config\Structure\Element\Field $field)
756  {
757  $sharedClass = '';
758  if ($field->getAttribute('shared') && $field->getConfigPath()) {
759  $sharedClass = ' shared shared-' . str_replace('/', '-', $field->getConfigPath());
760  return $sharedClass;
761  }
762  return $sharedClass;
763  }
764 
772  protected function _getRequiresCssClass(\Magento\Config\Model\Config\Structure\Element\Field $field, $fieldPrefix)
773  {
774  $requiresClass = '';
775  $requiredPaths = array_merge($field->getRequiredFields($fieldPrefix), $field->getRequiredGroups($fieldPrefix));
776  if (!empty($requiredPaths)) {
777  $requiresClass = ' requires';
778  foreach ($requiredPaths as $requiredPath) {
779  $requiresClass .= ' requires-' . $this->_generateElementId($requiredPath);
780  }
781  return $requiresClass;
782  }
783  return $requiresClass;
784  }
785 
792  private function getAppConfig()
793  {
794  if ($this->appConfig === null) {
795  $this->appConfig = ObjectManager::getInstance()->get(DeploymentConfig::class);
796  }
797  return $this->appConfig;
798  }
799 
806  private function getAppConfigDataValue($path)
807  {
808  $appConfig = $this->getAppConfig()->get(System::CONFIG_TYPE);
809  $scope = $this->getScope();
810  $scopeCode = $this->getStringScopeCode();
811 
813  $data = new DataObject(isset($appConfig[$scope]) ? $appConfig[$scope] : []);
814  } else {
815  $data = new DataObject(isset($appConfig[$scope][$scopeCode]) ? $appConfig[$scope][$scopeCode] : []);
816  }
817  return $data->getData($path);
818  }
819 
829  public function getElementVisibility()
830  {
831  if (null === $this->elementVisibility) {
832  $this->elementVisibility = ObjectManager::getInstance()->get(ElementVisibilityInterface::class);
833  }
834 
835  return $this->elementVisibility;
836  }
837 }
getScopeLabel(\Magento\Config\Model\Config\Structure\Element\Field $field)
Definition: Form.php:641
_addElementTypes(\Magento\Framework\Data\Form\AbstractForm $baseElement)
Definition: Form.php:255
getData($key='', $index=null)
Definition: DataObject.php:119
_getSharedCssClass(\Magento\Config\Model\Config\Structure\Element\Field $field)
Definition: Form.php:755
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
setForm(\Magento\Framework\Data\Form $form)
Definition: Form.php:112
$group
Definition: sections.phtml:16
_initElement(\Magento\Config\Model\Config\Structure\Element\Field $field, \Magento\Framework\Data\Form\Element\Fieldset $fieldset, $path, $fieldPrefix='', $labelPrefix='')
Definition: Form.php:341
__()
Definition: __.php:13
$prefix
Definition: name.phtml:25
$fieldId
Definition: element.phtml:16
_getRequiresCssClass(\Magento\Config\Model\Config\Structure\Element\Field $field, $fieldPrefix)
Definition: Form.php:772
_initGroup(\Magento\Config\Model\Config\Structure\Element\Group $group, \Magento\Config\Model\Config\Structure\Element\Section $section, \Magento\Framework\Data\Form\AbstractForm $form)
Definition: Form.php:227
$configFactory
Definition: config_data.php:43
__construct(\Magento\Backend\Block\Template\Context $context, \Magento\Framework\Registry $registry, \Magento\Framework\Data\FormFactory $formFactory, \Magento\Config\Model\Config\Factory $configFactory, \Magento\Config\Model\Config\Structure $configStructure, \Magento\Config\Block\System\Config\Form\Fieldset\Factory $fieldsetFactory, \Magento\Config\Block\System\Config\Form\Field\Factory $fieldFactory, array $data=[])
Definition: Form.php:138
setData($key, $value=null)
Definition: DataObject.php:72
_generateElementName($elementPath, $fieldPrefix='', $separator='/')
Definition: Form.php:509
$elementName
Definition: gallery.phtml:10
if(!isset($_GET['name'])) $name
Definition: log.php:14
$element
Definition: element.phtml:12