tags:

views:

50

answers:

2

I have a WordPress driven website and I need to be able to close the site at a moment's notice. I need some help to work out a way to do that whereby a php script will check a remote file (xml, php, whatever) hosted on another server to check for a variable (ie. website=closed). If variable is present then close the site with a message such as "Website temporarily closed". Does anyone have any tips on how to go about doing this, or know of any resources I can access.

WordPress knowledge = good / PHP knowledge = beginner

Thanks :-)

A: 

You could install a maintenance mode plugin, then within that code find the trigger to turn on maintenance mode, then inject a function (curl, for instance) that checks the other site for your variable. For example, if you choose to use the plugin mentioned above, in maintenance-mode.php line 46 checks to see if you've turned on maintenance mode:

if (substr($this->g_opt['mamo_activate'], 0, 2)=='on'){... 

you can add a function to maintenance-mode.php that checks for your variable:

function check_for_external_var(){
    $crl = curl_init();
    curl_setopt($crl, CURLOPT_URL, "example.com");// set url
    curl_setopt($crl, CURLOPT_RETURNTRANSFER, 1);//return page as string
    return curl_exec($crl);//return string
    curl_close($crl);//close curl connection
}

then assuming your external site returns on for maintenance mode on, and off for maintenance mode off, you can add to the maintenance-mode.php if statement like so:

if (substr($this->g_opt['mamo_activate'], 0, 2)=='on' || check_for_external_var()=='on'){...

this will check to see if either maintenance mode has been turned on from within the wordpress admin, or your external site; in either case it will activate maintenance mode.


EDIT:

Actually the above will not work the way (I think) you are looking for.

The only reason I can think of to have an external var somewhere shut down your site is so that you can turn off multiple sites at the same time. Is this close?

If that is the case, it would make more sense to have a script on the external site that does a GET to your WP installs that puts them into maintenance mode. To do it from within the site that runs the WP install, you'd need to run a script that checked the external site ever n seconds. This would create a lot of overhead, and could possible be unreliable.

A better solution would be to have a script on the external site that when accessed would do a get to a URL on your WP install that would initiate maintenance mode.

stormdrain
Thanks stormdarin :-) Shutting down multiple sites is the desired outcome... but how might I go about scripting the get?
Niels Oeltjen
I added another (long) answer... Hope it helps...
stormdrain
+1  A: 

OK, I was bored so I spent some time on this today :)

Apparently, there is an inbuilt function within WP to allow the site to go into maintenance mode. All there needs to be is a file in the root of the WP install, and it needs to be named .maintenance - in the same way .htaccess files get named with a leading period (this designates the file as hidden) and no extension.

So, create the .maintenace file in the root of your WP install (should be on the same level as wp-config.php, wp-login.php etc). In this file add the following:

<?php $upgrading = time(); ?>

this tells WP the site is in maintenance mode. NOTE: with this file in the directory as-is, the site will be inaccessible.

You can modify the look and feel of the maintenance mode message, and even put a timer on it so that the site will come back on after a certain amount of time. See here for more info.

With this in place, check the site to make sure maintenance mode is coming on. If it is, rename .maintenance to .maintenance_off. This will be our default state for this file; it will sit there named .maintenance_off allowing the site to function normally until you want to turn maintenance mode on when it will be renamed to .maintenance.

I'm already tired of writing maintenance mode, so from here on in I will be referring to maintenance mode as m-m, ok?

So now for the scripts;

On each of your WP installs that you want to be able to turn this on and off with, you will need 2 things:

  • the .maintenance_off file explained above;
  • a php script to do the renaming:

create a file called remote_maint.php in the root of your WP install, on the same level as your .maintenance_off file. In it add the following:

<?php

$p=$_GET;

/*
this is just some basic auth; not safe, not secure, but better than nothing. 
Change the key to something more complicated. Though, because we're using GET,
even if it's really complicated, it's still not secure. You should really improve
this if you don't want random people putting your WP installs into maintenance mode...
*/
$key='test';

//if mode==on, use turn_on() function otherwise use turn_off() function
($p['mode']=='on')?turn_on($p):turn_off($p);

function turn_on($p){
    //if the key in the request matches our key here, rename the file, otherwise set page header as unauthorized
    ($p['key']==$key)?rename('.maintenance_off','.maintenance'):header("HTTP/1.0 401 Unauthorized");
}

function turn_off($p){
    //if the key in the request matches our key here, rename the file, otherwise set page header as unauthorized
    ($p['key']==$key)?rename('.maintenance','.maintenance_off'):header("HTTP/1.0 401 Unauthorized");
}

?> 

OK, as the comments state, the "security" isn't secure. You should improve it... If it's any consolation, if someone did get the key you decide to use, the worst they could do is put your site into m-m.

What this script does is check the request to the page, example:

http://site.com/remote_maint.php?mode=on&amp;key=test

this request would tell the script that the mode is on and the key is test. The first ternary operation will see the mode is on and call the turn_on() function, sending with it the $_GET array which has been assigned to the variable $p. The turn_on() function will then check the key sent in the request ($p['key']) against the key set at the top of the script ($key); if it matches it will rename .maintenance_off to .maintenance effectively turning m-m on. If the key does not match the request, it sets the header of the page to 401 Unauthorized, see below.


With this all in place, time for the Central Command; the code that will be doing the calling. In my testing, I went with jQuery so that it would be possible to turn m-m on and off on multiple sites from the same page without reloading.

On another site, or wherever you want to administer the m-m, create a page called remote_maint_admin.php (actually it doesn't have to be .php, can be .html, or whatever), and add the following:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Remote Maintenance</title>
<script src="js/jquery.js"></script>
</head>
<body>
<div id='main'>
    <fieldset>
        <legend>site 1</legend>
        <div id='site-1' style='border:0px solid #000'>
            Auth key:
            <input type="text" id='key-1' size="30"/>
            <input type="button" value="Turn on" onClick="change_mode('on','http://site.com/','1');" />
            <input type="button" value="Turn off" onClick="change_mode('off','http://site.com/','1');" />
        </div>
        <br>
        <div id='status-1' style='border:1px solid #ccc;color:#666'>Status</div>
    </fieldset>
</div>
    <script>
    function change_mode(mode,url,id){
        var key = $('#key-'+id).attr('value');
        var url=url+'remote_maint.php?mode='+mode+'&key='+key;
        $.ajax({
            url:url,
            type: 'GET',
            complete: function(){
                $('#status-'+id).html('<b>Request Completed');
            },
        });
    }
    </script>       
</body>

change http://site.com/ to your url. To add more sites, copy the main div and repeat it:

<div id='main'>
    <fieldset>
        <legend>site 2</legend>
        <div id='site-2' style='border:0px solid #000'>
            Auth key:
            <input type="text" id='key-2' size="30"/>
            <input type="button" value="Turn on" onClick="change_mode('on','http://site2.com/','2');" />
            <input type="button" value="Turn off" onClick="change_mode('off','http://site2.com/','2');" />
        </div>
        <br>
        <div id='status-2' style='border:1px solid #ccc;color:#666'>Status</div>
    </fieldset>
</div>

here's another happy little div over here to manage another site

<div id='main'>
    <fieldset>
        <legend>site 3</legend>
        <div id='site-3' style='border:0px solid #000'>
            Auth key:
            <input type="text" id='key-3' size="30"/>
            <input type="button" value="Turn on" onClick="change_mode('on','http://site3.com/','3');" />
            <input type="button" value="Turn off" onClick="change_mode('off','http://myothersite.com/','3');" />
        </div>
        <br>
        <div id='status-3' style='border:1px solid #ccc;color:#666'>Status</div>
    </fieldset>
</div>

...and change the input id number (e.g. id='key-1' to id='key-2' and status id number (e.g. id='status-1' to id='status-2' and the javascript call (e.g onClick="change_mode('on','http://site.com/','1');" to onClick="change_mode('on','http://myothersite.com/','3');" respectively for each site you want to add...

Now when you enter your key into the textbox and hit Turn on or Turn off, the js will take your key and the mode (depending on which button you hit) and send it to the other server. If the key matches, m-m will be turned on or off, and the div below the buttons will update and say that the request completed. If the key doesn't match, The div below the buttons will still say request completed, though m-m won't change. I was thinking I could update the status div with the returned status code of the page which is why I set the header to 401 if it failed, but because of the same origin policy, cross site request status codes are always returned as 0. However, if you use a tool like Firebug, you can watch the console there to see if the request actually fails...

HTH

stormdrain
What can I say but THANK YOU SO MUCH!!! SO pleased you were bored :-)Thanks for such a considered solution, and for the thorough explanation (including comments). I have already learned a lot more about PHP thanks to that explanation. I'll let you know how it goes but you've at least sent me 95% of the way there with only the security to consider.Again, thanks so much!!!
Niels Oeltjen
Glad I was able to help. If you wouldn't mind, please mark the answer as the solution to your question. http://meta.stackoverflow.com/questions/5234/how-does-accepting-an-answer-work/5235#5235 Cheers!
stormdrain