Skip to content
Open
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
7 changes: 7 additions & 0 deletions src/Attributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,13 @@ public function setPrefix($prefix)
return $this;
}

public function setCallback($name, $getter, $setter = null)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should settle on a single name, I already renamed this once for you ;-) We could also introduce different Setters for Read/Write Callbacks. Because with this signature, I'm unsure what would happen when running:

->setCallback('value', null, [$this, 'setValue'])->setCallback('value', [$this, 'getValue'])

I would expect my setter to be still in place. Do you have a good proposal for this?

And apart from this, I didn't grasp what inconsistency this is going to fix, this is just a proxy method, isn't it? Is it about naming?

{
$this->registerAttributeCallback($name, $getter, $setter);

return $this;
}

/**
* Register callback for an attribute
*
Expand Down
92 changes: 92 additions & 0 deletions tests/AttributesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

namespace ipl\Tests\Html;

use Exception;
use ipl\Html\Attribute;
use ipl\Html\Attributes;
use ipl\Tests\Html\TestDummy\ElementWithCallbackAttributes;
use RuntimeException;
use UnexpectedValueException;

class AttributesTest extends TestCase
{
Expand Down Expand Up @@ -38,4 +43,91 @@ public function testForeach()
next($attrs);
}
}

public function testGetterCallbackInGet()
{
$callback = function () {
return new Attribute('callback', 'value from callback');
};

$attributes = (new Attributes())
->setCallback('callback', $callback);

$this->assertSame($attributes->get('callback')->getValue(), 'value from callback');
}

public function testSetterCallbackInSet()
{
$element = new ElementWithCallbackAttributes();

$attributes = $element->getAttributes();

$attributes->set('name', 'name from test');

$this->assertSame('name from test', $attributes->get('name')->getValue());
$this->assertSame('name from test', $element->getName());
}

public function testSetterCallbackInAdd()
{
$element = new ElementWithCallbackAttributes();

$attributes = $element->getAttributes();

$attributes->add('name', 'name from test');

$this->assertSame('name from test', $attributes->get('name')->getValue());
$this->assertSame('name from test', $element->getName());
}

public function testSetterCallbackIsProxied()
{
$element = new ElementWithCallbackAttributes();

$attributes = $element->getAttributes();

$attributes->get('name')->setValue('name from test');

$this->assertSame('name from test', $attributes->get('name')->getValue());
$this->assertSame('name from test', $element->getName());
}

public function testCantOverrideCallbacks()
{
$callback = function () {
return new Attribute('callback', 'value from callback');
};

$attributes = (new Attributes())
->setCallback('callback', $callback);

$this->expectException(RuntimeException::class);
$attributes->set('callback', 'overridden');
}

public function testGetterCallbackRuntimeException()
{
$callback = function () {
throw new Exception();
};

$attributes = (new Attributes())
->setCallback('callback', $callback);

$this->expectException(RuntimeException::class);
$attributes->get('callback');
}

public function testGetterCallbackValueException()
{
$callback = function () {
return [];
};

$attributes = (new Attributes())
->setCallback('callback', $callback);

$this->expectException(UnexpectedValueException::class);
$attributes->get('callback');
}
}
32 changes: 32 additions & 0 deletions tests/TestDummy/ElementWithCallbackAttributes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace ipl\Tests\Html\TestDummy;

use ipl\Html\BaseHtmlElement;

class ElementWithCallbackAttributes extends BaseHtmlElement
{
protected $name;

public function __construct()
{
$this->registerCallbacks();
}

public function getName()
{
return $this->name;
}

public function setName($name)
{
$this->name = $name;

return $this;
}

protected function registerCallbacks()
{
$this->getAttributes()->setCallback('name', [$this, 'getName'], [$this, 'setName']);
}
}