2 // vim: foldmethod=marker
4 * Ethna_SkeltonGenerator.php
6 * @author Masaki Fujimoto <fujimoto@php.net>
7 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
12 // {{{ Ethna_SkeltonGenerator
14 * ¥¹¥±¥ë¥È¥óÀ¸À®¥¯¥é¥¹
16 * @author Masaki Fujimoto <fujimoto@php.net>
20 class Ethna_SkeltonGenerator
23 * ¥×¥í¥¸¥§¥¯¥È¥¹¥±¥ë¥È¥ó¤òÀ¸À®¤¹¤ë
26 * @param string $basedir ¥×¥í¥¸¥§¥¯¥È¥Ù¡¼¥¹¥Ç¥£¥ì¥¯¥È¥ê
27 * @param string $id ¥×¥í¥¸¥§¥¯¥ÈID
28 * @return bool true:À®¸ù false:¼ºÇÔ
30 function generateProjectSkelton($basedir, $id)
34 array("app/action", 0755),
35 array("app/action_cli", 0755),
36 array("app/action_xmlrpc", 0755),
37 array("app/filter", 0755),
38 array("app/plugin", 0755),
39 array("app/plugin/Filter", 0755),
40 array("app/plugin/Validator", 0755),
41 array("app/view", 0755),
45 array("locale", 0755),
46 array("locale/ja", 0755),
47 array("locale/ja/LC_MESSAGES", 0755),
49 array("schema", 0755),
51 array("template", 0755),
52 array("template/ja", 0755),
55 array("www/css", 0755),
56 array("www/js", 0755),
59 $r = Ethna_Controller::checkAppId($id);
60 if (Ethna::isError($r)) {
64 $basedir = sprintf("%s/%s", $basedir, strtolower($id));
67 if (is_dir($basedir) == false) {
69 printf("creating directory ($basedir) [y/n]: ");
71 $fp = fopen("php://stdin", "r");
72 $r = trim(fgets($fp, 128));
74 if (strtolower($r) != 'y') {
75 return Ethna::raiseError('aborted by user');
78 if (mkdir($basedir, 0775) == false) {
79 return Ethna::raiseError('directory creation failed');
82 foreach ($dir_list as $dir) {
85 $target = "$basedir/$dir";
86 if (is_dir($target)) {
87 printf("%s already exists -> skipping...\n", $target);
90 if (mkdir($target, $mode) == false) {
91 return Ethna::raiseError('directory creation failed');
93 printf("project sub directory created [%s]\n", $target);
95 if (chmod($target, $mode) == false) {
96 return Ethna::raiseError('chmod failed');
100 // ¥¹¥±¥ë¥È¥ó¥Õ¥¡¥¤¥ëºîÀ®
101 $macro['application_id'] = strtoupper($id);
102 $macro['project_id'] = ucfirst($id);
103 $macro['project_prefix'] = strtolower($id);
104 $macro['basedir'] = realpath($basedir);
106 $macro['action_class'] = '{$action_class}';
107 $macro['action_form'] = '{$action_form}';
108 $macro['action_name'] = '{$action_name}';
109 $macro['action_path'] = '{$action_path}';
110 $macro['forward_name'] = '{$forward_name}';
111 $macro['view_name'] = '{$view_name}';
112 $macro['view_path'] = '{$view_path}';
114 $user_macro = $this->_getUserMacro();
115 $default_macro = $macro;
116 $macro = array_merge($macro, $user_macro);
118 // the longest if? :)
119 if ($this->_generateFile("www.index.php", "$basedir/www/index.php", $macro) == false ||
120 $this->_generateFile("www.info.php", "$basedir/www/info.php", $macro) == false ||
121 $this->_generateFile("www.unittest.php", "$basedir/www/unittest.php", $macro) == false ||
122 $this->_generateFile("www.xmlrpc.php", "$basedir/www/xmlrpc.php", $macro) == false ||
123 $this->_generateFile("www.css.ethna.css", "$basedir/www/css/ethna.css", $macro) == false ||
124 $this->_generateFile("dot.ethna", "$basedir/.ethna", $macro) == false ||
125 $this->_generateFile("app.controller.php", sprintf("$basedir/app/%s_Controller.php", $macro['project_id']), $macro) == false ||
126 $this->_generateFile("app.error.php", sprintf("$basedir/app/%s_Error.php", $macro['project_id']), $macro) == false ||
127 $this->_generateFile("app.action.default.php", "$basedir/app/action/Index.php", $macro) == false ||
128 $this->_generateFile("app.plugin.filter.default.php", sprintf("$basedir/app/plugin/Filter/%s_Plugin_Filter_ExecutionTime.php", $macro['project_id']), $macro) == false ||
129 $this->_generateFile("app.view.default.php", "$basedir/app/view/Index.php", $macro) == false ||
130 $this->_generateFile("app.unittest.php", sprintf("$basedir/app/%s_UnitTestManager.php", $macro['project_id']), $macro) == false ||
131 $this->_generateFile("etc.ini.php", sprintf("$basedir/etc/%s-ini.php", $macro['project_prefix']), $macro) == false ||
132 $this->_generateFile("skel.action.php", sprintf("$basedir/skel/skel.action.php"), $default_macro) == false ||
133 $this->_generateFile("skel.action_cli.php", sprintf("$basedir/skel/skel.action_cli.php"), $default_macro) == false ||
134 $this->_generateFile("skel.action_test.php", sprintf("$basedir/skel/skel.action_test.php"), $default_macro) == false ||
135 $this->_generateFile("skel.app_object.php", sprintf("$basedir/skel/skel.app_object.php"), $default_macro) == false ||
136 $this->_generateFile("skel.cli.php", sprintf("$basedir/skel/skel.cli.php"), $default_macro) == false ||
137 $this->_generateFile("skel.view.php", sprintf("$basedir/skel/skel.view.php"), $default_macro) == false ||
138 $this->_generateFile("skel.template.tpl", sprintf("$basedir/skel/skel.template.tpl"), $default_macro) == false ||
139 $this->_generateFile("skel.view_test.php", sprintf("$basedir/skel/skel.view_test.php"), $default_macro) == false ||
140 $this->_generateFile("template.index.tpl", sprintf("$basedir/template/ja/index.tpl"), $default_macro) == false) {
141 return Ethna::raiseError('generating files failed');
148 * ¥¢¥¯¥·¥ç¥ó¤Î¥¹¥±¥ë¥È¥ó¤òÀ¸À®¤¹¤ë
151 * @param string $action_name ¥¢¥¯¥·¥ç¥ó̾
152 * @param string $app_dir ¥×¥í¥¸¥§¥¯¥È¥Ç¥£¥ì¥¯¥È¥ê
153 * @param int $gateway ¥²¡¼¥È¥¦¥§¥¤
154 * @return bool true:À®¸ù false:¼ºÇÔ
156 function generateActionSkelton($action_name, $app_dir, $gateway = GATEWAY_WWW)
158 // discover controller
159 $controller_class = $this->_discoverController($app_dir);
160 if (Ethna::isError($controller_class)) {
161 return $controller_class;
164 $c =& new $controller_class;
165 $c->setGateway(GATEWAY_CLI);
167 $action_dir = $c->getActiondir($gateway);
168 $action_class = $c->getDefaultActionClass($action_name, $gateway);
169 $action_form = $c->getDefaultFormClass($action_name, $gateway);
170 $action_path = $c->getDefaultActionPath($action_name);
173 $macro['project_id'] = $c->getAppId();
174 $macro['action_name'] = $action_name;
175 $macro['action_class'] = $action_class;
176 $macro['action_form'] = $action_form;
177 $macro['action_path'] = $action_path;
179 $user_macro = $this->_getUserMacro();
180 $macro = array_merge($macro, $user_macro);
182 $this->_mkdir(dirname("$action_dir$action_path"), 0755);
186 $skelton = "skel.action.php";
189 $skelton = "skel.action_cli.php";
192 $skelton = "skel.action_xmlrpc.php";
196 if (file_exists("$action_dir$action_path")) {
197 printf("file [%s] already exists -> skip\n", "$action_dir$action_path");
198 } else if ($this->_generateFile($skelton, "$action_dir$action_path", $macro) == false) {
199 printf("[warning] file creation failed [%s]\n", "$action_dir$action_path");
201 printf("action script(s) successfully created [%s]\n", "$action_dir$action_path");
206 * ¥Ó¥å¡¼¤Î¥¹¥±¥ë¥È¥ó¤òÀ¸À®¤¹¤ë
209 * @param string $forward_name ¥¢¥¯¥·¥ç¥ó̾
210 * @param string $app_dir ¥×¥í¥¸¥§¥¯¥È¥Ç¥£¥ì¥¯¥È¥ê
211 * @return bool true:À®¸ù false:¼ºÇÔ
213 function generateViewSkelton($forward_name, $app_dir)
215 // discover controller
216 $controller_class = $this->_discoverController($app_dir);
217 if (Ethna::isError($controller_class)) {
218 return $controller_class;
221 $c =& new $controller_class;
222 $c->setGateway(GATEWAY_CLI);
224 $view_dir = $c->getViewdir();
225 $view_class = $c->getDefaultViewClass($forward_name, false);
226 $view_path = $c->getDefaultViewPath($forward_name, false);
229 $macro['project_id'] = $c->getAppId();
230 $macro['forward_name'] = $forward_name;
231 $macro['view_class'] = $view_class;
232 $macro['view_path'] = $view_path;
234 $user_macro = $this->_getUserMacro();
235 $macro = array_merge($macro, $user_macro);
237 $this->_mkdir(dirname("$view_dir/$view_path"), 0755);
239 if (file_exists("$view_dir$view_path")) {
240 printf("file [%s] already exists -> skip\n", "$view_dir$view_path");
241 } else if ($this->_generateFile("skel.view.php", "$view_dir$view_path", $macro) == false) {
242 printf("[warning] file creation failed [%s]\n", "$view_dir$view_path");
244 printf("view script(s) successfully created [%s]\n", "$view_dir$view_path");
249 * CLI¥¨¥ó¥È¥ê¥Ý¥¤¥ó¥È¤Î¥¹¥±¥ë¥È¥ó¤òÀ¸À®¤¹¤ë
252 * @param string $forward_name ¥¢¥¯¥·¥ç¥ó̾
253 * @param string $app_dir ¥×¥í¥¸¥§¥¯¥È¥Ç¥£¥ì¥¯¥È¥ê
254 * @return bool true:À®¸ù false:¼ºÇÔ
256 function generateCliSkelton($action_name, $app_dir)
258 // discover controller
259 $controller_class = $this->_discoverController($app_dir);
260 if (Ethna::isError($controller_class)) {
261 return $controller_class;
264 $c =& new $controller_class;
265 $c->setGateway(GATEWAY_CLI);
267 $app_dir = $c->getDirectory('app');
268 $bin_dir = $c->getDirectory('bin');
269 $cli_file = sprintf("%s/%s.%s", $bin_dir, $action_name, $c->getExt('php'));
272 $macro['project_id'] = $c->getAppId();
273 $macro['action_name'] = $action_name;
274 $macro['dir_app'] = $app_dir;
275 $macro['dir_bin'] = $bin_dir;
277 $user_macro = $this->_getUserMacro();
278 $macro = array_merge($macro, $user_macro);
280 if (file_exists($cli_file)) {
281 printf("file [%s] already exists -> skip\n", $cli_file);
282 } else if ($this->_generateFile("skel.cli.php", $cli_file, $macro) == false) {
283 printf("[warning] file creation failed [%s]\n", $cli_file);
285 printf("action script(s) successfully created [%s]\n", $cli_file);
290 * ¥Æ¥ó¥×¥ì¡¼¥È¤Î¥¹¥±¥ë¥È¥ó¤òÀ¸À®¤¹¤ë
293 * @param string $forward_name ¥¢¥¯¥·¥ç¥ó̾
294 * @param string $app_dir ¥×¥í¥¸¥§¥¯¥È¥Ç¥£¥ì¥¯¥È¥ê
295 * @return bool true:À®¸ù false:¼ºÇÔ
297 function generateTemplateSkelton($forward_name, $app_dir)
299 // discover controller
300 $controller_class = $this->_discoverController($app_dir);
301 if (Ethna::isError($controller_class)) {
302 return $controller_class;
305 $c =& new $controller_class;
306 $c->setGateway(GATEWAY_CLI);
308 $tpl_dir = $c->getTemplatedir();
309 if ($tpl_dir{strlen($tpl_dir)-1} != '/') {
312 $tpl_path = $c->getDefaultForwardPath($forward_name);
315 // add '_' for tpl and no user macro for tpl
316 $macro['_project_id'] = $c->getAppId();
318 $this->_mkdir(dirname("$tpl_dir/$tpl_path"), 0755);
320 if (file_exists("$tpl_dir$tpl_path")) {
321 printf("file [%s] already exists -> skip\n", "$tpl_dir$tpl_path");
322 } else if ($this->_generateFile("skel.template.tpl", "$tpl_dir$tpl_path", $macro) == false) {
323 printf("[warning] file creation failed [%s]\n", "$tpl_dir$tpl_path");
325 printf("template file(s) successfully created [%s]\n", "$tpl_dir$tpl_path");
330 * ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¹¥±¥ë¥È¥ó¤òÀ¸À®¤¹¤ë
333 * @param string $table_name ¥Æ¡¼¥Ö¥ë̾
334 * @param string $app_dir ¥×¥í¥¸¥§¥¯¥È¥Ç¥£¥ì¥¯¥È¥ê
335 * @return bool true:À®¸ù false:¼ºÇÔ
337 function generateAppObjectSkelton($table_name, $app_dir)
339 // discover controller
340 $controller_class = $this->_discoverController($app_dir);
341 if (Ethna::isError($controller_class)) {
342 return $controller_class;
345 $c =& new $controller_class;
346 $c->setGateway(GATEWAY_CLI);
348 $table_id = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($table_name));
350 $app_dir = $c->getDirectory('app');
351 $app_path = ucfirst($c->getAppId()) . '_' . $table_id .'.php';
354 $macro['project_id'] = $c->getAppId();
355 $macro['app_path'] = $app_path;
356 $macro['app_object'] = ucfirst($c->getAppId()) . '_' . $table_id;
358 $user_macro = $this->_getUserMacro();
359 $macro = array_merge($macro, $user_macro);
361 $path = "$app_dir/$app_path";
362 $this->_mkdir(dirname($path), 0755);
363 if (file_exists($path)) {
364 printf("file [%s] already exists -> skip\n", $path);
365 } else if ($this->_generateFile("skel.app_object.php", $path, $macro) == false) {
366 printf("[warning] file creation failed [%s]\n", $path);
368 printf("app-object script(s) successfully created [%s]\n", $path);
373 * ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Þ¥Í¡¼¥¸¥ã¤Î¥¹¥±¥ë¥È¥ó¤òÀ¸À®¤¹¤ë
376 * @param string $manager_name ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Þ¥Í¡¼¥¸Ì¾
377 * @param string $app_dir ¥×¥í¥¸¥§¥¯¥È¥Ç¥£¥ì¥¯¥È¥ê
378 * @return bool true:À®¸ù false:¼ºÇÔ
380 function generateAppManagerSkelton($manager_name, $app_dir)
382 // discover controller
383 $controller_class = $this->_discoverController($app_dir);
384 if (Ethna::isError($controller_class)) {
385 return $controller_class;
388 $c =& new $controller_class;
389 $c->setGateway(GATEWAY_CLI);
391 $manager_id = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($manager_name));
393 $app_dir = $c->getDirectory('app');
394 $app_path = ucfirst($c->getAppId()) . '_' . $manager_id .'Manager.php';
397 $macro['project_id'] = $c->getAppId();
398 $macro['app_path'] = $app_path;
399 $macro['app_manager'] = ucfirst($c->getAppId()) . '_' . $manager_id;
401 $user_macro = $this->_getUserMacro();
402 $macro = array_merge($macro, $user_macro);
404 $path = "$app_dir/$app_path";
405 $this->_mkdir(dirname($path), 0755);
406 if (file_exists($path)) {
407 printf("file [%s] already exists -> skip\n", $path);
408 } else if ($this->_generateFile("skel.app_manager.php", $path, $macro) == false) {
409 printf("[warning] file creation failed [%s]\n", $path);
411 printf("app-manager script(s) successfully created [%s]\n", $path);
416 * ¥¢¥¯¥·¥ç¥óÍѥƥ¹¥È¤Î¥¹¥±¥ë¥È¥ó¤òÀ¸À®¤¹¤ë
419 * @param string $action_name ¥¢¥¯¥·¥ç¥ó̾
420 * @param string $app_dir ¥×¥í¥¸¥§¥¯¥È¥Ç¥£¥ì¥¯¥È¥ê
421 * @return bool true:À®¸ù false:¼ºÇÔ
423 function generateActionTestSkelton($action_name, $app_dir, $gateway = GATEWAY_WWW)
425 // discover controller
426 $controller_class = $this->_discoverController($app_dir);
427 if (Ethna::isError($controller_class)) {
428 return $controller_class;
431 $c =& new $controller_class;
432 $c->setGateway(GATEWAY_CLI);
434 $action_dir = $c->getActiondir($gateway);
435 $action_class = $c->getDefaultActionClass($action_name, false);
436 $action_form = $c->getDefaultFormClass($action_name, false);
437 $action_path = $c->getDefaultActionPath($action_name . "Test", false);
440 $macro['project_id'] = $c->getAppId();
441 $macro['action_name'] = $action_name;
442 $macro['action_class'] = $action_class;
443 $macro['action_form'] = $action_form;
444 $macro['action_path'] = $action_path;
446 $user_macro = $this->_getUserMacro();
447 $macro = array_merge($macro, $user_macro);
449 $this->_mkdir(dirname("$action_dir$action_path"), 0755);
451 if (file_exists("$action_dir$action_path")) {
452 printf("file [%s] aleady exists -> skip\n", "$action_dir$action_path");
453 } else if ($this->_generateFile("skel.action_test.php", "$action_dir$action_path", $macro) == false) {
454 printf("[warning] file creation failed [%s]\n", "$action_dir$action_path");
456 printf("action test(s) successfully created [%s]\n", "$action_dir$action_path");
461 * ¥Ó¥å¡¼Íѥƥ¹¥È¤Î¥¹¥±¥ë¥È¥ó¤òÀ¸À®¤¹¤ë
464 * @param string $forward_name ¥¢¥¯¥·¥ç¥ó̾
465 * @return bool true:À®¸ù false:¼ºÇÔ
467 function generateViewTestSkelton($forward_name, $app_dir)
469 // discover controller
470 $controller_class = $this->_discoverController($app_dir);
471 if (Ethna::isError($controller_class)) {
472 return $controller_class;
475 $c =& new $controller_class;
476 $c->setGateway(GATEWAY_CLI);
478 $view_dir = $c->getViewdir();
479 $view_class = $c->getDefaultViewClass($forward_name, false);
480 $view_path = $c->getDefaultViewPath($forward_name . "Test", false);
483 $macro['project_id'] = $c->getAppId();
484 $macro['forward_name'] = $forward_name;
485 $macro['view_class'] = $view_class;
486 $macro['view_path'] = $view_path;
488 $user_macro = $this->_getUserMacro();
489 $macro = array_merge($macro, $user_macro);
491 $this->_mkdir(dirname("$view_dir/$view_path"), 0755);
493 if (file_exists("$view_dir$view_path")) {
494 printf("file [%s] aleady exists -> skip\n", "$view_dir$view_path");
495 } else if ($this->_generateFile("skel.view_test.php", "$view_dir$view_path", $macro) == false) {
496 printf("[warning] file creation failed [%s]\n", "$view_dir$view_path");
498 printf("view test(s) successfully created [%s]\n", "$view_dir$view_path");
506 * @param string $dir ºîÀ®¤¹¤ë¥Ç¥£¥ì¥¯¥È¥ê
507 * @param int $mode ¥Ñ¡¼¥ß¥Ã¥·¥ç¥ó
508 * @return bool true:À®¸ù false:¼ºÇÔ
510 function _mkdir($dir, $mode)
516 $parent = dirname($dir);
517 if ($dir == $parent) {
520 if (is_dir($parent) == false) {
521 $this->_mkdir($parent, $mode);
524 return mkdir($dir, $mode);
528 * ¥¹¥±¥ë¥È¥ó¥Õ¥¡¥¤¥ë¤Ë¥Þ¥¯¥í¤òŬÍѤ·¤Æ¥Õ¥¡¥¤¥ë¤òÀ¸À®¤¹¤ë
530 * ethna¥é¥¤¥Ö¥é¥ê¤Î¥Ç¥£¥ì¥¯¥È¥ê¹½Â¤¤¬Êѹ¹¤µ¤ì¤Æ¤¤¤Ê¤¤¤³¤È¤¬Á°Äó
531 * ¤È¤Ê¤Ã¤Æ¤¤¤ëÅÀ¤ËÃí°Õ
534 * @param string $skel ¥¹¥±¥ë¥È¥ó¥Õ¥¡¥¤¥ë
535 * @param string $entity À¸À®¥Õ¥¡¥¤¥ë̾
536 * @param array $macro ÃÖ´¹¥Þ¥¯¥í
537 * @return bool true:Àµ¾ï½ªÎ» false:¥¨¥é¡¼
539 function _generateFile($skel, $entity, $macro)
543 if (file_exists($entity)) {
544 printf("file [%s] already exists -> skip\n", $entity);
547 $c =& Ethna_Controller::getInstance();
549 $base = $c->getBasedir();
550 if (file_exists("$base/skel/$skel") == false) {
554 if (is_null($base)) {
555 $base = dirname(dirname(__FILE__));
558 $rfp = fopen("$base/skel/$skel", "r");
562 $wfp = fopen($entity, "w");
569 $s = fread($rfp, 4096);
570 if (strlen($s) == 0) {
574 foreach ($macro as $k => $v) {
575 $s = preg_replace("/{\\\$$k}/", $v, $s);
583 $st = stat("$base/skel/$skel");
584 if (chmod($entity, $st[2]) == false) {
588 printf("file generated [%s -> %s]\n", $skel, $entity);
594 * ¥æ¡¼¥¶ÄêµÁ¤Î¥Þ¥¯¥í¤òÀßÄꤹ¤ë(~/.ethna)
598 function _getUserMacro()
600 if (isset($_SERVER['USERPROFILE']) && is_dir($_SERVER['USERPROFILE'])) {
601 $home = $_SERVER['USERPROFILE'];
603 $home = $_SERVER['HOME'];
606 if (is_file("$home/.ethna") == false) {
610 $user_macro = parse_ini_file("$home/.ethna");
615 * ¥³¥ó¥È¥í¡¼¥é¥Õ¥¡¥¤¥ë/¥¯¥é¥¹¤ò¸¡º÷¤¹¤ë
619 function _discoverController($app_dir)
622 while (is_dir($app_dir) && $app_dir != "/") {
623 if (is_file("$app_dir/.ethna")) {
624 $ini_file = "$app_dir/.ethna";
627 $app_dir = dirname($app_dir);
630 if ($ini_file === null) {
631 return Ethna::raiseError('no .ethna file found');
634 $macro = parse_ini_file($ini_file);
635 if (isset($macro['controller_file']) == false || isset($macro['controller_class']) == false) {
636 return Ethna::raiseError('invalid .ethna file');
638 $file = $macro['controller_file'];
639 $class = $macro['controller_class'];
641 $controller_file = "$app_dir/$file";
642 if (is_file($controller_file) == false) {
643 return Ethna::raiseError("no such file $controller_file");
646 include_once($controller_file);
647 if (class_exists($class) == false) {
648 return Ethna::raiseError("no such class $class");