0.00
84 читателя, 77 топиков

Мелкие плюшки для админки

Отказавшись от использования плагина ManagerManager стали всплывать некоторые недостающие моменты, которые решились достаточно легко.
Во первых использованием плагина templatesEdit2, а во вторых созданием плагина на событие OnDocFormPrerender.
Ниже речь пойдёт о втором плагине.

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

Ctrl+S в ресурсах

Добрый вечер,
сидел, ковырял сайтик на ево и по привычке (от REVO) после изменений в ресурсах нажимал на CTRL + S и ничего полезного не происходило.

Подумал, погуглил и родился мини плагин на событие OnDocFormRender


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

Поиск дубликатов документов и их удаление

Иногда появляется необходимость в обширных каталогах найти одинаковые документы. При условии что вложенность большая и pagetitle документов не обязательно уникальны.

Моей задачей было удалять старые документы с идентичными ключевыми словами

Источник проблемы:
Сайт с огромным каталогом, импорт объектов из внешнего файла.
Импорт автоматизирован и повешен на крон. При импорте запрашиваются координаты объекта у яндекса, в следствии чего скрипты зависают, а объекты могут продублироваться.

Вот такой код, при необходимости повешенный на крон, успешно и без особых нагрузок корректно удаляет дублирующие документы c идентичными заголовками и ключевыми словами


<?php
	@ini_set("display_errors","1");
	error_reporting(E_ALL);	

	define('MODX_API_MODE', true);
	include_once(dirname(__FILE__)."/index.php");
	$modx->db->connect();
	if (empty ($modx->config)) {
		$modx->getSettings();
	}

	require_once($basePath.'assets/libs/resourse.php');
	$resourse=resourse::Instance($modx);

	$rsQuery = 'SELECT COUNT(c.id) AS cnt, c.pagetitle, t.value FROM '.$modx->getFullTableName('site_content').' c ';
	$rsQuery.= 'INNER JOIN '.$modx->getFullTableName('site_tmplvar_contentvalues').' t ON t.contentid = c.id AND t.tmplvarid = 3 '; // JOIN уникального ТВ параметра
	$rsQuery.= 'GROUP BY c.pagetitle, t.value HAVING COUNT(c.id) > 1 ORDER BY c.pagetitle';
	$res = $modx->db->query($rsQuery);
	
	if ($res && mysql_num_rows($res) > 0){
		while($i = mysql_fetch_assoc($res)){
			echo("<p>{$i['cnt']} - {$i['pagetitle']} - {$i['value']}</p>");
			$cnt = $i['cnt'] - 1;
			$sres = $modx->db->query("SELECT contentid FROM ".$modx->getFullTableName('site_tmplvar_contentvalues')." WHERE value = '{$i['value']}' ORDER BY contentid ASC LIMIT $cnt");
			if ($sres && mysql_num_rows($sres) > 0){
				while($z = mysql_fetch_assoc($sres)){
					echo("<p>Must-delete = {$z['contentid']}</p>");
					$resourse->delete($z['contentid']);
				}
			}
		}
	}
		
?>


*Код легко расширяется на учёт нескольких ТВ параметров.

Возможно кому-то данный пример будет полезен при решении его задач.

Оптимизация jpg-картинок

Гуглосервис PageSpeed Insights рекомендует «проводить базовую и расширенную оптимизацию всех изображений… При расширенной оптимизации проводится сжатие файлов JPEG и PNG (без потерь).»

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

[EVO] Ошибка при большом обьёме данных в multiTv

Если у кого бывала ситуация когда вы набиваете multiTv данными, и на определённом моменте после сохранения, ресурс больше не открывается — зайдите в phpmyadmin, в таблице modx_site_tmplvar_contentvalues поменяйте тип поля value с TEXT на MEDIUMTEXT.

Как сделать несколько меток со своими изображениями на сайте с помощью Яндекс.Карты API 2.1

Благодаря помощи местных мастеров своего дела решил топик оформить как пример использования API Яндекс карт. В поиске самого Яндекса много информации, но путного нет ничего. Если нужно на карте сделать несколько меток со своим изображением надо делать следующее:

Шаг 1


Подключаем API Яндекса между тэгами ...

<script src="http://api-maps.yandex.ru/2.1/?lang=ru_RU" type="text/javascript"></script>


Шаг 2


В самом шаблоне сайта, в выводимой области вставляем вывод карты:


<div id="map" style="width: 100%; height: 498px"></div>


Шаг 3


Сам код с метками. Выкладываю на своём примере, надо было по Москве 3 метки гостиниц поставить со своим дизайном:


<script type="text/javascript">
ymaps.ready(init);

function init () {

var myMap = new ymaps.Map("map", {
                center: [55.6938,37.6001],
                zoom: 11,
				controls: ['zoomControl']
            }); 


var myGeoObjects = [];
        
        myGeoObjects[0] = new ymaps.Placemark([55.6740,37.7333],{
				clusterCaption: 'Заголовок', 
			//balloonContentBody: 'Текст в балуне',
				},{
				// Необходимо указать данный тип макета.
				iconLayout: 'default#image',
				iconImageHref: 'images/pointer_3.png',
				// Размеры метки.
				iconImageSize: [151, 41],
				// Смещение левого верхнего угла иконки относительно
				// её «ножки» (точки привязки).
				iconImageOffset: [-3, -42]
				});
        
        myGeoObjects[1] = new ymaps.Placemark([55.6990,37.7377],{
				clusterCaption: 'Заголовок', 
			//balloonContentBody: 'Текст в балуне',
				},{
				// Необходимо указать данный тип макета.
				iconLayout: 'default#image',
				iconImageHref: 'images/pointer_2.png',
				// Размеры метки.
				iconImageSize: [176, 52],
				// Смещение левого верхнего угла иконки относительно
				// её «ножки» (точки привязки).
				iconImageOffset: [-23, -42]
		});
	
        myGeoObjects[2] = new ymaps.Placemark([55.7377,37.6501],{
				clusterCaption: 'Заголовок', 
			//balloonContentBody: 'Текст в балуне',
				},{
				// Необходимо указать данный тип макета.
				iconLayout: 'default#image',
				iconImageHref: 'images/pointer_1.png',
				// Размеры метки.
				iconImageSize: [165, 40],
				// Смещение левого верхнего угла иконки относительно
				// её «ножки» (точки привязки).
				iconImageOffset: [-16, -42]
		});
        
var clusterIcons=[{
        href:'/images/pointer.png',
        size:[31,40],
        offset:[0,0]
}];
        
   var clusterer = new ymaps.Clusterer({
        clusterDisableClickZoom: false,
        clusterOpenBalloonOnClick: false,
        // Устанавливаем стандартный макет балуна кластера "Карусель".
        clusterBalloonContentLayout: 'cluster#balloonCarousel',
        // Устанавливаем собственный макет.
           //clusterBalloonItemContentLayout: customItemContentLayout,
        // Устанавливаем режим открытия балуна. 
        // В данном примере балун никогда не будет открываться в режиме панели.
        clusterBalloonPanelMaxMapArea: 0,
        // Устанавливаем размеры макета контента балуна (в пикселях).
        clusterBalloonContentLayoutWidth: 300,
        clusterBalloonContentLayoutHeight: 200,
        // Устанавливаем максимальное количество элементов в нижней панели на одной странице
        clusterBalloonPagerSize: 5
        // Настройка внешего вида нижней панели.
        // Режим marker рекомендуется использовать с небольшим количеством элементов.
        // clusterBalloonPagerType: 'marker',
        // Можно отключить зацикливание списка при навигации при помощи боковых стрелок.
        // clusterBalloonCycling: false,
        // Можно отключить отображение меню навигации.
        // clusterBalloonPagerVisible: false
    });

clusterer.add(myGeoObjects);
myMap.geoObjects.add(clusterer);
}
</script>


Пример карты можно посмотреть тут www.project-i.ru/contacts.html

Нашёл пару полезных линков:
api.yandex.ru/maps/tools/getlonglat/ — криво определяет
u-karty.ru/opredelenie-koordinat-na-karte-yandex — адекватный поиск
api.yandex.ru/maps/jsbox/2.1/placemark

Огромное спасибо за наставления 118RUS и webber

Ajax. Метод №3

Вкратце о раннее рассказанных методах.
1) Отправляем ajax запрос на туже страницу где мы находимся, а с ответа в нужном html теге вырезаем результат
+ простота
— скорость
— необходимость вырезать из ответа нужное
2) Через index-ajax.php Урок или на прямую на php файл
+ скорость
— необходимость подготовки скриптов их прописыванию
— правка кода через фтп
— необходимо иметь заготовку
3) Тут подробнее. Данный метод у некоторых людей поменяет стиль программирования в МОДх ))))

— создайте плагин AJAX с кодом

switch($_GET['q']){	
	case 'liked':
	    echo $_POST['value'].'-OK';  //вот тут код отработки вашего кода
            // выведим просто значение $_POST['value'] 
	break;
}
die();


— выставите его на событие OnPageNotFound

Все. Заготовка готова. Такой код запоминается на раз-два-три.
Самое интересное как этим пользоваться. Еще не догадались???? ))))

в консоли firebug давайте потестим как оно работает


$.ajax({
    url:'liked',
    type:'post',
    data:{
        value:1
    }
})


Ответом сервера будет «1-ОК» )) Все работает…

Для тех кому интересен принцип:
— идёт запрос на сервер по URL: liked
— так как его не существует (здесь вся соль) выполняется событие OnPageNotFound
— наш плагин как раз на данном событии
— .htaccess MODx преобразует frienly url в переменную которую отсылает GET параметром на index.php — потому используем $_GET['q'] для определения action

И что мы емеем. Для разных action мы просто прописуем их в case '':. на эти url шлем запросы.

+ скорость
+ простота (может и не с первого раза, но гарантирую что вы подсядите)

Сниппет для скрытия кода от посторонних

Название: administration
Использовать нужно то, которое будет удобно для постоянного использования.
Категория: 01. System
Например. Можно по русски. 01 — для сортировки удобно, по крайней мере в evo.
Код:
<?php
if(isset($_SESSION['mgrValidated'])){
    return $then;
}
?>


Использование:
[!administration?then=`Привет! Как жизнь!`!]
[[!administration?then=`Привет! Как жизнь!`]]


Всё очень просто.

Посткриптум: Только сейчас заметил, что код не отличается в EVO и REVO :)

Замена стандартного поиска

Для поиска в админке я использую Doc Finder 1.6
Чтобы не лазить постоянно в раздел Модули, а попадать в поиск сразу при нажатии на меню Поиск делаем простенький плагин

Doc Finder Redirect
if ($action==71) {
	if ($moduleid = $modx->db->getValue($modx->db->select('id', $modx->getFullTableName('site_modules'), 'name LIKE \'%Doc Finder%\''))) {
		$modx->sendRedirect(MODX_MANAGER_URL . "index.php?a=112&id={$moduleid}");
	}
}

вешаем на событие OnManagerPageInit