CanastaWiki / Canasta

MediaWiki Docker image for Canasta, an all-in-one MediaWiki stack for easy deployment and management of enterprise-ready MediaWiki on production environments.
https://www.canasta.wiki
MIT License
36 stars 27 forks source link

"XML description is missing an element: structure." error with default Chameleon Layout on CanastaWiki #378

Closed zuobot closed 2 months ago

zuobot commented 2 months ago

Note: Cross post from ProfessionalWiki/chameleon Github, since I'm not sure it's the issue from Canasta enviroment, or from Chameleon Skin itself.

Context

I installed CanastaWiki on an Ubuntu localhost. Canasta has Chameleon skin come by default.

The overall contents of Canasta are as follows:

UPDATE 2024-04-08: I updated Chameleon to latest version (4.3.0) but the issue remain the same.

Issue

I loaded default layouts (navhead, stickyhead.xml...) from Customization.md page

Add into LocalSettings.php as in the guide: $egChameleonLayoutFile= __DIR__ . '/layout/navhead.xml';

However, when I reload the wiki, the issue is as below:

MediaWiki internal error.

Original exception: [f8bc8a0ea719f26b05e99198] /wiki/Special:Version MWException: /mediawiki/config/layout/navhead.xml: XML description is missing an element: structure.
Backtrace:
from /var/www/mediawiki/w/canasta-skins/chameleon/src/ComponentFactory.php(83)
#0 /var/www/mediawiki/w/canasta-skins/chameleon/src/Chameleon.php(151): Skins\Chameleon\ComponentFactory->getRootComponent()
#1 /var/www/mediawiki/w/canasta-skins/chameleon/src/Chameleon.php(126): Skins\Chameleon\Chameleon->addSkinModulesToOutput()
#2 /var/www/mediawiki/w/includes/skins/SkinTemplate.php(243): Skins\Chameleon\Chameleon->setupTemplateForOutput()
#3 /var/www/mediawiki/w/canasta-skins/chameleon/src/Chameleon.php(111): SkinTemplate->prepareQuickTemplate()
#4 /var/www/mediawiki/w/includes/skins/SkinTemplate.php(146): Skins\Chameleon\Chameleon->prepareQuickTemplate()
#5 /var/www/mediawiki/w/includes/skins/SkinTemplate.php(177): SkinTemplate->generateHTML()
#6 /var/www/mediawiki/w/includes/OutputPage.php(2876): SkinTemplate->outputPage()
#7 /var/www/mediawiki/w/includes/MediaWiki.php(922): OutputPage->output()
#8 /var/www/mediawiki/w/includes/MediaWiki.php(562): MediaWiki->main()
#9 /var/www/mediawiki/w/index.php(50): MediaWiki->run()
#10 /var/www/mediawiki/w/index.php(46): wfIndexMain()
#11 {main}

Exception caught inside exception handler: [f8bc8a0ea719f26b05e99198] /wiki/Special:Version MWException: /mediawiki/config/layout/navhead.xml: XML description is missing an element: structure.
Backtrace:
from /var/www/mediawiki/w/canasta-skins/chameleon/src/ComponentFactory.php(83)
#0 /var/www/mediawiki/w/canasta-skins/chameleon/src/Chameleon.php(151): Skins\Chameleon\ComponentFactory->getRootComponent()
#1 /var/www/mediawiki/w/canasta-skins/chameleon/src/Chameleon.php(126): Skins\Chameleon\Chameleon->addSkinModulesToOutput()
#2 /var/www/mediawiki/w/includes/skins/SkinTemplate.php(243): Skins\Chameleon\Chameleon->setupTemplateForOutput()
#3 /var/www/mediawiki/w/canasta-skins/chameleon/src/Chameleon.php(111): SkinTemplate->prepareQuickTemplate()
#4 /var/www/mediawiki/w/includes/skins/SkinTemplate.php(146): Skins\Chameleon\Chameleon->prepareQuickTemplate()
#5 /var/www/mediawiki/w/includes/skins/SkinTemplate.php(177): SkinTemplate->generateHTML()
#6 /var/www/mediawiki/w/includes/OutputPage.php(2876): SkinTemplate->outputPage()
#7 /var/www/mediawiki/w/includes/exception/MWException.php(181): OutputPage->output()
#8 /var/www/mediawiki/w/includes/exception/MWException.php(215): MWException->reportHTML()
#9 /var/www/mediawiki/w/includes/exception/MWExceptionHandler.php(129): MWException->report()
#10 /var/www/mediawiki/w/includes/exception/MWExceptionHandler.php(248): MWExceptionHandler::report()
#11 /var/www/mediawiki/w/includes/MediaWiki.php(581): MWExceptionHandler::handleException()
#12 /var/www/mediawiki/w/index.php(50): MediaWiki->run()
#13 /var/www/mediawiki/w/index.php(46): wfIndexMain()
#14 {main}

Please support me. I tried to search but the most revelant answer is 9 years ago I also check ComponentFactory.php and getRootComponent() function, but cannot figured out the issue.

Thanks for your support.

yaronkoren commented 2 months ago

@zuobot - sorry for the delay. The issue is the apparently file /mediawiki/config/layout/navhead.xml, which I assume doesn't exist at all, even though the error message makes it sound like it's just missing a tag or something. In the instructions you linked to, it says to add something like the following:

$egChameleonLayoutFile= __DIR__ . '/skins/chameleon/layouts/fixedhead.xml';

But you instead added this:

$egChameleonLayoutFile= __DIR__ . '/layout/navhead.xml';

Could that be the problem?

zuobot commented 2 months ago

Hi @yaronkoren , Really thanks for your response.

The issue should not be the file do not exist. The reason is as below explanation: The path after $egChameleonLayoutFile= should be relative to file LocalSettings.php

1. In base MediaWiki (the one the chameleon instruction follow), the LocalSettings.php file is like this structure:

.
├── LocalSetting.php
├── skins/
│   └── chameleon/
│       ├── layouts/
│       │   ├── fixedhead.xml
│       │   ├── navhead.xml
│       │   └── ...
│       └── themes/
│           ├── united.css
│           └── united_bootswatch.scss

That's why Chameleon instruction said the settings like below: $egChameleonLayoutFile= __DIR__ . '/skins/chameleon/layouts/fixedhead.xml';

2. However, in Canasa, the LocalSettings.php file is located inside the config folder.

So in my setting, I mkdir new layout and theme folder inside the config folder like below (with chmod 777)

.
└── config/
    └── LocalSetting.php/
        ├── layout/
        │   ├── fixedhead.xml
        │   ├── navhead.xml
        │   └── ...
        └── theme/
            ├── united.css
            └── united_bootswatch.scss

With this folder structure, I tried to changed the theme, follow the instruction on Chameleon guide

$egChameleonThemeFile = __DIR__ . '/theme/united.scss';
$egChameleonExternalStyleModules = [
    __DIR__ . '/theme/united_bootswatch.scss' => 'afterMain',
];

With this configuration, the theme was changed and there're no issue.

However, the similar configuration for layout has issue like I sent in the previous post $egChameleonLayoutFile= __DIR__ . '/layout/navhead.xml';

I still cannot find where's the issue, so looking for your to spend some time to take a look and support me. Appreciate your support.


Note 1: I tried to changed the link to the file do not exist at all, and the error should be FileFetcher\FileFetchingException not MWException: /mediawiki/config/layout/navhead.xml: XML description is missing an element: structure.

MediaWiki internal error.

Original exception: [540985ef67ed34c85abeae8d] /wiki/Main_Page FileFetcher\FileFetchingException: Could not fetch file: /mediawiki/config/skins/chameleon/layouts/navhead.xml
Backtrace:
from /var/www/mediawiki/w/vendor/jeroen/file-fetcher/src/SimpleFileFetcher.php(28)
#0 /var/www/mediawiki/w/canasta-skins/chameleon/src/ComponentFactory.php(101): FileFetcher\SimpleFileFetcher->fetchFile()
#1 /var/www/mediawiki/w/canasta-skins/chameleon/src/ComponentFactory.php(94): Skins\Chameleon\ComponentFactory->getLayoutXml()
#2 /var/www/mediawiki/w/canasta-skins/chameleon/src/ComponentFactory.php(70): Skins\Chameleon\ComponentFactory->getDomDocument()
#3 /var/www/mediawiki/w/canasta-skins/chameleon/src/Chameleon.php(151): Skins\Chameleon\ComponentFactory->getRootComponent()
#4 /var/www/mediawiki/w/canasta-skins/chameleon/src/Chameleon.php(126): Skins\Chameleon\Chameleon->addSkinModulesToOutput()
#5 /var/www/mediawiki/w/includes/skins/SkinTemplate.php(243): Skins\Chameleon\Chameleon->setupTemplateForOutput()
#6 /var/www/mediawiki/w/canasta-skins/chameleon/src/Chameleon.php(111): SkinTemplate->prepareQuickTemplate()
#7 /var/www/mediawiki/w/includes/skins/SkinTemplate.php(146): Skins\Chameleon\Chameleon->prepareQuickTemplate()
#8 /var/www/mediawiki/w/includes/skins/SkinTemplate.php(177): SkinTemplate->generateHTML()
#9 /var/www/mediawiki/w/includes/OutputPage.php(2876): SkinTemplate->outputPage()
#10 /var/www/mediawiki/w/includes/MediaWiki.php(922): OutputPage->output()
#11 /var/www/mediawiki/w/includes/MediaWiki.php(562): MediaWiki->main()
#12 /var/www/mediawiki/w/index.php(50): MediaWiki->run()
#13 /var/www/mediawiki/w/index.php(46): wfIndexMain()
#14 {main}

Exception caught inside exception handler: [540985ef67ed34c85abeae8d] /wiki/Main_Page FileFetcher\FileFetchingException: Could not fetch file: /mediawiki/config/skins/chameleon/layouts/navhead.xml
Backtrace:
from /var/www/mediawiki/w/vendor/jeroen/file-fetcher/src/SimpleFileFetcher.php(28)
#0 /var/www/mediawiki/w/canasta-skins/chameleon/src/ComponentFactory.php(101): FileFetcher\SimpleFileFetcher->fetchFile()
#1 /var/www/mediawiki/w/canasta-skins/chameleon/src/ComponentFactory.php(94): Skins\Chameleon\ComponentFactory->getLayoutXml()
#2 /var/www/mediawiki/w/canasta-skins/chameleon/src/ComponentFactory.php(70): Skins\Chameleon\ComponentFactory->getDomDocument()
#3 /var/www/mediawiki/w/canasta-skins/chameleon/src/Chameleon.php(151): Skins\Chameleon\ComponentFactory->getRootComponent()
#4 /var/www/mediawiki/w/canasta-skins/chameleon/src/Chameleon.php(126): Skins\Chameleon\Chameleon->addSkinModulesToOutput()
#5 /var/www/mediawiki/w/includes/skins/SkinTemplate.php(243): Skins\Chameleon\Chameleon->setupTemplateForOutput()
#6 /var/www/mediawiki/w/canasta-skins/chameleon/src/Chameleon.php(111): SkinTemplate->prepareQuickTemplate()
#7 /var/www/mediawiki/w/includes/skins/SkinTemplate.php(146): Skins\Chameleon\Chameleon->prepareQuickTemplate()
#8 /var/www/mediawiki/w/includes/skins/SkinTemplate.php(177): SkinTemplate->generateHTML()
#9 /var/www/mediawiki/w/includes/OutputPage.php(2876): SkinTemplate->outputPage()
#10 /var/www/mediawiki/w/includes/exception/MWExceptionRenderer.php(183): OutputPage->output()
#11 /var/www/mediawiki/w/includes/exception/MWExceptionRenderer.php(102): MWExceptionRenderer::reportHTML()
#12 /var/www/mediawiki/w/includes/exception/MWExceptionHandler.php(131): MWExceptionRenderer::output()
#13 /var/www/mediawiki/w/includes/exception/MWExceptionHandler.php(248): MWExceptionHandler::report()
#14 /var/www/mediawiki/w/includes/MediaWiki.php(581): MWExceptionHandler::handleException()
#15 /var/www/mediawiki/w/index.php(50): MediaWiki->run()
#16 /var/www/mediawiki/w/index.php(46): wfIndexMain()
#17 {main}

Note 2: Below is the function getRootComponent() of the file /var/www/mediawiki/w/canasta-skins/chameleon/src/ComponentFactory.php for your #reference:

    public function getRootComponent(): Structure {
        if ( $this->rootComponent === null ) {

            $document = $this->getDomDocument();

            $roots = $document->getElementsByTagName( 'structure' );

            if ( $roots->length > 0 ) {

                $element = $roots->item( 0 );
                if ( $element instanceof DOMElement ) {
                    $this->rootComponent = $this->getComponent( $element );
                }

            } else {
                // TODO: catch other errors, e.g. malformed XML
                throw new MWException( sprintf( '%s: XML description is missing an element: structure.',
                    $this->layoutFileName ) );
            }
        }

        return $this->rootComponent;
    }
yaronkoren commented 2 months ago

Ah, okay - so the file does exist at that location. In that case, I have to ask, then - what are the contents of navhead.xml?

jeffw16 commented 2 months ago

If I understand this correctly, this is definitely not the right approach to take. These modifications are not supported and we won't be able to help you if you deviate from how the config directory was defined by Canasta.

Instead of making this convoluted and unsupported new directory structure, why not simply remove the __DIR__ from the variable and use an absolute path?

zuobot commented 2 months ago

@yaronkoren @jeffw16 I found the solution. I share my note here in case anyone need it.

Inside the Canasta container, there're default layout folder /var/www/mediawiki/w/canasta-skins/chameleon/layouts. By default, Chamleon will prioritize to look for the layout in this layouts folder. The standard chameleon layout (if we don't config anything) is also in the file /var/www/mediawiki/w/canasta-skins/chameleon/layouts/standard.xml.

So if we want to use customized xml layout, there're 2 options:

Option 1:

  1. Copy the customized layout xml file to layouts folder inside docker container.

Command: docker cp LAYOUT_FILE.xml CONTAINER_NAME:/var/www/mediawiki/w/canasta-skins/chameleon/layouts/

To get the CONTAINER_NAME, use the command docker ps. It should has format CANASTA_ID-web-1.

  1. Then we can activate by setting the variable $egChameleonLayoutFile in LocalSettings.php by: $egChameleonLayoutFile= 'layouts/LAYOUT_FILE.xml';

For example: $egChameleonLayoutFile= 'layouts/stickyhead.xml';

Option 2:

  1. Rename default layouts folder inside container to different name (like layout_default) Command docker exec -w /var/www/mediawiki/w/canasta-skins/chameleon CONTAINER_NAME mv layouts layouts_default

  2. Then, Chameleon can able to look for layout in different folder in bind mount folder. Setting the variable $egChameleonLayoutFile : #$egChameleonLayoutFile= __DIR__ . '/layouts/navhead.xml'; The folder PATH after DIR . is the relative path to LocalSettings.php in the bind mount config/LocalSettings.php file.

jeffw16 commented 2 months ago

Moving around files within the Docker container during runtime is not supported. As soon as you kill the Docker container, your changes are permanently erased. Running docker exec after starting up the container every single time is also not supported. I personally would not use either option 1 or 2. I have an alternative solution that is in the spirit of Canasta and will be supported:

To get around this limitation, utilize the extensions folder in your host OS to store this file. I would recommend going to the extensions/ folder in the host OS, creating an empty chameleon-customizations/ folder inside of that, then with a layouts/ folder inside of that.

Then, you can set: $wgChameleonLayoutFile = '/var/www/mediawiki/w/user-skins/chameleon-customizations/layouts/layout_file.xml';

Update: It must not be named chameleon, otherwise the Canasta-bundled Chameleon files would be overridden.

zuobot commented 2 months ago

@jeffw16 it works flawlessly. thank you. P/S: there're typo on "extensions/ folder in the host OS". Should be skins/ folder