diff options
author | Eudyptula <eitan@mosenkis.net> | 2009-07-15 16:16:23 -0400 |
---|---|---|
committer | Eudyptula <eitan@mosenkis.net> | 2009-07-15 16:16:23 -0400 |
commit | 709c490155509f4c18f79f4d0632ab22ad32cc1a (patch) | |
tree | 5836ab01b99be05a05a254eca2e50de51237ae5d | |
parent | Added 'Show checked' link for package adder, fixed package selector verificat... (diff) | |
download | ingenue-709c490155509f4c18f79f4d0632ab22ad32cc1a.tar.gz ingenue-709c490155509f4c18f79f4d0632ab22ad32cc1a.tar.bz2 ingenue-709c490155509f4c18f79f4d0632ab22ad32cc1a.zip |
Added config status page, moving forward and back in config wizard; added config control of user registration and invites; added 'No results' in wlca search; cleaned up use of configuration object in wizard API; added step names to module metadata; check configurations for validity before building
-rw-r--r-- | frontend/classes/module.php | 3 | ||||
-rw-r--r-- | frontend/classes/wizard_api.php | 146 | ||||
-rw-r--r-- | frontend/css/wlca.css | 2 | ||||
-rw-r--r-- | frontend/functions/owner_or_admin.php | 9 | ||||
-rw-r--r-- | frontend/include/header.php | 10 | ||||
-rw-r--r-- | frontend/js/wlca.js | 6 | ||||
-rw-r--r-- | frontend/modules/gentoo_common.php | 2 | ||||
-rw-r--r-- | frontend/pages/configurations/manager.php | 9 | ||||
-rw-r--r-- | frontend/pages/configurations/status.php | 47 | ||||
-rw-r--r-- | frontend/pages/configurations/verifier.php | 39 | ||||
-rw-r--r-- | frontend/pages/configurations/wizard.php | 13 | ||||
-rw-r--r-- | frontend/pages/invite.php | 12 | ||||
-rw-r--r-- | frontend/pages/register.php | 4 | ||||
-rw-r--r-- | frontend/routing.csv | 2 | ||||
-rw-r--r-- | shared/classes/1conf_build_common.php | 9 | ||||
-rw-r--r-- | shared/classes/configuration.php | 8 | ||||
-rw-r--r-- | shared/classes/user.php | 2 | ||||
-rw-r--r-- | shared/config.php | 2 | ||||
-rw-r--r-- | shared/functions/load_config.php | 2 | ||||
-rw-r--r-- | shared/include/defaults.php | 2 | ||||
-rw-r--r-- | todo | 2 |
21 files changed, 190 insertions, 141 deletions
diff --git a/frontend/classes/module.php b/frontend/classes/module.php index 8971c42..9e6f9d0 100644 --- a/frontend/classes/module.php +++ b/frontend/classes/module.php @@ -1,11 +1,12 @@ <?php class module { - var $id, $name, $steps, $dir; + public $id, $name, $numsteps, $steps, $dir; function __construct($id) { $this->id=$id; require(FRONTEND."/modules/$id.info"); $this->name=$name; $this->steps=$steps; + $this->numsteps=count($steps); $this->dir=FRONTEND.'/modules/'.$dir; } } diff --git a/frontend/classes/wizard_api.php b/frontend/classes/wizard_api.php index 48fe637..381a267 100644 --- a/frontend/classes/wizard_api.php +++ b/frontend/classes/wizard_api.php @@ -1,30 +1,36 @@ <?php class wizard_step { - var $module, $step, $title, $next, $data=array(); - function __construct($mod, $step) { - $this->module=new module($mod); + var $configuration, $module, $step, $title, $next, $data=array(); + function __construct(&$c, $step, $noload=false) { + $this->configuration=&$c; + $this->module=new module($c->module); $this->step=$step; - $file=$this->module->dir."/step$step.php"; - if (!is_readable($file)) { - throw_exception("$mod step $step doesn't exist!"); + if (!$noload) { + $file=$this->module->dir."/step$step.php"; + if (!is_readable($file)) { + throw_exception("$mod step $step doesn't exist!"); + } + require($file); } - require($file); - $this->title="Step $step/{$this->module->steps}".($title?" - $title":''); - $this->next=isset($next)?$next:($this->step == $this->module->steps?null:$step+1); + $this->title=$this->module->steps[$step-1]; + $this->next=isset($next)?$next:($this->step == $this->module->numsteps?null:$step+1); } public function output() { global $conf; - echo "<h3>$this->title</h3>\n"; - $scale=$conf['progressbar_width']/$this->module->steps; - echo '<img src="'.url('images/full.gif').'" style="border-left: 1px solid black; border-top: 1px solid black; border-bottom: 1px solid black; width: '.$this->step*$scale.'px; height: 15px" /><img src="'.url('images/empty.gif').'" style="border-right: 1px solid black; border-top: 1px solid black; border-bottom: 1px solid black; width: '.($this->module->steps-$this->step)*$scale.'px; height: 15px" /><br/>'."\n"; - echo '<form action="'.url('config/'.wizard::$configuration->id).'" method="post">'; + echo "<div class=\"wizard\" id=\"step$this->step\">"; + echo '<form action="'.url('config/'.$this->configuration->id).'" method="post"><a style="float: right" href="'.url('config/'.$this->configuration->id.'/status').'">Status</a><h3>Step '.$this->step.': '.$this->title."</h3>\n"; + $scale=$conf['progressbar_width']/$this->module->numsteps; + echo '<img src="'.url('images/full.gif').'" style="border-left: 1px solid black; border-top: 1px solid black; border-bottom: 1px solid black; width: '.$this->step*$scale.'px; height: 15px" /><img src="'.url('images/empty.gif').'" style="border-right: 1px solid black; border-top: 1px solid black; border-bottom: 1px solid black; width: '.(count($this->module->steps)-$this->step)*$scale.'px; height: 15px" /><br/>'."\n"; + $this->echo_buttons(); foreach ($this->data as $obj) { if (!$obj->status) { echo print_warning('Please complete this field.'); } $obj->output(); } - echo '<br/><input type="submit" name="wizard_submit['.$this->step.']" value="Continue" />'."\n"; + echo '<br/>'; + $this->echo_buttons(); + echo '</div>'."\n"; } public function process() { global $request; @@ -41,75 +47,72 @@ class wizard_step { } public function verify() { foreach ($this->data as $obj) { - if (!$obj->status=$obj->verify()) { - return false; + if (!($obj->status=$obj->verify())) { + return $obj->status; } } return true; } private function text($text) { - $this->data[]=new wizard_text($text); + $this->data[]=new wizard_text($this->configuration, $text); } private function text_input($optname, $htmlname, $label) { - $this->data[]=new wizard_text_input($optname, $htmlname, $label); + $this->data[]=new wizard_text_input($this->configuration, $optname, $htmlname, $label); } private function select($optname, $htmlname, $label, $options) { - $this->data[]=new wizard_select($optname, $htmlname, $label, $options); + $this->data[]=new wizard_select($this->configuration, $optname, $htmlname, $label, $options); } private function radio($optname, $htmlname, $label, $options) { - $this->data[]=new wizard_radio($optname, $htmlname, $label, $options); + $this->data[]=new wizard_radio($this->configuration, $optname, $htmlname, $label, $options); } private function checkbox_array($optname, $htmlname, $label, $array, $delim=' ') { - $this->data[]=new wizard_checkbox_array($optname, $htmlname, $label, $array, $delim=' '); + $this->data[]=new wizard_checkbox_array($this->configuration, $optname, $htmlname, $label, $array, $delim=' '); } private function layered_checkbox_array($optname, $htmlname, $label, &$array, $delim=' ', $metadata) { - $this->data[]=new wizard_layered_checkbox_array($optname, $htmlname, $label, $array, $delim, $metadata); + $this->data[]=new wizard_layered_checkbox_array($this->configuration, $optname, $htmlname, $label, $array, $delim, $metadata); } private function query($q) { return $GLOBALS['S']['pdo']->query($q); } private function get_opt($opt) { - return wizard::get_opt($opt); + return $this->configuration->get_opt($opt); + } + private function echo_buttons() { + echo '<input type="button" onclick="window.location=\''.url('config/'.$this->configuration->id.'/'.($this->step-1)).'\'" value="Back" /> <input style="float: right" type="submit" name="wizard_submit['.$this->step.']" value="Next" /><br/>'; } } abstract class wizard { - public $status=true; - public static $configuration; - public static function set_configuration(&$c) { - self::$configuration=&$c; + public $status=true, $configuration; + function __construct(&$c) { + $this->configuration=&$c; } abstract public function output(); abstract public function process(); abstract public function verify(); abstract public function clear(); - public static function get_opt($name) { - $opts=self::$configuration->get_opts(); - return isset($opts[$name])?$opts[$name]:null; + protected function get_opt($name) { + return $this->configuration->get_opt($name); } - protected static function set_opt($name, $val) { + protected function set_opt($name, $val) { debug('wizard', "$name=$val"); if (substr($name, 0, 1) == ':') { - self::$configuration->$name=$val; - self::$configuration->write(); + $this->configuration->$name=$val; + $this->configuration->write(); } else { - self::$configuration->set_opt($name, $val); + $this->configuration->set_opt($name, $val); } } - protected static function opt_is($name, $val) { - $opts=self::$configuration->get_opts(); - if (isset($opts[$name]) && $opts[$name] === $val) { - return true; - } else { - return false; - } + protected function opt_is($name, $val) { + return $this->configuration->opt_is($name, $val); } - protected static function delete_opt($name) { - self::$configuration->delete_opt($name); + protected function delete_opt($name) { + return $this->configuration->delete_opt($name); } } class wizard_text extends wizard { protected $text; - function __construct($text) { + function __construct(&$c, $text) { + parent::__construct($c); $this->text=$text; } public function output() { @@ -125,7 +128,8 @@ class wizard_text extends wizard { } abstract class wizard_input extends wizard { protected $optname, $htmlname, $label; - function __construct($optname, $htmlname, $label) { + function __construct(&$c, $optname, $htmlname, $label) { + parent::__construct($c); $this->optname=$optname; $this->htmlname=htmlentities($htmlname); $this->label=htmlentities($label); @@ -143,10 +147,10 @@ abstract class wizard_input extends wizard { } } public function verify() { - return self::get_opt($this->optname)!==null; + return $this->get_opt($this->optname)!==null; } public function clear() { - self::delete_opt($this->optname); + return $this->delete_opt($this->optname); } } class wizard_text_input extends wizard_input { @@ -157,8 +161,8 @@ class wizard_text_input extends wizard_input { } class wizard_select extends wizard_input { private $options; - function __construct($optname, $htmlname, $label, $options) { - parent::__construct($optname, $htmlname, $label); + function __construct(&$c, $optname, $htmlname, $label, $options) { + parent::__construct($c, $optname, $htmlname, $label); $this->options=$options; } public function output() { @@ -166,7 +170,7 @@ class wizard_select extends wizard_input { echo '<select name="'.$this->htmlname.'">'."\n"; $i=0; foreach ($this->options as $val => $label) { - echo "\t".'<option value="'.$i++.'"'.(self::opt_is($this->optname, $val)?' selected="selected"':'').'>'.htmlentities($label).'</option>'."\n"; + echo "\t".'<option value="'.$i++.'"'.($this->opt_is($this->optname, $val)?' selected="selected"':'').'>'.htmlentities($label).'</option>'."\n"; } echo '</select>'."\n"; } @@ -174,12 +178,13 @@ class wizard_select extends wizard_input { global $request; $vals=array_keys($this->options); if (isset($request[$this->htmlname]) && is_numeric($request[$this->htmlname]) && isset($vals[$request[$this->htmlname]])) { - self::set_opt($this->optname, $vals[$request[$this->htmlname]]); + $this->set_opt($this->optname, $vals[$request[$this->htmlname]]); return true; } else return false; } public function verify() { - return ($val=self::get_opt($this->optname)) !== null && in_array($val, array_keys($this->options)); + if (($val=$this->get_opt($this->optname)) === null) return null; + return isset($this->options[$val]); } } class wizard_radio extends wizard_select { @@ -187,15 +192,15 @@ class wizard_radio extends wizard_select { echo "$this->label:<br/>\n"; $i=0; foreach ($this->options as $val => $label) { - echo "\t<input type=\"radio\" id=\"$this->htmlname-$i\" name=\"$this->htmlname\" value=\"".$i."\"".(self::opt_is($this->optname, $val)?' checked="checked"':'')."\" /><label for=\"$this->htmlname-$i\">".htmlentities($label)."</label>\n"; + echo "\t<input type=\"radio\" id=\"$this->htmlname-$i\" name=\"$this->htmlname\" value=\"".$i."\"".($this->opt_is($this->optname, $val)?' checked="checked"':'')."\" /><label for=\"$this->htmlname-$i\">".htmlentities($label)."</label>\n"; $i++; } } } class wizard_checkbox_array extends wizard_input { protected $array; - function __construct($optname, $htmlname, $label, $array, $delim=' ') { - parent::__construct($optname, $htmlname, $label); + function __construct(&$c, $optname, $htmlname, $label, $array, $delim=' ') { + parent::__construct($c, $optname, $htmlname, $label); $this->array=$array; $this->delim=$delim; } @@ -203,22 +208,22 @@ class wizard_checkbox_array extends wizard_input { echo "$this->label:<br/>\n"; $i=0; foreach ($this->array as $val => $label) { - echo "\t<input type=\"checkbox\" id=\"$this->htmlname-$i\" name=\"$this->htmlname[$i]\"".(self::opt_has($this->optname, $val, $this->delim)?' checked="checked"':'')." /><label for=\"$this->htmlname-$i\">$label</label><br/>\n"; + echo "\t<input type=\"checkbox\" id=\"$this->htmlname-$i\" name=\"$this->htmlname[$i]\"".($this->opt_has($this->optname, $val, $this->delim)?' checked="checked"':'')." /><label for=\"$this->htmlname-$i\">$label</label><br/>\n"; $i++; } } public function process() { global $request; $val=array(); - // FIXME we're assuming that array_keys order is determinate and the same as the foreach in output() $vals=array_keys($this->array); foreach ($request[$this->htmlname] as $i) { $val[]=$vals[$i]; } - self::set_opt($this->optname, implode($this->delim, $vals)); + $this->set_opt($this->optname, implode($this->delim, $vals)); } public function verify() { - if (($vals=self::get_opt($this->optname)) === null) return false; + if (($vals=$this->get_opt($this->optname)) === null) return null; + if (strlen($vals) == 0) return true; $vals=explode($this->delim, $vals); foreach ($vals as $i => $val) { if (isset($this->array[$val])) { @@ -227,18 +232,18 @@ class wizard_checkbox_array extends wizard_input { } return count($vals) == 0; } - protected static function opt_has($name, $val, $delim=' ') { - static $cache; - if (!isset($cache[$name][$delim])) { - $cache[$name][$delim]=explode($delim, self::get_opt($name)); + private static $opt_cache; + protected function opt_has($name, $val, $delim=' ') { + if (!isset(self::$opt_cache[$name][$delim])) { + self::$opt_cache[$name][$delim]=explode($delim, $this->get_opt($name)); } - return in_array($val, $cache[$name][$delim]); + return in_array($val, self::$opt_cache[$name][$delim]); } } class wizard_layered_checkbox_array extends wizard_checkbox_array { private $depth=0, $path_delims=array('', '/', '-'); - function __construct($optname, $htmlname, $label, &$array, $delim=' ', $metadata) { - parent::__construct($optname, $htmlname, $label, &$array, $delim); + function __construct(&$c, $optname, $htmlname, $label, &$array, $delim=' ', $metadata) { + parent::__construct($c, $optname, $htmlname, $label, &$array, $delim); $this->metadata=$metadata; for ($i=current(&$array); is_array($i); $i=current($i)) $this->depth++; global $S; @@ -253,11 +258,12 @@ class wizard_layered_checkbox_array extends wizard_checkbox_array { $this->r_output($this->array); } public function process() { - self::set_opt($this->optname, implode($this->delim, $this->r_process($this->array))); + $this->set_opt($this->optname, implode($this->delim, $this->r_process($this->array))); return true; } public function verify() { - if (($vals=self::get_opt($this->optname)) === null) return false; + if (($vals=$this->get_opt($this->optname)) === null) return null; + if (strlen($vals) == 0) return true; $vals=explode($this->delim, $vals); $r=$this->r_verify($vals, $this->array); debug('wlca', 'got results: '.implode(' ',$r)); @@ -288,7 +294,7 @@ class wizard_layered_checkbox_array extends wizard_checkbox_array { $this->r_output($val, $depth+1, $name, $name); $uid++; } - echo '</div>'; + echo '<h3 style="display: none">No results</h3></div>'; echo "<script type=\"text/javascript\">\n<!--\nif (wlca_show_checked(document.getElementById('{$conf['id']}'), 0, $this->depth) == 0) wlca_search(document.getElementById('{$conf['id']}-q').value, document.getElementById('{$conf['id']}'), 0, $this->depth);\n-->\n</script>\n"; } else { $meta=$this->metadata[$depth]; @@ -300,7 +306,7 @@ class wizard_layered_checkbox_array extends wizard_checkbox_array { } if (isset($meta['checkbox'])) { $enc=self::b36($ucid++); - echo '<input type="checkbox" id="-'.$enc.'" name="'.$this->htmlname.'['.$enc.']"'.(self::opt_has($this->optname, $this->format_label($array, $meta['checkbox'], $path, $name), $this->delim)?' checked="checked"':'').' /><label for="-'.$enc.'">'.$this->format_label($array, $meta['label'], $path, $name).'</label>'."\n"; + echo '<input type="checkbox" id="-'.$enc.'" name="'.$this->htmlname.'['.$enc.']"'.($this->opt_has($this->optname, $this->format_label($array, $meta['checkbox'], $path, $name), $this->delim)?' checked="checked"':'').' /><label for="-'.$enc.'">'.$this->format_label($array, $meta['label'], $path, $name).'</label>'."\n"; } elseif (isset($meta['label'])) { echo '<span class="wlcal">'.$this->format_label($array, $meta['label'], $path, $name)."</span>\n"; } diff --git a/frontend/css/wlca.css b/frontend/css/wlca.css index e090b89..2ff94a9 100644 --- a/frontend/css/wlca.css +++ b/frontend/css/wlca.css @@ -5,7 +5,7 @@ padding-left: 2em; } #plist { - height: 400px; + max-height: 15em; overflow: auto; margin: 10px; padding: 5px; diff --git a/frontend/functions/owner_or_admin.php b/frontend/functions/owner_or_admin.php new file mode 100644 index 0000000..d7b65c2 --- /dev/null +++ b/frontend/functions/owner_or_admin.php @@ -0,0 +1,9 @@ +<?php +function owner_or_admin($id) { + global $S; + if (!isset($S['user'])) return false; + if ($S['user']->id === $id) return true; + if ($S['user']->has_flag('a')) return true; + return false; +} +?> diff --git a/frontend/include/header.php b/frontend/include/header.php index 0fa0b3a..81e8d7b 100644 --- a/frontend/include/header.php +++ b/frontend/include/header.php @@ -39,9 +39,11 @@ echo '<li><a href="'.url().'">Home</a></li>'; echo '<li><a href="'.url('create').'">New configuration</a></li>'; echo '<li><a href="'.url('configurations').'">Manage configurations</a></li>'; echo '<li><a href="'.url('logs').'">Log viewer</a></li>'; -if (isset($S['user']) && $S['user']->hasflag('a')) { - echo '<li><a href="'.url('invite').'">Invite</a></li>'; -} +if (isset($S['user'])) { + if ($conf['invite'] && ($S['user']->has_flag('a') || $conf['invite'] != 'admin')) + echo '<li><a href="'.url('invite').'">Invite</a></li>'; +} elseif ($conf['registration']) + echo '<li><a href="'.url('register').'">Register</a>'; ?> </ul> </div> @@ -52,7 +54,7 @@ if (isset($S['user']) && $S['user']->hasflag('a')) { $links['logout'.(strlen($S['request'])?'/'.$S['request']:'')]='Logout'; } else { $links['login'.(strlen($S['request'])?'/'.$S['request']:'')]='Login'; - $links['register']='Register'; + if ($conf['registration']) $links['register']='Register'; } foreach ($links as $url => $text) { $links[$url]='<a href="'.url($url).'">'.htmlentities($text).'</a>'; diff --git a/frontend/js/wlca.js b/frontend/js/wlca.js index d62994b..7c1b13e 100644 --- a/frontend/js/wlca.js +++ b/frontend/js/wlca.js @@ -51,6 +51,9 @@ function wlca_search(q, el, depth, maxdepth, t) { wlca_collapse(el.id); } } + if (depth == 0) { + el.childNodes[el.childNodes.length-1].style.display=found?"none":""; + } return found; } function wlca_show_checked(el, depth, maxdepth) { @@ -69,5 +72,8 @@ function wlca_show_checked(el, depth, maxdepth) { el.childNodes[i].style.display=(lfound > 0?"":"none"); } } + if (depth == 0) { + el.childNodes[el.childNodes.length-1].style.display=found?"none":""; + } return found; } diff --git a/frontend/modules/gentoo_common.php b/frontend/modules/gentoo_common.php index cac9b4b..bc72b0b 100644 --- a/frontend/modules/gentoo_common.php +++ b/frontend/modules/gentoo_common.php @@ -1,4 +1,4 @@ <?php -$steps=3; +$steps=array('Profile', 'Extra Packages', 'Image Format'); $dir='gentoo'; ?> diff --git a/frontend/pages/configurations/manager.php b/frontend/pages/configurations/manager.php index 15ab529..148a470 100644 --- a/frontend/pages/configurations/manager.php +++ b/frontend/pages/configurations/manager.php @@ -20,7 +20,10 @@ function body_configurations_manager() { } else { $name=isset($request['name'])?$request['name']:null; $build=$c->build($name); - echo print_success('Submitted for build - <a href="'.url('logs/'.$build->id).'">Logs</a>'); + if (is_object($build)) + echo print_success('Submitted for build - <a href="'.url('logs/'.$build->id).'">Logs</a>'); + else + echo print_error('Invalid configuration', 'Your configuration could not be submitted for build. Please return to <a href="'.url("config/$c->id/$build").'">step '.$build.'</a> and continue configuration from there.'); } } echo '<form action="'.url('configurations').'" method="post"><table><tr><th>ID</th><th>Name</th>'.(count($conf['modules']) > 1?'<th>Module</th>':'').'<th>Status</th><th>Options</th><th>Builds</th></tr>'."\n"; @@ -39,9 +42,9 @@ function body_configurations_manager() { echo "$c->module</td><td>"; } if ($c->status > 0) { - echo '<a href="'.url("config/$c->id")."\">Step $c->status</a>'"; + echo '<a href="'.url("config/$c->id")."\">Step $c->status</a>"; } elseif ($c->status == 0) { - echo '<b>Ready</b> (<a href="'.url('verify/'.$c->id).'">verify</a>)'; + echo '<b>Ready</b> (<a href="'.url("config/$c->id/status").'">modify</a>)'; } else { echo $c->status; } diff --git a/frontend/pages/configurations/status.php b/frontend/pages/configurations/status.php new file mode 100644 index 0000000..ebeeab3 --- /dev/null +++ b/frontend/pages/configurations/status.php @@ -0,0 +1,47 @@ +<?php +function init_configurations_status() { + global $S, $request; + if (!isset($S['user'])) { + return 'login'; + } + if (!(isset($request['configuration']) && strlen($request['configuration']) == 6 && ctype_alnum($request['configuration']))) { + return '404'; + } + $r=$S['pdo']->query('SELECT * FROM `configurations` WHERE `id`=\''.$request['configuration'].'\''); + if ($r->rowCount() == 0) { + return '404'; + } + $S['status']['configuration']=new sql_configuration($r->fetch(PDO::FETCH_ASSOC)); + if ($S['status']['configuration']->owner != $S['user']->id) { + return '404'; + } + return array('title' => 'Status'); +} +function body_configurations_status() { + global $S; + $c=&$S['status']['configuration']; + $module=new module($c->module); + $status=true; + $good=0; + for ($i=1; $i<=$module->numsteps; $i++) { + $r[$i]='<li>'; + $step=new wizard_step($c, $i, !$status); + $r[$i].=($status?'<a href="'.url("config/$c->id/$i")."\">$step->title</a>":$step->title); + if ($status) { + $r[$i].=' - '; + $good+=($status=$step->verify())?1:0; + if ($status === null) + $r[$i].='<span style="color: yellow; background-color: black">Incomplete</span>'; + elseif ($status) + $r[$i].='<span style="color: green">Complete</span>'; + else + $r[$i].='<span style="color: red">INVALID</span>'; + } + $r[$i].='</li>'; + } + echo '<h3>'.($c->name?htmlentities($c->name):$c->id).": $good of $module->numsteps steps complete</h3>\n"; + echo '<ol>'.implode('', $r).'</ol>'; + if ($good < $module->numsteps) + echo '<a href="'.url("config/$c->id/".($good+1)).'">Finish configuration</a>'; +} +?> diff --git a/frontend/pages/configurations/verifier.php b/frontend/pages/configurations/verifier.php deleted file mode 100644 index ae27c3c..0000000 --- a/frontend/pages/configurations/verifier.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php -function init_configurations_verifier() { - global $S, $request; - if (!isset($S['user'])) { - return 'login'; - } - if (!(isset($request['configuration']) && strlen($request['configuration']) == 6 && ctype_alnum($request['configuration']))) { - return '404'; - } - $r=$S['pdo']->query('SELECT * FROM `configurations` WHERE `id`=\''.$request['configuration'].'\''); - if ($r->rowCount() == 0) { - return '404'; - } - $S['verifier']['configuration']=new sql_configuration($r->fetch(PDO::FETCH_ASSOC)); - if ($S['verifier']['configuration']->owner != $S['user']->id) { - return '404'; - } - return array('title' => 'Verify'); -} -function body_configurations_verifier() { - global $S; - $c=&$S['verifier']['configuration']; - wizard::set_configuration($c); - $module=new module($c->module); - $status=true; - echo '<ol>'; - for ($i=1; $i<=$module->steps; $i++) { - echo '<li>'; - if ($status) { - $step=new wizard_step($c->module, $i); - $status=$status && ($r=$step->verify()); - echo $r?'Valid':'INVALID'; - } else { - echo 'Unavailable'; - } - echo '</li>'; - } -} -?> diff --git a/frontend/pages/configurations/wizard.php b/frontend/pages/configurations/wizard.php index 571f803..cc46405 100644 --- a/frontend/pages/configurations/wizard.php +++ b/frontend/pages/configurations/wizard.php @@ -10,7 +10,6 @@ function init_configurations_wizard() { if ($configuration->owner != $S['user']->id) { return '404'; } - wizard::set_configuration($S['wizard']['configuration']); if (isset($request['wizard_submit'])) { $steps=array_keys($request['wizard_submit']); $step=$steps[0]; @@ -22,6 +21,7 @@ function init_configurations_wizard() { } elseif ($result === null) { debug('wizard', "$configuration->module step $step returned <i>null</i> - config finished"); $configuration->status=0; + unset($S['wizard']['step']); $configuration->write(); } else { $configuration->status=$result; @@ -45,7 +45,7 @@ function init_configurations_wizard() { wizard_load_step(1); } if (isset($S['wizard']['step'])) { - return array('title' => $S['wizard']['step']->title); + return array('title' => "Step {$S['wizard']['step']->step}: {$S['wizard']['step']->title}"); } else { return array('title' => 'Create'); } @@ -54,11 +54,10 @@ function body_configurations_wizard() { global $S, $conf; if (isset($S['wizard']['configuration'])) { $configuration=&$S['wizard']['configuration']; - if ($configuration->status == 0) { - echo print_success('Config finished!', '<form action="'.url('configurations').'" method="post"><input type="hidden" name="configuration" value="'.$configuration->id.'" />Name (optional): <input name="name" value="'.($configuration->name?htmlentities($configuration->name):'').'" /> <input type="submit" name="build" value="Build" /></form>'); - } else { + if (isset($S['wizard']['step'])) $S['wizard']['step']->output(); - } + else + echo print_success('Config finished!', '<form action="'.url('configurations').'" method="post"><input type="hidden" name="configuration" value="'.$configuration->id.'" />Name (optional): <input name="name" value="'.($configuration->name?htmlentities($configuration->name):'').'" /> <input type="submit" name="build" value="Build" /></form>'); } else { echo '<form action="'.url('create').'" method="post"><h3>Request an image built</h3>Name of your configuration (optional): <input name="name" /><br/>'; if (count($conf['modules']) > 1) { @@ -76,7 +75,7 @@ function body_configurations_wizard() { function &wizard_load_step($step) { global $S; if (!isset($S['wizard']['steps'][$step])) { - $S['wizard']['steps'][$step]=new wizard_step($S['wizard']['configuration']->module, $step); + $S['wizard']['steps'][$step]=new wizard_step($S['wizard']['configuration'], $step); } $S['wizard']['step']=&$S['wizard']['steps'][$step]; return $S['wizard']['steps']; diff --git a/frontend/pages/invite.php b/frontend/pages/invite.php index a04a12d..69047ab 100644 --- a/frontend/pages/invite.php +++ b/frontend/pages/invite.php @@ -1,12 +1,10 @@ <?php function init_invite() { - global $S; - if (!isset($S['user'])) { - return 'login'; - } - if (!$S['user']->hasflag('a')) { - return 'denied'; - } + global $S, $conf; + if (!$conf['invite']) return '404'; + if (!isset($S['user'])) return 'login'; + if ($conf['invite'] == 'admin' && !$S['user']->has_flag('a')) return '404'; + return array('title' => 'Invite'); } function body_invite() { global $S, $request, $conf; diff --git a/frontend/pages/register.php b/frontend/pages/register.php index e624ac1..1f76c69 100644 --- a/frontend/pages/register.php +++ b/frontend/pages/register.php @@ -1,6 +1,6 @@ <?php function init_register() { - global $S, $request; + global $S, $request, $conf; if (isset($S['user'])) { header('Location: '.url()); return 'welcome'; @@ -24,7 +24,7 @@ function init_register() { } } } - } + } elseif (!$conf['registration']) return '404'; return array('title' => 'Register'); } function body_register() { diff --git a/frontend/routing.csv b/frontend/routing.csv index 492e59e..7737b69 100644 --- a/frontend/routing.csv +++ b/frontend/routing.csv @@ -21,8 +21,8 @@ ^create$ configurations/wizard ^config/([a-zA-Z0-9]{6})$ configurations/wizard configuration ^config/([a-zA-Z0-9]{6})/([0-9]+)$ configurations/wizard configuration step +^config/([a-zA-Z0-9]{6})/status$ configurations/status configuration ^configurations$ configurations/manager -^verify/([a-zA-Z0-9]{6})$ configurations/verifier configuration # Download finished image ^download/([a-zA-Z0-9]{6})$ downloadimage build # Session diff --git a/shared/classes/1conf_build_common.php b/shared/classes/1conf_build_common.php index aae1e42..35ba6e6 100644 --- a/shared/classes/1conf_build_common.php +++ b/shared/classes/1conf_build_common.php @@ -41,6 +41,15 @@ abstract class conf_build_common extends sql_row_obj { } return $opts; } + // Returns the value (or object if $get_obj is true) of the option given by $name, or null if unset + public function get_opt($name, $get_obj=false) { + $opts=$this->get_opts($get_obj); + return isset($opts[$name])?$opts[$name]:null; + } + // Returns true if the given option is set and equals the given value, false otherwise + public function opt_is($name, $val) { + return (($r=$this->get_opt($name)) !== null && $r == $val); + } // Generates a unique id and sets status to 1, writes self to db and returns id public function init() { global $S; diff --git a/shared/classes/configuration.php b/shared/classes/configuration.php index fedef12..2714732 100644 --- a/shared/classes/configuration.php +++ b/shared/classes/configuration.php @@ -31,9 +31,15 @@ class sql_configuration extends conf_build_common { 'not_null' => true, 'default' => 0 ) - ); public function build($name=null) { + $module=new module($this->module); + for ($i=1; $i<=$module->numsteps; $i++) { + $step=new wizard_step($this, $i); + if (!$step->verify()) { + return $i; + } + } $build=new sql_build(); $build->init(); $build->name=$name; diff --git a/shared/classes/user.php b/shared/classes/user.php index 91a7a46..eef0977 100644 --- a/shared/classes/user.php +++ b/shared/classes/user.php @@ -35,7 +35,7 @@ class sql_user extends sql_row_obj { ) ); - public function hasflag($flag) { + public function has_flag($flag) { return (strpos($this->flags, $flag) !== false); } } diff --git a/shared/config.php b/shared/config.php index 1ac1ae7..2f73991 100644 --- a/shared/config.php +++ b/shared/config.php @@ -15,6 +15,8 @@ $emailfrom='noreply@gentoo.org'; // Used as the From: field in emails $check_email_dns=true; // Use DNS to check the domain of submitted emails for validity // $split_setup=false; // Whether the frontend and backend are running on different hosts // Frontend options: +// $registration=false; // Whether users can create new accounts without an invite +// $invite='admin'; // Who can use the invite function: true or 'user'=users; admin=admins; false=nobody // $logview_max=1000; // The maximum number of log entries shown on one page (1000 is a good start) // $progressbar_width=350; // The width, in pixels, of the config wizard progress bar // Backend options: diff --git a/shared/functions/load_config.php b/shared/functions/load_config.php index 27e01bc..7bf94b4 100644 --- a/shared/functions/load_config.php +++ b/shared/functions/load_config.php @@ -3,7 +3,7 @@ function load_config() { require(SHARED.'/include/defaults.php'); require(SHARED.'/config.php'); $modules=explode(' ', $modules); - foreach (explode(' ', 'title sqlhost sqluser sqlpass sqldb debug modules bundlers cookiename sessionlength mod_rewrite emailfrom check_email_dns split_setup logview_max progressbar_width pkgdir_root emerge_default_opts portdir frontend_location backend_id') as $var) { + foreach (explode(' ', 'title sqlhost sqluser sqlpass sqldb debug modules bundlers cookiename sessionlength mod_rewrite emailfrom check_email_dns split_setup registration invite logview_max progressbar_width pkgdir_root emerge_default_opts portdir frontend_location backend_id') as $var) { if (isset($$var)) { $GLOBALS['conf'][$var]=$$var; } diff --git a/shared/include/defaults.php b/shared/include/defaults.php index 4065cc0..66862a8 100644 --- a/shared/include/defaults.php +++ b/shared/include/defaults.php @@ -24,6 +24,8 @@ $mod_rewrite=true; $emailfrom='noreply@noreply.net'; $check_email_dns=false; $split_setup=false; +$registration=false; +$invite='admin'; $logview_max=1000; $progressbar_width=350; $emerge_default_opts='-t -v -K --color=y --root-deps=rdeps'; @@ -1,6 +1,5 @@ Have backend handle builds that it finds to already be running (break in to steps and store current status) Make package adding friendly for browsers without JS/CSS (use ul/li, not div) -Add configuration verification - each step must be validated before a build is submitted (check selected packages are available, etc.) Write a live git ebuild Write an AJAX-based self-updating status viewer *** Add logging besides just commands *** @@ -19,7 +18,6 @@ Completely plan out how frontend modules should function - each step needs to re Allow backend to define bail-out functions to call when it dies (things like unmounting the ISO it was copying) Add STDERR (maybe STDOUT) only option to log viewer Simplify status to numeric on builds - varchar isn't necessary -Add config option to enable/disable user self-registration/invitations/admin-only invites Move gentoo_profiles setup out of the general setup.php, allow per-module setup Move bundler selection out of gentoo module and generalize it (switch to builds instead of configurations) Improve the quality of base system creation (if necessary) |