UMIhelp

Разработка сайта на UMI.CMS => Шаблоны XSLT => Тема начата: Rodogor от 29 Мая 2012, 21:28:27

Название: Изучаю UMI, XSLT.
Отправлено: Rodogor от 29 Мая 2012, 21:28:27
Здравствуйте. Помогите пожалуйста разобраться с XSLT шаблонами.
Я в целом только изучаю систему и разбираюсь, поэтому могу сильно ошибаться. Пожалуйста, поправьте если что.
На примере одного конкретного макроса я пытаюсь понять как в целом взаимодействовать с системой.
Сейчас в голове такая картина:
Для добавлении функционала какого-либо из модулей, нужно найти его описания http://help-dev.umi-cms.ru/. Найти макрос, который реализует нужный функционал. Если макрос должен выводить информацию – пишем шаблон <xsl:template match="udata[@module = 'МОДУЛЬ'][@method = 'метод']">, затем пишем шаблон для элементов item данного макроса.  Если макрос связан с вводом инфы -  точно так же <xsl:template match="udata[@module = 'МОДУЛЬ'][@method = 'метод']">, в описание шаблона создаём <form> </form>. К примеру, <form name="frm_editblogmsg" method="post" action="/blogs20/postEdit/{$post/pid}/do/" onsubmit="site.forms.data.save(this); return site.forms.data.check(this);"> отправляет новый пост.
Проясните пожалуйста 1) откуда взялась инфа  action, что делает …/do (интуитивно тут понятно, с фигурными скобками тоже ясно) 2) onsubmit – интуитивно понятно, что сохранить формы сайта, но хочется более подробно вчитать про такие конструкции.

Поставил такую задачу: тестовый демо-сайт demodizzy. Нужно добавить возможность пользователям создавать СВОИ блоги и видеть в users/settings созданные блоги. Использовать XSLT шаблоны.


1)Изучив документацию, я пришёл к выводу, что за добавление своих блогов отвечает %blogs20 editUserBlogs()%.
Первый трабл - Я не могу понять, как вставить TPL шаблон в %blogs20 editUserBlogs()% XSLT.
Выполняю в адресной строке udata/blogs20/editUserBlogs – получаю XML, где вижу список имеющихся блогов(скрин не делаю, ничего необычного). Выполняю blogs20/editUserBlogs – получаю Debug message for UC-pages http://my.jetscreenshot.com/12061/20120529-xx4u-80kb.jpg. Это говорит о том, что в шаблоне не описано как обрабатывать вызов этого модуля и метода. Добавляю в файл Default.xsl
<xsl:template match="result[@module = 'blogs20'][@method='editUserBlogs']" >
<xsl:apply-templates select="document('udata://blogs20/editUserBlogs')" />
   </xsl:template>
Теперь я получаю XML в теле сайта.  http://my.jetscreenshot.com/12061/20120529-hmme-114kb.jpg
Имеющийся вопросы: 1)Почему он не преобразовывается в HTML ?
Попытка ответа: Потому что нет описания для этого, необходимо добавить обрабатывание этой раздачи, т.е. шаблонизатор для module="blogs20" method="editUserBlogs", должен быть шаблон.
disable-output-escaping="yes"  тут не причём, это экранирование тегов, если уже готовый HTML выдаётся.
Я правильно понял ?
2) Смотрю как организован просмотр блогов. Предположим, я хочу добавить новое поле для блога. Добавляю поле, тип число. Просматриваю через сайт– его нет. Дописываю к адресу поста блога .xml – вижу, что новое поле таки формируется XML документом. http://my.jetscreenshot.com/12061/20120529-avhz-114kb.jpg
В голове появляется тень мыслей 1) выводятся только конкретные статичные поля 2) нужно ковырять как и где выводятся
Начинаю смотреть по коду, как организовывается вывод поста блога.  Нахожу такую строчку –
   <xsl:value-of select="document(concat('udata://blogs20/postView/',$document-page-id))/udata/content" disable-output-escaping="yes" />
concat('udata://blogs20/postView/',$document-page-id) это грубо говоря udata://blogs20/postView/95/ если 95 ID поста блога, а что возвращает в этом случае всё выражение с дописанном в конце document(…udata/content) ?
Ткните пожалуйста в читалку, это реальный пробел в моих знаниях, а голова уже кругом.
Анализируем дальше… udata://blogs20/postView возвращает пост без нового поля, которое я сам создал.  http://my.jetscreenshot.com/12061/20120529-coat-105kb.jpg
Вопрос: Как сделать так, что бы возвращались все поля ?
Я попробовал искать, где же уже есть подобный механизм… Нашёл в emarket/personal/ в персональной информации.. Смотрю код -  ссылается на users/settings: <xsl:apply-templates select="document('udata://user/settings')" />. Нахожу код этого фрагмента:
<xsl:template match="udata[@method = 'settings']">
<form enctype="multipart/form-data" method="post" action="{$lang-prefix}/users/settings_do/" id="con_tab_profile">
         <div>
            <label>
               <span>
                  <xsl:text>&login;: </xsl:text>
               </span>
               <input type="text" name="login" class="textinputs" disabled="disabled" value="{$user-info//property[@name = 'login']/value}" />
            </label>
         </div>
…… убеждаемся, что тут всё прописано статично – вот логин вывелся, &login;, что бы на разных языках подмена была… дальше статинчные поля… а вот поле расширенная информация – не статично, т.е. добавив в типе данных новое поле – оно тут появляется.
<xsl:apply-templates select="document(concat('udata://data/getEditForm/', $user-id))" />
В data/common-edit-form.xsl находим <xsl:template match="udata[@method = 'getCreateForm' or @method = 'getEditForm']"> и смотрим каким образом выводятся эти поля, которые мы добавляем сами. В файле data/properties.xsl понимаем, что там просто вычисляются значения этих полей и выводятся. <xsl:template match="property|fields/field//value">
      <xsl:value-of select="value" />
   </xsl:template>

Неужели для того, что бы автоматом выводить новые поля блога, придётся столько раскопать и сделать ? Пусть в стоящей предомной задаче это и не нужно, но в целях углублённой экскурсии в UMI CMS лишним не будет..

Название: Re:Изучаю UMI, XSLT.
Отправлено: BaceH от 29 Мая 2012, 23:33:35
начните с простого, смените дизайн "охотниц за приведениями", поменяйте структуру, почитайте документацию.
а там глядишь и станет ясно как в шаблон вызвать функцию модуля, и как в нее передать параметры. ну и "столько раскопать" уже точно не надо будет.
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 29 Мая 2012, 23:57:24
начните с простого, смените дизайн "охотниц за приведениями", поменяйте структуру, почитайте документацию.
а там глядишь и станет ясно как в шаблон вызвать функцию модуля, и как в нее передать параметры. ну и "столько раскопать" уже точно не надо будет.

Дизайн менять научился. Структуру менять тоже... Но это всё относительно.

Что касается "столько раскопать" - буду Вам благодарен, если сообщите нужное направление, а то я чувствую, что точно не туда копаю...
Название: Re:Изучаю UMI, XSLT.
Отправлено: admin от 31 Мая 2012, 08:39:29
действительно направление поиска очень интересное, радует что люди лезут в суть, хотя и временин а это придется убить больше) Насчет написанных вопросов...

1.
Цитировать
К примеру, <form name="frm_editblogmsg" method="post" action="/blogs20/postEdit/{$post/pid}/do/" onsubmit="site.forms.data.save(this); return site.forms.data.check(this);"> отправляет новый пост.
Проясните пожалуйста 1) откуда взялась инфа  action, что делает …/do (интуитивно тут понятно, с фигурными скобками тоже ясно) 2) onsubmit – интуитивно понятно, что сохранить формы сайта, но хочется более подробно вчитать про такие конструкции.

action проставлен в шаблон, так как создатели шаблона заранее знают куда надо отправить форму, чтобы произошло нужное действие (сохранение редактируемого блога). Для того, чтобы система знала какой блог редактируется надо передать его id, что и достигается за счет динамической подстановки значения $post/pid, а фигурные скобки нужны чтобы система поняла что сюда надо подставить значение из переменной post (которая определяется где-то выше) и взять из этой переменной узел pid.

do подставляется в action как дополнительный параметр к макросу %blogs20 postEdit()%. Если ты заглянешь в код данной функии (или макроса в терминологии umi) в файле /classes/modules/blog20/class.php , то увидишь там (найдя функцию public function postEdit) такой кусочек
if(!$postId) {
$iTmp = getRequest('param0');
if($iTmp) {
$postId = $iTmp;
} else {
$this->redirect(getServer('HTTP_REFERER'));
}
}
он подтягивает значение id текущего сообщения из param0. Param0, param1 и т.д это значения из строчки вызова макроса /модуль/метод/param0/param1

Там же ниже ты увидишь кусок кода начинающийся со строк...
if(getRequest('param1') == 'do') {
....

вот если if срабатывает , то выполняется блок отвечающий за сохранение изменений


onsubmit это событие которое срабатывает при отправке почты, как ты правильно заметил, оно нужно чтобы если при заполнении формы что-то пользователь не заполнил из обязательного или заполнил не верно и его выкинуло обратно, значения которые он заполнял не обнулились а восстановились из куков или сесси (уже не помню точно). Это просто js функции, их ты можешь посмотреть в файле /js/site/form.js, файл этот ты в подключаемых не увидишь, так как он подключается файлом /js/site/__common.js (заглянув в конец этого файла поймешь о чем я)

2.
Цитировать
Я не могу понять, как вставить TPL шаблон в %blogs20 editUserBlogs()% XSLT

tpl не надо встраивать в xslt это разные шаблоны. Надо просто создать свой xslt шаблон если он отсутствовал в demodizzy или если ты делаешь шаблон с нуля (для начала разбирательств лучше конечно разбираться с demodizzy)

Цитировать
Выполняю blogs20/editUserBlogs – получаю Debug message for UC-pages http://my.jetscreenshot.com/12061/20120529-xx4u-80kb.jpg. Это говорит о том, что в шаблоне не описано как обрабатывать вызов этого модуля и метода.
Все верно только ты позже создаешь шаблон для страницы
<xsl:template match="result[@module = 'blogs20'][@method='editUserBlogs']" >
<xsl:apply-templates select="document('udata://blogs20/editUserBlogs')" />
   </xsl:template>

то что это шаблон для страницы, можно понять из того что у тебя match начинается с result узла. Result узелвстречается только в xml страниц, а не в результатах работы макроса (через протокол udata), протоколов upage, uobject, usel. В итоге у тебя есть шаблон для страницы которая возвращает result с @module = 'blogs20' и @method='editUserBlogs', и в этом шаблоне ты делаешь вызов макроса через протокол udata.... и тут момент, а где шаблон для вывода результатов макроса udata/blogs20/editUserBlogs для них надо тоже создать шаблон... что-то вроде то что проиcходит для макроса %blogs20 postEdit()%
<xsl:template match="udata[@module = 'blogs20'][@method = 'postEdit']">
<xsl:variable name="post" select="document('udata://blogs20/postView/')/udata" />
<xsl:copy-of select="$post" />
<div class="add_form">
<form name="frm_editblogmsg" method="post" action="/blogs20/postEdit/{$post/pid}/do/" onsubmit="site.forms.data.save(this); return site.forms.data.check(this);">
<div class="form_element">
<label class="required">
<span><xsl:text>Тема:</xsl:text></span>
<input type="text" name="title" class="textinputs" value="{$post/name}"/>
</label>
</div>
<div class="form_element">
<label class="required">
<span><xsl:text>Сообщение:</xsl:text></span>
<textarea name="content"><xsl:value-of select="$post/content" disable-output-escaping="yes" /></textarea>
</label>
</div>
<div class="form_element">
<input type="submit" class="button" value="Сохранить" />
</div>
</form>
</div>
</xsl:template>

<xsl:template match="udata[@module = 'blogs20'][@method = 'postEdit'][error]">
<xsl:apply-templates select="error" />
</xsl:template>


3.
Цитировать
disable-output-escaping="yes"  тут не причём, это экранирование тегов, если уже готовый HTML выдаётся
Да, все верно

4.
Цитировать
Начинаю смотреть по коду, как организовывается вывод поста блога.  Нахожу такую строчку –
   <xsl:value-of select="document(concat('udata://blogs20/postView/',$document-page-id))/udata/content" disable-output-escaping="yes" />
concat('udata://blogs20/postView/',$document-page-id) это грубо говоря udata://blogs20/postView/95/ если 95 ID поста блога, а что возвращает в этом случае всё выражение с дописанном в конце document(…udata/content) ?

<xsl:value-of select="document(concat('udata://blogs20/postView/',$document-page-id))/udata/content" disable-output-escaping="yes" /> делает следующее... получает через concat подстановку динамически формируемой переменной $document-page-id содержащей id текущей страницы (допустим она равна 95) и получаем строчку udata://blogs20/postView/95. Данyая строчка попав в атрибут document (вот так она выглядит - document('udata://blogs20/postView/95')  ) вернет результат обращения к макросу %blogs20 postView(95)%. Далее к полученному xml (можешь просмотреть его отдельно чтобы понять что дальше происходит или заглянуть в документацию http://help-dev.umi-cms.ru/blogs20.postView.html#xsltDesc) применяют обычную выборку... вернее сказать берут из этого xml узел /udata/content, то есть содержимое поля content и так как поле контент содержит html теги чтобы их не экранировало добавляют disable-output-escaping="yes" атрибут

Для того чтобы вывести любое поле какой-то страницы, ты всегда можешь обратиться через протокол upage к нужной тебе странице (upage://95 например) и получишь все поля что есть в этой странице. Далее дело техники, просто вытяни его.... Если тебе надо конкретное поле "Новое поле", то в том шаблоне где у тебя стоит <xsl:value-of select="document(concat('udata://blogs20/postView/',$document-page-id))/udata/content" disable-output-escaping="yes" />
пишешь такой вызов <xsl:value-of select="document(concat('upage://',$document-page-id))/udata//property[@name='test']/value" />


P.S. Задача вывода значения произвольного поля из страницы или объекта, это тот басиз который обязательно понадобиться при разработке шаблонов на xslt. Если еще не читали, советую глянуть книгу Данила Кострова (http://www.umi-cms.ru/support/docs/xslt-umi-devbook/) там есть весь необходимый базис касающийся xslt
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 03 Июня 2012, 11:00:04
Спасибо за ответ.
Я написал пост сразу после полученного сообщения и видимо забыл нажать отправить. Сейчас зашёл и сильно удивился, что поста нет.
К моменту получения поста уже успел продвинуться и сделать некоторые успехи, а Ваш пост направил в нужное русло ещё больше.
Книгу я конечно скачал прежде чем начать ковыряться и прочитал не один раз, просто порой тяжело понять на имеющихся примерах как и что..

Сейчас вот ломаю голову с таким моментом:
На 1-ую страницу сайта нужно выводить один div, на остальные - другой.
На 1-ую страницу вывожу без проблем - <xsl:if test="result[page/@is-default='1']"> ......тырыпыры..... </xsl:if>
А как описать остальные страницы - понять не могу, т.к. у них отсутствует is-default. Можно ли как-то в XSLT проверять наличие параметров ?

Вообще правильный ли подход - использование внутри <xsl:template match="/" mode="layout"> конструкций xsl:if ? Мне что-то интуитивно кажется, что это не правильно - нужно описывать в отдельных файлах/шаблонах, для наглядности..
Есть ощущение, что это логичнее сделать через <xsl:call-template name="my_block" />
Название: Re:Изучаю UMI, XSLT.
Отправлено: admin от 03 Июня 2012, 11:32:29
суть такая... конечно если у вас есть различия между главной и внутренними то надо что-то менять

один вариант менять внутри шаблона выборочные кустrи, или через конструкции xsl:if и xsl:choose, или через создание отдельного шаблона

например первый случай будет выглядеть так
<xsl:template match="/" mode="layout">
<html>
....
<xsl:choose>
<xsl:when test="result/page/@is-default='1'">
блок который выводиться на главной
</xsl:when>
<xsl:otherwise>
блок который выводиться на всех остальных
</xsl:otherwise>
</xsl:choose>
....
</html>
</xsl:template>

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

если же у вас куча отличий то стоит уже посмотреть в сторону отдельного шаблона, тогда делаете такой финт

<xsl:template match="/" mode="layout">
<xsl:choose>
<xsl:when test="result/page/@is-default='1'">
<xsl:apply-templates select="." mode="layout_main_page" />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="layout_other_page" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template match="/" mode="layout_main_page">
<html>
...
</html>
</xsl:template>

<xsl:template match="/" mode="layout_other_page">
<html>
...
</html>
</xsl:template>

если же у вас отличия страниц выводятся в области контента, например на странице контактов надо помимо текста страницы контактов еще и вывести карту проезда, то тогда шаблон общий один, мы его не трогаем, а  идем в то место где выводяться страницы контента, то есть /xslTpls/modules/content/common.xsl

и пониже шаблона описывающего шаблон для страниц типа content
<xsl:template match="result[@module = 'content']">
<div id="page_{$document-page-id}" umi:element-id="{$document-page-id}" umi:field-name="content" umi:empty="&empty-page-content;">
<xsl:value-of select=".//property[@name = 'content']/value" disable-output-escaping="yes" />
</div>
</xsl:template>

добавляем уточняющий шаблон для страницы контакты (например ориентируясь на то что её id =33)
<xsl:template match="result[@module = 'content' and @pageId=33]">
<div id="page_{$document-page-id}" umi:element-id="{$document-page-id}" umi:field-name="content" umi:empty="&empty-page-content;">
<xsl:value-of select=".//property[@name = 'content']/value" disable-output-escaping="yes" />
                
</div>
                <img src="/images/map.jpg" /> здесь выводим карту проезда, или что там еще надо вывести
</xsl:template>
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 03 Июня 2012, 12:31:13
Благодарю за столь быстрый ответ. С Вашей помощью мысли окончательно правильно сформировываются в нужное русло.
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 05 Июня 2012, 01:22:23
А не подскажите такой момент:
Структура каталога: Автомобили-Марка-Модель.
В "модель" нужно получить ссылку на "Марка".
Необходимо использовать Upage?
Я пока начал подбираться так -
<xsl:value-of select="document(concat('upage://',page/@parentId))"/>
Это я получаю родителя. У родителя
Цитировать
<page id="5" parentId="1" link="/avtomobili/toyota1/" is-active="1" object-id="317" type-id="71" type-guid="catalog-category" update-time="1338539083" alt-name="toyota1">
link="/avtomobili/toyota1/ это то что мне нужно. Как подобраться - не могу понять... Чисто интуитивно понимаю, что нужно полученный результат рассматривать как udata и оттуда вытянуть /page/@link.. Но что-то не выходит
Название: Re:Изучаю UMI, XSLT.
Отправлено: admin от 05 Июня 2012, 02:31:10
странно что не выходит, ведь все верно описал, в итоге у тебя будет такой код
<xsl:value-of select="document(concat('upage://',page/@parentId))/udata/page/@link" />
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 05 Июня 2012, 09:30:47
Благодарю за ответ. Прошу прощения, действительно верно написано. Походу засиделся вчера.

Утро вечера мудренее.

Думаю, не мне одному понадобиться.. Что бы поиском люди нашли эти вопросы - накидаю теги:
как вывести ссылку на родительскую страницу

Собственно я сформировал так:
<a href="{document(concat('upage://',page/@parentId))/udata/page/@link}"  class="a_link"><xsl:value-of select="document(concat('upage://',page/@parentId))/udata/page/name"/></a>
Цели я добился, но не слишком ли извращённый способ ? Или это нормально ?
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 06 Июня 2012, 17:44:21
Каталог, к нему прикреплён фотоальбом.  Мне нужно при просмотре объекта каталога вывести фото (jquery карусель). Получаю url таким способом

select="document(concat('upage://',./@id))/udata/page/properties/group[@name='photo_props']/property[@name='photo']/value/@path"/>


Есть плотное ощущение, что нужно копать в сторону %photoalbum photo()% и т.п., но в описании %photoalbum photo()%  сказано, что нужно использовать upage или udata... Т.е. обратиться localhost/udata/photoalbum/photo/14 нельзя. Хотя ответ есть, выглядит вот так:
Цитировать
<udata xmlns:xlink="http://www.w3.org/TR/xlink" module="photoalbum" method="photo" generation-time="0.015039">
<id>14</id>
<name>Toyota</name>
</udata>
Название: Re:Изучаю UMI, XSLT.
Отправлено: BaceH от 07 Июня 2012, 04:54:20
select="document(concat('upage://',./@id))//property[@name='photo']/value"/>
property[@name='photo'] - property с именем photo одно, полный путь указывать не обязательно.

%photoalbum photo()% описывает отображение фотографии, при жквери этого не нужно. Последний шаблон описывающий миниатюру из album.xsl
	<xsl:template match="page" mode="photo_list">

<xsl:variable name="image_full" select="document(concat('upage://',@id))//property[@name='photo']/value" />
<a href="{$image_full}" >
<xsl:call-template name="catalog-thumbnail">
<xsl:with-param name="element-id" select="@id" />
<xsl:with-param name="field-name">photo</xsl:with-param>
<xsl:with-param name="empty">&empty-photo;</xsl:with-param>
<xsl:with-param name="width">95</xsl:with-param>
<xsl:with-param name="height">64</xsl:with-param>
</xsl:call-template>
</a>


</xsl:template>
$image_full - получаем путь к оригиналу(это если оригинал не нужно подганять под размеры)
получаем
<a href="$image_full"><img src="$image_thum" ></a>

вот такой простой у меня слайдер:)
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 07 Июня 2012, 12:17:24
Я ещё не особо хорошо умею работать с переменными, походу самое время изучить.
Благодарю за совет.

Мой слайдер получился так:

<xsl:template match="udata" mode="object-view">
..........
<div id="slides">
<div class="slides_container">
<xsl:apply-templates select=".//group[@name='foto']/property/value" mode="foto"/>
</div>

</div>
</xsl:template>


<xsl:template match="value/page" mode="foto">

<img src="{document(concat('upage://',./@id))/udata/page/properties/group[@name='photo_props']/property[@name='photo']/value}" width="570" height="270"/>
</xsl:template>
Осталось решить вопрос с разрешением изображений и будет норм. :)

У меня ещё не сформировалось окончательно понимание XSLT и порой есть ощущение, что я пишу всякий бред.

У меня есть ощущение, что я неправильно применяю шаблоны, когда мне надо вывести более одного элемента, как в этом случае. Или всё же это правильно ? Изучая демо-шаблоны я натыкался на несколько способов.

   <xsl:apply-templates select=".//group[@name='foto']/property/value" mode="foto"/> - применить шаблон к части XML документа где такие proup/@name и т.п.
Далее нужно описать как обрабатывать.
<xsl:template match="value/page" mode="foto"> я написал value/page т.к. меня интересует только @id, которое в самом-самом конце дерева. Можно было написать value и пусть к @id указывать как ./page/@id...
Название: Re:Изучаю UMI, XSLT.
Отправлено: admin от 07 Июня 2012, 14:44:40
выглядит верно, а насчет какой вариант писать, прелесть xslt, что одно и тоже действие можно сделать несколькими вариантами? ваш вариант вполне уместен)
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 07 Июня 2012, 21:25:30
Проапгрейдил карусель, теперь к объекту каталога привязывается альбом и карусель с навигацией.
Может кому поможет, кто поиском забредёт:
Карусель http://slidesjs.com/


	<xsl:template match="udata" mode="object-view">
....................
<div id="products_example">
<div id="products">
<div class="slides_container">
<xsl:apply-templates select="document(concat('udata://photoalbum/album/(',.//group[@name='foto']/property/value/page/@link,')'))/udata/items" mode="foto"/>

</div>
<ul class="pagination">
<xsl:apply-templates select="document(concat('udata://photoalbum/album/(',.//group[@name='foto']/property/value/page/@link,')'))/udata/items" mode="foto_pagination"/>

</ul>
</div>
</xsl:template>



<xsl:template match="item" mode="foto">
<a href="#" target="_blank"><img src="{document(concat('upage://',./@id))/udata/page/properties/group[@name='photo_props']/property[@name='photo']/value}" width="570" /></a>
</xsl:template>

<xsl:template match="item" mode="foto_pagination">
<li><a href="#"><img src="{document(concat('upage://',./@id))/udata/page/properties/group[@name='photo_props']/property[@name='photo']/value}" width="55" /></a></li>
</xsl:template>
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 07 Июня 2012, 23:29:40
Осознал как делать формы для XSLT шаблонов, если нет описания.
К примеру, в описание нет XSLT для %blogs20 editUserBlogs()%

Находим TPL, в нём видим:
$FORMS['blog_new_line'] = <<<END
<div style="padding-top:10px;">
<h3>Создать новый блог</h3>
<div style="padding-left:15px;">
<form id="form_%bid%_edit" method="post" action="/blogs20/editUserBlogs/%bid%/">
<input type="hidden" name="redirect" value="%current_page%" />
<label for="blog_%bid%_title">Название</label><br />
<input type="text" id="blog_%bid%_title" name="blog[%bid%][title]" style="width:99%;border:1px solid #ccc;" value="%title%" /><br /><br />
<label for="blog_%bid%_description">Описание</label><br />
<input type="text" id="blog_%bid%_description" name="blog[%bid%][description]" style="width:99%;border:1px solid #ccc;" value="%description%" /><br /><br />
<label for="blog_%bid%_friendlist">Друзья</label><br />
<select id="blog_%bid%_friendlist" name="blog[%bid%][friendlist][]" multiple="multiple" style="width:99%;height:100px;border:1px solid #ccc;">%friends%</select><br /><br />

<span style="display:block;text-align:right;"><input type="submit" value="Сохранить" /></span>
</form>
</div>
</div>
END;

Пока не ясно что за %bid%, это ведь BlogID, а у нас новый блог. Выполняем TPL шаблон, смотрим его html:

<div style="padding-left:15px;">
<form id="form_new_edit" method="post" action="http://localhost/blogs20/editUserBlogs/new/">
<input type="hidden" name="redirect" value="/users/settings/">
<label for="blog_new_title">Название111111</label><br>
<input type="text" id="blog_new_title" name="blog[new][title]" style="width:99%;border:1px solid #ccc;" value=""><br><br>
<label for="blog_new_description">Описание</label><br>
<input type="text" id="blog_new_description" name="blog[new][description]" style="width:99%;border:1px solid #ccc;" value=""><br><br>
<label for="blog_new_friendlist">Друзья</label><br>
<select id="blog_new_friendlist" name="blog[new][friendlist][]" multiple="multiple" style="width:99%;height:100px;border:1px solid #ccc;"><option value="10">admin</option><option value="518">user</option><option value="299">Гость</option></select><br><br>

<span style="display:block;text-align:right;"><input type="submit" value="Сохранить"></span>
</form>
</div>
Понимаем, что %bid%=NEW. Дальше запиливаем XSTL уже без проблем.... Разве что список друзей получить из всех пользователей, да и то если нужен.
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 09 Июня 2012, 15:35:36
Походу я упёрся в тупик с тупым шаблонизированием.
не могу решить две задачи:
1. У блогов есть теги. Нужно вывести все блоги с соответствующими тегами. Не посты блогов, а именно сами блоги.
Варианты: изучить usel или написать свой макрос. Пора ковыряться по серьёзному.
2. Новости. "Все новости-Автомобили, Недвижимость, Государство,....". Нужно вывести последние новости из всех рубрик.
Варианты: usel или написать свой марокс.
А можно выкрутиться стандартным  udata/news/lastlist/(IDленты1)(UDленты2)//10/0, а если нужно для всех ID - то можно опять же получить это всё через XSLT....
Название: Re:Изучаю UMI, XSLT.
Отправлено: admin от 09 Июня 2012, 16:04:59
usel в обоих вариантах, правда с первым вопросом не пробовал на практике, а второй точно
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 11 Июня 2012, 12:21:27
А можно как-то дать возможность пользователям создавать фотоальбомы, добавлять фотоагрифии ? Смотрел в сторону getCreateForm - так и не понял, можно или нет.. Судя по всему нет.
Название: Re:Изучаю UMI, XSLT.
Отправлено: BaceH от 13 Июня 2012, 00:03:46
можно,  getCreateForm поможет, но делал через кастом.
Название: Re:Изучаю UMI, XSLT.
Отправлено: admin от 13 Июня 2012, 04:07:15
для добавления чего либо в систему, надо чтобы был макрос, который это делает, на данный момент можно добавить в систему элементы блога, комментарии, формы обратной связи или объект каталога

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

см темы в форуме например эту (http://umihelp.ru/forum/index.php/topic,1052.msg3313.html#msg3313), эту (http://umihelp.ru/forum/index.php/topic,1075.msg3227.html#msg3227) и эту (http://umihelp.ru/forum/index.php/topic,1071.0.html)

Следует также добавить, что для создания современного варианта загрузки фото, тебе желательно сделать загрузку фото на лету и отображение превью данной фотографии. Для этого в сети есть много примеров ajax uploader или files uploader. В общем эту визуальную часть на форуме еще не обсуждали

в итоге у тебя как минимум должно быть 2 составляющих для загрузки фото

1. форма с <input type="file" />
2. кастомный макрос который обрабатывает данные пересылаемые формой и сохраняющие их куда-то
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 15 Июня 2012, 13:07:20
Пока ещё не посетило меня прозрение по поводу добавления картинок.
Ковырял модуль блоги. Посмотрел код. Там есть такие моменты:
Цитировать
$sTitle   = getRequest('title');
$sContent = htmlspecialchars(trim(getRequest('content')));
Для меня становится понятно, что это из POST запроса выдёргиваются переменные и дальше присваиваются объекту Post.
$oPost->setValue('title', $sTitle);
Есть плотное ощущение, что так же я могу добавить img. Плюс нужно сделать функции ввода-вывода-редактирования сообщений с учётом этой переменной. Сейчас это попробую всё сделать, но почему-то думаю, что получиться должно.

Но мне остаётся не понятным такой момент:

Если я хочу сделать поле ввода сообщений блога с кнопками как на этом форуме (для добавления тегов), то там же я могу запилить загрузку картинки. Но для этого мне нужно, что бы какой-то макрос принял POST с фотографией, положил её в определённую папку и вернул уже ссылку.
Читал http://wiki.umisoft.ru/%D0%94%D0%BE%D0%B1%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86_%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D0%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%D1%81%D0%BA%D1%83%D1%8E_%D1%87%D0%B0%D1%81%D1%82%D1%8C  Добавление страниц через клиентскую часть.
 есть ощущение что не подойдёт такой вариант, т.к. там нужно указывать ID шаблона данных.. А какой ID у фотографий ? Я добавил через амдинку к блогу фотографию, посмотрел xml:
<group id="292" name="izobrazheniya">
<title>Изображения</title>
[b]<property id="380" name="kartinka" type="img_file">[/b]
<title>Картинка</title>
<value path="./images/cms/data/img_9.jpg" folder="/images/cms/data" name="img_9" ext="jpg" width="380" height="179">/images/cms/data/img_9.jpg</value>
</property>
</group>
Пытался манипулировать с ID 380, но понимаю что это ID конкретного свойства конкретного типа данных.

Мне нужно выхватить загрузку картинок как при загрузке в админке, но пока не могу расковырять где это находится всё..
Название: Re:Изучаю UMI, XSLT.
Отправлено: admin от 15 Июня 2012, 20:56:12
а можно посмотреть пример того что ты хочешь получить в итоге?
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 15 Июня 2012, 22:14:23
Функционал:
Отправляем пост. Нужно прикрепить изображение.

Программа минимум:
Просто прикрепить заранее фиксированное количество фотографий к посту блога. Пример:

http://my.jetscreenshot.com/12061/20120615-9brt-29kb.jpg

Т.е. я отправляю POST action=' /blogs20/postAdd/{$document-page-id}/'. Этот вариант я ещё не опробовал, думаю он сработает. в POST передастся картинка input type="file" . Есть тень мысли о том, что может не сработать, т.к. в postAdd нигде не указана в какую папку складывать картинку ну и т.п. Вот тут возникают трудности.

Другой вариант.

Предположим, поле ввода поста блога оформлено ПРИБЛИЗИТЕЛЬНО вот так
http://my.jetscreenshot.com/12061/20120615-idsf-35kb.jpg
Нажав вставив изображение попадаем в загрузчик, который так же POST-ом отправит КАКОМУ-ТО модулю (скорее всего data, а метод будет самописным addimg), который сложит картинку в нужную папку, зарегистрирует её в базе данных, присвоит нужный шаблон данных(не понимаю какой) и т.п.
Выбрали файл, загрузили, закрыли загрузчик и получили ссылку на него в теге (http://...).


Проблема вот в чём - не понимаю как загрузить файл. Ни дописав изменения в модуль blogs, ни отдельно.
Название: Re:Изучаю UMI, XSLT.
Отправлено: admin от 16 Июня 2012, 01:09:17
первый вариант значительно проще будет реализовать, для этого:

1. Создаешь в типе данных "Пост блога 2.0" группу полей с несколькими фотками (пусть группа называется fotos)
2. Создаешь кастомный макрос %blogs20 postAddCustom()% примерно такого вида (добавил туда сохранение всех стандартных полей и вывод id иерархического типа данных "Пост блога 2.0").
public function postAddCustom($blogId = false, $template = 'default') {
if($blogId === false) {
$iTmp = getRequest('param0');
if($iTmp) $blogId = $iTmp;
else      $blogId = getRequest('bid');
}

$blogId = intval($blogId);

if($oUsers = cmsController::getInstance()->getModule('users')) {
list($canRead, $canWrite) = permissionsCollection::getInstance()->isAllowedObject($oUsers->user_id, $blogId);
if(!$oUsers->is_auth() || (!$canWrite && $blogId)) {
return false;
}
} else {
return false;
}

$sTitle   = htmlspecialchars(trim(getRequest('title')));
$sContent = htmlspecialchars(trim(getRequest('content')));
if(strlen($sTitle) && strlen($sContent) && $blogId) {
if (!umiCaptcha::checkCaptcha()) {
$this->errorNewMessage("%errors_wrong_captcha%");
$this->errorPanic();
}
if(!($blog = umiHierarchy::getInstance()->getElement($blogId)) ||
($blog->getTypeId() != umiHierarchyTypesCollection::getInstance()->getTypeByName("blogs20", "blog")->getId()) ) {
$this->errorNewMessage('%error_wrong_parent%');
$this->errorPanic();
}
$iFriendsOnly = getRequest('visible_for_friends') ? 1 : 0;
$bActivity   = getRequest('draught') ? false : true;
$sTags   = getRequest('tags');
$oHierarchy = umiHierarchy::getInstance();
$hierarchy_type_id = umiHierarchyTypesCollection::getInstance()->getTypeByName("blogs20", "post")->getId();
$iPostId = $oHierarchy->addElement($blogId, $hierarchy_type_id, $sTitle, $sTitle);
permissionsCollection::getInstance()->setDefaultPermissions($iPostId);
$oPost   = $oHierarchy->getElement($iPostId, true);

if($bActivity) {
$bActivity = antiSpamHelper::checkContent($sContent.$sTitle.$sTags);
}

//umihelp add
$data = cmsController::getInstance()->getModule("data");
if($data instanceof def_module) {
$object_id = $oPost->getObjectId();
$data->saveEditedObject($object_id, true);
}
$oPost->getObject()->commit();
$oPost->commit();
//\umihelp add

$oPost->setIsActive($bActivity);
$oPost->setValue('title', $sTitle);
$oPost->setValue('content', $sContent);
$oPost->setValue('tags', $sTags);
$oPost->setValue('publish_time', new umiDate());
$oPost->setValue('only_for_friends', $iFriendsOnly);
// Raise Event
$oEventPoint = new umiEventPoint("blogs20PostAdded");
$oEventPoint->setMode("after");
$oEventPoint->setParam("id", $iPostId);
$oEventPoint->setParam('template', $template);
$this->setEventPoint($oEventPoint);
// Redirecting
$sRefererUri = getServer('HTTP_REFERER');
if(strlen($sRefererUri)) $this->redirect(str_replace("_err=","",$sRefererUri));
return null;
} else {
if($blogId && !strlen($sTitle) && strlen($sContent)) {
$this->errorNewMessage('Не заполнен заголовок');
} else if($blogId && strlen($sTitle) && !strlen($sContent)) {
$this->errorNewMessage('Не заполнен текст публикации');
}
}

list($sFormTemplate) = $this->loadTemplates('blogs20/'.$template, 'post_add_form');
$aParams = array('action'  => '/blogs20/postAdd/'.$blogId.'/',
'id'    => 'new',
//umihelp add
'post_type_id'    => umiHierarchyTypesCollection::getInstance()->getTypeByName("blogs20", "post")->getId();,
//\umihelp add
'title'   => '',
'content' => '',
'tags'    => '',
'visible_for_friends' => '',
'blog_select' => $this->prepareBlogSelect($blogId, false, $template)
);
return $this->parseTemplate($sFormTemplate, $aParams);
}

Кастом кидаешь в файл /classes/modules/blog20/__custom.php. Не забывай создать файл permissions.custom.php с содержимым:
<?php
$permissions = Array(
'add'    => array('postAddCustom')
);
?>

3. выводишь форму добавления блока (post_add_form) и внутрь формы вставляешь %data getCreateForm(%post_type_id%,default, fotos)%

после чего у тебя в форме добавления post для блока появятся поля из группы полей fotos с name типа data[new][foto1], они и сохраняться кодом
//umihelp add
$data = cmsController::getInstance()->getModule("data");
if($data instanceof def_module) {
$object_id = $oPost->getObjectId();
$data->saveEditedObject($object_id, true);
}
$oPost->getObject()->commit();
$oPost->commit();
//\umihelp add


p.s. писал все сходу, проверок не делал
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 16 Июня 2012, 12:06:49
Благодарю за помощь.
Сделал всё как Вы написали - точку с запятой в одном месте профиксил.
 %data getCreateForm(%post_type_id%,default, fotos)%
%post_type_id% ничего не возвращал, я вручную прописал ид.
В итоге появились нужные мне поля. Прикрепляю картинку, отправляю - она не запоминается.
Заменил action с /blogs20/postAdd/65/ на /blogs20/postAddCustom/65/ - не сработало так же. Заменил в classes.php postAdd на кастомный - не сработало так же.
Права у пользователя максимальные.
Сейчас буду вникать в процесс...
А можно ли как-нибудь отслеживать какой кастомный макрос срабатывает, какие переменные принимает и т.п. ? Есть ощущение, что не доходит до него мой input file


Дополнено: убедился, что выполняется именно кастомный макрос,
так же выполняется этот IF, внутри которого как я понимаю и происходит сохранение. $object_id получается корректно (перемещал сюда $oPost->setValue('tags', $sTags); и вместо $sTags подставлял $object_id.
Цитировать
      //umihelp add
         $data = cmsController::getInstance()->getModule("data");
         if($data instanceof def_module) {
            $object_id = $oPost->getObjectId();
            $data->saveEditedObject($object_id, true);

         }
         $oPost->getObject()->commit();
         $oPost->commit();
         //\umihelp add
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 16 Июня 2012, 12:48:35
Не понял прикола. Начал ковыряться в сторону saveEditedObjectData и развивать мысль, что передавать надо не $object_id а собственно объект, начал менять всё - получил ошибки.. Через ctrl-z изменения отменил, сохранил, обновляю окно umi с ошибками, браузер спрашивает отправить ли заново данные, я отправил... икартинка улетела.. теперь все отправляются. Не понятно.. Сверяю с первоначальным кодом - вроде 1в1. Но у меня уже два десятка постов без картинок.:)
Благодарю за помощь, Вы действительно очень много помогли мне. Более менее разбирусь сам - постараюсь проявлять активность на Вашем форуме. :)
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 17 Июня 2012, 13:28:11
Снова не знаю в какую сторону капать, поиском что-то не смог найти, не знаю как сформулировать запрос.
Я делаю что-то вроде автоблогов. Пользователи регистрируются, создают блог о своей машине. Выбирая марку-модель у блога заполняются теги, к примеру "TOYOTA, COROLLA".
Навигацию по блогам хочется сделать такую: site.ru/blogs - сюда выводится список марок. Получения списка марок два варианта - 1) через USEL пробегаемся и формируем список из 1-ого тега блогов, сортируем по алфавиту 2) заранее задаём список марок. Имя марки = тег.
Заходим по ссылке blogs/toyota – по тегу Toyota получаем список марок. Заходя по ссылке blogs/Toyota/corolla – получаем посты блогов  с тегом TOYOTA COROLLA.
Проблема: не могу понять, как реализовать такую структуру, кроме как заранее создать кучу статичных страниц, и в зависимости от ID страницы выдавать результат.
Хотелось бы наоборот – есть блоги с названиями и тегами, и по этому названию и тегам сформировать страницу site.ru/blogs/марка/модель/, т.е. можно ли как-то создавать такие страницы ? Уверен, что можно, но пока для меня больно крутая задача.
Я немного не могу понять как UMI по псевдостатическому адресу подбирает модуль (ну это ещё можно понять) и метод. К примеру, заходим site.ru/test_blog - module="blogs20" method="blog", заходим site.ru/test_blog/test_post - module="blogs20" method="post".
Смотрим @id страниц и взглянем на эти страницы через upage.
<basetype id="25" module="blogs20" method="blog">Блог</basetype>
 <basetype id="28" module="blogs20" method="post">Пост блога</basetype>
Получается, что таким обращаясь к странице сайта, возможно по link находится id объекта, а по нему всё остальное восстанавливается.
Basetype - Элемент описывающий базовый тип для этой страницы (назначение страниц этого типа). Не совпадает с ID в шаблонах данных. Что это за тип пока не могу понять.
Предположим, что если мне сделать свои basetype для выдачи марок и моделей, назовём это более универсальнее - КАТЕГОРИИ БЛОГА, ну и соответствующие методы – то мне ещё нужно будет в целом переделать blogs20, что бы появились те самые категории. Опять же не понятно – категории это ведь динамические страницы, которые не создаются как блоги и посты блогов, хотя их создание можно просто автоматизировать при создание блога.

Вот так же не понятно  - хочу сделать страницу добавления блога. К примеру, site.ru/blogs/add. Можно создать статичную страницу blogs, указать её родительской к пользовательским блогам. Вложить в неё страницу с псевдостатическим адресом add и получим site.ru/blogs/add, потом по ID страницы можно выдать нужный контент….
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 17 Июня 2012, 14:26:23
Я вроде понял как сформулировать свой вопрос за малое количество букв:
нужно что бы обращаясь к site.ru/blogs/toyota/corola происходило вот что:
site.ru/blogs - это ведёт к макросу, а /toyota/corola были аргументами


Ковыряю в сторону xsl:param

Анализируя модуль поиска понял, что можно реализовать через xsl:raram - search/search_do/?search_string=поиск
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 09 Июля 2012, 17:54:46
Может быть кто-нибудь подскажет, можно ли в XSLT шаблонизаторе использовать такие конструкции:

<xsl:apply-templates select="document('udata://content/pagesByAccountTags/(проверка)/')" /> - русский тег
<xsl:apply-templates select="document('udata://content/pagesByAccountTags/(проверка проверка)/')" />  - тег с пробелами. Если у меня к примеру картинки получают теги Toyota Corolla и когда я нахожусь внутри каталога Toyota Corolla - автоматом хочу выводить все картинки. У каталога тег так же состоит из двух слов. Можно ли как-то вставить там %20 вместо пробела ?
Или придётся переписать много всего, что бы всюду пробелы заменялись на точки ?
Название: Re:Изучаю UMI, XSLT.
Отправлено: admin от 10 Июля 2012, 04:29:00
надо просто сделать php urlencode переменной, о том как это делается можно глянуть тут Передача значений на кириллице в кастомный метод (http://wiki.umisoft.ru/%D0%9F%D0%B5%D1%80%D0%B5%D0%B4%D0%B0%D1%87%D0%B0_%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B9_%D0%BD%D0%B0_%D0%BA%D0%B8%D1%80%D0%B8%D0%BB%D0%BB%D0%B8%D1%86%D0%B5_%D0%B2_%D0%BA%D0%B0%D1%81%D1%82%D0%BE%D0%BC%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4)
Название: Re:Изучаю UMI, XSLT.
Отправлено: Rodogor от 23 Июля 2012, 16:22:57
Всё заработало, и русские буквы и пробелы. Благодарю..

Ранее я уже делал такую конструкцию - отдельно обрабатывал первые 5 элементов, а потом оставшиеся. Вроде всё работало.
Сейчас пробую получить первые n элементов - не выходит.

	<xsl:apply-templates select="document('udata://content/menu/')/udata/items/item[position() &lt;= 2]"/>

<xsl:apply-templates select="document('udata://content/menu/')/udata/items/item[position() &gt; 2]"/>
Получаем сначала первые 2 элемента, а потом остальные.
Сейчас копирую этот же код - не работает.
Цитировать
Warning: XSLTProcessor::transformToXml() [xsltprocessor.transformtoxml]: Invalid context position in /var/www/.........
Не могу понять как так получается.  читая документацию, вижу что "Сущность &lt; используется в XML вместо < (меньше), а сущность &gt; — вместо > (больше)" - после &lt; отсутствует равно. Но и так не работает.....