Skip to content
Snippets Groups Projects
Commit 4d500c50 authored by Cristina Chumillas's avatar Cristina Chumillas
Browse files

Issue #3301853 by matthieuscarset, mherchel, lauriii, pdureau, dww, Chi,...

Issue #3301853 by matthieuscarset, mherchel, lauriii, pdureau, dww, Chi, smustgrave: Create twig filters: |add_class and |set_attribute
parent 706b0006
No related branches found
No related tags found
25 merge requests!54479.5.x SF update,!5014Issue #3071143: Table Render Array Example Is Incorrect,!4868Issue #1428520: Improve menu parent link selection,!4289Issue #1344552 by marcingy, Niklas Fiekas, Ravi.J, aleevas, Eduardo Morales...,!4114Issue #2707291: Disable body-level scrolling when a dialog is open as a modal,!4100Issue #3249600: Add support for PHP 8.1 Enums as allowed values for list_* data types,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2334Issue #3228209: Add hasRole() method to AccountInterface,!2062Issue #3246454: Add weekly granularity to views date sort,!1591Issue #3199697: Add JSON:API Translation experimental module,!1484Exposed filters get values from URL when Ajax is on,!1255Issue #3238922: Refactor (if feasible) uses of the jQuery serialize function to use vanillaJS,!1105Issue #3025039: New non translatable field on translatable content throws error,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!925Issue #2339235: Remove taxonomy hard dependency on node module,!877Issue #2708101: Default value for link text is not saved,!872Draft: Issue #3221319: Race condition when creating menu links and editing content deletes menu links,!844Resolve #3036010 "Updaters",!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493,!485Sets the autocomplete attribute for username/password input field on login form.,!30Issue #3182188: Updates composer usage to point at ./vendor/bin/composer
......@@ -140,6 +140,8 @@ public function getFilters() {
// CSS class and ID filters.
new TwigFilter('clean_class', '\Drupal\Component\Utility\Html::getClass'),
new TwigFilter('clean_id', '\Drupal\Component\Utility\Html::getId'),
new TwigFilter('add_class', [$this, 'addClass']),
new TwigFilter('set_attribute', [$this, 'setAttribute']),
// This filter will render a renderable array to use the string results.
new TwigFilter('render', [$this, 'renderVar']),
new TwigFilter('format_date', [$this->dateFormatter, 'format']),
......@@ -706,4 +708,56 @@ public function suggestThemeHook(?array $element, string|\Stringable $suggestion
return $element;
}
/**
* Adds a value into the class attributes of a given element.
*
* Assumes element is an array.
*
* @param array $element
* A render element.
* @param string[]|string ...$classes
* The class(es) to add to the element. Arguments can include string keys
* directly, or arrays of string keys.
*
* @return array
* The element with the given class(es) in attributes.
*/
public function addClass(array $element, ...$classes): array {
$attributes = new Attribute($element['#attributes'] ?? []);
$attributes->addClass(...$classes);
$element['#attributes'] = $attributes->toArray();
// Make sure element gets rendered again.
unset($element['#printed']);
return $element;
}
/**
* Sets an attribute on a given element.
*
* Assumes the element is an array.
*
* @param array $element
* A render element.
* @param string $name
* The attribute name.
* @param mixed $value
* (optional) The attribute value.
*
* @return array
* The element with the given sanitized attribute's value.
*/
public function setAttribute(array $element, string $name, mixed $value = NULL): array {
$element['#attributes'] = AttributeHelper::mergeCollections(
$element['#attributes'] ?? [],
new Attribute([$name => $value])
);
// Make sure element gets rendered again.
unset($element['#printed']);
return $element;
}
}
......@@ -4,8 +4,10 @@
// cspell:ignore mila
use Drupal\Component\Serialization\Json;
use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\Core\GeneratedLink;
use Drupal\Core\Render\Markup;
use Drupal\Core\Render\RenderableInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Template\Loader\StringLoader;
......@@ -438,7 +440,7 @@ public function testTwigAddSuggestionFilter($original_render_array, $suggestion,
}
/**
* A data provider for ::testTwigAddSuggestionFilter().
* Provides data for ::testTwigAddSuggestionFilter().
*
* @return \Iterator
*/
......@@ -542,6 +544,130 @@ public function providerTestTwigAddSuggestionFilter(): \Iterator {
];
}
/**
* Tests Twig 'add_class' filter.
*
* @covers ::addClass
* @dataProvider providerTestTwigAddClass
*/
public function testTwigAddClass($element, $classes, $expected_result) {
$processed = $this->systemUnderTest->addClass($element, $classes);
$this->assertEquals($expected_result, $processed);
}
/**
* Provides data for ::testTwigAddClass().
*
* @return \Iterator
*/
public function providerTestTwigAddClass(): \Iterator {
yield 'should add a class on element' => [
['#type' => 'container'],
'my-class',
['#type' => 'container', '#attributes' => ['class' => ['my-class']]],
];
yield 'should add a class from a array of string keys on element' => [
['#type' => 'container'],
['my-class'],
['#type' => 'container', '#attributes' => ['class' => ['my-class']]],
];
yield 'should add a class from a Markup value' => [
['#type' => 'container'],
[Markup::create('my-class')],
['#type' => 'container', '#attributes' => ['class' => ['my-class']]],
];
yield '#printed should be removed after class(es) added' => [
[
'#markup' => 'This content is already is rendered',
'#printed' => TRUE,
],
'',
[
'#markup' => 'This content is already is rendered',
'#attributes' => [
'class' => [''],
],
],
];
}
/**
* Tests Twig 'set_attribute' filter.
*
* @covers ::setAttribute
* @dataProvider providerTestTwigSetAttribute
*/
public function testTwigSetAttribute($element, $key, $value, $expected_result) {
$processed = $this->systemUnderTest->setAttribute($element, $key, $value);
$this->assertEquals($expected_result, $processed);
}
/**
* A data provider for ::testTwigSetAttribute().
*
* @return \Iterator
*/
public function providerTestTwigSetAttribute(): \Iterator {
yield 'should add attributes on element' => [
['#theme' => 'image'],
'title',
'Aloha',
[
'#theme' => 'image',
'#attributes' => [
'title' => 'Aloha',
],
],
];
yield 'should merge existing attributes on element' => [
[
'#theme' => 'image',
'#attributes' => [
'title' => 'Aloha',
],
],
'title',
'Bonjour',
[
'#theme' => 'image',
'#attributes' => [
'title' => 'Bonjour',
],
],
];
yield 'should add JSON attribute value correctly on element' => [
['#type' => 'container'],
'data-slider',
Json::encode(['autoplay' => TRUE]),
[
'#type' => 'container',
'#attributes' => [
'data-slider' => '{"autoplay":true}',
],
],
];
yield '#printed should be removed after setting attribute' => [
[
'#markup' => 'This content is already is rendered',
'#printed' => TRUE,
],
'title',
NULL,
[
'#markup' => 'This content is already is rendered',
'#attributes' => [
'title' => NULL,
],
],
];
}
}
class TwigExtensionTestString {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment