<commit_before><?php

namespace Nails\Admin\Admin;

use Nails\Admin\Constants;
use Nails\Admin\Controller\Base;
use Nails\Admin\Factory\Nav;
use Nails\Admin\Helper;
use Nails\Common\Exception\FactoryException;
use Nails\Common\Exception\NailsException;
use Nails\Common\Exception\ValidationException;
use Nails\Common\Factory\Component;
use Nails\Common\Factory\Model\Field;
use Nails\Common\Service\AppSetting;
use Nails\Common\Service\FormValidation;
use Nails\Common\Service\Input;
use Nails\Common\Service\Session;
use Nails\Components;
use Nails\Factory;
use Nails\Common\Interfaces;

/**
 * Class Settings
 *
 * @package Nails\Admin\Admin
 */
class Settings extends Base
{
    /**
     * @var \stdClass[]
     */
    protected static $aSettings = [];

    // --------------------------------------------------------------------------

    /**
     * Announces this controller's navGroups
     *
     * @return \stdClass
     */
    public static function announce()
    {
        /** @var Nav $oNav */
        $oNav = Factory::factory('Nav', Constants::MODULE_SLUG);
        $oNav
            ->setLabel('Settings')
            ->setIcon('fa-wrench');

        static::discoverSettings();

        foreach (static::$aSettings as $sSlug => $oSetting) {

            //  @todo (Pablo 2021-03-24) - check for permissions

            $oNav->addAction(
                $oSetting->label,
                'index?setting=' . $sSlug
            );
        }

        return $oNav;
    }

    // --------------------------------------------------------------------------

    /**
     * Returns an array of permissions which can be configured for the user
     *
     * @return array
     */
    public static function permissions(): array
    {
        $aPermissions = parent::permissions();

        //  @todo (Pablo 2021-03-24) - offer permissions for each setting

        return $aPermissions;
    }

    // --------------------------------------------------------------------------

    /**
     * Discovers component settings classes
     *
     * @throws NailsException
     */
    protected static function discoverSettings(): void
    {
        if (empty(static::$aSettings)) {
            foreach (Components::available() as $oComponent) {

                $aClasses = $oComponent
                    ->findClasses('Settings')
                    ->whichImplement(Interfaces\Component\Settings::class);

                foreach ($aClasses as $sClass) {

                    /** @var Interfaces\Component\Settings $oClass */
                    $oClass = new $sClass();
                    $sSlug  = md5($sClass);

                    static::$aSettings[$sSlug] = (object) [
                        'label'     => $oClass->getLabel(),
                        'slug'      => md5($sClass),
                        'instance'  => $oClass,
                        'component' => $oComponent,
                    ];
                }
            }

            arraySortMulti(static::$aSettings, 'label');
        }
    }

    // --------------------------------------------------------------------------

    public function index()
    {
        /** @var Input $oInput */
        $oInput = Factory::service('Input');
        /** @var FormValidation $oFormValidation */
        $oFormValidation = Factory::service('FormValidation');
        /** @var Session $oSession */
        $oSession = Factory::service('Session');

        static::discoverSettings();

        $oSetting = static::$aSettings[$oInput->get('setting')] ?? null;
        if (empty($oSetting)) {
            show404();

        } elseif ($oInput->post()) {
            try {

                $oFormValidation
                    ->buildValidator(array_combine(
                        array_map(function (Components\Setting $oField) {
                            return $oField->getKey();
                        }, $oSetting->instance->get()),
                        array_map(function (Components\Setting $oField) {
                            return $oField->getValidation();
                        }, $oSetting->instance->get())
                    ))
                    ->run();

                /** @var Components\Setting $oField */
                foreach ($oSetting->instance->get() as $oField) {
                    if (!$oField->isReadOnly()) {

                        $mValue     = $oInput->post($oField->getKey());
                        $cFormatter = $oField->getSaveFormatter();
                        if ($cFormatter !== null) {
                            $mValue = call_user_func($cFormatter, $mValue);<commit_msg>Add permission support<commit_after><?php

namespace Nails\Admin\Admin;

use Nails\Admin\Constants;
use Nails\Admin\Controller\Base;
use Nails\Admin\Factory\Nav;
use Nails\Admin\Helper;
use Nails\Common\Exception\FactoryException;
use Nails\Common\Exception\NailsException;
use Nails\Common\Exception\ValidationException;
use Nails\Common\Factory\Component;
use Nails\Common\Factory\Model\Field;
use Nails\Common\Service\AppSetting;
use Nails\Common\Service\FormValidation;
use Nails\Common\Service\Input;
use Nails\Common\Service\Session;
use Nails\Components;
use Nails\Factory;
use Nails\Common\Interfaces;

/**
 * Class Settings
 *
 * @package Nails\Admin\Admin
 */
class Settings extends Base
{
    /**
     * @var \stdClass[]
     */
    protected static $aSettings = [];

    // --------------------------------------------------------------------------

    /**
     * Announces this controller's navGroups
     *
     * @return \stdClass
     */
    public static function announce()
    {
        /** @var Nav $oNav */
        $oNav = Factory::factory('Nav', Constants::MODULE_SLUG);
        $oNav
            ->setLabel('Settings')
            ->setIcon('fa-wrench');

        static::discoverSettings();

        foreach (static::$aSettings as $sSlug => $oSetting) {

            if (userHasPermission('admin:admin:settings:' . $oSetting->slug)) {

                $oNav->addAction(
                    $oSetting->label,
                    'index?setting=' . $sSlug,
                    array_filter([

                        $oSetting->component->type === 'driver'
                            ? Factory::factory('NavAlert', Constants::MODULE_SLUG)
                            ->setValue('Driver')
                            ->setLabel($oSetting->component->forModule)
                            ->setSeverity('warning')
                            : null,

                        $oSetting->component->type === 'skin'
                            ? Factory::factory('NavAlert', Constants::MODULE_SLUG)
                            ->setValue('Skin')
                            ->setLabel($oSetting->component->forModule)
                            ->setSeverity('info')
                            : null,
                    ])
                );
            }
        }

        return $oNav;
    }

    // --------------------------------------------------------------------------

    /**
     * Returns an array of permissions which can be configured for the user
     *
     * @return array
     */
    public static function permissions(): array
    {
        $aPermissions = parent::permissions();

        static::discoverSettings();

        foreach (static::$aSettings as $sSlug => $oSetting) {

            $aPermissions[$oSetting->slug] = sprintf(
                'Manage settings for %s (%s)',
                $oSetting->label,
                $oSetting->component->slug
            );
        }

        return $aPermissions;
    }

    // --------------------------------------------------------------------------

    /**
     * Discovers component settings classes
     *
     * @throws NailsException
     */
    protected static function discoverSettings(): void
    {
        if (empty(static::$aSettings)) {
            foreach (Components::available() as $oComponent) {

                $aClasses = $oComponent
                    ->findClasses('Settings')
                    ->whichImplement(Interfaces\Component\Settings::class);

                foreach ($aClasses as $sClass) {

                    /** @var Interfaces\Component\Settings $oClass */
                    $oClass = new $sClass();
                    $sSlug  = md5($sClass);

                    static::$aSettings[$sSlug] = (object) [
                        'label'     => $oClass->getLabel(),
                        'slug'      => md5($sClass),
                        'instance'  => $oClass,
                        'component' => $oComponent,
                    ];
                }
            }

            arraySortMulti(static::$aSettings, 'label');
        }
    }

    // --------------------------------------------------------------------------

    public function index()
    {
        /** @var Input $oInput */
        $oInput = Factory::service('Input');
        /** @var FormValidation $oFormValidation */
        $oFormValidation = Factory::service('FormValidation');
        /** @var Session $oSession */
        $oSession = Factory::service('Session');

        static::discoverSettings();

        $oSetting = static::$aSettings[$oInput->get('setting')] ?? null;
        if (empty($oSetting)) {
            show404();

        } elseif (!userHasPermission('admin:admin:settings:' . $oSetting->slug)) {
            unauthorised();

        } elseif ($oInput->post()) {
            try {

                $oFormValidation
                    ->buildValidator(array_combine(
                        array_map(function (Components\Setting $oField) {
                            return $oField->getKey();
                        }, $oSetting->instance->get()),
                        array_map(function (Components\Setting $oField) {
                            return $oField->getValidation();
                        }, $oSetting->instance->get())
                    ))
                    ->run();

                /** @var Components\Setting $oField */
                foreach ($oSetting->instance->get() as $oField) {
                    if (!$oField->isReadOnly()) {

                        $mValue     = $oInput->post($oField->getKey());
                        $cFormatter = $oField->getSaveFormatter();
                        if ($cFormatter !== null) {
                            $mValue = call_user_func($cFormatter, $mValue);
{'fraction_non_alphanumeric': 0.1802678485403218, 'fraction_numerical': 0.0025050582907794583, 'mean_word_length': 1.3468234230160525, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 80, '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': '1529945', 'n_tokens_mistral': 2610, 'n_tokens_neox': 2503, 'n_words': 472}