Source for file joinmatrix.php

Documentation is available at joinmatrix.php

  1. <?php
  2. /**
  3. * Similar to JoinData, but presents the options in a matrix not a list
  4. *
  5. @author    Stuart Prescott
  6. @copyright  Copyright Stuart Prescott
  7. @license    http://opensource.org/licenses/gpl-license.php GNU Public License
  8. @version    $Id$
  9. @package    Bumblebee
  10. @subpackage FormsLibrary
  11. */
  12.  
  13. /** Load ancillary functions */
  14. require_once 'inc/typeinfo.php';
  15.  
  16. /** parent object */
  17. require_once 'field.php';
  18. /** uses ID field objects */
  19. require_once 'idfield.php';
  20. /** database row manipulation object */
  21. require_once 'dbrow.php';
  22. /** connect to database */
  23. require_once 'inc/db.php';
  24.  
  25. /**
  26. * Similar to JoinData, but presents the options in a matrix not a list
  27. *
  28. * The entries in one table can be a matrix with the coordinates from two others
  29. *
  30. * We respect the 'field' interface while overriding pretty much all of it.
  31. *
  32. * Typical usage:<code>
  33. *   // jointable has structure: key1 key2 field1 field2 field3...
  34. *   // where key1 is the id key of table1 and key2 is the id key for table2.
  35. *   // we will display field* in rows for each key2 for a given key1
  36. *   $f = new JoinMatrix('jointable', 'jtid'
  37.                       'key1', 'id1', 'table1',
  38.                       'key2', 'id2', 'table2', $name, $longname, $description);
  39. *   $key1 = new TextField('key1', 'label1');
  40. *   $key1->setFormat('id', '%s (%s)', array('name', 'longname'));
  41. *   $key2 = new TextField('key2', 'label2');
  42. *   $f->addKeys($key1, $key2);
  43. *   $f1 = new TextField('field1', 'label');
  44. *   $f->addElement($f1);
  45. *   $f2 = new TextField('field2', 'label');
  46. *   $f->addElement($f2);
  47. *   $f->setKey($val);
  48. *   </code>
  49. @package    Bumblebee
  50. @subpackage FormsLibrary
  51. */
  52. class JoinMatrix extends Field {
  53.   /** @var string   name of the join table (table has columns of form (LeftID, RightID) to join Left and Right tables */
  54.   var $joinTable;
  55.   /** @var string  column in the join table that is the ID field for entries (unused) */
  56.   var $jtIdField;
  57.  
  58.   /** @var string   value of the key for the left table that should be constant */
  59.   var $jtConstKeyId;
  60.   /** @var string   column name in the join table for the column with keys/Ids from the left table (id will be constant throughout the process) */
  61.   var $jtConstKeyCol;
  62.   /** @var string   name of the left table */
  63.   var $table1;
  64.   /** @var string   column name of ID column in the left table */
  65.   var $table1IdCol;
  66.   /** @var Field    representation of the key for the left table (unused?)  */
  67.   var $key1;
  68.   /** @var array    list of Field objects to be included along the header of the matrix */
  69.   var $header1 = array();
  70.  
  71.   /** @var string   column name in the join table for the column with keys/Ids from the right table (id will vary throughout the process) */
  72.   var $jtVarKeyCol;
  73.   /** @var string   name of the right table */
  74.   var $table2;
  75.   /** @var string   column name of ID column in the right table */
  76.   var $table2IdCol;
  77.   /** @var Field    representation of the key for the right table  */
  78.   var $key2;
  79.  
  80.   /** @var DBRow    prototype DBRow object that is replicated for each entry in the join table (1:many join) */
  81.   var $protoRow;
  82.   /** @var array    list of DBRow objects for each row returned in a 1:many join */
  83.   var $rows;
  84.   /** @var integer  number of rows in the join */
  85.   var $number = 0;
  86.   /** @var string   number of columns that this field should span in the table */
  87.   var $colspan = 1;
  88.   /** @var array    list of id-pairs in the join table */
  89.   var $table2All;
  90.   /** @var integer  number of fields that are also in the join table */
  91.   var $numFields = 0;
  92.   /** @var boolean  SQL errors should be fatal (die()) */
  93.   var $fatal_sql = 0;
  94.  
  95.   /**
  96.   *  Create a new joinmatrix object
  97.   *
  98.   * @param string $jointable    see $this->joinTable
  99.   * @param string $jtIdField    (presently unused)
  100.   * @param string $jtConstKeyCol  see $this->jtConstKeyCol
  101.   * @param string $table1IdCol  see $this->table1IdCol
  102.   * @param string $table1       see $this->table1
  103.   * @param string $jtVarKeyCol  see $this->jtVarKeyCol
  104.   * @param string $table2IdCol  see $this->table2IdCol
  105.   * @param string $table2       see $this->table2
  106.   * @param string $name       the name of the field (db name, and html field name
  107.   * @param string $longname    used in the html label
  108.   * @param string $description  used in the html title or longdesc for the field
  109.   */
  110.   function JoinMatrix($joinTable$jtIdField,
  111.                       $jtConstKeyCol$table1IdCol$table1,
  112.                       $jtVarKeyCol,   $table2IdCol$table2,
  113.                       $name$longname$description=''{
  114.     parent::Field($name$longname$description);
  115.     //$this->DEBUG=10;
  116.     $this->joinTable     = $joinTable;
  117.     $this->jtIdField     = $jtIdField;
  118.     $this->jtConstKeyCol = $jtConstKeyCol;
  119.     $this->table1IdCol   = $table1IdCol;
  120.     $this->table1        = $table1;
  121.     $this->jtVarKeyCol   = $jtVarKeyCol;
  122.     $this->table2IdCol   = $table2IdCol;
  123.     $this->table2        = $table2;
  124.     $this->protoRow = new DBRow($this->joinTable-1);
  125.     $id new IdField($jtIdField);
  126.     $this->protoRow->addElement($id);
  127.     $k1 new IdField($jtConstKeyCol);
  128.     $this->protoRow->addElement($k1);
  129.     $k2 new IdField($jtVarKeyCol);
  130.     $this->protoRow->addElement($k2);
  131.     $this->protoRow->editable 1;
  132.     $this->protoRow->autonumbering = 1;
  133.     $this->header2 array();
  134.     $this->rows = array();
  135.     $this->notifyIdChange = 1;
  136.   }
  137.  
  138.   /**
  139.   * Add key Fields for the id columns in the left and right tables
  140.   *
  141.   * @param Field $key1   key field for left table (unused?)
  142.   * @param Field $key2   key field for right table
  143.   */
  144.   function addKeys($key1$key2{
  145.     $this->key1 = $key1;
  146.     //$this->key1->namebase = $this->table1;
  147.     $this->key2 = $key2;
  148.     //$this->key2->namebase = $this->table2;
  149.   }
  150.  
  151.   /**
  152.   * set the id that this object will match in the left table
  153.   *
  154.   * @param integer   $id    id from the left table to match
  155.   */
  156.   function setKey($id{
  157.     $this->jtConstKeyId = $id;
  158.     $this->_fillFromProto();
  159.     //preDump($this);
  160.   }
  161.  
  162.   /**
  163.   * populates the matrix from the database
  164.   *
  165.   * @global string prefix to table names
  166.   */
  167.   function _populateList({
  168.     global $TABLEPREFIX;
  169.     $this->table2All = array();
  170.     $q 'SELECT '.$this->table2IdCol.', '.$this->key2->name
  171.         .' FROM '.$TABLEPREFIX.$this->table2.' AS '.$this->table2
  172.         .' ORDER BY '.$this->key2->name;
  173.     $sql db_get($q$this->fatal_sql);
  174.     if (db_num_rows($sql)==0{
  175.       $this->number = 0;
  176.       return;
  177.     else {
  178.       while ($g db_fetch_array($sql)) {
  179.         $this->table2All[$g;
  180.       }
  181.     }
  182.     $this->number = count($this->table2All);
  183.   }
  184.  
  185.   /**
  186.   * add a field to the join table
  187.   * Field will appear in each row returned from the join table
  188.   * @param Field  $field            the field to be added
  189.   * @param string  $groupValidTest  data validation routine for this field
  190.   */
  191.   function addElement($field{
  192.     $this->protoRow->addElement($field);
  193.     $this->header1[$field;
  194.     $this->numFields++;
  195.   }
  196.  
  197.   /**
  198.   * Create a new row from the protorow for storing data
  199.   * @param integer  $rowNum   number of this row (used as unique identifier in the namebase)
  200.   */
  201.   function _createRow($rowNum{
  202.     $this->rows[$rowNumclone($this->protoRow);
  203.     $this->rows[$rowNum]->setNamebase($this->name.'-'.$rowNum.'-');
  204.   }
  205.  
  206.   /**
  207.   * Fill from the database one row at a time
  208.   */
  209.   function _fillFromProto({
  210.     $this->_populateList();
  211.     $this->log('Creating rows: '.$this->number);
  212.     for ($i=0$i $this->number$i++{
  213.       $this->_createRow($i);
  214.       $this->rows[$i]->fields[$this->jtConstKeyCol]->value $this->jtConstKeyId;
  215.       $this->rows[$i]->fields[$this->jtVarKeyCol]->value $this->table2All[$i][$this->table2IdCol];
  216.       $this->rows[$i]->ignoreId true;
  217.       $this->rows[$i]->recStart $i;
  218.       $this->rows[$i]->restriction =
  219.                       $this->jtVarKeyCol   .'='qw($this->table2All[$i][$this->table2IdCol])
  220.              .' AND '.$this->jtConstKeyCol .'='qw($this->jtConstKeyId);
  221.       $this->rows[$i]->fill();
  222. //       $this->rows[$i]->insertRow = ! ($this->rows[$i]->fields[$this->table2IdCol]->value > 0);
  223.     }
  224.   }
  225.  
  226.   function display({
  227.     return $this->selectable();
  228.   }
  229.  
  230.   function selectable({
  231.     $eol "\n";
  232.     $t '<table><tr><td></td>'.$eol;
  233.     for ($field=0$field $this->numFields$field++{
  234.       $t .= '<td title="'.$this->header1[$field]->description.'">'
  235.               .$this->header1[$field]->longname.'</td>'.$eol;
  236.     }
  237.     $t .= '</tr>'.$eol;
  238.     for ($row=0$row<$this->number$row++{
  239.       $t .= '<tr><td>'.$this->table2All[$row][$this->key2->name]
  240.            .$this->rows[$row]->fields[$this->jtVarKeyCol]->hidden()
  241.            .'</td>'.$eol;
  242.       for ($field=0$field $this->numFields$field++{
  243.         $f =$this->rows[$row]->fields[$this->header1[$field]->name];
  244.         if ($this->editable{
  245.           $ft $f->selectable();
  246.         else {
  247.           $ft $f->selectedValue();
  248.         }
  249.         $t .= '<td title="'.$f->description.'">'.$ft.'</td>'.$eol;
  250.       }
  251.       $t .= '</tr>'.$eol;
  252.     }
  253.     $t .= '</table>';
  254.     return $t;
  255.   }
  256.  
  257.   function selectedValue({
  258.     $editable $this->editable;
  259.     $this->editable = 0;
  260.     $t $this->selectable();
  261.     $this->editable = $editable;
  262.     return $t;
  263.   }
  264.  
  265.   function displayInTable($cols=3{
  266.     //check how many fields we need to have (again) as we might have to show more this time around.
  267.     //$cols += $this->colspan;
  268.     $eol "\n";
  269.     $t '<tr><td colspan="'.($cols+$this->colspan).'" title="'.$this->description.'">'
  270.                       .$this->longname.'</td></tr>'
  271.         .'<tr><td colspan="'.$this->colspan.'">'.$eol;
  272.     $t .= $this->selectable();
  273.     for ($i=0$i<$cols-2$i++{
  274.       $t .= '<td></td>';
  275.     }
  276.     $t .= '</tr>'.$eol;
  277.     return $t;
  278.   }
  279.  
  280.   function update($data{
  281.     for ($i=0$i $this->number$i++{
  282.       $rowchanged $this->rows[$i]->update($data);
  283.       if ($rowchanged{
  284.         $this->log('JoinData-Row '.$i.' has changed.');
  285.         foreach (array_keys($this->rows[$i]->fieldsas $k{
  286.           #$this->rows[$i]->fields[$this->jtRightIDCol]->changed = $rowchanged;
  287.           #if ($v->name != $this->jtRightIDCol && $v->name != $this->jtLeftIDCol) {
  288.             $this->rows[$i]->fields[$k]->changed $rowchanged;
  289.           #}
  290.         }
  291.       }
  292.       $this->changed += $rowchanged;
  293.     }
  294.     $this->log('Overall JoinData row changed='.$this->changed);
  295.     return $this->changed;
  296.   }
  297.  
  298.   /**
  299.   * trip the complex field within us to sync(), which allows us
  300.   * to then know our actual value (at last).
  301.   *
  302.   * @param $name   (unused)
  303.   * @param $force  (unused)
  304.   */
  305.   function sqlSetStr($name=''$force=false{
  306.     //$this->DEBUG=10;
  307.     #echo "JoinData::sqlSetStr";
  308.     $this->_joinSync();
  309.     //We return an empty string as this is only a join table entry,
  310.     //so it has no representation within the row itself.
  311.     return '';
  312.   }
  313.  
  314.   /**
  315.   * synchronise the join table
  316.   */
  317.   function _joinSync({
  318.     for ($i=0$i $this->number$i++{
  319.       #echo "before sync row $i oob='".$this->oob_status."' ";
  320.       $this->changed += $this->rows[$i]->changed;
  321.       $this->log('JoinData::_joinSync(): Syncing row '.$i);
  322.       $this->oob_status |= $this->rows[$i]->sync();
  323.       $this->oob_errorMessage .= $this->rows[$i]->errorMessage;
  324.       $this->changed += $this->rows[$i]->changed;
  325.       #echo " after sync row $i oob='".$this->oob_status."'";
  326.     }
  327.   }
  328.  
  329.  
  330.   /**
  331.   * override the isValid method of the Field class, using the
  332.   * checkValid method of each member row completed as well as
  333.   * cross checks on other fields.
  334.   *
  335.   * @return boolean data is valid
  336.   */
  337.   function isValid({
  338.     $this->isValid = 1;
  339.     for ($i=0$i $this->number$i++{
  340.       $this->isValid = $this->rows[$i]->checkValid(&& $this->isValid;
  341.     }
  342.     return $this->isValid;
  343.   }
  344.  
  345.   /**
  346.   * Change the Id value of each row
  347.   */
  348.   function idChange($newId{
  349.     for ($i=0$i $this->number$i++{
  350.       $this->rows[$i]->setId($newId);
  351.     }
  352.   }
  353.  
  354.   /**
  355.   * Set the name base of the rows
  356.   */
  357.   function setNamebase($namebase=''{
  358.     for ($i=0$i $this->number$i++{
  359.       $this->rows[$i]->setNamebase($namebase);
  360.     }
  361.     $this->protoRow->setNamebase($namebase);
  362.   }
  363.  
  364.   /**
  365.   * set whether each row is editable
  366.   */
  367.   function setEditable($editable=false{
  368.     for ($i=0$i $this->number$i++{
  369.       $this->rows[$i]->setEditable($editable);
  370.     }
  371.     $this->protoRow->setEditable($editable);
  372.   }
  373.  
  374. // class JoinMatrix
  375.  
  376. ?>

Documentation generated on Tue, 06 Mar 2007 10:01:43 +0000 by phpDocumentor 1.3.0