return $str;
}
-# Encode for output in html. converts \n to <br />
+# Encode for output in html. Convert newlines to <br />
#
# Example: <p>~foo.html~</p>
function enc_htmlbr($str) {
return encode_options($str, $states_assoc, $use_keys = true);
}
+# display <option>s
+function enc_provinces($str) {
+ $provinces_assoc = array("AB" => "Alberta", "BC" => "British Columbia", "MB" => "Manitoba", "NF" => "Newfoundland", "NB" => "New Brunswick", "NS" => "Nova Scotia", "NT" => "Northwest Territories", "NU" => "Nunavut", "ON" => "Ontario", "PE" => "Prince Edward Island", "QC" => "Quebec", "SK" => "Saskatchewan", "YT" => "Yukon Territory");
+ $ret = '';
+
+ return encode_options($str, $provinces_assoc, $use_keys = true);
+}
+
+
+
+
define('PULLDOWN_ARRAY', 0); define('PULLDOWN_HASH', 1); define('PULLDOWN_2D', 2);
foreach($options as $value => $display) {
$out .= '<option';
- if(in_array($value, $selected, $strict = true)) {
+ if(in_array($value, $selected)) {
$out .= ' selected="selected"';
}
--- /dev/null
+drop table if exists wfpl_sessions;
+create table wfpl_sessions (
+ id int unique auto_increment,
+ session_key varchar(16),
+ length int,
+ expires int);
+
+drop table if exists wfpl_session_data;
+create table wfpl_session_data (
+ id int unique auto_increment,
+ session_id int,
+ name varchar(100),
+ value text);
# }
function file_run($filename) {
- require_once($filename);
- ereg_replace('.*/', '', $filename);
- $func = basename($filename, '.php') . '_main';
- return $func();
+ require_once($filename);
+ $func = basename($filename, '.php') . '_main';
+
+ return $func();
}
?>
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 '';
}
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);
+ if($str == '') {
+ return '0';
+ }
+ return $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) {
# see code/wfpl/metaform/template.html for the html templates for these elements
$GLOBALS['types'] = array(
# type input format sql
+ 'varname' => array('textbox', 'varname', 'varchar(50)'),
'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)'),
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 {
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.
$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);
$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');
$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;
$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');
RewriteEngine on
-RewriteRule ^$ /~form~/run.php
+RewriteRule ^$ /run.php
RewriteRule ^[^/]*\.html$ /~form~/run.php
<form action="~metaform_name~" method="get">
<p>The form name should not contain any capitals or symbols (besides underscore)</p>
- <p>Form name: <input type="text" name="form_name" value="~form_name.attr~" /></p>
+ <p>Form name: <input type="text" name="form_name" value="~form_name.attr~" /> (This is used as the database table name (if any) and the basename of all the files.)</p>
<h3>Features</h3>
<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>
<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>
</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~~-->
</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>
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~-->
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) {
# 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) {<!--~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~-->
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'];
$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
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');
}
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'];
$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();
# along with wfpl; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-# you'll need this file that calles db_connect()
+# you'll need this file that calls db_connect()
if(!isset($GLOBALS['wfpl_db_handle'])) {
if(file_exists('db_connect.php')) {
require_once('db_connect.php');
# and these database tables:
# create table wfpl_sessions (id int unique auto_increment, session_key varchar(16), length int, expires int);
# create table wfpl_session_data (id int unique auto_increment, session_id int, name varchar(100), value text);
+# run this command to install/clear the tables:
+# mysql DATABASE_NAME < code/wfpl/examples/session.sql
+# note: you may need these parameters for mysql: -u USERNAME -p
# GLOSSARY
#
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.
# 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;
}
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;
+}
+
?>
--- /dev/null
+<?php
+
+# Copyright (C) 2007 Jason Woofenden
+#
+# This file is part of wfpl.
+#
+# wfpl is free software; you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation; either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# wfpl is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+# more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with wfpl; if not, write to the Free Software Foundation, Inc., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+# This file contains functions to manipulate/calculate dates/times
+
+function ymd_to_days($year, $month, $day) {
+ return (int)(mktime(12,0,0,$month,$day, $year, 0) / 86400);
+}
+
+function days_to_ymd($days) {
+ return explode('-', date('Y-n-j', $days * 86400 + 43200));
+}
+
+function days_to_weekday_name($days) {
+ $day_names = array('Thursday', 'Friday', 'Saturday', 'Sunday', 'Monday', 'Tuesday', 'Wednesday');
+ return $day_names[$days % 7];
+}
+
+
+#function time_test() {
+# for($i = 0; $i < 41 * 86400; $i += 86399) {
+# echo "seconds: $i";
+# $days = (int)($i / 86400);
+# list($year, $month, $day) = days_to_ymd($days);
+# echo ", days_to_ymd($days): $year-$month-$day";
+# $days = ymd_to_days($year, $month, $day);
+# echo ", ymd_to_days($year, $month, $day): $days\n<br>";
+# }
+#}