Порой для какой то тривиальной и простой и популярной задачи бывает сложно отыскать простое решение, кажется что истина где-то рядом и уже придуман не один способ их решения, но они что-то все не находятся… Суть вот в чём — для популярной системы WordPress внизу страницы нужно вставить ссылку на следующую страницу из этой же категории. Замучившись искать какой-н. плагин я придумал, как я считаю, оригинальное но немного громоздкое и извращённое решение, поэтому не ругайте сильно что криво и если знаете как решить это просто — откомментесь, пожалуйста.
В WP есть стандартная функция wp_list_pages которая генерирует список ссылок на страницы из заданной категории, рассмотрим парсин выдаваемых результатов подробнее:
суть: если мы находимся на странице из какой либо категории — выдаём список ссылок элементы из той же категории(если есть родитель — получаем элементы у которых такой же родитель), если в корне(родителя нет) — то ссылки на элементы у которых родитель текущая страница(категория) с глубиной вложенности — 1 уровень.
Суть регулярных выражений: первое в строку $children перезаписывает то что нам сгенерировала wp_list_pages обрубая теги li с классом current_page_item, причём заменяя его на знак "!". Делается это для того чтобы отсеять ссылки на текущую страницу и на те что находятся с order выше(раньше) текущей страницы, т.к. нам нужна ссылка на следующую страницу.
Загоняем в массив наши ссылки
break;
}
}
Суть: Проходим циклом по всему массиву ссылок и проверяем — встречается ли нам восклицательный знак(на который мы меняли ссылку на текущую страницу) первым или вторым символом(в каком то из случаев, не помню в каком — вроде бы когда ссылка на текущую страницу была где-то в середине — перед ней получался пробел). И как только это условие срабатывает — записываем в $result начиная со второго символа(без "!", получится начало тега а) и до конца, прибавляя к полученному закрытие тега а, т.к. они обрубились когда мы резали по ним в массив функцией explode
Проверяем длиннее ли 5 символов наша строка — почему 5, просто потому что если хотя бы 5 символов есть — то это точно ссылка, т.к. туда могло попасть просто закрытие тега а, если элемент в массиве был последним
Далее пойдёт вообще полный бред, который можно было бы сделать регулярками, но я тогда ещё не очень в них шарил, да и сейчас не на высоком уровне, поэтому сделал так:
Определяем максимальную длину(29) и… и… мм, чет на столько полный бред я написал что даже не могу вспомнить зачем настолько тупой ничего не делающий цикл, аа, вспомнил! Мы наращиваем переменную $i в которой будет храница позиция символа > в строке
Далее:
}
Делаем цикл от символа > до конца строки и получаем позицию < Почему так извращённо а не просто вычтя 4 от длины строки? Мало ли там к-нить пробелы ещё после затесались…
Копируем в $tmp содержимое строки между символами > и < в результате чего у нас там оказывается текст названия ссылки
Проверяем длиннее ли он максимальной длины что мы указали ранее(29 символов), если да — то копируем в $res2 содержимое оригинальной целой строки всего тега а с href и прочими атрибутами до символа > включительно, в результате чего в $res2 у нас оказывается
}
$tmp = substr($result,$i+1,$k-$i-1);
if (strlen($tmp)>$max_symb) {
$res2 = substr($result,0,$i+1);
$res2.= substr($tmp,0,$max_symb)."...";
$res2.= substr($result,$k);
}
?>
Read Next: <?php echo $res2;?> »
<?php }?>
В WP есть стандартная функция wp_list_pages которая генерирует список ссылок на страницы из заданной категории, рассмотрим парсин выдаваемых результатов подробнее:
if ($post->post_parent)
$children = wp_list_pages("depth=1&title_li=&child_of=".$post->post_parent."&echo=0");
else
$children = wp_list_pages("depth=1&title_li=&child_of=".$post->ID."&echo=0");
суть: если мы находимся на странице из какой либо категории — выдаём список ссылок элементы из той же категории(если есть родитель — получаем элементы у которых такой же родитель), если в корне(родителя нет) — то ссылки на элементы у которых родитель текущая страница(категория) с глубиной вложенности — 1 уровень.
$children = preg_replace('/<li\s+[^>]*?class="[^"]*(?:current_page_item)[^"]*"[^>]*>((?:(?!<\/li>).)*)<\/li>/si','!',$children);
$children = preg_replace('/<[\/\!]*?li[^<>]*?>/si','',$children);
Суть регулярных выражений: первое в строку $children перезаписывает то что нам сгенерировала wp_list_pages обрубая теги li с классом current_page_item, причём заменяя его на знак "!". Делается это для того чтобы отсеять ссылки на текущую страницу и на те что находятся с order выше(раньше) текущей страницы, т.к. нам нужна ссылка на следующую страницу.
$test = explode("
", $children);Загоняем в массив наши ссылки
$result = "";
for ($i=0;$i<count($test);$i++) {
$tmp = $test[$i];
if ($tmp[0]=="!" || $tmp[1]=="!") {
$result = substr($test[$i]."
",2);break;
}
}
Суть: Проходим циклом по всему массиву ссылок и проверяем — встречается ли нам восклицательный знак(на который мы меняли ссылку на текущую страницу) первым или вторым символом(в каком то из случаев, не помню в каком — вроде бы когда ссылка на текущую страницу была где-то в середине — перед ней получался пробел). И как только это условие срабатывает — записываем в $result начиная со второго символа(без "!", получится начало тега а) и до конца, прибавляя к полученному закрытие тега а, т.к. они обрубились когда мы резали по ним в массив функцией explode
if(strlen($result)>5) {
Проверяем длиннее ли 5 символов наша строка — почему 5, просто потому что если хотя бы 5 символов есть — то это точно ссылка, т.к. туда могло попасть просто закрытие тега а, если элемент в массиве был последним
Далее пойдёт вообще полный бред, который можно было бы сделать регулярками, но я тогда ещё не очень в них шарил, да и сейчас не на высоком уровне, поэтому сделал так:
$max_symb = 29;
for ($i=0; $i<strlen($result); $i++) {
if ($result[$i] == ">") break;
}
Определяем максимальную длину(29) и… и… мм, чет на столько полный бред я написал что даже не могу вспомнить зачем настолько тупой ничего не делающий цикл, аа, вспомнил! Мы наращиваем переменную $i в которой будет храница позиция символа > в строке
Далее:
for ($k=$i; $k<strlen($result); $k++) {
if (substr($result,$k,4) == "
") break;}
Делаем цикл от символа > до конца строки и получаем позицию < Почему так извращённо а не просто вычтя 4 от длины строки? Мало ли там к-нить пробелы ещё после затесались…
$tmp = substr($result,$i+1,$k-$i-1);
Копируем в $tmp содержимое строки между символами > и < в результате чего у нас там оказывается текст названия ссылки
if (strlen($tmp)>$max_symb) {
$res2 = substr($result,0,$i+1);
$res2.= substr($tmp,0,$max_symb)."...";
$res2.= substr($result,$k);
}
Проверяем длиннее ли он максимальной длины что мы указали ранее(29 символов), если да — то копируем в $res2 содержимое оригинальной целой строки всего тега а с href и прочими атрибутами до символа > включительно, в результате чего в $res2 у нас оказывается
что-то типа этого.
Затем к $res2 добавляем часть строки названия ссылки до максимального символа(29-го) и троеточие на конце.
И потом добавляем из оригинальной строки окончания после символа < включительно, получается закрытие тега а.
Результате всех этих действий в $res2 у нас теперь хранится ссылка с названием следующей страницы (по order), находящейся в той же категории что и текущая и если длина названия следующей страницы больше 29 символов - обрублена до 29 и добавлено троеточие. Вот, попытался поделиться этим извращённым хардкордом который мне пришлось однажды написать, не найдя к-нить простого готового решения для такой тривиальной задачки, далее прилагаю полный листинг кода и ссылку на проект где это было использовано http://staging.widefunnel.com/ (смотреть внизу страницы, чуть позже и возможно на самом widefunnel.com, сейчас недоступно - наверное переносят, они еще давно хотели, это был редизайн блога)
Полный код:
<?php
if ($post->post_parent)
$children = wp_list_pages("depth=1&title_li=&child_of=".$post->post_parent."&echo=0");
else
$children = wp_list_pages("depth=1&title_li=&child_of=".$post->ID."&echo=0");
$children = preg_replace('/<li\s+[^>]*?class="[^"]*(?:current_page_item)[^"]*"[^>]*>((?:(?!<\/li>).)*)<\/li>/si','!',$children);
$children = preg_replace('/<[\/\!]*?li[^<>]*?>/si','',$children);
$test = explode("", $children);
$result = "";
for ($i=0;$i<count($test);$i++) {
$tmp = $test[$i];
if ($tmp[0]=="!" || $tmp[1]=="!") {
$result = substr($test[$i]."
",2);
break;
}
}
?>
<?php if(strlen($result)>5) {?>
<?php
$max_symb = 29;
for ($i=0; $i<strlen($result); $i++) {
if ($result[$i] == ">") break;
}
for ($k=$i; $k<strlen($result); $k++) {
if (substr($result,$k,4) == "
") break;}
$tmp = substr($result,$i+1,$k-$i-1);
if (strlen($tmp)>$max_symb) {
$res2 = substr($result,0,$i+1);
$res2.= substr($tmp,0,$max_symb)."...";
$res2.= substr($result,$k);
}
?>
Read Next: <?php echo $res2;?> »
<?php }?>