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;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc