diogenes.table-editor.inc.php

00001 <?php
00002 /*
00003  * Copyright (C) 2003-2004 Polytechnique.org
00004  * http://opensource.polytechnique.org/
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 
00022 require_once dirname(__FILE__).'/diogenes.misc.inc.php';
00023 require_once dirname(__FILE__).'/diogenes.database.table.inc.php';
00024 
00031 class DiogenesTableEditor extends DiogenesDatabaseTable {
00033   var $actions;
00035   var $autoinc;
00037   var $id;
00039   var $idedit;
00041   var $idsum = true;
00043   var $idfield;
00045   var $jtables = array();
00047   var $wheres = array();
00050   var $prefix = "frm_";
00052   var $readonly = false;
00054   var $maxrows = 0;
00055 
00057   var $table_class = "light";
00059   var $table_style = "";
00060   
00067   function DiogenesTableEditor($table, $idfield, $idedit = false) {
00068     global $globals;
00069     if (!is_object($globals->db))
00070       die("\$globals->db is not an object!");
00071 
00072     $this->DiogenesDatabaseTable($globals->db,$table);
00073 
00074     $this->actions = array();
00075 
00076     if (!isset($this->vars[$idfield]))
00077       die("the field '$idfield' was not found in '$table'");
00078     $this->idfield = $idfield;
00079     $extra = new flagset($this->vars[$idfield]["extra"]);
00080     $this->autoinc = $extra->hasflag("auto_increment");
00081     $this->idedit = $idedit;
00082 
00083     // unless the id field is editable, remove it from the variables
00084     if (!$this->idedit)
00085       unset($this->vars[$idfield]);
00086   }
00087 
00088 
00095   function addAction($text,$url)
00096   {
00097     array_push($this->actions, array("text" => $text, "url" =>$url));
00098   }
00099 
00100 
00111   function add_join_table($name,$joinid,$joindel,$joinextra="") {
00112     $this->jtables[$name] = array("joinid" => $joinid,"joindel" => $joindel,
00113       "joinextra" => $joinextra);
00114   }
00115 
00116 
00127   function add_join_field($table,$name,$field,$value,$desc,$sum,$type="text") {
00128     $this->vars[$name] = array("table" => $table, "field" => $field, "type" => $type,
00129      "value" => $value, "desc" => $desc, "sum" => $sum);
00130   }
00131 
00132 
00137   function add_where_condition($cond) {
00138     array_push($this->wheres, $cond);
00139   }
00140 
00141 
00146   function delete_db($id) {
00147     if ($id != '') {
00148       $this->dbh->query("delete from {$this->table} where {$this->idfield}='$id'");
00149 
00150       // delete dependencies in the tables on which we have a join
00151       foreach ($this->jtables as $key => $val) {
00152         if ($val['joindel']) {
00153           $sql = "delete from {$key} where {$val['joinid']}='$id'";
00154           if ($val['joinextra'])
00155             $sql .= " and {$val['joinextra']}";
00156           $this->dbh->query($sql);
00157         }
00158       }
00159       reset($this->jtables);
00160     }
00161   }
00162 
00163 
00173   function describe($name,$desc,$sum,$type='',$value='',$trans=null) {
00174     if (!isset($this->vars[$name]))
00175       die("unknown field $name");
00176     $this->vars[$name]["desc"] = $desc;
00177     $this->vars[$name]["sum"] = $sum;
00178     if (!empty($type))
00179       $this->vars[$name]["type"] = $type;
00180     if (!empty($value))
00181       $this->vars[$name]["value"] = $value;
00182     if (!empty($trans) and $type=="set")
00183       $this->vars[$name]["trans"] = $trans;
00184   }
00185 
00186 
00196   function describe_join_value($name,$desc,$sum,$vtable,$vjoinid,$vfield) {
00197     global $globals;
00198     if (!isset($this->vars[$name]))
00199       die("unknown field $name");
00200     $this->vars[$name]["desc"] = $desc;
00201     $this->vars[$name]["sum"] = $sum;
00202     $this->vars[$name]["type"] = "ext";
00203 
00204     $this->vars[$name]["vtable"] = $vtable;
00205     $this->vars[$name]["vjoinid"] = $vjoinid;
00206     $this->vars[$name]["vfield"] = $vfield;
00207   }
00208 
00209 
00215   function hide($name, $value = null) {
00216     if (!isset($this->vars[$name]))
00217       die("unknown field $name");
00218 
00219     if (!empty($value))
00220       $this->vars[$name]["value"] = $value;
00221 
00222     $this->vars[$name]["edit"] = false;
00223     $this->vars[$name]["show"] = false;
00224   }
00225 
00226 
00230   function hide_id() {
00231     $this->idsum = false;
00232   }
00233 
00234 
00240   function lock($name, $value = null) {
00241     if (!isset($this->vars[$name]))
00242       die("unknown field $name");
00243     
00244     if (!empty($value))
00245       $this->vars[$name]["value"] = $value;
00246     
00247     $this->vars[$name]["edit"] = false;
00248   }
00249   
00254   function from_db($id) {
00255     $sql = $this->make_select(false,$id);
00256     $res = $this->dbh->query($sql);
00257 
00258     if ($myrow = mysql_fetch_assoc($res)) {
00259       $this->id = $id;
00260       foreach ($this->vars as $key => $val) {
00261         $this->vars[$key]['value'] = $myrow[$key];
00262       }
00263       reset($this->vars);
00264       return true;
00265     } else {
00266       return false;
00267     }
00268   }
00269 
00270 
00273   function from_request() {
00274     if (isset($_REQUEST[$this->prefix.'id']))
00275       $this->id = clean_request($this->prefix.'id');
00276 
00277     foreach ($this->vars as $key => $val) {
00278       // if this field is editable, retrieve the value from $_REQUEST
00279       if ($val['edit'])
00280         $this->vars[$key]['value'] = clean_request($this->prefix.$key);
00281 
00282       // apply type-specific transformations
00283       switch ($val['type']) {
00284       case "set":
00285         if ( is_array($this->vars[$key]['value']) )
00286           $this->vars[$key]['value'] = implode(",",$this->vars[$key]['value']);
00287         break;
00288       case "timestamp":
00289         $this->vars[$key]['value'] = mktime($this->vars[$key]['value']);
00290         break;
00291       }
00292     }
00293     reset($this->vars);
00294   }
00295 
00296 
00299   function to_db() {
00300     $varlst = new flagset();
00301     foreach ($this->vars as $key => $val) {
00302       # we only want fields from our own table that are either editable or new
00303       if (($val['table'] == $this->table) && ($val['edit'] || !isset($this->id))) {
00304         switch ($val['type']) {
00305         case "password":
00306           if ($val['value'])
00307             $varlst->addflag("$key='".md5($val['value'])."'");
00308           break;
00309         default:
00310           $varlst->addflag("$key='{$val['value']}'");
00311         }
00312       }
00313     }
00314     reset($this->vars);
00315 
00316     if (isset($this->id)) {
00317       $sql = "update {$this->table} set {$varlst->value} where {$this->idfield}='{$this->id}'";
00318       if ($this->wheres)
00319         $sql .= " AND " . join(" AND ", $this->wheres);
00320     } else {
00321       if (!$this->autoinc && !$this->idedit) {
00322         list($this->id) = mysql_fetch_row($this->dbh->query("select MAX({$this->idfield})+1 from {$this->table}"));
00323         $varlst->addflag("{$this->idfield}='{$this->id}'");
00324       }
00325       $sql = "insert into {$this->table} set {$varlst->value}";
00326     }
00327     $this->dbh->query($sql);
00328 
00329     // retrieve the insertion id
00330     if ($this->idedit) { 
00331       $this->id = $this->vars[$this->idfield]['value'];
00332     } else if ($this->autoinc && !isset($this->id)) {
00333       $this->id = $this->dbh->insert_id();
00334     }
00335   }
00336 
00337 
00342   function make_join_flag($val) {
00343     if ($val['table'] == $this->table) {
00344       // this field is local, no join clause needed
00345       return "";
00346     } else {
00347       // not a local field, we need a join clause
00348       $tbl_key = $val['table'];
00349       $tbl_val = $this->jtables[$tbl_key];
00350       $flg = "left join $tbl_key on {$this->table}.{$this->idfield}={$tbl_key}.{$tbl_val['joinid']}";
00351       if ($tbl_val['joinextra'])
00352         $flg .= " and {$tbl_val['joinextra']}";
00353       return $flg;
00354     }
00355   }
00356 
00357 
00364   function make_select($list,&$num) {
00365     if ($list) {
00366       $varlst = new flagset("{$this->table}.{$this->idfield}");
00367       $orderby = "";
00368       $num = $this->idsum ? 1 : 0;
00369     } else {
00370       $varlst = new flagset();
00371     }
00372 
00373     $joinlst = new flagset();
00374     // run over all the variables
00375     foreach ($this->vars as $key => $val) {
00376       // if we are listing the summary, we want only the variables
00377       // where ['sum'] is true.
00378       if (!$list || $val['sum']) {
00379         // type conversion
00380         if ($val['type'] == "timestamp")
00381           $varlst->addflag("UNIX_TIMESTAMP({$val['table']}.{$val['field']}) as $key");
00382         else
00383           $varlst->addflag("{$val['table']}.{$val['field']} as $key");
00384 
00385         // do we need a join clause?
00386         if ($flag = $this->make_join_flag($val))
00387           $joinlst->addflag($flag);
00388 
00389         // if we are listing the summary, we want an order clause
00390         if ($list) {
00391           if (!$orderby) $orderby = "order by $key";
00392           $num++;
00393         }
00394       }
00395     }
00396 
00397     reset($this->vars);
00398 
00399     $sql = "select {$varlst->value} from {$this->table} {$joinlst->value}";
00400 
00401     # if we are in edit mode, add a WHERE condition
00402     if (!$list)
00403       $this->add_where_condition("{$this->table}.{$this->idfield}='$num'");
00404 
00405     # sum up all the WHERE conditions
00406     if ($this->wheres)
00407       $sql .= " where " . join(" AND ", $this->wheres);
00408 
00409     # add order by clause
00410     if ($list)
00411       $sql .= " $orderby";
00412    
00413     return $sql;
00414   }
00415 
00416 
00422   function set_maxrows($maxrows)
00423   {
00424     // check we were given a zero or positive number
00425     if ($maxrows < 0) {
00426       trigger_error("You cannot pass a negative number ($maxrows) to set_maxrows!");
00427       return;
00428     }
00429     
00430     $this->maxrows = $maxrows;
00431   }
00432   
00440   function run(&$page,$outputvar='',$template='') {
00441     global $globals;
00442 
00443     $action = clean_request('action');
00444     $page->assign('table',$this->table);
00445 
00446     switch($action) {
00447     case "edit":
00448       // check we are not in read-only mode
00449       if ($this->readonly) die("Sorry, this table is read-only.");
00450         
00451       // if this is an existing entry, retrieve it
00452       if (clean_request("{$this->prefix}id") != '') {
00453         $this->from_db(clean_request("{$this->prefix}id"));
00454         $page->assign('id',$this->id);
00455       }
00456       
00457       // remove the uneditable fields
00458       #foreach ($this->vars as $key => $val) {
00459       #if (!$val['edit'])
00460       #  unset($this->vars[$key]);
00461       #}
00462       reset($this->vars);
00463      
00464       $page->assign('doedit',true);
00465       break;
00466     case "update":
00467       // check we are not in read-only mode
00468       if ($this->readonly) die("Sorry, this table is read-only.");
00469 
00470       $this->from_request();
00471       $this->to_db();
00472       break;
00473     case "del":
00474       // check we are not in read-only mode
00475       if ($this->readonly) die("Sorry, this table is read-only.");
00476       
00477       $this->delete_db(clean_request("{$this->prefix}id"));
00478       break;
00479     }
00480 
00481     // if we are not in editor mode, display the list
00482     if ($action != "edit") {
00483       $ncols = 0;
00484       $sql = $this->make_select(true,$ncols);
00485       $res = $this->dbh->query($sql);
00486       $page->assign('ncols',$ncols);
00487 
00488       // determine start and stop of displayed results
00489       $p_total = mysql_num_rows($res);
00490       $p_start = isset($_REQUEST['start']) ? $_REQUEST['start'] : 0;
00491       $p_stop = $this->maxrows ? min($p_total, $p_start + $this->maxrows) : $p_total;
00492       $counter = 0;
00493 
00494       while (($counter < $p_stop) and ($myarr = mysql_fetch_assoc($res))) {
00495         if ($counter >= $p_start) {
00496           $actions = array();
00497           foreach ($this->actions as $myaction) {
00498             $url = $myaction['url'];
00499             foreach ($myarr as $key=>$val)
00500               $url = str_replace("%$key%", $val, $url);
00501 
00502             array_push($actions, array($myaction['text'],$url));
00503           }
00504           $page->append('rows', array($myarr[$this->idfield], $myarr, $actions) );
00505         }
00506         $counter++;
00507       }
00508       mysql_free_result($res);
00509 
00510       // smarty assignements for prev / next page links
00511       $page->assign('p_prev', $p_start ? max($p_start - $this->maxrows, 0) : -1);
00512       $page->assign('p_next', ($p_stop < $p_total) ? $p_stop  : - 1 );
00513       $page->assign('p_total', $p_total);
00514      
00515     }
00516 
00517     $page->assign('vars',$this->vars);
00518     $page->assign('prefix',$this->prefix);
00519     $page->assign('idfield',$this->idfield);
00520     $page->assign('idsum',$this->idsum);
00521     $page->assign('readonly',$this->readonly);
00522     if ($this->readonly && ($this->actions == array()))
00523       $page->assign('hideactions', 1);
00524     $page->assign('table_class', $this->table_class);
00525     $page->assign('table_style', $this->table_style);
00526       
00527     // translations
00528     $page->assign('msg_previous_page', __("previous page"));
00529     $page->assign('msg_next_page', __("next page"));
00530     $page->assign('msg_id', __("id"));
00531     $page->assign('msg_action', __("action"));
00532     $page->assign('msg_create', __("create"));
00533     $page->assign('msg_delete', __("delete"));
00534     $page->assign('msg_edit', __("edit"));
00535     $page->assign('msg_new_entry', __("new entry"));
00536     $page->assign('msg_existing_entry', __("existing entry"));
00537     $page->assign('msg_no_change', __("(blank = no change)"));
00538     $page->assign('msg_back', __("back"));
00539     $page->assign('msg_confirm_delete', 
00540                   __("You are about to delete this entry. Do you want to proceed?"));
00541     $page->assign('msg_submit', __("Submit"));
00542     
00543     // if requested, assign the content to be displayed
00544     if (!empty($outputvar)) {
00545       if (empty($template))
00546         $template = $globals->libroot."/templates/table-editor.tpl";
00547       $page->assign($outputvar, $page->fetch($template));
00548     }
00549   }
00550 
00551 }
00552 
00553 ?>

Generated on Fri Jan 11 01:20:08 2008 for Diogenes by  doxygen 1.5.1