migrate_spip-1.0.0/src/Plugin/SpipRichText/Lists.php
src/Plugin/SpipRichText/Lists.php
<?php
declare(strict_types=1);
namespace Drupal\migrate_spip\Plugin\SpipRichText;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\migrate_spip\Attribute\SpipRichText;
use Drupal\migrate_spip\SpipRichTextBase;
/**
* Manage SPIP lists.
*/
#[SpipRichText(
id: 'lists',
label: new TranslatableMarkup('List'),
weight: -20,
)]
final class Lists extends SpipRichTextBase {
/**
* {@inheritdoc}
*/
public function apply(string $text): string {
if (preg_match("/\n-[*#]/S", $text) !== 1) {
return $text;
}
$elements = explode("\n\n", $text);
foreach ($elements as $element) {
// If element starts with a html tag block, extract it.
if (preg_match('#^</?(?:' . self::HTML_TAGS_BLOCK . '[^>]*?)>#s', $element, $matches)) {
$element = mb_substr($element, mb_strlen($matches[0]));
}
// If element finishes with a html tag block, extract it.
if (preg_match('#<(?:(' . self::HTML_TAGS_BLOCK . ')[^>]*?)>(.*?)</\1>$#', $element, $matches)) {
$element = mb_substr($element, 0, -mb_strlen($matches[0]));
}
// If element finishes with an ending html tag block, extract it.
elseif (preg_match('#</(?:' . self::HTML_TAGS_BLOCK . ')>$#', $element, $matches)) {
$element = mb_substr($element, 0, -mb_strlen($matches[0]));
}
$replace = $this->applyList("\n" . $element);
if ($replace) {
$text = str_replace($element, $replace, $text);
}
}
return $text;
}
/**
* Apply list element.
*
* @param string $text
* The part of text to process.
*
* @return string|null
* The part of text processed.
*/
protected function applyList(string $text): ?string {
if (
str_contains($text, '-') === FALSE ||
preg_match("/-[*#]/S", $text) !== 1
) {
return NULL;
}
$text = $this->applyListItem($text, 'init');
$text = preg_replace_callback(",(\n-)(\\*+|#+)([^*#].*)?(?=(?:\\z|\n-)),UsS", [static::class, 'applyListItem'], $text);
$text = $this->applyListItem($text, 'close');
return trim($text);
}
/**
* Apply list item element.
*
* @param mixed $t
* The string or the matched string to process.
* @param string $op
* The operation.
*
* @return string
* The process list item.
*
* @see https://github.com/spip/textwheel/blob/2.0/wheels/spip/spip-listes.php
* @see tw_liste_item()
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ElseExpression)
* @SuppressWarnings(PHPMD.IfStatementAssignment)
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings(PHPMD.ShortVariable)
*/
private function applyListItem(mixed $t, string $op = 'item'): string {
$nouv_type = NULL;
static $niveau;
static $pile_li;
static $pile_type;
static $type;
switch ($op) {
case 'init':
$niveau = 0;
$pile_li = [];
$pile_type = [];
$type = '';
break;
case 'close':
// Retour sur terre.
$ajout = '';
while ($niveau > 0) {
$ajout .= $pile_li[$niveau];
$ajout .= $pile_type[$niveau];
$niveau--;
}
$t .= $ajout;
break;
case 'ul':
case 'ol':
$nouv_type = $op;
break;
case 'item':
default:
$profond = 0;
if ($l = strlen($t[2])) {
$profond = $l;
$nouv_type = 'ul';
if (strncmp($t[2], '#', 1) == 0) {
$nouv_type = 'ol';
}
}
if ($profond > 0) {
$ajout = '';
// Changement de type de liste au meme niveau : il faut
// descendre un niveau plus bas, fermer ce niveau, et
// remonter.
$change_type = ($type && ($type <> $nouv_type) && ($profond == $niveau)) ? 1 : 0;
$type = $nouv_type;
// d'abord traiter les descentes.
while ($niveau > $profond - $change_type) {
$ajout .= $pile_li[$niveau];
$ajout .= $pile_type[$niveau];
if (!$change_type) {
unset($pile_li[$niveau]);
}
$niveau--;
}
// Puis les identites (y compris en fin de descente)
if ($niveau == $profond && !$change_type) {
$ajout .= $pile_li[$niveau];
}
// Puis les montees (y compris apres une descente un cran trop bas)
while ($niveau < $profond) {
if ($niveau == 0) {
$ajout .= "\n\n";
}
elseif (!isset($pile_li[$niveau])) {
$ajout .= '<li>';
$pile_li[$niveau] = '</li>';
}
$niveau++;
$ajout .= "<$type>";
$pile_type[$niveau] = "</$type>";
}
$ajout .= '<li>';
$pile_li[$profond] = '</li>';
}
else {
// Puce normale ou <hr>.
$ajout = $t[1];
}
$t = $ajout . $t[3];
break;
}
return $t;
}
}
