diff --git a/Helper/Data.php b/Helper/Data.php index ac1a6c9..4814772 100644 --- a/Helper/Data.php +++ b/Helper/Data.php @@ -6,6 +6,9 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper { + const STORE_VIEW_SCOPE_CODE = 'stores'; + const WEBSITE_SCOPE_CODE = 'websites'; + /** @var \Magento\Framework\App\Helper\Context */ protected $context; @@ -18,16 +21,29 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper * @var \Magento\Backend\Model\Url */ protected $urlBuilder; + /** + * @var \Magento\Config\Model\Config\Structure\SearchInterface + */ + protected $configStructure; + /** + * @var \Magento\Framework\Escaper + */ + protected $escaper; /** + * Data constructor. * @param \Magento\Framework\App\Helper\Context $context * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Backend\Model\Url $urlBuilder + * @param \Magento\Config\Model\Config\Structure\SearchInterface $configStructure + * @param \Magento\Framework\Escaper $escaper */ public function __construct( \Magento\Framework\App\Helper\Context $context, \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Backend\Model\Url $urlBuilder + \Magento\Backend\Model\Url $urlBuilder, + \Magento\Config\Model\Config\Structure\SearchInterface $configStructure, + \Magento\Framework\Escaper $escaper ) { parent::__construct($context); @@ -37,6 +53,8 @@ public function __construct( // an instance of \Magento\Framework\Url instead of \Magento\Backend\Model\Url, we must explicitly request it // via DI. $this->urlBuilder = $urlBuilder; + $this->configStructure = $configStructure; + $this->escaper = $escaper; } /** @@ -46,17 +64,17 @@ public function __construct( * @return array */ public function getScopeTree() { - $tree = array('websites' => array()); + $tree = array(self::WEBSITE_SCOPE_CODE => array()); $websites = $this->storeManager->getWebsites(); /* @var $website Website */ foreach($websites as $website) { - $tree['websites'][$website->getId()] = array('stores' => array()); + $tree[self::WEBSITE_SCOPE_CODE][$website->getId()] = array(self::STORE_VIEW_SCOPE_CODE => array()); /* @var $store Store */ foreach($website->getStores() as $store) { - $tree['websites'][$website->getId()]['stores'][] = $store->getId(); + $tree[self::WEBSITE_SCOPE_CODE][$website->getId()][self::STORE_VIEW_SCOPE_CODE][] = $store->getId(); } } @@ -66,15 +84,51 @@ public function getScopeTree() { /** * Wrapper method to get config value at path, scope, and scope code provided * - * @param $path - * @param $contextScope - * @param $contextScopeId - * @return mixed + * @param string $path + * @param string $contextScope + * @param string|int $contextScopeId + * @return string */ protected function _getConfigValue($path, $contextScope, $contextScopeId) { return $this->context->getScopeConfig()->getValue($path, $contextScope, $contextScopeId); } + /** + * Gets human-friendly display value(s) for given config path + * + * @param string $path + * @param string $contextScope + * @param string|int $contextScopeId + * @return array + */ + public function getConfigDisplayValue($path, $contextScope, $contextScopeId) { + $value = $this->_getConfigValue($path, $contextScope, $contextScopeId); + + $labels = [$value]; //default labels to raw value + + /** @var \Magento\Config\Model\Config\Structure\Element\Field $field */ + $field = $this->configStructure->getElement($path); + + if($field->getOptions()) { + $labels = []; //reset labels so we can add human-friendly labels + + $optionsByValue = []; + foreach($field->getOptions() as $option) { + $optionsByValue[$option['value']] = $option; + } + + $values = explode(',', $value); + + foreach($values as $valueInstance) { + $labels[] = isset($optionsByValue[$valueInstance]) + ? $optionsByValue[$valueInstance]['label'] : $valueInstance; + + } + } + + return $labels; + } + /** * Gets array of scopes and scope IDs where path value is different * than supplied context scope and context scope ID. @@ -90,41 +144,43 @@ public function getOverriddenLevels($path, $contextScope, $contextScopeId) { $currentValue = $this->_getConfigValue($path, $contextScope, $contextScopeId); - if(is_null($currentValue)) { - return array(); //something is off, let's bail gracefully. - } - $overridden = array(); switch($contextScope) { - case 'websites': - $stores = array_values($tree['websites'][$contextScopeId]['stores']); + case self::WEBSITE_SCOPE_CODE: + $stores = array_values($tree[self::WEBSITE_SCOPE_CODE][$contextScopeId][self::STORE_VIEW_SCOPE_CODE]); foreach($stores as $storeId) { - $value = $this->_getConfigValue($path, 'stores', $storeId); + $value = $this->_getConfigValue($path, self::STORE_VIEW_SCOPE_CODE, $storeId); if($value != $currentValue) { $overridden[] = array( 'scope' => 'store', - 'scope_id' => $storeId + 'scope_id' => $storeId, + 'value' => $value, + 'display_value' => $this->getConfigDisplayValue($path, self::STORE_VIEW_SCOPE_CODE, $storeId) ); } } break; case 'default': - foreach($tree['websites'] as $websiteId => $website) { - $websiteValue = $this->_getConfigValue($path, 'websites', $websiteId); + foreach($tree[self::WEBSITE_SCOPE_CODE] as $websiteId => $website) { + $websiteValue = $this->_getConfigValue($path, self::WEBSITE_SCOPE_CODE, $websiteId); if($websiteValue != $currentValue) { $overridden[] = array( 'scope' => 'website', - 'scope_id' => $websiteId + 'scope_id' => $websiteId, + 'value' => $websiteValue, + 'display_value' => $this->getConfigDisplayValue($path, self::WEBSITE_SCOPE_CODE, $websiteId) ); } - foreach($website['stores'] as $storeId) { - $value = $this->_getConfigValue($path, 'stores', $storeId); + foreach($website[self::STORE_VIEW_SCOPE_CODE] as $storeId) { + $value = $this->_getConfigValue($path, self::STORE_VIEW_SCOPE_CODE, $storeId); if($value != $currentValue && $value != $websiteValue) { $overridden[] = array( 'scope' => 'store', - 'scope_id' => $storeId + 'scope_id' => $storeId, + 'value' => $value, + 'display_value' => $this->getConfigDisplayValue($path, self::STORE_VIEW_SCOPE_CODE, $storeId) ); } } @@ -135,6 +191,31 @@ public function getOverriddenLevels($path, $contextScope, $contextScopeId) { return $overridden; } + /** + * Get HTML formatted value label(s) + * + * @param array $labels + * @return string + */ + protected function getFormattedValueLabels(array $labels) { + if(count($labels) == 1) { + //if only one value, simply return it + return '' . + nl2br($this->escaper->escapeHtml($labels[0])) . + ''; + } + + $formattedLabels = ''; + + foreach($labels as $label) { + $formattedLabels .= '
  • ' . + nl2br($this->escaper->escapeHtml($label)) . + '
  • '; + } + + return ''; + } + /** * Get HTML output for override hint UI * @@ -145,11 +226,13 @@ public function getOverriddenLevels($path, $contextScope, $contextScopeId) { public function formatOverriddenScopes($section, array $overridden) { $formatted = '
    ' . '

    ' . __('This config field is overridden at the following scope(s):') . '

    ' . - '
    '; + $formatted .= ''; return $formatted; } diff --git a/README.md b/README.md index 2a9f310..bd45c29 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,9 @@ After installing the module, when viewing a system configuration field, an alert The icon is only shown when the value is overridden at a more specific scope than the current one – that is, if viewing at the default scope, overrides at the website or store view level are shown, but if viewing at the website level, only overrides below the currently selected website are shown. -Along with the alert message, a detailed list of the exact scope(s) that override the value, with links directly to the store config for the current section at those scopes. +Along with the alert message, a detailed list of the exact scope(s) that override the value, with links directly to the store config for the current section at those scopes. Clicking an override hint row arrow will expand the row to also show the field's value at that scope. -![Screenshot of system config scope hints module](https://ericisaweso.me/images/magento2-configscopehints-v3.png) +![Screenshot of system config scope hints module](https://ericisaweso.me/images/magento2-configscopehints-v3.1.png) ## Compatibility and Technical Notes diff --git a/etc/module.xml b/etc/module.xml index 313d310..373d5c0 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,5 +1,5 @@ - + diff --git a/view/adminhtml/layout/adminhtml_system_config_edit.xml b/view/adminhtml/layout/adminhtml_system_config_edit.xml index 1fc2604..e75b768 100644 --- a/view/adminhtml/layout/adminhtml_system_config_edit.xml +++ b/view/adminhtml/layout/adminhtml_system_config_edit.xml @@ -2,5 +2,6 @@ +