Мод добавления пробелов

Здесь авторы могут постить бета-версии своих модификаций для phpBB 3.0.x. Внимание! Не устанавливайте бета-версии модов на работающие форумы!
Правила форума
Местная Конституция | Шаблон запроса | Документация (phpBB3) | Переход на 3.0.6 и выше | FAQ-3 (phpbb3) | Как задавать вопросы | Как устанавливать моды

Ваш вопрос может быть удален без объяснения причин, если на него есть ответы по приведённым ссылкам (а вы рискуете получить предупреждение ;) ).
Аватара пользователя
c61
phpBB 2.0.6
Сообщения: 506
Стаж: 13 лет 9 месяцев
Благодарил (а): 42 раза
Поблагодарили: 251 раз

Re: Мод добавления пробелов

Сообщение c61 »

Sheer писал(а):Ну так доделайте.
Хмммм... Регулярки... Только не сегодня)
Аватара пользователя
Sheer
Former team member
Сообщения: 12113
Стаж: 19 лет 7 месяцев
Откуда: Калининград не Кенигсберг
Благодарил (а): 54 раза
Поблагодарили: 2756 раз

Re: Мод добавления пробелов

Сообщение Sheer »

c61
Ха-ха три раза.
Изображение
Общие ошибки новичков (07.11.2005) & Как задавать вопросы
Мини FAQ
Если ничто другое не помогает, прочтите, наконец, инструкцию!
"Никакая инструкция не может перечислить всех обязанностей должностного лица, предусмотреть все отдельные случаи и дать вперёд соответствующие указания, а поэтому господа инженеры должны проявить инициативу и, руководствуясь знаниями своей специальности и пользой дела, принять все усилия для оправдания своего назначения".
Циркуляр Морского технического комитета №15 от 29.11.1910 г.
Аватара пользователя
c61
phpBB 2.0.6
Сообщения: 506
Стаж: 13 лет 9 месяцев
Благодарил (а): 42 раза
Поблагодарили: 251 раз

Re: Мод добавления пробелов

Сообщение c61 »

Sheer писал(а):Ха-ха три раза
Регулярки - это не смешно( Я их недолюбливаю из-за всяких закорючек, которые надо ставить в нужных (и ненужных) местах, а также из-за того, что на разных версиях php можно (при желании) получить разный результат. Вернее, для старых версий иногда можно не получить никакого результата)

Полагаю, сделаю ошибку, если возьму и выложу здесь готовый код. Значительно полезнее будет, если автор этого мода самостоятельно сделает необходимые дополнения-изменения "по наводке". То есть попробуем провести обучение - как решать такие задачи. Я тоже рассчитываю чему-то научиться)

Итак, что нам понадобится:
  1. немного логики
  2. умение смотреть исходный код в браузере
  3. тестировщик регулярок (например, этот)
  4. минимальные знания php
Как говорилось ранее, нам не следует проводить замены в ссылках (url) и публикуемых кодах ("code", "icode").

Посмотрим, какие подходы к решению задачи возможны, если мы собираемся использовать хук:
  1. внести исправления в сообщение пользователя в том момент, когда отправляются данные формы
  2. внести исправления перед выдачей сообщения на просмотр
Для (1) есть очевидное преимущество - уменьшение нагрузки на сервер, поскольку исправления надо сделать однократно. Но есть существенный недостаток - требуется разбор бб-кодов с url, поскольку нам требуется знать, какие бб-коды их используют, и придётся получать список, а также разбор "code", "icode" и всего прочего, что админ сам напридумывает.

Для (2) преимущество - все url уже в тэге "a", грамотно реализованнные "code", "icode" и тп - в тэге "code". Недостаток - надо ещё исключить из анализа javascript, встречающийся после раскрытия некоторых бб-кодов. Ещё недостаток - повышение нагрузки на сервер, поскольку хук работает при выдачи сообщения, но кэширование страниц нам помогает в снижении нагрузки. Поэтому выбираем вариант (2) - он вообще-то уже был выбран без этих рассуждений).

Сделаем примерчик для code/icode (разумеется, вложения бб-кодов не рассматриваем, поскольку практически никто не ставит полезный мод, их учитывающий) и посмотрим, как выглядит html-код в браузере:

Код: Выделить всё

тестовый пример[code]code level1 [url=http://mysite.ru]link[/url]
icode level1 [url=http://mysite.ru]link[/url]link[/code]
Это мы видим в сообщении:
тестовый пример

Код: Выделить всё

code level1 [url=http://mysite.ru]link[/url]
icode level1 [url=http://mysite.ru]link[/url]link

Этот html-код мы видим в браузере, если посмотрим исходный код:

Код: Выделить всё

тестовый пример<div class="codebox"><div>Код: <a href="#" onclick="selectCode(this); return false;">Выделить всё</a></div><pre><code class="auto">code level1 &#91;url=http://mysite.ru&#93;link&#91;/url&#93;</code></pre></div><span class="inlinecodebox"><code>icode level1 <a href="http://mysite.ru" class="postlink">link</a></code></span><a href="http://mysite.ru" class="postlink">link</a>
Обратите внимание: мы сразу нашли странность реализации "icode" - ведь ссылка оказалась действующей ! Но это нас не должно волновать - мы пишем тестовый пример вовсе не для поиска чужих багов, а для создания собственных)

Добавим ещё и javascript (в том числе в "code") - ведь мы должны исключить скрипты из обработки. Получаем такой тестовый пример:

Код: Выделить всё

тестовый пример<div class="codebox"><div>Код: <a href="#" onclick="selectCode(this); return false;">Выделить всё</a></div><pre><code class="auto">code level1 &#91;url=http://mysite.ru&#93;link&#91;/url&#93;<script type="text/javascript">
var test1 = 123;
</script></code></pre></div><span class="inlinecodebox"><code>icode level1 <a href="http://mysite.ru" class="postlink">link</a></code></span><a href="http://mysite.ru" class="postlink">link</a><script type="text/javascript">
var test1 = 123;
</script>
Напишем регулярное выражение для выделения нужных нам тэгов (причём с учетом вложенности, мало ли чего пользователи натворят). Собственно, сами писать ничего не будем, а возьмём готовое. Просто найдем в сети и модифицируем. Где искать - не скажу, ищите сами, ключевые слова были сказаны выше) Начнём с тэга "code". Регулярка:

Код: Выделить всё

/(?=(<code.*?>(?>(?1)|.)*?</code>))/isu
Конструкция с "?" в начале и всякие "?" и "?1" в середине - для рекурсивного поиска. Модификаторы "isu" - соответственно: поиск без учета регистра, многострочный, utf-8. Проверяем на нашем тестировщике. Получаем:

Код: Выделить всё

Array
(
    [0] => Array
        (
            [0] => 
            [1] => 
        )

    [1] => Array
        (
            [0] => <code class="auto">code level1 [url=http://mysite.ru]link[/url]<script type="text/javascript">
var test1 = 123;
</script></code>
            [1] => <code>icode level1 <a href="http://mysite.ru" class="postlink">link</a></code>
        )

)
"Ну и что ?" - скажете. А где же позиции символов ? Добавляем в функцию preg_match_all() тестировщика последним параметром PREG_OFFSET_CAPTURE и наблюдаем такое:

Код: Выделить всё

Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => 
                    [1] => 155
                )

            [1] => Array
                (
                    [0] => 
                    [1] => 325
                )

        )

    [1] => Array
        (
            [0] => Array
                (
                    [0] => <code class="auto">code level1 [url=http://mysite.ru]link[/url]<script type="text/javascript">
var test1 = 123;
</script></code>
                    [1] => 155
                )

            [1] => Array
                (
                    [0] => <code>icode level1 <a href="http://mysite.ru" class="postlink">link</a></code>
                    [1] => 325
                )

        )

)
Но радоваться рано - в комментариях к preg_math_all на php.net сказано: "PREG_OFFSET_CAPTURE always seems to provide byte offsets, rather than character position offsets, even when you are using the unicode /u modifier." Вот предлагаю самостоятельно с этим и разобраться !

Далее мы сделаем регулярки для тэгов "a", "script". Затем объединим результаты, после чего наконец-то определимся с диапазонами номеров символов текста, внутри которых можем проводить замены.

P.S. Может, мне продолжать и не стоит - самостоятельно намного интереснее сделать)

Добавлено спустя 22 минуты 52 секунды:
Забыл упомянуть: есть ещё один вариант решения задачи - когда не требуется определять позиции символов. Для этого используются замены найденных тэгов на некие уникальные последовательности символов. Затем проводится требуемая замена для вставки пробелов. А потом уникальные последовательности заменяются обратно на вырезанные ранее тэги. Этот путь требует немного больше ресурсов сервера, но реализация проще.
Аватара пользователя
Sheer
Former team member
Сообщения: 12113
Стаж: 19 лет 7 месяцев
Откуда: Калининград не Кенигсберг
Благодарил (а): 54 раза
Поблагодарили: 2756 раз

Re: Мод добавления пробелов

Сообщение Sheer »

c61 писал(а):Регулярки - это не смешно
И я о том же.
c61 писал(а):что нам понадобится
Не хватает одного пункта
5. знание и понимание синтаксиса регулярных выражений и умение составлять шаблоны regexp
Вот это самое главное.
Изображение
Общие ошибки новичков (07.11.2005) & Как задавать вопросы
Мини FAQ
Если ничто другое не помогает, прочтите, наконец, инструкцию!
"Никакая инструкция не может перечислить всех обязанностей должностного лица, предусмотреть все отдельные случаи и дать вперёд соответствующие указания, а поэтому господа инженеры должны проявить инициативу и, руководствуясь знаниями своей специальности и пользой дела, принять все усилия для оправдания своего назначения".
Циркуляр Морского технического комитета №15 от 29.11.1910 г.
Аватара пользователя
c61
phpBB 2.0.6
Сообщения: 506
Стаж: 13 лет 9 месяцев
Благодарил (а): 42 раза
Поблагодарили: 251 раз

Re: Мод добавления пробелов

Сообщение c61 »

Sheer писал(а):Не хватает одного пункта5. знание и понимание синтаксиса регулярных выражений и умение составлять шаблоны regexp
Ха-ха ! Вот это как раз и не требуется) Доказательство было приведено выше.
Аватара пользователя
Sheer
Former team member
Сообщения: 12113
Стаж: 19 лет 7 месяцев
Откуда: Калининград не Кенигсберг
Благодарил (а): 54 раза
Поблагодарили: 2756 раз

Re: Мод добавления пробелов

Сообщение Sheer »

Да ну?!
Разбудите меня ночью, и спросите что сделает pregmatch(), если использовать вот это шаблон "|^[-0-9a-z_\.]+@[-0-9a-z_^\.]+\.[a-z]{2,6}$|i" и почему там ^ и не ?
Изображение
Общие ошибки новичков (07.11.2005) & Как задавать вопросы
Мини FAQ
Если ничто другое не помогает, прочтите, наконец, инструкцию!
"Никакая инструкция не может перечислить всех обязанностей должностного лица, предусмотреть все отдельные случаи и дать вперёд соответствующие указания, а поэтому господа инженеры должны проявить инициативу и, руководствуясь знаниями своей специальности и пользой дела, принять все усилия для оправдания своего назначения".
Циркуляр Морского технического комитета №15 от 29.11.1910 г.
Аватара пользователя
c61
phpBB 2.0.6
Сообщения: 506
Стаж: 13 лет 9 месяцев
Благодарил (а): 42 раза
Поблагодарили: 251 раз

Re: Мод добавления пробелов

Сообщение c61 »

А мы не будем использовать такие шаблоны) Как было сказано, на понадобится только один шаблон, причём общеизвестный, найденный в инете.
Аватара пользователя
Sheer
Former team member
Сообщения: 12113
Стаж: 19 лет 7 месяцев
Откуда: Калининград не Кенигсберг
Благодарил (а): 54 раза
Поблагодарили: 2756 раз

Re: Мод добавления пробелов

Сообщение Sheer »

c61 писал(а):Собственно, сами писать ничего не будем, а возьмём готовое. Просто найдем в сети и модифицируем
Это частный случай. К тому же надо еще грамотно модифицировать. Вот тут знание и понадобится.
Изображение
Общие ошибки новичков (07.11.2005) & Как задавать вопросы
Мини FAQ
Если ничто другое не помогает, прочтите, наконец, инструкцию!
"Никакая инструкция не может перечислить всех обязанностей должностного лица, предусмотреть все отдельные случаи и дать вперёд соответствующие указания, а поэтому господа инженеры должны проявить инициативу и, руководствуясь знаниями своей специальности и пользой дела, принять все усилия для оправдания своего назначения".
Циркуляр Морского технического комитета №15 от 29.11.1910 г.
Аватара пользователя
c61
phpBB 2.0.6
Сообщения: 506
Стаж: 13 лет 9 месяцев
Благодарил (а): 42 раза
Поблагодарили: 251 раз

Re: Мод добавления пробелов

Сообщение c61 »

Не "частный", а для решения данной (конкретной) задачи. Мы не будет пытаться решать "любую задачу", это невозможно)

Добавлено спустя 18 минут 3 секунды:
Sheer писал(а):надо еще грамотно модифицировать
Любой, хоть немного понимающий php (но не регулярки), может заменить в выражении "div" на "code", затем на "a", затем на "script", для этого особые знания и понимание синтаксиса регулярных выражений не нужны, достаточно немного логики. То есть совсем немного мозгов)
Аватара пользователя
Пчелкин
phpBB 3.3.0
Сообщения: 11361
Стаж: 16 лет 8 месяцев
Благодарил (а): 1832 раза
Поблагодарили: 1358 раз

Re: Мод добавления пробелов

Сообщение Пчелкин »

Регулярки - не регулярки...Хорошо что я в этом нибельме...А то б голова заболела...
Пусть разбираются те, кто в этом деле собаку съел...
Вы лучше скажите - можно сделать что б это хук физически вносил пробелы в бд?
Фигли эти пробелы, когда при открытии сообщения в правке их нет...Убрал хук и все непробелы опять непробелы...
Толку-то от такого хука?
NIKON-D90, AF-S 18-105, AF-S 14-24, AF-S 24-70
Аватара пользователя
МайскийЖук
phpBB 3.0.7-PL1
Сообщения: 2535
Стаж: 16 лет 11 месяцев
Благодарил (а): 17 раз
Поблагодарили: 366 раз

Мод добавления пробелов

Сообщение МайскийЖук »

:lol:

Наконец-то здоровый взгляд на вещи из народа. А то все regexp`ы, да regexp`ы. Парят народу голову не пойми чем, да? :D
Любовь и боль, покой и бой я как любой несу с собой…
Аватара пользователя
Пчелкин
phpBB 3.3.0
Сообщения: 11361
Стаж: 16 лет 8 месяцев
Благодарил (а): 1832 раза
Поблагодарили: 1358 раз

Re: Мод добавления пробелов

Сообщение Пчелкин »

Ага...временные меры хуже самой каторги...всегда могут обернуться против нас...при том неожиданно...
NIKON-D90, AF-S 18-105, AF-S 14-24, AF-S 24-70
Аватара пользователя
c61
phpBB 2.0.6
Сообщения: 506
Стаж: 13 лет 9 месяцев
Благодарил (а): 42 раза
Поблагодарили: 251 раз

Re: Мод добавления пробелов

Сообщение c61 »

Пчелкин писал(а):можно сделать что б это хук физически вносил пробелы в бд?
Можно, см. вариант (1) - хук при отправке формы. Но реализация значительно сложнее, чем вариант (2).
МайскийЖук писал(а):Парят народу голову не пойми чем, да?
Парю тем, что можно и без знания регулярок жить)

Добавлено спустя 1 час 7 минут 21 секунду:
Поскольку никто ничего не желает программировать, придётся всё-таки мне... Вот из вредности выложу готовый код без объяснений и без изменения ранее использовавшейся стратегии замены - вместо do_replace:

Код: Выделить всё

function do_replace(&$item)
{
	if(!isset($item['MESSAGE'])) return;
	
	// Составляем список знаков препинания
	$list = array(',', '(');
	$list_replace = array(', ', ' (');

	// Составляем список случаев обратной замены
	$list_anti = array(', 0', ', 1', ', 2', ', 3', ', 4', ', 5', ', 6', ', 7', ', 8', ', 9');
	$list_antireplace = array(',0', ',1', ',2', ',3', ',4', ',5', ',6', ',7', ',8', ',9');

	// Разыскиваемые тэги
	$tags = array("code","a","script");
	$ent = array();
	foreach($tags as $tag)
	{
		// Поиск тэга
		if(preg_match_all("/(?=(<$tag.*?>(?>(?1)|.)*?<\/$tag>))/isu",$item['MESSAGE'],$matches,PREG_OFFSET_CAPTURE))
		{
			foreach($matches[1] as $match)
			{
				// Собираем вхождения тэгов в массив 'индекс' => 'длина'
				$ent[(int) $match[1]] = (int) strlen($match[0]);
			}
		}
	}
	// Добавляем пустышку - чтобы алгоритм обработал остатки текста за последним тэгом
	$ent[(int) strlen($item['MESSAGE'])] = (int) 0;

	// Сортируем по ключу, по возрастанию
	if(ksort($ent))
	{
		// Начальный индекс, новый текст
		$start = 0;
		$newtext = '';
		// Проход по всем вхождениям
		foreach($ent as $key => $val)
		{
			if($key > $start)	// Индекс больше стартового ?
			{
				// Да. Выделяем подстроку
				$substr = substr($item['MESSAGE'],$start,$key-$start);
				// Проводим замены в подстроке:
				// Ищем в сообщениях знаки препинания и добавляем после них пробелы
				$substr = str_replace($list, $list_replace, $substr);
				// Ищем в сообщениях знаки препинания и убираем после них пробелы
				$substr = str_replace($list_anti, $list_antireplace, $substr);
				// Отправляем подстроку с заменами и тэг в результирующий текст
				$newtext .= $substr . substr($item['MESSAGE'],$key,$val);
				// Переопределяем начальный индекс
				$start = $key + $val;
			}
		}

		// Если всё нормально - переопределяем текст сообщения
		if($newtext != '')
		{
			$item['MESSAGE'] = $newtext;
		}
	}
}
и проверяйте... И только одна регулярка. А ещё спорили) Обратите внимание: никаких функций для обработки мультибайтовых символов, всё в бинарном виде. Ну дальше-то кто-нибудь облагородит ?.. Кто хотел потренироваться с регулярками ?
Аватара пользователя
Sheer
Former team member
Сообщения: 12113
Стаж: 19 лет 7 месяцев
Откуда: Калининград не Кенигсберг
Благодарил (а): 54 раза
Поблагодарили: 2756 раз

Re: Мод добавления пробелов

Сообщение Sheer »

c61 писал(а):Кто хотел потренироваться с регулярками ?
Я не... да и зачем, если str_replace() работает быстрее, чем preg_match_replace() :)
Изображение
Общие ошибки новичков (07.11.2005) & Как задавать вопросы
Мини FAQ
Если ничто другое не помогает, прочтите, наконец, инструкцию!
"Никакая инструкция не может перечислить всех обязанностей должностного лица, предусмотреть все отдельные случаи и дать вперёд соответствующие указания, а поэтому господа инженеры должны проявить инициативу и, руководствуясь знаниями своей специальности и пользой дела, принять все усилия для оправдания своего назначения".
Циркуляр Морского технического комитета №15 от 29.11.1910 г.
Аватара пользователя
c61
phpBB 2.0.6
Сообщения: 506
Стаж: 13 лет 9 месяцев
Благодарил (а): 42 раза
Поблагодарили: 251 раз

Re: Мод добавления пробелов

Сообщение c61 »

Sheer писал(а):... str_replace() работает быстрее, чем preg_match_replace()
Конечно ! За это и боролись.

Однако, в вышеприведенном коде есть один мааааленький баг, который будет проявляться только при определённых условиях... Вот думаю, объявить конкурс на поиск или не стоит ?..

Вернуться в «Бета-версии модов для phpBB 3.0.x»