Хак: Добавить списки в шаблонизатор для DLE

Хак: Добавить списки в шаблонизатор

Данный хак позволяет использовать один файл шаблона для вывода шаблона обертки и списка заданных элементов.
Рассмотрим с пользой на примере страницы облака тегов color.sandev.pro/tags/
Для данной страницы используется только один шаблон tagscloud.tpl в котором список тегов выводится одним тегом {tags}, который выводит уже сформированный html код прописанный в php файле. Что, согласитесь, очень неудобно когда хочется кастомизации.
Сейчас для решения данной задачи пришлось бы создавать отдельный файл шаблона tagscloud_item.tpl и в php коде создавать новый объект класса dle_template.

С помощью данного хака можно избавиться от этих 2х шагов и использовать только один обработчик и один файл шаблона. Так же можно передавать любые параметры из шаблона в обработчик.

Установка:
Открыть файл engine/classes/templates.class.php
Найти строку:
	function compile($tpl) {

Выше нее вставить:
	/**
	 * Глобальный шаблон - оболочка списка, временное хранение
	 * @var array
	 */
	private $listTpl = [];

	/**
	 * Инициализация шаблона и получение параметров
	 * @param  string $tag имя тега
	 * @return array ['tag' => 'Имя списка', 'replace' => 'область тега для дальнейшей замены', 'params' => [array]]
	 */
	public function getList($tag = '')
	{
		$tag = totranslit($tag);
		if (!$tag) {
			return;
		}
		preg_match("#\\[{$tag}(?:\?([^]]*))?\\](.+?)\\[/{$tag}\\]#is", $this->copy_template, $matches);
		if (!$matches[0]) {
			return;
		}
		$tag = 'list_' . $list;
		$this->listTpl[$tag] = [
			'data' => $this->data,
			'block_data' => $this->block_data,
			'tpl' => $this->copy_template,
		];
		$this->data = [];
		$this->block_data = [];
		$this->copy_template = $this->template = trim($matches[2]);
		parse_str($matches[1], $params);

		return [
			'tag' => $tag,
			'replace' => $matches[0],
			'params' => $params,
		];
	}

	/**
	 * Возвращение глобального шаблона и замена области тега на сформированный шаблон
	 * @param array $tag  результат функции getList
	 */
	public function setList($tag = [])
	{
		if (!$this->listTpl[$tag['tag']]) {
			return;
		}
		$this->copy_template = $this->template = $this->listTpl[$tag['tag']]['tpl'];
		$this->copy_template = str_replace(
			$tag['replace'],
			$this->result[$tag['tag']],
			$this->copy_template
		);
		$this->data = $this->listTpl[$tag['tag']]['data'];
		$this->block_data = $this->listTpl[$tag['tag']]['block_data'];
		unset($this->result[$tag['tag']]);
		unset($this->listTpl[$tag['tag']]);
	}



Простейший пример применения в PHP скрипте:
		if ($list = $tpl->getList('list')) {

			for ($i = 0; $i < 10; $i++) {
				$tpl->set('{index}', $i);
				$tpl->compile($list['tag']);
			}

			$tpl->setList($list);
			unset($list);
		}



Теперь инструкция для облака тегов.
В шаблоне tagscloud.tpl вместо тега {tags} использовать конструкцию:
			[list?limit=500&sort=count&min_count=5]
			<a href="{link}" title="{count} [declination={count}]новост|ь|и|ей[/declination] по тегу {tag}"><span class="tagname">{tag}</span><span class="tagcount">{count}</span></a>
			[/list]


Все передаваемые параметры не обязательны.
limit - общее максимальное количество тегов на страницу.
sort - тип сортировки: count (по количеству новостей в теге). По умолчанию сортировка по алфавиту.
min_count - минимальное количество новостей в теге для его отображения.


Открыть файл engine/modules/tagscloud.php
Найти строку:
		} else $sql_select = "SELECT tag, COUNT(*) AS count FROM " . PREFIX . "_tags GROUP BY tag";

Ниже нее вставить:
////////////////////////////////////////////////////
		//Получаем параметры и подгружаем шаблон списка
		$tpl_list = $tpl->getList('list');
		//Ниже формируем запрос с учетом параметров
		$sql_select = 'SELECT tag, COUNT(*) AS count FROM ' . PREFIX . '_tags GROUP BY tag';
		if (($min_count = (int)$tpl_list['params']['min_count']) > 0) {
			//Минимальное количество новостей по тегу
			$sql_select .= ' HAVING count >= ' . $min_count;
		}
		if ($tpl_list['params']['sort'] == 'count') {
			//Сортировка по количеству
			$sql_select .= ' ORDER BY count DESC';
		} else {
			//Сортировка по тегу (по алфавиту)
			$sql_select .= ' ORDER BY tag ASC';
		}
		if (($limit = (int)$tpl_list['params']['limit']) > 0) {
			//Общее количество тегов
			$sql_select .= ' LIMIT 0,' . $limit;
		}
////////////////////////////////////////////////////


Ниже найти и удалить строку (таких строки в файле 2, нужно удалить вторую):
usort ($list, "compare_tags");


Опять же чуть ниже найти строку:
			if (trim($value['tag']) != "" ) {

Ниже нее вставить:
////////////////////////////////////////////////////
				//Стандартный обработчик тегов шаблона
				$tpl->set('{link}', $config['http_home_url'] . 'tags/' . urlencode($value['tag']) . '/');
				$tpl->set('{tag}', $value['tag']);
				$tpl->set('{count}', $value['count']);

				$tpl->compile($tpl_list['tag']);
////////////////////////////////////////////////////


Далее найти строку:
		$tags = implode(", ", $tags);

Ниже нее вставить:
////////////////////////////////////////////////////
		//Возвращаем обратно глобальный шаблон и заменяет тег списка на сформированный шаблон
		$tpl->setList($tpl_list);
		unset($tpl_list);
////////////////////////////////////////////////////


Вот пример, выводится не более 100 тегов отсортированных по количеству новостей, у которых не менее 30 новостей на один тег:
[list?limit=100&sort=count&min_count=30]

Хак: Добавить списки в шаблонизатор


На этом все.
Буду рад комментариям, замечаниям и предложениям!

С уважением,
Олег Александрович a.k.a. Sander
Добавить комментарий
  • Логин
  • E-mail (не обязательно)
Повторите рисунок:
antibot
© Sander-Development. 2009-2018.
При копировании, ссылка на источник обязательна.