UMIhelp

Разработка сайта на UMI.CMS => Шаблоны XSLT => Тема начата: sam от 17 Декабря 2015, 17:50:50

Название: Проверка по дням недели
Отправлено: sam от 17 Декабря 2015, 17:50:50
Здравствуйте! Просьба подсказать - как в XSLT сделать проверку по дням недели? Например, в условиях доставки с понедельника по четверг вывести инфо. "доставка - завтра и позже", а вот с пятницы по воскресенье "доставка - вторник и позже".

Если (пятница-воскресенье):
"доставка - вторник и позже"
Иначе:
"доставка - завтра и позже"
Название: Re: Проверка по дням недели
Отправлено: e.ioffe от 18 Декабря 2015, 18:25:48
Я бы делал это не в xslt, а в кастомном методе.

Что-то вроде:

public function getDeliveryDate() {
 if(пятница - воскресенье) {
   return 'tuesday';
} else {
   return 'tomorrow';
}
}
Название: Re: Проверка по дням недели
Отправлено: sam от 18 Декабря 2015, 18:36:09
Интересно. Т.е. в каком-то файле прописать подобный макрос, а потом в xslt сделать вызов этого макроса (getDeliveryDate())?

А наверняка ведь есть у этой задачи решение и в xslt? Просто системные файлы трогать не хочется.
Название: Re: Проверка по дням недели
Отправлено: e.ioffe от 18 Декабря 2015, 18:49:48
Да, в файле custom.php Он не системный
Название: Re: Проверка по дням недели
Отправлено: sam от 18 Декабря 2015, 19:38:07
В какой конкретной директиве этот custom.php?

Подойдет ли такой код?:
public function getDeliveryDate() {
  if (пятница, суббота, воскресенье) {
    return 'вторник и позже';
  } else {
    return 'завтра и позже';
  }
}
И последний связанный вопрос - откуда система поймет, что, например, сегодня "пятница, суббота или воскресенье"?
Название: Re: Проверка по дням недели
Отправлено: e.ioffe от 19 Декабря 2015, 13:59:30
В php есть функция date, которая при определенном параметре возвращает текущий день недели - http://php.net/manual/ru/function.date.php

Файл custom.php находится в папке /classes/modules/
Название: Re: Проверка по дням недели
Отправлено: sam от 19 Декабря 2015, 23:46:00
Спасибо! Тут я все же вижу один минус - если обновить версию системы, данный custom.php тоже обновиться, и наш с вами макрос исчезнет. А если сделать это с помощью xslt, тогда нет, так как шаблоны при обновлении версий не меняются.

Может можно решить эту задачу через xslt, или Вы убедите меня в обратном?
Название: Re: Проверка по дням недели
Отправлено: e.ioffe от 20 Декабря 2015, 00:06:05
При обновлении системы файл custom.php не обновляется.
Название: Re: Проверка по дням недели
Отправлено: sam от 20 Декабря 2015, 20:04:21
1. Ясно. Переубедили. Просьба, пока не реализовывал еще, мой переделанный конечный вариант проверите?

public function getDeliveryDate() {
  if (friday) {
    return 'понедельник и позже';
  } else if (saturday, sunday) {
    return 'вторник и позже';
  } else {
    return 'завтра и позже';
  }
}
2. И если я правильно понял, код надо ставить после комментария "//TODO: Write your own macroses here".

3. И последнее - искал, не смог найти, как сделать вызов макроса в xslt?!
Название: Re: Проверка по дням недели
Отправлено: e.ioffe от 20 Декабря 2015, 21:38:41
1. С точки зрения логики, код правильный.
2. Да.
3. http://wiki.umisoft.ru/%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BA%D0%B0%D1%81%D1%82%D0%BE%D0%BC%D0%BD%D1%8B%D1%85_%D0%BC%D0%B0%D0%BA%D1%80%D0%BE%D1%81%D0%BE%D0%B2_%D0%B2_XSLT
Название: Re: Проверка по дням недели
Отправлено: sam от 21 Декабря 2015, 01:13:33
Спасибо! Но, не получилось у меня ничего. Что-то неправильно делаю, причем, если я правильно понимаю, ошибка при вызове макроса (на 78 строке вызов макроса):
Цитировать
Warning: XSLTProcessor::transformToXml() [xsltprocessor.transformtoxml]: Invalid number of arguments in /docs/classes/system/subsystems/umiTemplaters/types/umiTemplaterXSLT.php on line 53

Warning: XSLTProcessor::transformToXml() [xsltprocessor.transformtoxml]: runtime error: file /docs/xsltTpls/modules/catalog/object-view.xsl line 78 element value-of in /docs/classes/system/subsystems/umiTemplaters/types/umiTemplaterXSLT.php on line 53

Warning: XSLTProcessor::transformToXml() [xsltprocessor.transformtoxml]: XPath evaluation returned no result. in /docs/classes/system/subsystems/umiTemplaters/types/umiTemplaterXSLT.php on line 53

Вызов делал, как уже писал, так: <xsl:value-of select="document(concat('udata://custom/getDeliveryDate()/'))/udata" /> (пробовал в конце udata убирать, тоже не помогло).

Что я не так делал, или как мне устранить эту ошибку?
Название: Re: Проверка по дням недели
Отправлено: e.ioffe от 21 Декабря 2015, 07:39:04
Нужно убрать concat
Название: Re: Проверка по дням недели
Отправлено: sam от 22 Декабря 2015, 00:45:52
Ничего не могу понять?! Макрос вставил куда надо, вызов тоже сделал:
.../classes/modules/custom.php
		после //TODO: Write your own macroses here
public function getDeliveryDate() {
if (friday) {
return 'понедельник и позже';
} else if (saturday - sunday) {
return 'вторник и позже';
} else {
return 'завтра и позже';
}
}

.../object-view.xsl
<xsl:value-of select="document('udata://custom/getDeliveryDate()/')/udata" />
А вместо нужной информации сообщение:
Цитировать
Method custom::getDeliveryDate() doesn't exists
А XML выводит следующее:
Цитировать
<udata module="custom" method="getDeliveryDate" generation-time="0.007301">понедельник и позже</udata>

Что не так?
Название: Re: Проверка по дням недели
Отправлено: sam от 22 Декабря 2015, 10:38:49
А еще, если обратить внимание, и XML неправильную информацию выводит - вместо "завтра и позже" там "понедельник и позже".
Название: Re: Проверка по дням недели
Отправлено: sam от 22 Декабря 2015, 13:49:58
Решил идти еще одним путем - сделал так:
		public function getDeliveryDate() {
echo "Hello World!";
}
Вызвал это из адресной строки - mydomain/udata://custom/getDeliveryDate - на белом экране получил "Hello World!".

Дальше попробовал вызвать тоже самое из шаблона так - <xsl:value-of select="document('udata://custom/getDeliveryDate()/')/udata" />,
И опять получил это же сообщение - "Method custom::getDeliveryDate() doesn't exists"

Ничего не могу понять?!
Название: Re: Проверка по дням недели
Отправлено: sam от 22 Декабря 2015, 17:36:28
Одну свою ошибку я нашел - xsl-вызов был неправильный, вернее "()" были лишними при вызове - для сравнения пишу оба:
<xsl:value-of select="document('udata://custom/getDeliveryDate()/')/udata" /> // неправильный вызов
<xsl:value-of select="document('udata://custom/getDeliveryDate/')/udata" /> // правильный вызов

Теперь надо как-то разобраться с самим макросом, чтобы проверка была правильной - за советы и помощь буду признателен!
Название: Re: Проверка по дням недели
Отправлено: sam от 22 Декабря 2015, 18:46:47
Не судите строго за все мои предыдущие сообщения - я не программист! Но, тем не менее, методом "проб и ошибок" я сделал вроде бы рабочий макрос (по текущему дню каждую строку проверял - if/elseif/else):
		public function getDeliveryDate() {
$weekday = date('l');
if ($weekday == 'Friday') {
return 'понедельник и позже';
} elseif (($weekday == 'Saturday') || ($weekday == 'Sunday')) {
return 'вторник и позже';
} else {
return 'завтра и позже';
}
}
<xsl:value-of select="document('udata://custom/getDeliveryDate/')/udata" />
Буду признателен за комментарии, и буду рад, если кому-то это будет полезно!

P.S. e.ioffe большое спасибо за советы и помощь!
Название: Re: Проверка по дням недели
Отправлено: crazygeorgio от 22 Декабря 2015, 20:22:08
я бы использовал switch case, читается лучше

public function getDeliveryDate() {
  $weekday = date('w');
  switch($weekday) {
      case 5:
        return 'понедельник и позже';
      break;
      case 6: case 0:
        return 'вторник и позже';
      break;
      default:
        return 'завтра и позже';
      break; 
  }
}

еще Евгений как-то рекомендовал выносить кастомные методы в модули, а не прямо в custom.php
         

Название: Re: Проверка по дням недели
Отправлено: sam от 22 Декабря 2015, 21:19:38
У этой темы еще есть продолжение: есть вызов наличии товара <xsl:value-of select="//property[@name = 'available']/value/item/@name" />

Подобно тому, как ниже, надо сделать проверку по "ожидается поставка"/"поставка на заказ"
						<xsl:choose>
<xsl:when test="условие если_available_value_равен_ожидается поставка_или_поставка на заказ">
<xsl:text>после прихода</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="document('udata://custom/getDeliveryDate/')/udata" />
</xsl:otherwise>
</xsl:choose>
Подскажете, что написать вместо "условие если_available_value_равен_ожидается поставка_или_поставка на заказ" в коде выше?
Название: Re: Проверка по дням недели
Отправлено: crazygeorgio от 22 Декабря 2015, 22:15:36
мне кажется проверку лучше по id делать, название могут и поменять, а id останется
<xsl:choose>
  <xsl:when test=".//property[@name = 'available']/value/item/@id = XXX or .//property[@name = 'available']/value/item/@id = YYY">
    <xsl:text>после прихода</xsl:text>
  </xsl:when>
  <xsl:otherwise>
    <xsl:value-of select="document('udata://custom/getDeliveryDate/')/udata" />
  </xsl:otherwise>
</xsl:choose>
Название: Re: Проверка по дням недели
Отправлено: sam от 22 Декабря 2015, 22:21:28
Я так и поступил, т.е. нашел, что по id лучше сделать проверку, только никак не мог написать проверку одновременно для двух id, Вы подсказали. Спасибо!
Название: Re: Проверка по дням недели
Отправлено: e.ioffe от 23 Декабря 2015, 10:45:02
Метод вызывается так, без скобок udata://custom/getDeliveryDate/
Название: Re: Проверка по дням недели
Отправлено: sam от 23 Декабря 2015, 13:45:17
e.ioffe спасибо! Я нашел, что метод вызывается, как Вы написали. И с макросом разобрался. И еще проверку на "available" в xslt сделал (по id статуса), только потом переделал - когда товар в наличии, то выводится инфо. из макроса, а во всех остальных случаях инфо. xsl:text "после прихода".

Если подскажете, я бы в макрос добавил еще - $holidays = 00/00/0000, 00/00/0000 и т.д., чтобы в праздники выводить иную информацию о сроках доставки (первый if не должен противоречить второму). Как это правильно сделать?
		public function getDeliveryDate() {
$weekday = date('l');

$holidays = 00/00/0000, 00/00/0000...; // Здесь должны быть даты праздников - как правильно их написать? Ниже проверка

if ($weekday == 'Friday') {
return 'понедельник и позже';
} else if (($weekday == 'Saturday') || ($weekday == 'Sunday')) {
return 'вторник и позже';
} else {
return 'завтра и позже';
}

if ($holidays == '?!') { // Например, если завтра дата праздника, то уже сегодня инфо. из return ниже
return 'после праздника';
} else ($holidays == '?!') { // И если сегодня день праздника, то инфо. см. return ниже
return то, что обычно, т.е. первые три условия из макроса;
}

}
Название: Re: Проверка по дням недели
Отправлено: crazygeorgio от 23 Декабря 2015, 13:55:29
все-таки настаиваю

public function getDeliveryDate() {
  $weekday = date('w');//от 0 до 6, 6-суббота, 0-воскресенье
  $day = date('d/m/Y');
  $holidays = array('31/12/2015', '01/01/2016', '07/01/2016');
  if (in_array($day, $holidays)) {
    $weekday = 7;//для праздников
  }
  switch($weekday) {
      case 5:
        return 'понедельник и позже';
      break;
      case 6: case 0:
        return 'вторник и позже';
      break;
      case 7:
        return 'после праздника';
      break;
      default:
        return 'завтра и позже';
      break; 
  }
}
Название: Re: Проверка по дням недели
Отправлено: sam от 23 Декабря 2015, 14:47:20
Спасибо! Если это рабочий вариант (не испытывал еще), то почему-бы и нет. Просто вариант от e.ioffe уже испытан на практике.
if (in_array($day, $holidays)) - это я правильно понимаю, что, "если содержимое формат_даты/дата равна дате праздника, указанной в праздники, то день недели равен 7 (т.е. присвоили сами), а дальше проверка - включающая в себя этот условно седьмой день "?
И, crazygeorgio испытан ли подобный вариант на практике? И как интервал по дате праздников сделать, например, с 31.12.2015 по 11.01.2016?
Название: Re: Проверка по дням недели
Отправлено: crazygeorgio от 23 Декабря 2015, 15:10:16
мне то что испытывать) у меня такой задачи нет) понимаете все правильно

для интервала наверное нужно делать отдельно проверку по временной метке timestamp, либо в массив вбивать все 12 дней, в любом случае праздников не так много, ну будет там массив из десятков двух-трех значений, не так много на мой взгляд, единственное что каждый год список нужно обновлять, ну его можно в принципе задать в каком-нибудь справочнике в системе и из-него подтягивать значения
Название: Re: Проверка по дням недели
Отправлено: sam от 23 Декабря 2015, 15:34:25
Сократил дату до 4-х значений, вместо 8-и - год убрал, чтобы массив не перегрузить:
public function getDeliveryDate() {
$weekday = date('w'); //from 0 to 6, 6-Saturday, 0-Sunday
$day = date('d/m');
$holidays = array('01/01', '02/01', '03/01', '04/01', '05/01', '06/01', '07/01', '08/01', '09/01', '10/01' '22/02', '07/03', '30/05', '08/05', '11/06', '03/11', '31/12'); // с 31.12 по 10.01 полностью праздники
if (in_array($day, $holidays)) {
$weekday = 7; //For holidays
}
switch($weekday) {
case 5:
return 'понедельник и позже';
break;
case 6: case 0:
return 'вторник и позже';
break;
case 7:
return 'после праздника';
break;
default:
return 'завтра и позже';
break; 
}
}
А можно в этот-же макрос включить вчерашнюю проверку "//property[@name = 'available']/value/item/@id = '10694' or //property[@name = 'available']/value/item/@id = '10695'" return "после прихода", чтобы в xslt не делать проверку?
Название: Re: Проверка по дням недели
Отправлено: crazygeorgio от 23 Декабря 2015, 16:00:52
что-то вроде этого должно быть, но нужно передавать параметр id элемента в метод

public function getDeliveryDate($element_id = false) {
        if($element_id)  {
          $element = umiHierarchy::getInstance()->getElement($element_id);

          if (!$element instanceof umiHierarchyElement) {
             // выбрасываем исключение
             throw new publicException(getLabel('error-page-does-not-exist'));
          }
          $available = $element->getValue('available');
        }
$weekday = date('w'); //from 0 to 6, 6-Saturday, 0-Sunday
$day = date('d/m');
$holidays = array('01/01', '02/01', '03/01', '04/01', '05/01', '06/01', '07/01', '08/01', '09/01', '10/01' '22/02', '07/03', '30/05', '08/05', '11/06', '03/11', '31/12'); // с 31.12 по 10.01 полностью праздники
if (in_array($day, $holidays)) {
   $weekday = 7; //For holidays
}
        if (isset($available) && $available == 10694) {
           $weekday = 8;
        }

switch($weekday) {
case 5:
return 'понедельник и позже';
break;
case 6: case 0:
return 'вторник и позже';
break;
case 7:
return 'после праздника';
break;
case 8:
return 'после прихода';
break;
default:
return 'завтра и позже';
break; 
}
}
Название: Re: Проверка по дням недели
Отправлено: sam от 23 Декабря 2015, 16:19:28
Цитировать
что-то вроде этого должно быть, но нужно передавать параметр id элемента в метод

Ничего не понял - разве, что могу попробовать расшифровать Ваши действия: прежде, чем задать переменную $available, нашли $element_id, дальше проверку тоже не совсем понял, затем задали уже переменную наличии товара, после чего добавили еще одно условие, если наличие равняется "10694", задали цифровое значение, далее вывели текст.

P.S. Просто, извиняюсь, как выше писал - я не программист, потому Вам приходится меня за руку водить!
Название: Re: Проверка по дням недели
Отправлено: crazygeorgio от 23 Декабря 2015, 16:50:14
все страницы в umi это элементы, у всех них есть уникальный идетификатор id, они выводятся во всех стандартных макросах xslt

<udata module="catalog" method="getObjectsList" generation-time="0.009930">
  <lines>
    <item id="45" alt_name="homyachok_pushistyj" link="/market/hamsters/homyachok_pushistyj/"
     xlink:href="upage://45">Хомячок пушистый</item>
    <item id="47" alt_name="homyachok_obychnyj" link="/market/hamsters/homyachok_obychnyj/"
     xlink:href="upage://47">Хомячок обычный</item>
    <item id="48" alt_name="homyachok_na_kolesah" link="/market/hamsters/homyachok_na_kolesah/"
     xlink:href="upage://48">Хомячок на колесах</item>
    <item id="50" alt_name="homyachok_smile" link="/market/hamsters/homyachok_smile/"
     xlink:href="upage://50">Хомячок с улыбкой</item>
    <item id="54" alt_name="testovyj_homyak" link="/market/hamsters/testovyj_homyak/"
     xlink:href="upage://54">Тестовый хомяк</item>
  </lines>
  <total>9</total>
  <per_page>10</per_page>
  <category_id>44</category_id>
  <type_id>772</type_id>
</udata>

так вот id нужно передать в макросе <xsl:value-of select="document(concat('udata://custom/getDeliveryDate/',id))/udata" />

только вот конструкцию для id нужно смотреть как записать, все зависит от того в каком месте вызывается макрос

далее в методе производится проверка передан ли параметр или нет, если передан, то получаем страницу, если получили страницу получаем значение поля available, устанавливаем переменную, далее если переменная установлена и ее значение равно нужному назначаем значение для вывода текста
Название: Re: Проверка по дням недели
Отправлено: sam от 23 Декабря 2015, 17:06:31
Вызов будет произведен из object-view.xsl после цены, наличии и информации о стоимости доставки. Как в таком случае вызвать макрос?

И еще, обязательно сделать следующую проверку - нельзя убрать это (наличие всегда имеет какой-либо статус)?
if (!$element instanceof umiHierarchyElement) {
throw new publicException(getLabel('error-page-does-not-exist'));
}

И последнее - можно ли код сделать так, как было при xslt - если available=10692 (есть в наличии) то выводить инфо из case 5, case 6, case 0, case 7, default (что-то одно в зависимости от условия), а при остальных статусах (нет, ожидается, под заказ и т.д.) выводить case 8?
Название: Re: Проверка по дням недели
Отправлено: crazygeorgio от 23 Декабря 2015, 17:28:37
тогда скорее всего <xsl:value-of select="document(concat('udata://custom/getDeliveryDate/',page/@id))/udata" />

можно и не делать проверку

        if (isset($available) && $available != 10692) {
           $weekday = 8;
        }
Название: Re: Проверка по дням недели
Отправлено: sam от 23 Декабря 2015, 19:39:12
1. Если я правильно понял по коду, если статус не равно "есть в наличии", то выводить "после прихода" - правильно?
        if (isset($available) && $available != 10692) {
           $weekday = 8;
        }
2. И еще, вот конечный код - все ли верно?
		public function getDeliveryDate() {
if ($element_id) {
$element = umiHierarchy::getInstance()->getElement($element_id);
$available = $element->getValue('available');
}
$weekday = date('w'); //from 0 to 6, 6 - saturday, 0 - sunday
$day = date('d/m');
$holidays = array('31/12', '01/01', '02/01', '03/01', '04/01', '05/01', '06/01', '07/01', '08/01', '09/01', '10/01', '22/02', '07/03', '30/05', '08/05', '11/06', '03/11');
if (in_array($day, $holidays)) {
$weekday = 7; //for day equals holidays
}
if (isset($available) && $available != 10692) {
$weekday = 8; //for is not available
}
switch($weekday) {
case 5:
return 'понедельник и позже';
break;
case 6: case 0:
return 'вторник и позже';
break;
case 7:
return 'после праздника';
break;
case 8:
return 'после прихода';
break;
default:
return 'завтра и позже';
break; 
}
}
Название: Re: Проверка по дням недели
Отправлено: crazygeorgio от 23 Декабря 2015, 19:57:35
ну вроде должно быть все верно, проверьте как работает
Название: Re: Проверка по дням недели
Отправлено: sam от 23 Декабря 2015, 20:12:55
OK! Спасибо! Ночью буду испытывать. Напишу, если что-то пойдет не так.
Название: Re: Проверка по дням недели
Отправлено: sam от 24 Декабря 2015, 00:18:50
Попробовал макрос вместе с вызовом - в качестве праздничного дня для проверки, взял сегодняшний день, инфо из case 7 выводится (после праздника), но система выводит следующую ошибку:
Цитировать
Notice: Undefined variable: element_id in /docs/classes/modules/custom.php on line 12

На этой 12-й строке if ($element_id). Проверка на переменную есть, а самой переменной нет, видимо на это?! К чему должна равняться эта переменная - $element_id = ?!

И еще, есть одно противоречие - когда наличие товара равно "под заказ"/"ожидается", и в праздничные дни должно выводиться case 8 (после прихода), а выводится case 7 (после праздника)?! Как это противоречие исправить?

А когда не праздничный/обычный день, выводится default (завтра и позже) для любого статуса, будто это "в наличии", "под заказ" или "ожидается", а согласно нашему условию должна производиться проверка, и выводиться соответствующая информация.

P.S. После всего, мне хочется вернуться к варианту от e.ioffe, и начать испытывать все на том варианте - если с этим вариантом не справлюсь, так и поступлю, думаю.
Название: Re: Проверка по дням недели
Отправлено: crazygeorgio от 24 Декабря 2015, 04:04:20
написал же выше, что нужно передавать переменную!!! public function getDeliveryDate($element_id = false) { исправьте и тогда уже посмотрите что дальше
Название: Re: Проверка по дням недели
Отправлено: sam от 24 Декабря 2015, 11:01:21
Спасибо! Как раз это я и не перенёс. Теперь вроде все работает, согласно логике макроса, без противоречий. Протестировал по-разному - если сегодня праздник - в наличии - доставка "после праздника", а для отсутствующих товаров "после прихода", если выходные дни, то такая-же логика - в наличии - доставка "понедельник/вторник и позже", а для отсутствующих "после прихода".
Теперь, только раз в год даты новогодних праздников отредактировать - у всех остальных даты не меняются.
Название: Re: Проверка по дням недели
Отправлено: crazygeorgio от 24 Декабря 2015, 14:27:58
бывает что и меняются, перенос дней и все такое... так же как и не все выходные бывают выходными по этой же причине)