55 lines
1.5 KiB
PHP
55 lines
1.5 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Core\Services;
|
|
|
|
class Shortcodes
|
|
{
|
|
/** @var array<string, callable> */
|
|
private static array $handlers = [];
|
|
|
|
public static function register(string $name, callable $handler): void
|
|
{
|
|
$key = strtolower(trim($name));
|
|
if ($key === '') {
|
|
return;
|
|
}
|
|
self::$handlers[$key] = $handler;
|
|
}
|
|
|
|
public static function render(string $content, array $context = []): string
|
|
{
|
|
if ($content === '' || !self::$handlers) {
|
|
return $content;
|
|
}
|
|
|
|
return preg_replace_callback('/\[([a-zA-Z0-9_-]+)([^\]]*)\]/', function (array $m) use ($context): string {
|
|
$tag = strtolower((string)($m[1] ?? ''));
|
|
if (!isset(self::$handlers[$tag])) {
|
|
return (string)$m[0];
|
|
}
|
|
$attrs = self::parseAttrs((string)($m[2] ?? ''));
|
|
try {
|
|
$out = (self::$handlers[$tag])($attrs, $context);
|
|
return is_string($out) ? $out : '';
|
|
} catch (\Throwable $e) {
|
|
return '';
|
|
}
|
|
}, $content) ?? $content;
|
|
}
|
|
|
|
private static function parseAttrs(string $raw): array
|
|
{
|
|
$attrs = [];
|
|
if ($raw === '') {
|
|
return $attrs;
|
|
}
|
|
if (preg_match_all('/([a-zA-Z0-9_-]+)\s*=\s*"([^"]*)"/', $raw, $matches, PREG_SET_ORDER)) {
|
|
foreach ($matches as $match) {
|
|
$attrs[strtolower((string)$match[1])] = (string)$match[2];
|
|
}
|
|
}
|
|
return $attrs;
|
|
}
|
|
}
|