Return error page if field value is something

I often have kind of the same problem. Here I have a tiny code that does not work.

How do I return/visit the error page if (in this case) the field key status has the value unpublished?

kirby()->routes(array( 
  array(
    'pattern' => '(.+)', 
    'action'  => function() {
      if( $page->status === 'unpublished' ) {
        return site()->visit('error');
      }
    }
  ),
));

Lessons learned:

  • $page is not passed to the route. Route is inited before the $page is set.
  • The (:all) don’t work. 368.

Be creative!

What about using a shared controller for all pages and do the magic there?

This should work:

kirby()->routes(array(
  array(
    'pattern' => '(.+)',
    'action'  => function($uri) {
      $page = page($uri);
      if( $page->status()->value() === 'unpublished' ) {
        return site()->visit('error');
      }
      else {
          return site()->visit($page);
      }
    }
  ),
));

Edit: I added an else statement.

@flokosiol

Interesting that you reply to my topic with my own answer. :slight_smile: Maybe that could be a solution in the future.

getkirby/kirby/issues/423

@texnixe

That does only work for single language sites. Else it will not match. I have found that it’s possible to get the “original” url in the server variable, like this:

print_r( substr( $_SERVER['HTTP_REFERER'], 0, -5 ) );

I have not found a way to remove the stuff in the beginning safely enough. I also don’t know how reliable it is.

For me it returns:

http://localhost/status/panel/pages/projects

So, no good enough solution yet. More ideas are welcome.

Update

The $_SERVER['HTTP_REFERER']only seems to be active when logged in to the panel so that solution is out of the question.

Yes, you are right, multi-lang sites and routes are difficult: Routes in multi-lang setup

1 Like

I tried your suggestion a little bit more because it’s still possible to use a site controller in 2.3, just not with a plugin yet.

<?php
return function($site, $pages, $page) {
  $errorPage = site()->errorPage();
  echo site()->visit(  $errorPage->uri() );
  die;
};

I did not get the visit function to work. Maybe it will only work inside a route? It output error instead of the template.

// Loads the error page with default template
return function($site, $pages, $page) {
  $page = site()->errorPage();
  $template = tpl::load(
    kirby()->roots()->templates() . DS . 'default.php',
      array(
        'site' => $site,
        'pages' => array(),
        'page' => $page,
      )
    );
  echo $template;
  die;
}

I also tried to load a template, but because it loses the variables in the snippets it does not work.

Workaround

The closest thing I have for a solution is a site.php controller with a header::redirect.

It redirects to the error page. Not perfect but the best I could come up with.

<?php
return function($site, $pages, $page) {
  if( $page->status()->value() === 'unpublished') {
    $errorPage = site()->errorPage();
      if( $page->uri() != $errorPage->id() ) {
        header::redirect($errorPage->url(), 301);
      }
  }
};

@lukasbestle

You set this to solved. You think this is the best solution right now then?

There’s always a better solution, but I think yours is just fine. It’s a more elegant equivalent of putting:

<?php if($page->status() == 'unpublished') { go('error'); die(); } ?>

in the first line of the template.

Do you want this to apply to all pages of the site? The default controller is only a fallback if there is no specific page controller. So wouldn’t it then make more sense to put that bit of code into the header snippet?

1 Like

@lukasbestle

I don’t know if it would work if the error config is changed?

go can not be used with a redirect code, but I hope that will change. I even added an issue for it 160.

@texnixe

I thought when we finally have a global controller site.php we could use that, but as you say it’s just a fallback and it would still not be nice if we have 10 controllers. The problem remains.

The header snippet still seems to be the only good option in this case.

Thank you both!

Well, you could always use go($site->errorPage()), but normally the error option won’t be changed later on, so I haven’t yet needed that.

1 Like