JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
fixed pulldowns, metaform suppors zip and decimal, run.php supports straight html...
authorJason Woofenden <jason183@herkamire.com>
Wed, 11 Jul 2007 22:04:33 +0000 (18:04 -0400)
committerJason Woofenden <jason183@herkamire.com>
Wed, 11 Jul 2007 22:04:33 +0000 (18:04 -0400)
encode.php
format.php
metaform.php
metaform/htaccess
metaform/main.html
metaform/preview.html
metaform/template.html
metaform/template.php
run.php
template.php

index 3f4119c..243b21f 100644 (file)
@@ -190,7 +190,7 @@ function encode_options($selected, $options, $keys_from) {
        foreach($options as $value => $display) {
                $out .= '<option';
 
-               if(in_array($value, $selected, $strict = true)) {
+               if(in_array($value, $selected)) {
                        $out .= ' selected="selected"';
                }
 
index c40f55e..e968158 100644 (file)
@@ -33,7 +33,7 @@ function format_options($str, $name) {
                die("Couldn't find options for \"$name\". Be sure to call pulldown().");
        }
 
-       if(!in_array($str, array_keys($GLOBALS[$name . '_options']['options']), $strict = true)) {
+       if(!in_array($str, array_keys($GLOBALS[$name . '_options']['options']))) {
                return '';
        }
 
@@ -45,6 +45,22 @@ function format_int($str) {
        return ereg_replace('^0*([1-9])', '\1', $str);
 }
 
+function format_decimal($str) {
+       $str = ereg_replace('[^0-9.]', '', $str);
+       $pos = strpos($str, '.');
+       if($pos !== false) {
+               $str = str_replace('.', '', $str);
+               if($pos == 0) {
+                       return '0.' . $str;
+               } elseif($pos == strlen($str)) {
+                       return $str;
+               } else {
+                       return substr($str, 0, $pos) . '.' . substr($str, $pos);
+               }
+       }
+       return $str;
+}
+
 # return 0 of there's no digits
 function format_int_0($str) {
        $str = format_int($str);
@@ -55,7 +71,11 @@ function format_int_0($str) {
 }
 
 function format_zip($str) {
-       return ereg_replace('[^0-9]', '', $str);
+       $str = ereg_replace('[^0-9]', '', $str);
+       if(strlen($str) > 5) {
+               return substr($str, 0, 5) . '-' . substr($str, 5);
+       }
+       return $str;
 }
 
 function format_filename($str) {
index a473bbc..e6e4123 100644 (file)
@@ -32,7 +32,9 @@ $GLOBALS['types'] = array(
        'name' =>       array('textbox',     'oneline',    'varchar(200)'),
        'textbox' =>    array('textbox',     'oneline',    'varchar(200)'),
        'int' =>        array('textbox',     'int',        'int'),
+       'decimal' =>    array('textbox',     'decimal',    'decimal(12,12)'),
        'bigint' =>     array('textbox',     'int',        'varchar(100)'), # up to 100 digits, stored as a string
+       'zip' =>        array('textbox',     'zip',        'varchar(20)'),
        'email' =>      array('textbox',     'email',      'varchar(100)'),
        'phone' =>      array('textbox',     'phone',      'varchar(32)'),
        'state' =>      array('states',      'oneline',    'varchar(2)'),
@@ -72,6 +74,8 @@ function metaform() {
                tem_set('opt_email', $GLOBALS['opt_email']);
                $GLOBALS['opt_db'] = format_yesno($_REQUEST['opt_db']);
                tem_set('opt_db', $GLOBALS['opt_db']);
+               $GLOBALS['opt_listing'] = format_yesno($_REQUEST['opt_listing']);
+               tem_set('opt_listing', $GLOBALS['opt_listing']);
                $GLOBALS['opt_http_pass'] = format_yesno($_REQUEST['opt_http_pass']);
                tem_set('opt_http_pass', $GLOBALS['opt_http_pass']);
        } else {
@@ -180,6 +184,19 @@ function view_sql() {
        view_headers();
        echo make_sql();
 }
+
+# always_field is a form field that always submits (unlike say, checkboxes). It's used to detect if the form has submitted or not.
+function find_always_field($fields) {
+       foreach($fields as $field) {
+               list($name, $type, $input, $format, $sql) = $field;
+               if($input != 'submit' && $input != 'checkbox' && $input != 'radio') {
+                       return $name;
+               }
+       }
+
+       return false;
+}
+       
        
 
 # pass false if you want to exclude the <head> and <body> tag etc.
@@ -190,6 +207,7 @@ function make_html($whole_file = true) {
        $tem->load('code/wfpl/metaform/template.html');
        $tem->set('form_name', $GLOBALS['form_name']);
        $fields = get_fields();
+       $tem->set('always_field', find_always_field($fields));
        foreach($fields as $field) {
                list($name, $type, $input, $format, $sql) = $field;
                $tem->set('name', $name);
@@ -216,6 +234,12 @@ function make_html($whole_file = true) {
                $tem->sub('opt_db_1_else');
        }
 
+       if($GLOBALS['opt_listing'] == 'Yes') {
+               $tem->sub('opt_listing_1');
+       } else {
+               $tem->sub('opt_listing_1_else');
+       }
+
        if($GLOBALS['opt_email'] == 'Yes' && $GLOBALS['opt_db'] != 'Yes') {
                $tem->set('name', 'send');
                $tem->set('caption', 'Send');
@@ -252,7 +276,7 @@ function make_php() {
        $fields = get_fields();
        $db_fields = '';
        $php_fields = '';
-       $always_field = false;
+       $always_field = find_always_field($fields);
        $image_included_yet = false;
        foreach($fields as $field) {
                list($name, $type, $input, $format, $sql) = $field;
@@ -283,16 +307,22 @@ function make_php() {
                                $tem->sub('formats');
                        }
                        $tem->sub('tem_sets');
-                       if(!$always_field and $input != 'checkbox' and $input != 'radio') {
-                               $always_field = $name;
-                       }
                }
        }
-       # always_field is a form field that always submits (unlike say, checkboxes). It's used to detect if the form has submitted or not.
+
        $tem->set('always_field', $always_field);
        $tem->set('db_fields', $db_fields);
        $tem->set('php_fields', $php_fields);
        $tem->set('metaform_url', edit_url());
+       if($GLOBALS['opt_listing'] == 'Yes') {
+               $tem->sub('opt_listing_1');
+               $tem->sub('opt_listing_2');
+               $tem->sub('opt_listing_3');
+               $tem->sub('opt_listing_4');
+       } else {
+               $tem->sub('opt_listing_3_else');
+               $tem->sub('opt_listing_4_else');
+       }
        if($GLOBALS['opt_db'] == 'Yes') {
                $tem->sub('opt_db_1');
                $tem->sub('opt_db_2');
index eb2ad6d..362282a 100644 (file)
@@ -1,3 +1,3 @@
 RewriteEngine  on
-RewriteRule    ^$  /~form~/run.php
+RewriteRule    ^$  /run.php
 RewriteRule    ^[^/]*\.html$  /~form~/run.php
index 5d0bc2e..fd70d42 100644 (file)
@@ -19,6 +19,8 @@
 
     <p><input type="checkbox" name="opt_db~opt_db.checked~" value="Yes" /> Save form results to a database.</p>
 
+    <p><input type="checkbox" name="opt_listing~opt_listing.checked~" value="Yes" /> Provide a "Listing" page.</p>
+
     <p><input type="checkbox" name="opt_http_pass~opt_http_pass.checked~" value="Yes" /> Password protect this form (with HTTP authentication).</p>
 
        <p>Below, specify the fields you'd like in your form, one field per line. After each field name, put at least one space, then the field type. The following field types are available: ~available_types.html~.</p>
index fd8f193..2731e23 100644 (file)
   <h1>This grey thing is a preview. It will NOT work. Don't click button(s) in it</h1>
 ~preview~
   </div>
-    <p><form action="~form_name~.tgz" method="get"><input type="hidden" name="form_name" value="~form_name.attr~" /><input type="hidden" name="opt_email" value="~opt_email.attr~" /><input type="hidden" name="opt_db" value="~opt_db.attr~" /><input type="hidden" name="opt_http_pass" value="~opt_http_pass.attr~" /><input type="hidden" name="fields" value="~fields.attr~" /><input type="submit" name="download_tar" value="Download tar ball" /></form></p>
+    <p><form action="~form_name~.tgz" method="get"><input type="hidden" name="form_name" value="~form_name.attr~" /><input type="hidden" name="opt_email" value="~opt_email.attr~" /><input type="hidden" name="opt_db" value="~opt_db.attr~" /><input type="hidden" name="opt_listing" value="~opt_listing.attr~" /><input type="hidden" name="opt_http_pass" value="~opt_http_pass.attr~" /><input type="hidden" name="fields" value="~fields.attr~" /><input type="submit" name="download_tar" value="Download tar ball" /></form></p>
 
   <form action="~metaform_name~" method="get">
-       <p><input type="hidden" name="form_name" value="~form_name.attr~" /><input type="hidden" name="opt_email" value="~opt_email.attr~" /><input type="hidden" name="opt_db" value="~opt_db.attr~" /><input type="hidden" name="opt_http_pass" value="~opt_http_pass.attr~" /><input type="hidden" name="fields" value="~fields.attr~" /><input type="submit" name="edit" value="Back to editing" /></p>
+       <p><input type="hidden" name="form_name" value="~form_name.attr~" /><input type="hidden" name="opt_email" value="~opt_email.attr~" /><input type="hidden" name="opt_db" value="~opt_db.attr~" /><input type="hidden" name="opt_listing" value="~opt_listing.attr~" /><input type="hidden" name="opt_http_pass" value="~opt_http_pass.attr~" /><input type="hidden" name="fields" value="~fields.attr~" /><input type="submit" name="edit" value="Back to editing" /></p>
 
     <p><input type="submit" name="view_sql" value="View SQL" /></p>
 
index 22656fd..a7d84d5 100644 (file)
@@ -19,9 +19,6 @@
 </head>
 
 <body>
-<!--~~form start~~--><!--~form start~-->
-  <h2><!--~opt_db_1 start~--><!--~~new_msg start~~-->Add a new entry<!--~~end~~--><!--~~edit_msg start~~-->Edit entry "~~name.html~~"<!--~~end~~--><!--~end~--><!--~opt_db_1_else start~-->~form_name~ entry form<!--~end~--></h2>
-
   <!--~~message_container start~~-->
        <div style="border: 2px solid red; background: #fbb; padding: 5px; margin: 20px 0px">
        <!--~~message_box start~~-->
@@ -33,6 +30,9 @@
        </div>
   <!--~~end~~-->
 
+<!--~~form start~~--><!--~form start~-->
+  <h2><!--~opt_db_1 start~--><!--~~new_msg start~~-->Add a new entry<!--~~end~~--><!--~~edit_msg start~~-->Edit entry "~~~always_field~.html~~"<!--~~end~~--><!--~end~--><!--~opt_db_1_else start~-->~form_name~ entry form<!--~end~--></h2>
+
   <form action="~form_name~.html~enctype_attr~" method="post"><!--~opt_db_2 start~--><!--~~editing start~~--><input type="hidden" name="~form_name~_edit_id" value="~~~form_name~_edit_id.attr~~" /><!--~~end~~--><!--~end~--><!--~uploads start~--><input type="hidden" name="MAX_FILE_SIZE" value="~~upload_max_filesize~~" /><!--~end~-->
     <table cellspacing="0" cellpadding="4" border="0" summary=""><!--~row start~-->
 
     </table>
   </form>
 <!--~end~--><!--~~end~~-->
+<!--~opt_listing_1 start~--><!--~~listings start~~-->
+  <h2>~form_name~ Listing</h2>
+
+  <table cellspacing="0" cellpadding="4" border="1" summary=""><!--~~listing_row start~~-->
+  <tr><td class="listing"><a href="~form_name~.html?~form_name~_edit_id=~~id~~">~~~always_field~.html~~</a></td><td><a href="~form_name~.html?~form_name~_delete_id=~~id~~" onclick="return confirm('Permanently delete?')">[delete this record]</a></td></tr><!--~~end~~-->
+
+  </table>
+
+  <p><a href="~form_name~.html?~form_name~_new=1">[Add a new record]</a></p>
+<!--~~end~~--><!--~end~--><!--~opt_listing_1_else start~-->
 <!--~~thankyou start~~-->
   <p>Thank you for taking the time to fill out this form.</p>
-<!--~~end~~-->
+<!--~~end~~--><!--~end~-->
 </body>
 </html>
index 890c49b..48fb37f 100644 (file)
@@ -38,7 +38,7 @@ require_once('code/wfpl/template.php');
 require_once('code/wfpl/format.php');
 require_once('code/wfpl/messages.php');
 require_once('code/wfpl/email.php');<!--~opt_db_2 start~-->
-require_once('code/wfpl/db.php');<!--~end~--><!--~image_include start~-->
+require_once('db_connect.php');<!--~end~--><!--~image_include start~-->
 require_once('code/wfpl/upload.php');<!--~end~-->
 
 function ~form_name~_get_fields() {<!--~formats start~-->
@@ -57,7 +57,27 @@ function ~form_name~_get_fields() {<!--~formats start~-->
 function ~form_name~_tem_sets(~php_fields~) {<!--~tem_sets start~-->
        tem_set('~name~', $~name~);<!--~end~-->
 }
+<!--~opt_listing_2 start~-->
+# You may pass a "where clause" for the db query.
+function ~form_name~_display_listing($where = 'order by ~always_field~ limit 100') {
+       $rows = db_get_rows('~form_name~', 'id,~always_field~', $where);
+       if($rows == false || count($rows) == 0) {
+               return false;
+       }
 
+       foreach($rows as $row) {
+               list($id, $~always_field~) = $row;
+               tem_set('id', $id);
+               if($~always_field~ == '') {
+                       $~always_field~ = '--';
+               }
+               tem_set('~always_field~', $~always_field~);
+               tem_sub('listing_row');
+       }
+       tem_sub('listings');
+       return true;
+}
+<!--~end~-->
 function ~form_name~() {<!--~opt_http_pass_2 start~-->
        # To remove password protection, just delete this block:
        if (!isset($_SERVER['PHP_AUTH_USER']) || $_SERVER['PHP_AUTH_USER'] != AUTH_USER || $_SERVER['PHP_AUTH_PW'] != AUTH_PASS) {
@@ -75,20 +95,30 @@ function ~form_name~() {<!--~opt_http_pass_2 start~-->
                # add hidden field for database id of row we're editing
                tem_set('~form_name~_edit_id', $edit_id);
                tem_sub('editing');
-               tem_sub('edit_msg');
        }
 
        $delete_id = format_int($_REQUEST['~form_name~_delete_id']);
        unset($_REQUEST['~form_name~_delete_id']);
        if($delete_id) {
                db_delete('~form_name~', 'where id=%i', $delete_id);
-               message('Entry deleted.');
+               message('Entry deleted.');<!--~opt_listing_3 start~-->
+
+               if(~form_name~_display_listing()) {
+                       return;
+               }
+               unset($delete_id);<!--~end~--><!--~opt_listing_3_else start~-->
 
                # FIXME: what to do after delete?
-               return;
+               return;<!--~end~-->
        }
 
-       if(!$edit_id && !$delet_id) {
+       if(!$edit_id && !$delet_id) {<!--~opt_listing_1 start~-->
+               if(!isset($_REQUEST['~form_name~_new']) && !isset($_REQUEST['~always_field~'])) {
+                       if(~form_name~_display_listing()) {
+                               return;
+                       }
+               }
+               <!--~end~-->
                tem_sub('new_msg');
        }<!--~end~-->
 
@@ -96,20 +126,17 @@ function ~form_name~() {<!--~opt_http_pass_2 start~-->
                list(~php_fields~) = ~form_name~_get_fields();
 
                if("you're happy with the POSTed values") {<!--~opt_db_4 start~-->
-                       if(file_exists($db_connector = 'db_connect.php') || file_exists($db_connector = 'code/db_connect.php')) {
-                               require_once($db_connector);
-                               if($edit_id) {<!--~image_db start~-->
-                                       # uploading nothing means leaving it as is.
-                                       if(!$~name~ && $delete_~name~ != 'Yes') {
-                                               $~name~ = db_get_value('~form_name~', '~name~', 'where id=%i', $edit_id);
-                                       }
-                                       <!--~end~-->
-                                       db_update('~form_name~', ~form_name.upper~_DB_FIELDS, ~php_fields~, 'where id=%i', $edit_id);
-                                       message('Entry updated.');
-                               } else {
-                                       db_insert('~form_name~', ~form_name.upper~_DB_FIELDS, ~php_fields~);
-                                       message('Entry saved.');
+                       if($edit_id) {<!--~image_db start~-->
+                               # uploading nothing means leaving it as is.
+                               if(!$~name~ && $delete_~name~ != 'Yes') {
+                                       $~name~ = db_get_value('~form_name~', '~name~', 'where id=%i', $edit_id);
                                }
+                               <!--~end~-->
+                               db_update('~form_name~', ~form_name.upper~_DB_FIELDS, ~php_fields~, 'where id=%i', $edit_id);
+                               message('Entry updated.');
+                       } else {
+                               db_insert('~form_name~', ~form_name.upper~_DB_FIELDS, ~php_fields~);
+                               message('Entry saved.');
                        }<!--~end~--><!--~opt_email_2 start~-->
                        if($GLOBALS['~form_name~_form_recipient'] != "fixme@example.com") {
                                $to = $GLOBALS['~form_name~_form_recipient'];
@@ -130,11 +157,10 @@ function ~form_name~() {<!--~opt_http_pass_2 start~-->
                                        $error = true;
                                }
                        }<!--~end~-->
-                       if($error !== true) {
-                               tem_load('~form_name~.html');
-                               tem_sub('thankyou');
-                               tem_output();
-                               exit();
+                       if($error !== true) {<!--~opt_listing_4 start~-->
+                               ~form_name~_display_listing();<!--~end~--><!--~opt_listing_4_else start~-->
+                               tem_sub('thankyou');<!--~end~-->
+                               return;
                        }
                }
                # otherwise, we display the form again. ~form_name~_get_fields() has
@@ -152,7 +178,11 @@ function ~form_name~() {<!--~opt_http_pass_2 start~-->
 
        tem_set('upload_max_filesize', upload_max_filesize());<!--~end~-->
 
-       display_messages();
+       # this has to be later in the file because it requres that ~always_field~ be set already
+       if($edit_id) {
+               tem_sub('edit_msg');
+       }
+
        tem_sub('form');
 }
 
diff --git a/run.php b/run.php
index c5ae240..f77e7d0 100644 (file)
--- a/run.php
+++ b/run.php
@@ -59,6 +59,10 @@ require_once('code/wfpl/file_run.php');
 require_once('code/wfpl/http.php');
 require_once('code/wfpl/template.php');
 
+if(file_exists('code/config.php')) {
+       file_run('code/config.php');
+}
+
 function run_php($basename = false) {
        if(!$basename) {
                $basename = $_SERVER['REDIRECT_URL'];
@@ -72,36 +76,51 @@ function run_php($basename = false) {
        $html_file = "$basename.html";
        $php_file = "$basename.php";
 
-       if(!file_exists($php_file)) {
-               if(file_exists($html_file)) {
-                       readfile($html_file);
+       $html_exists = file_exists($html_file);
+       $php_exists = file_exists($php_file);
+
+       if(!$php_exists && !$html_exists) {
+               header('HTTP/1.0 404 File Not Found');
+               if(file_exists('404.php') || file_exists('404.html')) {
+                       run_php('404');
                } else {
-                       header('HTTP/1.0 404 File Not Found');
-                       if(file_exists('404.php') || file_exists('404.html')) {
-                               run_php('404');
-                       } else {
-                               echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html><head><title>404</title></head><body><h1>404 File Not Found</h1></body></html>';
-                       }
+                       echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html><head><title>404</title></head><body><h1>404 File Not Found</h1></body></html>';
                }
+       }
+
+       # If there's no template.html we don't want to parse $html_file.
+       if($html_exists && !$php_exists && !file_exists('template.html')) {
+               readfile($html_file);
                exit();
        }
 
-       if(file_exists($html_file)) {
-               $GLOBALS['wfpl_template'] = new tem();
-               tem_load($html_file);
+       if($html_exists) {
+               tem_load_new($html_file);
        }
 
-       # files can return a basename or URL of a page to be run/displayed
-       $other = file_run($php_file);
-       if($other) {
-               if(strpos($other, ':')) {
-                       redirect($other);
-                       exit();
+       if($php_exists) {
+               # files can return a basename or URL of a page to be run/displayed
+               $other = file_run($php_file);
+               if($other) {
+                       if(strpos($other, ':')) {
+                               redirect($other);
+                               exit();
+                       }
+                       if(substr($other, 0, 2) == './') {
+                               redirect(ereg_replace('/[^/]*$', substr($other, 1), this_url()));
+                               exit();
+                       }
+                       run_php($other);
+                       return;
+               }
+       } else {
+               $sub_names = tem_top_sub_names();
+               foreach($sub_names as $sub_name) {
+                       tem_sub($sub_name);
                }
-               run_php($other);
-               return;
        }
 
+       # Check for $GLOBALS['wfpl_template'] because it might have been set (or unset) by the php script.
        if($GLOBALS['wfpl_template']) {
                if(file_exists('template.html')) {
                        $tem = new tem();
index 2425275..822738b 100644 (file)
@@ -177,6 +177,15 @@ class tem {
                print($this->run($templ));
        }
 
+       # return the names of the top level subs, or an empty array
+       function top_sub_names() {
+               if(isset($this->sub_subs['top_level_subs'])) {
+                       return $this->sub_subs['top_level_subs'];
+               } else {
+                       return array();
+               }
+       }
+
        # return the contents of the top-level sub-templates
        #
        # this does not run the sub-templates, so if you've not called tem_sub() on them, they will be blank.
@@ -186,10 +195,9 @@ class tem {
        #     values: contents of said sub-template.
        function top_subs() {
                $ret = array();
-               if(isset($this->sub_subs['top_level_subs'])) {
-                       foreach($this->sub_subs['top_level_subs'] as $name) {
-                               $ret[$name] = $this->get($name);
-                       }
+               $names = $this->top_sub_names();
+               foreach($names as $name) {
+                       $ret[$name] = $this->get($name);
                }
                return $ret;
        }
@@ -264,9 +272,22 @@ function template_run($template, &$keyval) {
        return preg_replace_callback(array('|<!--~([^~]*)~-->|', '|~([^~]*)~|', '|<span class="template">([^<]*)</span>|', '|<p class="template">([^<]*)</p>|'), 'template_filler', $template);
 }
 
+function tem_top_sub_names() {
+       tem_init();
+       return $GLOBALS['wfpl_template']->top_sub_names();
+}
+
 function tem_top_subs() {
        tem_init();
        return $GLOBALS['wfpl_template']->top_subs();
 }
 
+# replaces currently set template, and returns the old.
+function tem_load_new($file) {
+       $old = $GLOBALS['wfpl_template'];
+       $GLOBALS['wfpl_template'] = new tem();
+       $GLOBALS['wfpl_template']->load($file);
+       return $old;
+}
+
 ?>