Created
April 18, 2011 10:06
-
-
Save Zegnat/925103 to your computer and use it in GitHub Desktop.
Form builder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
# ### ### ### ### ### ### ### ### ### ### | |
# HEAD | |
header('Content-Type: text/html; charset=utf-8'); | |
error_reporting(E_ALL); | |
ini_set('display_errors', '1'); | |
ini_set('memory_limit', '12M'); | |
function pre_var_dump() { | |
$args = func_get_args(); | |
echo '<pre>',call_user_func_array('var_dump',$args),'</pre>'; | |
} | |
# ### ### ### ### ### ### ### ### ### ### | |
# SETTINGS | |
if (!defined('MAXDEPTH')) define('MAXDEPTH',ini_get('max_input_nesting_level')-2); | |
if (!defined('DBHOST')) define('DBHOST','localhost:8889'); | |
if (!defined('DBNAME')) define('DBNAME','school'); | |
if (!defined('DBUSER')) define('DBUSER','root'); | |
if (!defined('DBPASS')) define('DBPASS','root'); | |
# ### ### ### ### ### ### ### ### ### ### | |
# DATABASE CONNECT | |
mysql_connect(DBHOST,DBUSER,DBPASS) or die(mysql_error()); | |
mysql_select_db(DBNAME) or die(mysql_error()); | |
# ### ### ### ### ### ### ### ### ### ### | |
# START | |
# Create one central variable: | |
$form = isset($_POST['form'])?$_POST['form']:array(); | |
unset($_POST['form']); | |
# Are there any actions with parameters? | |
if (isset($_POST['action'])&&count($action=explode(' ',$_POST['action']))>1) { | |
if ($action[0]=='add') { | |
if (in_array($action[1],array('text','textarea','checkbox'))) $form[] = array('type'=>$action[1],'name'=>''); | |
} | |
else if ($action[0]=='repeat') { | |
$walkway = explode(',',$action[1]); | |
if (count($walkway)<MAXDEPTH) { | |
$repeater = &$form; | |
foreach ($walkway as $step) $repeater = &$repeater[$step]; | |
$repeater = array('type'=>'repeat','name'=>'','min'=>0,'max'=>-1,'value'=>array($repeater)); | |
} | |
} | |
else if ($action[0]=='move') { | |
$walkway = explode(',',$action[2]); | |
if ($action[1]=='down') $walkway[(count($walkway)-1)]++; | |
if (end($walkway)>0) { | |
$lower = &$form; | |
foreach ($walkway as $step) $lower = &$lower[$step]; | |
$move = $lower; | |
if (!!$move) { | |
$upper = &$form; | |
$walkway[(count($walkway)-1)]--; | |
foreach ($walkway as $step) $upper = &$upper[$step]; | |
$lower = $upper; | |
$upper = $move; | |
} | |
} | |
} | |
else if ($action[0]=='merge') { | |
$walkway = explode(',',$action[2]); | |
$merge = &$form; | |
foreach ($walkway as $step) $merge = &$merge[$step]; | |
$repeater = &$form; | |
for ($i=0,$l=count($walkway);$i<($l-1);$i++) $repeater = &$repeater[$walkway[$i]]; | |
$repeater[end($walkway)-1]['value'][] = $merge; | |
$action = array('delete',$action[2]); | |
} | |
else if ($action[0]=='out') { | |
$walkway = explode(',',$action[2]); | |
$jumper = &$form; | |
foreach ($walkway as $step) $jumper = &$jumper[$step]; | |
$parent = &$form; | |
for ($i=0,$l=count($walkway);$i<($l-3);$i++) $parent = &$parent[$walkway[$i]]; | |
array_splice($parent,$walkway[count($walkway)-3]+1,0,array($jumper)); | |
$action = array('delete',$action[2]); | |
} | |
# Deleter, no else, can be triggered by above IFs. | |
if ($action[0]=='delete') { | |
do { | |
$element = &$form; | |
for ($i=0,$arr=explode(',',$action[1]),$l=count($arr);$i<($l-1);$i++) $element = &$element[$arr[$i]]; | |
array_splice($element,end($arr),1); | |
$action[1] = false; | |
if (in_array('value',$arr)) { | |
$element = &$form; | |
for ($i=0,$arr=array_slice($arr,0,count($arr)-2),$l=count($arr);$i<$l;$i++) $element = &$element[$arr[$i]]; | |
if (count($element['value'])<1) $action[1] = implode(',',$arr); | |
} | |
} while ($action[1]!==false); | |
} | |
} | |
# Are there any actions without parameters? | |
else if (isset($_POST['action'])&&strlen($action=$_POST['action'])>0) { | |
if ($action=='cancel'||$action=='load') { | |
$table = $action=='load'?intval($_POST['formselect']):(strlen($id=$_POST['formid'])>0&&is_int(intval($id))?intval($id):false); | |
if ($action=='load'&&!$table) { | |
pre_var_dump('Nothing to load.'); | |
} else if ($table) { | |
$info = mysql_query("SELECT * FROM db_form_settings WHERE id=".$table) or die(mysql_error()); | |
$arr = mysql_fetch_array($info); | |
$_POST['formid'] = $arr['id']; | |
$_POST['formname'] = $arr['name']; | |
$form = loadList($table); | |
} else { | |
$action = 'new'; | |
} | |
} | |
else if ($action=='drop'&&$id=intval($_POST['formselect'])) { | |
$array = array(); | |
$tables = mysql_query("SELECT table_name FROM information_schema.TABLES WHERE TABLE_SCHEMA = '".DBNAME."' AND TABLE_NAME LIKE 'db_form_".$id."%'") or die(mysql_error()); | |
while($row = mysql_fetch_assoc($tables)) $array[] = $row['table_name']; | |
mysql_query("DROP TABLE ".implode(',',$array)) or die(mysql_error()); | |
mysql_query("DELETE FROM db_form_settings WHERE id='".$id."'") or die(mysql_error()); | |
if ($id==$_POST['formid']) $action = 'new'; | |
} | |
else if ($action=='save') { | |
$error = array(); | |
$QUERY = array(); | |
if (strlen($name=trim($_POST['formname']))==0) $error[] = 'You must enter a name for your form.'; | |
if (count($form)==0) $error[] = 'You must build a form for it to be saved.'; | |
if (isset($_POST['formid'])&&strlen($_POST['formid'])>0&&is_int(intval($_POST['formid']))) { | |
$QUERY[] = "UPDATE db_form_settings SET name='".mysql_real_escape_string($_POST['formname'])."' WHERE id='".intval($_POST['formid'])."'"; | |
} else { | |
$QUERY[] = "INSERT INTO db_form_settings(name) VALUE('".mysql_real_escape_string($_POST['formname'])."')"; | |
# Don’t forget to set the new formid! | |
$get = mysql_query("SHOW TABLE STATUS LIKE 'db_form_settings'") or die(mysql_error()); | |
$arr = mysql_fetch_array($get); | |
$_POST['formid'] = $arr['Auto_increment']; | |
mysql_free_result($get); | |
} | |
$mid = $_POST['formid']; | |
$ids = array(array($mid,$form)); | |
$subs = 0; | |
do { | |
list($id, $items) = array_shift($ids); | |
$subs++; | |
$table = 'db_form_'.$id; | |
$QUERY[] = "DROP TABLE IF EXISTS ".$table; | |
$QUERY[] = "CREATE TABLE ".$table."(id INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(id), type TINYTEXT NOT NULL, name TEXT NOT NULL, required INT, min INT, max INT, subform TINYTEXT)"; | |
foreach ($items as $i=>$item) { | |
if (strlen(trim($item['name']))==0&&!in_array('You must enter a name for every form item.',$error)) $error[] = 'You must enter a name for every form item.'; | |
if ($i==0) $QUERY[] = "INSERT INTO ".$table." VALUES"; | |
else $QUERY[count($QUERY)-1] .= ", "; | |
$QUERY[count($QUERY)-1] .= "(NULL,'".mysql_real_escape_string($item['type'])."','".mysql_real_escape_string($item['name'])."','".(isset($item['required'])?1:0)."',"; | |
if ($item['type']=='repeat') { | |
$nid = $mid.'_'.$subs; | |
$QUERY[count($QUERY)-1] .= "'".(($mi=$item['min'])<=0||!is_int(intval($mi))?'0':intval($mi))."','".(($ma=$item['max'])<=0||$ma<$mi||!is_int(intval($ma))?0:intval($ma))."','".$nid."')"; | |
if ($mi==1&&$ma==1) $error[] = 'You should not use a repeater when you don’t allow it to be repeated.'; | |
$ids[] = array($nid,$item['value']); | |
} else $QUERY[count($QUERY)-1] .= "NULL,NULL,NULL)"; | |
} | |
} while(count($ids)); | |
if (!count($error)) { | |
foreach ($QUERY as $statement) mysql_query($statement) or die(mysql_error()); | |
} | |
} | |
# Empty form, no else, can be triggered by above IFs. | |
if ($action=='new') { | |
$_POST['formid'] = ''; | |
$_POST['formname'] = ''; | |
$form = array(); | |
} | |
} | |
# ### ### ### ### ### ### ### ### ### ### | |
# DEBUG | |
//echo '<pre><h3>Action</h3></pre>',pre_var_dump(isset($action)?$action:null),'<pre><h3>$_POST</h3></pre>',pre_var_dump($_POST),'<pre><h3>$form</h3></pre>',pre_var_dump($form); | |
# ### ### ### ### ### ### ### ### ### ### | |
# FUNCTIONS | |
# These are used mostly for recursion. | |
function array_add($array,$value) { $array[] = $value; return $array; }; | |
function loadList($id) { | |
$form = array(); | |
$table = mysql_query("SELECT * FROM db_form_".$id) or die(mysql_error()); | |
while($item = mysql_fetch_array($table,MYSQL_ASSOC)) { | |
if ($item['type']=='repeat') $form[] = array_merge(array_slice($item,1,5),array('value'=>loadList($item['subform']))); | |
else $form[] = array_slice($item,1,3); | |
} | |
return $form; | |
} | |
function drawList($base,$depth=array()) { | |
$deep = ''; | |
$id = ''; | |
$prev = false; | |
foreach ($depth as $i) { | |
$deep .= '['.$i.']'; | |
$id .= $i.','; | |
} | |
foreach ($base as $i=>$element) { | |
if (isset($element['type'])&&in_array($type=$element['type'],array('text','textarea','checkbox','repeat'))) { | |
echo '<li class="'.$type.'">'; | |
echo '<input type="hidden" name="form'.$deep.'['.$i.'][type]" value="'.$type.'"><span></span>'; | |
echo '<input name="form'.$deep.'['.$i.'][name]" value="'.$element['name'].'">'; | |
echo ' | '; | |
if ($type!='repeat') { | |
echo '<label for="required'.$id.$i.'"><input type="checkbox" name="form'.$deep.'['.$i.'][required]" id="required'.$id.$i.'"'.(isset($element['required'])&&$element['required']?' checked':'').'> Required</label>'; | |
} else { | |
echo '<label for="min'.$id.$i.'">Min: <input name="form'.$deep.'['.$i.'][min]" id="min'.$id.$i.'" value="'.(($mi=$element['min'])<=0||!is_int(intval($mi))?'0':intval($mi)).'"></label>'; | |
echo '<label for="max'.$id.$i.'">Max: <input name="form'.$deep.'['.$i.'][max]" id="max'.$id.$i.'" value="'.(($ma=$element['max'])<=0||$ma<$mi||!is_int(intval($ma))?'∞':intval($ma)).'"></label>'; | |
} | |
echo ' | '; | |
echo '<button type="submit" name="action" value="move up '.$id.$i.'"'.($i==0?' disabled':'').' title="Move up">Up</button>'; | |
echo '<button type="submit" name="action" value="move down '.$id.$i.'"'.($i==count($base)-1?' disabled':'').' title="Move down">Down</button>'; | |
if ($type!='repeat') { | |
echo ' | '; | |
echo '<button type="submit" name="action" value="repeat '.$id.$i.'"'.(count($depth)==MAXDEPTH||$type=='repeat'?' disabled':'').' title="Create repeating block">Repeat</button>'; | |
echo '<button type="submit" name="action" value="merge up '.$id.$i.'"'.(!$prev||$type=='repeat'?' disabled':'').' title="Merge with the above repeating block">Merge up</button>'; | |
echo '<button type="submit" name="action" value="out down '.$id.$i.'"'.(!$depth?' disabled':'').' title="Jump out of this repeating block">Jump down</button>'; | |
} | |
echo ' | <button type="submit" name="action" value="delete '.$id.$i.'" title="Delete this element">Delete</button>'; | |
if ($prev=($type=='repeat')) { | |
echo '<ul>'; | |
drawList($element['value'],array_add(array_add($depth,$i),'value')); | |
echo '</ul>'; | |
} | |
echo '</li>'; | |
} | |
} | |
} | |
?> | |
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<title>Form builder.</title> | |
<style> | |
html{text-align:center;} | |
body{max-width:960px;margin:0 auto;text-align:left;font-family:sans-serif,sansserif;} | |
*{font-size:100%;} | |
#form>button{padding:.5em 2em;margin:0 .5em 0 0;} | |
#formsettings,#form,#error{border:2px solid #FFDDDD;padding:.5em 1em;margin:2em 0;} | |
#error{border-color:#CD2A2F;padding:0 1em;} | |
#error ul{list-style:none;margin:0;padding:0;} | |
#error li{background:transparent url(img/delete.png) left center no-repeat;padding-left:26px;margin:.5em 0;} | |
#formsettings label{margin:0 1em 0 0;} | |
#form ul{margin:2em 0;padding:0;list-style:none;} | |
#form li{margin:5px 0;} | |
#form li.repeat{background-color:rgba(126,140,66,.1);margin-left:-10px;padding:.2em 0 .2em 10px;border-top:1px solid rgba(106,120,46,.3);} | |
#form ul ul{padding-left:10px;margin:0;} | |
#form button,#form label{cursor:pointer;cursor:hand;} | |
select{margin:0 .5em;padding: 0 2em 0 .5em;} | |
button[value=new]{margin:0 .5em !important;} | |
li label{padding:0 .5em;} | |
li input[type=checkbox]{margin:0 .5em 0 0;} | |
li button[name=action]{width:32px;height:32px;text-indent:40em;overflow:hidden;border:0;background:transparent center center no-repeat;color:rgba(255,255,255,0);} | |
li button[value*=" up "]{background-image:url(img/up.png);} | |
li button[value*=" down "]{background-image:url(img/down.png);} | |
li button[value^="repeat "]{background-image:url(img/repeat.png);} | |
li button[value^="delete "]{background-image:url(img/delete.png);} | |
li button[value^="merge up "]{background-image:url(img/mergeup.png);} | |
li button[value^="out down "]{background-image:url(img/jumpdown.png);} | |
button[disabled]{opacity:.3;} | |
input[name$="[type]"]+span{width:16px;height:16px;border:0;background:transparent center center no-repeat;display:inline-block;margin: 0 .5em -3px 0;} | |
input[name$="[type]"][value="text"]+span{background-image:url(img/text.png);} | |
input[name$="[type]"][value="textarea"]+span{background-image:url(img/textarea.png);} | |
input[name$="[type]"][value="checkbox"]+span{background-image:url(img/checkbox.png);} | |
input[name$="[type]"][value="repeat"]+span{background-image:url(img/repeat.png);} | |
input[id^=min],input[id^=max]{width:3em;} | |
</style> | |
<form method="post" accept-charset="utf-8"> | |
<?php if (isset($error)&&count($error)) { ?><div id="error"> | |
<ul><?php foreach ($error as $msg) { echo '<li>'.$msg.'</li>'; } ?></ul> | |
</div><?php } ?> | |
<div id="formsettings"> | |
<input type="hidden" name="formid" value="<?php echo isset($_POST['formid'])?$_POST['formid']:''; ?>"> | |
<label for="formname">Form name</label> <input name="formname" id="formname" value="<?php echo isset($_POST['formname'])?trim($_POST['formname']):''; ?>"><br> | |
</div> | |
<div id="form"> | |
<button type="submit" name="action" value="add text">Text</button> | |
<button type="submit" name="action" value="add textarea">Textarea</button> | |
<button type="submit" name="action" value="add checkbox">Checkbox</button> | |
<ul> | |
<?php drawList($form); ?> | |
</ul> | |
<button type="submit" name="action" value="cancel">Cancel</button> | |
<button type="submit" name="action" value="save">Save</button> | |
| | |
<button type="submit" name="action" value="new">New</button> | |
| | |
<select name="formselect"> | |
<?php | |
$forms = mysql_query("SELECT * FROM db_form_settings") or die(mysql_error()); | |
while($form = mysql_fetch_array($forms)) { | |
echo '<option value="'.$form[0].'"'.(isset($_POST['formid'])&&$_POST['formid']==$form[0]?' selected':'').'>'.$form[1].'</option>'; | |
} | |
?> | |
</select> | |
<button type="submit" name="action" value="load">Load</button> | |
<button type="submit" name="action" value="drop">Delete</button> | |
</div> | |
</form> | |
<?php | |
# ### ### ### ### ### ### ### ### ### ### | |
# DEBUG | |
//echo '<pre><h3>Action</h3></pre>',pre_var_dump(isset($action)?$action:null),'<pre><h3>$_POST</h3></pre>',pre_var_dump($_POST),'<pre><h3>$form</h3></pre>',pre_var_dump($form); | |
# ### ### ### ### ### ### ### ### ### ### | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment