Задача: создание календаря(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="[[+filter_key]]" id="mse2_[[+idx]]" value="[[+value]]" />
// блок календаря
<div id="[[+idx]]_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']);
// при клике устанавливаем период
$("#[[+idx]]_datepicker").datepicker({
range:'period',
onSelect:function(dateText,inst,extensionRange){
// записываем диапазон через _ пример: 11.12.2017_14.12.2017
var date=extensionRange.startDateText+"_"+extensionRange.endDateText;
// записываем в инпут
$('#mse2_[[+idx]]').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 `modx_site_content` AS `t1`
LEFT JOIN `modx_site_tmplvar_contentvalues` `t2` ON t2.contentid = t1.id AND t2.tmplvarid = 35
LEFT JOIN `modx_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/