source: trunk/bin/module_maker/module.cli.php @ 259

Last change on this file since 259 was 259, checked in by quinn, 17 years ago

Misc bug fixes. Added App::dropQuery() method.

File size: 20.2 KB
Line 
1#!/usr/local/bin/php -q
2<?php
3/**
4 * module.cli.php
5 * Code by Strangecode :: www.strangecode.com :: This document contains copyrighted information
6 */
7
8include_once dirname(__FILE__) . '/_config.inc.php';
9
10$op = null;
11$valid_ops = array('clean', 'var', 'test');
12
13// Test for arguments.
14if (isset($_SERVER['argv'][2]) && isset($_SERVER['argv'][3])) {
15    $module_name_singular = $_SERVER['argv'][2];
16    $module_name_plural = $_SERVER['argv'][3];
17} else {
18    die(basename($_SERVER['argv'][0]) . " Error: invalid arguments. Try like this:
19
20    " . basename($_SERVER['argv'][0]) . " site_directory name_singular name_plural [operation]
21   
22Valid operations include: " . join(', ', $valid_ops) . "
23
24The following files will be generated by this script:
25<site_directory>/admin/nameplural.php
26<site_directory>/admin/_templates/namesingular_list.ihtml
27<site_directory>/admin/_templates/namesingular_form.ihtml
28<site_directory>/html/nameplural.php
29<site_directory>/html/_templates/namesingular_list.ihtml
30<site_directory>/html/_templates/namesingular.ihtml
31
32");
33}
34
35// Test for operation.
36if (isset($_SERVER['argv'][4])) {
37    // Optional fourth arg is op.
38    $op = $_SERVER['argv'][4];
39    // Make sure op is valid.
40    if (!in_array($op, $valid_ops)) {
41        die(basename($_SERVER['argv'][0]) . " Warning: Operation '$op' is not something I know how to do Please select one of: " . join(", ", $valid_ops) . "\n");
42    }
43}
44
45switch ($op) {
46case 'test' :
47    echo "RUNNING MODULE MAKER IN TEST MODE.\n\n";
48    break;
49default :
50
51}
52
53
54/********************************************************************
55* CONFIG
56********************************************************************/
57
58// Where deleted files go:
59$user_trash_folder = $_SERVER['HOME'] . '/.Trash';
60
61// Directories
62$skel_dir = realpath(dirname(__FILE__) . '/skel');
63$admin_dir = realpath(COMMON_BASE . '/admin');
64$admin_tpl_dir = realpath(COMMON_BASE . '/admin/_templates');
65$public_dir = realpath(COMMON_BASE . '/html');
66$public_tpl_dir = realpath(COMMON_BASE . '/html/_templates');
67
68// Names
69$module_title = ucwords(str_replace('_', ' ', $module_name_plural));
70$item_title = ucwords(str_replace('_', ' ', $module_name_singular));
71$module_name_upper = mb_strtoupper(str_replace('_', ' ', $module_name_plural));
72
73// Admin files
74$admin_script = $module_name_plural . '.php';
75$admin_list_template = $module_name_singular . '_list.ihtml';
76$admin_form_template = $module_name_singular . '_form.ihtml';
77
78// Public files
79$public_script = $module_name_plural . '.php';
80$public_list_template = $module_name_singular . '_list.ihtml';
81$public_detail_template = $module_name_singular . '_view.ihtml';
82
83// Databaes names
84$db_tbl = $module_name_singular . '_tbl';
85$primary_key = $module_name_singular . '_id';
86
87// Only after we've defined essential files can we clean.
88if ('clean' == $op) {
89    echo "Beginning file cleanup\n";
90    trashFile("$admin_dir/$admin_script");
91    trashFile("$admin_tpl_dir/$admin_list_template");
92    trashFile("$admin_tpl_dir/$admin_form_template");
93    trashFile("$public_dir/$public_script");
94    trashFile("$public_tpl_dir/$public_list_template");
95    trashFile("$public_tpl_dir/$public_detail_template");
96    echo "End file cleanup\n";
97    die;
98}
99
100// Go!
101echo 'Running Module Maker. Using database: ' . $app->getParam('db_name') . "\n";
102
103
104/********************************************************************
105* PREPROCESSING
106********************************************************************/
107
108// Ensure skel files exist.
109if (
110    !file_exists("$skel_dir/admin.php") ||
111    !file_exists("$skel_dir/public.php") ||
112    !file_exists("$skel_dir/public.ihtml") ||
113    !file_exists("$skel_dir/public_list.ihtml")
114) {
115    die(basename($_SERVER['argv'][0]) . " Warning: one or more skeleton source files missing. Please check directory: $skel_dir.\n");
116}
117
118// Ensure essential directories exist.
119if (!is_dir("$admin_dir")) {
120    die(basename($_SERVER['argv'][0]) . " Error: $admin_dir directory not found.\n");
121}
122if (!is_dir("$admin_tpl_dir")) {
123    die(basename($_SERVER['argv'][0]) . " Error: $admin_tpl_dir directory not found.\n");
124}
125if (!is_dir("$public_dir")) {
126    die(basename($_SERVER['argv'][0]) . " Error: $public_dir directory not found.\n");
127}
128if (!is_dir("$public_tpl_dir")) {
129    die(basename($_SERVER['argv'][0]) . " Error: $public_tpl_dir directory not found.\n");
130}
131
132// Get DB tables.
133$qid = $db->query("SHOW TABLES");
134while (list($row) = mysql_fetch_row($qid)) {
135    $tables[] = $row;
136}
137
138// Make sure requested table is in database.
139if (!in_array($db_tbl, $tables)) {
140    die(sprintf("%s Warning: %s does not exist in database %s. Please select one of: \n\n%s\n\n", basename($_SERVER['argv'][0]), $db_tbl, $app->getParam('db_name'), join("\n", $tables)));
141}
142
143// Ensure requested table contains columns.
144// Get DB table column info.
145$qid = $db->query("DESCRIBE " . $db->escapeString($db_tbl));
146while ($row = mysql_fetch_row($qid)) {
147    $cols[] = $row;
148}
149if (!is_array($cols) || empty($cols)) {
150    die(basename($_SERVER['argv'][0]) . " Warning: $db_tbl does not have any columns.\n");
151}
152
153
154/******************************************************************************
155 * SETUP VARIABLES
156 *****************************************************************************/
157
158
159// Loop through columns
160$upload_file_capability = false;
161$headers = array();
162$public_list_page_vars = array();
163$public_detail_page_vars = array();
164$set_values_default = array();
165if (is_array($cols) && !empty($cols)) {
166    foreach ($cols as $col) {
167
168        // Human readable.
169        $field = $col[0];
170        $field_title = ucfirst(str_replace('_', ' ', $field));
171        $type = preg_replace('/^(\w+).*$/', '\\1', $col[1]);
172        $default = $col[4];
173
174        // Get primary key.
175//         if ('PRI' == $col[3]) {
176//             $primary_key = $field;
177//         }
178
179        // Our form will require type="multipart/form-data".
180        if (preg_match('/file|image/i', $field)) {
181            $upload_file_capability = true;
182        }
183
184        // Column headers.
185        $headers[$field] = $field_title;
186
187        // Get php code for printing variables.
188        $public_list_page_vars[] = "<\x3fphp echo oTxt(\$" . $module_name_singular . "_list[\$i]['$field']); \x3f>";
189        $public_detail_page_vars[] = "<\x3fphp echo oTxt(\$item['$field']); \x3f>";
190        $set_values_default[] = "'$field' => '$default'";
191    }
192}
193
194// -------------FILES-------------
195
196$skel_files['skel_admin_script'] = file_get_contents($skel_dir . '/admin.php');
197$skel_files['skel_admin_list_template'] = file_get_contents($skel_dir . '/adm_list.ihtml');
198$skel_files['skel_admin_form_template'] = file_get_contents($skel_dir . '/adm_form.ihtml');
199$skel_files['skel_public_script'] = file_get_contents($skel_dir . '/public.php');
200$skel_files['skel_public_list_template'] = file_get_contents($skel_dir . '/public_list.ihtml');
201$skel_files['skel_public_detail_template'] = file_get_contents($skel_dir . '/public.ihtml');
202
203
204// Search-replace variables ----------------------------------
205
206// Admin script file upload replacement routines...
207
208$search['admin_form_tag_init'] = '/%ADMIN_FORM_TAG_INIT%/';
209$replace['admin_form_tag_init'] = '<form method="post" action="<\x3fphp echo \$_SERVER[\'PHP_SELF\']; \x3f>" class="sc-form">';
210$search['admin_upload_include'] = '/%ADMIN_UPLOAD_INCLUDE%/';
211$replace['admin_upload_include'] = '';
212$search['admin_upload_config'] = '/%ADMIN_UPLOAD_CONFIG%/';
213$replace['admin_upload_config'] = '';
214$search['admin_upload_init'] = '/%ADMIN_UPLOAD_INIT%/';
215$replace['admin_upload_init'] = '';
216$search['admin_upload_del'] = '/%ADMIN_UPLOAD_DEL%/';
217$replace['admin_upload_del'] = '';
218$search['admin_upload_insert'] = '/%ADMIN_UPLOAD_INSERT%/';
219$replace['admin_upload_insert'] = '';
220$search['admin_upload_update'] = '/%ADMIN_UPLOAD_UPDATE%/';
221$replace['admin_upload_update'] = '';
222
223if ($upload_file_capability) {
224    // Form arguments
225    $replace['admin_form_tag_init'] = "<form enctype=\"multipart/form-data\" method=\"post\" action=\"<\x3fphp echo oTxt(\$_SERVER['PHP_SELF']); \x3f>\" class=\"sc-form\">\n<input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"__///__\" />";
226
227    // Include statement.
228    $replace['admin_upload_include'] = "require_once 'codebase/lib/Upload.inc.php';\n";
229
230    // Config
231    $replace['admin_upload_config'] = <<<E_O_F
232
233// This module has file upload capability.
234\$upload = new Upload();
235\$upload->setParam(array(
236    'upload_path' => COMMON_BASE . '/html/_db_files/__///__',
237    'dest_file_perms' => 0666,
238    'allow_overwriting' => false,
239    'valid_file_extensions' => array('jpg', 'gif', 'png', 'jpeg'),
240));
241
242E_O_F;
243
244    // Main init.
245    $replace['admin_upload_init'] = <<<E_O_F
246
247// Copy uploaded image name into form data.
248\$_POST['__///__'] = isset(\$_FILES['__///__']) ? \$_FILES['__///__']['name'] : '';
249
250
251E_O_F;
252
253    // Delete.
254    $replace['admin_upload_del'] = <<<E_O_F
255
256    // Delete file.
257    if ('' != \$upload->getFilenameGlob(getFormData('%PRIMARY_KEY%') . '_*')) {
258        \$upload->deleteFile(\$upload->getFilenameGlob(getFormData('%PRIMARY_KEY%') . '_*'));
259    }
260E_O_F;
261
262    // Insert 1.
263    $replace['admin_upload_insert'] = <<<E_O_F
264
265        // Upload files with prepended primary key.
266        \$new_file = \$upload->process('__///__',  \$%PRIMARY_KEY% . '_' . getFormData('__///__'));
267
268        // If file upload errors, redirect to edit operation for the inserted record.
269        if (\$upload->anyErrors() || false === \$new_file) {
270            \$app->dieURL(\$_SERVER['PHP_SELF'] . '?op=edit&%PRIMARY_KEY%=' . \$%PRIMARY_KEY%);
271        }
272E_O_F;
273
274    // Update.
275    $replace['admin_upload_update'] = <<<E_O_F
276
277        // Upload new files.
278        if (getFormData('__///__')) {
279            // Get old file names for deletion.
280            \$old_file = \$upload->getFilenameGlob(getFormData('%PRIMARY_KEY%') . '_*');
281            // Process new file upload with prepended primary key.
282            \$new_file = \$upload->process('__///__',  getFormData('%PRIMARY_KEY%') . '_' . getFormData('__///__'));
283            if (false === \$new_file || \$upload->anyErrors()) {
284                // Upload failed. Reload form. Display errors.
285                \$frm =& editRecordForm(getFormData('%PRIMARY_KEY%'));
286                \$frm = array_merge(\$frm, getFormData());
287                \$nav->add(_("Edit %ITEM_TITLE%"));
288                \$main_template = '%ADMIN_FORM_TEMPLATE%';
289                break;
290            } else {
291                // Upload succeeded. Delete old files.
292                if ('' != \$old_file && \$old_file != \$new_file[0]['name']) {
293                    \$upload->deleteFile(\$old_file);
294                }
295            }
296        }
297E_O_F;
298} // End upload_file_capability.
299
300
301// Simple...
302
303$search['date'] = '/%DATE%/';
304$replace['date'] = date($app->getParam('date_format'));
305
306$search['name_plural'] = '/%NAME_PLURAL%/';
307$replace['name_plural'] = $module_name_plural;
308
309$search['name_singular'] = '/%NAME_SINGULAR%/';
310$replace['name_singular'] = $module_name_singular;
311
312$search['title'] = '/%TITLE%/';
313$replace['title'] = $module_title;
314
315$search['item_title'] = '/%ITEM_TITLE%/';
316$replace['item_title'] = $item_title;
317
318$search['primary_key'] = '/%PRIMARY_KEY%/';
319$replace['primary_key'] = $primary_key;
320
321$search['db_tbl'] = '/%DB_TBL%/';
322$replace['db_tbl'] = $db_tbl;
323
324$search['name_upper'] = '/%NAME_UPPER%/';
325$replace['name_upper'] = $module_name_upper;
326
327$search['admin_script'] = '/%ADMIN_SCRIPT%/';
328$replace['admin_script'] = $admin_script;
329
330$search['admin_list_template'] = '/%ADMIN_LIST_TEMPLATE%/';
331$replace['admin_list_template'] = $admin_list_template;
332
333$search['admin_form_template'] = '/%ADMIN_FORM_TEMPLATE%/';
334$replace['admin_form_template'] = $admin_form_template;
335
336$search['public_script'] = '/%PUBLIC_SCRIPT%/';
337$replace['public_script'] = $public_script;
338
339$search['public_list_template'] = '/%PUBLIC_LIST_TEMPLATE%/';
340$replace['public_list_template'] = $public_list_template;
341
342$search['public_detail_template'] = '/%PUBLIC_DETAIL_TEMPLATE%/';
343$replace['public_detail_template'] = $public_detail_template;
344
345$search['public_detail_page_vars'] = '/%PUBLIC_DETAIL_PAGE_VARS%/';
346$replace['public_detail_page_vars'] = join("\n", $public_detail_page_vars);
347
348$search['public_list_page_vars'] = '/%PUBLIC_LIST_PAGE_VARS%/';
349$replace['public_list_page_vars'] = join("\n", $public_list_page_vars);
350
351$search['set_values_default'] = '/%SET_VALUES_DEFAULT%/';
352$replace['set_values_default'] = join(",\n        ", $set_values_default);
353
354$search['search_fields'] = '/%SEARCH_FIELDS%/';
355$replace['search_fields'] = join(", ", $headers);
356
357
358
359// Complex....
360
361echo "Generating admin form table rows...\n";
362$output = array();
363exec(dirname($_SERVER['argv'][0]) . "/form_template.cli.php " . COMMON_BASE . " $db_tbl", $output, $return_val);
364if ($return_val == 0) {
365    $search['adm_form_table_rows'] = '/%ADM_FORM_TABLE_ROWS%/';
366    $replace['adm_form_table_rows'] = join("\n", $output);
367} else {
368    die(basename($_SERVER['argv'][0]) . " Error: could not execute form_template.cli.php.\n");
369}
370
371echo "Generating admin list table header rows...\n";
372$output = array();
373exec(dirname($_SERVER['argv'][0]) . "/list_template.cli.php " . COMMON_BASE . " $db_tbl headerrows", $output, $return_val);
374if ($return_val == 0) {
375    $search['adm_list_header_rows'] = '/%ADM_LIST_HEADER_ROWS%/';
376    $replace['adm_list_header_rows'] = join("\n", $output);
377} else {
378    die(basename($_SERVER['argv'][0]) . " Error: could not execute list_template.cli.php.\n");
379}
380
381echo "Generating admin list table rows...\n";
382$output = array();
383exec(dirname($_SERVER['argv'][0]) . "/list_template.cli.php " . COMMON_BASE . " $db_tbl listrows", $output, $return_val);
384if ($return_val == 0) {
385    $search['adm_list_rows'] = '/%ADM_LIST_ROWS%/';
386    $replace['adm_list_rows'] = join("\n", $output);
387} else {
388    die(basename($_SERVER['argv'][0]) . " Error: could not execute list_template.cli.php.\n");
389}
390
391echo "Generating sortorder...\n";
392$output = array();
393exec(dirname($_SERVER['argv'][0]) . "/sql.cli.php " . COMMON_BASE . " $db_tbl sortorder", $output, $return_val);
394if ($return_val == 0) {
395    $search['sort_order'] = '/%SORT_ORDER%/';
396    $replace['sort_order'] = join("\n", $output);
397} else {
398    die(basename($_SERVER['argv'][0]) . " Error: could not execute sql.cli.php.\n");
399}
400
401echo "Generating insert data...\n";
402$output = array();
403exec(dirname($_SERVER['argv'][0]) . "/sql.cli.php " . COMMON_BASE . " $db_tbl insert", $output, $return_val);
404if ($return_val == 0) {
405    $search['insert'] = '/%INSERT%/';
406    $replace['insert'] = join("\n", $output);
407} else {
408    die(basename($_SERVER['argv'][0]) . " Error: could not execute sql.cli.php.\n");
409}
410
411echo "Generating update data...\n";
412$output = array();
413exec(dirname($_SERVER['argv'][0]) . "/sql.cli.php " . COMMON_BASE . " $db_tbl update", $output, $return_val);
414if ($return_val == 0) {
415    $search['update'] = '/%UPDATE%/';
416    $replace['update'] = join("\n", $output);
417} else {
418    die(basename($_SERVER['argv'][0]) . " Error: could not execute sql.cli.php.\n");
419}
420
421echo "Generating search data...\n";
422$output = array();
423exec(dirname($_SERVER['argv'][0]) . "/sql.cli.php " . COMMON_BASE . " $db_tbl search", $output, $return_val);
424if ($return_val == 0) {
425    $search['search'] = '/%SEARCH%/';
426    $replace['search'] = join("\n", $output);
427} else {
428    die(basename($_SERVER['argv'][0]) . " Error: could not execute sql.cli.php.\n");
429}
430
431echo "Generating form validation data...\n";
432$output = array();
433exec(dirname($_SERVER['argv'][0]) . "/validation.cli.php " . COMMON_BASE . " $db_tbl", $output, $return_val);
434if ($return_val == 0) {
435    $search['form_validation'] = '/%FORM_VALIDATION%/';
436    $replace['form_validation'] = join("\n", $output);
437} else {
438    die(basename($_SERVER['argv'][0]) . " Error: could not execute validation.cli.php.\n");
439}
440
441/******************************************************************************
442 * PRINT VAR INSTEAD.
443 *****************************************************************************/
444
445if ('var' == $op) {
446    if (isset($_SERVER['argv'][5]) && isset($replace[$_SERVER['argv'][5]])) {
447        echo "\n\n" . $replace[$_SERVER['argv'][5]] . "\n\n";
448    } else if (isset($_SERVER['argv'][5]) && isset($skel_files[$_SERVER['argv'][5]])) {
449        echo "\n\n" . preg_replace($search, $replace, $skel_files[$_SERVER['argv'][5]]) . "\n\n";
450    } else {
451        die(basename($_SERVER['argv'][0]) . " Error: variable " . (isset($_SERVER['argv'][5]) ? $_SERVER['argv'][5] : '') . " not defined. Please choose one of:\n" . join(', ', array_keys(array_merge($replace, $skel_files))) . "\n");
452    }
453    die;
454}
455
456
457/******************************************************************************
458 * WRITE FILES
459 *****************************************************************************/
460
461// (1) Admin script.
462if (file_exists("$admin_dir/$admin_script")) {
463    echo "Admin script already exists: $admin_dir/$admin_script\n";
464} else {
465    echo "Writing admin script: $admin_dir/$admin_script\n";
466    if ('test' != $op) {
467        $fp = fopen("$admin_dir/$admin_script", "w");
468        fwrite($fp, preg_replace($search, $replace, $skel_files['skel_admin_script']));
469        fclose($fp);
470    }
471}
472
473// (2) Admin list template.
474if (file_exists("$admin_tpl_dir/$admin_list_template")) {
475    echo "Admin list template already exists: $admin_tpl_dir/$admin_list_template\n";
476} else {
477    echo "Writing admin list template: $admin_tpl_dir/$admin_list_template\n";
478    if ('test' != $op) {
479        $fp = fopen("$admin_tpl_dir/$admin_list_template", "w");
480        fwrite($fp, preg_replace($search, $replace, $skel_files['skel_admin_list_template']));
481        fclose($fp);
482    }
483}
484
485// (3) Admin form template.
486if (file_exists("$admin_tpl_dir/$admin_form_template")) {
487    echo "Admin form template already exists: $admin_tpl_dir/$admin_form_template\n";
488} else {
489    echo "Writing admin form template: $admin_tpl_dir/$admin_form_template\n";
490    if ('test' != $op) {
491        $fp = fopen("$admin_tpl_dir/$admin_form_template", "w");
492        fwrite($fp, preg_replace($search, $replace, $skel_files['skel_admin_form_template']));
493        fclose($fp);
494    }
495}
496
497// (4) Public script.
498if (file_exists("$public_dir/$public_script")) {
499    echo "Public script already exists: $public_dir/$public_script\n";
500} else {
501    echo "Writing public script: $public_dir/$public_script\n";
502    if ('test' != $op) {
503        $fp = fopen("$public_dir/$public_script", "w");
504        fwrite($fp, preg_replace($search, $replace, $skel_files['skel_public_script']));
505        fclose($fp);
506    }
507}
508
509// (5) Public list template.
510if (file_exists("$public_tpl_dir/$public_list_template")) {
511    echo "Public list template already exists: $public_tpl_dir/$public_list_template\n";
512} else {
513    echo "Writing public list template: $public_tpl_dir/$public_list_template\n";
514    if ('test' != $op) {
515        $fp = fopen("$public_tpl_dir/$public_list_template", "w");
516        fwrite($fp, preg_replace($search, $replace, $skel_files['skel_public_list_template']));
517        fclose($fp);
518    }
519}
520
521// (6) Public detail template.
522if (file_exists("$public_tpl_dir/$public_detail_template")) {
523    echo "Public detail template already exists: $public_tpl_dir/$public_detail_template\n";
524} else {
525    echo "Writing public detail template: $public_tpl_dir/$public_detail_template\n";
526    if ('test' != $op) {
527        $fp = fopen("$public_tpl_dir/$public_detail_template", "w");
528        fwrite($fp, preg_replace($search, $replace, $skel_files['skel_public_detail_template']));
529        fclose($fp);
530    }
531}
532
533echo "Done!\n";
534
535
536/********************************************************************
537* FUNCTIONS
538********************************************************************/
539
540function trashFile($file_path_name)
541{
542    global $user_trash_folder;
543    static $file_prefix;
544
545    if (!isset($file_prefix)) {
546        $file_prefix = time();
547    } else {
548        $file_prefix++;
549    }
550
551    // Make user trash folder.
552    if (!is_dir($user_trash_folder)) {
553        echo "Attempting to create user trash folder: $user_trash_folder/\n";
554        mkdir($user_trash_folder);
555        chmod($user_trash_folder, 0700);
556    }
557    if (!is_dir("$user_trash_folder/") || !is_writable("$user_trash_folder/")) {
558        die("User trash directory not available: $user_trash_folder/\n");
559    }
560
561    // Move file to trash.
562    if (file_exists($file_path_name)) {
563        rename($file_path_name, sprintf('%s/%s_%s', $user_trash_folder, $file_prefix, basename($file_path_name)));
564        printf("Moved to trash: %s -> %s\n", $file_path_name, sprintf('%s/%s_%s', $user_trash_folder, $file_prefix, basename($file_path_name)));
565    } else {
566        printf("File not found: %s\n", $file_path_name);
567    }
568}
569
570?>
Note: See TracBrowser for help on using the repository browser.