PageRenderTime 27ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/akelos/makelos/tasks/akelos/create_app.task.php

https://github.com/onivan/akelos
PHP | 430 lines | 396 code | 29 blank | 5 comment | 22 complexity | fee84651e31c7bc02614df15beb8a199 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. if(!empty($options['v']) || !empty($options['version'])){
  3. echo AKELOS_VERSION."\n";
  4. exit(0);
  5. }
  6. if(!empty($options['base_dir'])){
  7. echo AK_BASE_DIR."\n";
  8. exit(0);
  9. }
  10. if(!empty($options['h']) || !empty($options['help'])){
  11. die(<<<HELP
  12. Description:
  13. The 'akelos' command creates a new Akelos application with a default
  14. directory structure and configuration at the path you specify.
  15. Example:
  16. akelos ~/Code/PHP/weblog
  17. This generates a skeletal Akelos installation in ~/Code/PHP/weblog.
  18. See the README in the newly created application to get going.
  19. Usage: akelos [-vsqhf --dependencies] <-pd>
  20. -d --directory=<value> Destination directory for installing
  21. the application.
  22. -p --public_html=<value> Location where the application will be
  23. accessed by the web server.
  24. -i --dependencies Includes a copy of the framework into the
  25. application directory. (true)
  26. -f --force Overwrite files that already exist. (false)
  27. -q --quiet Suppress normal output. (false)
  28. -s --skip Skip files that already exist. (false)
  29. --prompt Prompts before performing install. (true)
  30. -h --help Show this help message.
  31. -v --version Print the akelos version.
  32. --base_dir Print the path where akelos resides.
  33. HELP
  34. );
  35. }
  36. class AkelosInstaller
  37. {
  38. public $options = array();
  39. public $errors = array();
  40. public function __construct($options)
  41. {
  42. $default_options = array(
  43. 'source' => $this->getAbsolutePath(dirname(__FILE__).DIRECTORY_SEPARATOR.str_repeat(DIRECTORY_SEPARATOR.'..',5)),
  44. 'force' => false,
  45. 'skip' => false,
  46. 'quiet' => false,
  47. 'public_html' => false,
  48. 'dependencies' => false
  49. );
  50. $this->options = array_merge($default_options, $options);
  51. $this->options['directory'] = $this->getAbsolutePath(@$this->options['directory']);
  52. if(empty($this->options['directory'])){
  53. trigger_error('You must supply a valid destination path', E_USER_ERROR);
  54. }
  55. $this->source_tree = Ak::dir($this->options['source'],array('dirs'=>true,'recurse'=>true));
  56. $this->destination_tree = Ak::dir($this->options['directory'],array('dirs'=>true,'recurse'=>true));
  57. }
  58. public function install()
  59. {
  60. if(empty($this->destination_tree) || !empty($this->options['force'])){
  61. if(!is_dir($this->options['directory'])){
  62. if(!$this->_makeDir($this->options['directory'])){
  63. $this->addError("Can't create directory: " . $this->options['directory']);
  64. return false;
  65. }
  66. }
  67. $this->_copyApplicationFiles($this->source_tree, $this->options['source']);
  68. if(empty($this->options['dependencies'])){
  69. $this->_linkDependencies();
  70. }
  71. $this->runEvironmentSpecificTasks();
  72. $this->_linkPublicHtmlFolder();
  73. }else{
  74. $this->addError('Installation directory is not empty. Add --force if you want to override existing files');
  75. }
  76. }
  77. public function yield($message)
  78. {
  79. if(empty($this->options['quiet'])){
  80. echo $message."\n";
  81. }
  82. }
  83. public function addError($error)
  84. {
  85. $this->errors[$error] = '';
  86. }
  87. public function getErrors()
  88. {
  89. return array_keys($this->errors);
  90. }
  91. public function hasErrors()
  92. {
  93. return !empty($this->errors);
  94. }
  95. public function runEvironmentSpecificTasks()
  96. {
  97. if($evironment = $this->guessEnvironment()){
  98. $method_name = 'run'.$evironment.'Tasks';
  99. if(method_exists($this, $method_name)){
  100. $this->$method_name();
  101. }
  102. }
  103. }
  104. // Environment specific tasks
  105. public function guessEnvironment()
  106. {
  107. if(AK_WIN){
  108. if(file_exists('C:/xampp/apache/conf/httpd.conf')){
  109. return 'DefaultXamppOnWindows';
  110. }
  111. }
  112. return false;
  113. }
  114. public function runDefaultXamppOnWindowsTasks()
  115. {
  116. // XAMPP has mod_rewrite disabled by default so we will try to enable it.
  117. $http_conf = file_get_contents('C:/xampp/apache/conf/httpd.conf');
  118. if(strstr($http_conf, '#LoadModule rewrite_module')){
  119. $this->yield('Enabling mod_rewrite');
  120. file_put_contents('C:/xampp/apache/conf/httpd.conf.akelos', $http_conf);
  121. file_put_contents('C:/xampp/apache/conf/httpd.conf',
  122. str_replace(
  123. '#LoadModule rewrite_module',
  124. 'LoadModule rewrite_module',
  125. $http_conf
  126. ));
  127. $this->yield('Restarting Apache');
  128. // Stop apache
  129. exec('C:\xampp\apache\bin\pv -f -k apache.exe -q');
  130. exec('rm C:\xampp\apache\logs\httpd.pid');
  131. // Start Apache in the background
  132. $shell = new COM('WScript.Shell');
  133. $shell->Run('C:\xampp\apache\bin\apache.exe', 0, false);
  134. }
  135. $my_cnf = @file_get_contents('C:/xampp/mysql/bin/my.cnf');
  136. // InnoDB engine is not enabled by default on XAMPP we need it enabled in order to use transactions
  137. if(strstr($my_cnf, '#innodb_')){
  138. $this->yield('Enabling InnoDB MySQL engine.');
  139. file_put_contents('C:/xampp/mysql/bin/my.cnf.akelos', $my_cnf);
  140. file_put_contents('C:/xampp/mysql/bin/my.cnf',
  141. str_replace(
  142. array('skip-innodb', '#innodb_', '#set-variable = innodb'),
  143. array('#skip-innodb', 'innodb_', 'set-variable = innodb')
  144. ,$my_cnf));
  145. $this->yield('Restarting MySQL server.');
  146. $shell = new COM('WScript.Shell');
  147. $shell->Run('C:\xampp\mysql\bin\mysqladmin --user=pma --password= shutdown', 0, false);
  148. $shell = new COM('WScript.Shell');
  149. $shell->Run('C:\xampp\mysql\bin\mysqld --defaults-file=C:\xampp\mysql\bin\my.cnf --standalone --console', 0, false);
  150. }
  151. }
  152. // Protected methods
  153. protected function _linkPublicHtmlFolder()
  154. {
  155. if(!empty($this->options['public_html'])){
  156. if(function_exists('symlink')){
  157. $this->options['public_html'] = $this->getAbsolutePath($this->options['public_html']);
  158. $link_info = @linkinfo($this->options['public_html']);
  159. $target = $this->options['directory'].DS.'public';
  160. if($target == $this->options['public_html']){
  161. // No need to symlink, same path on target
  162. return true;
  163. }
  164. if(!is_numeric($link_info) || $link_info < 0){
  165. $this->yield("\n Adding symbolic link ".$this->options['public_html'].' to the public web server.');
  166. if(@symlink($target, $this->options['public_html'])){
  167. return true;
  168. }
  169. }
  170. }
  171. $this->yield("\n Could not create a symbolic link of ".$this->options['directory'].DS.'public'.' at '.$this->options['public_html']);
  172. }
  173. return false;
  174. }
  175. protected function _linkDependencies()
  176. {
  177. $fw_path = str_replace(AK_BASE_DIR, '', AK_FRAMEWORK_DIR);
  178. $fw_on_app = $this->options['directory'].DS.trim($fw_path, DS);
  179. $this->yield("\n Linking the application with the framework at ".$this->options['source'])."\n";
  180. $old = "defined('AK_FRAMEWORK_DIR') || define('AK_FRAMEWORK_DIR', AK_BASE_DIR.DS.'vendor'.DS.'akelos');";
  181. $new = "defined('AK_FRAMEWORK_DIR') || define('AK_FRAMEWORK_DIR', '".addcslashes(AK_FRAMEWORK_DIR,'\\')."');";
  182. $paths = array(
  183. $this->options['directory'].DS.'config'.DS.'boot.php',
  184. $this->options['directory'].DS.'makelos',
  185. $this->options['directory'].DS.'test'.DS.'shared'.DS.'config'.DS.'app_config.php');
  186. foreach($paths as $path){
  187. file_put_contents($path, str_replace($old, $new, file_get_contents($path)));
  188. }
  189. Ak::rmdir_tree($fw_on_app);
  190. }
  191. protected function _copyApplicationFiles($directory_structure, $base_path = '.')
  192. {
  193. foreach ($directory_structure as $k=>$node){
  194. $path = $base_path.DS.$node;
  195. if(is_dir($path)){
  196. $this->_makeDir($path);
  197. }elseif(is_file($path)){
  198. $this->_copyFile($path);
  199. }elseif(is_array($node)){
  200. foreach ($node as $dir=>$items){
  201. $path = $base_path.DS.$dir;
  202. if(is_dir($path)){
  203. $this->_makeDir($path);
  204. $this->_copyApplicationFiles($items, $path);
  205. }
  206. }
  207. }
  208. }
  209. }
  210. protected function _makeDir($path)
  211. {
  212. $dir = $this->_getDestinationPath($path);
  213. if($this->_canUsePath($dir)){
  214. if(!is_dir($dir)){
  215. $this->yield(" Creating directory: ".$dir);
  216. if(!@mkdir($dir))
  217. return false;
  218. }
  219. }
  220. return true;
  221. }
  222. protected function _copyFile($path)
  223. {
  224. $destination_file = $this->_getDestinationPath($path);
  225. if($this->_canUsePath($destination_file)){
  226. if(!file_exists($destination_file)){
  227. $this->yield(" Creating file: ".$destination_file);
  228. copy($path, $destination_file);
  229. }elseif(md5_file($path) != md5_file($destination_file)){
  230. $this->yield(" Modifying file: ".$destination_file);
  231. copy($path, $destination_file);
  232. }
  233. $source_file_mode = fileperms($path);
  234. $target_file_mode = fileperms($destination_file);
  235. if($source_file_mode != $target_file_mode){
  236. $this->yield(" Setting $destination_file permissions to: ".(sprintf("%o",$source_file_mode)));
  237. chmod($destination_file,$source_file_mode);
  238. }
  239. }
  240. }
  241. /**
  242. * Computes the destination path
  243. *
  244. * Giving /path/to/the_framework/lib/Ak.php will rerturn /my/project/path/lib/Ak.php
  245. */
  246. protected function _getDestinationPath($path)
  247. {
  248. return str_replace($this->options['source'].DS, $this->options['directory'].DS, $path);
  249. }
  250. /**
  251. * Returns false if operating on the path is not allowed
  252. */
  253. protected function _canUsePath($path)
  254. {
  255. if(strstr($path, '.empty_directory') || strstr($path, '.git')){
  256. return false;
  257. }
  258. if(is_file($path) || is_dir($path)){
  259. return !empty($this->options['skip']) ? false : !empty($this->options['force']);
  260. }
  261. return true;
  262. }
  263. static function getAbsolutePath($path)
  264. {
  265. $_path = $path;
  266. if (!preg_match((AK_WIN ? "/^\w+:/" : "/^\//"), $path )) {
  267. $current_dir = AK_WIN ? str_replace("\\", DS, realpath('.').DS) : realpath('.').DS;
  268. $_path = $current_dir . $_path;
  269. }
  270. $start = '';
  271. if(AK_WIN){
  272. list($start, $_path) = explode(':', $_path, 2);
  273. $start .= ':';
  274. }
  275. $real_parts = array();
  276. $parts = explode(DS, $_path);
  277. for ($i = 0; $i < count($parts); $i++ ) {
  278. if (strlen($parts[$i]) == 0 || $parts[$i] == "."){
  279. continue;
  280. }
  281. if ($parts[$i] == '..'){
  282. if(count($real_parts) > 0){
  283. array_pop($real_parts);
  284. }
  285. }else{
  286. array_push($real_parts, $parts[$i]);
  287. }
  288. }
  289. return $start.DS.implode(DS,$real_parts );
  290. }
  291. }
  292. function get_command_value($options, $short, $long, $default = null, $error_if_unset = null, $value_if_isset = null){
  293. $isset = isset($options[$long]) || isset($options[$short]);
  294. $value = isset($options[$short]) ?
  295. $options[$short] :
  296. (isset($options[$long])?$options[$long]:$default);
  297. if(is_null($value) && !empty($error_if_unset)){
  298. echo Ak::t($error_if_unset)."\n";
  299. exit(0);
  300. }
  301. if(!is_null($value_if_isset) && $isset){
  302. return $isset ? $value_if_isset : $value;
  303. }
  304. return is_null($value) ? false : $value;
  305. }
  306. $directory_candidate = get_command_value($options, 'd', 'directory', false);
  307. foreach ($options as $k => $v){
  308. if(!$directory_candidate && !preg_match('/^(d|directory|p|public_html|i|dependencies|f|force|q|quiet|s|skip|prompt)$/', $v)){
  309. $directory_candidate = $v;
  310. }
  311. }
  312. $directory = AkelosInstaller::getAbsolutePath(
  313. get_command_value($options, 'd', 'directory', $directory_candidate,
  314. 'Destination directory can\'t be blank'));
  315. $public_html = get_command_value($options, 'p', 'public_html', false);
  316. $public_html = empty($public_html) ? false : AkelosInstaller::getAbsolutePath($public_html);
  317. $dependencies= get_command_value($options, 'i', 'dependencies', true, null, false);
  318. $force = get_command_value($options, 'f', 'force', false);
  319. $quiet = get_command_value($options, 'q', 'quiet', false);
  320. $skip = get_command_value($options, 's', 'skip', false);
  321. $prompt = get_command_value($options, 'prompt', 'prompt', true);
  322. if($prompt){
  323. echo "\nInstall Akelos in $directory\n";
  324. if($public_html)
  325. echo "symlink the public directory to $public_html\n";
  326. echo $dependencies ?
  327. "copy the Akelos Framework files to vendor/akelos\n" :
  328. "symlink the Akelos Framework in ".AK_FRAMEWORK_DIR."\n" ;
  329. if($force)
  330. "OVERWRITE EXISTING FILES in $directory\n";
  331. AkInstaller::promptUserVar("Shall web proceed installing? \nPress enter to continue", array('optional' => true));
  332. }
  333. $Installer = new AkelosInstaller(array(
  334. 'directory' =>$directory,
  335. 'public_html' =>$public_html,
  336. 'public_html' =>$public_html,
  337. 'dependencies' =>$dependencies,
  338. 'force' =>$force,
  339. 'quiet' =>$quiet,
  340. 'skip' =>$skip,
  341. 'prompt' =>$prompt,
  342. ));
  343. $Installer->install();
  344. if(!$quiet){
  345. if($Installer->hasErrors()){
  346. echo "\nThere where some errors during the installation process:\n";
  347. echo "\n * ".join("\n * ",$Installer->getErrors());
  348. }elseif(empty($Installer->options['force'])){
  349. echo "\n Please point your browser to ".
  350. (empty($Installer->options['public_html']) ? $Installer->options['directory'] : $Installer->options['public_html']).
  351. " in order to complete the installation process or\n\n".
  352. " run \n\n ./script/configure -i\n\nto configure the database details\n";
  353. }
  354. echo "\n";
  355. }