Как сделать, чтобы функция обрабатывалась рекурсивно?

Рейтинг: 1Ответов: 1Опубликовано: 14.08.2023

Как сделать, чтобы функция обрабатывалась рекурсивно для шорткодов любой вложенности?

  1. [random]{Вариант1|Вариант2}[/random]
  2. {Вариант1|[random]Вариант2|Вариант2[/random]}

Сейчас возникает проблема, когда пытаюсь использовать [random][/random] внутри {}

function generateSpinText($template) {

    $processCurlyBraces = function($matches) use (&$processCurlyBraces, &$processRandomBraces) {
        $options = explode('|', $matches[1]);
        // Обработка вложенных скобок
        foreach ($options as &$option) {
            if (preg_match('/\[random/', $option)) {
                $option = preg_replace_callback('/\[random(\d*)\]([^\[]*?)\[\/random\]/s', $processRandomBraces, $option);
            }
            $option = preg_replace_callback('/\{([^{}]+)\}/', $processCurlyBraces, $option);
        }
        return $options[array_rand($options)];
    };

    $processRandomBraces = function($matches) use (&$processCurlyBraces, &$processRandomBraces) {
        $content = $matches[2];
        $options = explode('|', $content);

        // Обработка вложенных скобок
        foreach ($options as &$option) {
            if (preg_match('/\{/', $option)) {
                $option = preg_replace_callback('/\{([^{}]+)\}/', $processCurlyBraces, $option);
            }
            $option = preg_replace_callback('/\[random(\d*)\]([^\[]*?)\[\/random\]/s', $processRandomBraces, $option);
        }

        $count = isset($matches[1]) && $matches[1] !== '' ? intval($matches[1]) : count($options);
        shuffle($options);
        $selectedOptions = array_slice($options, 0, $count);
        return implode('', $selectedOptions);
    };

    // обработка {}
    while (preg_match('/\{([^{}]+)\}/', $template)) {
        $template = preg_replace_callback('/\{([^{}]+)\}/', $processCurlyBraces, $template);
    }

    // обработка [random][/random]
    while (preg_match('/\[random(\d*)\]([^\[]*?)\[\/random\]/s', $template)) {
        $template = preg_replace_callback('/\[random(\d*)\]([^\[]*?)\[\/random\]/s', $processRandomBraces, $template);
    }

    return $template;
}

Ответы

▲ 0
function generateSpinText($template) {

  do {
    $replaced = false;

    // Обработка шорткода {}
    $template = preg_replace_callback('/\{([^{}]+)\}/', function($matches) use( & $replaced) {
      $replaced = true;
      $content = $matches[1];

      // Если содержимое {} является другим шорткодом, обрабатываем его сначала
      if (preg_match('/\[random/', $content)) {
        $content = self::generateSpinText($content);
      }

      $options = explode('|', $content);
      return $options[array_rand($options)];
    }, $template);

    // Обработка шорткода [randomX]
    $template = preg_replace_callback('/\[random(\d*)\]([^\[]*?)\[\/random\]/', function($matches) use( & $replaced) {
      $replaced = true;
      $options = explode('|', $matches[2]);
      $count = isset($matches[1]) && $matches[1] !== '' ? intval($matches[1]) : count($options);
      shuffle($options);
      $selectedOptions = array_slice($options, 0, $count);
      return implode('', $selectedOptions);
    }, $template);

  } while ($replaced);

  return $template;
}