Get dates from interval

Hi !
I’m filtering dates from bastian calendar’s plugin by intervals. Everything is working well, I’m just wondering how to add a class if a date is corresponding to the interval of projects ? I already did some tries but I can’t return the function from the controller to the template, how would you do that ?

with these lines in my controller :

<?php
return function($site, $pages, $page) {

$projects = page('projects')->children()->visible();

$now = date('Y-m-d', time()); // replace 'Y-m-d' with the correct format of your parameter
$date = param('date', $now); // set $now as default if param is empty


if($date = param('date')) {
  $projects = $projects->filter(function($child) use($date) {

    $begin = new DateTime($child->date_from('Y-m-d') );
    $end = new DateTime($child->date_to('Y-m-d'));
    $interval = DateInterval::createFromDateString('1 day');
    $period = new DatePeriod($begin, $interval, $end);

    //create date array for each chilc
    foreach ($period as $dt):
       $dates[] = $dt->format('Y-m-d');
    endforeach;

    if(in_array($date, $dates)) {
      return $child;
    }
  });
}
 return compact('projects');
};

And this is from my calendar with differents classes

<td <?php 
                        $class = null;
                        if($day->month() != $month) {
                            $class = 'inactive';
                        }elseif(in_array($day, $dt)) { 
                            $class = 'event';
                        } // here I would like another ELSEIF with possible values from projects interval
                        if($class) echo 'class="' . $class . '" ';
                        ?>>
                        <a <?php e($day == $activelink, 'class="active"') ?> href="<?php echo url('/projects/' . url::paramsToString(['date' => $day])) ?>"><?php echo ($day->isToday()) ? '<div class="today">' . $dateWithZero . '</div>' : $dateWithZero ?></a>

                    </td>

I’m missing some context here. Maybe you can post the complete template. I assume that table cell is part of a complete monthly calendar…

And what do you mean by possible values from projects interval, can you give an example of what these values are supposed to be?

Of course ! The table is part of the cell month’s calendar. When I click on a day, the template is returning every subpage if this subpage has a date_from to date_to corresponding to that day. But I would like to add a class to days directly inside the calendar : if a subpage has an event between 01-02-2018 and 03-02-2018, three days could have a class to show that there is an event on these days directly inside the calendar.

<ul class="container">
        <?php foreach($currentYear->months() as $month): ?>
        <li class="month">
            <h2><?php echo $month->name() ?></h2>
            <table>

                <?php foreach($month->weeks(6) as $week): ?>

                <tr>  
                    <?php foreach($week->days() as $day): ?>
                    <?php $dateWithZero = date("d", strtotime($day)); ?>
                    <?php $activelink = kirby()->request()->params()->date(); ?>

                    <td <?php 
                        $class = null;
                        if($day->month() != $month) {
                            $class = 'inactive';
                        }elseif(in_array($day, $dt)) { 
                            $class = 'event';
                        }
                        if($class) echo 'class="' . $class . '" ';
                        ?>>


                        <a <?php e($day == $activelink, 'class="active"') ?> href="<?php echo url('/projects/' . url::paramsToString(['date' => $day])) ?>"><?php echo ($day->isToday()) ? '<div class="today">' . $dateWithZero . '</div>' : $dateWithZero ?></a>

                    </td>
                    <?php endforeach ?>  
                </tr>
                <?php endforeach ?>
            </table>
        </li>    
        <?php endforeach ?>
    </ul>

Basically, you would have to wrap your filter stuff from the controller into a function that returns a filtered collection for a particular, so that you can check for each day, if that day does have events or not.

I would not have said it better !
How could I do all these things in a same time ? Using collection::extractValue($item, $field) ?
Actually, I don’t even know how to do that…

As I said, just wrap your filter code in a function:

function getDayEvents($events, $day) {

  // your filter code
  $filteredCollection = ...

  return $filteredCollection;
}

Then call like this

if(getDayEvents($events, $day)->count()):

// do something
endif;

Did you mean to include the function inside the controller like this ? :

return function($site, $pages, $page) {

    $projects = page('projects')->children()->visible();

    $now = date('Y-m-d', time()); // replace 'Y-m-d' with the correct format of your parameter
    $date = param('date', $now); // set $now as default if param is empty

    function getDayEvents($event, $day) {
        if($date = param('date')) {
            $projects = $projects->filter(function($child) use($date) {

                $begin = new DateTime($child->date_from('Y-m-d') );
                $end = new DateTime($child->date_to('Y-m-d'));
                $interval = DateInterval::createFromDateString('1 day');
                $period = new DatePeriod($begin, $interval, $end);

                //create date array for each chilc
                foreach ($period as $dt):
                $dates[] = $dt->format('Y-m-d');
                endforeach;

                if(in_array($date, $dates)) {
                    return $child;
                }
            });
        }
        return $projects;
    }
    return compact('projects');

I also didn’t understand if you intentionally wrote $events to suggests a foreach somewhere ? I tried

                        $class = null;
                        if($day->month() != $month) {
                            $class = 'inactive';
                        }elseif (getDayEvents($event, $day)->count()){ 
                            $class = 'event';
                        }
                        if($class) echo 'class="' . $class . '" ';

but $event or $events are undefined

No, remove the param part, you want to use $daywithin the function, not the parameter. And $events was just an example, in your case it’s $projects, of course… but the name of the function parameter doesn’t matter.

Your function would then look like this:

function getDayEvents($events, $day) {

            $projects = $projects->filter(function($child) use($day) {
                
                $date = $day; // what you do here depends on the type of your day parameter, you have to find a way to deal with the day you get from the calendar and the date you get from your parameter, maybe convert both to Unix timestamp before you pass it to the function
                $begin = new DateTime($child->date_from('Y-m-d') );
                $end = new DateTime($child->date_to('Y-m-d'));
                $interval = DateInterval::createFromDateString('1 day');
                $period = new DatePeriod($begin, $interval, $end);

                //create date array for each chilc
                foreach ($period as $dt):
                $dates[] = $dt->format('Y-m-d');
                endforeach;

                if(in_array($date, $dates)) {
                    return $child;
                }
            });
        return $projects;
}

I’d put this in a plugin file.

You can then use this function in your controller to filter your projects by parameter (by passing the date param as second function param) and in your template to check if there any projects per day.

Thank you very much for writing me the function but I’m afraid I don’t have enough skills. How to use this function in my controller and get the corresponding esleif statement ?

According to to what you said, I tried

controller

if($date = param('getDayEvents', 'date')) {
  $projects = $projects->filter(function($child) use($date) {

    $begin = new DateTime($child->date_from('Y-m-d') );
    $end = new DateTime($child->date_to('Y-m-d'));
    $interval = DateInterval::createFromDateString('1 day');
    $period = new DatePeriod($begin, $interval, $end);

    //create date array for each chilc
    foreach ($period as $dt):
       $dates[] = $dt->format('Y-m-d');
    endforeach;

    if(in_array($date, $dates)) {
      return $child;
    }
  });
}
 return compact('projects');
};

the if statement

if($day->month() != $month) {
                            $class = 'inactive';
                        }elseif (getDayEvents($events, $day)->count()){ 
                            $class = 'event';
                        }
                        if($class) echo 'class="' . $class . '" ';

You can’t use the function inside the param helper.

If you return $projects from your controller, don’t use $events when calling the function.

Instead of repeating the code in the controller, use the function.

If you need someone to do the coding for you, I’m available for freelance work (or someone else here).

Good to know !
I will probably contact someone here for this specific case before trying to get it work by myself.
Thanks for your following

Best