Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better handling of legacy configuration file options for disabled modules #5629

Closed
marc-farre opened this issue Apr 8, 2022 · 13 comments
Closed

Comments

@marc-farre
Copy link
Collaborator

marc-farre commented Apr 8, 2022

Is your feature request related to a problem? Please describe.

Add a module setting in the protected/config/common.php file.
Uninstall the module or remove or rename the attribute in the module.php that is used in common.php.
Humhub crashes (see log bellow).

Describe the solution you'd like

Humhub should ignore modules names or attributes names that doesn't exists and add an error in the log to prevent the admin to update the common.php configuration file.

Describe alternatives you've considered

Add a notice in https://docs.humhub.org/docs/admin/troubleshooting

Error log:

yii\base\InvalidConfigException: Object configuration must be an array containing a "class" or "__class" element. in /var/www/humhub/protected/vendor/yiisoft/yii2/BaseYii.php:368
Stack trace:
#0 /var/www/humhub/protected/vendor/yiisoft/yii2/base/Module.php(427): yii\BaseYii::createObject()
#1 /var/www/humhub/protected/humhub/modules/ui/view/helpers/ThemeHelper.php(45): yii\base\Module->getModule()
#2 /var/www/humhub/protected/humhub/modules/ui/view/helpers/ThemeHelper.php(188): humhub\modules\ui\view\helpers\ThemeHelper::getThemes()
#3 /var/www/humhub/protected/humhub/modules/ui/view/helpers/ThemeHelper.php(176): humhub\modules\ui\view\helpers\ThemeHelper::getThemeParent()
#4 /var/www/humhub/protected/humhub/modules/ui/view/helpers/ThemeHelper.php(138): humhub\modules\ui\view\helpers\ThemeHelper::getThemeTree()
#5 /var/www/humhub/protected/humhub/modules/ui/view/components/ThemeVariables.php(129): humhub\modules\ui\view\helpers\ThemeHelper::getAllVariables()
#6 /var/www/humhub/protected/humhub/modules/ui/view/components/ThemeVariables.php(116): humhub\modules\ui\view\components\ThemeVariables->storeVariables()
#7 /var/www/humhub/protected/humhub/modules/ui/view/components/ThemeVariables.php(67): humhub\modules\ui\view\components\ThemeVariables->ensureLoaded()
#8 /var/www/humhub/protected/humhub/modules/ui/view/components/Theme.php(213): humhub\modules\ui\view\components\ThemeVariables->get()
#9 /var/www/humhub/protected/modules/legal/widgets/views/cookies.php(25): humhub\modules\ui\view\components\Theme->variable()
#10 /var/www/humhub/protected/vendor/yiisoft/yii2/base/View.php(348): require('...')
#11 /var/www/humhub/protected/vendor/yiisoft/yii2/base/View.php(257): yii\base\View->renderPhpFile()
#12 /var/www/humhub/protected/vendor/yiisoft/yii2/base/View.php(156): yii\base\View->renderFile()
#13 /var/www/humhub/protected/vendor/yiisoft/yii2/base/Widget.php(237): yii\base\View->render()
#14 /var/www/humhub/protected/modules/legal/widgets/CookieNote.php(27): yii\base\Widget->render()
#15 /var/www/humhub/protected/humhub/components/Widget.php(63): humhub\modules\legal\widgets\CookieNote->run()
#16 /var/www/humhub/protected/humhub/widgets/BaseStack.php(88): humhub\components\Widget::widget()
#17 /var/www/humhub/protected/humhub/components/Widget.php(63): humhub\widgets\BaseStack->run()
#18 /var/www/humhub/protected/humhub/modules/ui/view/components/View.php(435): humhub\components\Widget::widget()
#19 /var/www/humhub/protected/modules/clean-theme/themes/clean/views/humhub/layouts/main.php(53): humhub\modules\ui\view\components\View->endBody()
#20 /var/www/humhub/protected/modules/seve/themes/seve/views/humhub/layouts/main.php(10): require('...')
#21 /var/www/humhub/protected/vendor/yiisoft/yii2/base/View.php(348): require('...')
#22 /var/www/humhub/protected/vendor/yiisoft/yii2/base/View.php(257): yii\base\View->renderPhpFile()
#23 /var/www/humhub/protected/humhub/components/Controller.php(136): yii\base\View->renderFile()
#24 /var/www/humhub/protected/vendor/yiisoft/yii2/base/Controller.php(411): humhub\components\Controller->renderContent()
#25 /var/www/humhub/protected/humhub/modules/admin/controllers/SettingController.php(138): yii\base\Controller->render()
#26 [internal function]: humhub\modules\admin\controllers\SettingController->actionCaching()
#27 /var/www/humhub/protected/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array()
#28 /var/www/humhub/protected/vendor/yiisoft/yii2/base/Controller.php(181): yii\base\InlineAction->runWithParams()
#29 /var/www/humhub/protected/vendor/yiisoft/yii2/base/Module.php(534): yii\base\Controller->runAction()
#30 /var/www/humhub/protected/vendor/yiisoft/yii2/web/Application.php(104): yii\base\Module->runAction()
#31 /var/www/humhub/protected/vendor/yiisoft/yii2/base/Application.php(392): yii\web\Application->handleRequest()
#32 /var/www/humhub/index.php(27): yii\base\Application->run()
#33 {main}
@ArchBlood
Copy link
Contributor

Personally I believe that the common.php should only be used in extreme cases just like the web.php and console.php where needed, while variables less needed should be configurable by the common.php file, this is even more so for OAuth clients and such where it is no longer needed to be used at all.

My suggestion would be making a list (which is already in the community site) of variables that are less used ordered by recommendation while creating the settings for admins in the admin panel for more important variables. This would reduce the need for the use of a common.php configuration to the bare minimum.

@marc-farre
Copy link
Collaborator Author

If think it would be great if this issue is solved.
See https://community.humhub.com/content/perma?id=269230
It should be quite easy. If need, I can have a look to it.

@luke-
Copy link
Contributor

luke- commented Jun 29, 2023

@funkycram Would be great if you can take a look into it.

@marc-farre
Copy link
Collaborator Author

@luke- For the moment, I didn't succeed to find a solution for it (I'll try later if I find more time).

FYI, this issue crashed my updated to HumHub 1.16 because I had this in my config.php file:

        'search' => [
            'searchItemLimit' => 10000,
        ],

I'm afraid many of us are experiencing this bug.
The solution was to finish DB migrations manually: php yii migrate/up --includeModuleMigrations=1 and to flush cache, but some sys-admin might not know how to deal with this issue.

Error log:

Exception (Invalid Configuration) 'yii\base\InvalidConfigException' with message 'The configuration for the "search" component must contain a "class" element.' 

in /var/www/humhub/protected/vendor/yiisoft/yii2/di/ServiceLocator.php:210

Stack trace:
#0 /var/www/humhub/protected/vendor/yiisoft/yii2/di/ServiceLocator.php(266): yii\di\ServiceLocator->set()
#1 /var/www/humhub/protected/vendor/yiisoft/yii2/base/Component.php(181): yii\di\ServiceLocator->setComponents()
#2 /var/www/humhub/protected/vendor/yiisoft/yii2/BaseYii.php(558): yii\base\Component->__set()
#3 /var/www/humhub/protected/vendor/yiisoft/yii2/base/BaseObject.php(108): yii\BaseYii::configure()
#4 /var/www/humhub/protected/vendor/yiisoft/yii2/base/Application.php(205): yii\base\BaseObject->__construct()
#5 /var/www/humhub/protected/humhub/components/ApplicationTrait.php(42): yii\base\Application->__construct()
#6 /var/www/humhub/index.php(28): humhub\components\Application->__construct()
#7 {main}

@ArchBlood
Copy link
Contributor

Here's an idea that could probably help mitigate such issues, similar to the requirements.php file we create a variables.php within modules and check against this file within the common.php file?

3rd-party Module Example

<?php

/**
 * This file provides to overwrite the default HumHub / Yii configuration by your local common (Console and Web) environments
 * @see http://www.yiiframework.com/doc-2.0/guide-concept-configurations.html
 * @see http://docs.humhub.org/admin-installation-configuration.html
 * @see http://docs.humhub.org/dev-environment.html
 */

// Default configuration values
$config = [
    'common_variable' => 'Default value for common variable',
];

// Check for installed modules
$moduleManager = Yii::$app->getModuleManager();
$installedModules = $moduleManager->getModules();

// Merge installed modules' configurations
foreach ($installedModules as $moduleId => $moduleClass) {
    $variablesFile = Yii::getAlias('@' . $moduleId . '/variables.php');
    if (file_exists($variablesFile)) {
        $moduleConfig = require($variablesFile);
        // Merge the module-specific configurations with the default configuration
        $config = array_merge($config, $moduleConfig);
    }
}

return $config;

variables.php Example

<?php

// Module-specific configurations
return [
    'module_variable_1' => 'Value 1',
    'module_variable_2' => 'Value 2',
    // Add more module-specific variables as needed
];

@luke-
Copy link
Contributor

luke- commented Apr 8, 2024

@marc-farre If you have time, maybe you can test my PR. This should prevent errors caused by old config variables.

@marc-farre
Copy link
Collaborator Author

@luke- Thanks very much for this PR!

I've tested to add this in config/common.php:

    'modules' => [
        'space' => [
            'missingProperty' => 'some value',
        ],
    ],

And I have:
yii\base\UnknownPropertyException
Setting unknown property: humhub\modules\space\Module::missingProperty

But I think your PR should help me find a solution. I'll try to work on it as soon as possible (if I manage to work it out!).

@luke-
Copy link
Contributor

luke- commented Apr 8, 2024

@marc-farre My PR should only protect/warn if there are outdated configuration entries. (e.g. Search/Directory)

There is still an error for incorrect configuration entries. That is intentional.

@marc-farre
Copy link
Collaborator Author

@luke- I see.

New test:

  1. Enable a test-module module
  2. Add this configuration:
    'modules' => [
        'test-module' => [
            'icon' => 'gear',
        ],
    ],
  1. Disable the module and run cron jobs

I still have the error:

yii\base\InvalidConfigException: Object configuration must be an array containing a "class" or "__class" element. in /var/www/humhub/protected/vendor/yiisoft/yii2/BaseYii.php:369
Stack trace:
#0 /var/www/humhub/protected/vendor/yiisoft/yii2/base/Module.php(446): yii\BaseYii::createObject()
#1 /var/www/humhub/protected/humhub/components/ModuleManager.php(513): yii\base\Module->getModule()
#2 /var/www/humhub/protected/humhub/components/ModuleManager.php(369): humhub\components\ModuleManager->getModule()
#3 /var/www/humhub/protected/humhub/modules/content/components/ContentContainerModuleManager.php(170): humhub\components\ModuleManager->getModules()
#4 /var/www/humhub/protected/humhub/modules/content/components/ContentContainerModuleManager.php(145): humhub\modules\content\components\ContentContainerModuleManager->getAvailable()
#5 /var/www/humhub/protected/humhub/modules/content/components/ContentContainerModuleManager.php(341): humhub\modules\content\components\ContentContainerModuleManager->getEnabled()
#6 [internal function]: humhub\modules\content\components\ContentContainerModuleManager->humhub\modules\content\components\{closure}()
#7 /var/www/humhub/protected/vendor/yiisoft/yii2/caching/Cache.php(609): call_user_func()
#8 /var/www/humhub/protected/humhub/modules/content/components/ContentContainerModuleManager.php(339): yii\caching\Cache->getOrSet()
#9 /var/www/humhub/protected/humhub/modules/content/widgets/WallCreateContentMenu.php(153): humhub\modules\content\components\ContentContainerModuleManager->getContentClasses()
#10 /var/www/humhub/protected/humhub/modules/space/controllers/SpaceController.php(104): humhub\modules\content\widgets\WallCreateContentMenu::canCreateEntry()
#11 [internal function]: humhub\modules\space\controllers\SpaceController->actionHome()
#12 /var/www/humhub/protected/vendor/yiisoft/yii2/base/InlineAction.php(58): call_user_func_array()
#13 /var/www/humhub/protected/vendor/yiisoft/yii2/base/Controller.php(179): yii\base\InlineAction->runWithParams()
#14 /var/www/humhub/protected/vendor/yiisoft/yii2/base/Module.php(553): yii\base\Controller->runAction()
#15 /var/www/humhub/protected/vendor/yiisoft/yii2/web/Application.php(104): yii\base\Module->runAction()
#16 /var/www/humhub/protected/vendor/yiisoft/yii2/base/Application.php(385): yii\web\Application->handleRequest()
#17 /var/www/humhub/index.php(28): yii\base\Application->run()
#18 {main}
Copy StacktraceSearch StackoverflowSearch GoogleException
Invalid Configuration – yii\base\InvalidConfigException
Object configuration must be an array containing a "class" or "__class" element.
1. in /var/www/humhub/protected/vendor/yiisoft/yii2/BaseYii.phpat line 369
360361362363364365366367368369370371372373374375376377378            return static::$container->get($class, $params, $type);
        }
 
        if (isset($type['class'])) {
            $class = $type['class'];
            unset($type['class']);
            return static::$container->get($class, $params, $type);
        }
 
        throw new InvalidConfigException('Object configuration must be an array containing a "class" or "__class" element.');
    }
 
    private static $_logger;
 
    /**
     * @return Logger message logger
     */
    public static function getLogger()
    {
2. in /var/www/humhub/protected/vendor/yiisoft/yii2/base/Module.php at line 446– yii\BaseYii::createObject()
3. in /var/www/humhub/protected/humhub/components/ModuleManager.php at line 513– yii\base\Module::getModule()
507508509510511512513514515516517518519        if ($id instanceof Module) {
            return $id;
        }
 
        // Enabled Module
        if (Yii::$app->hasModule($id)) {
            return Yii::$app->getModule($id, true);
        }
 
        // Disabled Module
        if (isset($this->modules[$id])) {
            $class = $this->modules[$id];
            return Yii::createObject($class, [$id, Yii::$app]);
4. in /var/www/humhub/protected/humhub/components/ModuleManager.php at line 369– humhub\components\ModuleManager::getModule()
363364365366367368369370371372373374375                continue;
            }
 
            if ($options['returnClass']) {
                $modules[$id] = $class;
            } else {
                $module = $this->getModule($id);
                if ($module instanceof Module) {
                    $modules[$id] = $module;
                }
            }
        }
 
5. in /var/www/humhub/protected/humhub/modules/content/components/ContentContainerModuleManager.php at line 170– humhub\components\ModuleManager::getModules()
164165166167168169170171172173174175176        if ($this->_available !== null) {
            return $this->_available;
        }
 
        $this->_available = [];
 
        foreach (Yii::$app->moduleManager->getModules() as $module) {
            if ($this->isAvailableModule($module)) {
                $this->_available[$module->id] = $module;
            }
        }
 
        return $this->_available;
6. in /var/www/humhub/protected/humhub/modules/content/components/ContentContainerModuleManager.php at line 145– humhub\modules\content\components\ContentContainerModuleManager::getAvailable()
139140141142143144145146147148149150151     *
     * @return array a list of enabled module ids
     */
    public function getEnabled()
    {
        $enabled = [];
        $available = $this->getAvailable();
        foreach ($this->getStates() as $id => $state) {
            if (array_key_exists($id, $available) && ($state === ContentContainerModuleState::STATE_ENABLED || $state === ContentContainerModuleState::STATE_FORCE_ENABLED)) {
                $enabled[] = $id;
            }
        }
        $enabled[] = 'post';
7. in /var/www/humhub/protected/humhub/modules/content/components/ContentContainerModuleManager.php at line 341– humhub\modules\content\components\ContentContainerModuleManager::getEnabled()
335336337338339340341342343344345346347     * @since 1.13
     */
    public function getContentClasses(): array
    {
        return Yii::$app->runtimeCache->getOrSet(__METHOD__ . $this->contentContainer->id, function () {
            $contentClasses = [];
            foreach ($this->getEnabled() as $moduleId) {
                $module = Yii::$app->getModule($moduleId);
                foreach ($module->getContentClasses($this->contentContainer) as $class) {
                    $content = new $class($this->contentContainer);
                    if (!($content instanceof ContentActiveRecord)) {
                        throw new InvalidConfigException($class . ' must be instance of ContentActiveRecord!');
                    }
8. humhub\modules\content\components\ContentContainerModuleManager::humhub\modules\content\components\{closure}()
9. in /var/www/humhub/protected/vendor/yiisoft/yii2/caching/Cache.php at line 609– call_user_func()
10. in /var/www/humhub/protected/humhub/modules/content/components/ContentContainerModuleManager.php at line 339– yii\caching\Cache::getOrSet()
333334335336337338339340341342343344345     * @param ContentContainerActiveRecord|null $contentContainer
     * @return ContentActiveRecord[]
     * @since 1.13
     */
    public function getContentClasses(): array
    {
        return Yii::$app->runtimeCache->getOrSet(__METHOD__ . $this->contentContainer->id, function () {
            $contentClasses = [];
            foreach ($this->getEnabled() as $moduleId) {
                $module = Yii::$app->getModule($moduleId);
                foreach ($module->getContentClasses($this->contentContainer) as $class) {
                    $content = new $class($this->contentContainer);
                    if (!($content instanceof ContentActiveRecord)) {
11. in /var/www/humhub/protected/humhub/modules/content/widgets/WallCreateContentMenu.php at line 153– humhub\modules\content\components\ContentContainerModuleManager::getContentClasses()
147148149150151152153154155156157158159    public static function canCreateEntry(?ContentContainerActiveRecord $contentContainer, string $type = 'any'): bool
    {
        if (!($contentContainer instanceof ContentContainerActiveRecord)) {
            return false;
        }
 
        foreach ($contentContainer->moduleManager->getContentClasses() as $content) {
            $wallEntryWidget = WallStreamEntryWidget::getByContent($content);
            if (!$wallEntryWidget) {
                continue;
            }
 
            switch ($type) {
12. in /var/www/humhub/protected/humhub/modules/space/controllers/SpaceController.php at line 104– humhub\modules\content\widgets\WallCreateContentMenu::canCreateEntry()
9899100101102103104105106107108109110    public function actionHome()
    {
        $space = $this->contentContainer;
 
        return $this->render('home', [
            'space' => $space,
            'canCreateEntries' => WallCreateContentMenu::canCreateEntry($space),
            'isMember' => $space->isMember(),
            'isSingleContentRequest' => !empty(Yii::$app->request->getQueryParam('contentId')),
        ]);
    }
 
    /**
13. humhub\modules\space\controllers\SpaceController::actionHome()
14. in /var/www/humhub/protected/vendor/yiisoft/yii2/base/InlineAction.php at line 58– call_user_func_array()
15. in /var/www/humhub/protected/vendor/yiisoft/yii2/base/Controller.php at line 179– yii\base\InlineAction::runWithParams()
16. in /var/www/humhub/protected/vendor/yiisoft/yii2/base/Module.php at line 553– yii\base\Controller::runAction()
17. in /var/www/humhub/protected/vendor/yiisoft/yii2/web/Application.php at line 104– yii\base\Module::runAction()
18. in /var/www/humhub/protected/vendor/yiisoft/yii2/base/Application.php at line 385– yii\web\Application::handleRequest()
19. in /var/www/humhub/index.php at line 28– yii\base\Application::run()
222324252627282930313233    (is_readable(__DIR__ . '/protected/config/dynamic.php')) ? require(__DIR__ . '/protected/config/dynamic.php') : [],
    require(__DIR__ . '/protected/config/common.php'),
    require(__DIR__ . '/protected/config/web.php')
);

luke- added a commit that referenced this issue Apr 8, 2024
* Added handling for legacy configuration file options

* Code Style fixes

* Fix #5629: Better handling of legacy configuration file options

* Removed unused imports

* Fixed typo
@luke-
Copy link
Contributor

luke- commented Apr 8, 2024

@luke- FYI, I have merged the PR - It only covers core related scenario with changed modules/settings (e.g. removal of modules such as search) and prevents a fatal error and displays a warning in the SelfTest.

For other scenarios we need different checks:

  • Custom configurations of not existent modules
  • Invalid properties of modules and components

However, it would be important that we do not suppress such errors - instead we should show a more meaningful error.

@marc-farre marc-farre changed the title Prevent Humhub from crashing in case of error in the protected/config/common.php file Better handling of legacy configuration file options for disabled non-core module Apr 9, 2024
@marc-farre marc-farre changed the title Better handling of legacy configuration file options for disabled non-core module Better handling of legacy configuration file options for disabled modules Apr 9, 2024
marc-farre added a commit that referenced this issue Apr 9, 2024
marc-farre added a commit that referenced this issue Apr 9, 2024
marc-farre added a commit that referenced this issue Apr 9, 2024
marc-farre added a commit that referenced this issue Apr 9, 2024
@marc-farre
Copy link
Collaborator Author

marc-farre commented Apr 9, 2024

@luke- thanks!

1/ Custom configurations of not existent modules

I've started a PR here: https://github.com/humhub/humhub/pull/6938/files
I know it's not perfect, but this is what I managed to do!

I wanted to throw an InvalidConfigException but, it doesn't work. Instead, I have:

An Error occurred while handling another error:
Error: Call to a member function get() on null in /var/www/hhcore/protected/humhub/modules/file/validators/FileValidator.php:46

So with the PR, a flash error is displayed, and the same message is added as an error in the log:

image

If you agree with the PR, I'll fix the test issues.

2/ Invalid properties of modules and components

We already have an exception explaining the error, so I think it's enough for now (even if we could later explain where to find the configuration containing this unknown property): https://github.com/yiisoft/yii2/blob/master/framework/base/Component.php#L210

@luke-
Copy link
Contributor

luke- commented Apr 9, 2024

@marc-farre Thanks looks good. Is it ready to merge or is something to do or test?

@marc-farre
Copy link
Collaborator Author

@marc-farre Thanks looks good. Is it ready to merge or is something to do or test?

Yes. Now checks have passed.

@luke- luke- closed this as completed Apr 9, 2024
github-merge-queue bot pushed a commit that referenced this issue Apr 9, 2024
#6938)

* Fix #5629: Better handling of legacy configuration file options for disabled non-core modules

* Fix #5629: Better handling of legacy configuration file options for disabled non-core modules

* Fix #5629: Better handling of legacy configuration file options for disabled non-core modules

* Fix #5629: Better handling of legacy configuration file options for disabled non-core modules
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants