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

Internal: Add custom escaper for template renderer [ED-18015] #30189

Merged
merged 9 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{# TODO: Need to add base classes #}
<{{ settings.tag | e('html_tag') }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't it come sanitized from the props resolver?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have some validations, but as for today we validate it and also when printing sanitize it, just like full_url, this is the same. not sure about it, what do you think? I think if we are going to remove it, we also need to remove full_url

class="{{ settings.classes | join(' ') }}"
>
{% if settings.link.href %}
<a href="{{ settings.link.href | e('full_url') }}" target="{{ settings.link.target }}">
{{ settings.title }}
</a>
{% else %}
{{ settings.title }}
{% endif %}
</{{ settings.tag | e('html_tag') }}>
45 changes: 5 additions & 40 deletions modules/atomic-widgets/elements/atomic-heading/atomic-heading.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
use Elementor\Modules\AtomicWidgets\PropTypes\Size_Prop_Type;
use Elementor\Modules\AtomicWidgets\Styles\Style_Definition;
use Elementor\Modules\AtomicWidgets\Styles\Style_Variant;
use Elementor\Utils;
use Elementor\Modules\AtomicWidgets\TemplateRenderer\Has_Template;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Atomic_Heading extends Atomic_Widget_Base {
use Link_Query;
use Has_Template;

const BASE_STYLE_KEY = 'base';

Expand All @@ -37,46 +38,10 @@ public function get_icon() {
return 'eicon-t-letter';
}

protected function render() {
$settings = $this->get_atomic_settings();

$format = $this->get_heading_template( ! empty( $settings['link']['href'] ) );
$args = $this->get_template_args( $settings );

printf( $format, ...$args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}

private function get_heading_template( bool $is_link_enabled ): string {
return $is_link_enabled ? '<%1$s %2$s><a %3$s>%4$s</a></%1$s>' : '<%1$s %2$s>%3$s</%1$s>';
}

private function get_template_args( array $settings ): array {
$tag = $settings['tag'];
$title = esc_html( $settings['title'] );
$attrs = array_filter([
'class' => array_filter( [
$settings['classes'] ?? '',
static::get_base_style_class( self::BASE_STYLE_KEY ) ?? '',
] ),
]);

$default_args = [
Utils::validate_html_tag( $tag ),
Utils::render_html_attributes( $attrs ),
protected function get_templates(): array {
return [
'elementor/elements/atomic-heading' => __DIR__ . '/atomic-heading.html.twig',
];

if ( ! empty( $settings['link']['href'] ) ) {
$link_args = [
Utils::render_html_attributes( $settings['link'] ),
esc_html( $title ),
];

return array_merge( $default_args, $link_args );
}

$default_args[] = $title;

return $default_args;
}

protected function define_atomic_controls(): array {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{# TODO: Need to escape the image src #}
<img
class="{{ settings.classes }}"
class="{{ settings.classes | join(' ') }}"
{% for attr, value in settings.image %}
{{ attr | e('html_attr') }}="{{ value }}"
{% if attr == 'src' %}
src="{{ value | e('full_url') }}"
{% else %}
{{ attr | e('html_attr') }}="{{ value }}"
{% endif %}
{% endfor %}
>
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ private function get_template_args( array $settings ): array {
$tag = Utils::validate_html_tag( $settings['tag'] );
$attrs = array_filter([
'class' => array_filter([
$settings['classes'] ?? '',
...( $settings['classes'] ?? [] ),
self::get_base_style_class( self::BASE_STYLE_KEY ) ?? '',
]),
]);
Expand Down
2 changes: 1 addition & 1 deletion modules/atomic-widgets/elements/atomic-svg/atomic-svg.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected function render() {

$this->set_svg_attributes( $svg, $settings );

$svg->add_class( $settings['classes'] ?? '' );
$svg->add_class( implode( ' ', $settings['classes'] ?? [] ) );

$valid_svg = ( new Svg_Sanitizer() )->sanitize( $svg->get_updated_html() );

Expand Down
2 changes: 1 addition & 1 deletion modules/atomic-widgets/elements/div-block/div-block.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ protected function add_render_attributes() {
$this->add_render_attribute( '_wrapper', [
'class' => [
'e-div-block',
$settings['classes'] ?? '',
...( $settings['classes'] ?? [] ),
],
] );
}
Expand Down
3 changes: 2 additions & 1 deletion modules/atomic-widgets/module.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Elementor\Modules\AtomicWidgets\Elements\Atomic_Image\Atomic_Image;
use Elementor\Modules\AtomicWidgets\Elements\Atomic_Paragraph\Atomic_Paragraph;
use Elementor\Modules\AtomicWidgets\Elements\Atomic_Svg\Atomic_Svg;
use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Array_Transformer;
use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Combine_Array_Transformer;
use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Image_Src_Transformer;
use Elementor\Modules\AtomicWidgets\PropsResolver\Transformers\Settings\Image_Transformer;
Expand Down Expand Up @@ -141,7 +142,7 @@ private function register_settings_transformers( Transformers_Registry $transfor
$transformers->register( String_Prop_Type::get_key(), new Primitive_Transformer() );

// Other
$transformers->register( Classes_Prop_Type::get_key(), new Combine_Array_Transformer( ' ' ) );
$transformers->register( Classes_Prop_Type::get_key(), new Array_Transformer() );
$transformers->register( Image_Prop_Type::get_key(), new Image_Transformer() );
$transformers->register( Image_Src_Prop_Type::get_key(), new Image_Src_Transformer() );
$transformers->register( Image_Attachment_Id_Prop_Type::get_key(), new Primitive_Transformer() );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Elementor\Modules\AtomicWidgets\PropsResolver\Transformers;

use Elementor\Modules\AtomicWidgets\PropsResolver\Transformer_Base;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

class Array_Transformer extends Transformer_Base {
public function transform( $value, $key ) {
if ( ! is_array( $value ) ) {
return null;
}

return array_filter( $value );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function transform( $value, $key ): array {

$link_attrs = [
'href' => esc_url( $value['href'] ),
'target' => $value['isTargetBlank'] ? '_blank' : '',
'target' => $value['isTargetBlank'] ? '_blank' : '_self',
];

return array_filter( $link_attrs );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Elementor\Utils;
use ElementorDeps\Twig\Environment;
use ElementorDeps\Twig\TemplateWrapper;
use ElementorDeps\Twig\Runtime\EscaperRuntime;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
Expand All @@ -27,6 +27,11 @@ private function __construct() {
'autoescape' => 'name',
]
);

$escaper = $this->env->getRuntime( EscaperRuntime::class );

$escaper->setEscaper( 'full_url', 'esc_url' );
$escaper->setEscaper( 'html_tag', [ Utils::class, 'validate_html_tag' ] );
}

public static function instance(): self {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div>
<div class="">
<h1>This is my title</h1>
<p>This comes from part</p>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="{{ settings.classes }}">
<div class="{{ settings.classes | join (' ') }}">
<h1>{{ settings.title }}</h1>
<p>widget id: {{ id }}, widget type: {{ type }}</p>
{{ settings.prop_not_exists }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div>
<div class="{{ settings.classes | join (' ') }}">
<h1>{{ settings.title }}</h1>
{% include 'elementor/parts/part' %}
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function test_render__basic_template() {
'elementor/elements/test' => __DIR__ . '/mocks/basic.html.twig'
],
'settings' => [
'classes' => 'class1 class2',
'classes' => [ 'class1', 'class2' ],
'title' => 'This is my title',
],
] );
Expand All @@ -59,6 +59,7 @@ public function test_render__multiple_templates() {
],
'main' => 'elementor/elements/test',
'settings' => [
'classes' => null,
'title' => 'This is my title',
],
] );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,16 @@ public function get_atomic_settings_data_provider() {
'settings' => [
'classes' => [
'$$type' => 'classes',
'value' => [ 'one', 'two', 'three' ],
'value' => [ 'one', 'two', 'three', null ],
],
'outer_classes' => [
'$$type' => 'classes',
'value' => 111, // Invalid value for classes
],
],
'result' => [
'classes' => 'one two three',
'inner_classes' => '',
'classes' => [ 'one', 'two', 'three' ],
'inner_classes' => [],
'outer_classes' => null,
],
],
Expand Down