Логотип

Документация по макросам и шаблонам UMI.CMS

Предположим, что шаблон страницы, где мы хотим отобразить формы добавления и список комментариев, выглядит следующим образом (пример шаблона для страницы полного текста новости):

// news.item 

<xsl:template match="result[@module = 'news'][@method = 'item']">

  // правила отображения контента; рассматривать не будем

  <h3><a name="comments">Комментарии</a></h3>

  // здесь мы хотим увидеть список комментариев 
   
  // здесь мы отобразим форму добавления новых комментариев 
  
</xsl:template>

Для отображения списка комментариев воспользуемся макросом %comments insert()%, передав ему id текущей страницы. Например в приведенном выше шаблоне это будет значение атрибута id элемента page ответа UMIData (см. «Формат UMI Data»).

Поэтому мы можем написать инструкцию apply-templates для обработки результатов макроса, построив запрос при помощи функции concat() и подключив результаты макроса при помощи функции document():

<xsl:apply-templates select="document(concat('udata://comments/insert/', page/@id))/udata"/>

Ответ макроса в формате UData можно посмотреть, набрав в адресной строке: http://адрес_сайта/udata/comments/insert/id_страницы_с_комментариями

Для отображения формы добавления нового комментария нам нужно учесть случаи с зарегистрированными пользователями и гостями сайта (мы будем показывать им разные формы). Поэтому добавим apply-templates и выберем элемент user ответа UMIData, который описывает пользователя, открывшего текущую страницу:

<xsl:apply-templates select="user"/>

В зависимости от содержимого элемента user мы и будем выводить под списком комментариев разные формы.

Теперь осталось только описать сами шаблоны для списка комментариев и вывода форм.

Список комментариев

Вариант, когда комментарии отсутствуют опишем так (менее специфичный шаблон, он будет выбран "по-умолчанию"):

<xsl:template match="udata[@module = 'comments'][@method = 'insert']">
   <span>Нет комментариев</span>
</xsl:template>

Условие [@module = 'comments'][@method = 'insert'] указывает, что это шаблон должен быть применен для обработки результатов макроса %comments insert()%.

В случае, когда присутствуют комментарии, в XML-ответе макроса будут ветви items с вложенными элементами item, и мы можем обработать список при помощи следующего шаблона:

<xsl:template match="udata[@module = 'comments'][@method = 'insert'][items/item]">
  <xsl:variable name="doc-numpages" select="document(concat('udata://system/numpages/', total, '/', per_page, '/notemplate/p/10'))/udata" />

  <ul class="comments">
    <xsl:apply-templates select="items/item" mode="comments.list" /> 
  </ul>

  <xsl:apply-templates select="$doc-numpages" mode="paging.words" />   // utils.xsl 
  <xsl:apply-templates select="$doc-numpages" mode="paging.numbers" /> // utils.xsl 

</xsl:template>

Условием [@module = 'comments'][@method = 'insert'][items/item] указывает, что этот шаблон должен быть применен для обработки результатов макроса %comments insert()% с элементами item вложенными в items.

Можно видеть также, что в этом шаблоне уже подключен пейджинг, пример создания которого можно посмотреть в отдельной главе: Постраничный вывод (пейджинг) стредствами XSLT-шаблонизатора. Параметры total и per_page для макроса %system numpages()% уже содержатся в ответе макроса %comments insert()%.

Место, куда будет выведен список комментариев указан инструкцией apply-templates, которая выбирает каждый элемент item из ответа макроса, описывающий отдельный комментарий из списка, и применяет к ним шаблоны. Для оформления внешнего вида каждого комментария опишем такой шаблон:

<xsl:template match="item" mode="comments.list">
  <li>

    <xsl:value-of select="@num" />.&nbsp;
    <span class="title">
       <xsl:value-of select="@title" />
    </span>
 
    &nbsp;-&nbsp;

    <xsl:apply-templates select="document(concat('udata://users/viewAuthor/', @author_id))/udata"/>

    <div class="message">
          <xsl:value-of select="." disable-output-escaping="yes" />
    </div>

  </li>
</xsl:template>

Для получения данных об авторе комментария мы воспользовались макросом %users viewAuthor()%, которому передали в качестве параметра значение атрибута author_id элемента item.

Шаблоны оформления автора можно дополнить самостоятельно (см. XML-ответ макроса %users viewAuthor()%), ниже приводится простейший вариант создания ссылки с электронным адресом автора:

<xsl:template match="udata[@module = 'users'][@method = 'viewAuthor']">
  <xsl:value-of select="nickname" />
</xsl:template>

<xsl:template match="udata[@module = 'users'][@method = 'viewAuthor'][email]">
  <a class="author" href="mailto:{email}">
    <xsl:value-of select="nickname" />
  </a>
</xsl:template>

Если автор не указал свой e-mail, будет выбран первый шаблон и выведен только nickname. Если в ответ макроса присутствует элемент email будет задействован второй шаблон (с условием [email]), который подставит его значение в ссылку после слова "mailto:".

Форма добавления комментариев

Создадим два шаблона, описывающих вывод формы для зарегистрированных пользователей и гостей сайта.

Зарегистрированный пользователь

Случай авторизованного автора описывает следующее условие match="user[@status = 'auth']", поэтому шаблон может выглядеть следующим образом:

<xsl:template match="user[@status = 'auth']">

  <h3><a name="addcomment">Добавить комментарий</a></h3>

  <form method="post" action="/comments/post/{/result/@pageId}/" name="form_addcomment" id="form_addcomment">

     <fieldset class="intext">
         <label for="comment_title" id="for_title" title="Заголовок">
           <span>Заголовок:&nbsp;<sup class="asterisk">*</sup></span>
           <input type="text" name="title" id="comment_title" />
         </label>

         <label for="comment_text" id="for_comment" title="Текст">
           <span>Текст:&nbsp;<sup class="asterisk">*</sup></span>
           <textarea name="comment" id="comment_text" cols="6" />
         </label>
     </fieldset>

     <input class="submit-send" type="submit" value="Отправить"/>

  </form>

</xsl:template>

За отправку комментария отвечает метод post модуля "Комментарии", которому мы передаем id страницы, на которой мы выводим форму (id страницы находится, например, в атрибуте pageId тега result). Пары атрибут-значение name="title" и name="comment" для полей ввода являются обязательными, так как в ином случае метод comments/post не обработает эти данные.

Незарегистрированный пользователь

Случай Гостя описывается менее специфичным условием соответствия — match="user". Кроме того, необходимо предусмотреть вариант скрытия формы, в случае запрета в настройках модуля оставлять комментарии для незарегистрированных пользователей. Макрос %comments insert()% в этом случае не отобразит элементы action в своем ответе, чем мы и воспользуемся.

Создадим следующий шаблон:

<xsl:template match="user">
      <xsl:apply-templates select="document(concat('udata://comments/insert/', /result/@pageId))/udata/action"/>
</xsl:template>

Мы передали макросу %comments insert()% id текущей страницы таким же образом, что и ранее, и выбрали элемент action для того, чтобы построить форму добавления комментария. Теперь необходимо создать шаблон, который будет обрабатывать элемент action и в итоге выводить форму:

<xsl:template match="action">
  <h3><a name="addcomment">Добавить комментарий</a></h3>

  <form method="post" action="{.}" name="form_addcomment" id="form_addcomment">

    <fieldset class="intext">
       <label for="comment_title" id="for_title" title="Заголовок">
         <span>Заголовок:&nbsp;<sup class="asterisk">*</sup></span>
         <input type="text" name="title" id="comment_title" />
       </label>

       <label for="comment_author">
          <span>Ваш ник:</span>
          <input type="text" name="author_nick" id="comment_author" />
       </label>

       <label for="comment_email">
          <span>Ваш e-mail:</span>
          <input type="text" name="author_email" id="comment_email" />
       </label>

       <label for="comment_text" id="for_comment" title="Текст">
          <span>Текст:&nbsp;<sup class="asterisk">*</sup></span>
          <textarea name="comment" id="comment_text" cols="6" />
       </label>
    </fieldset>

    // здесь мы хотим отобразить капчу 

    <input class="btt submit-send" type="submit" value="отправить"/>

  </form>

</xsl:template>

Значение action для формы находится в элементе action, который обрабатывает этот шаблон. Поэтому его можно вывести просто указав {.} (точка — означает текущий элемент).

Здесь также следует обратить внимание на то, что пары атрибут-значение name="title", name="author_nick", name="author_email", name="comment" для полей ввода являются обязательными, иначе метод post не обработает эти данные.

Осталась последняя задача — реализовать вывод CAPTCHA (защитного кода). Для этого мы воспользуемся макросом %system captcha()%. Этот макрос возвращает URL картинки с защитным кодом и случайную строку, которую можно добавить к адресу картинки, чтобы избежать кэширования браузерами. Добавим в место отображения картинки следующее:

<xsl:apply-templates select="document('udata://system/captcha')/udata[url]" />

Добавим также следующее описание шаблона:

<xsl:template match="udata[@module = 'system'][@method = 'captcha']">
  <fieldset>
    <legend>Введите символы защиты от автосозданий&nbsp;<sup class="asterisk">*</sup></legend>

    <label for="captcha" id="for_captcha" title="Защитный код">
      <div class="input">
        <input type="text" name="captcha" id="captcha" />
      </div>
      <span><img src="{url}{@random_string}" /></span>
    </label>
  </fieldset>
</xsl:template>

Значение элемента url — это адрес картинки, а атрибут random_string, это случайная строка вида "?1255523102". Пара атрибут-значение name="captcha" необходима для метода post, обрабатывающего форму.