Skip to content

Commit

Permalink
AttributeBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
19Gerhard85 committed Jan 29, 2025
1 parent 92e2a5e commit 5bd58dd
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 162 deletions.
155 changes: 155 additions & 0 deletions src/StimulusBundle/src/Builder/StimulusAttributeBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php

namespace Symfony\UX\StimulusBundle\Builder;

use Symfony\UX\StimulusBundle\Helper\StimulusSyntaxHelper;

class StimulusAttributeBuilder
{
private string $controllerName;
private array $actions = [];
private array $values = [];
private array $classes = [];
private array $targets = [];
private array $outlets = [];
private array $attributes = [];

public static function controller(string $controllerName): self
{
$builder = new self();
$builder->controllerName = $controllerName;

return $builder;
}

public function action(string $actionName, ?string $eventName = null, array $parameters = []): self
{
$this->actions[] = [
'actionName' => $actionName,
'eventName' => $eventName,
'parameters' => $parameters,
];

return $this;
}

public function value(string $key, mixed $value): self
{
$this->values[$key] = $value;

return $this;
}

public function class(string $key, mixed $value): self
{
$this->classes[$key] = $value;

return $this;
}

public function target(string $key, mixed $value): self
{
$this->targets[$key] = $value;

return $this;
}

public function outlet(string $identifier, string $outlet, mixed $selector): self
{
$this->outlets[] = [
'identifier' => $identifier,
'outlet' => $outlet,
'selector' => $selector,
];

return $this;
}

public function build(): array
{
$syntaxHelper = new StimulusSyntaxHelper();
$controllerName = $syntaxHelper->normalizeControllerName($this->controllerName);

$this->attributes['data-controller'] = $controllerName;

//Actions
$this->attributes = array_merge(
$this->attributes,
...
array_map(function (array $actionData) use ($controllerName): array {
$actionName = htmlspecialchars($actionData['actionName']);
$eventName = $actionData['eventName'];

$action = sprintf('%s#%s', $controllerName, $actionName);
if (null !== $eventName) {
$action = sprintf('%s->%s', htmlspecialchars($eventName), $action);
}

return ['data-action' => $action];
}, $this->actions)
);

//Action Parameters
$this->attributes = array_merge(
$this->attributes,
...
array_map(
function (array $actionData) use ($controllerName, $syntaxHelper): array {
$parameters = [];

foreach ($actionData['parameters'] as $name => $value) {
$key = $syntaxHelper->normalizeKeyName($name);
$value = $syntaxHelper->getFormattedValue($value);

$parameters[sprintf(
'data-%s-%s-param',
$controllerName,
$key
)] = htmlspecialchars($value);
}

return $parameters;
},
$this->actions
)
);

//Values
foreach ($this->values as $key => $value) {
if (null === $value) {
continue;
}

$key = $syntaxHelper->normalizeKeyName($key);
$value = $syntaxHelper->getFormattedValue($value);

$this->attributes[sprintf('data-%s-%s-value', $controllerName, $key)] = $value;
}

//Classes
foreach ($this->classes as $key => $class) {
$key = $syntaxHelper->normalizeKeyName($key);

$this->attributes[sprintf('data-%s-%s-class', $controllerName, $key)] = $class;
}

//Outlets
foreach ($this->outlets as $outletItem) {
$identifier = $syntaxHelper->normalizeControllerName($outletItem['identifier']);
$outlet = $syntaxHelper->normalizeKeyName($outletItem['outlet']);

$this->attributes[sprintf('data-%s-%s-outlet', $identifier, $outlet)] = htmlspecialchars(
$outletItem['selector']
);
}

//Targets
foreach ($this->targets as $key => $target) {
$key = $syntaxHelper->normalizeKeyName($key);

$this->attributes[sprintf('data-%s-target', $key)] = htmlspecialchars($target);
}

return $this->attributes;
}
}
162 changes: 0 additions & 162 deletions src/StimulusBundle/src/Form/Extension/FormTypeExtension.php

This file was deleted.

40 changes: 40 additions & 0 deletions src/StimulusBundle/src/Helper/StimulusSyntaxHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Symfony\UX\StimulusBundle\Helper;

use Stringable;

use function is_bool;
use function is_callable;
use function is_object;
use function is_scalar;

class StimulusSyntaxHelper
{
public function normalizeControllerName(string $controllerName): string
{
return preg_replace('/^@/', '', str_replace('_', '-', str_replace('/', '--', $controllerName)));
}

public function normalizeKeyName(string $str): string
{
// Adapted from ByteString::camel
$str = ucfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $str))));

// Adapted from ByteString::snake
return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1-\2', $str));
}

public function getFormattedValue(mixed $value): string
{
if ($value instanceof Stringable || (is_object($value) && is_callable([$value, '__toString']))) {
$value = (string)$value;
} elseif (!is_scalar($value)) {
$value = json_encode($value);
} elseif (is_bool($value)) {
$value = $value ? 'true' : 'false';
}

return (string)$value;
}
}

0 comments on commit 5bd58dd

Please sign in to comment.