To begin with, please upgrade your installation to 2.2.15.
You should be able to use the OnPageNotFound event to see if the resource does in fact exist, just isn't published. Unfortunately it doesn't appear as if any information about the page that was requested is provided, so you'd need to process the GET to look for the resource ID yourself.
With friendly URLs on, you need to deal with the 'q=page.html' GET value, which can get interesting if it's using the full path, and if it's using a non-standard suffix. Once you get a resource ID returned, then you can do whatever you want with it in the way of headers.
$id = $modx->resourceIdentifier; $query = $modx->newQuery("modResource", array('id' => $id)); $query->select(array( 'id' => 'id', 'parent' => 'parent', 'published' => 'published' )); if ($query->prepare() && $query->stmt->execute()) { $results = $query->stmt->fetchAll(PDO::FETCH_ASSOC); } if (empty($results)) { $modx->log(modX::LOG_LEVEL_ERROR, '[Forward Plugin] Resource not found with id: ' . $id ); return ''; } if (isset($results['published'] && (! empty($results['published']))) { return ''; } if (isset($results['parent'] && (!empty($results['parent']))) $url = $modx->makeUrl($results['parent'], "", "", "full"); $modx->sendRedirect($url); } return '';
I think best place to catch this before the 404 is thrown would be in a plugin attached to OnHandleRequest. The ID of the resource should be available there as $modx->resourceIdentifier.
This should get you started. If the resources are all in the default context ('web'), you should be able to do this:
$id = $modx->resourceIdentifier; $query = $modx->newQuery("modResource", array('id' => $id)); $query->select(array( 'id' => 'id', 'parent' => 'parent', 'published' => 'published' )); if ($query->prepare() && $query->stmt->execute()) { $results = $query->stmt->fetchAll(PDO::FETCH_ASSOC); } if (empty($results)) { $modx->log(modX::LOG_LEVEL_ERROR, '[Forward Plugin] Resource not found with id: ' . $id ); return ''; } if (isset($results['published'] && (! empty($results['published']))) { return ''; } if (isset($results['parent'] && (!empty($results['parent']))) $url = $modx->makeUrl($results['parent'], "", "", "full"); $modx->sendRedirect($url); } return '';
Be aware that this will ignore resources at the root of the tree, since their parent field contains a 0.
Saving the resource after unpublishing it should clear the cache, but it might not clear the resource map, which could contain the published status. In that case, you might have to call $modx->reloadContext() at the top or your code, which would slow down all page loads.
Let us know if it works.
<?php $id = $modx->resourceIdentifier; $query = $modx->newQuery("modResource", array('id' => $id)); $query->select(array( 'id' => 'id', 'parent' => 'parent', 'published' => 'published' )); if ($query->prepare() && $query->stmt->execute()) { $results = $query->stmt->fetchAll(PDO::FETCH_ASSOC); } if (empty($results)) { $modx->log(modX::LOG_LEVEL_ERROR, '[Forward Plugin] Resource not found with id: ' . $id ); return ''; } if (isset($results['published']) && (!empty($results['published']))) { $modx->log(modX::LOG_LEVEL_ERROR, '[Forward Plugin] Resource published'); return ''; } if (isset($results['parent']) && (!empty($results['parent']))) { $modx->log(modX::LOG_LEVEL_ERROR, '[Forward Plugin] Redirect 302'); $url = $modx->makeUrl($results['parent'], "", "", "full"); $modx->sendRedirect($url); } $modx->log(modX::LOG_LEVEL_ERROR, '[Forward Plugin] Nothing'); return '';
... [2014-10-07 15:19:13] (ERROR @ /index.php) [Forward Plugin] Resource not found with id: [2014-10-07 15:19:13] (ERROR @ /index.php) [Forward Plugin] Resource not found with id: [2014-10-07 15:19:13] (ERROR @ /index.php) [Forward Plugin] Resource not found with id: [2014-10-07 15:19:13] (ERROR @ /index.php) [Forward Plugin] Resource not found with id: [2014-10-07 15:19:13] (ERROR @ /index.php) [Forward Plugin] Resource not found with id: [2014-10-07 15:19:14] (ERROR @ /index.php) [Forward Plugin] Resource not found with id: [2014-10-07 15:19:14] (ERROR @ /index.php) [Forward Plugin] Resource not found with id: [2014-10-07 15:19:14] (ERROR @ /index.php) [Forward Plugin] Resource not found with id: [2014-10-07 15:19:14] (ERROR @ /index.php) [Forward Plugin] Resource not found with id: [2014-10-07 15:19:17] (ERROR @ /index.php) [Forward Plugin] Resource not found with id: ...
$uri = $_SERVER['REQUEST_URI']; /* Use the next line if a subdirectory name is part of the uri */ /* (echo $_SERVER['REQUEST_URI'] in a test snippet to find out) */ // $uri = str_replace('/subdirectory/', '', $uri); $id = $modx->findResource($uri); if empty($id) { /* True page not found, do nothing */ return ''; } /* See if it's published */ $c = $modx->newQuery('modResource', $id); $query->select('published'); $published = $modx->getValue($query->prepare()); if (empty($published)) { /* URL of temporarily unpublished page (I think 302 is the default code) */ $modx->sendRedirect('http://mysite.com/somepaget.html'); } return '';