<commit_before><?php

namespace CtiDigital\Configurator\Component;

use CtiDigital\Configurator\Api\ComponentInterface;
use CtiDigital\Configurator\Exception\ComponentException;
use CtiDigital\Configurator\Api\LoggerInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Encryption\EncryptorInterface;
use Magento\Store\Model\StoreFactory;
use Magento\Store\Model\WebsiteFactory;
use Magento\Theme\Model\ResourceModel\Theme\Collection;
use Magento\Theme\Model\ResourceModel\Theme\CollectionFactory;
use Magento\Config\Model\ResourceModel\Config as ConfigResource;
use Magento\Framework\App\Config as ScopeConfig;

class Config implements ComponentInterface
{
    const PATH_THEME_ID = 'design/theme/theme_id';

    protected $alias = 'config';
    protected $name = 'Configuration';
    protected $description = 'Component to set the store/system configuration values';

    /**
     * @var ConfigResource
     */
    protected $configResource;

    /**
     * @var ScopeConfig
     */
    protected $scopeConfig;

    /**
     * @var CollectionFactory
     */
    protected $collectionFactory;

    /**
     * @var EncryptorInterface
     */
    protected $encryptor;

    /**
     * @var WebsiteFactory
     */
    protected $websiteFactory;

    /**
     * @var StoreFactory
     */
    protected $storeFactory;

    /**
     * @var LoggerInterface
     */
    private $log;

    /**
     * Config constructor.
     * @param ConfigResource $configResource
     * @param ScopeConfig $scopeConfig
     * @param CollectionFactory $collectionFactory
     * @param EncryptorInterface $encryptor
     */
    public function __construct(
        ConfigResource $configResource,
        ScopeConfig $scopeConfig,
        CollectionFactory $collectionFactory,
        EncryptorInterface $encryptor,
        WebsiteFactory $websiteFactory,
        StoreFactory $storeFactory,
        LoggerInterface $log
    ) {
        $this->configResource = $configResource;
        $this->scopeConfig = $scopeConfig;
        $this->collectionFactory = $collectionFactory;
        $this->encryptor = $encryptor;
        $this->websiteFactory = $websiteFactory;
        $this->storeFactory = $storeFactory;
        $this->log = $log;
    }

    /**
     * @param $data
     * @SuppressWarnings(PHPMD)
     */
    public function execute($data = null) //phpcs:ignore Generic.Metrics.NestingLevel
    {
        try {
            $validScopes = ['global', 'websites', 'stores'];
            foreach ($data as $scope => $configurations) {
                if (!in_array($scope, $validScopes)) {
                    throw new ComponentException(sprintf("This is not a valid scope '%s' in your config.", $scope));
                }

                if ($scope == "global") {
                    foreach ($configurations as $configuration) {
                        // Handle encryption parameter
                        $encryption = 0;
                        if (isset($configuration['encryption']) && $configuration['encryption'] == 1) {
                            $encryption = 1;
                        }

                        $convertedConfiguration = $this->convert($configuration);
                        $this->setGlobalConfig(
                            $convertedConfiguration['path'],
                            $convertedConfiguration['value'],
                            $encryption
                        );
                    }
                }

                if ($scope == "websites") {
                    foreach ($configurations as $code => $websiteConfigurations) {
                        foreach ($websiteConfigurations as $configuration) {
                            // Handle encryption parameter
                            $encryption = 0;
                            if (isset($configuration['encryption']) && $configuration['encryption'] == 1) {
                                $encryption = 1;
                            }
                            $convertedConfiguration = $this->convert($configuration);
                            $this->setWebsiteConfig(
                                $convertedConfiguration['path'],
                                $convertedConfiguration['value'],
                                $code,
                                $encryption
                            );
                        }
                    }
                }

                if ($scope == "stores") {
                    foreach ($configurations as $code => $storeConfigurations) {
                        foreach ($storeConfigurations as $configuration) {
                            // Handle encryption parameter
                            $encryption = 0;
                            if (isset($configuration['encryption']) && $configuration['encryption'] == 1) {
                                $encryption = 1;
                            }

                            $convertedConfiguration = $this->convert($configuration);
                            $this->setStoreConfig(
                                $convertedConfiguration['path'],
                                $convertedConfiguration['value'],
                                $code,
                                $encryption
                            );
                        }
                    }
                }
            }
        } catch (ComponentException $e) {
            $this->log->logError($e->getMessage());
        }
    }

    private function setGlobalConfig($path, $value, $encrypted = 0)
    {
        try {
            // Check existing value, skip if the same
            $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT;
            $existingValue = $this->scopeConfig->getValue($path, $scope);
            if ($value == $existingValue) {
                $this->log->logComment(sprintf("Global Config Already: %s = %s", $path, $value));
                return;
            }

            if ($encrypted) {
                $value = $this->encrypt($value);
            }

            // Save the config
            $this->configResource->saveConfig($path, $value, $scope, 0);<commit_msg>Auto-encrypt any paths using an encryption model, regardless of the encryption flag<commit_after><?php

namespace CtiDigital\Configurator\Component;

use CtiDigital\Configurator\Api\ComponentInterface;
use CtiDigital\Configurator\Exception\ComponentException;
use CtiDigital\Configurator\Api\LoggerInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Encryption\EncryptorInterface;
use Magento\Store\Model\StoreFactory;
use Magento\Store\Model\WebsiteFactory;
use Magento\Theme\Model\ResourceModel\Theme\Collection;
use Magento\Theme\Model\ResourceModel\Theme\CollectionFactory;
use Magento\Config\Model\ResourceModel\Config as ConfigResource;
use Magento\Framework\App\Config as ScopeConfig;

class Config implements ComponentInterface
{
    const PATH_THEME_ID = 'design/theme/theme_id';
    const CLASS_ENCRYPTED = 'Magento\Config\Model\Config\Backend\Encrypted';

    protected $alias = 'config';
    protected $name = 'Configuration';
    protected $description = 'Component to set the store/system configuration values';

    /**
     * @var ConfigResource
     */
    protected $configResource;

    /**
     * @var ScopeConfig
     */
    protected $scopeConfig;

    /**
     * @var CollectionFactory
     */
    protected $collectionFactory;

    /**
     * @var EncryptorInterface
     */
    protected $encryptor;

    /**
     * @var WebsiteFactory
     */
    protected $websiteFactory;

    /**
     * @var StoreFactory
     */
    protected $storeFactory;

    /**
     * @var LoggerInterface
     */
    private $log;

    /**
     * @var ScopeConfig\Initial
     */
    private $initialConfig;

    /**
     * Config constructor.
     * @param ConfigResource $configResource
     * @param ScopeConfig $scopeConfig
     * @param ScopeConfig\Initial $initialConfig
     * @param CollectionFactory $collectionFactory
     * @param EncryptorInterface $encryptor
     * @param WebsiteFactory $websiteFactory
     * @param StoreFactory $storeFactory
     * @param LoggerInterface $log
     */
    public function __construct(
        ConfigResource $configResource,
        ScopeConfig $scopeConfig,
        ScopeConfig\Initial $initialConfig,
        CollectionFactory $collectionFactory,
        EncryptorInterface $encryptor,
        WebsiteFactory $websiteFactory,
        StoreFactory $storeFactory,
        LoggerInterface $log
    ) {
        $this->configResource = $configResource;
        $this->scopeConfig = $scopeConfig;
        $this->initialConfig = $initialConfig;
        $this->collectionFactory = $collectionFactory;
        $this->encryptor = $encryptor;
        $this->websiteFactory = $websiteFactory;
        $this->storeFactory = $storeFactory;
        $this->log = $log;
    }

    /**
     * @param $data
     * @SuppressWarnings(PHPMD)
     */
    public function execute($data = null) //phpcs:ignore Generic.Metrics.NestingLevel
    {
        try {
            $validScopes = ['global', 'websites', 'stores'];
            foreach ($data as $scope => $configurations) {
                if (!in_array($scope, $validScopes)) {
                    throw new ComponentException(sprintf("This is not a valid scope '%s' in your config.", $scope));
                }

                if ($scope == "global") {
                    foreach ($configurations as $configuration) {
                        // Handle encryption parameter

                        $encryption = 0;
                        if (isset($configuration['encryption']) && $configuration['encryption'] == 1) {
                            $encryption = 1;
                        }

                        $convertedConfiguration = $this->convert($configuration);
                        // Check if the path uses an encryption model. If yes, set encryption to true
                        $encryption = $this->determineEncryption($convertedConfiguration, $encryption);
                        $this->setGlobalConfig(
                            $convertedConfiguration['path'],
                            $convertedConfiguration['value'],
                            $encryption
                        );
                    }
                }

                if ($scope == "websites") {
                    foreach ($configurations as $code => $websiteConfigurations) {
                        foreach ($websiteConfigurations as $configuration) {
                            // Handle encryption parameter
                            $encryption = 0;
                            if (isset($configuration['encryption']) && $configuration['encryption'] == 1) {
                                $encryption = 1;
                            }
                            $convertedConfiguration = $this->convert($configuration);
                            // Check if the path uses an encryption model. If yes, set encryption to true
                            $encryption = $this->determineEncryption($convertedConfiguration, $encryption);
                            $this->setWebsiteConfig(
                                $convertedConfiguration['path'],
                                $convertedConfiguration['value'],
                                $code,
                                $encryption
                            );
                        }
                    }
                }

                if ($scope == "stores") {
                    foreach ($configurations as $code => $storeConfigurations) {
                        foreach ($storeConfigurations as $configuration) {
                            // Handle encryption parameter
                            $encryption = 0;
                            if (isset($configuration['encryption']) && $configuration['encryption'] == 1) {
                                $encryption = 1;
                            }

                            $convertedConfiguration = $this->convert($configuration);
                            // Check if the path uses an encryption model. If yes, set encryption to true
                            $encryption = $this->determineEncryption($convertedConfiguration, $encryption);
                            $this->setStoreConfig(
                                $convertedConfiguration['path'],
                                $convertedConfiguration['value'],
                                $code,
                                $encryption
                            );
                        }
                    }
                }
            }
        } catch (ComponentException $e) {
            $this->log->logError($e->getMessage());
        }
    }

    private function determineEncryption(array $configuration, $encryption)
    {
        $metaData = $this->initialConfig->getMetadata();

        foreach($metaData as $path => $processor) {
            if($path == $configuration['path']) {
                if (isset($processor['backendModel']) && $processor['backendModel'] === self::CLASS_ENCRYPTED) {
                    $encryption = 1;
                }
            }
        }

        return $encryption;
    }

    private function setGlobalConfig($path, $value, $encrypted = 0)
    {
        try {
            // Check existing value, skip if the same
            $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT;
            $existingValue = $this->scopeConfig->getValue($path, $scope);
            if ($value == $existingValue) {
                $this->log->logComment(sprintf("Global Config Already: %s = %s", $path, $value));
                return;
            }

            if ($encrypted) {
                $value = $this->encrypt($value);
            }

            // Save the config
            $this->configResource->saveConfig($path, $value, $scope, 0);
{'fraction_non_alphanumeric': 0.10241657077100115, 'fraction_numerical': 0.0016542002301495973, 'mean_word_length': 1.5612451648554062, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5132252', 'n_tokens_mistral': 3331, 'n_tokens_neox': 3152, 'n_words': 681}