<commit_before><?php

class HtmlBBcodeUtils
{

	public static $br_implicit, $br_explicit;

	public static $zeilen_counter = 0;

	public static $zeilenlaenge;

	/**
	 * @param int $init
	 */
	public static function initZeilenCounter($init = 1)
	{
		self::$zeilen_counter = $init;
	}

	/**
	 * @param string $text
	 * @return string
	 */
	static function bbcode_normalize($text)
	{
		$text = preg_replace("/\[(\/?)list([^\]]*)\]/siu", "[\\1LIST\\2]", $text);
		$text = preg_replace("/\[(\/?)quote\]/siu", "[\\1QUOTE]", $text);
		$text = preg_replace("/\[(\/?)b\]/siu", "[\\1B]", $text);
		$text = preg_replace("/\[(\/?)i\]/siu", "[\\1I]", $text);
		$text = preg_replace("/\[(\/?)u\]/siu", "[\\1U]", $text);
		$text = preg_replace("/\[(\/?)url([^\]]*)\]/siu", "[\\1URL\\2]", $text);
		$text = preg_replace("/\[p\](.*)\[\/p\]/siuU", "\\1", $text);

		$text = str_replace(chr(194).chr(160), " ", $text);
		$text = preg_replace("/ {2,}/", " ", $text);

		$x = explode("\n", $text);
		foreach ($x as $i=>$zeile) {
			$x[$i] = trim($zeile);
		}
		return implode("\n", $x);
	}

	/**
	 * @static
	 * @param string $text
	 * @param int $zeilenlaenge
	 * @return array|string[]
	 */
	static function bbcode2zeilen_absaetze($text, $zeilenlaenge)
	{
		HtmlBBcodeUtils::$zeilenlaenge = $zeilenlaenge;
		$text = str_replace("\r", "", $text);
		$text = preg_replace("/\[list(.*)\[\/list\]/siU", "\n\n[LIST\\1[/LIST]\n\n", $text);
		$text = preg_replace("/\[quote(.*)\[\/quote\]/siU", "\n\n[QUOTE\\1[/QUOTE]\n\n", $text);
		$text = preg_replace("/\\n( *\\n)+/", "\n\n", $text);

		$text   = preg_replace("/[\\n ]+\[\*\]/siU", "\n[*]", $text);
		$text   = trim($text, " \n");
		$x      = explode("\n\n", $text);
		$return = array();

		foreach ($x as $y) {
			if (mb_stripos($y, "[list") === 0 || mb_stripos($y, "[ulist") === 0 || mb_stripos($y, "[quote") === 0) {
				$str_neu = preg_replace_callback("/(\[quote[^\]]*\])(.*)(\[\/quote\])/siU", function ($matches) {
					$out = $matches[1];

					$zeils     = explode("\n", $matches[2]);
					$zeils_neu = array();
					foreach ($zeils as $zeile) {
						$x           = HtmlBBcodeUtils::text2zeilen($zeile, HtmlBBcodeUtils::$zeilenlaenge - 10);
						$zeils_neu[] = "###ZEILENNUMMER###" . implode("\n###ZEILENNUMMER###", $x);
					}
					$out .= implode("\n", $zeils_neu);
					$out .= $matches[3];

					return $out;
				}, $y);

				$str_neu = preg_replace_callback("/(\[list[^\]]*\])(.*)(\[\/list\])/siuU", function ($matches) {
					$out = $matches[1];
					$x = explode("[*]", $matches[2]);

					if (count($x) > 1) for ($i = 1; $i < count($x); $i++) if (trim($x[$i]) != "") {
						$zeils = explode("\n", trim($x[$i]));
						$zeils_neu = array();
						foreach ($zeils as $zeile) {
							$z           = HtmlBBcodeUtils::text2zeilen($zeile, HtmlBBcodeUtils::$zeilenlaenge - 10);
							$zeils_neu[] = "###ZEILENNUMMER###" . implode("\n###ZEILENNUMMER###", $z);
						}
						$out .= "[*]" . implode("[*]", $zeils_neu);
					}
					$out .= $matches[3];

					return $out;
				}, $str_neu);

			} else {
				$zeils     = explode("\n", $y);
				$zeils_neu = array();
				foreach ($zeils as $zeile) {
					$x           = HtmlBBcodeUtils::text2zeilen($zeile, HtmlBBcodeUtils::$zeilenlaenge);
					$zeils_neu[] = "###ZEILENNUMMER###" . implode("\n###ZEILENNUMMER###", $x);
				}

				$str_neu = implode("\n", $zeils_neu);
			}

			$str_neu = preg_replace_callback("/###ZEILENNUMMER###/", function () {
				return "#ZEILE#";
			}, $str_neu);

			$str_neu = preg_replace("/([^\\n])#ZEILE#/siu", "\\1\n#ZEILE#", $str_neu);

			$return[] = $str_neu;
		}

		return $return;
	}

	/**
	 * @param string $text
	 * @param int $zeilenlaenge
	 * @return array|int[]
	 */
	static function getBBCodeStats($text, $zeilenlaenge) {
		static::initZeilenCounter(1);
		$absaetze = static::bbcode2html_absaetze($text, false, $zeilenlaenge);
		$strs = $absaetze["html"];
		preg_match_all("/<span class='zeilennummer'>([0-9]+)<\/span>/siu", $strs[count($strs) - 1], $matches);
		$anzahl_absaetze = count($strs);
		$anzahl_zeilen = $matches[1][count($matches[1]) - 1];
		return array($anzahl_absaetze, $anzahl_zeilen);
	}

	/**
	 * @static
	 * @param string $text
	 * @param bool $praesentations_hacks
	 * @param int $zeilenlaenge
	 * @return array|string[]
	 */
	static function bbcode2html_absaetze($text, $praesentations_hacks = false, $zeilenlaenge)
	{
		$text = str_replace("\r", "", $text);
		$text = preg_replace("/\[list(.*)\[\/list\]/siU", "\n\n[LIST\\1[/LIST]\n\n", $text);
		$text = preg_replace("/\[quote(.*)\[\/quote\]/siU", "\n\n[QUOTE\\1[/QUOTE]\n\n", $text);
		$text = preg_replace("/\\n( *\\n)+/", "\n\n", $text);

		$text                = preg_replace("/[\\n ]+\[\*\]/siU", "\n[*]", $text);
		$text                = trim($text, " \n");
		$x                   = explode("\n\n", $text);
		$absaetze_html       = array();
		$absaetze_bbcode     = array();
		$absaetze_html_plain = array();

		HtmlBBcodeUtils::$br_implicit = ($praesentations_hacks ? " <br class='implicit'>" : "<br>"); // wird bei responsiver Ansicht manchmal ausgeblendet
		HtmlBBcodeUtils::$br_explicit = "<br>";
		HtmlBBcodeUtils::$zeilenlaenge = $zeilenlaenge;

		foreach ($x as $y) {
			$absaetze_bbcode[]     = $y;
			$abs                   = HtmlBBcodeUtils::bbcode2html($y);
			$absaetze_html_plain[] = $abs;

			if (mb_stripos($abs, "<ul") === 0 || mb_stripos($abs, "<ol") === 0 || mb_stripos($abs, "<blockquote") === 0) {
				$str_neu = str_ireplace("<ul", "<ul class='text'", $abs);
				$str_neu = str_ireplace("<ol", "<ol class='text'", $str_neu);
				$str_neu = str_ireplace("<blockquote", "<blockquote class='text'", $str_neu);
				$str_neu = preg_replace("/( |<br>)*<\/li>/", "</li>", $str_neu);
				$str_neu = preg_replace_callback("/(<(blockquote|li)[^>]*>)(.*)(<\/\\2>)/siU", function ($matches) {
					$out = $matches[1];

					$zeils     = explode("<br>", $matches[3]);
					$zeils_neu = array();
					foreach ($zeils as $zeile) {
						$x           = HtmlBBcodeUtils::text2zeilen($zeile, HtmlBBcodeUtils::$zeilenlaenge - 10);
						$zeils_neu[] = "###ZEILENNUMMER###" . implode(HtmlBBcodeUtils::$br_implicit . "###ZEILENNUMMER###", $x);
					}
					$out .= implode("<br>", $zeils_neu);
					$out .= $matches[4];

					return $out;
				}, $str_neu);
			} else {
				$zeils     = explode("<br>", $abs);
				$zeils_neu = array();
				foreach ($zeils as $zeile) {
					$x           = HtmlBBcodeUtils::text2zeilen($zeile, HtmlBBcodeUtils::$zeilenlaenge);
					$zeils_neu[] = "###ZEILENNUMMER###" . implode(HtmlBBcodeUtils::$br_implicit . "###ZEILENNUMMER###", $x);
				}

				$str_neu = "<div class='text'>";
				$str_neu .= implode("<br>", $zeils_neu);
				$str_neu .= "</div>";
			}

			$str_neu = preg_replace_callback("/###ZEILENNUMMER###/", function () {
				return "<span class='zeilennummer'>" . HtmlBBcodeUtils::$zeilen_counter++ . "</span>";
			}, $str_neu);

			$absaetze_html[] = $str_neu;
		}

		return array("html" => $absaetze_html, "html_plain" => $absaetze_html_plain, "bbcode" => $absaetze_bbcode);
	}

	static function wrapWithTextClass($text) {
		if (mb_stripos($text, "<ul") === 0) $text = str_ireplace("<ul", "<ul class='text'", $text);
		if (mb_stripos($text, "<ol") === 0) $text = str_ireplace("<ol", "<ol class='text'", $text);

		if (mb_stripos($text, "<ul") !== 0 && mb_stripos($text, "<ol") !== 0 && mb_stripos($text, "<blockquote") !== 0) {
			$text = "<div class='text'>" . $text . "</div>";
		}
		return $text;
	}


	static function bbcode2html_absaetze2_block($text, $maxlen)
	{
		echo $text . "\n\n";
		preg_match("/(<ul[^>]*>)(.*)<\/ul>/siu", $text, $matches, PREG_OFFSET_CAPTURE);
		var_dump($matches);
		preg_match("/(<ol[^>]*>)(.*)<\/ol>/siu", $text, $matches, PREG_OFFSET_CAPTURE);
		return $text;
	}

	/**
	 * @static
	 * @param string $text
	 * @param int $zeilenlaenge
	 * @return array|string[]
	 */
	static function bbcode2html_absaetze2($text, $zeilenlaenge)
	{
		$text = str_replace("\r", "", $text);
		$text = preg_replace("/\\n( *\\n)+/", "\n\n", $text);
		//$text                      = preg_replace("/[ \\n]*(\[\/?(BLOCKQUOTE|LIST)[^\]]*\][ \\n]*/siu", "\\1", $text);
		$text = preg_replace("/[\\n ]+\[\*\]/siU", "\n[*]", $text);
		$text = trim($text, " \n");
		echo $text . "\n----------------\n";
		$x                   = explode("\n\n", $text);
		$absaetze_html       = array();
		$absaetze_bbcode     = array();
		$absaetze_html_plain = array();

		foreach ($x as $y) {
			$absaetze_bbcode[] = $y;
			echo $y . "\n=================\n";
			$abs                   = HtmlBBcodeUtils::bbcode2html($y);
			$absaetze_html_plain[] = $abs;
			echo $abs . "\n=================\n";

			$str_neu = self::bbcode2html_absaetze2_block($abs, $zeilenlaenge);

			$zeils     = explode("<br>", $abs);
			$zeils_neu = array();
			foreach ($zeils as $zeile) {
				$zeile = preg_replace("/<ul([^>]*)>/siu", "<ul\\1 class='text'>", $zeile);
				$zeile = preg_replace("/<ol([^>]*)>/siu", "<ol\\1 class='text'>", $zeile);
				$zeile = preg_replace("/<blockquote([^>]*)>/siu", "<blockquote\\1 class='text'>", $zeile);

				//$zeile = preg_replace("/(<ul([^>]*)>|<ol([^>]*)>|<blockquote([^>]*)>| )*(.*)/siu", "\\1###ZEILENNUMMER###"$zeile);
				/*
					$x           = HtmlBBcodeUtils::text2zeilen($zeile, $zeilenlaenge);
				$zeils_neu[] = "###ZEILENNUMMER###" . implode("<br>###ZEILENNUMMER###", $x);
				*/
			}

			$str_neu = preg_replace_callback("/###ZEILENNUMMER###/", function () {
				return "<span class='zeilennummer'>" . HtmlBBcodeUtils::$zeilen_counter++ . "</span>";
			}, $str_neu);


			$absaetze_html[] = $str_neu;
		}

		return array("html" => $absaetze_html, "html_plain" => $absaetze_html_plain, "bbcode" => $absaetze_bbcode);
	}

	/**
	 * @static
	 * @param string $text
	 * @param int $max_len
	 * @param bool $debug
	 * @return array|string[]
	 */
	static function text2zeilen($text, $max_len, $debug = false)
	{

		$zeilen                    = array();
		$letztes_leerzeichen       = -1;
		$letztes_leerzeichen_count = 0;
		$in_html_modus             = false;
		$aktuelle_zeile            = "";
		$aktuelle_zeile_count      = 0;

		$cache_key = md5("text2zeilen" . $max_len . $text);
		$cached = Cache::getObject($cache_key);
		if (is_array($cached)) return $cached;

		for ($i = 0; $i < mb_strlen($text); $i++) {
			$curr_char = mb_substr($text, $i, 1);
			if ($in_html_modus) {
				if ($curr_char == ">") $in_html_modus = false;
				$aktuelle_zeile .= $curr_char;
			} else {
				$aktuelle_zeile .= $curr_char;

				if ($curr_char == "<") {
					$in_html_modus = true;
					continue;
				}

				$aktuelle_zeile_count++;
				if (in_array($curr_char, array(" ", "-"))) {
					$letztes_leerzeichen       = mb_strlen($aktuelle_zeile) - 1;
					$letztes_leerzeichen_count = $aktuelle_zeile_count;
				}
				if ($aktuelle_zeile_count == $max_len) {
					if ($debug) echo "Aktuelle Zeile: \"" . htmlentities($aktuelle_zeile, ENT_COMPAT, "UTF-8") . "\"<br>";
					if ($debug) echo "Count: \"" . $aktuelle_zeile_count . "\"<br>";
					if ($debug) echo "Letztes Leerzeichen: \"" . $letztes_leerzeichen . "\"<br>";

					if ($letztes_leerzeichen == -1) {
						if ($debug) echo "Umbruch forcieren<br>";
						$zeilen[]             = mb_substr($aktuelle_zeile, 0, mb_strlen($aktuelle_zeile) - 1) . "-";
						$aktuelle_zeile       = $curr_char;
						$aktuelle_zeile_count = 1;
					} else {
						$ueberhang = mb_substr($aktuelle_zeile, $letztes_leerzeichen + 1);
						if ($debug) echo "Überhang: \"" . htmlentities($ueberhang, ENT_COMPAT, "UTF-8") . "\"<br>";
						$zeilen[] = mb_substr($aktuelle_zeile, 0, $letztes_leerzeichen + 1); // Leerzeichen bleiben am Ende erhalten; wg. Bindestrichen nötig

						$aktuelle_zeile            = $ueberhang;
						$aktuelle_zeile_count      = $max_len - $letztes_leerzeichen_count;
						$letztes_leerzeichen       = -1;
						$letztes_leerzeichen_count = 0;
					}
					if ($debug) echo "Neue aktuelle Zeile: \"" . htmlentities($aktuelle_zeile, ENT_COMPAT, "UTF-8") . "\"<br>";
					if ($debug) echo "Count: \"" . $aktuelle_zeile_count . "\"<br><br>";
				}
			}
		}
		if (mb_strlen(trim($aktuelle_zeile)) > 0) $zeilen[] = $aktuelle_zeile;

		Cache::setObject($cache_key, $zeilen);

		return $zeilen;
	}


	/**
	 * @static
	 * @param string $text
	 * @return string
	 */
	static function bbcode2html($text)
	{
		$text = preg_replace_callback("/(\[o?list[^\]]*\])(.*)(\[\/o?list\])/siuU", function($matches) {
			$parts = explode("[*]", trim($matches[2]));
			$str = $matches[1];
			foreach ($parts as $part) if ($part != "") $str .= "[LI]" . trim($part) . "[/LI]";
			$str .= $matches[3];
			return  $str;
		}, $text);

		$text = preg_replace_callback("/(\[quote[^\]]*\])(.*)(\[\/o?quote\])/siuU", function($matches) {
			$first_open = mb_stripos($matches[2], "[LIST");
			$first_close = mb_stripos($matches[2], "[/LIST]");

			if ($first_close !== false && ($first_open === false || $first_close < $first_open)) $matches[2] = trim(mb_substr($matches[2], 0, $first_close) . "\n" . mb_substr($matches[2], $first_close + 7));
			return $matches[1] . $matches[2] . $matches[3];
		}, $text);

		//echo "<br>IN========<br>";
		//echo CHtml::encode($text);
		$code = new \Decoda\Decoda();
		$code->addFilter(new AntraegeBBCodeFilter());
		$code->addFilter(new \Decoda\Filter\UrlFilter());
		$code->reset($text);
		$text = $code->parse();
		//echo "<br>OUT========<br>";
		//echo CHtml::encode($text);

		$text = str_replace("<br>\n", "<br>", $text);
		$text = str_replace("\n", "<br>", $text);
		$text = preg_replace("/<br *\/>/siu", "<br>", $text);

		$text = preg_replace("/<ul>[<br>\\n]*<li>/siu", "<ul>\n<li>", $text);
		$text = preg_replace("/<\/li>[<br>\\n]*<li>/siu", "</li>\n<li>", $text);
		$text = preg_replace("/<\/li>[<br>\\n]*<\/ul>/siu", "</li>\n</ul>", $text);

		return $text;
	}


	/**
	 * @static
	 * @param array $matches<commit_msg>Bugfix: zu früher Zeilenumbruch wegen HTML-Escaping<commit_after><?php

class HtmlBBcodeUtils
{

	public static $br_implicit, $br_explicit;

	public static $zeilen_counter = 0;

	public static $zeilenlaenge;

	/**
	 * @param int $init
	 */
	public static function initZeilenCounter($init = 1)
	{
		self::$zeilen_counter = $init;
	}

	/**
	 * @param string $text
	 * @return string
	 */
	static function bbcode_normalize($text)
	{
		$text = preg_replace("/\[(\/?)list([^\]]*)\]/siu", "[\\1LIST\\2]", $text);
		$text = preg_replace("/\[(\/?)quote\]/siu", "[\\1QUOTE]", $text);
		$text = preg_replace("/\[(\/?)b\]/siu", "[\\1B]", $text);
		$text = preg_replace("/\[(\/?)i\]/siu", "[\\1I]", $text);
		$text = preg_replace("/\[(\/?)u\]/siu", "[\\1U]", $text);
		$text = preg_replace("/\[(\/?)url([^\]]*)\]/siu", "[\\1URL\\2]", $text);
		$text = preg_replace("/\[p\](.*)\[\/p\]/siuU", "\\1", $text);

		$text = str_replace(chr(194).chr(160), " ", $text);
		$text = preg_replace("/ {2,}/", " ", $text);

		$x = explode("\n", $text);
		foreach ($x as $i=>$zeile) {
			$x[$i] = trim($zeile);
		}
		return implode("\n", $x);
	}

	/**
	 * @static
	 * @param string $text
	 * @param int $zeilenlaenge
	 * @return array|string[]
	 */
	static function bbcode2zeilen_absaetze($text, $zeilenlaenge)
	{
		HtmlBBcodeUtils::$zeilenlaenge = $zeilenlaenge;
		$text = str_replace("\r", "", $text);
		$text = preg_replace("/\[list(.*)\[\/list\]/siU", "\n\n[LIST\\1[/LIST]\n\n", $text);
		$text = preg_replace("/\[quote(.*)\[\/quote\]/siU", "\n\n[QUOTE\\1[/QUOTE]\n\n", $text);
		$text = preg_replace("/\\n( *\\n)+/", "\n\n", $text);

		$text   = preg_replace("/[\\n ]+\[\*\]/siU", "\n[*]", $text);
		$text   = trim($text, " \n");
		$x      = explode("\n\n", $text);
		$return = array();

		foreach ($x as $y) {
			if (mb_stripos($y, "[list") === 0 || mb_stripos($y, "[ulist") === 0 || mb_stripos($y, "[quote") === 0) {
				$str_neu = preg_replace_callback("/(\[quote[^\]]*\])(.*)(\[\/quote\])/siU", function ($matches) {
					$out = $matches[1];

					$zeils     = explode("\n", $matches[2]);
					$zeils_neu = array();
					foreach ($zeils as $zeile) {
						$x           = HtmlBBcodeUtils::text2zeilen($zeile, HtmlBBcodeUtils::$zeilenlaenge - 10);
						$zeils_neu[] = "###ZEILENNUMMER###" . implode("\n###ZEILENNUMMER###", $x);
					}
					$out .= implode("\n", $zeils_neu);
					$out .= $matches[3];

					return $out;
				}, $y);

				$str_neu = preg_replace_callback("/(\[list[^\]]*\])(.*)(\[\/list\])/siuU", function ($matches) {
					$out = $matches[1];
					$x = explode("[*]", $matches[2]);

					if (count($x) > 1) for ($i = 1; $i < count($x); $i++) if (trim($x[$i]) != "") {
						$zeils = explode("\n", trim($x[$i]));
						$zeils_neu = array();
						foreach ($zeils as $zeile) {
							$z           = HtmlBBcodeUtils::text2zeilen($zeile, HtmlBBcodeUtils::$zeilenlaenge - 10);
							$zeils_neu[] = "###ZEILENNUMMER###" . implode("\n###ZEILENNUMMER###", $z);
						}
						$out .= "[*]" . implode("[*]", $zeils_neu);
					}
					$out .= $matches[3];

					return $out;
				}, $str_neu);

			} else {
				$zeils     = explode("\n", $y);
				$zeils_neu = array();
				foreach ($zeils as $zeile) {
					$x           = HtmlBBcodeUtils::text2zeilen($zeile, HtmlBBcodeUtils::$zeilenlaenge);
					$zeils_neu[] = "###ZEILENNUMMER###" . implode("\n###ZEILENNUMMER###", $x);
				}

				$str_neu = implode("\n", $zeils_neu);
			}

			$str_neu = preg_replace_callback("/###ZEILENNUMMER###/", function () {
				return "#ZEILE#";
			}, $str_neu);

			$str_neu = preg_replace("/([^\\n])#ZEILE#/siu", "\\1\n#ZEILE#", $str_neu);

			$return[] = $str_neu;
		}

		return $return;
	}

	/**
	 * @param string $text
	 * @param int $zeilenlaenge
	 * @return array|int[]
	 */
	static function getBBCodeStats($text, $zeilenlaenge) {
		static::initZeilenCounter(1);
		$absaetze = static::bbcode2html_absaetze($text, false, $zeilenlaenge);
		$strs = $absaetze["html"];
		preg_match_all("/<span class='zeilennummer'>([0-9]+)<\/span>/siu", $strs[count($strs) - 1], $matches);
		$anzahl_absaetze = count($strs);
		$anzahl_zeilen = $matches[1][count($matches[1]) - 1];
		return array($anzahl_absaetze, $anzahl_zeilen);
	}

	/**
	 * @static
	 * @param string $text
	 * @param bool $praesentations_hacks
	 * @param int $zeilenlaenge
	 * @return array|string[]
	 */
	static function bbcode2html_absaetze($text, $praesentations_hacks = false, $zeilenlaenge)
	{
		$text = str_replace("\r", "", $text);
		$text = preg_replace("/\[list(.*)\[\/list\]/siU", "\n\n[LIST\\1[/LIST]\n\n", $text);
		$text = preg_replace("/\[quote(.*)\[\/quote\]/siU", "\n\n[QUOTE\\1[/QUOTE]\n\n", $text);
		$text = preg_replace("/\\n( *\\n)+/", "\n\n", $text);

		$text                = preg_replace("/[\\n ]+\[\*\]/siU", "\n[*]", $text);
		$text                = trim($text, " \n");
		$x                   = explode("\n\n", $text);
		$absaetze_html       = array();
		$absaetze_bbcode     = array();
		$absaetze_html_plain = array();

		HtmlBBcodeUtils::$br_implicit = ($praesentations_hacks ? " <br class='implicit'>" : "<br>"); // wird bei responsiver Ansicht manchmal ausgeblendet
		HtmlBBcodeUtils::$br_explicit = "<br>";
		HtmlBBcodeUtils::$zeilenlaenge = $zeilenlaenge;

		foreach ($x as $y) {
			$absaetze_bbcode[]     = $y;
			$abs                   = HtmlBBcodeUtils::bbcode2html($y);
			$absaetze_html_plain[] = $abs;

			if (mb_stripos($abs, "<ul") === 0 || mb_stripos($abs, "<ol") === 0 || mb_stripos($abs, "<blockquote") === 0) {
				$str_neu = str_ireplace("<ul", "<ul class='text'", $abs);
				$str_neu = str_ireplace("<ol", "<ol class='text'", $str_neu);
				$str_neu = str_ireplace("<blockquote", "<blockquote class='text'", $str_neu);
				$str_neu = preg_replace("/( |<br>)*<\/li>/", "</li>", $str_neu);
				$str_neu = preg_replace_callback("/(<(blockquote|li)[^>]*>)(.*)(<\/\\2>)/siU", function ($matches) {
					$out = $matches[1];

					$zeils     = explode("<br>", $matches[3]);
					$zeils_neu = array();
					foreach ($zeils as $zeile) {
						$x           = HtmlBBcodeUtils::text2zeilen($zeile, HtmlBBcodeUtils::$zeilenlaenge - 10);
						$zeils_neu[] = "###ZEILENNUMMER###" . implode(HtmlBBcodeUtils::$br_implicit . "###ZEILENNUMMER###", $x);
					}
					$out .= implode("<br>", $zeils_neu);
					$out .= $matches[4];

					return $out;
				}, $str_neu);
			} else {
				$zeils     = explode("<br>", $abs);
				$zeils_neu = array();
				foreach ($zeils as $zeile) {
					$x           = HtmlBBcodeUtils::text2zeilen($zeile, HtmlBBcodeUtils::$zeilenlaenge);
					$zeils_neu[] = "###ZEILENNUMMER###" . implode(HtmlBBcodeUtils::$br_implicit . "###ZEILENNUMMER###", $x);
				}

				$str_neu = "<div class='text'>";
				$str_neu .= implode("<br>", $zeils_neu);
				$str_neu .= "</div>";
			}

			$str_neu = preg_replace_callback("/###ZEILENNUMMER###/", function () {
				return "<span class='zeilennummer'>" . HtmlBBcodeUtils::$zeilen_counter++ . "</span>";
			}, $str_neu);

			$absaetze_html[] = $str_neu;
		}

		return array("html" => $absaetze_html, "html_plain" => $absaetze_html_plain, "bbcode" => $absaetze_bbcode);
	}

	static function wrapWithTextClass($text) {
		if (mb_stripos($text, "<ul") === 0) $text = str_ireplace("<ul", "<ul class='text'", $text);
		if (mb_stripos($text, "<ol") === 0) $text = str_ireplace("<ol", "<ol class='text'", $text);

		if (mb_stripos($text, "<ul") !== 0 && mb_stripos($text, "<ol") !== 0 && mb_stripos($text, "<blockquote") !== 0) {
			$text = "<div class='text'>" . $text . "</div>";
		}
		return $text;
	}


	static function bbcode2html_absaetze2_block($text, $maxlen)
	{
		echo $text . "\n\n";
		preg_match("/(<ul[^>]*>)(.*)<\/ul>/siu", $text, $matches, PREG_OFFSET_CAPTURE);
		var_dump($matches);
		preg_match("/(<ol[^>]*>)(.*)<\/ol>/siu", $text, $matches, PREG_OFFSET_CAPTURE);
		return $text;
	}

	/**
	 * @static
	 * @param string $text
	 * @param int $zeilenlaenge
	 * @return array|string[]
	 */
	static function bbcode2html_absaetze2($text, $zeilenlaenge)
	{
		$text = str_replace("\r", "", $text);
		$text = preg_replace("/\\n( *\\n)+/", "\n\n", $text);
		//$text                      = preg_replace("/[ \\n]*(\[\/?(BLOCKQUOTE|LIST)[^\]]*\][ \\n]*/siu", "\\1", $text);
		$text = preg_replace("/[\\n ]+\[\*\]/siU", "\n[*]", $text);
		$text = trim($text, " \n");
		echo $text . "\n----------------\n";
		$x                   = explode("\n\n", $text);
		$absaetze_html       = array();
		$absaetze_bbcode     = array();
		$absaetze_html_plain = array();

		foreach ($x as $y) {
			$absaetze_bbcode[] = $y;
			echo $y . "\n=================\n";
			$abs                   = HtmlBBcodeUtils::bbcode2html($y);
			$absaetze_html_plain[] = $abs;
			echo $abs . "\n=================\n";

			$str_neu = self::bbcode2html_absaetze2_block($abs, $zeilenlaenge);

			$zeils     = explode("<br>", $abs);
			$zeils_neu = array();
			foreach ($zeils as $zeile) {
				$zeile = preg_replace("/<ul([^>]*)>/siu", "<ul\\1 class='text'>", $zeile);
				$zeile = preg_replace("/<ol([^>]*)>/siu", "<ol\\1 class='text'>", $zeile);
				$zeile = preg_replace("/<blockquote([^>]*)>/siu", "<blockquote\\1 class='text'>", $zeile);

				//$zeile = preg_replace("/(<ul([^>]*)>|<ol([^>]*)>|<blockquote([^>]*)>| )*(.*)/siu", "\\1###ZEILENNUMMER###"$zeile);
				/*
					$x           = HtmlBBcodeUtils::text2zeilen($zeile, $zeilenlaenge);
				$zeils_neu[] = "###ZEILENNUMMER###" . implode("<br>###ZEILENNUMMER###", $x);
				*/
			}

			$str_neu = preg_replace_callback("/###ZEILENNUMMER###/", function () {
				return "<span class='zeilennummer'>" . HtmlBBcodeUtils::$zeilen_counter++ . "</span>";
			}, $str_neu);


			$absaetze_html[] = $str_neu;
		}

		return array("html" => $absaetze_html, "html_plain" => $absaetze_html_plain, "bbcode" => $absaetze_bbcode);
	}

	/**
	 * @static
	 * @param string $text
	 * @param int $max_len
	 * @param bool $debug
	 * @return array|string[]
	 */
	static function text2zeilen($text, $max_len, $debug = false)
	{

		$zeilen                    = array();
		$letztes_leerzeichen       = -1;
		$letztes_leerzeichen_count = 0;
		$in_html_modus             = false;
		$aktuelle_zeile            = "";
		$aktuelle_zeile_count      = 0;

		$cache_key = md5("text2zeilen" . $max_len . $text);
		$cached = Cache::getObject($cache_key);
		if (is_array($cached)) return $cached;

		for ($i = 0; $i < mb_strlen($text); $i++) {
			$curr_char = mb_substr($text, $i, 1);
			if ($in_html_modus) {
				if ($curr_char == ">") $in_html_modus = false;
				$aktuelle_zeile .= $curr_char;
			} else {
				$aktuelle_zeile .= $curr_char;

				if ($curr_char == "<") {
					$in_html_modus = true;
					continue;
				}

				$aktuelle_zeile_count++;
				if (in_array($curr_char, array(" ", "-"))) {
					$letztes_leerzeichen       = mb_strlen($aktuelle_zeile) - 1;
					$letztes_leerzeichen_count = $aktuelle_zeile_count;
				}
				if ($aktuelle_zeile_count == $max_len) {
					if ($debug) echo "Aktuelle Zeile: \"" . htmlentities($aktuelle_zeile, ENT_COMPAT, "UTF-8") . "\"<br>";
					if ($debug) echo "Count: \"" . $aktuelle_zeile_count . "\"<br>";
					if ($debug) echo "Letztes Leerzeichen: \"" . $letztes_leerzeichen . "\"<br>";

					if ($letztes_leerzeichen == -1) {
						if ($debug) echo "Umbruch forcieren<br>";
						$zeilen[]             = mb_substr($aktuelle_zeile, 0, mb_strlen($aktuelle_zeile) - 1) . "-";
						$aktuelle_zeile       = $curr_char;
						$aktuelle_zeile_count = 1;
					} else {
						$ueberhang = mb_substr($aktuelle_zeile, $letztes_leerzeichen + 1);
						if ($debug) echo "Überhang: \"" . htmlentities($ueberhang, ENT_COMPAT, "UTF-8") . "\"<br>";
						$zeilen[] = mb_substr($aktuelle_zeile, 0, $letztes_leerzeichen + 1); // Leerzeichen bleiben am Ende erhalten; wg. Bindestrichen nötig

						$aktuelle_zeile            = $ueberhang;
						$aktuelle_zeile_count      = $max_len - $letztes_leerzeichen_count;
						$letztes_leerzeichen       = -1;
						$letztes_leerzeichen_count = 0;
					}
					if ($debug) echo "Neue aktuelle Zeile: \"" . htmlentities($aktuelle_zeile, ENT_COMPAT, "UTF-8") . "\"<br>";
					if ($debug) echo "Count: \"" . $aktuelle_zeile_count . "\"<br><br>";
				}
			}
		}
		if (mb_strlen(trim($aktuelle_zeile)) > 0) $zeilen[] = $aktuelle_zeile;

		Cache::setObject($cache_key, $zeilen);

		return $zeilen;
	}


	/**
	 * @static
	 * @param string $text
	 * @return string
	 */
	static function bbcode2html($text)
	{
		$text = preg_replace_callback("/(\[o?list[^\]]*\])(.*)(\[\/o?list\])/siuU", function($matches) {
			$parts = explode("[*]", trim($matches[2]));
			$str = $matches[1];
			foreach ($parts as $part) if ($part != "") $str .= "[LI]" . trim($part) . "[/LI]";
			$str .= $matches[3];
			return  $str;
		}, $text);

		$text = preg_replace_callback("/(\[quote[^\]]*\])(.*)(\[\/o?quote\])/siuU", function($matches) {
			$first_open = mb_stripos($matches[2], "[LIST");
			$first_close = mb_stripos($matches[2], "[/LIST]");

			if ($first_close !== false && ($first_open === false || $first_close < $first_open)) $matches[2] = trim(mb_substr($matches[2], 0, $first_close) . "\n" . mb_substr($matches[2], $first_close + 7));
			return $matches[1] . $matches[2] . $matches[3];
		}, $text);

		//echo "<br>IN========<br>";
		//echo CHtml::encode($text);
		$code = new \Decoda\Decoda();
		$code->setEscaping(false);
		$code->addFilter(new AntraegeBBCodeFilter());
		$code->addFilter(new \Decoda\Filter\UrlFilter());
		$code->reset($text);
		$text = $code->parse();
		//echo "<br>OUT========<br>";
		//echo CHtml::encode($text);

		$text = str_replace("<br>\n", "<br>", $text);
		$text = str_replace("\n", "<br>", $text);
		$text = preg_replace("/<br *\/>/siu", "<br>", $text);

		$text = preg_replace("/<ul>[<br>\\n]*<li>/siu", "<ul>\n<li>", $text);
		$text = preg_replace("/<\/li>[<br>\\n]*<li>/siu", "</li>\n<li>", $text);
		$text = preg_replace("/<\/li>[<br>\\n]*<\/ul>/siu", "</li>\n</ul>", $text);

		return $text;
	}


	/**
	 * @static
	 * @param array $matches
{'fraction_non_alphanumeric': 0.25255037669874913, 'fraction_numerical': 0.008435168162647345, 'mean_word_length': 3.3421505712944124, 'pattern_counts': {'":': 0, '<': 187, '<?xml version=': 0, '>': 188, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3003693', 'n_tokens_mistral': 12580, 'n_tokens_neox': 10992, 'n_words': 1849}