April 9, 2011

Command Line EE

EE1 Ever needed an easy way to schedule an action with a cron or get your website content from the command line. The code below has everything you need to interact with your EE website using the PHP CLI.

File cli.php

<?php
/**
 * Command Line ExpressionEngine
 *
 * Arguments:
 *  server_[name]=[value]
 *  get_[name]=[value]
 *  post_[name]=[value]
 *  cookie_[name]=[value]
 *  env_[name]=[value]
 *  files_[name]=[value]
 *  session_[name]=[value]
 *  [segment_1] [segment_2] ... [segment_n]
 *
 * Examples:
 * Run action id 12:
 * cli.php get_ACT=12
 *
 * Get page at /site/info
 * cli.php site info
 *
 * Post 'email' to action id 12 on page /site/form/contact
 * cli.php "get_ACT=12" post_email=bjones@test.com site form contact
 *
 * Notes:
 * In order to allow more memory usage or a longer execution time
 * execute with php option -d
 * -d max_execution_time=60 memory_limit=134217728
 *
 * @package   EE-CLI
 * @version   1.0
 * @author    Jeremy Messenger <jlmessengertech+github@gmail.com>
 * @copyright 2011 Jeremy Messenger
 * @license   GPL
 * @link      http://jlmessenger.com
 */

// make sure this isn't being called by a web browser
if (isset($_SERVER['REMOTE_ADDR'])) die('Permission denied.');

/**
 * Constant to identify command line execution thru this script
 */
define('CMD', 1);

// _REQUEST is built automatically later
$superglobals = array('SERVER', 'GET', 'POST', 'COOKIE', 'ENV', 'FILES', 'SESSION');

// manually set the URI path based on command line arguments...
unset($argv[0]); // first argument is this file itself

// parse arguments for overridden superglobals
foreach ($argv as $key => $arg)
{
    $subargs = explode('=', $arg, 2);
    if (count($subargs) == 2)
    {
        $opts = explode('_', $subargs[0], 2);
        if (count($opts) == 2)
        {
            $opts[0] = strtoupper($opts[0]);
            if (in_array($opts[0], $superglobals))
            {
                $gl = '_'.$opts[0];

                if ($opts[0] == 'SERVER')
                {
                    $opts[1] = strtoupper($opts[1]);
                }

                $GLOBALS[$gl][$opts[1]] = $subargs[1];
                unset($argv[$key]);
            }
        }
    }
}

// build _REQUEST from _GET, _POST, & _COOKIE
// build in the same order as defined in php.ini
$requestorder = str_split(ini_get('variables_order'));
foreach($requestorder as $char)
{
    switch($char)
    {
        case 'G':
            $_REQUEST = array_merge($_GET, $_REQUEST);
            break;
        case 'P':
            $_REQUEST = array_merge($_POST, $_REQUEST);
            break;
        case 'C':
            $_REQUEST = array_merge($_COOKIE, $_REQUEST);
            break;
        //case 'E': _ENV
        //case 'S': _SERVER
    }
}

// build required _SERVER vars
// QUERY_STRING from _GET
// PATH_INFO from argv
// REQUEST_URI from the others
$querystring = array();
foreach($_GET as $key => $val)
{
    $querystring[] = urlencode($key).'='.urlencode($val);
}

$_SERVER['SCRIPT_NAME'] = 'index.php';
$_SERVER['PATH_INFO'] = count($argv) ? '/'.implode('/', $argv).'/' : '';
$_SERVER['QUERY_STRING'] = implode('&', $querystring);
$_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'].$_SERVER['PATH_INFO'].'?'.$_SERVER['QUERY_STRING'];

// EE Ouput class assumes that this is set
// and will cause a notice unless we set it
if (!isset($_SERVER['SERVER_PROTOCOL']))
{
    $_SERVER['SERVER_PROTOCOL'] = 'CLI';
}

// no longer needed
unset($superglobals);
unset($requestorder);
unset($querystring);

/**
 * Call up the framework
 */
include('index.php');
?>