Create a gist now

Instantly share code, notes, and snippets.

anonymous /CLI.php
Created Dec 28, 2012

CodeIgniter Command Line Add-On described at http://caseymclaughlin.com/articles/codeigniter-on-the-command-line
CodeIgniter CLI Interface
An example CLI interface for CodeIgniter. It accepts command-line arguments,
and sandboxes the application to a single controller for CLI applications.
Installation:
------------------------------------
1. Copy the entry.php file into the root folder (next to the main index.php).
Also, rename it whatever you want (e.g. utils.php, or maint.php)
2. Copy the CLI.php file into your application/libraries folder.
3. Copy the shellcontroller.php file into your application/controllers folder, and
rename it to whatever you want. Delete the example methods, and
have fun!
4. Copy the views/shellcontroller contents into your application/views folder,
and modify to your heart's content!
Limitations
------------------------------------
* Unless you install some other CodeIgniter plugin that allows you to call
a controller from another controller, then you will be limited to using only
a single controller from the CLI.
* Any HTTP-dependent CodeIgniter functions and classes won't work, obviously.
This includes redirects, etc.
License
-------------------------------------
* Everything in this repository is licensed MIT.
About MY APP
MY APP is a CodeIgniter-based web application to make magical things happen
and do all kinds of other fun stuff.. Blah Blah Blah..
Your Environment:
============================
PHP: <?php echo phpversion(); ?>
CodeIgniter: <?php echo CI_VERSION; ?>
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* CLI Class
*
* Originally written by Phil Sturgeon (http://github.com/philsturgeon/codeigniter-cli)
* Modifications by Casey McLaughlin
*
* @license GPL2
*/
class CLI
{
private $CI; // CodeIgniter instance
private $wait_msg = 'Press any key to continue...';
private $validation_errors = array();
// --------------------------------------------------------------------
/**
* Constructor
*/
function CLI()
{
//This is the constructor..
$this->CI =& get_instance();
log_message('debug', 'CLI Class Initialized');
}
// --------------------------------------------------------------------
/**
* Write output to the command line
*
* @param string $output
* @return CLI
*/
function write($output = '')
{
// If there are multiple lines, seperate them by newlines
if(is_array($output))
$output = implode("\n", $output);
// Output the lot
fwrite(STDOUT, $output);
return $this;
}
// --------------------------------------------------------------------
/**
* Write a line to the command line
*
* @param string $output
* @return CLI
*/
function writeln($output = '')
{
return $this->write($output . "\n");
}
// --------------------------------------------------------------------
/**
* Read an input and apply validation rules
*
* This method allows you to use all of the validation rules built-in to
* CodeIgniter's form_validation class.
*
* The function returns the value if validation passed. If not, it returns
* FALSE. You can then retrieve the validation errors from the get_validation_errors()
* method.
*
* @param string $input_name Give the input a unique name (e.g. 'username' or 'menu_selection')
* @param string $rules See CodeIgniter Form_validation reference
* @param string $message A message to display at the prompt
* @param string $options An array of options that the user must choose from
* @return boolean|string If validation passed, return the value; if not, return FALSE
*/
function read_and_validate($input_name, $rules, $message = '', $options = array())
{
$this->CI->load->library('form_validation');
$input = $this->read($message, $options);
$input_name = $input;
//Turn the rules into an array
if (strlen($rules) > 0)
{
$rules = (strpos($rules, "|")) ? explode("|", $rules) : array($rules);
//Foreach rule, run it...
foreach($rules as $rule)
{
// Is the rule a callback?
$callback = FALSE;
if (substr($rule, 0, 9) == 'callback_')
{
$rule = substr($rule, 9);
$callback = TRUE;
}
// Strip the parameter (if exists) from the rule
// Rules can contain a parameter: max_length[5]
$param = FALSE;
if (preg_match("/(.*?)\[(.*?)\]/", $rule, $match))
{
$rule = $match[1];
$param = $match[2];
}
// Call the function that corresponds to the rule
if ($callback === TRUE)
{
if ( ! method_exists($this->CI, $rule))
{
continue;
}
// Run the function and grab the result
$result = $this->CI->$rule($input, $param);
}
elseif (method_exists($this->CI->form_validation, $rule))
{
$result = $this->CI->form_validation->$rule($input, $param);
}
elseif (function_exists($rule))
$result = call_user_func($rule, $input);
//Prep or check if was false
if (is_string($result) && ! is_bool($result))
$input = $result;
elseif ($result === FALSE)
{
if ( ! isset($this->CI->form_validation->_error_messages[$rule]))
{
if (FALSE === ($line = $this->CI->lang->line($rule)))
$this->validation_errors[$input_name] = 'Unable to access an error message corresponding to your field name.';
}
else
$this->validation_errors[$input_name] = $this->CI->form_validation->_error_messages[$rule];
}
}
}
if ( ! isset($this->validation_errors[$input_name]) OR count($this->validation_errors[$input_name]) == 0)
return $input;
else
return FALSE;
}
// --------------------------------------------------------------------
/**
* Retrieve any validation errors for failed read_and_validate() items
*
* @param string $input_name
* @return boolean|array FALSE if there are no validation errors, otherwise an array
*/
function get_validation_errors($input_name = 'ALL')
{
if ($input_name == 'ALL')
return $this->validation_errors;
else
{
if (isset($this->validation_errors[$input_name]))
return $this->validation_errors[$input_name];
else
return FALSE; //or throw exception?
}
}
// --------------------------------------------------------------------
/**
* Read a variable from the command-line
*
* Waits for the user to enter a value, then returns that value
* as a string
*
* @param string|array Output or options
* @param array Optional - Options
*
* @return string
*/
function read($message = '', $options = array())
{
//If the user sent the options as the first parameter...
if (is_array($message))
{
$options = $message;
$message = '';
}
//Point message to output.
$output =& $message;
// If a question has been asked with the read
if( ! empty($output))
{
$options_output = '';
//Let's not do this for now.
//if( ! empty($options) && ( ! isset($this->hide_options) OR $this->hide_options === FALSE))
// $options_output = ' [ '.implode(', ', $options).' ]';
fwrite(STDOUT, $output.$options_output.': ');
}
// Read the input from keyboard.
$input = trim(fgets(STDIN));
// If options are provided and the choice is not in the array, tell them to try again
if( ! empty($options) && ! in_array($input, $options))
{
$this->write('This is not a valid option. Please try again.');
$this->new_line();
$input = $this->read($output, $options);
}
//Reset the hide options
$this->hide_options = FALSE;
// Return the value
return $input;
}
// --------------------------------------------------------------------
/**
* Send a newline to the command line
*
* @param int $lines
* @return CLI
*/
function new_line($lines = 1)
{
// Do it once or more, write with empty string gives us a new line
for($i = 0; $i < $lines; $i++) $this->write("\n");
return $this;
}
// --------------------------------------------------------------------
/**
* Clears the screen by printing 100 new lines
*
* @return CLI
*/
function clear_screen()
{
// works, ugly
return $this->new_line(100);
}
// --------------------------------------------------------------------
/**
* Make the computer go "beep"
*
* Thanks to Daniel Morris (danielxmorris.com)
*/
function beep($beeps = 1)
{
$string_beeps = '';
// Output the correct number of beep characters
for ($i = 0; $i < $beeps; $i++) $string_beeps .= "\x07";
print $string_beeps;
return $this;
}
// --------------------------------------------------------------------
/**
* Pause and wait for input. Optionally display a custom message.
*
* @param string $message
*/
function pause($message = '')
{
if ($message != '')
$this->write("\n$message");
$this->read();
}
// --------------------------------------------------------------------
/**
* Wait the specified number of seconds. Optional countdown
*
* @param int $seconds
* @param boolean $countdown
* @return CLI
*/
function wait($seconds = 0, $countdown = FALSE)
{
// Diplay the countdown
if($countdown == TRUE)
{
$i = $seconds;
while ( $i > 0 )
{
fwrite(STDOUT, "\r".$i.'...');
sleep(1);
$i--;
}
}
else // No countdown timer please
{
// Set number of seconds?
if($seconds > 0)
sleep($seconds);
else // No seconds mentioned, lets wait for user input
{
$this->write($this->wait_msg);
$this->read();
}
}
return $this;
}
// --------------------------------------------------------------------
/**
* Output a file from the views/ folder to the command line
*
* If not final, then it wil return any input the user entered
* on the CLI.
*
* @param string $view
* @param array $data
* @return CLI
*/
function view($view, $data = array())
{
$to_show = $this->CI->load->view($view, $data, TRUE);
$this->writeln($to_show);
return $this;
}
}
// END CLI Class
/* End of file CLI.php */
/* Location: ./application/libraries/CLI.php */
#!/usr/bin/php
<?php
/*
* CLI Interface for our app
*/
//Die if not the command line.
if ( ! php_sapi_name() == 'cli' OR ! empty($_SERVER['REMOTE_ADDR']))
{
header("HTTP/1.0 403 Forbidden");
exit('Beat It.');
}
//Read the input.. Allowed inputs are:
// path (e.g 'welcome/index')
// -v or --verbose To set the flag for verbose input
// -u or --username for username
// -p or --password for password
// -? or --help
$in_args = array();
foreach($argv as $arg)
{
if (strcmp(substr($arg, 0, 1), '-') == 0)
{
if ($arg == '-v' OR $arg == '--verbose')
define('CLI_VERBOSE', TRUE);
elseif ($arg == '-u' OR $arg == '--username')
define('CLI_USER', $arg);
elseif ($arg == '-p' OR $arg == '--password')
define('CLI_PASS', $arg);
elseif ($arg == '-?' OR $arg == '--help')
define('CLI_HELP_MODE', TRUE);
else
die("\n\n" . substr($arg,1) . " is not a valid option. Use -? for help\n");
}
elseif(strcmp(basename(__FILE__), $arg) != 0)
$in_args[] = $arg;
}
//Set defaults for any inputs not explictely given
if ( ! defined('CLI_HELP_MODE'))
define('CLI_HELP_MODE', FALSE);
if ( ! defined('CLI_VERBOSE'))
define('CLI_VERBOSE', FALSE);
if ( ! defined('CLI_USER'))
define('CLI_USER', '');
if ( ! defined('CLI_PASS'))
define('CLI_PASS', '');
//Route to the utils controller using some trickery
if (count($in_args) > 0)
$_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI'] = 'shellcontroller/' . array_shift($in_args);
else
$_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI'] = 'shellcontroller/index';
//Run It!
require dirname(__FILE__) . '/index.php';
/* EOF */
My Application Command-Line Utilities
Main Menu
====================================
A: Display information about this application.
Q: Exit the Application
1: Do something...
2: Do something else...
MY APP Command-Line Utilties allows CLI access
Usage:
entry.php [-v] [-u] [-p] [path/to/action]
Options:
-? --help This Help screen
-v --verbose Use verbose mode (for automated operations)
-u --username Supply a username
-p --password Supply a password (can be plaintext or a MD5/SHA1/SHA256 hash)
For the interactive main menu, do not supply a [path/to/action]
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* Shell Controller
*
* @author Casey McLaughlin
*/
class Shellcontroller extends Controller {
/**
* Constructor
*/
function Shellcontroller()
{
parent::Controller();
//Only CLI allowed
if ( ! php_sapi_name() == 'cli' OR ! empty($_SERVER['REMOTE_ADDR']))
show_error('You are not authorized', 403);
$this->load->library('CLI');
//IF YOU WANT, you can code authentication check here, based on the crednetials
//supplied by the command line.
//If the user typed -? or --help as a CLI-switch, just show the help
if (CLI_HELP_MODE == TRUE)
$this->quickhelp();
}
// --------------------------------------------------------------------
/**
* Index action displays a main menu
*/
function index()
{
//Sessions work on the CLI!
$this->session->set_userdata('started_on_main_menu', TRUE);
//Map key entries to methods in this class
$allowed_actions = array(
'A' => 'about',
'E' => 'quit',
'Q' => 'quit',
'1' => 'something',
'2' => 'something_else'
);
$this->cli->clear_screen();
$this->cli->view('index_view', $this->data);
$input = $this->cli->read('Make your selection: ');
$input = trim(strtoupper($input));
//If input was valid, run the corresponding method
if (in_array($input, array_keys($allowed_actions)))
return call_user_func(array($this, $allowed_actions[$input]));
else
{
//The user typed in something wonky. Make them feel bad.
$this->cli->pause("You did not make a valid selection! Press any key to try again");
$this->index();
}
}
// --------------------------------------------------------------------
function something()
{
$this->cli->writeln("Going to do something... Code some magical goodness here.");
}
// --------------------------------------------------------------------
function something_else()
{
$this->cli->writeln("Going to do something else. Did I mention that you have full access to your models and database here.");
}
// --------------------------------------------------------------------
function about()
{
$this->cli->clear_screen();
$this->cli->view('about_view', $this->data, TRUE);
$this->_return();
}
// --------------------------------------------------------------------
function quickhelp()
{
$this->cli->view('quickhelp_view', $this->data);
$this->_return();
}
// --------------------------------------------------------------------
function _return()
{
$this->cli->wait();
if ($this->session->userdata('started_on_main_menu'))
return $this->index();
else
return $this->quit();
}
// --------------------------------------------------------------------
function quit()
{
$this->cli->write("\n\nGoodbye!");
}
}
/* End of file shellcontroller.php */
/* Location: ./system/application/controllers/shellcontroller.php */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment