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

Replace mediawiki-core modification with extension code #14

Open
simontaurus opened this issue Nov 16, 2024 · 0 comments
Open

Replace mediawiki-core modification with extension code #14

simontaurus opened this issue Nov 16, 2024 · 0 comments

Comments

@simontaurus
Copy link
Collaborator

simontaurus commented Nov 16, 2024

These mediawiki core modifications https://github.com/OpenSemanticLab/mediawiki/commits/REL1_39-dev/?author=simontaurus were never merged and should be replaced by a hook in this extension.

Code that uses the onBeforePageDisplay hook to manipulate the generated html.

Select a div of class "mw-parser-output" that has at least one child of class "mw-slot-header". Create a associative array of slots with "main" as the first slot element. Interate over all childs of this div. The first elements go in the slot "main". If an element of class "mw-slot-header" is encountert a new slot with the text value of this element as name is created. All following elements go into this slot until another element of class "mw-slot-header" is found. Finally replace the content of the div with class "mw-parser-output" by wrapping the elements of each slot in a div with id "mw-slot-wrapper-<slot_name>" and class "mw-slot-wrapper".

ensure the order of slots while inserting: "header" (if present), "main", "footer" (if present), any other slot (if present)

$wgHooks['OutputPageParserOutput'][] = function ( $out, $parserOutput ) {
//$wgHooks['BeforePageDisplay'][] = function ( $out, $skin ) {
    // get the HTML from the parser output when using OutputPageParserOutput
    $html = $parserOutput->getText();
    // get the HTML from the output when using BeforePageDisplay
    //$html = $out->getHtml();

    // Note: this manipulation interactes with Skin:Citizen if wgCitizenEnableCollapsibleSections is true
    // The behavior of those section is correct but the elements are located in the wrong wrapper
    // which is not a major as long as those wrappers are not visible
    $wrap = true;

    // Use DOMDocument to parse the HTML
    $dom = new DOMDocument();
    @$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

    // Use XPath to find the target div
    $xpath = new DOMXPath($dom);
    $parserOutputDivs = $xpath->query('//div[contains(@class, "mw-parser-output")]');

    foreach ($parserOutputDivs as $div) {
        $slotHeaders = $xpath->query('.//*[contains(@class, "mw-slot-header")]', $div);

        if ($slotHeaders->length > 0) {
            $slots = ['main' => []];
            $currentSlot = 'main';

            // Iterate over all child nodes of the div
            foreach ($div->childNodes as $child) {
                if ($child->nodeType === XML_ELEMENT_NODE && $child->hasAttributes() && $child->getAttribute('class') === 'mw-slot-header') {
                    // Create a new slot with the text content of the mw-slot-header
                    $currentSlot = trim($child->textContent);
                    $slots[$currentSlot] = [];
                } else {
                    // Add the child to the current slot
                    $slots[$currentSlot][] = $child;
                }
            }

            // Create a new document fragment to hold the wrapped slots
            $newFragment = $dom->createDocumentFragment();

            // Define the order of slots
            $orderedSlots = ['header', 'main', 'footer'];

            // Append slots in the defined order
            foreach ($orderedSlots as $slotName) {
                if (isset($slots[$slotName])) {
                    if ($wrap) {
                        $wrapperDiv = $dom->createElement('div');
                        $wrapperDiv->setAttribute('id', 'mw-slot-wrapper-' . htmlspecialchars($slotName));
                        $wrapperDiv->setAttribute('class', 'mw-slot-wrapper');
                        // debug
                        //$wrapperDiv->setAttribute('style', 'border: 1px solid #aaa;');
                        //$wrapperDiv->appendChild($dom->createElement('p', '>' . htmlspecialchars($slotName)));

                        foreach ($slots[$slotName] as $element) {
                            $wrapperDiv->appendChild($element);
                        }

                        $newFragment->appendChild($wrapperDiv);
                    } else {
                        foreach ($slots[$slotName] as $element) {
                            $newFragment->appendChild($element);
                        }
                    }
                }
            }

            // Append any remaining slots that are not in the predefined order
            foreach ($slots as $slotName => $elements) {
                if (!in_array($slotName, $orderedSlots)) {

                    $details = $dom->createElement('details');
                    $details->setAttribute('class', 'mw-slot-details');
                    $summary = $dom->createElement('summary', htmlspecialchars($slotName));
                    $summary->setAttribute('class', 'mw-slot-details-summary');
                    $details->appendChild($summary);

                    if ($wrap) {
                        $wrapperDiv = $dom->createElement('div');
                        $wrapperDiv->setAttribute('id', 'mw-slot-wrapper-' . htmlspecialchars($slotName));
                        $wrapperDiv->setAttribute('class', 'mw-slot-wrapper');
                        // debug
                        //$wrapperDiv->setAttribute('style', 'border: 1px solid #aaa;');
                        //$wrapperDiv->appendChild($dom->createElement('p', '>' . htmlspecialchars($slotName)));

                        foreach ($elements as $element) {
                            $details->appendChild($element);
                        }
                        
                        $wrapperDiv->appendChild($details);
                        $newFragment->appendChild($wrapperDiv);
                    } else {
                        foreach ($elements as $element) {
                            $details->appendChild($element);
                        }
                        $newFragment->appendChild($details);
                    }
                }
            }

            // Replace the original content with the new wrapped content
            while ($div->firstChild) {
                $div->removeChild($div->firstChild);
            }
            $div->appendChild($newFragment);
        }
    }

    // Save the modified HTML back to the parser output when using OutputPageParserOutput
    $parserOutput->setText($dom->saveHTML());
    // when using BeforePageDisplay
    //$out->clearHtml();
    //$out->addHtml( $dom->saveHTML() );
    return true;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant