Максим Кузнецов

Максим Кузнецов

Был в сети 04 августа 2021, 21:51
Заказы принимаю
Это решение так себе, т.к. при пагинации скрытые элементы просто не будут отображены пользователю, но все равно будут учитываться при подсчете — в итоге на каждой странице будет отображено разное количество видео.

Вообще, конкретно в вашем случае, самый правильный вариант будет примерно таким:
&where=`{"video:LIKE": "%youtube%"}
— при условии, что в тв-поле «video» у вас хранится полная ссылка до видео.

UPD: как альтернатива — нужно проверять тв-поле на то, чтобы оно было !=NULL и !="", т.к. до первого заполнения тв-поля его не существует в принципе в таблице, а после первого заполнения и очищения значения поле уже есть, но оно пустое.
Если задача — избавиться от гет-параметров в пользу чпу, то примерно так:
1. В чанках оформления кнопок фильтров прописываем адрес в виде ссылки, например так:
<label>
	<a href="[[~2]]/[[+value]]" [[+checked:is=``:then=``:else=` active`]]> [[+title]]</a>
</label>
где 2 — вымышленный путь до страницы каталога site.ru/catalog/

2. Реализуем
кастомную маршрутизацию, с помощью которой страницы вида site.ru/catalog/лофт/ будет подставлять нужную страницу и вбивать желаемый гет-параметр. Альтернативно можно передавать не гет-параметр, а плейсхолдер, который впоследствии вставлять в &where сниппета, отображающего товары.
Не особо. Ну, точнее, нагружаем, но, во-первых, только подходящие по критерию ресурсы (свежесозданные документы, у которых есть картинка и которые подходят по типу шаблона), а во-вторых, на крайне незначительные значения (можете замерить, думаю, на хорошем хостинге будет что-нибудь в пределах 0.1 секунд).

Как альтернатива, можете на то же событие и с теми же условиями самолично перехватывать через POST значение нужной формы с картинкой, грузить ее и записывать путь в тв-поле.
Ну, если нужно быстрое решение и нет желания копаться в 2file, то предлагаю решить вопрос плагином:

<?php
	if ($modx->event->name == 'OnDocFormSave' && $mode == 'new') {
		$template = $resource->get('template');
		
		if ($template == айди_нужного_шаблона_ресурсов_которые_создаются) {
			$image = $resource->getTVValue('название_тв_поле_куда_сохраняется_картинка');
			
			if (strlen($image) > 0 ) {
				list($image,) = explode('|', $image);
				
				//на этом месте мы получаем простое название файла (123.jpg)
				
				$image = '/прописываем_полный_путь_до_папки_с_картинками/' . $image;
				
				$resource->setTVValue('название_тв_поле_куда_сохраняется_картинка', $image);
				
			}
			
		}
	
		
		$resource->save();
	}

+ включить на событие OnDocFormSave и добавить ограничивающих условий по вкусу.
Вообще, выглядит так, будто проблема с самим formit2resource/2file.
На вашем месте, я бы подошел к вопросу с другой стороны: я так понимаю, что formit2resource — модуль для создания страниц с админки + рассылка?

Может, проще создавать страницы через ticketForm + совершать рассылку плагином? В ticketForm уже по-умолчанию есть удобная форма для загрузки изображений, но если она не подходит — всегда можно решить задачу через плагин или платные аналоги загрузчиков.
Меняем:
foreach($tags_list as $key => $value) {
		$result  .= $pdoTools->getChunk($tpl, array(
			'tag' => $key,
			'count' => $value,
			'tags_page' => $tags_page
		));
	}

На:
$counter = 1;
	if (!isset($limit)) {
		$limit = 10;
	}

	foreach($tags_list as $key => $value) {
		if ($counter <= $limit) {
			$result  .= $pdoTools->getChunk($tpl, array(
				'tag' => $key,
				'count' => $value,
				'tags_page' => $tags_page
			));

			$counter = $counter + 1;
		}
	}
+ добавить в вызов сниппета параметр &limit.
Вот так:
//...
	//до этих строк изменений нет

	$result = '';

	$tags_list = array();

	foreach($tags as $tag) {
		$key = $tag['value'];
		
		if (array_key_exists($key, $tags_list)) {
			$tags_list[$key] = $tags_list[$key] + 1;
		}
		else {
			$tags_list[$key] = 1;
		}
	}
	
	asort($tags_list);
	$tags_list = array_reverse($tags_list, true);

	$result = '';

	foreach($tags_list as $key => $value) {
		$result  .= $pdoTools->getChunk($tpl, array(
			'tag' => $key,
			'count' => $value,
			'tags_page' => $tags_page
		));
	}
	
	return $result;

— в таком варианте результат будет отсортирован от самых используемых тегов к наименее.
Вряд ли это сработает — данный сниппет возвращает результат единым куском. Нужно заменить процесс формирования $tags_list, чтобы ключом заносилось наименование тега, а значением — количество использований. После чего отсортировать массив по krsort(); и точно также вывести результат.
Упс) Извиняюсь — для себя я реализовал теги в виде site.ru/tag/тег/ через кастомную маршрутизацию, поэтому и такая ссылка. Просто замените чанк на что-нибудь в духе:

href="{$tags_page}?tag={$tag | replace : " " : "%20"}/"

Что же до подсчета кол-ва использований, то примерно так:
<?php
	$pdoTools = $modx->getService('pdoTools');
	$TvSuperSelect = $modx->getService('tvsuperselect', 'tvsuperselect', MODX_CORE_PATH . 'components/tvsuperselect/model/tvsuperselect/');
	if (!$TvSuperSelect) {
		$modx->log(xPDO::LOG_LEVEL_ERROR, 'Не удалось загрузить TvSuperSelect');
		return;
	}

	$q = $modx->newQuery('tvssOption');
	$q->select('value, tv_id');
	$q->where(array(
		'tv_id' => $tv_id
	));
	
	if ($q->prepare() && $q->stmt->execute()) {
		$tags = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
	}
	
	$result = '';
	
	$tags_list = array();
	$tags_count_list = array();

	foreach($tags as $tag) {
		if (in_array($tag['value'], $tags_list)) {
			$key = array_search($tag['value'], $tags_list);
			
			$tags_count_list[$key] = $tags_count_list[$key] + 1;
		}
		else {
			array_push($tags_list, $tag['value']);
			array_push($tags_count_list, 1);
		}
	}
	
	$result = '';

	foreach($tags_list as $key => $value) {
		$result  .= $pdoTools->getChunk($tpl, array(
			'tag' => $value,
			'count' => $tags_count_list[$key],
			'tags_page' => $tags_page
		));
	}
	
	return $result;
— осталось только добавить сортировку массива по вкусу.)
Ну и в чанк добавить плейсхолдер [[+count]] для отображения
С минимальным функционалом, облако тегов к компоненту можно реализовать следующим способом:

1. Создаем сниппет (tags.list):
<?php
	$pdoTools = $modx->getService('pdoTools');
	$TvSuperSelect = $modx->getService('tvsuperselect', 'tvsuperselect', MODX_CORE_PATH . 'components/tvsuperselect/model/tvsuperselect/');
	if (!$TvSuperSelect) {
		$modx->log(xPDO::LOG_LEVEL_ERROR, 'Не удалось загрузить TvSuperSelect');
		return;
	}

	$q = $modx->newQuery('tvssOption');
	$q->groupby('value');
	$q->select('value, tv_id');
	$q->where(array(
		'tv_id' => $tv_id
	));
	
	if ($q->prepare() && $q->stmt->execute()) {
		$tags = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
	}
	
	$tags_page = $modx->makeUrl($tags_page, '', '', 'full');
	
	foreach($tags as $tag) {
		$result  .= $pdoTools->getChunk($tpl, array(
			'tag' => $tag['value'],
			'tags_page' => $tags_page
		));
	}
	
	return $result;

2. Создаем чанк для отображения кнопки тега (tags.list.item):
<a href="{$tags_page}{$tag | replace : " " : "%20"}/">{$tag}</a><br />

3. Вызываем созданный сниппет:
{$_modx->runSnippet('!tags.list', [
	'tv_id' => 5,
	'tpl' => 'tags.list.item',
	'tags_page' => 99
])}

При желании можно добавить подсчет использований каждого тега, убрав $q->groupby('value') и добавив счетчик внутри цикла.
При наличие собственных плагинов на событие «OnBeforeDocFormSave» tvSuperSelect возвращает ошибку:
/home/(путь)/components/tvsuperselect/tv/output/

— при том, что по отдельности как дополнение, так и плагин срабатывают корректно.
Без оптимизации — будет, но не слишком ощутимо. При 300к+ разница уже становится ощутимей. Ну и дополнительным фактором является функционал сайта — поиск, выборки с фильтрацией и тому подобное без дополнительных настроек начнут просядать.