Skip to content

[5.x] Attribute Modifier #9796

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

Merged
merged 14 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
42 changes: 42 additions & 0 deletions src/Modifiers/CoreModifiers.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,48 @@ public function at($value, $params)
return Stringy::at($value, Arr::get($params, 0));
}

/**
* Returns an attribute ($params[0]) with its value when the given $value variable is not empty.
*
* @param string $value
* @param array $params
* @return string
*/
public function attribute($value, $params)
{
if (! $name = Arr::get($params, 0)) {
throw new \Exception('Attribute name is required.');
}

if ($value instanceof Collection) {
$value = $value->all();
}

if (\is_array($value)) {
if (empty($value)) {
return '';
}

$value = \json_encode($value);
}

if (\is_bool($value)) {
return $value ? ' '.$name : '';
}

if (\is_object($value)) {
$value = (string) $value;
}

$value = trim($value);

if ($value === '') {
return '';
}

return sprintf(' %s="%s"', $name, Html::entities($value));
}

/**
* Returns a focal point as a background-position CSS value.
*
Expand Down
74 changes: 74 additions & 0 deletions tests/Modifiers/AttributeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace Tests\Modifiers;

use Statamic\Modifiers\Modify;
use Tests\TestCase;

class AttributeTest extends TestCase
{
/**
* @test
*
* @dataProvider attributeProvider
*/
public function it_converts_to_attribute($value, $expected)
{
$this->assertEquals($expected, $this->modify($value, 'foo'));
}

public static function attributeProvider()
{
return [
'string' => ['bar baz', ' foo="bar baz"'],
'entities' => ['{<!&>}', ' foo="{&lt;!&amp;&gt;}"'],
'integer' => [1, ' foo="1"'],
'integer > 1' => [2, ' foo="2"'],
'negative integer' => [-1, ' foo="-1"'],
'float' => [1.5, ' foo="1.5"'],
'empty string' => ['', ''],
'true' => [true, ' foo'],
'false' => [false, ''],
'array' => [['one' => ['two' => 'three']], ' foo="{&quot;one&quot;:{&quot;two&quot;:&quot;three&quot;}}"'],
'empty array' => [[], ''],
'collection' => [collect(['one' => 'two']), ' foo="{&quot;one&quot;:&quot;two&quot;}"'],
'empty collection' => [collect(), ''],
'object with __toString' => [new AttributeTestStringable, ' foo="Test"'],
];
}

/** @test */
public function it_throws_exception_without_argument()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Attribute name is required.');

$this->modify('value', null);
}

/** @test */
public function it_throws_exception_when_value_is_an_object_without_toString_method()
{
$this->expectException(\Error::class);
$this->expectExceptionMessage('Object of class Tests\Modifiers\AttributeTestNotStringable could not be converted to string');

$this->modify(new AttributeTestNotStringable, 'foo');
}

private function modify($value, $attribute)
{
return Modify::value($value)->attribute($attribute)->fetch();
}
}

class AttributeTestStringable
{
public function __toString()
{
return 'Test';
}
}

class AttributeTestNotStringable
{
}
Loading