Обрізання тексту та/або заміна стандартної функції the_excerpt()

Зауважив, що функція WordPress the_excerpt() є громіздкою. На її виконання йде багато часу та ресурсів. Тому що вона викликає get_the_excerpt() , the_content() і до всіх них, включаючи сам the_excerpt() , застосовуються різні хуки. У результаті виходить чимало операцій – це потрібно далеко не завжди. Я наприклад, до цитат ставлюся просто – коротко сказати про що стаття, вирізавши невеликий її шматок – досить просто тексту.

З цим недоліком я мирився доти, доки мені не знадобилося обрізати текст до певної кількості символів. Тоді то я і вирішив написати функцію тексту, що обрізає.

Результат заміни the_excerpt() мене порадував: генерація сторінки зменшилася в середньому з 0,850 с до 0,550 с , при 9 викликах the_excerpt() (цей час на комп’ютері, на сервері зазвичай воно менше). 9 викликів – це кількість постів, що виводяться в рубриці, до кожного з яких застосовувався the_excerpt() .

Нижче наведена функція, якою можна замінити стандартну функцію WordPress the_excerpt() .

GitHub

<?php

/**
 * Натисніть на особливий текст вгору до відповідного номера параметрів.
 * Strips any of shortcodes.
 *
 * Important changes:
 * 2.8.0 - Improved logic to work with HTML tags in cutting text.
 * 2.7.2 - Cuts direct URLs від content.
 * 2.7.0 - `sanitize_callback` parameter.
 * 2.6.5 - `ignore_more` parameter.
 * 2.6.2 - Regular to remove block shortcodes like: [foo]some data[/foo].
 * 2.6 - Removed the `save_format` parameter and replaced it with 2 parameters `autop` and `save_tags`.
 *
 * @author Kama (wp-kama.ru)
 * @version 2.8.0
 *
 * @param string|array $args {
 * Optional. Arguments to customize output.
 *
 * @type int $maxchar Max number of characters.
 * @type string $text The text to be cut. Default is `post_excerpt` if there is no `post_content`.
 * If the text has `<!--more-->`, then `maxchar` is ignored and everything
 * up to `<!--more-->` is taken including HTML.
 * @type bool $autop Переміщення line breaks with `<p>` and `<br>` or not?
 * @type string $more_text The text of `Read more` link.
 * @type string $save_tags Tags to be left in the text. Для прикладу `<strong><b><a>`.
 * @type string $sanitize_callback Text cleaning function.
 * @type bool $ignore_more Whether to ignore `<!--more-->` in the content.
 *
 * }
 *
 * @return string HTML
 */
function kama_excerpt( $args = '' ){
	global $post;

	if( is_string( $args ) ){
		parse_str ($ args, $ args);
	}

	$rg = (object) array_merge( [
		'maxchar' => 350,
		'text' => '',
		'autop' => true,
		'more_text' => 'Читати далі...',
		'ignore_more' => false,
		'save_tags' => '<strong><b><a><em><i><var><code><span>',
		'sanitize_callback' => static function( string $text, object $rg ){
			return strip_tags($text, $rg->save_tags);
		},
	], $ args);

	$ rg = apply_filters ( 'kama_excerpt_args', $ rg);

	if( ! $rg->text ){
		$rg->text = $post->post_excerpt?: $post->post_content;
	}

	$text = $rg->text;
	// strip content shortcodes: [foo] some data [/ foo]. Consider markdown
	$text = preg_replace( '~[([a-z0-9_-]+)[^]]*](?!().*?[/1]~is', '' , $ Text);
	// strip інші shortcodes: [singlepic id=3]. Consider markdown
	$text = preg_replace( '~[/?[^]]*](?!()~', '', $text );
	// strip direct URLs
	$text = preg_replace( '~(?<=s)https?://.+s~', '', $text );
	$ Text = trim ($ Text);

	// <!--more-->
	if( ! $rg->ignore_more && strpos( $text, '<!--more-->' ) ){

		preg_match( '/(.*)<!--more-->/s', $text, $mm );

		$ text = trim ($ mm [1]);

		$text_append = sprintf( ' <a href="%s#more-%d">%s</a>', get_permalink( $post ), $post->ID, $rg->more_text );
	}
	// Text, excerpt, content
	else {

		$text = call_user_func( $rg->sanitize_callback, $text, $rg );
		$has_tags = false !== strpos( $text, '<' );

		// collect html tags
		if( $has_tags ){
			$tags_collection = [];
			$nn = 0;

			$text = preg_replace_callback( '/<[^>]+>/', static function( $match ) use ( & $tags_collection, & $nn ){
				$nn++;
				$holder = "~$nn";
				$tags_collection[ $holder ] = $match[0];

				return $holder;
			}, $ text);
		}

		// cut text
		$ cuted_text = mb_substr ($ text, 0, $ rg-> maxchar);
		if( $text !== $cuted_text ){

			// del last word, it not complate in 99%
			$text = preg_replace( '/(.*)sS*$/s', '1...', trim( $cuted_text ) );
		}

		// bring html tags back
		if( $has_tags ){
			$text = strtr($text, $tags_collection);
			$text = force_balance_tags($text);
		}
	}

	// add tags. Simple analog of wpautop()
	if( $rg->autop ){

		$text = preg_replace(
			[ "/r/", "/n{2,}/", "/n/" ],
			[ '', '</p><p>', '<br />' ],
			"<p>$text</p>"
		);
	}

	$text = apply_filters( 'kama_excerpt', $text, $rg );

	if( isset( $text_append ) ){
		$text.=$text_append;
	}

	return $text;
}

Як працює функція

  1. Обрізає до певної кількості символів. Вказується у параметрі maxchar.

  2. Розуміє тег <!–more–> у записі. Якщо він присутній, бажана кількість символів, що виводяться, ігнорується і виводиться все що вище <!–more–> зі збереженням HTML розмітки.

  3. Можна вказати зберігати перенесення рядків або писати весь текст в один рядок. За умовчанням переноси зберігаються, якщо потрібний “суцільник” ставимо параметр autop = 0 .

  4. Можна вказати, які HTML теги не потрібно вирізати. Наприклад, ми хочемо залишити теги <strong> і <em> , тоді вказуємо їх так:save_tags=<strong><em>

  5. Функцію також можна використовувати для обрізання будь-якого тексту, який буде переданий. Для цього вказуємо текст у параметрі text.

Обрізка завжди обчислює кількість символів, а потім прибирає останні символи до пробілу. Потрібно це для того, щоб насамкінець завжди залишалося закінчене слово, а не шматок недописаного (думаю це некрасиво).

Використання

Вставляємо вказаний код у файл functions.php вашої теми. І де потрібно вивести обрізаний текст, викликаємо функцію так:

<?php echo kama_excerpt(['maxchar'=>100, 'text'=>'бла бла']); ?>

Щоб замінити стандартний the_excerpt() потрібно просто замінити the_excerpt() kama_excerpt () . Все це має бути всередині циклу WordPress .

ВАЖЛИВО: Параметр textпри заміні the_excerpt() ; вказувати не треба!

Приклад використання функції для обрізання будь-якого тексту:

$str = "Функція [foo]some text[/foo] [foo]some text[/foo] обрізання тексту для Worpress,
можна використовувати [foo url='bar'] та інших движках.";

echo kama_excerpt(['text'=>$str, 'maxchar'=>70]);

Отримаємо:

<p>Функцію обрізки тексту для Worpress,<br />
можна застосовувати і на інших...</p>

При обрізанні функції тексту, що передається, спрацьовує тільки та частина функції яка необхідна (ніяких зайвих операцій).

Дуже простий приклад обрізки тексту

Якщо ви не хочете використовувати функцію і вам потрібно просто обрізати текст не збереження html теги та інше, то можна скористатися таким коротким рядком усередині циклу WordPress:

<?php
$maxchar = 152;
$text = strip_tags( get_the_content() );
echo mb_substr($text, 0, $maxchar);
?>

152 – це кількість символів, що залишаються.

Або

Використовуйте функцію wp_trim_words() .

Залишити коментар

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *