![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/extmag/shiplab/Model/ |
<?php /** * Copyright © Extmag. All rights reserved. */ namespace Extmag\Shiplab\Model; use Extmag\Shiplab\Helper\Config\Structure\Element\Field; use Extmag\Shiplab\Helper\Config\Structure\Element\Group; use Exception; use Magento\Backend\Model\Session; use Magento\Config\Model\Config\Reader\Source\Deployed\SettingChecker; use Magento\Framework\App\Config\ReinitableConfigInterface; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Config\ValueFactory; use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject; use Magento\Framework\DB\Transaction; use Magento\Framework\DB\TransactionFactory; use Magento\Framework\Event\ManagerInterface; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Simplexml\Element; use Magento\Store\Model\StoreManagerInterface; use UnexpectedValueException; /** * Backend config model * * Used to save configuration * @author Magento Core Team <[email protected]> * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @api * @since 100.0.2 */ class Config extends DataObject { /** * Config data for sections * * @var array */ protected $_configData; /** * Event dispatcher * * @var ManagerInterface */ protected $_eventManager; /** * System configuration structure * * @var \Extmag\Shiplab\Helper\Config */ protected $_configStructure; /** * Application config * * @var ScopeConfigInterface */ protected $_appConfig; /** * Global factory * * @var ScopeConfigInterface */ protected $_objectFactory; /** * TransactionFactory * * @var TransactionFactory */ protected $_transactionFactory; /** * Config data loader * * @var Configuration */ protected $_configLoader; /** * Config data factory * * @var ValueFactory */ protected $_configValueFactory; /** * @var StoreManagerInterface */ protected $_storeManager; /** * @var Config\Reader\Source\Deployed\SettingChecker */ protected $settingChecker; /** * @var Session */ public $session; /** * @param ReinitableConfigInterface $config * @param ManagerInterface $eventManager * @param \Extmag\Shiplab\Helper\Config $configStructure * @param TransactionFactory $transactionFactory * @param Configuration $configLoader * @param ValueFactory $configValueFactory * @param StoreManagerInterface $storeManager * @param Session $session * @param SettingChecker|null $settingChecker * @param array $data */ public function __construct( ReinitableConfigInterface $config, ManagerInterface $eventManager, \Extmag\Shiplab\Helper\Config $configStructure, TransactionFactory $transactionFactory, Configuration $configLoader, ValueFactory $configValueFactory, StoreManagerInterface $storeManager, Session $session, SettingChecker $settingChecker = null, array $data = [] ) { parent::__construct($data); $this->_eventManager = $eventManager; $this->_configStructure = $configStructure; $this->_transactionFactory = $transactionFactory; $this->_appConfig = $config; $this->_configLoader = $configLoader; $this->_configValueFactory = $configValueFactory; $this->_storeManager = $storeManager; $this->settingChecker = $settingChecker ?: ObjectManager::getInstance()->get(SettingChecker::class); $this->session = $session; } /** * Save config section * * Require set: section, website, store and groups * * @return $this * @throws Exception */ public function save() { $this->initScope(); $sectionId = $this->getSection(); $groups = $this->getGroups(); if (empty($groups)) { return $this; } $oldConfig = $this->_getConfig(true); /** @var Transaction $deleteTransaction */ $deleteTransaction = $this->_transactionFactory->create(); /** @var Transaction $saveTransaction */ $saveTransaction = $this->_transactionFactory->create(); $changedPaths = []; // Extends for old config data $extraOldGroups = []; foreach ($groups as $groupId => $groupData) { $this->_processGroup( $groupId, $groupData, $groups, $sectionId, $extraOldGroups, $oldConfig, $saveTransaction, $deleteTransaction ); $groupChangedPaths = $this->getChangedPaths($sectionId, $groupId, $groupData, $oldConfig, $extraOldGroups); $changedPaths = array_merge($changedPaths, $groupChangedPaths); } try { $deleteTransaction->delete(); $saveTransaction->save(); // re-init configuration $this->_appConfig->reinit(); $this->clearSessionByCarrier(); // website and store codes can be used in event implementation, so set them as well $this->_eventManager->dispatch( "extmag_shiplab_configuration_changed_section_{$this->getSection()}", [ 'store' => $this->getStore(), 'direction' => $this->getDirection(), 'country' => $this->getCountry(), 'changed_paths' => $changedPaths, ] ); } catch (Exception $e) { // re-init configuration $this->_appConfig->reinit(); throw $e; } return $this; } public function clearSessionByCarrier() { } /** * Get scope name and scopeId * * @return void */ protected function initScope() { if ($this->getSection() === null) { $this->setSection(''); } if ($this->getStore() === null) { $this->setStore(''); } if ($this->getDirection() === null) { $this->setDirection(''); } if ($this->getCountry() === null) { $this->setCountry(''); } if ($this->getStore()) { $scope = 'store'; $scopeId = (int)$this->getStore(); $scopeCode = $this->getStore(); } elseif ($this->getDirection()) { $scope = 'direction'; $scopeId = (int)$this->getDirection(); $scopeCode = $this->getDirection(); } elseif ($this->getCountry()) { $scope = 'country'; $scopeId = (int)$this->getCountry(); $scopeCode = $this->getCountry(); } else { $scope = 'default'; $scopeId = 0; $scopeCode = ''; } $this->setScope($scope); $this->setScopeId($scopeId); $this->setScopeCode($scopeCode); } /** * Return formatted config data for current section * * @param bool $full Simple config structure or not * * @return array */ protected function _getConfig($full = true) { return $this->_configLoader->getConfigByPath( $this->getSection(), $this->getScope(), $this->getScopeId(), $full ); } /** * Process group data * * @param string $groupId * @param array $groupData * @param array $groups * @param string $sectionPath * @param array & $extraOldGroups * @param array & $oldConfig * @param Transaction $saveTransaction * @param Transaction $deleteTransaction * * @return void * @throws LocalizedException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _processGroup( $groupId, array $groupData, array $groups, $sectionPath, array &$extraOldGroups, array &$oldConfig, Transaction $saveTransaction, Transaction $deleteTransaction ) { $groupPath = $sectionPath . '/' . $groupId; if (isset($groupData['fields'])) { /** @var Group $group */ $group = $this->_configStructure->getElement($groupPath); // set value for group field entry by fieldname // use extra memory $fieldsetData = []; foreach ($groupData['fields'] as $fieldId => $fieldData) { $fieldsetData[$fieldId] = $fieldData['value'] ?? null; } foreach ($groupData['fields'] as $fieldId => $fieldData) { /*$isReadOnly = $this->settingChecker->isReadOnly( $groupPath . '/' . $fieldId, $this->getScope(), $this->getScopeCode() ); if ($isReadOnly) { continue; }*/ $field = $this->getField($sectionPath, $groupId, $fieldId); /** @var Configuration $backendModel */ $backendModel = $field->hasBackendModel() ? $field->getBackendModel() : ObjectManager::getInstance()->create(Configuration::class); if (!isset($fieldData['value'])) { $fieldData['value'] = null; } $data = [ 'field' => $fieldId, 'groups' => $groups, 'group_id' => $group->getId(), 'scope' => $this->getScope(), 'scope_id' => $this->getScopeId(), 'scope_code' => $this->getScopeId(), 'field_config' => $field->getData(), 'fieldset_data' => $fieldsetData, ]; $backendModel->addData($data); $path = $this->getFieldPath($field, $fieldId, $extraOldGroups, $oldConfig); $dataValue = $fieldData['value']; if (is_array($dataValue)) { $dataValue = implode(",", $dataValue); } $backendModel->setPath($path)->setValue($dataValue); $inherit = !empty($fieldData['inherit']); if (isset($oldConfig[$path])) { $backendModel->setConfigId($oldConfig[$path]['config_id']); /** * Delete config data if inherit */ if (!$inherit) { $saveTransaction->addObject($backendModel); } else { $deleteTransaction->addObject($backendModel); } } elseif (!$inherit) { $backendModel->unsConfigId(); $saveTransaction->addObject($backendModel); } } } if (isset($groupData['groups'])) { foreach ($groupData['groups'] as $subGroupId => $subGroupData) { $this->_processGroup( $subGroupId, $subGroupData, $groups, $groupPath, $extraOldGroups, $oldConfig, $saveTransaction, $deleteTransaction ); } } } /** * Get field object * * @param string $sectionId * @param string $groupId * @param string $fieldId * * @return Field * @throws LocalizedException */ protected function getField(string $sectionId, string $groupId, string $fieldId): Field { /** @var Group $group */ $group = $this->_configStructure->getElement($sectionId . '/' . $groupId); $fieldPath = $group->getPath() . '/' . $this->getOriginalFieldId($group, $fieldId); return $this->_configStructure->getElement($fieldPath); } /** * Map field name if they were cloned * * @param Group $group * @param string $fieldId * * @return string * @throws LocalizedException * @throws LocalizedException */ protected function getOriginalFieldId(Group $group, string $fieldId): string { if ($group->shouldCloneFields()) { $cloneModel = $group->getCloneModel(); /** @var \Magento\Config\Model\Config\Structure\Element\Field $field */ foreach ($group->getChildren() as $field) { foreach ($cloneModel->getPrefixes() as $prefix) { if ($prefix['field'] . $field->getId() === $fieldId) { $fieldId = $field->getId(); break(2); } } } } return $fieldId; } /** * Get field path * * @param Field $field * @param string $fieldId * @param array &$oldConfig Need for compatibility with _processGroup() * @param array &$extraOldGroups Need for compatibility with _processGroup() * * @return string */ protected function getFieldPath(Field $field, string $fieldId, array &$oldConfig, array &$extraOldGroups): string { $path = $field->getGroupPath() . '/' . $fieldId; /** * Look for custom defined field path */ $configPath = $field->getConfigPath(); if ($configPath && strrpos($configPath, '/') > 0) { // Extend old data with specified section group $configGroupPath = substr($configPath, 0, strrpos($configPath, '/')); if (!isset($extraOldGroups[$configGroupPath])) { $oldConfig = $this->extendConfig($configGroupPath, true, $oldConfig); $extraOldGroups[$configGroupPath] = true; } $path = $configPath; } return $path; } /** * Extend config data with additional config data by specified path * * @param string $path Config path prefix * @param bool $full Simple config structure or not * @param array $oldConfig Config data to extend * * @return array */ public function extendConfig($path, $full = true, $oldConfig = []) { $extended = $this->_configLoader->getConfigByPath($path, $this->getScope(), $this->getScopeId(), $full); if (is_array($oldConfig) && !empty($oldConfig)) { return $oldConfig + $extended; } return $extended; } /** * Get changed paths * * @param string $sectionId * @param string $groupId * @param array $groupData * @param array &$oldConfig * @param array &$extraOldGroups * * @return array * @throws LocalizedException */ protected function getChangedPaths( string $sectionId, string $groupId, array $groupData, array &$oldConfig, array &$extraOldGroups ): array { $changedPaths = []; if (isset($groupData['fields'])) { foreach ($groupData['fields'] as $fieldId => $fieldData) { $field = $this->getField($sectionId, $groupId, $fieldId); $path = $this->getFieldPath($field, $fieldId, $oldConfig, $extraOldGroups); if ($this->isValueChanged($oldConfig, $path, $fieldData)) { $changedPaths[] = $path; } } } if (isset($groupData['groups'])) { $subSectionId = $sectionId . '/' . $groupId; foreach ($groupData['groups'] as $subGroupId => $subGroupData) { $subGroupChangedPaths = $this->getChangedPaths( $subSectionId, $subGroupId, $subGroupData, $oldConfig, $extraOldGroups ); $changedPaths = array_merge($changedPaths, $subGroupChangedPaths); } } return $changedPaths; } /** * Check is config value changed * * @param array $oldConfig * @param string $path * @param array $fieldData * * @return bool */ protected function isValueChanged(array $oldConfig, string $path, array $fieldData): bool { if (isset($oldConfig[$path]['value'])) { $result = !isset($fieldData['value']) || $oldConfig[$path]['value'] !== $fieldData['value']; } else { $result = empty($fieldData['inherit']); } return $result; } /** * Add data by path section/group/field * * @param string $path * @param mixed $value * * @return void * @throws UnexpectedValueException */ public function setDataByPath($path, $value) { $path = trim($path); if ($path === '') { throw new UnexpectedValueException('Path must not be empty'); } $pathParts = explode('/', $path); $keyDepth = count($pathParts); if ($keyDepth !== 3) { throw new UnexpectedValueException( "Allowed depth of configuration is 3 (<section>/<group>/<field>). Your configuration depth is " . $keyDepth . " for path '$path'" ); } $data = [ 'section' => $pathParts[0], 'groups' => [ $pathParts[1] => [ 'fields' => [ $pathParts[2] => ['value' => $value], ], ], ], ]; $this->addData($data); } /** * Get config data value * * @param string $path * @param null|bool &$inherit * @param null|array $configData * * @return Element */ public function getConfigDataValue($path, &$inherit = null, $configData = null) { $this->load(); if ($configData === null) { $configData = $this->_configData; } if (isset($configData[$path])) { $data = $configData[$path]; $inherit = false; } else { $data = $this->_appConfig->getValue($path, $this->getScope(), $this->getScopeCode()); $inherit = true; } return $data; } /** * Load config data for section * * @return array */ public function load() { if ($this->_configData === null) { $this->initScope(); $this->_configData = $this->_getConfig(false); } return $this->_configData; } }