Fixing content type ordering when content_type is not defined.
[akelos.git] / script / setup
blob9d23e4b8233b8660c402441a95b90b61e2e18180
1 #!/usr/bin/env php
2 <?php
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
5 // +----------------------------------------------------------------------+
6 // | Akelos Framework - http://www.akelos.org |
7 // +----------------------------------------------------------------------+
8 // | Copyright (c) 2002-2006, Akelos Media, S.L. & Bermi Ferrer Martinez |
9 // | Released under the GNU Lesser General Public License, see LICENSE.txt|
10 // +----------------------------------------------------------------------+
12 /**
13 * @package AkelosFramework
14 * @subpackage Installer
15 * @author Bermi Ferrer <bermi a.t akelos c.om>
16 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
17 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
20 class AkelosInstaller
22 var $options = array();
23 var $errors = array();
25 function AkelosInstaller($options)
27 $default_options = array(
28 'source' => $this->_absolutePath(dirname(__FILE__).DIRECTORY_SEPARATOR.'..'),
29 'force' => false,
30 'skip' => false,
31 'quiet' => false,
32 'public_html' => false,
33 'dependencies' => false
35 $this->options = array_merge($default_options, $options);
37 $this->options['directory'] = $this->_absolutePath(@$this->options['directory']);
39 if(empty($this->options['directory'])){
40 trigger_error('You must supply a valid destination path', E_USER_ERROR);
43 $this->source_tree = Ak::dir($this->options['source'],array('dirs'=>true,'recurse'=>true));
45 if(empty($this->options['dependencies'])){
46 $this->framework_dirs = array('lib', 'vendor', 'test');
48 foreach ($this->framework_dirs as $framework_dir){
49 foreach ($this->source_tree as $k => $v){
50 if(isset($v[$framework_dir])){
51 unset($this->source_tree[$k]) ;
57 $this->destination_tree = Ak::dir($this->options['directory'],array('dirs'=>true,'recurse'=>true));
60 function install()
62 if(empty($this->destination_tree) || !empty($this->options['force'])){
63 if(!is_dir($this->options['directory'])){
64 if(!$this->_makeDir($this->options['directory'])){
65 $this->addError("Can't create directory: " . $this->options['directory']);
66 return false;
70 $this->_copyFrameworkFiles($this->source_tree, $this->options['source']);
72 if(empty($this->options['dependencies'])){
73 $this->_setupApplicationTestingEnvironment();
74 $this->_linkDependencies();
77 $this->runEvironmentSpecificTasks();
79 $this->_linkPublicHtmlFolder();
81 }else{
82 $this->addError('Installation directory is not empty. Add --force if you want to override existing files');
89 function _setupApplicationTestingEnvironment()
91 $source_test_dir = $this->options['source'].DS.'test';
92 $test_dir = $this->options['directory'].DS.'test';
94 $this->_makeDir($test_dir);
95 $this->_copyFile($source_test_dir.DS.'app.php');
97 $this->_makeDir($test_dir.DS.'fixtures');
98 $this->_makeDir($test_dir.DS.'fixtures'.DS.'app');
100 $this->_copyFile($source_test_dir.DS.'fixtures'.DS.'app'.DS.'application_controller.php');
101 $this->_copyFile($source_test_dir.DS.'fixtures'.DS.'app'.DS.'shared_model.php');
103 $this->_makeDir($test_dir.DS.'fixtures'.DS.'config');
104 $this->_copyFile($source_test_dir.DS.'fixtures'.DS.'config'.DS.'config.php');
106 $this->_makeDir($test_dir.DS.'fixtures'.DS.'data');
107 $this->_makeDir($test_dir.DS.'fixtures'.DS.'public');
108 $this->_copyFile($source_test_dir.DS.'fixtures'.DS.'public'.DS.'.htaccess');
109 $this->_copyFile($source_test_dir.DS.'fixtures'.DS.'public'.DS.'index.php');
113 function _linkPublicHtmlFolder()
115 if(!empty($this->options['public_html'])){
116 if(function_exists('symlink')){
117 $this->options['public_html'] = $this->_absolutePath($this->options['public_html']);
118 $link_info = @linkinfo($this->options['public_html']);
119 if(!is_numeric($link_info) || $link_info < 0){
120 $this->yield("\n Adding symbolic link ".$this->options['public_html'].' to the public web server.');
121 if(@symlink($this->options['directory'].DS.'public',$this->options['public_html'])){
122 return true;
126 $this->yield("\n Could not create a symbolic link of ".$this->options['directory'].DS.'public'.' at '.$this->options['public_html']);
128 }else{
129 $this->_addRootLevelDispatcher();
130 $this->_addHtaccessDirectoryProtection();
132 return false;
135 function _linkDependencies()
137 $this->yield("\n Linking the application with the framework at ".$this->options['source'])."\n";
138 foreach (array(
139 'config'.DS.'DEFAULT-config.php',
140 'app'.DS.'controllers'.DS.'framework_setup_controller.php') as $file){
141 if(file_exists($this->options['directory'].DS.$file)){
142 $file_contents = str_replace("// defined('AK_FRAMEWORK_DIR') ? null : define('AK_FRAMEWORK_DIR', '/path/to/the/framework');",
143 "defined('AK_FRAMEWORK_DIR') ? null : define('AK_FRAMEWORK_DIR', '".addcslashes($this->options['source'],'\\')."');",
144 file_get_contents($this->options['directory'].DS.$file));
145 file_put_contents($this->options['directory'].DS.$file, $file_contents);
150 function _addRootLevelDispatcher()
152 $this->_copyFile($this->options['source'].DS.'index.php');
153 $this->_copyFile($this->options['source'].DS.'.htaccess');
156 function _addHtaccessDirectoryProtection()
158 foreach($this->source_tree as $k=>$node){
159 if (is_array($node)){
160 $folder = array_shift(array_keys($node));
161 $path = $this->options['directory'].DS.$folder;
162 if(is_dir($path) && !file_exists($path.DS.'.htaccess') && $folder != 'public'){
163 file_put_contents($path.DS.'.htaccess', "order allow,deny\ndeny from all");
169 function _copyFrameworkFiles($directory_structure, $base_path = '.')
171 foreach ($directory_structure as $k=>$node){
173 $path = $base_path.DS.$node;
174 if(is_dir($path)){
175 $this->_makeDir($path);
176 }elseif(is_file($path)){
177 $this->_copyFile($path);
178 }elseif(is_array($node)){
179 foreach ($node as $dir=>$items){
180 $path = $base_path.DS.$dir;
181 if(is_dir($path)){
182 $this->_makeDir($path);
183 $this->_copyFrameworkFiles($items, $path);
191 function _makeDir($path)
193 $dir = $this->_getDestinationPath($path);
195 if($this->_canUsePath($dir)){
196 if(!is_dir($dir)){
197 $this->yield(" Creating directory: ".$dir);
198 if(!@mkdir($dir))
199 return false;
202 return true;
205 function _copyFile($path)
207 $destination_file = $this->_getDestinationPath($path);
209 if($this->_canUsePath($destination_file)){
210 if(!file_exists($destination_file)){
211 $this->yield(" Creating file: ".$destination_file);
212 copy($path, $destination_file);
213 }elseif(md5_file($path) != md5_file($destination_file)){
214 $this->yield(" Modifying file: ".$destination_file);
215 copy($path, $destination_file);
218 $source_file_mode = fileperms($path);
219 $target_file_mode = fileperms($destination_file);
220 if($source_file_mode != $target_file_mode){
221 $this->yield(" Setting $destination_file permissions to: ".(sprintf("%o",$source_file_mode)));
222 chmod($destination_file,$source_file_mode);
228 * Computes the destination path
230 * Gicing /path/to/the_framework/lib/Ak.php will rerturn /my/project/path/lib/Ak.php
233 function _getDestinationPath($path)
235 return str_replace($this->options['source'], $this->options['directory'], $path);
239 * Returns false if operating on the path is not allowed
241 function _canUsePath($path)
243 if(is_file($path) || is_dir($path)){
244 return !empty($this->options['skip']) ? false : !empty($this->options['force']);
247 return true;
250 function _absolutePath($path)
252 $_path = $path;
253 if (!preg_match((AK_OS == 'WINDOWS' ? "/^\w+:/" : "/^\//"), $path )) {
254 $current_dir = AK_OS == 'WINDOWS' ? str_replace("\\", DS, realpath('.').DS) : realpath('.').DS;
255 $_path = $current_dir . $_path;
257 $start = '';
258 if(AK_OS == 'WINDOWS'){
259 list($start, $_path) = explode(':', $_path, 2);
260 $start .= ':';
262 $real_parts = array();
263 $parts = explode(DS, $_path);
264 for ($i = 0; $i < count($parts); $i++ ) {
265 if (strlen($parts[$i]) == 0 || $parts[$i] == "."){
266 continue;
268 if ($parts[$i] == '..'){
269 if(count($real_parts) > 0){
270 array_pop($real_parts);
272 }else{
273 array_push($real_parts, $parts[$i]);
276 return $start.DS.implode(DS,$real_parts );
279 function yield($message)
281 if(empty($this->options['quiet'])){
282 echo $message."\n";
286 function addError($error)
288 $this->errors[$error] = '';
291 function getErrors()
293 return array_keys($this->errors);
296 function hasErrors()
298 return !empty($this->errors);
302 function runEvironmentSpecificTasks()
304 if($evironment = $this->guessEnvironment()){
305 $method_name = 'run'.$evironment.'Tasks';
306 if(method_exists($this, $method_name)){
307 $this->$method_name();
312 // Environment specific tasks
314 function guessEnvironment()
316 if(AK_OS == 'WINDOWS'){
317 if(file_exists('C:/xampp/apache/conf/httpd.conf')){
318 return 'DefaultXamppOnWindows';
321 return false;
324 function runDefaultXamppOnWindowsTasks()
326 // XAMPP has mod_rewrite disabled by default so we will try to enable it.
327 $http_conf = file_get_contents('C:/xampp/apache/conf/httpd.conf');
328 if(strstr($http_conf, '#LoadModule rewrite_module')){
329 $this->yield('Enabling mod_rewrite');
330 file_put_contents('C:/xampp/apache/conf/httpd.conf.akelos', $http_conf);
331 file_put_contents('C:/xampp/apache/conf/httpd.conf',
332 str_replace(
333 '#LoadModule rewrite_module',
334 'LoadModule rewrite_module',
335 $http_conf
338 $this->yield('Restarting Apache');
339 // Stop apache
340 exec('C:\xampp\apache\bin\pv -f -k apache.exe -q');
341 exec('rm C:\xampp\apache\logs\httpd.pid');
343 // Start Apache in the background
344 $shell = new COM('WScript.Shell');
345 $shell->Run('C:\xampp\apache\bin\apache.exe', 0, false);
348 $my_cnf = @file_get_contents('C:/xampp/mysql/bin/my.cnf');
349 // InnoDB engine is not enabled by default on XAMPP we need it enabled in order to use transactions
350 if(strstr($my_cnf, '#innodb_')){
351 $this->yield('Enabling InnoDB MySQL engine.');
352 file_put_contents('C:/xampp/mysql/bin/my.cnf.akelos', $my_cnf);
353 file_put_contents('C:/xampp/mysql/bin/my.cnf',
354 str_replace(
355 array('skip-innodb', '#innodb_', '#set-variable = innodb'),
356 array('#skip-innodb', 'innodb_', 'set-variable = innodb')
357 ,$my_cnf));
359 $this->yield('Restarting MySQL server.');
360 $shell = new COM('WScript.Shell');
361 $shell->Run('C:\xampp\mysql\bin\mysqladmin --user=pma --password= shutdown', 0, false);
362 $shell = new COM('WScript.Shell');
363 $shell->Run('C:\xampp\mysql\bin\mysqld --defaults-file=C:\xampp\mysql\bin\my.cnf --standalone --console', 0, false);
369 define('DS', DIRECTORY_SEPARATOR);
370 define('AK_OS', (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? 'WINDOWS' : 'UNIX'));
371 define('AK_PHP5', version_compare(PHP_VERSION, '5', '>=') == 1 ? true : false);
373 define('AK_BASE_DIR', str_replace(DS.'script'.DS.'setup','',__FILE__));
374 @ini_set("include_path",(AK_BASE_DIR.DS.'vendor'.DS.'pear'.PATH_SEPARATOR.ini_get("include_path")));
377 if(!empty($_SERVER['argv'][1]) && $_SERVER['argv'][1][0] != '-'){
378 $_SERVER['argv'][0] = '-d';
382 require_once (dirname(__FILE__).DS.'..'.DS.'lib'.DS.'Ak.php');
383 require_once (dirname(__FILE__).DS.'..'.DS.'vendor'.DS.'pear'.DS.'PHP'.DS.'Compat'.DS.'Function'.DS.'file_put_contents.php');
384 require_once (dirname(__FILE__).DS.'..'.DS.'vendor'.DS.'pear'.DS.'Console'.DS.'Getargs.php');
386 $config = array(
389 'directory' => array(
390 'short' => 'd',
391 'max' => 1,
392 'min' => 1,
393 'desc' => 'Destination directory for installing the application.'),
397 'force' => array(
398 'short' => 'f',
399 'max' => 0,
400 'min' => 0,
401 'default' => 'false',
402 'desc' => 'Overwrite files that already exist.'),
405 'skip' => array(
406 'short' => 's',
407 'max' => 0,
408 'min' => 0,
409 'default' => 'false',
410 'desc' => 'Skip files that already exist.'),
413 'quiet' => array(
414 'short' => 'q',
415 'max' => 0,
416 'min' => 0,
417 'default' => 'false',
418 'desc' => 'Suppress normal output.'),
421 'public_html' => array(
422 'short' => 'p',
423 'max' => 1,
424 'min' => 1,
425 'desc' => 'Location where the application will be accesed by the webserver.'),
429 'dependencies' => array(
430 'short' => 'deps',
431 'max' => 0,
432 'min' => 0,
433 'default' => 'true',
434 'desc' => 'Includes a copy of the framework into the application directory.'),
437 'help' => array(
438 'short' => 'h',
439 'max' => 0,
440 'min' => 0,
441 'desc' => 'Show this help message.'),
449 $args =& Console_Getargs::factory($config);
451 if (PEAR::isError($args)) {
452 if ($args->getCode() === CONSOLE_GETARGS_ERROR_USER) {
453 echo Console_Getargs::getHelp($config, null, $args->getMessage())."\n";
454 } else if ($args->getCode() === CONSOLE_GETARGS_HELP) {
455 echo @Console_Getargs::getHelp($config)."\n";
457 exit;
460 $options = $args->getValues();
462 if(empty($options)){
463 echo Console_Getargs::getHelp($config)."\n";
464 exit;
467 $Installer = new AkelosInstaller($options);
469 $Installer->install();
471 if($args->getValue('quiet') == ''){
472 if($Installer->hasErrors()){
473 echo "\nThere where some errors during the installation process:\n";
474 echo "\n * ".join("\n * ",$Installer->getErrors());
475 }elseif(empty($Installer->options['force'])){
476 echo "\n Please point your browser to ".
477 (empty($Installer->options['public_html']) ? $Installer->options['directory'] : $Installer->options['public_html']).
478 " in order to complete the installation process";
480 echo "\n";