Completed
Push — master ( c5cc72...7c6f56 )
by Jean-Christophe
02:02
created

Micro::xcopy()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 33
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 14
nc 8
nop 3
1
<?php
2
use micro\controllers\Autoloader;
3
use micro\utils\StrUtils;
4
include 'ModelsCreator.php';
5
include 'Console.php';
6
class Micro {
7
	private static $configOptions;
8
	private static $composer=["require"=>["twig/twig"=>"~1.0"]];
9
	private static $toolsConfig;
10
	private static $indexContent="\n\t\$this->loadView('index.html');\n";
11
	private static $mainViewTemplate="index.html";
12
13
	public static function downloadZip($url,$zipFile="tmp/tmp.zip"){
14
		$f = file_put_contents($zipFile, fopen($url, 'r'), LOCK_EX);
15
	if(FALSE === $f)
16
		die("Couldn't write to file.");
17
	else{
18
		echo $f." downloaded.\n";
19
	}
20
	}
21
22
	public static function createComposerFile(){
23
		$composer=json_encode(self::$composer);
24
		echo "Composer file creation...\n";
25
		self::writeFile("composer.json", $composer);
26
	}
27
28
	public static function unzip($zipFile,$extractPath="."){
29
		$zip = new \ZipArchive();
30
		if (! $zip) {
31
			echo "<br>Could not make ZipArchive object.";
32
			exit;
33
		}
34
		if($zip->open($zipFile) !== TRUE){
35
			echo "Error :- Unable to open the Zip File";
36
		}
37
		/* Extract Zip File */
38
		$zip->extractTo($extractPath);
39
		$zip->close();
40
	}
41
42
	public static function xcopy($source, $dest, $permissions = 0755)
43
	{
44
		// Check for symlinks
45
		if (is_link($source)) {
46
			return symlink(readlink($source), $dest);
47
		}
48
49
		// Simple copy for a file
50
		if (is_file($source)) {
51
			return copy($source, $dest);
52
		}
53
54
		// Make destination directory
55
		if (!is_dir($dest)) {
56
			mkdir($dest, $permissions,true);
57
		}
58
59
		// Loop through the folder
60
		$dir = dir($source);
61
		while (false !== $entry = $dir->read()) {
62
			// Skip pointers
63
			if ($entry == '.' || $entry == '..') {
64
				continue;
65
			}
66
67
			// Deep copy directories
68
			self::xcopy("$source/$entry", "$dest/$entry", $permissions);
69
		}
70
71
		// Clean up
72
		$dir->close();
73
		return true;
74
	}
75
76
	public static function delTree($dir) {
77
		$files = array_diff(scandir($dir), array('.','..'));
78
		foreach ($files as $file) {
79
			(is_dir("$dir/$file")) ? self::delTree("$dir/$file") : unlink("$dir/$file");
80
		}
81
		return rmdir($dir);
82
	}
83
84
	public static function openFile($filename){
85
		if(file_exists($filename)){
86
			return file_get_contents($filename);
87
		}
88
		return false;
89
	}
90
91
	public static function writeFile($filename,$data){
92
			return file_put_contents($filename,$data);
93
	}
94
95
	public static function replaceAll($array,$subject){
96
		array_walk($array, function(&$item){if(is_array($item)) $item=implode("\n", $item);});
97
		return str_replace(array_keys($array), array_values($array), $subject);
98
	}
99
100
	public static function openReplaceWrite($source,$destination,$keyAndValues){
101
		$str=self::openFile($source);
102
		$str=self::replaceAll($keyAndValues,$str);
103
		return self::writeFile($destination,$str);
104
	}
105
106
	private static function getOption($options,$option,$longOption,$default=NULL){
107
		if(array_key_exists($option, $options)){
108
			$option=$options[$option];
109
		}else if(array_key_exists($longOption, $options)){
110
			$option=$options[$longOption];
111
		}
112
		else if(isset($default)===true){
113
			$option=$default;
114
		}else
115
			$option="";
116
		return $option;
117
	}
118
119
	public static function create($projectName,$force=false){
120
		self::$toolsConfig=include("toolsConfig.php");
121
		$arguments=[
122
				["b","dbName",$projectName],
123
				["r","documentRoot","Main"],
124
				["s","serverName","127.0.0.1"],
125
				["p","port","3306"],
126
				["u","user","root"],
127
				["w","password",""],
128
				["m","all-models",false],
129
				["q","phpmv",false],
130
		];
131
		if(!is_dir($projectName) || $force){
132
			if(!$force)
133
				self::safeMkdir($projectName);
134
			chdir($projectName);
135
			echo "Downloading micro.git from https://github.com/phpMv/...\n";
136
			self::safeMkdir("tmp");self::safeMkdir(".micro");
137
			self::downloadZip("https://github.com/phpMv/micro/archive/master.zip","tmp/tmp.zip");
138
			echo "Files extraction...\n";
139
			self::unzip("tmp/tmp.zip","tmp/");
140
			self::safeMkdir("app");
141
			self::safeMkdir("app/views/main");
142
			self::safeMkdir("app/controllers");
143
			define('ROOT', realpath('./app').DS);
144
			echo "Files copy...\n";
145
			self::xcopy("tmp/micro-master/micro/","app/micro");
146
			self::xcopy("tmp/micro-master/project-files/templates", "app/micro/tools/templates");
147
			self::xcopy("tmp/micro-master/project-files/app/controllers/ControllerBase.php", "app/controllers/ControllerBase.php");
148
149
150
			echo "Config files creation...\n";
151
			self::openReplaceWrite("tmp/micro-master/project-files/.htaccess", getcwd()."/.htaccess", array("%rewriteBase%"=>$projectName));
152
			self::$configOptions=["%siteUrl%"=>"http://127.0.0.1/".$projectName."/"];
153
			self::$configOptions["%projectName%"]=$projectName;
154
			self::$configOptions["%injections%"]="";
155
			self::$configOptions["%cssFiles%"]=[];
156
			self::$configOptions["%jsFiles%"]=[];
157
			$options=self::parseArguments();
158
			foreach ($arguments as $argument){
159
				self::$configOptions["%".$argument[1]."%"]=self::getOption($options,$argument[0], $argument[1],$argument[2]);
160
			}
161
			self::showConfigOptions();
162
163
			self::includePhpmv();
164
165
			self::openReplaceWrite("tmp/micro-master/project-files/templates/config.tpl", "app/config.php", self::$configOptions);
166
			self::xcopy("tmp/micro-master/project-files/index.php", "index.php");
167
			self::openReplaceWrite("tmp/micro-master/project-files/templates/vHeader.tpl", "app/views/main/vHeader.html", self::$configOptions);
168
			self::openReplaceWrite("tmp/micro-master/project-files/templates/vFooter.tpl", "app/views/main/vFooter.html", self::$configOptions);
169
170
			require_once 'app/micro/controllers/Autoloader.php';
171
			Autoloader::register();
172
			if(StrUtils::isBooleanTrue(self::$configOptions["%all-models%"]))
173
				ModelsCreator::create();
174
			self::createController("Main",self::$indexContent);
175
			self::xcopy("tmp/micro-master/project-files/app/views/".self::$mainViewTemplate, "app/views/index.html");
176
			echo "deleting temporary files...\n";
177
			self::delTree("tmp");
178
			self::createComposerFile();
179
			$answer=Console::question("Do you want to run composer install ?",["y","n"]);
180
			if(Console::isYes($answer))
181
				system("composer install");
182
			echo "project `{$projectName}` successfully created.\n";
183
		}else{
184
			echo "The {$projectName} folder already exists !\n";
185
			$answer=Console::question("Would you like to continue ?",["y","n"]);
186
			if(Console::isYes($answer)){
187
				self::create($projectName,true);
188
			}else
189
				die();
190
		}
191
	}
192
	private static function includePhpmv(){
193
		if(self::$configOptions["%phpmv%"]!==false){
194
			$phpmv=self::$configOptions["%phpmv%"];
195
			switch ($phpmv){
196
				case "bootstrap":case "semantic":
197
					self::$configOptions["%injections%"]="\"jquery\"=>function(){
198
					\t\t\$jquery=new Ajax\php\micro\JsUtils([\"defer\"=>true]);
199
					\t\t\$jquery->{$phpmv}(new Ajax\\".ucfirst($phpmv)."());
200
					\t\treturn \$jquery;
201
					\t}";
202
					break;
203
				default:
204
					throw new Exception($phpmv." is not a valid option for phpMv-UI.");
205
					break;
206
			}
207
			self::$composer["require"]["phpmv/php-mv-ui"]="dev-master";
208
			if($phpmv==="bootstrap"){
209
				self::$configOptions["%cssFiles%"][]=self::includeCss(self::$toolsConfig["cdn"]["bootstrap"]["css"]);
210
				self::$configOptions["%jsFiles%"][]=self::includeJs(self::$toolsConfig["cdn"]["jquery"]);
211
				self::$configOptions["%jsFiles%"][]=self::includeJs(self::$toolsConfig["cdn"]["bootstrap"]["js"]);
212
				self::$mainViewTemplate="bootstrap.html";
213
			}
214
			elseif($phpmv==="semantic"){
215
				self::$configOptions["%cssFiles%"][]=self::includeCss(self::$toolsConfig["cdn"]["semantic"]["css"]);
216
				self::$configOptions["%jsFiles%"][]=self::includeJs(self::$toolsConfig["cdn"]["jquery"]);
217
				self::$configOptions["%jsFiles%"][]=self::includeJs(self::$toolsConfig["cdn"]["semantic"]["js"]);
218
				self::$indexContent='
219
		$semantic=$this->jquery->semantic();
220
		$semantic->htmlHeader("header",1,"Micro framework");
221
		$bt=$semantic->htmlButton("btTest","Semantic-UI Button");
222
		$bt->onClick("$(\'#test\').html(\'It works with Semantic-UI too !\');");
223
		$this->jquery->compile($this->view);
224
		$this->loadView("index.html");';
225
				self::$mainViewTemplate="semantic.html";
226
			}
227
		}
228
	}
229
230
	private static function includeCss($filename){
231
		return "<link rel=\"stylesheet\" type=\"text/css\" href=\"{$filename}\">";
232
	}
233
234
	private static function includeJs($filename){
235
		return "<script src=\"{$filename}\"></script>";
236
	}
237
238
	private static function showConfigOptions(){
239
		$output = implode(', ', array_map(
240
		function ($v, $k) {if(is_array($v))
241
			$v=implode(",",$v );
242
			return sprintf("%s='%s'", str_ireplace("%", "", $k), $v); },
243
		self::$configOptions,
244
		array_keys(self::$configOptions)
245
		));
246
		echo "command line arguments :\n";
247
		echo $output."\n";
248
	}
249
250
	public static function createController($controllerName,$indexContent=null,$force=false){
251
		$controllerName=ucfirst($controllerName);
252
		self::safeMkdir("app/controllers");
253
		$filename="app/controllers/{$controllerName}.php";
254
		if(file_exists($filename) && !$force){
255
			$answer=Console::question("The file {$filename} exists.\nWould you like to replace it?",["y","n"]);
256
			if(Console::isYes($answer))
257
				self::createController($controllerName,$indexContent,true);
258
		}else{
259
			echo "Creating the Controller {$controllerName} at the location {$filename}\n";
260
			self::openReplaceWrite("app/micro/tools/templates/controller.tpl", $filename, ["%controllerName%"=>$controllerName,"%indexContent%"=>$indexContent]);
261
		}
262
	}
263
264
	private static function safeMkdir($dir){
265
		if(!is_dir($dir))
266
			return mkdir($dir,0777,true);
267
	}
268
269
	private static function setDir($dir=null){
270
		if(file_exists($dir) && is_dir($dir)){
271
			$microDir=$dir.DIRECTORY_SEPARATOR.".micro";
272
			if(file_exists($microDir) && is_dir($microDir)){
273
				chdir($dir);
274
				echo "The project folder is {$dir}\n";
275
				return true;
276
			}
277
		}
278
		$newDir=dirname($dir);
279
		if($newDir===$dir)
280
			return false;
281
		else
282
			return self::setDir($newDir);
283
	}
284
285
	private static function parseArguments(){
286
		global $argv;
287
		array_shift($argv);
288
		$out = array();
289
		foreach($argv as $arg){
290
			if(substr($arg, 0, 2) == '--'){
291
				preg_match ("/\=|\:|\ /", $arg, $matches, PREG_OFFSET_CAPTURE);
292
				$eqPos=$matches[0][1];
293
				//$eqPos = strpos($arg, '=');
294
				if($eqPos === false){
295
					$key = substr($arg, 2);
296
					$out[$key] = isset($out[$key]) ? $out[$key] : true;
297
				}
298
				else{
299
					$key = substr($arg, 2, $eqPos - 2);
300
					$out[$key] = substr($arg, $eqPos + 1);
301
				}
302
			}
303
			else if(substr($arg, 0, 1) == '-'){
304
				if(substr($arg, 2, 1) == '='||substr($arg, 2, 1) == ':' || substr($arg, 2, 1) == ' '){
305
					$key = substr($arg, 1, 1);
306
					$out[$key] = substr($arg, 3);
307
				}
308
				else{
309
					$chars = str_split(substr($arg, 1));
310
					foreach($chars as $char){
311
						$key = $char;
312
						$out[$key] = isset($out[$key]) ? $out[$key] : true;
313
					}
314
				}
315
			}
316
			else{
317
				$out[] = $arg;
318
			}
319
		}
320
		return $out;
321
	}
322
	public static function init($command){
323
		global $argv;
324
		switch ($command) {
325
			case "project":case "create-project":case "new":
326
			self::create($argv[2]);
327
			break;
328
			case "all-models":
329
				self::_init();
330
				ModelsCreator::create();
331
				break;
332
			case "model":
333
				self::_init();
334
				ModelsCreator::create($argv[2]);
335
				break;
336
			case "controller":
337
				self::_init();
338
				self::createController($argv[2]);
339
				break;
340
			default:
341
				;
342
			break;
343
		}
344
	}
345
	private static function _init(){
346
		if(!self::setDir(getcwd())){
347
			echo "Failed to locate project root folder\n";
348
			echo "A Micro project must contain the .micro empty folder.\n";
349
			die();
350
		}
351
		define('ROOT', realpath('./app').DS);
352
353
		require_once 'app/micro/controllers/Autoloader.php';
354
		Autoloader::register();
355
	}
356
}
357
error_reporting(E_ALL);
358
359
define('DS', DIRECTORY_SEPARATOR);
360
361
Micro::init($argv[1]);