[Solar-svn] Revision 2978
pmjones at solarphp.com
pmjones at solarphp.com
Fri Feb 29 17:31:08 CST 2008
Solar_Php: [NEW] Class to let you execute Solar scripts in a separate PHP environment; captures the output, exit code, and last line of the run (depending on the execution mode). Expected to be useful for docs and testing.
Added: trunk/Solar/Php.php
===================================================================
--- trunk/Solar/Php.php (rev 0)
+++ trunk/Solar/Php.php 2008-02-29 23:31:08 UTC (rev 2978)
@@ -0,0 +1,387 @@
+<?php
+/**
+ *
+ * Lets you execute a Solar-based script in a separate PHP process, then get
+ * back its exit code, last line, and output.
+ *
+ * Intended use is for documentation and testing, where you don't want the
+ * classes loaded in the main environment to interact with the classes in the
+ * working environment.
+ *
+ * An example to run `echo "hello world!"` in a separate process:
+ *
+ * {{code: php
+ * require_once 'Solar.php';
+ *
+ * $ini = array(
+ * 'include_path' => '/path/to/lib',
+ * 'error_reporting' => E_ALL | E_STRICT,
+ * 'error_display' => 1,
+ * 'html_errors' => 0,
+ * );
+ *
+ * $php = Solar::factory('Solar_Php');
+ *
+ * $php->setIniFile(false)
+ * ->setIniArray($ini)
+ * ->setMode('passthru')
+ * ->run('echo "hello world!\n"');
+ *
+ * Solar::stop();
+ * }}
+ *
+ */
+class Solar_Php extends Solar_Base {
+
+ /**
+ *
+ * User-defined configuration values.
+ *
+ * @var array
+ *
+ */
+ protected $_Solar_Php = array(
+ 'php' => null,
+ 'ini_file' => null,
+ 'ini_set' => null,
+ 'solar_config' => null,
+ 'mode' => null,
+ );
+
+ /**
+ *
+ * Command to invoke the PHP binary.
+ *
+ * @var string
+ *
+ * @todo switch this based on Windows/Mac/Linux.
+ *
+ */
+ protected $_php = '/usr/local/bin/php';
+
+ /**
+ *
+ * Which php.ini file to use.
+ *
+ * Null means to use the default php.ini file, but false means to use *no*
+ * php.ini file.
+ *
+ * @var string
+ *
+ */
+ protected $_ini_file = null;
+
+ /**
+ *
+ * Override php.ini file settings with these settings.
+ *
+ * Format is an array of key-value pairs, where the key is the setting
+ * name and the value is the setting value.
+ *
+ * @var array
+ *
+ */
+ protected $_ini_set = array();
+
+ /**
+ *
+ * When calling Solar::start() in the new process, use this as the $config
+ * value.
+ *
+ * @var mixed
+ *
+ */
+ protected $_solar_config = null;
+
+ /**
+ *
+ * The process execution mode.
+ *
+ * Valid settings are:
+ *
+ * `echo`
+ * : Echoes the command, does not execute it.
+ *
+ * `exec`
+ * : Uses [[php::exec() | ]] for the process.
+ *
+ * `passthru`
+ * : Uses [[php::passthru() | ]] for the process.
+ *
+ * `shell_exec`
+ * : Uses [[php::shell_exec() | ]] for the process.
+ *
+ * `system`
+ * : Uses [[php::system() | ]] for the process.
+ *
+ * @var mixed
+ *
+ */
+ protected $_mode = 'exec';
+
+ /**
+ *
+ * After the code runs, each line of output (if any).
+ *
+ * @var array
+ *
+ */
+ protected $_output;
+
+ /**
+ *
+ * After the code runs, the last line of output (if any).
+ *
+ * @var array
+ *
+ */
+ protected $_last_line;
+
+ /**
+ *
+ * After the code runs, the exit status code (if any).
+ *
+ * Note that null is *not* the same as zero; zero is normally an "OK"
+ * exit code, whereas null means "no exit code given".
+ *
+ * @var array
+ *
+ */
+ protected $_exit_code;
+
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param array $config User-defined configuration values.
+ *
+ */
+ public function __construct($config = null)
+ {
+ // parent construction
+ parent::__construct($config);
+
+ // populate each of these properties with its config value ...
+ $list = array_keys($this->_Solar_Php);
+ foreach ($list as $key) {
+ // ... but only if not null.
+ if ($this->_config[$key] !== null) {
+ $var = "_$key";
+ $this->$var = $this->_config[$key];
+ }
+ }
+ }
+
+ /**
+ *
+ * Sets the PHP command to call at the command line.
+ *
+ * @param string $php The PHP command; e.g., "/usr/local/php".
+ *
+ * @return Solar_Php
+ *
+ */
+ public function setPhp($php)
+ {
+ $this->_php = $php;
+ return $this;
+ }
+
+ /**
+ *
+ * Sets the location of the php.ini file to use.
+ *
+ * If null, uses the default php.ini file location.
+ *
+ * If false, uses *no* php.ini file (the `--no-php-ini` switch).
+ *
+ * @param string $file The php.ini file location.
+ *
+ * @return Solar_Php
+ *
+ */
+ public function setIniFile($file)
+ {
+ if ($file !== null && $file !== false) {
+ $file = (string) $file;
+ }
+ $this->_ini_file = $file;
+ return $this;
+ }
+
+ /**
+ *
+ * Sets one php.ini value, overriding the php.ini file.
+ *
+ * @param string $key The php.ini setting name.
+ *
+ * @param string $val The php.ini setting value.
+ *
+ * @return Solar_Php
+ *
+ */
+ public function setIniVal($key, $val)
+ {
+ $this->_ini_set[$key] = $val;
+ return $this;
+ }
+
+ /**
+ *
+ * Sets an array of php.ini values, overriding the php.ini file.
+ *
+ * Each key in the array is a php.ini setting name, and each value is the
+ * corresponding php.ini value.
+ *
+ * @param string $list The array of php.ini key-value pairs.
+ *
+ * @return Solar_Php
+ *
+ */
+ public function setIniArray($list)
+ {
+ foreach ($list as $key => $val) {
+ $this->_ini_set[$key] = $val;
+ }
+ return $this;
+ }
+
+ /**
+ *
+ * Sets an array of php.ini values, overriding the php.ini file.
+ *
+ * Each key in the array is a php.ini setting name, and each value is the
+ * corresponding php.ini value.
+ *
+ * @param string $list The array of php.ini key-value pairs.
+ *
+ * @return Solar_Php
+ *
+ */
+ public function setSolarConfig($solar_config)
+ {
+ $this->_solar_config = $solar_config;
+ return $this;
+ }
+
+ public function setMode($mode)
+ {
+ $list = array('echo', 'exec', 'passthru', 'shell_exec', 'system');
+ if (! in_array($mode, $list)) {
+ throw $this->_exception('ERR_UNKNOWN_MODE');
+ } else {
+ $this->_mode = $mode;
+ }
+ return $this;
+ }
+
+ public function runFile($file)
+ {
+ $code = file_get_contents($file);
+ return $this->run($code);
+ }
+
+ // @todo strip the opening and closing php tags from $code
+ public function run($code)
+ {
+ // clean up from last run
+ $this->_output = array();
+ $this->_last_line = null;
+ $this->_exit_code = null;
+
+ $cmd = $this->_buildCommand() . " --run " . $this->_buildCode($code);
+
+ switch ($this->_mode) {
+ case 'echo':
+ echo $cmd;
+ break;
+ case 'exec':
+ $this->_last_line = exec($cmd, $this->_output, $this->_exit_code);
+ break;
+ case 'passthru':
+ passthru($cmd, $this->_exit_code);
+ break;
+ case 'shell_exec':
+ $this->_output = shell_exec($cmd);
+ $this->_last_line = end($this->_output);
+ reset($this->_output);
+ break;
+ case 'system':
+ $this->_last_line = system($cmd, $this->_exit_code);
+ break;
+ }
+
+ return $this;
+ }
+
+ public function getExitCode()
+ {
+ return $this->_exit_code;
+ }
+
+ public function getOutput()
+ {
+ return $this->_output;
+ }
+
+ public function getLastLine()
+ {
+ return $this->_last_line;
+ }
+
+ protected function _buildCode($code)
+ {
+ // strip long opening tag
+ if (substr($code, 0, 5) == '<?php') {
+ $code = substr($code, 5);
+ }
+
+ // strip short opening tag
+ if (substr($code, 0, 2) == '<?') {
+ $code = substr($code, 2);
+ }
+
+ // strip closing tag
+ if (substr($code, -2) == '?>') {
+ $code = substr($code, 0, -2);
+ }
+
+ // get the solar config as a variable
+ $solar_config = var_export($this->_solar_config, true);
+
+ // wrap the code in Solar::start() and Solar::stop()
+ $code = "require 'Solar.php'; "
+ . "Solar::start($solar_config); "
+ . "$code; "
+ . "Solar::stop();";
+
+ // escape for shell, and done
+ return escapeshellarg($code);
+ }
+
+ protected function _buildCommand()
+ {
+ // the PHP binary
+ $cmd = $this->_php;
+
+ // using a php.ini file?
+ if ($this->_ini_file) {
+ // non-default file or path
+ $cmd .= " --php-ini " . escapeshellarg($this->_ini_file);
+ } elseif ($this->_ini_file === false) {
+ // explicitly *no* file ot be used
+ $cmd .= " --no-php-ini";
+ }
+
+ // override php.ini values
+ foreach ((array) $this->_ini_set as $key => $val) {
+ $key = escapeshellarg($key);
+ $val = escapeshellarg($val);
+ $cmd .= " --define $key=$val";
+ }
+
+ return $cmd;
+ }
+}
+?>
\ No newline at end of file
More information about the Solar-svn
mailing list