Несколько изображений к товару средствами модуля Фотогалереи

Материал из Umicms
Перейти к:навигация, поиск

Актуально для версии 2.9.5

Задача

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

Решение

Задачу можно решить средствами модуля "Фотогалереи", ниже дан пример.

Вариант 1

1) Создадим в типе данных, к которому относится товар, поле типа ссылка на дерево:

Symlink field.png

2) Создадим товар с этим типом данных и заполним созданное поле в карточке товара страницами фотографий:

Symlink page.png

3) Теперь осталось это вывести, вывод в tpl есть в статье Добавление_нескольких_фотографий_к_описанию_объекта_каталога, второй вариант. В xslt же все еще проще, у нас будет примерно следующий xml документ, который нужно обработать:

<group id="5585" name="kartinki">
	<title>Картинки</title>
	<property id="979" name="pictures" type="symlink">
		<title>Фотографии</title>
		<value>
			<page id="5316" parentId="5315" link="/testovyj_fotoalbom/fotografiya_1/" is-active="1" object-id="5733" type-id="74" type-guid="photoalbum-photo" update-time="1395411568" alt-name="fotografiya_1" xlink:href="upage://5316">
				<basetype id="46" module="photoalbum" method="photo">Фотография</basetype>
				<name>Фотография 1</name>
			</page>
			<page id="5317" parentId="5315" link="/testovyj_fotoalbom/photografiya_2/" is-active="1" object-id="5734" type-id="74" type-guid="photoalbum-photo" update-time="1395411993" alt-name="photografiya_2" xlink:href="upage://5317">
				<basetype id="46" module="photoalbum" method="photo">Фотография</basetype>
				<name>Фотография 2</name>
			</page>
			<page id="5318" parentId="5315" link="/testovyj_fotoalbom/fotografiya_2/" is-active="1" object-id="5735" type-id="74" type-guid="photoalbum-photo" update-time="1395411640" alt-name="fotografiya_2" xlink:href="upage://5318">
				<basetype id="46" module="photoalbum" method="photo">Фотография</basetype>
				<name>Фотография 3</name>
			</page>
			<page id="5319" parentId="5315" link="/testovyj_fotoalbom/fotografiya_4/" is-active="1" object-id="5736" type-id="74" type-guid="photoalbum-photo" update-time="1395411634" alt-name="fotografiya_4" xlink:href="upage://5319">
				<basetype id="46" module="photoalbum" method="photo">Фотография</basetype>
				<name>Фотография 4</name>
			</page>
			<page id="5320" parentId="5315" link="/testovyj_fotoalbom/fotografiya_5/" is-active="1" object-id="5737" type-id="74" type-guid="photoalbum-photo" update-time="1395411658" alt-name="fotografiya_5" xlink:href="upage://5320">
				<basetype id="46" module="photoalbum" method="photo">Фотография</basetype>
				<name>Фотография 5</name>
			</page>
			<page id="5321" parentId="5315" link="/testovyj_fotoalbom/fotografiya_6/" is-active="1" object-id="5738" type-id="74" type-guid="photoalbum-photo" update-time="1395411690" alt-name="fotografiya_6" xlink:href="upage://5321">
				<basetype id="46" module="photoalbum" method="photo">Фотография</basetype>
				<name>Фотография 6</name>
			</page>
		</value>
	</property>
</group>

Обработать это дерево можно с помощью следующей конструкции:

<div style="max-width: 300; max-height: 300;">
	<ul class="bxslider">
		<xsl:for-each select="./page/properties/group[@name = 'kartinki']/property[@name = 'pictures']/value/page">
			<li>
				<xsl:apply-templates select="document(concat('udata://system/makeThumbnail/(.', document(concat('upage://', ./@id,  '.photo'))//value, ')/200/auto'))"/>
			</li>
		</xsl:for-each>
	</ul>
</div>

и шаблона, знакомого нам по статье Несколько_изображений_к_товару_средствами_протокола_ufs (bxslider мы берем оттуда же):

<xsl:template match="udata[@module = 'system' and @method = 'makeThumbnail']">
	<img src="{src}"/>
</xsl:template>

Плюсы

  • Легко реализовать в административном интерфейсе
  • Легко вывести на сайте

Минусы

  • Нельзя добавить дополнительное изображение через eip
  • Для создания фотографии нужно идти в другой модуль, это очень долго

Кастомизация административного интерфейса

Попробуем решить последний минус и облегчить жизнь пользователю, то есть будет нужно:

  • Дать возможность создать фотографию через карточку товара.

Пример кастомизации даем ниже.

1) Создадим в директории /styles/skins/mac/data/modules/catalog файл form.modify.custom.xsl следующего содержания:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xsl:stylesheet SYSTEM "ulang://common">
<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:umi="http://www.umi-cms.ru/TR/umi"
	xmlns:php="http://php.net/xsl"
	>
	
	<xsl:template match="field[@type = 'symlink']" mode="form-modify">
		<xsl:choose>
			<xsl:when test="@name = 'pictures'">
				<h3>Прикрепить фотографию:</h3>
				<div class="field symlink" id="{generate-id()}" name="{@input_name}">
					<label for="symlinkInput{generate-id()}">
						<span class="label">
							<acronym>
								<xsl:apply-templates select="." mode="sys-tips" />
								<strong><xsl:value-of select="@title" />:</strong>
							</acronym>
							<xsl:apply-templates select="." mode="required_text" />
						</span>
						<span id="symlinkInput{generate-id()}">
							<ul id="test">
								<xsl:apply-templates select="values/item" mode="symlink" />
							</ul>
						</span>
					</label>
				</div>
				<h3>Добавить фотографию:</h3>
				<xsl:variable name="filemanager">
					<xsl:text>elfinder</xsl:text>
				</xsl:variable>
				<span>
					<strong>Выберите изображение:</strong>
				</span>
				<div style="display: block;" class="field file" id="{generate-id()}" umi:input-name="photo"
					umi:field-type="img_file"
					umi:name="photo"
					umi:folder="{@destination-folder}"
					umi:file="{@relative-path}"
					umi:folder-hash="{php:function('elfinder_get_hash', string(@destination-folder))}"
					umi:file-hash="{php:function('elfinder_get_hash', string(@relative-path))}"
					umi:lang="{/result/@interface-lang}"
					umi:filemanager="{$filemanager}"
					>
					<label for="symlinkInput{generate-id()}">
						<span id="fileControlContainer_{generate-id()}">
						</span>
					</label>
				</div>
				<xsl:variable name="gen_id" select="string(concat('fileControlContainer_', generate-id()))"/>
				<xsl:variable name="sym_id" select="string(concat('symlinkInput', generate-id()))"/>
				
				<script type="text/javascript">
					$(document).ready(function(){
						$('#make_element').click(function(){
							
							$('#make_element').attr('src', "/images/cms/loading.gif");
							
							$photo_name = $('#option_name').val();
							$photo_path = $('#<xsl:value-of select="$gen_id"/> option:selected').val();
							$page_id = '<xsl:value-of select="../../../@id"/>';
							
							if($photo_name == '' || $photo_path == ''){
								$('#make_element').attr('src', "/images/cms/admin/mac/table/ico_add.gif");
								return jQuery.jGrowl('Выберите изображение и укажите его имя', {
													 'header': 'Поля не заполнены',
													 'life': 1500
													});
							}
							
							$.ajax({
								  type: "POST",
								  url: "/udata://custom/makePhoto/.json",
								  dataType: "json",
								  data: { photo_name: $photo_name,
								          photo_path: $photo_path,
										  page_id: $page_id
								  }
							}).done(function(json) {
								$('#make_element').attr('src', "/images/cms/admin/mac/table/ico_add.gif");
								$li = json.result;														
								$('#<xsl:value-of select="$sym_id"/> ul').append($li);	
								return jQuery.jGrowl('Элемент успешно добавлен, теперь можно добавить еще', {
													 'header': 'Элемент успешно добавлен',
													 'life': 1500
													});
							  })
							  .fail(function() {
								$('#make_element').attr('src', "/images/cms/admin/mac/table/ico_add.gif");
								return jQuery.jGrowl('При добавлении элемента произошла ошибка', {
													 'header': 'Ошибка',
													 'life': 1000
													});
							  })
						});
					});
				</script>
				<span>
					<strong>Укажите имя изображения:</strong>
				</span>
				<span style="display: block;">
					<input id="option_name" type="text" style="width: 45%;"/>
					<img id="make_element" src="/images/cms/admin/mac/table/ico_add.gif"/>
				</span>
			</xsl:when>
			<xsl:otherwise>
				<div class="field symlink" id="{generate-id()}" name="{@input_name}">
					<label for="symlinkInput{generate-id()}">
						<span class="label">
							<acronym>
								<xsl:apply-templates select="." mode="sys-tips" />
								<xsl:value-of select="@title" />
							</acronym>
							<xsl:apply-templates select="." mode="required_text" />
						</span>
						<span id="symlinkInput{generate-id()}">
							<ul>
								<xsl:apply-templates select="values/item" mode="symlink" />
							</ul>
						</span>
					</label>
				</div>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>

	<xsl:include href="udata://core/importSkinXsl/form.modify.xsl"/>
</xsl:stylesheet>

2) Добавим в файл /classes/modules/custom.php следующий кастомный метод:

public function makePhoto(){		
	$name = urldecode($_POST['photo_name']);
	$name = htmlspecialchars($name);		
	$path = $_POST['photo_path'];
	$page_id = $_POST['page_id'];
	
	$hierarchy_col = umiHierarchy::getInstance();
	$h_types_col = umiHierarchyTypesCollection::getInstance();
	
	$h_type_id = $h_types_col->getTypeByName("photoalbum", "photo")->getId();		
	$photo_id = $hierarchy_col->addElement($page_id, $h_type_id, $name, translit::convert($name));

	if($photo_id){
		$photo = $hierarchy_col->getElement($photo_id, true, true);
		$photo->setIsActive();
		$photo->setValue('photo', $path);
		$photo->commit();
		$page = $hierarchy_col->getElement($page_id, true, true);
		$value = $page->getValue('pictures');
		$value[] = $photo;
		$page->setValue('pictures', $value);
		$page->commit();
		$uri = $hierarchy_col->getPathById($photo_id);
		return "<li style=\"background-color: rgb(255, 255, 254);\"><a href=\"javascript:void(0);\" class=\"button\"><img src=\"/images/cms/admin/mac/tree/symlink_delete.png\" alt=\"delete\"></a><img src=\"/images/cms/admin/mac/tree/ico_photoalbum_photo.png\"><span title=\"photoalbum photo\">$name</span><a href=\"$uri\">$uri</a></li>";
	}else{
		return 'Не удалось создать фотографию';
	}
}

3) Теперь в карточке товара мы увидим следующее:

Custom adm symlink.png

Не рекомендуем добавлять в эту же группу полей еще поля типа ссылка на дерево, могут быть проблемы с версткой

Вариант 2

1) Создадим в типе данных, к которому относится товар, поле типа ссылка на дерево:

Symlink field alb.png

2) Создадим товар с этим типом данных и выберем в нем фотоальбом, в котором есть фотографии:

Symlink page alb.png

3) Теперь осталось это вывести. В tpl для этого понадобится макрос %data getProperty()%, который выведет поле типа ссылка на дерево, а в шаблоне для вывода поля нам понадобится макрос %photoalbum album()%, для вывода картинок. В xslt же все еще проще, у нас будет примерно следующий xml документ, который нужно обработать:

<group id="5585" name="kartinki">
	<title>Картинки</title>
	<property id="980" name="fotoalbom" type="symlink">
		<title>Фотоальбом</title>
		<value>
			<page id="5315" parentId="0" link="/testovyj_fotoalbom/" is-active="1" object-id="5732" type-id="73" type-guid="photoalbum-album" update-time="1395411705" alt-name="testovyj_fotoalbom" xlink:href="upage://5315">
				<basetype id="45" module="photoalbum" method="album">Фотоальбом</basetype>
				<name>Тестовый фотоальбом 1</name>
			</page>
		</value>
	</property>
</group>

Обработать это дерево можно с помощью следующего вызова (снова используется bxslider):

<xsl:apply-templates select="document(concat('udata://photoalbum/album/', ./page/properties/group[@name = 'kartinki']/property[@name = 'fotoalbom']/value/page/@id))"/>

и двух темлпейтов:

<xsl:template match="udata[@module = 'photoalbum' and @method = 'album']">
	<div style="max-width: 300; max-height: 300;">
		<ul class="bxslider">
			<xsl:for-each select="./items/item">
				<li>
					<xsl:apply-templates select="document(concat('udata://system/makeThumbnail/(.', document(concat('upage://', ./@id,  '.photo'))//value, ')/200/auto'))"/>
				</li>
			</xsl:for-each>
		</ul>
	</div>
</xsl:template>

<xsl:template match="udata[@module = 'system' and @method = 'makeThumbnail']">
	<img src="{src}"/>
</xsl:template>

Плюсы

  • Легко реализовать в административном интерфейсе
  • Фотографии можно добавлять в eip
  • Фотографии можно загружать массово через модуль "Фотогалереи"

Минусы

  • Модуль "Фотогалереи" будет забит множеством альбомов для каждого товара
  • Для создания фотоальбома нужно идти в другой модуль, это очень долго

Добавление обработчика события

Попробуем решить последний минус и облегчить жизнь пользователю, то есть будет нужно:

  • Автоматически генерировать альбом при создании товара и привязывать его к нему

Пример кастомизации даем ниже.

Для создания фотоальбома мы воспользуемся событийной моделью UMI.CMS и напишем обработчик для события systemCreateElement.

1) Добавим следующий кастомный метод в файл /classes/modules/catalog/__custom.php:

public function mkAlbum(iUmiEventPoint $event){
	if($event->getMode() === "after") {
		$page = $event->getRef("element");
		$page_type = $page->getHierarchyType();
		if ($page_type->getName() == 'catalog' && $page_type->getExt() == 'object'){
			$page_name = $page->getName();
			$page_id = $page->getId();
			$hierarchy_col = umiHierarchy::getInstance();
			$h_types_col = umiHierarchyTypesCollection::getInstance();
			$h_type_id = $h_types_col->getTypeByName("photoalbum", "album")->getId();				
			$album_id = $hierarchy_col->addElement($page_id, $h_type_id, 'Альбом для товара ' . $page_name, translit::convert('Альбом для товара ' . $page_name));
			$album = $hierarchy_col->getElement($album_id, true, true);
			$album->setIsActive();
			$album->commit();
			$page->setValue('fotoalbom', $album_id);
			$page->commit();				
		}
	}
}

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

2) В той же директории создадим файл custom_events.php следующего содержания:

<?php
	new umiEventListener('systemCreateElement', 'catalog', 'mkAlbum');
?>

и файл permissions.custom.php следующего содержания:

<?php
	$permissions = array(
		'tree' => array(),
		'view' => array('mkAlbum')
	);
?>

3) Теперь при создании товара через административную панель будут происходить следующие действия:

  • Будет создаваться фотоальбом с именем "Альбом для товара <имя_товара>"
  • Альбом будет добавлять в страницу товара, в поле типа ссылка на дерево со строковым идентификатором 'fotoalbom'
  • Добавленный фотоальбом по иерархии будет дочерним к странице товара