Вывод последних зарегистрированных пользователей (XSLT) — различия между версиями

Материал из Umicms
Перейти к:навигация, поиск
 
(не показано 15 промежуточных версий 2 участников)
Строка 1: Строка 1:
'''Задача''': Вывести на сайте список последних зарегистрированных на сайте пользователей (на примере шаблонов demodizzy).<br/>
+
'''Актуально для версии 2.9'''
 +
<br/>
 +
 
 +
'''Задача''': Вывести на сайте список последних зарегистрированных пользователей (на примере шаблонов demodizzy).<br/>
 
'''Решение''': Для решения задачи будем использовать макросы %users count_users()% и %users list_users()%.<br/>
 
'''Решение''': Для решения задачи будем использовать макросы %users count_users()% и %users list_users()%.<br/>
  
Строка 13: Строка 16:
 
Так как макрос %users list_users()% выводит по умолчанию только 10 первых пользователей, то чтобы  при вызове макроса получить последних пользователей, нам будет необходимо использовать пейджинг (udata://users/list_users/notemplate/10/?p=2).<br/>
 
Так как макрос %users list_users()% выводит по умолчанию только 10 первых пользователей, то чтобы  при вызове макроса получить последних пользователей, нам будет необходимо использовать пейджинг (udata://users/list_users/notemplate/10/?p=2).<br/>
  
Чтобы высчитать число последней страницы пейджинга, нам необходимо узнать общее количество всех активированных пользователей на сайте(%users count_users()%) и количество пользователей выводимых макросом %users list_users()% на одну страницу (задаем самостоятельно).<br/>
+
Чтобы высчитать число последней страницы пейджинга, нам необходимо узнать общее количество всех активированных пользователей на сайте(для этого используем макрос %users count_users()%) и количество пользователей выводимых макросом %users list_users()% на одну страницу (задаем самостоятельно).<br/>
 +
 
 +
Этапы получения необходимых для отображения данных будут выглядеть следующим образом:<br/>
 +
1. Получаем udata-результат работы макроса list_users (в этом результате содержится вся информация).<br/>
 +
2. Из udata-результата получаем элементы списка по правилу отбора items/item и в каждом полученном элементе списка находим id объекта, по которому инициализируем его получение через протокол uobject.<br/>
 +
3. Распределяем полученные из объекта данные (логин, дата регистрации, имя) по верстке.<br/>
 +
 
 +
Для упрощения кода и уменьшения количества вызовов темплейтов будем использовать такую функциональность как расширенные свойства - extProps. Данная функциональность позволяет получить в результате запроса нужные нам поля, такие как дата регистрации, логин, имя пользователя. Чтобы получить все необходимые данные, нам будет достаточно добавить к вызову GET параметр &extProps= с перечислением всех нужных нам свойств объекта.<br/>
 +
 
 +
В результате, количество этапов уменьшиться и станет следующим:<br/>
 +
1. Получаем udata-результат работы макроса list_users (в этом результате содержится вся информация).<br/>
 +
2. Из udata-результата получаем элементы списка по правилу отбора items/item и распределяем полученные данные (логин, дата регистрации, имя) по верстке.<br/>
  
В шаблоне дизайна (layouts/default.xsl) там, где мы хотим увидеть результаты своей работы, сделаем вызов темплейта с передачей параметра количества элементов выводимых на одной странице. Заметьте, что мы везде используем mode="lastreg":
+
Более того, по совету нашего разработчика, код можно ещё упростить пропустив этап получения udata-результата, ведь мы можем сразу вызвать макрос list_users с получением информации на нужном нам уровне, то есть вместо вызова \udata, мы можем сделать вызов \udata\items\item. <br/>
  
 +
Приступим. В шаблоне дизайна (layouts/default.xsl) там, где мы хотим увидеть результаты своей работы, сделаем вызов темплейта с именем lastregusers:
 
<source lang="xml" >
 
<source lang="xml" >
 
<!-- @name="Вывод последних зарегистрированных пользователей"  
 
<!-- @name="Вывод последних зарегистрированных пользователей"  
 
     @path="/modules/users/lastRegisteredUsers.xsl"  
 
     @path="/modules/users/lastRegisteredUsers.xsl"  
 
-->
 
-->
<xsl:apply-templates select="document('udata://users/count_users')/udata" mode="lastreg">
+
<xsl:call-template name="lastregusers" />
<xsl:with-param name="perpage" select="10"/>
+
 
</xsl:apply-templates>
 
 
</source>
 
</source>
  
Разрабатываемая функциональность относится к модулю users, поэтому перейдем в папку /modules/users/ и скопируем какой-либо шаблон, сделав из него заготовку и переименовав lastRegisteredUsers.xsl. Также подключим созданный файл шаблона в файле common.xsl:
+
Разрабатываемая функциональность относится к модулю users, поэтому перейдем в папку /modules/users/ и скопируем какой-либо шаблон, сделав из него заготовку и переименовав в lastRegisteredUsers.xsl. Также подключим созданный файл шаблона в файле common.xsl:
 
<source lang="xml" >
 
<source lang="xml" >
 
       <xsl:include href="lastRegisteredUsers.xsl" />
 
       <xsl:include href="lastRegisteredUsers.xsl" />
Строка 43: Строка 57:
 
</xsl:stylesheet>
 
</xsl:stylesheet>
 
</source>
 
</source>
 +
 
В следующем листинге, мы:<br/>
 
В следующем листинге, мы:<br/>
1) Получаем данные от вызываемого в layouts/default.xsl макроса, в том числе получаем переданный параметр perpage.<br/>
+
1) Описываем темплейт с именем lastregusers вызванный в файле default.xsl, подготавливая нужные для вызова макроса %users list_users()% данные: количество выводимых элементов на одной странице '''perpage''', расчёт общего количества пользователей на сайте '''allusers''' и расчёт последней страницы пейджинга с результатами макроса '''countpage'''. Для расчёта мы используем функции floor() И div.<br/>
2) В переменной countpage вычисляем значение последней страницы, используя функции floor и dev.<br/>
+
 
 
   '''Справка:'''
 
   '''Справка:'''
 
   floor()- возвращает наибольшее целое, меньшее, чем переданное функции число;
 
   floor()- возвращает наибольшее целое, меньшее, чем переданное функции число;
 
   div - деление;
 
   div - деление;
 
   . (точка) - ссылка на текущий узел (в нашем случае это общее количество пользователей).
 
   . (точка) - ссылка на текущий узел (в нашем случае это общее количество пользователей).
3) Вызываем макрос %users list_users()% с нужными нам параметрами.
+
 
<source lang="xml" >
+
2) Вызываем макрос с подготовленными данными и сразу с помощью элемента sort сортируем результат по id.<br/>
<xsl:template match="udata[@module = 'users'][@method = 'count_users']" mode="lastreg">
+
3) Тянем за собой параметр allusers с общим количеством всех активных пользователей на сайте.<br/>
<xsl:param name="perpage"/>
 
<xsl:variable name="countpage" select="floor((. - 1) div $perpage)" />
 
<xsl:apply-templates select="document(concat('udata://users/list_users/notemplate/',$perpage,'/?p=',$countpage))/udata" mode="lastreg" >
 
<xsl:with-param name="countpage" select="."/>
 
</xsl:apply-templates>
 
</xsl:template>
 
</source>
 
В следующем листинге, мы:<br/>
 
1) Получаем udata-результат работы макроса list_users.<br/>
 
2) Вызываем новый темплейт, в котором передаем элементы из udata предварительно их отсортировав в обратном порядке по значению атрибута @id.<br/>
 
3) Продолжаем тянуть за собой параметр countpage с общим количеством пользователей на сайте.<br/>
 
 
4) Пишем общий для всех элементов код верстки.
 
4) Пишем общий для всех элементов код верстки.
 +
 
<source lang="xml" >
 
<source lang="xml" >
<xsl:template match="udata[@module = 'users'][@method = 'list_users']" mode="lastreg">
+
<xsl:template name="lastregusers">
<xsl:param name="countpage"/>
+
<xsl:variable name="perpage" select="10" />
<div class="infoblock">
+
<xsl:variable name="allusers" select="document('udata://users/count_users')/udata" />
<div class="title"><h2>К нам присоединились:</h2></div>
+
<xsl:variable name="countpage" select="floor((document('udata://users/count_users')/udata - 1) div $perpage)" />
<div class="body">
+
 
<div class="in">
+
<div class="infoblock">
<strong>Приветствуем новых пользователей: </strong>
+
<div class="title"><h2>К нам присоединились</h2></div>
<ol class="recentPages">
+
<div class="body">
<xsl:apply-templates select="items/item" mode="lastreg" >
+
<div class="in">
<xsl:with-param name="countpage" select="$countpage"/>
+
<strong>Приветствуем новых пользователей: </strong>
<xsl:sort order="descending" select="@id"/>
+
<ol class="recentPages">
</xsl:apply-templates>
+
<xsl:apply-templates select="document(concat('udata://users/list_users//',$perpage,'/?p=',$countpage,'&amp;extProps=register_date,fname,login'))/udata/items/item" mode="lastreg">
</ol>
+
<xsl:with-param name="allusers" select="$allusers"/>
</div>
+
<xsl:sort order="descending" select="@id"/>
</div>
+
</xsl:apply-templates>
 +
</ol>
 
</div>
 
</div>
 +
</div>
 +
</div>
 
</xsl:template>
 
</xsl:template>
 +
 
</source>
 
</source>
 +
 +
 
В следующем листинге, мы:<br/>
 
В следующем листинге, мы:<br/>
1) Получаем отсортированный список элементов, берем у них значение атрибута @id и вызываем темплейт с получением объекта по протоколу uobject.<br/>
+
1) Получаем элементы с расширенными параметрами и распределяем данные (порядковый номер, дата регистрации, имя пользователя, логин) по верстке.<br/>
2) В качестве параметра к темплейту, передаем текущую позицию элемента начиная отсчет от общего количества всех пользователей на сайте и уменьшенную на 2 шага (пользователи "супервайзер" и "гость").<br/>
 
 
<source lang="xml" >
 
<source lang="xml" >
<xsl:template match="items/item" mode="lastreg">
+
<xsl:template match="item" mode="lastreg">
<xsl:param name="countpage"/>
+
<xsl:param name="allusers"/>
<xsl:variable name="countpage" select="($countpage - 1) - position()" />
+
<xsl:variable name="numberuser" select="($allusers - 1) - position()" />
 
 
<xsl:apply-templates select="document(concat('uobject://',@id))" mode="lastreg" >
+
<li>
<xsl:with-param name="countpage" select="$countpage"/>
+
<xsl:value-of select="$numberuser" />)
</xsl:apply-templates>
+
<xsl:value-of select=".//property[@name='register_date']/value/@formatted-date" /> -
 +
<xsl:value-of select=".//property[@name='fname']/value" />
 +
(<xsl:value-of select=".//property[@name='login']/value" />)
 +
</li>
 
 
 
</xsl:template>
 
</xsl:template>
 
</source>
 
</source>
 +
 
В следующем листинге, мы:<br/>
 
В следующем листинге, мы:<br/>
1) Получаем объект и распределяем данные (порядковый номер, дата регистрации, имя пользователя, логин) по верстке.<br/>
+
1) Запрещаем показывать пользователя sv из группы Супервайзеры и учетную запись Гостя. Можно было бы обойтись и без данного темплейта, а использовать в предыдущем конструкцию <xsl:if test="" />, но по заверениям разработчика, конструкции if работают в xslt медленно и если есть такая возможность, то лучше их не использовать.<br/>
2) Запрещаем показывать пользователей из группы Супервайзеры и учетную запись Гостя.<br/>
 
 
<source lang="xml" >
 
<source lang="xml" >
<xsl:template match="object" mode="lastreg">
+
<xsl:template match="items/item[.//property[@name='login']/value = 'sv' or .//property[@name='login']/value = 'Гость']" mode="lastreg" />
<xsl:param name="countpage"/>
 
        <xsl:if test="not(//property[@name='groups']/value/item[@name='Супервайзеры'] or //property[@name='login']/value = 'Гость')" >
 
    <li>
 
  <xsl:value-of select="$countpage" />)
 
  <xsl:value-of select="//property[@name='register_date']/value/@formatted-date" /> -
 
  <xsl:value-of select="//property[@name='fname']/value" />
 
    (<xsl:value-of select="//property[@name='login']/value" />)
 
    </li>
 
</xsl:if>
 
 
</xsl:template>
 
 
</source>
 
</source>
 +
 +
Принцип по которому все работает прост и скрывается в приоритетах: оба темплейта имеют одинаковый режим mode, но у второго темплейта условие выбора match задано конкретнее чем у первого, поэтому для XSLT данное правило будет иметь более высокий приоритет и при наступлении нужного match'а мы ничего не делаем, пропуская найденный удовлетворяющий условию item.<br/>
 +
 
'''Результат:'''<br/>
 
'''Результат:'''<br/>
 
[[Файл:26-05-2013 1-01-46.png]]
 
[[Файл:26-05-2013 1-01-46.png]]
 +
 +
 +
 +
[[Категория:Модуль Пользователи]][[Категория:Верстка в XSLT]]

Текущая версия на 16:40, 5 июня 2013

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

Задача: Вывести на сайте список последних зарегистрированных пользователей (на примере шаблонов demodizzy).
Решение: Для решения задачи будем использовать макросы %users count_users()% и %users list_users()%.

Для начала, если Вы хотите чтобы список пользователей был виден всем пользователям сайта, а не только зарегистрированным, то необходимо изменить права на указанные макросы при помощи файла permissions.custom.php:

<?php
	$permissions = Array(
		             'registrate' => Array('list_users','count_users')
	                     );
?>

Так как макрос %users list_users()% выводит по умолчанию только 10 первых пользователей, то чтобы при вызове макроса получить последних пользователей, нам будет необходимо использовать пейджинг (udata://users/list_users/notemplate/10/?p=2).

Чтобы высчитать число последней страницы пейджинга, нам необходимо узнать общее количество всех активированных пользователей на сайте(для этого используем макрос %users count_users()%) и количество пользователей выводимых макросом %users list_users()% на одну страницу (задаем самостоятельно).

Этапы получения необходимых для отображения данных будут выглядеть следующим образом:
1. Получаем udata-результат работы макроса list_users (в этом результате содержится вся информация).
2. Из udata-результата получаем элементы списка по правилу отбора items/item и в каждом полученном элементе списка находим id объекта, по которому инициализируем его получение через протокол uobject.
3. Распределяем полученные из объекта данные (логин, дата регистрации, имя) по верстке.

Для упрощения кода и уменьшения количества вызовов темплейтов будем использовать такую функциональность как расширенные свойства - extProps. Данная функциональность позволяет получить в результате запроса нужные нам поля, такие как дата регистрации, логин, имя пользователя. Чтобы получить все необходимые данные, нам будет достаточно добавить к вызову GET параметр &extProps= с перечислением всех нужных нам свойств объекта.

В результате, количество этапов уменьшиться и станет следующим:
1. Получаем udata-результат работы макроса list_users (в этом результате содержится вся информация).
2. Из udata-результата получаем элементы списка по правилу отбора items/item и распределяем полученные данные (логин, дата регистрации, имя) по верстке.

Более того, по совету нашего разработчика, код можно ещё упростить пропустив этап получения udata-результата, ведь мы можем сразу вызвать макрос list_users с получением информации на нужном нам уровне, то есть вместо вызова \udata, мы можем сделать вызов \udata\items\item.

Приступим. В шаблоне дизайна (layouts/default.xsl) там, где мы хотим увидеть результаты своей работы, сделаем вызов темплейта с именем lastregusers:

<!-- @name="Вывод последних зарегистрированных пользователей" 
     @path="/modules/users/lastRegisteredUsers.xsl" 
-->
<xsl:call-template name="lastregusers" />

Разрабатываемая функциональность относится к модулю users, поэтому перейдем в папку /modules/users/ и скопируем какой-либо шаблон, сделав из него заготовку и переименовав в lastRegisteredUsers.xsl. Также подключим созданный файл шаблона в файле common.xsl:

      <xsl:include href="lastRegisteredUsers.xsl" />
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet	version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:umi="http://www.umi-cms.ru/TR/umi">
	
	<!-- @name="Вывод последних зарегистрированных пользователей"
             @import="common.xsl"
	     @call="/layouts/default.xsl" 
	-->

</xsl:stylesheet>

В следующем листинге, мы:
1) Описываем темплейт с именем lastregusers вызванный в файле default.xsl, подготавливая нужные для вызова макроса %users list_users()% данные: количество выводимых элементов на одной странице perpage, расчёт общего количества пользователей на сайте allusers и расчёт последней страницы пейджинга с результатами макроса countpage. Для расчёта мы используем функции floor() И div.

 Справка:
 floor()- возвращает наибольшее целое, меньшее, чем переданное функции число;
 div - деление;
 . (точка) - ссылка на текущий узел (в нашем случае это общее количество пользователей).

2) Вызываем макрос с подготовленными данными и сразу с помощью элемента sort сортируем результат по id.
3) Тянем за собой параметр allusers с общим количеством всех активных пользователей на сайте.
4) Пишем общий для всех элементов код верстки.

<xsl:template name="lastregusers">
<xsl:variable name="perpage" select="10" />
<xsl:variable name="allusers" select="document('udata://users/count_users')/udata" />
<xsl:variable name="countpage" select="floor((document('udata://users/count_users')/udata - 1) div $perpage)" />

<div class="infoblock">
<div class="title"><h2>К нам присоединились</h2></div>
<div class="body">
	<div class="in">
		<strong>Приветствуем новых пользователей: </strong>
		<ol class="recentPages">
			<xsl:apply-templates select="document(concat('udata://users/list_users//',$perpage,'/?p=',$countpage,'&amp;extProps=register_date,fname,login'))/udata/items/item" mode="lastreg">
				<xsl:with-param name="allusers" select="$allusers"/>
				<xsl:sort order="descending" select="@id"/>
			</xsl:apply-templates>
		</ol>
	</div>
</div>
</div>
</xsl:template>


В следующем листинге, мы:
1) Получаем элементы с расширенными параметрами и распределяем данные (порядковый номер, дата регистрации, имя пользователя, логин) по верстке.

<xsl:template match="item" mode="lastreg">
	<xsl:param name="allusers"/>
	<xsl:variable name="numberuser" select="($allusers - 1) - position()" />
	
		<li>
			<xsl:value-of select="$numberuser" />) 
			<xsl:value-of select=".//property[@name='register_date']/value/@formatted-date" /> - 
			<xsl:value-of select=".//property[@name='fname']/value" />
			(<xsl:value-of select=".//property[@name='login']/value" />)
		</li>
	
</xsl:template>

В следующем листинге, мы:
1) Запрещаем показывать пользователя sv из группы Супервайзеры и учетную запись Гостя. Можно было бы обойтись и без данного темплейта, а использовать в предыдущем конструкцию <xsl:if test="" />, но по заверениям разработчика, конструкции if работают в xslt медленно и если есть такая возможность, то лучше их не использовать.

<xsl:template match="items/item[.//property[@name='login']/value = 'sv' or .//property[@name='login']/value = 'Гость']" mode="lastreg" />

Принцип по которому все работает прост и скрывается в приоритетах: оба темплейта имеют одинаковый режим mode, но у второго темплейта условие выбора match задано конкретнее чем у первого, поэтому для XSLT данное правило будет иметь более высокий приоритет и при наступлении нужного match'а мы ничего не делаем, пропуская найденный удовлетворяющий условию item.

Результат:
26-05-2013 1-01-46.png