Moving pages based on date

I have a page called ‘Projects’, the sub-pages within ‘Projects’ can be split into two categories, upcoming and past which will be distinguished by the date.

I’m having trouble figuring out how best to architect this. Could I do this explicitly, and split the sub-pages amongst two sub-pages ‘Upcoming’ and ‘Past’?

Like this:
projects
____upcoming
________1-example
________2-example
____past
________1-example
________2-example
________3-example

How could I move a page from past to upcoming when the date is past the present? Looking through the documentation it seems I could use a panel.hook?. Is there a more optimal solution to handle this kind of content taxonomy? I would appreciate any ideas?

A hook is not such a great idea, because it depends on Panel actions. No action in the Panel (like creating or deleting or updating a page), no hook triggered.

I wouldn’t split them into categories, but just filter by date in your template.

Edit: moving them to another folder also changes the project’s URL, unless you use routes to prevent that.

If for some reason you do need those two subfolders, you could use a cron job that calls a script that checks if a page needs to be moved at given intervals and then moves the page.

1 Like

The changing of paths is bad from the view of SEO. I‘m sure you should follow texnixe‘s way…

Well, yes, in general, but it all depends on the use case. If you want a page to disappear like an event when it is over, then you might as well move it.

1 Like

The fact of disapearing of a content is different from changing a path for the same content.

Thank you very much for the advice, I think you’re both completely right. It’s best to keep them in the same folder.

Is there a way to update a checkbox field when the date has passed? Would the most suitable way be a cron job as mentioned already?

You don’t need a checkbox field. And you don’t need a cron job if you don’t have to move pages.

Please describe what you want to do with those pages based on date? Do you only want to show future projects? Or both, but on different pages or in different sections?

You can filter just based on date, see these examples: https://getkirby.com/docs/cookbook/filtering#fun-with-filtering-by-date

Or you can group them on upcoming and past, if you map this keyword to the date (that is, sort of create a virtual field to group by).

Apologies, I haven’t been very clear. I thought about doing this from an organizational standpoint within the panel. There will be a few 100 of these ‘Projects’. It was shortsighted as had not thought of the points that yourself and Heiner mentioned. I have now thought about using the Kirby Index plugin and having a column in there which corresponds to a checkbox denoting whether or not the date has passed. Ideally, I would like to update the column automatically when the date passes.

I still don’t get the point of doing this manually with a checkbox. Even in the Panel you can use the index field to just show projects that are upcoming. Or sort them by upcoming first.

Or is it not possible to classify a project as upcoming or past solely based on the date field?

Thanks for replying so swiftly. Yes, The Index field does allow the user to sort them by date. Some ‘Projects’ last longer than a day up until a week, I was just hoping there would be an automated definitive way to categorized them as ‘Passed’ or ‘Upcoming’ not necessarily a checkbox.

The plugin allows you to filter data with a custom data filter, so you could in fact use that to display only upcoming/current projects, that is, check if either the start date or the end date are in the future.

Thanks, I’ve found an example on Github. However, I’m completely sure what is going on. Is $data the ‘Projects’ object and $item each induvidual Project?

class IndexfieldFilters {
  static function thumbnail ($data) {
    foreach ($data as &$item) {
      $p = page($item['uri']);
      $thumb = $p->images()->first()->thumb(['width'=>36])->url();
      $item['thumbnail'] = '<img src="' . $thumb . '">';
    }
    return $data;
  }
}

Blueprint

pageindex:
  label: Items
  type: index
  options: children
  filter: IndexfieldFilters::thumbnail
  columns:
    thumbnail:
      label: 
      width: 36
      sort: false
      class: index-thumbnail
    title: Title

It’s probably an object of arrays, you could dump it to check what it actually contains.

I assume you would have to check the date of each item and then remove the item if it is past. It’s a bit of a pitty that the field doesn’t support options from a controller like here, but that could easily be added.

Sorry if this seems like a silly question but where do put the code to var_dump?

You can do something like this to filter out dates in the past:

<?php

class MyDataFilters {
  static function myfilterfunc($data) {

    foreach($data as $key => $item) {
        $page = page($item['uri']);
        if($page->date() < time()) {
          unset($data[$key]);
        }
    }

    return $data;
  }
}

You can extend this to check for start or end date…

Thanks for the help. I got the error:

Object of class Field could not be converted to int in file: /Users/Sun/git/s-t/www/site/plugins/mydatafields/mydatafields.php on line: 7

I remember trying to format the date modified field into a more readable once before on another project and got the same error. I never managed to resolve it.

This was with the following code:

class IndexFilter {
    static function date($data) {
        foreach($data as $key => $item) {
            $page = page($item['uri']);
            if($page->startdate() < time()) {
                unset($data[$key]);
            }
        }
        return $data;
    }
}

That’s because - other than a date field called date, startdate() returns a field object, not an integer:


 if(strtotime($page->startdate()->value()) < time()) {
1 Like

Thanks you this has solved my needs perfectly

Fine! But please next time, be more specific about what you want to achieve right from the beginning. You get a usable answer faster!