X-Git-Url: http://git.polytechnique.org/?a=blobdiff_plain;f=include%2Fdiogenes%2Fdiogenes.table-editor.inc.php;fp=include%2Fdiogenes%2Fdiogenes.table-editor.inc.php;h=22ec5890b194804c66c60f5c70b442249189453e;hb=6855525e48fad5de270500a5445c4f4ff85d8bda;hp=0000000000000000000000000000000000000000;hpb=e69709aa8ee6108a1197e46b45367ba8dab55a52;p=diogenes.git diff --git a/include/diogenes/diogenes.table-editor.inc.php b/include/diogenes/diogenes.table-editor.inc.php new file mode 100644 index 0000000..22ec589 --- /dev/null +++ b/include/diogenes/diogenes.table-editor.inc.php @@ -0,0 +1,553 @@ +db)) + die("\$globals->db is not an object!"); + + $this->DiogenesDatabaseTable($globals->db,$table); + + $this->actions = array(); + + if (!isset($this->vars[$idfield])) + die("the field '$idfield' was not found in '$table'"); + $this->idfield = $idfield; + $extra = new flagset($this->vars[$idfield]["extra"]); + $this->autoinc = $extra->hasflag("auto_increment"); + $this->idedit = $idedit; + + // unless the id field is editable, remove it from the variables + if (!$this->idedit) + unset($this->vars[$idfield]); + } + + + /** Add an "action" (hyperlink) to be displayed next to items in the summary. + * + * @param text the text for the hyperlink + * @param url the url for the hyperlink. anything of the form %foobar% will + * be replaced by the value of the field 'foobar' + */ + function addAction($text,$url) + { + array_push($this->actions, array("text" => $text, "url" =>$url)); + } + + + /** Adds a join with another table. + * + * @param $name the name of the table + * @param $joinid the fields on which we do a join with our "id" + * @param $joindel should we delete the joined entries in the table when we + delete an entry from $this->table? + * @param $joinextra extra clause for the join + * + * @see delete_db + */ + function add_join_table($name,$joinid,$joindel,$joinextra="") { + $this->jtables[$name] = array("joinid" => $joinid,"joindel" => $joindel, + "joinextra" => $joinextra); + } + + + /** EXPERIMENTAL : Add a field from another table. + * + * @param $table the table for which we are adding the field + * @param $name name of the variable (AS clause) + * @param $field the name of the table's field + * @param $value the default value of the field + * @param $desc a description + * @param $sum should we display this field in the table summary? + * @param $type type of the field : "enum", "set", "text", "textarea", "timestamp" + */ + function add_join_field($table,$name,$field,$value,$desc,$sum,$type="text") { + $this->vars[$name] = array("table" => $table, "field" => $field, "type" => $type, + "value" => $value, "desc" => $desc, "sum" => $sum); + } + + + /** Add a WHERE condition to the SELECT used for listing. + * + * @param cond string containing the WHERE condition + */ + function add_where_condition($cond) { + array_push($this->wheres, $cond); + } + + + /** Deletes the specified entry from the database. + * + * @param $id id of the entry to be deleted + */ + function delete_db($id) { + if ($id != '') { + $this->dbh->query("delete from {$this->table} where {$this->idfield}='$id'"); + + // delete dependencies in the tables on which we have a join + foreach ($this->jtables as $key => $val) { + if ($val['joindel']) { + $sql = "delete from {$key} where {$val['joinid']}='$id'"; + if ($val['joinextra']) + $sql .= " and {$val['joinextra']}"; + $this->dbh->query($sql); + } + } + reset($this->jtables); + } + } + + + /** Describe a column and sets it visibility + * + * @param name the name of the field + * @param desc the description for the field + * @param sum a boolean indicating whether to display the field in the summary + * @param type type of the field (optional) + * @param value default value of the field (optional) + * @param trans stores translations when it's a "set" value + */ + function describe($name,$desc,$sum,$type='',$value='',$trans=null) { + if (!isset($this->vars[$name])) + die("unknown field $name"); + $this->vars[$name]["desc"] = $desc; + $this->vars[$name]["sum"] = $sum; + if (!empty($type)) + $this->vars[$name]["type"] = $type; + if (!empty($value)) + $this->vars[$name]["value"] = $value; + if (!empty($trans) and $type=="set") + $this->vars[$name]["trans"] = $trans; + } + + + /** Describe a column and tell where to find possible values and sets it visibility + * + * @param name the name of the field + * @param desc the description for the field + * @param sum a boolean indicating whether to display the field in the summary + * @param vtable the name of the table where are located the external values + * @param vjoinid the $vtable field name corresponding to $this->table field $name + * @param vfield the $vtable field wich hold the significative and comprehensive value + */ + function describe_join_value($name,$desc,$sum,$vtable,$vjoinid,$vfield) { + global $globals; + if (!isset($this->vars[$name])) + die("unknown field $name"); + $this->vars[$name]["desc"] = $desc; + $this->vars[$name]["sum"] = $sum; + $this->vars[$name]["type"] = "ext"; + + $this->vars[$name]["vtable"] = $vtable; + $this->vars[$name]["vjoinid"] = $vjoinid; + $this->vars[$name]["vfield"] = $vfield; + } + + + /** Make a field hidden and uneditable + * + * @param name the name of the field + * @param value default value of the field (optional) + */ + function hide($name, $value = null) { + if (!isset($this->vars[$name])) + die("unknown field $name"); + + if (!empty($value)) + $this->vars[$name]["value"] = $value; + + $this->vars[$name]["edit"] = false; + $this->vars[$name]["show"] = false; + } + + + /** Do not display the id field in the summary + * + */ + function hide_id() { + $this->idsum = false; + } + + + /** Make a field uneditable + * + * @param name the name of the field + * @param value default value of the field (optional) + */ + function lock($name, $value = null) { + if (!isset($this->vars[$name])) + die("unknown field $name"); + + if (!empty($value)) + $this->vars[$name]["value"] = $value; + + $this->vars[$name]["edit"] = false; + } + + /** Read the selected entry from database + * + * @param id id of the entry we want to read + */ + function from_db($id) { + $sql = $this->make_select(false,$id); + $res = $this->dbh->query($sql); + + if ($myrow = mysql_fetch_array($res)) { + $this->id = $id; + foreach ($this->vars as $key => $val) { + $this->vars[$key]['value'] = $myrow[$key]; + } + reset($this->vars); + return true; + } else { + return false; + } + } + + + /** Read the current entry's values from the $_REQUEST variable + */ + function from_request() { + if (isset($_REQUEST[$this->prefix.'id'])) + $this->id = clean_request($this->prefix.'id'); + + foreach ($this->vars as $key => $val) { + // if this field is editable, retrieve the value from $_REQUEST + if ($val['edit']) + $this->vars[$key]['value'] = clean_request($this->prefix.$key); + + // apply type-specific transformations + switch ($val['type']) { + case "set": + if ( is_array($this->vars[$key]['value']) ) + $this->vars[$key]['value'] = implode(",",$this->vars[$key]['value']); + break; + case "timestamp": + $this->vars[$key]['value'] = mktime($this->vars[$key]['value']); + break; + } + } + reset($this->vars); + } + + + /** Write the current entry to database. + */ + function to_db() { + $varlst = new flagset(); + foreach ($this->vars as $key => $val) { + # we only want fields from our own table that are either editable or new + if (($val['table'] == $this->table) && ($val['edit'] || !isset($this->id))) { + switch ($val['type']) { + case "password": + if ($val['value']) + $varlst->addflag("$key='".md5($val['value'])."'"); + break; + default: + $varlst->addflag("$key='{$val['value']}'"); + } + } + } + reset($this->vars); + + if (isset($this->id)) { + $sql = "update {$this->table} set {$varlst->value} where {$this->idfield}='{$this->id}'"; + if ($this->wheres) + $sql .= " AND " . join(" AND ", $this->wheres); + } else { + if (!$this->autoinc && !$this->idedit) { + list($this->id) = mysql_fetch_row($this->dbh->query("select MAX({$this->idfield})+1 from {$this->table}")); + $varlst->addflag("{$this->idfield}='{$this->id}'"); + } + $sql = "insert into {$this->table} set {$varlst->value}"; + } + $this->dbh->query($sql); + + // retrieve the insertion id + if ($this->idedit) { + $this->id = $this->vars[$this->idfield]['value']; + } else if ($this->autoinc && !isset($this->id)) { + $this->id = $this->dbh->insert_id(); + } + } + + + /** Returns the JOIN clause to read a field. + * + * @param $val the field we want to read + */ + function make_join_flag($val) { + if ($val['table'] == $this->table) { + // this field is local, no join clause needed + return ""; + } else { + // not a local field, we need a join clause + $tbl_key = $val['table']; + $tbl_val = $this->jtables[$tbl_key]; + $flg = "left join $tbl_key on {$this->table}.{$this->idfield}={$tbl_key}.{$tbl_val['joinid']}"; + if ($tbl_val['joinextra']) + $flg .= " and {$tbl_val['joinextra']}"; + return $flg; + } + } + + + /** Create the SELECT request to display the table summary + * or to read an entry from the database + * + * @param $list boolean : are we displaying the summary? + * @param $num depending on $list, either the column names or the entry to display + */ + function make_select($list,&$num) { + if ($list) { + $varlst = new flagset("{$this->table}.{$this->idfield}"); + $orderby = ""; + $num = $this->idsum ? 1 : 0; + } else { + $varlst = new flagset(); + } + + $joinlst = new flagset(); + // run over all the variables + foreach ($this->vars as $key => $val) { + // if we are listing the summary, we want only the variables + // where ['sum'] is true. + if (!$list || $val['sum']) { + // type conversion + if ($val['type'] == "timestamp") + $varlst->addflag("UNIX_TIMESTAMP({$val['table']}.{$val['field']}) as $key"); + else + $varlst->addflag("{$val['table']}.{$val['field']} as $key"); + + // do we need a join clause? + if ($flag = $this->make_join_flag($val)) + $joinlst->addflag($flag); + + // if we are listing the summary, we want an order clause + if ($list) { + if (!$orderby) $orderby = "order by $key"; + $num++; + } + } + } + + reset($this->vars); + + $sql = "select {$varlst->value} from {$this->table} {$joinlst->value}"; + + # if we are in edit mode, add a WHERE condition + if (!$list) + $this->add_where_condition("{$this->table}.{$this->idfield}='$num'"); + + # sum up all the WHERE conditions + if ($this->wheres) + $sql .= " where " . join(" AND ", $this->wheres); + + # add order by clause + if ($list) + $sql .= " $orderby"; + + return $sql; + } + + + /** Set the maximum number of rows to return per page when viewing entries. + * By default, this is set to 0, meaning all rows are returned. + * + * @param maxrows the maximum number of rows (0 means unlimited) + */ + function set_maxrows($maxrows) + { + // check we were given a zero or positive number + if ($maxrows < 0) { + trigger_error("You cannot pass a negative number ($maxrows) to set_maxrows!"); + return; + } + + $this->maxrows = $maxrows; + } + + /** Process the requested action and fill out the Smarty variables for display. + * By default, displays the entries in the database table. + * + * @param page the page that will display the editor's forms + * @param outputvar the Smarty variable to which we should assign the output + * @param template the template to use for display + */ + function run(&$page,$outputvar='',$template='') { + global $globals; + + $action = clean_request('action'); + $page->assign('table',$this->table); + + switch($action) { + case "edit": + // check we are not in read-only mode + if ($this->readonly) die("Sorry, this table is read-only."); + + // if this is an existing entry, retrieve it + if (clean_request("{$this->prefix}id") != '') { + $this->from_db(clean_request("{$this->prefix}id")); + $page->assign('id',$this->id); + } + + // remove the uneditable fields + #foreach ($this->vars as $key => $val) { + #if (!$val['edit']) + # unset($this->vars[$key]); + #} + reset($this->vars); + + $page->assign('doedit',true); + break; + case "update": + // check we are not in read-only mode + if ($this->readonly) die("Sorry, this table is read-only."); + + $this->from_request(); + $this->to_db(); + break; + case "del": + // check we are not in read-only mode + if ($this->readonly) die("Sorry, this table is read-only."); + + $this->delete_db(clean_request("{$this->prefix}id")); + break; + } + + // if we are not in editor mode, display the list + if ($action != "edit") { + $ncols = 0; + $sql = $this->make_select(true,$ncols); + $res = $this->dbh->query($sql); + $page->assign('ncols',$ncols); + + // determine start and stop of displayed results + $p_total = mysql_num_rows($res); + $p_start = isset($_REQUEST['start']) ? $_REQUEST['start'] : 0; + $p_stop = $this->maxrows ? min($p_total, $p_start + $this->maxrows) : $p_total; + $counter = 0; + + while (($counter < $p_stop) and ($myarr = mysql_fetch_array($res))) { + if ($counter >= $p_start) { + $actions = array(); + foreach ($this->actions as $myaction) { + $url = $myaction['url']; + foreach ($myarr as $key=>$val) + $url = str_replace("%$key%", $val, $url); + + array_push($actions, array($myaction['text'],$url)); + } + $page->append('rows', array($myarr[$this->idfield], $myarr, $actions) ); + } + $counter++; + } + mysql_free_result($res); + + // smarty assignements for prev / next page links + $page->assign('p_prev', $p_start ? max($p_start - $this->maxrows, 0) : -1); + $page->assign('p_next', ($p_stop < $p_total) ? $p_stop : - 1 ); + $page->assign('p_total', $p_total); + + } + + $page->assign('vars',$this->vars); + $page->assign('prefix',$this->prefix); + $page->assign('idfield',$this->idfield); + $page->assign('idsum',$this->idsum); + $page->assign('readonly',$this->readonly); + if ($this->readonly && ($this->actions == array())) + $page->assign('hideactions', 1); + $page->assign('table_class', $this->table_class); + $page->assign('table_style', $this->table_style); + + // translations + $page->assign('msg_previous_page', __("previous page")); + $page->assign('msg_next_page', __("next page")); + $page->assign('msg_id', __("id")); + $page->assign('msg_action', __("action")); + $page->assign('msg_create', __("create")); + $page->assign('msg_delete', __("delete")); + $page->assign('msg_edit', __("edit")); + $page->assign('msg_new_entry', __("new entry")); + $page->assign('msg_existing_entry', __("existing entry")); + $page->assign('msg_no_change', __("(blank = no change)")); + $page->assign('msg_back', __("back")); + $page->assign('msg_confirm_delete', + __("You are about to delete this entry. Do you want to proceed?")); + $page->assign('msg_submit', __("Submit")); + + // if requested, assign the content to be displayed + if (!empty($outputvar)) { + if (empty($template)) + $template = $globals->libroot."/templates/table-editor.tpl"; + $page->assign($outputvar, $page->fetch($template)); + } + } + +} + +?>