0.00
97 читателей, 75 топиков

[REVO] Удаление старых изображений. Скрипт

Данный скрипт позволяет удалять изображения с сервера, которые уже не используются в работе системы.

1) Скрипт работает! только с tv параметрами.
2) Не является плагином или сниппетом

Настройки:

1) Настраиваем подключение к БД
$host = ''; //Database host
$user = ''; //User
$pass = ''; //Password
$dbname = ''; //Database name


2) Указываем имя таблицы со значениями tv параметров
$table_name = 'revo_site_tmplvar_contentvalues'; //Table name


3) Указываем id tv параметра который отвечает за изображения. При этом скрипт обрабатывает как одиночные так и мультизагруженные изображения например через MIGX
$tmplvarid = ''; // Required value for tmplvarid


4) Указываем имя папки с изображениями. Необходимо учесть путь о корня. Также прошу обратить внимание что данная версия скрипта не смотрит сквозь вложенные папки.
$folder_name = ''; //FoНастрlder with images


5) Настраиваем работу скрипта по крону.

Прошу учесть что вся работа скрипта проверялась на vds при 20000 изображений. При этом было удалено порядка 9000 устаревших файлов.

<?php
$host = 'localhost'; //Database host
$user = ''; //User
$pass = ''; //Password
$dbname = ''; //Database name
$table_name = 'revo_site_tmplvar_contentvalues'; //Table name
$tmplvarid = ''; // Required value for tmplvarid
$folder_name = 'images'; //FoНастрlder with images


$connect = mysqli_connect($host, $user, $pass);

//Get files list
$files_list = scandir($folder_name);
unset($files_list[0]);
unset($files_list[1]);
$files_list_accoc = array_flip($files_list);
mysqli_set_charset($connect, "utf8");
echo "<p>Files list:</p>";
$i = 1;
foreach($files_list as $value)
	{
	echo $i . ". " . $value . "
";
//Searching for files in database
	$q = "SELECT * FROM " . $dbname . "." . $table_name . " WHERE tmplvarid=" . $tmplvarid . " AND value like '%" .$value. "%'";
	$result = mysqli_query($connect, $q);
	$rows = mysqli_num_rows($result);
//Remove from list if exist
	if ($rows == 1)
		{
		unset($files_list_accoc[$value]);
		}
	$i++;
	}
mysqli_close($connect);
$files_list_trash = array_flip($files_list_accoc);
echo "<hr><p>Useless files:</p>";
$ii = 1;
//Removing of useless files
foreach($files_list_trash as $value)
	{
	$command = "rm -rf " . $folder_name . "/" . $value;
	echo $ii .". '" .$command. "'
"; 
	//Test it, before uncomment next line
	exec($command);
	$ii ++ ;
	}
?>


removeOldImage git

Данное решение используется для узко-направленных задач и не всем может подойти.

eForm - ограничение максимального количества символов и вывод сообщения об ошибке

По аналогии с проверкой размера файла, сделал проверку количества вводимых символов в textarea с выводом сообщения.
Вызов формы:
[!validatetextsize!]
[!eForm? ... &eFormOnValidate=`validatetextsize`!]

в чанке &tpl:
<textarea name="text" eform="Обращение ::0"></textarea>

сниппет validatetextsize:
<?php
function validatetextsize($fields,&$vMsg,&$rMsg){
       if (strlen(htmlspecialchars($fields['text']))>2500){//имя элемента массива совпадает с аттрибутом name
		$vMsg[]='Превышен максимальный размер сообщения 2500 символов';
	}
        return; 
};
?>

не уверен в необходимости использования тут htmlspecialchars(), но на всякий случай поставил.
правки и дополнения приветствуются

UPDATE
то же самое, но с добавлением класса для подсветки невалидного поля с помощью css
<?php
function validatetextsize($fields,&$vMsg,&$rMsg,&$rClass){
       if (strlen(htmlspecialchars($fields['text']))>2500){//имя элемента массива совпадает с аттрибутом name
		$vMsg[]='Превышен максимальный размер сообщения 2500 символов';
                $rClass['text'] = 'invalid';
	}
        return; 
};
?>


UPDATE 2
для сайтов в UTF-8 кодировке рекомендуется использовать mb_strlen() для подсчета кириллических символов

[EVO] eForm - вывод сообщения о превышении допустимого размера файла

Долго искал, готовых решений не нашел, на основании этого топика сделал простое решение. Вызов формы:
[!validatefilesize!]
[!eForm? ... &eFormOnValidate=`validatefilesize`!]

в чанке &tpl:
<input type="file" name="testfile" eform="Файл :file:0">

сниппет validatefilesize:
<?php
function validatefilesize($fields,&$vMsg,&$rMsg){
	if ($_FILES['testfile']['size'] > 1024){  //имя поля и максимальный размер файла    
		$vMsg[]='Размер файла больше допустимого';
	}
	return; 
};
?>

думаю много кому пригодится, правки и дополнения приветствуются.

[EVO] Установка заголовка Last-Modified и 304 Not Modified для поисковых систем (Update от 15.11.2014)

Зачем нужен Last-Modified

HTTP заголовок Last-Modified сообщает клиенту время последнего изменения страницы (объекта). Если клиент (браузер, поисковый робот) получил заголовок Last-Modified, то при следующем обращении к адресу, при условии, что страница (объект) есть в локальном кеше, он добавит вопрос If-Modified-Since (не изменилась ли страница после даты, полученной в Last-Modified). В свою очередь сервер, получив запрос If-Modified-Since должен сверить полученную временную метку с временем последнего изменения страницы и, если страница не изменялась ответить 304 Not Modified.
Если страница не изменилась, то сервер прекратит передачу данных после отправки заголовков с кодом 304 Not Modified, тело страницы, изображения и другие объекты передаваться не будут.
Для поисковых же систем это полезно тем что за один и тот же промежуток времени робот успеет проиндексировать больше новых страниц на вашем сайте, потому что не будет загружать страницы которые не поменялись.

Читать дальше →

[REVO] Какие параметры сортировки есть у Gallery?

Какие параметры сортировки есть у Gallery? Никак не могу найти какие значения может принимать параметр sort. Конкретно мне необходимо выводить изображения по цифрам по порядку, например: 01-ОП, 02-ОП, 03-ОП…

[EVO] Автозамена названия чанков и TV в шаблонах, чанках, TV и содержимом ресурсов

Ковыряя японскую ветку MODX, нашел такой функционал — при изменении названия чанка или TV, автоматом обновлялись шаблоны, чанки, TV и содержимое ресурсов.
Вот накидал плагин
<?php
/**
 * Chunk&TV-sync
 *
 * Автозамена названия чанков и TV в шаблонах, чанках, TV и содержимом ресурсов
 *
 * @category    plugin
 * @version     0.1
 * @internal    @events         OnBeforeChunkFormSave,OnBeforeTVFormSave
 * @internal    @properties     
 */
 
if (!defined('MODX_BASE_PATH')) { die('HACK???'); }
$prefix=$this->db->config['table_prefix'];
switch ($_POST['a']) {
    case "79": // update chunk
        $was_name = $modx->db->getValue($modx->db->select('name', $prefix.'site_htmlsnippets', "id='{$id}'"));
        $name = stripslashes($_POST['name']);
        $was_name = str_replace("'", "''", $was_name);
        $name = str_replace("'", "''", $name);
        if ($name !== $was_name) {
            $modx->db->update("content=REPLACE(content,'{{{$was_name}}}','{{{$name}}}')", $prefix.'site_content');
            $modx->db->update("content=REPLACE(content,'{{{$was_name}}}','{{{$name}}}')", $prefix.'site_templates');
            $modx->db->update("snippet=REPLACE(snippet,'{{{$was_name}}}','{{{$name}}}')", $prefix.'site_htmlsnippets');
            $modx->db->update("value=REPLACE(value,    '{{{$was_name}}}','{{{$name}}}')", $prefix.'site_tmplvar_contentvalues');
            $modx->db->update("content=REPLACE(content,'{{{$was_name}:','{{{$name}:')", $prefix.'site_content');
            $modx->db->update("content=REPLACE(content,'{{{$was_name}:','{{{$name}:')", $prefix.'site_templates');
            $modx->db->update("snippet=REPLACE(snippet,'{{{$was_name}:','{{{$name}:')", $prefix.'site_htmlsnippets');
            $modx->db->update("value=REPLACE(value,    '{{{$was_name}:','{{{$name}:')", $prefix.'site_tmplvar_contentvalues');
        }
        break;
    case "302": // update TV
        $was_name = $modx->db->getValue($modx->db->select('name', $prefix.'site_tmplvars', "id='{$id}'"));
        $name = stripslashes($_POST['name']);
        $was_name = str_replace("'", "''", $was_name);
        $name = str_replace("'", "''", $name);
        if ($name !== $was_name) {
            $modx->db->update("content=REPLACE(content,'[*{$was_name}*]','[*{$name}*]')", $prefix.'site_content');
            $modx->db->update("content=REPLACE(content,'[*{$was_name}*]','[*{$name}*]')", $prefix.'site_templates');
            $modx->db->update("snippet=REPLACE(snippet,'[*{$was_name}*]','[*{$name}*]')", $prefix.'site_htmlsnippets');
            $modx->db->update("value=REPLACE(value,    '[*{$was_name}*]','[*{$name}*]')", $prefix.'site_tmplvar_contentvalues');
            $modx->db->update("content=REPLACE(content,'[*{$was_name}:','[*{$name}:')", $prefix.'site_content');
            $modx->db->update("content=REPLACE(content,'[*{$was_name}:','[*{$name}:')", $prefix.'site_templates');
            $modx->db->update("snippet=REPLACE(snippet,'[*{$was_name}:','[*{$name}:')", $prefix.'site_htmlsnippets');
            $modx->db->update("value=REPLACE(value,    '[*{$was_name}:','[*{$name}:')", $prefix.'site_tmplvar_contentvalues');
        }
        break;
}

UPD
поправил

Выборка по алфавиту с фильтрацией по букве

Хотелось, чтобы формировался список по первой букве, и список этих букв, а потом при нажатии на букву отфильтровывалось.
Все в общем на базе сниппета snippet.DLFirstChar (Группировка документов по первой букве) от Agel_Nash Спасибо ему за правку сниппета огромное!

Формируется два списка буквы(для сортировки) и сам список блоков по первой букве названия ресурса.
В принципе по запросу «фильтрация блоков с помощью jquery» в Яндексе много по этому есть.
Надо скачать отсюда тут много разных эффектов или сразу отсюда (здесь можно выбросить картинки и оставить только папки scripts и stylesheets) — копируем например в папку jqsort

На странице, где все это делаем такие вызовы:

<link href="jqsort/stylesheets/screen.css" type="text/css" rel="stylesheet" media="screen,projection" />
<script type="text/javascript" src="jqsort/scripts/jquery.js"></script>
<script type="text/javascript" src="jqsort/scripts/framework.js"></script>

<ul id="filter">
<li class="current"><a href="#">All</a></li>
[!DLFirstChar? &parents=`xxx` &idType=`parents` &orderBy=`BINARY pagetitle ASC` &tpl=`FCharTpl1` &tplOnNewChar=`FCharTplOnNew1`!]
</ul>

<ul id="portfolio">
[!DLFirstChar? &parents=`xxx` &idType=`parents` &orderBy=`BINARY pagetitle ASC` &tpl=`FCharTpl` &tplOnNewChar=`FCharTplOnNew` !]
</ul>

xxx- id папки, откуда берете документы для сортировки
Чанки:
FCharTpl
[+CharSeparator+][+OnNewChar+]<a href="[+url+]">[+pagetitle+]</a>

FCharTplOnNew
<li class="[[FCharToLower? &str=`[+char+]`]]"><h4>[+char+] <small>([+total+])</small></h4>

&tplCharSeparator=`FCharTplSeparator` этот чанк не использовал, но если кому надо, то можно включить
FCharTpl1
[+CharSeparator+][+OnNewChar+]

FCharTplOnNew1
<li><a href="#">[+char+]</a></li>

+++++++++++
Сниппет FCharToLower(делает букву строчной)

<?php
$output = $str;
$str = mb_strtolower($str);
echo $str;
?>

Как перевести заголовок страницы в ЧПУ на английском языке. Идея и исполнение для дальнейшей разработки.

Проблема

Довольно часто на сайтах можно встретить ЧПУ смешанного типа. Допустим, «site.ru/news/ekonomika/obama-prinyal-zakon.hyml»
Мы видим в этом УРЛ смешение транслита и нормального перевода. Не знаю как вам, но меня это зачастую коробит. Хочется однообразия — или везде перевод, или везде транслит.

Как поступал

Брал в файлике структуру сайта, загонял в переводчик и уже оттуда копировал-вставлял англоязычные термины в админку. Брр.

Как решить проблему

Будем писать плагин автоматического перевода pagetitle.
Итак, для начала нам нужно зайти на Яндекс.Апи переводчика и получить себе ключ.
Дальше ползём в админку MODx и создаём плагин. Я назвал его yandexTranslation. В «Системных событиях» отмечаем галочку «OnDocFormRender».
Код плагина:

global $e;
$e = &$modx->Event;
$e->output('<!-- yandexTranslation --->
<script>
    window.$j = jQuery.noConflict();
    key="ВАШ КЛЮЧ АПИ";
    source=$j("input[name=\'pagetitle\']");
    result=$j("input[name=\'alias\']");
    url=\'https://translate.yandex.net/api/v1.5/tr.json/translate\';
    function get_translate(source,result,key,debugTxt){
        if(source.val().length>0)
            {
                $j.ajax({
			type:\'POST\',
			url: url,
			cache: false,
			data:{
				key:key,
				text:source.val(),
				lang:\'ru-en\'
				},
			success:function(data){
				responseStatus=data[\'code\'];
				if (responseStatus==200)
				{
				    responseText=data[\'text\'][0];
				}
				else
				{
				    responseText=\'Error! \' + responseStatus;
				}
				re=/[^a-zа-я]/g;
                		responseText=responseText.toLowerCase();
				responseText =  responseText.replace(re,"-",responseText);
				result.val(responseText);
			},
			error: function (xhr, ajaxOptions, thrownError) {
				alert(\'Error ajax\');
			}
			});
		}
		else
		{
			source.css(\'border\',\'1px solid red\');
		}
	};
    $j(source).bind(\'blur change click\',function(){
        get_translate(source,result,key,"change");
    });			
</script>
<!-- // yandexTranslation --->');

Что делает:

При событиях blur change click на поле pagetitle отправляет аякс-запрос на сервер перевода, получает ответ, слегка форматирует его и устанавливает в поле alias
Вместо тысячи слов:

P.S.
Это не готовый модуль, а просто идея для дальнейшей разработки. Тем не менее, он упростил жизнь контент-менеджера примерно в два раза.
В светлом будущем надеюсь на подобный функционал уже в боевой версии MODx.

[EVO] Плиточная галерея из вордпресса

С таким выводом картинок я столкнулся при переносе сайта с вордпресса на MODX. Описание алгоритма найти не удалось, долго возиться с этим сайтом тоже не хотелось, поэтому я взял готовый код для вордпресса.
Получился такой сниппет для использования с MultiPhotos SimpleGallery — github.com/Pathologic/tiledphotos

Вызов сниппета:
[[tiledphotos? &width=`540` &margin=`2` &css=`1`]]

width — максимальная ширина блока, в котором выводятся картинки, margin — расстояние между картинками, css — подключает стили из вордпресса.

Дополнительно можно использовать параметр &k — это коэффициент увеличения размеров превьюшки (не знаю, зачем я его использовал) и параметр $thumbOptions — дополнительные параметры для phpthumb (по умолчанию — zc=C).

Шаблоны для вывода обрабатываются так же, как в DocLister, стартовый набор — в коде сниппета.

В шаблоне groupTpl можно задавать ширину в процентах с помощью плейсхолдера [+rel.width+]. Стили в комплекте вроде бы изменены под этот случай.

Так как картинки добываются в конечном итоге с помощью DocLister, то для пагинации и т.п. нужно использовать параметры DocLister.

Выглядит так:

Или так — зависит от ширины блока и разнообразия размеров картинок:

[EVO] Рейтинг для товара с JotX

Добрый день.
Сегодня написал сниппет который выводит рейтинг для товара с использованием JotX.
Наверняка можно лучше сделать, но на скорую руку меня вполне устроил.

Логика
Пользователь оставляя комментарий к товару оценивает его.

Использование
1. Устанавливаем JotX и правим один из трех файлов assets/snippets/jot/configs добавля, ну например select (в моем случае это tree.config.php)

[+form.guest:is=`1`:then=`
		<div class="jot-controls">
			<div class="jot-input-prepend">
				Отцените товар 
				<select name="zvezda">
					<option value="0" disabled selected>Выбор</option>
					<option value="1">1</option>
					<option value="2">2</option>
					<option value="3">3</option>
					<option value="4">4</option>
					<option value="5">5</option>				
				</select>
			</div>
		</div>
	`+]

2. Создаем сниппет show-rating

<?php
/*
* show-rating
*
* Рейтинг товара для JotX
*
* [[show-rating? &docid=`[*id*]` &customfields=`zvezda`]]
*
* &docid - ID документа
* &customfields - название кастомного поля которое было выбранно в JotX
*
* Author:
*       darksmoke from modx.im
*       dsmoke(at)ukr.net
*/

$docid= $modx->db->escape($docid); 

$res = $modx->db->query("SELECT `jot_fields`.label, `jot_fields`.content FROM `jot_content` RIGHT JOIN `jot_fields`  ON `jot_content`.`id`= `jot_fields`.`id` WHERE `jot_content`.`uparent`='". $docid ."' ");

$count = $modx->db->getRecordCount($res);

if($count >= 1) { 
	while( $row = $modx->db->getRow( $res ) ){
		if($row['label'] == $customfields)
			$r+= $row['content'];
	}
	$raiting = round($r/$count,1);  
	$output = '<div class="myraiting'.round($raiting).'"><span>рейтинг '.$raiting.'<span></div>';
} else { 
	// нет рейтинга
	$output = '<div class="myraiting0"></div>';
}

return $output;
?>

3. Вызываем JotX что бы можно было голосовать за товар
[[JotX? &config=`tree` &customfields=`zvezda`]]

4. вставляем в шаблон вывод рейтинга
[[show-rating? &docid=`[*id*]` &customfields=`zvezda`]]

С помощью css приводим результат в нужный вид.