RRZE-Webteam / rrze-elements-blocks

Sammlung von Gestaltungselementen für WordPress-Websites für den BlockEditor
GNU General Public License v3.0
2 stars 0 forks source link

Kses filtert Blockparameter heraus und sorgt dafür, dass normale Administratoren keine Blöcke setzen können #85

Closed lukasniebler closed 3 months ago

lukasniebler commented 4 months ago

Problem

Auf Multisite-Instanzen werden Inhalte von normalen Nutzern automatisch durch wp_kses gefiltert. Wenn ein Block nun HTML-Tags oder CSS-Styling besitzt, welches durch kses nicht erlaubt ist, sorgt es dafür, dass nach Veröffentlichung des Beitrags der Block im Frontend falsch dargestellt und beim erneuten Laden der Seite im Blockeditor invalidiert wird.

Hintergrund

Kses filtert standardmäßig einige HTML-Tags und Attribute aus den Blöcken heraus und sorgt dafür, dass diese invalidiert werden. Das Problem: Falls man Kses lockert, trifft das im schlechtesten Fall auf alle Anwendungsfälle von Userinput zu oder z.B. auf den gesamten Post.

Es muss also eine Lösung gefunden werden, damit nur die spezifischen Blöcke die notwendigen Tags setzen können, ohne dass User-Input weitere Tags setzt.

Alle Inline-Styles sollten in der finalen Version durch Klassen ersetzt werden, auch in den SVG-Files selbst. Die Liste der notwendigen Anpassungen sollte verkleinert werden.

Viele HTML-Tags und Attribute stammen noch vom klassischen Elements. Deshalb ggf. prüfen, inwiefern diese für den finalen Output benötigt werden.

Im Gutenberg-Plugin

function gutenberg_kses_allowed_html( $allowedtags ) {
    if ( ! gutenberg_is_experiment_enabled( 'gutenberg-form-blocks' ) ) {
        return $allowedtags;
    }

    $allowedtags['input'] = array(
        'type'          => array(),
        'name'          => array(),
        'value'         => array(),
        'checked'       => array(),
        'required'      => array(),
        'aria-required' => array(),
        'class'         => array(),
    );

    $allowedtags['label'] = array(
        'for'   => array(),
        'class' => array(),
    );

    $allowedtags['textarea'] = array(
        'name'          => array(),
        'required'      => array(),
        'aria-required' => array(),
        'class'         => array(),
    );
    return $allowedtags;
}
add_filter( 'wp_kses_allowed_html', 'gutenberg_kses_allowed_html', 10, 2 );

Unfertige Lösung bis jetzt

    /**
     * [__construct description]
     * @param string $pluginFile [description]
     */
    public function __construct($pluginFile)
    {
        $this->pluginFile = $pluginFile;
        add_action('wp_enqueue_scripts', [$this, 'enqueueScripts']);
        add_filter('wp_kses_allowed_html', [$this, 'extendKsesAllowedHtml'], 10, 1);
        add_filter('safe_style_css', [$this, 'extendAllowedCssStyles'], 10, 1);
    }

    function __destruct()
    {
        //add_filter('the_content', 'wpautop');
    }

    /**
     * Extends allowed HTML tags and attributes based on plugin needs.
     *
     * @param array $allowedtags Existing allowed tags configuration.
     * @return array Modified allowed tags configuration.
     */
    public function extendKsesAllowedHtml($allowedtags)
    {
        // Custom tags and attributes
        $custom_tags = [
            'div' => [
                'class' => true,
                'id' => true,
                'style' => true,
            ],
            'span' => [
                'class' => true,
                'style' => true,
                'tabindex' => true,
            ],
            'a' => [
                'href' => true,
                'title' => true,
                'class' => true,
                'style' => true,
            ],
            'button' => [
                'type' => true,
                'class' => true,
                'aria-controls' => true,
                'aria-expanded' => true,
                'aria-selected' => true,
                'tabindex' => true,
                'style' => true,
            ],
            'svg' => [
                'xmlns' => true,
                'fill' => true,
                'viewbox' => true,
                'role' => true,
                'aria-hidden' => true,
                'focusable' => true,
                'preserveaspectratio' => true,
                'style' => true,
                'class' => true,
                'alt' => true,
                'width' => true,
                'height' => true,
                'font-size' => true,
            ],
            'path' => [
                'd' => true,
                'fill' => true,
                'fill-rule' => true,
                'clip-rule' => true,
            ],
        ];

        // Merge with existing tags
        foreach ($custom_tags as $tag => $attributes) {
            if (isset($allowedtags[$tag])) {
                // Merge attributes if tag is already set
                $allowedtags[$tag] = array_merge($allowedtags[$tag], $attributes);
            } else {
                // Set new tag and attributes
                $allowedtags[$tag] = $attributes;
            }
        }

        return $allowedtags;
    }

    public function extendAllowedCssStyles($styles)
    {
        $custom_styles = ['display', 'fill', 'margin', 'padding', 'color', 'background-color', 'font-size'];
        return array_merge($styles, $custom_styles);
    }

ToDo