View source
<?php
namespace Drupal\xbbcode_standard\Plugin\XBBCode;
use Drupal\Core\Render\Markup;
use Drupal\xbbcode\Parser\Tree\TagElementInterface;
use Drupal\xbbcode\Plugin\RenderTagPlugin;
use Drupal\xbbcode_standard\TreeEncodeTrait;
class TableTagPlugin extends RenderTagPlugin {
use TreeEncodeTrait;
public const ALIGNMENT = [
'~' => 'left',
'!' => 'center',
'#' => 'right',
];
public function buildElement(TagElementInterface $tag) : array {
$element['#type'] = 'table';
if ($caption = $tag
->getAttribute('caption')) {
$element['#caption'] = $caption;
}
$alignments = [];
if ($header = $tag
->getAttribute('header') ?: $tag
->getOption()) {
$headers = self::tabulateText($header)[0] ?: [
$header,
];
foreach ($headers as $i => $cell) {
if ($cell && array_key_exists($cell[0], self::ALIGNMENT)) {
$alignments[$i] = self::ALIGNMENT[$cell[0]];
$headers[$i] = substr($cell, 1);
}
else {
$headers[$i] = ltrim($cell);
$alignments[$i] = NULL;
}
}
if (implode('', $headers)) {
$element['#header'] = $headers;
}
}
foreach (static::tabulateTree($tag
->getChildren()) as $i => $row) {
foreach ($row as $j => $cell) {
$content = $cell
->getContent();
if (!isset($alignments[$j])) {
$alignments[$j] = '';
}
$align = $alignments[$j] ?: (is_numeric($content) ? 'right' : NULL);
$element["row-{$i}"][$j] = [
'#markup' => Markup::create($content),
'#wrapper_attributes' => $align ? [
'style' => [
'text-align:' . $align,
],
] : NULL,
];
}
}
return $element;
}
public function getDefaultSample() : string {
return $this
->t('[{{ name }} caption=Title header=!Item,Color,#Amount]
Fish,Red,1
Fish,Blue,2
[/{{ name }}]
[{{ name }}=~Left,Auto,!Center,#Right]
One,Two,Three,"Four, Five"
1,2,3,4
[/{{ name }}]
');
}
private static function tabulateTree(array $children) : array {
$table = [];
[
$token,
$text,
] = static::encodeTree($children);
foreach (self::tabulateText($text) as $i => $row) {
foreach ($row as $j => $cell) {
$table[$i][$j] = self::decodeTree($cell, $children, $token);
}
}
return $table;
}
private static function tabulateText($text) : array {
$trimmed = preg_replace('/<br\\s*\\/?>\\n/', "\n", $text);
$breaks = $trimmed !== $text;
$text = trim($trimmed);
preg_match_all("/\n (?:\n (?'quote'['\"]|"|&\\#039;)\n (?'quoted'\n (?:\\\\.|(?!\\\\|\\k'quote')[^\\\\])*\n )\n \\k'quote'\n |\n (?'unquoted'\n (?:\\\\.|[^\\\\,\\v])*\n )\n )\n (?'delimiter',|\\v+|\$)\n /x", $text, $match, PREG_SET_ORDER);
array_pop($match);
$rows = [];
$row = [];
foreach ((array) $match as $token) {
$value = stripslashes($token['quoted'] ?: $token['unquoted']);
if ($breaks) {
$value = nl2br($value);
}
$row[] = $value;
if ($token['delimiter'] !== ',') {
$rows[] = $row;
$row = [];
}
}
return $rows;
}
}