Задача: создание календаря(datepicker) с диапазоном дат, фильтрация мероприятий вошедших в диапазон выбранных дат по двум параметрам: 1 - ежедневность 2 - конкретная дата мероприятия.
НЕОБХОДИМО
Создаём собственный фильтр:
[[!mFilter2?
&element=`pdoResources`
&tpl=`tpl_chunk` // Чанк оформления всего блока фильтров и результатов.
&parents=`[[*id]]` // Список категорий, через запятую, для ограничения вывода результатов.
&limit=`999` // Лимиты
&depth=`0` // Глубина поиска
&filters=`tv| everyday_date:Everyday` // Список фильтров ресурсов, через запятую.
&includeTVs=`everyday_date` // Список ТВ параметров для выборки, через запятую.
&sort=`resource| menuindex:asc` // Сортировка.
&tplFilter.outer.tv| everyday_date=`tpl.mFilter2.filter.outer` // Стандартный чанк оформления одной группы фильтров.
&tplFilter.row.tv| everyday_date=`tpl.mFilter2.filter.date` // Стандартный чанк оформления одного фильтра в группе.
]]
Указываем в настройках, в параметре mse2_filters_handler_class значение custom_filters
Создаем чанк для вывода календаря tpl.mFilter2.filter.date
<input type="hidden" name="" id="mse2_" value="" />
// блок календаря
<div id="_datepicker"></div>
// стилизация календаря
<link rel="stylesheet" href="//jquery-ui-bootstrap.github.io/jquery-ui-bootstrap/css/custom-theme/jquery-ui-1.10.3.custom.css"/>
<style>
.ui-datepicker .selected-start:not(.selected-end) a,
.ui-datepicker .selected-end:not(.selected-start) a {
background: #F3FDD5;
}
.ui-datepicker .selected.first-of-month:not(.selected-start) a {
border-left: 2px dotted #D4E7F6;
padding-left: 1px;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="https://rawgit.com/Artemeey/5ebc39370e568c34f03dce1639cabee8/raw/8de40b26479c406ee9cd6f9b4b3f4ad05370a024/jquery.datepicker.extension.range.min.js"></script>
<script type="text/javascript">
$ (function() {
// переводим календарь на русский язык
$ .datepicker.regional['ru'] = {
closeText: 'Закрыть',
prevText: '<Пред',
nextText: 'След>',
currentText: 'Сегодня',
monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь',
'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],
monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн',
'Июл','Авг','Сен','Окт','Ноя','Дек'],
dayNames: ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'],
dayNamesShort: ['вск','пнд','втр','срд','чтв','птн','сбт'],
dayNamesMin: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'],
dateFormat: 'yy-mm-dd',
firstDay: 1,
isRTL: false
} ;
$ .datepicker.setDefaults($ .datepicker.regional['ru']);
// при клике устанавливаем период
$ ("#_datepicker").datepicker({
range:'period',
onSelect:function(dateText,inst,extensionRange){
// записываем диапазон через _ пример: 11.12.2017_14.12.2017
var date=extensionRange.startDateText+"_"+extensionRange.endDateText;
// записываем в инпут
$ ('#mse2_').val(date);
// обновляем фильтр
mSearch2.load();
}
} );
} );
</script>
Создаём файл custom.class.php по пути core/components/msearch2/custom/filters/custom.class.php
class custom_filters extends mse2FiltersHandler {
// эта функция обязательна, она работает в паре с filterEveryday
public function buildEverydayFilter(array $ values, $ name = '', $ format = 'Y-m-d', $ sort = 'desc'){
return $ this->buildDateFilter($ values, $ name,$ format,$ sort);
}
// В этой функции и происходит магия, в данном примере будут показываться те ресурсы, у которых в 35 тв указана ежедневность мероприятия, а в 36 тв дата мероприятия, например: указав диапазон 11.12.2017_14.12.2017 покажутся все ресурсы у которых в 36 тв есть любая дата в диапазоне 11.12.2017_14.12.2017 или те ресурсы у которых в 35 тв выбраны любой день недели в диапазоне от ПН до ЧТ(Соответствует датам 11.12.2017-14.12.2017)
public function filterEveryday(array $ requested, array $ values, array $ ids, $ format = 'Y-m-d'){
$ array=array();
// парсим даты в формате Y-m-d_Y-m-d
$ array_date_search=explode('_',$ requested[0]);
$ date_search=$ array_date_search[0];
$ requested[0]=$ date_search;
// формируем массив дней недель выбранного диапазона дат- $ array_week
$ array_week=array();
$ days=(strtotime($ array_date_search[1])-strtotime($ array_date_search[0]))/(60*60*24);
$ dweek_search_n=date('N',strtotime($ array_date_search[0]));
for($ i=0;$ i<7;$ i++){
if($ i>$ days){
break;
}
$ array_week[]=$ dweek_search_n;
$ dweek_search_n++;
if($ dweek_search_n>7){
$ dweek_search_n=1;
}
}
// формируем массив дат в заданом диапазоне - $ array_days
$ start =new DateTime($ array_date_search[0]);
$ end =new DateTime($ array_date_search[1]);
$ step =new DateInterval('P1D');
$ period =new DatePeriod($ start, $ step, $ end);
foreach($ period as $ datetime) {
$ array_days[]=$ datetime->format("Y-m-d");
}
$ array_days[]=$ start->format("Y-m-d");
$ array_days[]=$ end->format("Y-m-d");
// получаем ид ресурсов подходящих нашей выборке
$ sql="
SELECT t1.id, t2.value AS t2_value, t3.value AS t3_value
FROM `a_site_content` AS `t1`
LEFT JOIN `a_site_tmplvar_contentvalues` `t2` ON t2.contentid = t1.id AND t2.tmplvarid = 35
LEFT JOIN `a_site_tmplvar_contentvalues` `t3` ON t3.contentid = t1.id AND t3.tmplvarid = 36
WHERE (
`t1`.`id` IN (".implode(",",$ ids).")
)
";
foreach($ this->modx->query($ sql) as $ row){
// ищем совпадения в двух массивах по дню недели
$ t2_value_array=explode('| | ',$ row['t2_value']);
$ t2_value_intersect=array_intersect($ array_week,$ t2_value_array);
if(count($ t2_value_intersect)>0){
$ array[$ date_search][]=$ row['id'];
} else{
// ищем совпадения в двух массивах по дате
$ t3_value_array=explode(',',$ row['t3_value']);
$ t3_value_intersect=array_intersect($ array_days,$ t3_value_array);
if(count($ t3_value_intersect)>0){
$ array[$ date_search][]=$ row['id'];
}
}
}
if(count($ array_date_search)==1){
foreach ($ values as $ k => $ v){
foreach ($ v as $ k_d => $ v_d){
$ array[$ requested[0]][]=$ v_d;
}
}
}
return $ this->filterDefault($ requested, $ array, $ ids);
}
}
Пример: http://piterguide.ru/ekskursii/sbornyie/sbornyie-tematicheskie-ekskursii/