With a bit of framework (mainly Apache configuration writing), you can do wondrous PHP switching things.
Code: Select all
#!/usr/bin/php
<?php
set_time_limit(0);
echo "== PHP Switch Utility ==\n\n";
require_once('/php/ini_generator/Extension.php');
function prompt($length = '255') {
if (!isset ($GLOBALS['StdinPointer'])) $GLOBALS['StdinPointer'] = fopen("php://stdin","r");
$line = fgets($GLOBALS['StdinPointer'],$length);
return trim($line);
}
function write_apache2_php_conf($file, $version, $type = 'cgi') {
$major_version = (int) substr($version, 0, strpos($version, '.'));
$new_config = '';
if ($type == 'sapi') {
$new_config .= "LoadModule \"C:/php/$version/php{$major_version}apache2.dll\"\n";
$new_config .= 'PHPIniDir "C:/php"'."\n";
} else { // $type == 'cgi'
$new_config .= "ScriptAlias /php/ \"C:/php/$version/\"\n";
if ($major_version == 4) {
$new_config .= 'Action application/x-httpd-php "/php/php.exe"'."\n";
} else {
$new_config .= 'Action application/x-httpd-php "/php/php-cgi.exe"'."\n";
}
}
$fh = fopen($file, 'w');
$status = fwrite($fh, $new_config);
fclose($fh);
return $status;
}
function write_php_ini($file, $version, $base_file, $extension_file) {
$extensions = Extension::newFromFile($extension_file);
$ini_extensions = '';
foreach ($extensions as $extension) {
if (!$extension->canLoad($version)) continue;
$ini_extensions .= $extension->toIniString() . "\r\n";
}
$ini_base = file_get_contents($base_file);
$new_config = $ini_base .
"\r\n; This portion is automatically generated for PHP $version\r\n" .
$ini_extensions;
$new_config = str_replace('{EXT_DIR}', "C:\\php\\$version\\ext", $new_config);
$fh = fopen($file, 'w');
$status = fwrite($fh, $new_config);
fclose($fh);
return $status;
}
$config_file = 'C:\Program Files\Apache Group\Apache2\conf\php.conf';
//determine the current setup
$cur_config = file_get_contents($config_file);
preg_match('#ScriptAlias /php/ (?:")?(?:C|c):/php/([A-Za-z0-9.]+)/(?:")?#', $cur_config, $matches);
$cur_version = $matches[1];
//determine installed PHP stuffs
$versions = array();
$dir = '/php/';
if (!is_dir($dir)) exit('PHP directory doesn\'t exist!');
if (!($dh = opendir($dir))) exit('PHP directory is not readable');
while (($filename = readdir($dh)) !== false) {
if (!is_numeric($filename[0])) continue;
//$versions[] = explode('.', $filename); //better sorting
$versions[] = $filename;
}
closedir($dh);
//output info
echo "Current version is $cur_version.\n";
echo "Available versions:\n";
foreach ($versions as $version) {
echo " - $version\n";
}
echo "\n";
$repeats = 0;
while( true ) {
if ($repeats || empty($argv[1])) {
echo "Switch to: ";
$new_version = prompt(); //allow passing via arguments
} else {
$new_version = $argv[1];
}
if (empty($new_version)) {
$new_version = $cur_version;
break;
}
if ($new_version == 'x') exit('PHP switch aborted.');
$repeats++;
if ($repeats > 10) exit('Max repeats reached, aborting.');
if (!in_array($new_version, $versions)) {
echo "Invalid version. Press ENTER to abort.\n";
continue;
}
break;
}
echo "\n";
echo ($new_version == $cur_version ? 'Reloading' : 'Switching to') . " $new_version\n";
echo "Writing new Apache configuration... ";
if (!write_apache2_php_conf($config_file, $new_version, 'cgi')) {
exit('failed.');
}
echo "done\n";
echo "Writing new PHP configuration... ";
if (!write_php_ini('C:\php\ini_dir\webserver\php.ini', $new_version,
'C:\php\ini_dir\php.ini', 'C:\php\ini_dir\extensions.txt')) {
exit('failed.');
}
echo "done\n";
echo "Restarting Apache... ";
shell_exec('"C:\Program Files\Apache Group\Apache2\bin\Apache.exe" -k restart');
echo "done\n";
?>
Edit - Oops, you'll need this code to (unit test available if anyone's interested)
Code: Select all
<?php
class Extension {
var $filename;
var $rules;
var $directive;
var $_compiled;
function Extension($filename, $rules, $directive = null) {
$this->filename = $filename;
$this->rules = $rules;
$this->directive = $directive;
}
function getFilename() {return $this->filename;}
function getRules() {return $this->rules;}
function getDirective() {return $this->directive;}
function newFromFile($file) {
$string = file_get_contents($file);
return Extension::newFromString($string);
}
function newFromString($string) {
$lines = explode("\n", $string);
$extensions = array();
foreach ($lines as $line) {
if (!($line = trim($line))) continue;
if (($comment_start = strpos($line, ';')) !== false) {
//strip out comment
$line = substr($line, 0, $comment_start);
}
if (!($line = trim($line))) continue;
$bits = explode('|', $line);
$filename = trim($bits[0]);
$rules = preg_split('/\s+/', trim($bits[1]));
$directive = isset($bits[2]) ? trim($bits[2]) : null;
$extensions[] =& new Extension($filename, $rules, $directive);
}
return $extensions;
}
function canLoad($version) {
if (empty($_compiled)) $this->_compiled = $this->_compileRules($this->rules);
$compiled_version = $this->_compileVersion($version);
//first, determine if the value is excluded, if it is, immediately false
$excluded = $this->_matchesCompiledRules($compiled_version,
$this->_compiled['exclude']);
if ($excluded) return false;
//now, check if it's in the forward
if (!empty($this->_compiled['forward'])) {
$result = version_compare($version, $this->_compiled['forward'],
'>=');
if ($result) return true;
}
//now, check if it matches any of the inclusion ones
$included = $this->_matchesCompiledRules($compiled_version,
$this->_compiled['include']);
return $included;
}
function _compileRules($rules) {
$return = array('include' => array(), 'exclude' => array(),
'forward' => null);
foreach ($rules as $rule) {
//is exclusion?
if ($rule[0] == '!') {
$return['exclude'][] = $this->_compileVersion(substr($rule, 1));
continue;
}
//is forward?
if ($rule[strlen($rule)-1] == '+') {
$return['forward'] = substr($rule, 0, strlen($rule)-1);
continue;
}
//ah, it's inclusion
$return['include'][] = $this->_compileVersion($rule);
}
return $return;
}
function _compileVersion($version) {
$version = preg_replace('/([^0-9\.]+)/', '.$1.', $version);
$version = str_replace(array('-','_','+','..'), '.', $version);
return explode('.', $version);
}
function _matchesCompiledRules($compiled_version, $compiled_rules) {
foreach($compiled_rules as $rule) {
$matches = true;
foreach($rule as $key => $number) {
if (!isset($compiled_version[$key])) break;
if ($compiled_version[$key] != $number) {
$matches = false;
break;
}
}
if ($matches) {
return true;
}
}
return false;
}
function toIniString() {
return ($this->directive ? $this->directive : 'extension') . ' = ' . $this->filename;
}
}
?>
Actually, the code isn't that good. I don't like it very much. But it works.