DB_Table
[ class tree: DB_Table ] [ index: DB_Table ] [ all elements ]

Source for file Table.php

Documentation is available at Table.php

  1. <?php
  2.  
  3. /**
  4. * Error code at instantiation time when the first parameter to the
  5. * constructor is not a PEAR DB object.
  6. */
  7. define('DB_TABLE_ERR_NOT_DB_OBJECT',    -1);
  8.  
  9. /**
  10. * Error code at instantiation time when the PEAR DB $phptype is not
  11. * supported by DB_Table.
  12. */
  13. define('DB_TABLE_ERR_PHPTYPE',          -2);
  14.  
  15. /**
  16. * Error code when you call select() or selectResult() and the first
  17. * parameter does not match any of the $this->sql keys.
  18. */
  19. define('DB_TABLE_ERR_SQL_UNDEF',        -3);
  20.  
  21. /**
  22. * Error code when you try to insert data to a column that is not in the
  23. * $this->col array.
  24. */
  25. define('DB_TABLE_ERR_INS_COL_NOMAP',    -4);
  26.  
  27. /**
  28. * Error code when you try to insert data, and that data does not have a
  29. * column marked as 'require' in the $this->col array.
  30. */
  31. define('DB_TABLE_ERR_INS_COL_REQUIRED'-5);
  32.  
  33. /**
  34. * Error code when auto-validation fails on data to be inserted.
  35. */
  36. define('DB_TABLE_ERR_INS_DATA_INVALID'-6);
  37.  
  38. /**
  39. * Error code when you try to update data to a column that is not in the
  40. * $this->col array.
  41. */
  42. define('DB_TABLE_ERR_UPD_COL_NOMAP',    -7);
  43.  
  44. /**
  45. * Error code when you try to update data, and that data does not have a
  46. * column marked as 'require' in the $this->col array.
  47. */
  48. define('DB_TABLE_ERR_UPD_COL_REQUIRED'-8);
  49.  
  50. /**
  51. * Error code when auto-validation fails on update data.
  52. */
  53. define('DB_TABLE_ERR_UPD_DATA_INVALID'-9);
  54.  
  55. /**
  56. * Error code when you use a create() flag that is not recognized (must
  57. * be 'safe', 'drop', or boolean false.
  58. */
  59. define('DB_TABLE_ERR_CREATE_FLAG',      -10);
  60.  
  61. /**
  62. * Error code at create() time when you define an index in $this->idx
  63. * that has no columns.
  64. */
  65. define('DB_TABLE_ERR_IDX_NO_COLS',      -11);
  66.  
  67. /**
  68. * Error code at create() time when you define an index in $this->idx
  69. * that refers to a column that does not exist in the $this->col array.
  70. */
  71. define('DB_TABLE_ERR_IDX_COL_UNDEF',    -12);
  72.  
  73. /**
  74. * Error code at create() time when you define a $this->idx index type
  75. * that is not recognized (must be 'normal' or 'unique').
  76. */
  77. define('DB_TABLE_ERR_IDX_TYPE',         -13);
  78.  
  79. /**
  80. * Error code at create() time when you have an error in a 'char' or
  81. * 'varchar' definition in $this->col (usually because 'size' is wrong).
  82. */
  83. define('DB_TABLE_ERR_DECLARE_STRING',   -14);
  84.  
  85. /**
  86. * Error code at create() time when you have an error in a 'decimal'
  87. * definition (usually becuase the 'size' or 'scope' are wrong).
  88. */
  89. define('DB_TABLE_ERR_DECLARE_DECIMAL',  -15);
  90.  
  91. /**
  92. * Error code at create() time when you define a column in $this->col
  93. * with an unrecognized 'type'.
  94. */
  95. define('DB_TABLE_ERR_DECLARE_TYPE',     -16);
  96.  
  97. /**
  98. * Error code at validation time when a column in $this->col has an
  99. * unrecognized 'type'.
  100. */
  101. define('DB_TABLE_ERR_VALIDATE_TYPE',    -17);
  102.  
  103. /**
  104. * Error code at create() time when you define a column in $this->col
  105. * with an invalid column name (usually because it's a reserved keyword).
  106. */
  107. define('DB_TABLE_ERR_DECLARE_COLNAME',  -18);
  108.  
  109. /**
  110. * Error code at create() time when you define an index in $this->idx
  111. * with an invalid index name (usually because it's a reserved keyword).
  112. */
  113. define('DB_TABLE_ERR_DECLARE_IDXNAME',  -19);
  114.  
  115.  
  116. /**
  117. * The PEAR class for errors
  118. */
  119. require_once 'PEAR.php';
  120.  
  121. /**
  122. * The Date class for recasting date and time values
  123. */
  124. require_once 'Date.php';
  125.  
  126.  
  127. /**
  128. * DB_Table supports these RDBMS engines and their various native data
  129. * types; we need these here instead of in Manager.php becuase the
  130. * initial array key tells us what databases are supported.
  131. */
  132. $GLOBALS['_DB_TABLE']['type'= array(
  133.     'fbsql' => array(
  134.         'boolean'   => 'DECIMAL(1,0)',
  135.         'char'      => 'CHAR',
  136.         'varchar'   => 'VARCHAR',
  137.         'smallint'  => 'SMALLINT',
  138.         'integer'   => 'INTEGER',
  139.         'bigint'    => 'LONGINT',
  140.         'decimal'   => 'DECIMAL',
  141.         'single'    => 'REAL',
  142.         'double'    => 'DOUBLE PRECISION',
  143.         'clob'      => 'CLOB',
  144.         'date'      => 'CHAR(10)',
  145.         'time'      => 'CHAR(8)',
  146.         'timestamp' => 'CHAR(19)'
  147.     ),
  148.     'mssql' => array(
  149.         'boolean'   => 'DECIMAL(1,0)',
  150.         'char'      => 'CHAR',
  151.         'varchar'   => 'VARCHAR',
  152.         'smallint'  => 'SMALLINT',
  153.         'integer'   => 'INTEGER',
  154.         'bigint'    => 'BIGINT',
  155.         'decimal'   => 'DECIMAL',
  156.         'single'    => 'REAL',
  157.         'double'    => 'FLOAT',
  158.         'clob'      => 'TEXT',
  159.         'date'      => 'CHAR(10)',
  160.         'time'      => 'CHAR(8)',
  161.         'timestamp' => 'CHAR(19)'
  162.     ),
  163.     'mysql' => array(
  164.         'boolean'   => 'DECIMAL(1,0)',
  165.         'char'      => 'CHAR',
  166.         'varchar'   => 'VARCHAR',
  167.         'smallint'  => 'SMALLINT',
  168.         'integer'   => 'INTEGER',
  169.         'bigint'    => 'BIGINT',
  170.         'decimal'   => 'DECIMAL',
  171.         'single'    => 'FLOAT',
  172.         'double'    => 'DOUBLE',
  173.         'clob'      => 'LONGTEXT',
  174.         'date'      => 'CHAR(10)',
  175.         'time'      => 'CHAR(8)',
  176.         'timestamp' => 'CHAR(19)'
  177.     ),
  178.     'oci8' => array(
  179.         'boolean'   => 'NUMBER(1)',
  180.         'char'      => 'CHAR',
  181.         'varchar'   => 'VARCHAR2',
  182.         'smallint'  => 'NUMBER(6)',
  183.         'integer'   => 'NUMBER(11)',
  184.         'bigint'    => 'NUMBER(19)',
  185.         'decimal'   => 'NUMBER',
  186.         'single'    => 'REAL',
  187.         'double'    => 'DOUBLE PRECISION',
  188.         'clob'      => 'CLOB',
  189.         'date'      => 'CHAR(10)',
  190.         'time'      => 'CHAR(8)',
  191.         'timestamp' => 'CHAR(19)'
  192.     ),
  193.     'pgsql' => array(
  194.         'boolean'   => 'DECIMAL(1,0)',
  195.         'char'      => 'CHAR',
  196.         'varchar'   => 'VARCHAR',
  197.         'smallint'  => 'SMALLINT',
  198.         'integer'   => 'INTEGER',
  199.         'bigint'    => 'BIGINT',
  200.         'decimal'   => 'DECIMAL',
  201.         'single'    => 'REAL',
  202.         'double'    => 'DOUBLE PRECISION',
  203.         'clob'      => 'TEXT',
  204.         'date'      => 'CHAR(10)',
  205.         'time'      => 'CHAR(8)',
  206.         'timestamp' => 'CHAR(19)'
  207.     ),
  208.     'sqlite' => array(
  209.         'boolean'   => 'BOOLEAN',
  210.         'char'      => 'CHAR',
  211.         'varchar'   => 'VARCHAR',
  212.         'smallint'  => 'SMALLINT',
  213.         'integer'   => 'INTEGER',
  214.         'bigint'    => 'BIGINT',
  215.         'decimal'   => 'NUMERIC',
  216.         'single'    => 'FLOAT',
  217.         'double'    => 'DOUBLE',
  218.         'clob'      => 'CLOB',
  219.         'date'      => 'DATE',
  220.         'time'      => 'TIME',
  221.         'timestamp' => 'TIMESTAMP'
  222.     )
  223. );
  224.  
  225.  
  226. /**
  227. * US-English error messages.  DB_Table has no other embedded strings, so
  228. * if you want to internationalize, you can modify these for your
  229. * language.
  230. */
  231. $GLOBALS['_DB_TABLE']['error'= array(
  232.     DB_TABLE_ERR_NOT_DB_OBJECT       => 'First parameter must be a DB object',
  233.     DB_TABLE_ERR_PHPTYPE             => 'DB phptype not supported',
  234.     DB_TABLE_ERR_SQL_UNDEF           => 'Select key not in map',
  235.     DB_TABLE_ERR_INS_COL_NOMAP       => 'Insert column not in map',
  236.     DB_TABLE_ERR_INS_COL_REQUIRED    => 'Insert data must be set and non-null for column',
  237.     DB_TABLE_ERR_INS_DATA_INVALID    => 'Insert data not valid for column',
  238.     DB_TABLE_ERR_UPD_COL_NOMAP       => 'Update column not in map',
  239.     DB_TABLE_ERR_UPD_COL_REQUIRED    => 'Update column must be set and non-null',
  240.     DB_TABLE_ERR_UPD_DATA_INVALID    => 'Update data not valid for column',
  241.     DB_TABLE_ERR_CREATE_FLAG         => 'Create flag not valid',
  242.     DB_TABLE_ERR_IDX_NO_COLS         => 'No columns for index',
  243.     DB_TABLE_ERR_IDX_COL_UNDEF       => 'Column not in map for index',
  244.     DB_TABLE_ERR_IDX_TYPE            => 'Type not valid for index',
  245.     DB_TABLE_ERR_DECLARE_STRING      => 'String column declaration not valid',
  246.     DB_TABLE_ERR_DECLARE_DECIMAL     => 'Decimal column declaration not valid',
  247.     DB_TABLE_ERR_DECLARE_TYPE        => 'Column type not valid',
  248.     DB_TABLE_ERR_VALIDATE_TYPE       => 'Cannot validate for unknown type on column',
  249.     DB_TABLE_ERR_DECLARE_COLNAME     => 'Column name not valid',
  250.     DB_TABLE_ERR_DECLARE_IDXNAME     => 'Index name not valid',
  251.     DB_TABLE_ERR_DECLARE_TYPE        => 'Column type not valid'
  252. );
  253.  
  254.  
  255. /**
  256. * DB_Table is a database API and data type SQL abstraction class.
  257. * DB_Table provides database API abstraction, data type abstraction,
  258. * automated SELECT, INSERT, and UPDATE queries, automated table
  259. * creation, automated validation of inserted/updated column values,
  260. * and automated creation of QuickForm elemnts based on the column
  261. * definitions.
  262. * $Id: Table.php,v 1.41 2004/04/20 15:17:16 pmjones Exp $
  263. *
  264. @author Paul M. Jones <pmjones@ciaweb.net>
  265. @version 0.17 alpha
  266. *
  267. @package DB_Table
  268. */
  269.  
  270. class DB_Table {
  271.     
  272.     
  273.     /**
  274.     * 
  275.     * The PEAR DB object that connects to the database.
  276.     * 
  277.     * @access public
  278.     * 
  279.     * @var object 
  280.     * 
  281.     */
  282.     
  283.     var $db = null;
  284.     
  285.     
  286.     /**
  287.     * 
  288.     * The table or view in the database to which this object binds.
  289.     * 
  290.     * @access public
  291.     * 
  292.     * @var string 
  293.     * 
  294.     */
  295.     
  296.     var $table = null;
  297.     
  298.     
  299.     /**
  300.     * 
  301.     * Associative array of column definitions.
  302.     * 
  303.     * @access public
  304.     * 
  305.     * @var array 
  306.     * 
  307.     */
  308.     
  309.     var $col = array();
  310.     
  311.     
  312.     /**
  313.     * 
  314.     * Associative array of index definitions.
  315.     * 
  316.     * @access public
  317.     * 
  318.     * @var array 
  319.     * 
  320.     */
  321.     
  322.     var $idx = array();
  323.     
  324.     
  325.     /**
  326.     * 
  327.     * Baseline SQL SELECT mappings for select() and selectResult().
  328.     * 
  329.     * @access public
  330.     * 
  331.     * @var array 
  332.     * 
  333.     */
  334.     
  335.     var $sql = array();
  336.     
  337.     
  338.     /**
  339.     * 
  340.     * Whether or not to automatically validate data at insert-time.
  341.     * 
  342.     * @access private
  343.     * 
  344.     * @var bool 
  345.     * 
  346.     */
  347.     
  348.     var $_valid_insert = true;
  349.     
  350.     
  351.     /**
  352.     * 
  353.     * Whether or not to automatically validate data at update-time.
  354.     * 
  355.     * @access private
  356.     * 
  357.     * @var bool 
  358.     * 
  359.     */
  360.     
  361.     var $_valid_update = true;
  362.     
  363.     
  364.     /**
  365.     * 
  366.     * When calling select() and selectResult(), use this fetch mode (usually
  367.     * a DB_FETCHMODE_* constant).  If null, uses whatever is set in the $db
  368.     * PEAR DB object.
  369.     * 
  370.     * @access public
  371.     * 
  372.     * @var int 
  373.     * 
  374.     */
  375.     
  376.     var $fetchmode = null;
  377.     
  378.     
  379.     /**
  380.     * 
  381.     * When fetchmode is DB_FETCHMODE_OBJECT, use this class for each
  382.     * returned row.  If null, uses whatever is set in the $db
  383.     * PEAR DB object.
  384.     * 
  385.     * @access public
  386.     * 
  387.     * @var string 
  388.     * 
  389.     */
  390.     
  391.     var $fetchmode_object_class = null;
  392.     
  393.     
  394.     /**
  395.     * 
  396.     * If there is an error on instantiation, this captures that error.
  397.     *
  398.     * This property is used only for errors encountered in the constructor
  399.     * at instantiation time.  To check if there was an instantiation error...
  400.     *
  401.     * <code>
  402.     * $obj =& new DB_Table();
  403.     * if ($obj->error) {
  404.     *     // ... error handling code here ...
  405.     * }
  406.     * </code>
  407.     * 
  408.     * @var object PEAR_Error 
  409.     * 
  410.     */
  411.     
  412.     var $error = null;
  413.     
  414.     
  415.     /**
  416.     * 
  417.     * Specialized version of throwError() modeled on PEAR_Error.
  418.     * 
  419.     * Throws a PEAR_Error with a DB_Table error message based on a
  420.     * DB_Table constant error code.
  421.     * 
  422.     * @static
  423.     * 
  424.     * @access public
  425.     * 
  426.     * @param string $code A DB_Table error code constant.
  427.     * 
  428.     * @param string $extra Extra text for the error (in addition to the
  429.     *  regular error message).
  430.     * 
  431.     * @return object PEAR_Error 
  432.     * 
  433.     */
  434.     
  435.     function &throwError($code$extra = null)
  436.     {
  437.         // get the error message text based on the error code
  438.         $text $GLOBALS['_DB_TABLE']['error'][$code];
  439.         
  440.         // add any additional error text
  441.         if ($extra{
  442.             $text .= ' ' $extra;
  443.         }
  444.         
  445.         // done!
  446.         return PEAR::throwError($text$code);
  447.     }
  448.     
  449.     
  450.     /**
  451.     * 
  452.     * Constructor.
  453.     * 
  454.     * If there is an error on instantiation, $this->error will be
  455.     * populated with the PEAR_Error.
  456.     * 
  457.     * @access public
  458.     * 
  459.     * @param object &$db A PEAR DB object.
  460.     * 
  461.     * @param string $table The table name to connect to in the database.
  462.     * 
  463.     * @param mixed $create The automatic table creation mode to pursue:
  464.     *  boolean false to not attempt creation, 'safe' to
  465.     *  create the table only if it does not exist, or
  466.     *  'drop' to drop any existing table with the same name
  467.     *  and re-create it.
  468.     * 
  469.     * @return object DB_Table 
  470.     * 
  471.     */
  472.     
  473.     function DB_Table(&$db$table$create = false)
  474.     {
  475.         // is the first argument a DB object?
  476.         if (is_subclass_of($db'db_common')) {
  477.             $this->error =DB_Table::throwError(DB_TABLE_ERR_NOT_DB_OBJECT);
  478.             return;
  479.         }
  480.         
  481.         // is the RDBMS supported?
  482.         if (DB_Table::supported($db->phptype)) {
  483.             $this->error =DB_Table::throwError(
  484.                 DB_TABLE_ERR_PHPTYPE,
  485.                 "({$db->phptype})"
  486.             );
  487.             return;
  488.         }
  489.         
  490.         // set the class properties
  491.         $this->db =$db;
  492.         $this->table = $table;
  493.         
  494.         // should we attempt table creation?
  495.         if ($create{
  496.             // yes, attempt to create the table with the appropriate
  497.             // flag.
  498.             $result $this->create($create);
  499.             if (PEAR::isError($result)) {
  500.                 // problem creating the table
  501.                 $this->error =$result;
  502.                 return;
  503.             }
  504.         }
  505.     }
  506.     
  507.     
  508.     /**
  509.     * 
  510.     * Is a particular RDBMS supported by DB_Table?
  511.     * 
  512.     * @static
  513.     * 
  514.     * @access public
  515.     * 
  516.     * @param string $phptype The RDBMS type for PHP.
  517.     * 
  518.     * @return bool True if supported, false if not.
  519.     * 
  520.     */
  521.     
  522.     function supported($phptype)
  523.     {
  524.         $supported array_keys($GLOBALS['_DB_TABLE']['type']);
  525.         return in_array(strtolower($phptype)$supported);
  526.     }
  527.     
  528.     
  529.     
  530.     /**
  531.     * 
  532.     * Returns all or part of the $this->col property array.
  533.     * 
  534.     * @access public
  535.     * 
  536.     * @param mixed $col If null, returns the $this->col property array
  537.     *  as it is.  If string, returns that column name from the $this->col
  538.     *  array. If an array, returns those columns named as the array
  539.     *  values from the $this->col array as an array.
  540.     *
  541.     * @return mixed All or part of the $this->col property array, or
  542.     *  boolean false if no matching column names are found.
  543.     * 
  544.     */
  545.     
  546.     function getColumns($col = null)
  547.     {
  548.         // by default, return all column definitions
  549.         if (is_null($col)) {
  550.             return $this->col;
  551.         }
  552.         
  553.         // if the param is a string, only return the column definition
  554.         // named by the that string
  555.         if (is_string($col)) {
  556.             if (isset($this->col[$col])) {
  557.                 return $this->col[$col];
  558.             else {
  559.                 return false;
  560.             }
  561.         }
  562.         
  563.         // if the param is a sequential array of column names,
  564.         // return only those columns named in that array
  565.         if (is_array($col)) {
  566.             $set = array();
  567.             foreach ($col as $name{
  568.                 $set[$name$this->getColumns($name);
  569.             }
  570.             
  571.             if (count($set== 0{
  572.                 return false;
  573.             else {
  574.                 return $set;
  575.             }
  576.         }
  577.         
  578.         // param was not null, string, or array
  579.         return false;
  580.     }
  581.     
  582.     
  583.     /**
  584.     * 
  585.     * Returns all or part of the $this->idx property array.
  586.     * 
  587.     * @access public
  588.     * 
  589.     * @param string $col If specified, returns only this index key
  590.     *  from the $this->col property array.
  591.     * 
  592.     * @return array All or part of the $this->idx property array.
  593.     * 
  594.     */
  595.     
  596.     function getIndexes($idx = null)
  597.     {
  598.         // by default, return all index definitions
  599.         if (is_null($idx)) {
  600.             return $this->idx;
  601.         }
  602.         
  603.         // if the param is a string, only return the index definition
  604.         // named by the that string
  605.         if (is_string($idx)) {
  606.             if (isset($this->idx[$idx])) {
  607.                 return $this->idx[$idx];
  608.             else {
  609.                 return false;
  610.             }
  611.         }
  612.         
  613.         // if the param is a sequential array of index names,
  614.         // return only those indexes named in that array
  615.         if (is_array($idx)) {
  616.             $set = array();
  617.             foreach ($idx as $name{
  618.                 $set[$name$this->getIndexes($name);
  619.             }
  620.             
  621.             if (count($set== 0{
  622.                 return false;
  623.             else {
  624.                 return $set;
  625.             }
  626.         }
  627.         
  628.         // param was not null, string, or array
  629.         return false;
  630.     }
  631.     
  632.     
  633.     /**
  634.     *
  635.     * Select rows from the table using one of the 'DB::get*()' methods.
  636.     * 
  637.     * @access public
  638.     * 
  639.     * @param string $sqlkey The name of the SQL SELECT to use from the
  640.     *  $this->sql property array.
  641.     * 
  642.     * @param string $filter Ad-hoc SQL snippet to AND with the default
  643.     *  SELECT WHERE clause.
  644.     * 
  645.     * @param string $order Ad-hoc SQL snippet to override the default
  646.     *  SELECT ORDER BY clause.
  647.     * 
  648.     * @param int $start The row number to start listing from in the
  649.     *  result set.
  650.     * 
  651.     * @param int $count The number of rows to list in the result set.
  652.     * 
  653.     * @return mixed An array of records from the table (if anything but
  654.     *  'getOne'), a single value (if 'getOne'), or a PEAR_Error object.
  655.     *
  656.     * @see DB::getAll()
  657.     *
  658.     * @see DB::getAssoc()
  659.     *
  660.     * @see DB::getCol()
  661.     *
  662.     * @see DB::getOne()
  663.     *
  664.     * @see DB::getRow()
  665.     *
  666.     * @see DB_Table::_swapModes()
  667.     *
  668.     */
  669.     
  670.     function select($sqlkey$filter = null$order = null,
  671.         $start = null$count = null)
  672.     {
  673.         // build the base command
  674.         $sql $this->buildSQL($sqlkey$filter$order$start$count);
  675.         
  676.         // set the get*() method name
  677.         if (isset($this->sql[$sqlkey]['get'])) {
  678.             $method ucwords(strtolower(trim($this->sql[$sqlkey]['get'])));
  679.             $method = "get$method";
  680.         else {
  681.             $method 'getAll';
  682.         }
  683.         
  684.         // DB_Table assumes you are using a shared PEAR DB object.  Other
  685.         // scripts using the same object probably expect its fetchmode
  686.         // not to change, unless they change it themselves.  Thus, to
  687.         // provide friendly mode-swapping, we will restore these modes
  688.         // afterwards.
  689.         $restore_mode $this->db->fetchmode;
  690.         $restore_class $this->db->fetchmode_object_class;
  691.         
  692.         // swap modes
  693.         $this->_swapModes($this->fetchmode$this->fetchmode_object_class);
  694.         
  695.         // get the result
  696.         $result $this->db->$method($sql);
  697.             
  698.         // swap modes back
  699.         $this->_swapModes($restore_mode$restore_class);
  700.         
  701.         // return the result
  702.         return $result;
  703.     }
  704.     
  705.     
  706.     /**
  707.     *
  708.     * Select rows from the table as a DB_Result object.
  709.     * 
  710.     * @access public
  711.     * 
  712.     * @param string $sqlkey The name of the SQL SELECT to use from the
  713.     *  $this->sql property array.
  714.     * 
  715.     * @param string $filter Ad-hoc SQL snippet to add to the default
  716.     *  SELECT WHERE clause.
  717.     * 
  718.     * @param string $order Ad-hoc SQL snippet to override the default
  719.     *  SELECT ORDER BY clause.
  720.     * 
  721.     * @param int $start The record number to start listing from in the
  722.     *  result set.
  723.     * 
  724.     * @param int $count The number of records to list in the result set.
  725.     * 
  726.     * @return mixed A PEAR_Error on failure, or a DB_Result object on
  727.     *  success.
  728.     *
  729.     * @see DB_Table::_swapModes()
  730.     *
  731.     */
  732.     
  733.     function selectResult($sqlkey$filter = null$order = null
  734.         $start = null$count = null)
  735.     {
  736.         // build the base command
  737.         $sql $this->buildSQL($sqlkey$filter$order$start$count);
  738.         
  739.         // DB_Table assumes you are using a shared PEAR DB object.  Other
  740.         // scripts using the same object probably expect its fetchmode
  741.         // not to change, unless they change it themselves.  Thus, to
  742.         // provide friendly mode-swapping, we will restore these modes
  743.         // afterwards.
  744.         $restore_mode $this->db->fetchmode;
  745.         $restore_class $this->db->fetchmode_object_class;
  746.         
  747.         // swap modes
  748.         $this->_swapModes($this->fetchmode$this->fetchmode_object_class);
  749.         
  750.         // get the result
  751.         $result =$this->db->query($sql);
  752.         
  753.         // swap modes back
  754.         $this->_swapModes($restore_mode$restore_class);
  755.         
  756.         // return the result
  757.         return $result;
  758.     }
  759.     
  760.     
  761.     /**
  762.     * 
  763.     * Change the $this->db PEAR DB object fetchmode and
  764.     * fetchmode_object_class.
  765.     * 
  766.     * Becase DB_Table objects tend to use the same PEAR DB object, it
  767.     * may sometimes be useful to have one object return results in one
  768.     * mode, and have another object return results in a different mode.
  769.     * This method allows us to switch DB fetch modes on the fly.
  770.     * 
  771.     * @access private
  772.     * 
  773.     * @param string $new_mode A DB_FETCHMODE_* constant.  If null,
  774.     *  defaults to whatever the DB object is currently using.
  775.     * 
  776.     * @param string $new_class The object class to use for results when
  777.     *  the $db object is in DB_FETCHMODE_OBJECT fetch mode.  If null,
  778.     *  defaults to whatever the the DB object is currently using.
  779.     * 
  780.     * @return void 
  781.     * 
  782.     */
  783.     
  784.     function _swapModes($new_mode$new_class)
  785.     {
  786.         // get the old (current) mode and class
  787.         $old_mode $this->db->fetchmode;
  788.         $old_class $this->db->fetchmode_object_class;
  789.         
  790.         // don't need to swap anything if the new modes are both
  791.         // null or if the old and new modes already match.
  792.         if ((is_null($new_mode&& is_null($new_class)) ||
  793.             ($old_mode == $new_mode && $old_class == $new_class)) {
  794.             return;
  795.         }
  796.         
  797.         // set the default new mode
  798.         if (is_null($new_mode)) {
  799.             $new_mode $old_mode;
  800.         }
  801.         
  802.         // set the default new class
  803.         if (is_null($new_class)) {
  804.             $new_class $old_class;
  805.         }
  806.         
  807.         // swap modes
  808.         $this->db->setFetchMode($new_mode$new_class);
  809.     }
  810.     
  811.     
  812.     /**
  813.     * 
  814.     * Build the SQL command from a specified $this->sql element.
  815.     * 
  816.     * @access public
  817.     * 
  818.     * @param string $sqlkey The $this->sql key to use as the basis for the
  819.     *  SQL query string.
  820.     * 
  821.     * @param string $filter A filter to add to the WHERE clause of the
  822.     *  defined SELECT in $this->sql.
  823.     * 
  824.     * @param string $order An ORDER clause to override the defined order
  825.     *  in $this->sql.
  826.     * 
  827.     * @param int $start The row number to start listing from in the
  828.     *  result set.
  829.     * 
  830.     * @param int $count The number of rows to list in the result set.
  831.     * 
  832.     * @return mixed A PEAR_Error on failure, or an SQL command string on
  833.     *  success.
  834.     * 
  835.     */
  836.     
  837.     function buildSQL($sqlkey$filter = null$order = null,
  838.         $start = null$count = null)
  839.     {
  840.         // does the SQL SELECT key exist?
  841.         $tmp array_keys($this->sql);
  842.         if (in_array($sqlkey$tmp)) {
  843.             return $this->throwError(
  844.                 DB_TABLE_ERR_SQL_UNDEF,
  845.                 "('$sqlkey')"
  846.             );
  847.         }
  848.         
  849.         // the SQL clause parts and their default values
  850.         $part = array(
  851.             'select' => '*',
  852.             'from'   => $this->table,
  853.             'join'   => null,
  854.             'where'  => null,
  855.             'group'  => null,
  856.             'having' => null,
  857.             'order'  => null
  858.         );
  859.         
  860.         // loop through each possible clause
  861.         foreach ($part as $key => $val{
  862.             if (isset($this->sql[$sqlkey][$key])) {
  863.                 continue;
  864.             else {
  865.                 $part[$key$this->sql[$sqlkey][$key];
  866.             }
  867.         }
  868.         
  869.         // add the filter to the WHERE part
  870.         if ($filter{
  871.             if ($part['where']{
  872.                 $part['where'.= $filter;
  873.             else {
  874.                 $part['where'.= " AND ($filter)";
  875.             }
  876.         }
  877.         
  878.         // override the ORDER part
  879.         if ($order{
  880.             $part['order'$order;
  881.         }
  882.         
  883.         // build up the command string form the parts
  884.         $cmd '';
  885.         foreach ($part as $key => $val{
  886.             
  887.             // if the part value has not been set, skip it
  888.             if ($val{
  889.                 continue;
  890.             }
  891.             
  892.             switch ($key{
  893.             
  894.             case 'join':
  895.                 $cmd .= strtoupper($key. " $val\n";
  896.                 break;
  897.                 
  898.             case 'group':
  899.             case 'order':
  900.                 $cmd .= strtoupper($key. " BY $val\n";
  901.                 break;
  902.                 
  903.             default:
  904.                 $cmd .= strtoupper($key. " $val\n";
  905.                 break;
  906.             
  907.             }
  908.         }
  909.         
  910.         // add LIMIT if requested
  911.         if (is_null($start&& is_null($count)) {
  912.             $cmd $this->db->modifyLimitQuery(
  913.                 $cmd$start$count);
  914.         }
  915.         
  916.         return $cmd;
  917.     }
  918.     
  919.     
  920.     /**
  921.     *
  922.     * Insert a single table row after validating through validInsert().
  923.     * 
  924.     * @access public
  925.     * 
  926.     * @param array $data An associative array of key-value pairs where
  927.     *  the key is the column name and the value is the column value.  This
  928.     *  is the data that will be inserted into the table.  Data is checked
  929.     *  against the column data type for validity.
  930.     * 
  931.     * @return mixed Void on success, a PEAR_Error object on failure.
  932.     *
  933.     * @see validInsert()
  934.     * 
  935.     * @see DB::autoExecute()
  936.     * 
  937.     */
  938.         
  939.     function insert($data)
  940.     {
  941.         // validate the data if auto-validation is turned on
  942.         if ($this->_valid_insert{
  943.             $result $this->validInsert($data);
  944.             if (PEAR::isError($result)) {
  945.                 return $result;
  946.             }
  947.         }
  948.         
  949.         return $this->db->autoExecute($this->table$data,
  950.             DB_AUTOQUERY_INSERT);
  951.     }
  952.     
  953.     
  954.     /**
  955.     * 
  956.     * Turn on (or off) automatic validation of inserted data.
  957.     * 
  958.     * @access public
  959.     * 
  960.     * @param bool $flag True to turn on auto-validation, false to turn it off.
  961.     * 
  962.     * @return void 
  963.     * 
  964.     */
  965.     
  966.     function autoValidInsert($flag = true)
  967.     {
  968.         if ($flag === true || $flag === false{
  969.             $this->_valid_insert $flag;
  970.         elseif ($flag{
  971.             $this->_valid_insert = true;
  972.         else {
  973.             $this->_valid_insert = false;
  974.         }
  975.     }
  976.     
  977.     
  978.     /**
  979.     *
  980.     * Validate an array for insertion into the table.
  981.     * 
  982.     * @access public
  983.     * 
  984.     * @param array $data An associative array of key-value pairs where
  985.     *  the key is the column name and the value is the column value.  This
  986.     *  is the data that will be inserted into the table.  Data is checked
  987.     *  against the column data type for validity.
  988.     * 
  989.     * @return mixed Boolean true on success, a PEAR_Error object on
  990.     *  failure.
  991.     *
  992.     * @see insert()
  993.     * 
  994.     */
  995.         
  996.     function validInsert(&$data)
  997.     {
  998.         // loop through the data, and disallow insertion of unmapped
  999.         // columns
  1000.         foreach ($data as $col => $val{
  1001.             if (isset($this->col[$col])) {
  1002.                 return $this->throwError(
  1003.                     DB_TABLE_ERR_INS_COL_NOMAP,
  1004.                     "('$col')"
  1005.                 );
  1006.             }
  1007.         }
  1008.         
  1009.         // loop through each column mapping, and check the data to be
  1010.         // inserted into it against the column data type. we loop through
  1011.         // column mappings instead of the insert data to make sure that
  1012.         // all necessary columns are being inserted.
  1013.         foreach ($this->col as $col => $val{
  1014.             
  1015.             // is the value allowed to be null?
  1016.             if (isset($val['require']&&
  1017.                 $val['require'== true &&
  1018.                 (isset($data[$col]|| is_null($data[$col]))) {
  1019.                 return $this->throwError(
  1020.                     DB_TABLE_ERR_INS_COL_REQUIRED,
  1021.                     "'$col'"
  1022.                 );
  1023.             }
  1024.             
  1025.             // does the value to be inserted match the column data type?
  1026.             if (isset($data[$col]&&
  1027.                 $this->isValid($data[$col]$col)) {
  1028.                 return $this->throwError(
  1029.                     DB_TABLE_ERR_INS_DATA_INVALID,
  1030.                     "'$col' ('$data[$col]')"
  1031.                 );
  1032.             }
  1033.         }
  1034.         
  1035.         return true;
  1036.     }
  1037.     
  1038.     
  1039.     /**
  1040.     *
  1041.     * Update table row(s) matching a custom WHERE clause, after checking
  1042.     * against validUpdate().
  1043.     * 
  1044.     * @access public
  1045.     * 
  1046.     * @param array $data An associative array of key-value pairs where
  1047.     *  the key is the column name and the value is the column value.  These
  1048.     *  are the columns that will be updated with new values.
  1049.     * 
  1050.     * @param string $where An SQL WHERE clause limiting which records
  1051.     *  are to be updated.
  1052.     * 
  1053.     * @return mixed Void on success, a PEAR_Error object on failure.
  1054.     *
  1055.     * @see validUpdate()
  1056.     *
  1057.     * @see DB::autoExecute()
  1058.     * 
  1059.     */
  1060.     
  1061.     function update($data$where)
  1062.     {
  1063.         // validate the data if auto-validation is turned on
  1064.         if ($this->_valid_update{
  1065.             $result $this->validUpdate($data);
  1066.             if (PEAR::isError($result)) {
  1067.                 return $result;
  1068.             }
  1069.         }
  1070.         
  1071.         return $this->db->autoExecute($this->table$data,
  1072.             DB_AUTOQUERY_UPDATE$where);
  1073.     }
  1074.     
  1075.     
  1076.     /**
  1077.     * 
  1078.     * Turn on (or off) automatic validation of updated data.
  1079.     * 
  1080.     * @access public
  1081.     * 
  1082.     * @param bool $flag True to turn on auto-validation, false to turn it off.
  1083.     * 
  1084.     * @return void 
  1085.     * 
  1086.     */
  1087.     
  1088.     function autoValidUpdate($flag = true)
  1089.     {
  1090.         if ($flag === true || $flag === false{
  1091.             $this->_valid_update $flag;
  1092.         elseif ($flag{
  1093.             $this->_valid_update = true;
  1094.         else {
  1095.             $this->_valid_update = false;
  1096.         }
  1097.     }
  1098.     
  1099.     
  1100.     /**
  1101.     *
  1102.     * Validate an array for updating the table.
  1103.     * 
  1104.     * @access public
  1105.     * 
  1106.     * @param array $data An associative array of key-value pairs where
  1107.     *  the key is the column name and the value is the column value.  This
  1108.     *  is the data that will be inserted into the table.  Data is checked
  1109.     *  against the column data type for validity.
  1110.     * 
  1111.     * @return mixed Boolean true on success, a PEAR_Error object on
  1112.     *  failure.
  1113.     *
  1114.     * @see update()
  1115.     * 
  1116.     */
  1117.         
  1118.     function validUpdate(&$data)
  1119.     {
  1120.         // loop through each data element, and check the
  1121.         // data to be updated against the column data type.
  1122.         foreach ($data as $col => $val{
  1123.             
  1124.             // does the column exist?
  1125.             if (isset($this->col[$col])) {
  1126.                 return $this->throwError(
  1127.                     DB_TABLE_ERR_UPD_COL_NOMAP,
  1128.                     "('$col')"
  1129.                 );
  1130.             }
  1131.             
  1132.             // the column definition
  1133.             $defn $this->col[$col];
  1134.             
  1135.             // is it allowed to be null?
  1136.             if (isset($defn['require']&&
  1137.                 $defn['require'== true &&
  1138.                 isset($data[$col]&&
  1139.                 is_null($data[$col])) {
  1140.                 return $this->throwError(
  1141.                     DB_TABLE_ERR_UPD_COL_REQUIRED,
  1142.                     $col
  1143.                 );
  1144.             }
  1145.             
  1146.             // does the value to be inserted match the column data type?
  1147.             if ($this->isValid($data[$col]$col)) {
  1148.                 return $this->throwError(
  1149.                     DB_TABLE_ERR_UPD_DATA_INVALID,
  1150.                     "$col ('$data[$col]')"
  1151.                 );
  1152.             }
  1153.         }
  1154.         
  1155.         return true;
  1156.     }
  1157.     
  1158.     
  1159.     /**
  1160.     *
  1161.     * Delete table rows matching a custom WHERE clause.
  1162.     * 
  1163.     * @access public
  1164.     * 
  1165.     * @param string $where The WHERE clause for the delete command.
  1166.     *
  1167.     * @return mixed Void on success or a PEAR_Error object on failure.
  1168.     *
  1169.     * @see DB::query()
  1170.     * 
  1171.     */
  1172.     
  1173.     function delete($where)
  1174.     {
  1175.         return $this->db->query("DELETE FROM $this->table WHERE $where");
  1176.     }
  1177.     
  1178.     
  1179.     /**
  1180.     *
  1181.     * Generate a sequence value; sequence name defaults to the table name.
  1182.     * 
  1183.     * @access public
  1184.     * 
  1185.     * @param string $seq_name The sequence name; defaults to _table_id.
  1186.     * 
  1187.     * @return integer The next value in the sequence.
  1188.     *
  1189.     * @see DB::nextID()
  1190.     *
  1191.     */
  1192.     
  1193.     function nextID($seq_name = null)
  1194.     {
  1195.         if (is_null($seq_name)) {
  1196.             $seq_name = "_{$this->table}_id";
  1197.         } else {
  1198.             $seq_name = "_{$this->table}_{$seq_name}";
  1199.         }
  1200.         
  1201.         return $this->db->nextId($seq_name);
  1202.     }
  1203.     
  1204.     
  1205.     /**
  1206.     * 
  1207.     * Escape and enquote a value for use in an SQL query.
  1208.     * 
  1209.     * Helps makes user input safe against SQL injection attack.
  1210.     * 
  1211.     * @access public
  1212.     * 
  1213.     * @return string The value with quotes escaped, and inside single quotes.
  1214.     * 
  1215.     * @see DB_Common::quoteSmart()
  1216.     * 
  1217.     */
  1218.     
  1219.     function quote($val)
  1220.     {
  1221.         return $this->db->quoteSmart($val);
  1222.     }
  1223.     
  1224.     
  1225.     /**
  1226.     * 
  1227.     * Return a blank row array based on the column map.
  1228.     * 
  1229.     * The array keys are the column names, and all values are set to null.
  1230.     * 
  1231.     * @access public
  1232.     * 
  1233.     * @return array An associative array where the key is column name
  1234.     * and the value is null.
  1235.     * 
  1236.     */
  1237.     
  1238.     function getBlankRow()
  1239.     {
  1240.         $row = array();
  1241.         
  1242.         foreach ($this->col as $key => $val{
  1243.             $row[$key] = null;
  1244.         }
  1245.         
  1246.         $this->recast($row);
  1247.         
  1248.         return $row;
  1249.     }
  1250.     
  1251.     
  1252.     /**
  1253.     * 
  1254.     * Force array elements to the proper types for their columns.
  1255.     * 
  1256.     * This will not valiate the data, and will forcibly change the data
  1257.     * to match the recast-type.
  1258.     * 
  1259.     * The date, time, and timestamp recasting has special logic for
  1260.     * arrays coming from an HTML_QuickForm object so that the arrays
  1261.     * are converted into properly-formatted strings.
  1262.     * 
  1263.     * @todo If a column key holds an array of values (say from a multiple
  1264.     * select) then this method will not work properly; it will recast the
  1265.     * value to the string 'Array'.  Is this bad?
  1266.     * 
  1267.     * @access public
  1268.     * 
  1269.     * @param array &$data The data array to re-cast.
  1270.     *
  1271.     * @return void
  1272.     * 
  1273.     */
  1274.     
  1275.     function recast(&$data)
  1276.     {
  1277.         $keys = array_keys($data);
  1278.         
  1279.         foreach ($keys as $key) {
  1280.         
  1281.             if (! isset($this->col[$key])) {
  1282.                 continue;
  1283.             }
  1284.             
  1285.             unset($val);
  1286.             $val =& $data[$key];
  1287.             
  1288.             switch ($this->col[$key]['type']{
  1289.             
  1290.             case 'boolean':
  1291.                 $val = ($val) ? 1 : 0;
  1292.                 break;
  1293.                 
  1294.             case 'char':
  1295.             case 'varchar':
  1296.             case 'clob':
  1297.                 settype($val, 'string');
  1298.                 break;
  1299.                 
  1300.             case 'date':
  1301.             
  1302.                 if (is_array($val) &&
  1303.                     isset($val['Y']) &&
  1304.                     isset($val['m']) &&
  1305.                     isset($val['d'])) {
  1306.                     
  1307.                     // the date is in HTML_QuickForm format,
  1308.                     // convert into a string
  1309.                     $y = $val['Y'];
  1310.                     
  1311.                     $m = ($val['m'] < 10)
  1312.                         ? '0'.$val['m'] : $val['m'];
  1313.                         
  1314.                     $d = ($val['d'] < 10)
  1315.                         ? '0'.$val['d'] : $val['d'];
  1316.                         
  1317.                     $val = "$y-$m-$d";
  1318.                     
  1319.                 } else {
  1320.                 
  1321.                     // convert using the Date class
  1322.                     $tmp =& new Date($val);
  1323.                     $val = $tmp->format('%Y-%m-%d');
  1324.                     
  1325.                 }
  1326.                 
  1327.                 break;
  1328.             
  1329.             case 'time':
  1330.             
  1331.                 if (is_array($val) &&
  1332.                     isset($val['H']) &&
  1333.                     isset($val['i']) &&
  1334.                     isset($val['s'])) {
  1335.                     
  1336.                     // the time is in HTML_QuickForm format,
  1337.                     // convert into a string
  1338.                     $h = ($val['H'] < 10)
  1339.                         ? '0' . $val['H'] : $val['H'];
  1340.                     
  1341.                     $i = ($val['i'] < 10)
  1342.                         ? '0' . $val['i'] : $val['i'];
  1343.                         
  1344.                     $s = ($val['s'] < 10)
  1345.                         ? '0' . $val['s'] : $val['s'];
  1346.                         
  1347.                     $val = "$h:$i:$s";
  1348.                     
  1349.                 } else {
  1350.                     // date does not matter in this case, so
  1351.                     // pre 1970 and post 2040 are not an issue.
  1352.                     $tmp = strtotime(date('Y-m-d') . " $val");
  1353.                     $val = date('H:i:s', $tmp);
  1354.                 }
  1355.                 
  1356.                 break;
  1357.                 
  1358.             case 'timestamp':
  1359.                 if (is_array($val) &&
  1360.                     isset($val['Y']) &&
  1361.                     isset($val['m']) &&
  1362.                     isset($val['d']) &&
  1363.                     isset($val['H']) &&
  1364.                     isset($val['i']) &&
  1365.                     isset($val['s'])) {
  1366.                     
  1367.                     // timestamp is in HTML_QuickForm format,
  1368.                     // convert to a string
  1369.                     $y = $val['Y'];
  1370.                     
  1371.                     $m = ($val['m'] < 10)
  1372.                         ? '0'.$val['m'] : $val['m'];
  1373.                         
  1374.                     $d = ($val['d'] < 10)
  1375.                         ? '0'.$val['d'] : $val['d'];
  1376.                         
  1377.                     $h = ($val['H'] < 10)
  1378.                         ? '0' . $val['H'] : $val['H'];
  1379.                     
  1380.                     $i = ($val['i'] < 10)
  1381.                         ? '0' . $val['i'] : $val['i'];
  1382.                         
  1383.                     $s = ($val['s'] < 10)
  1384.                         ? '0' . $val['s'] : $val['s'];
  1385.                         
  1386.                     $val = "$y-$m-$d $h:$i:$s";
  1387.                     
  1388.                 } else {
  1389.                     // convert using the Date class
  1390.                     $tmp =& new Date($val);
  1391.                     $val = $tmp->format('%Y-%m-%d %H:&i:&s');
  1392.                 }
  1393.                 
  1394.                 break;
  1395.             
  1396.             case 'smallint':
  1397.             case 'integer':
  1398.             case 'bigint':
  1399.                 settype($val, 'integer');
  1400.                 break;
  1401.             
  1402.             case 'decimal':
  1403.             case 'single':
  1404.             case 'double':
  1405.                 settype($val, 'float');
  1406.                 break;
  1407.             }
  1408.         }
  1409.     }
  1410.     
  1411.     
  1412.     /**
  1413.     * 
  1414.     * Create the table based on $this->col and $this->idx.
  1415.     * 
  1416.     * @access public
  1417.     * 
  1418.     * @param mixed $flag Boolean false to abort the create attempt from
  1419.     * the start, 'drop' to drop the existing table and
  1420.     * re-create it, or 'safe' to only create the table if it
  1421.     * does not exist in the database.
  1422.     * 
  1423.     * @return mixed Boolean false if there was no attempt to create the
  1424.     * table, boolean true if the attempt succeeded, or a PEAR_Error if
  1425.     * the attempt failed.
  1426.     *
  1427.     * @see DB_Table_Manager::create()
  1428.     * 
  1429.     */
  1430.     
  1431.     function create($flag)
  1432.     {
  1433.         // are we OK to create the table?
  1434.         $ok = false;
  1435.         
  1436.         // check the create-flag
  1437.         switch ($flag) {
  1438.         
  1439.         case 'drop':
  1440.             // forcibly drop an existing table
  1441.             $this->db->query("DROP TABLE {$this->table}");
  1442.             $ok = true;
  1443.             break;
  1444.         
  1445.         case 'safe':
  1446.             // create only if table does not exist
  1447.             $list = $this->db->getListOf('tables');
  1448.             // ok to create only if table does not exist
  1449.             $ok (in_array($this->table$list));
  1450.             break;
  1451.             
  1452.         default:
  1453.             // unknown flag
  1454.             return $this->throwError(
  1455.                 DB_TABLE_ERR_CREATE_FLAG,
  1456.                 "('$flag')"
  1457.             );
  1458.         }
  1459.         
  1460.         // are we going to create the table?
  1461.         if (! $ok) {
  1462.             return false;
  1463.         } else {
  1464.             include_once 'DB/Table/Manager.php';
  1465.             return DB_Table_Manager::create(
  1466.                 $this->db$this->table$this->col$this->idx$flag
  1467.             );
  1468.         }
  1469.     }
  1470.     
  1471.     
  1472.     /**
  1473.     * 
  1474.     * Check if a value validates against the DB_Table data type for a
  1475.     * given column. This only checks that it matches the data type; it
  1476.     * does not do extended validation.
  1477.     * 
  1478.     * @access public
  1479.     * 
  1480.     * @param array $val A value to check against the column's DB_Table
  1481.     * data type.
  1482.     * 
  1483.     * @param array $col A column name from $this->col.
  1484.     * 
  1485.     * @return boolean True if the value validates (matches the
  1486.     * data type), false if not.
  1487.     * 
  1488.     * @see DB_Table_Valid
  1489.     * 
  1490.     */
  1491.     
  1492.     function isValid($val, $col)
  1493.     {
  1494.         // is the value null?
  1495.         if (is_null($val)) {
  1496.             // is the column required?
  1497.             if ($this->isRequired($col)) {
  1498.                 // yes, so not valid
  1499.                 return false;
  1500.             } else {
  1501.                 // not required, so it's valid
  1502.                 return true;
  1503.             }
  1504.         }
  1505.         
  1506.         // make sure we have the validation class
  1507.         include_once 'DB/Table/Valid.php';
  1508.         
  1509.         // validate values per the column type
  1510.         $map = array_keys($GLOBALS['_DB_TABLE']['type']['sqlite']);
  1511.         
  1512.         // is the column type on the map?
  1513.         if (! in_array($this->col[$col]['type']$map)) {
  1514.             return $this->throwError(
  1515.                 DB_TABLE_ERR_VALIDATE_TYPE,
  1516.                 "'$col' ('{$this->col[$col]['type']}')"
  1517.             );
  1518.         }
  1519.         
  1520.         // validate for the type
  1521.         switch ($this->col[$col]['type']{
  1522.         
  1523.         case 'char':
  1524.         case 'varchar':
  1525.             $result = DB_Table_Valid::isChar(
  1526.                 $val,
  1527.                 $this->col[$col]['size']
  1528.             );
  1529.             break;
  1530.         
  1531.         case 'decimal':
  1532.             $result = DB_Table_Valid::isDecimal(
  1533.                 $val,
  1534.                 $this->col[$col]['size'],
  1535.                 $this->col[$col]['scope']
  1536.             );
  1537.             break;
  1538.             
  1539.         default:
  1540.             $result = call_user_func(
  1541.                 array(
  1542.                     'DB_Table_Valid',
  1543.                     'is' . ucwords($this->col[$col]['type'])
  1544.                 ),
  1545.                 $val
  1546.             );
  1547.             break;
  1548.         }
  1549.         
  1550.         // have we passed the check so far, and should we
  1551.         // also check for allowed values?
  1552.         if ($result && isset($this->col[$col]['qf_vals'])) {
  1553.             $result = in_array(
  1554.                 $val,
  1555.                 array_keys($this->col[$col]['qf_vals'])
  1556.             );
  1557.         }
  1558.         
  1559.         return $result;
  1560.     }
  1561.     
  1562.     
  1563.     /**
  1564.     * 
  1565.     * Is a specific column required to be set and non-null?
  1566.     * 
  1567.     * @access public
  1568.     * 
  1569.     * @param mixed $column The column to check against.
  1570.     * 
  1571.     * @return boolean True if required, false if not.
  1572.     * 
  1573.     */
  1574.     
  1575.     function isRequired($column)
  1576.     {
  1577.         if (isset($this->col[$column]['require']&&
  1578.             $this->col[$column]['require'== true{
  1579.             return true;
  1580.         } else {
  1581.             return false;
  1582.         }
  1583.     }
  1584.     
  1585.     
  1586.     /**
  1587.     * 
  1588.     * Create and return a QuickForm object based on table columns.
  1589.     *
  1590.     * @access public
  1591.     *
  1592.     * @param array $columns A sequential array of column names to use in
  1593.     * the form; if null, uses all columns.
  1594.     *
  1595.     * @param string $array_name By default, the form will use the names
  1596.     * of the columns as the names of the form elements.  If you pass
  1597.     * $array_name, the column names will become keys in an array named
  1598.     * for this parameter.
  1599.     * 
  1600.     * @param array $args An associative array of optional arguments to
  1601.     * pass to the QuickForm object.  The keys are...
  1602.     *
  1603.     * 'formName' : String, name of the form; defaults to the name of this
  1604.     * table.
  1605.     * 
  1606.     * 'method' : String, form method; defaults to 'post'.
  1607.     * 
  1608.     * 'action' : String, form action; defaults to
  1609.     * $_SERVER['REQUEST_URI'].
  1610.     * 
  1611.     * 'target' : String, form target target; defaults to '_self'
  1612.     * 
  1613.     * 'attributes' : Associative array, extra attributes for <form>
  1614.     * tag; the key is the attribute name and the value is attribute
  1615.     * value.
  1616.     * 
  1617.     * 'trackSubmit' : Boolean, whether to track if the form was
  1618.     * submitted by adding a special hidden field
  1619.     * 
  1620.     * @return object HTML_QuickForm
  1621.     * 
  1622.     * @see HTML_QuickForm
  1623.     * 
  1624.     * @see DB_Table_QuickForm
  1625.     * 
  1626.     */
  1627.     
  1628.     function &getForm($columns = null, $array_name = null, $args = array())
  1629.     {
  1630.         include_once 'DB/Table/QuickForm.php';
  1631.         $coldefs = $this->_getFormColDefs($columns);
  1632.         return DB_Table_QuickForm::getForm($coldefs$array_name$args);
  1633.     }
  1634.     
  1635.     
  1636.     /**
  1637.     * 
  1638.     * Adds elements and rules to a pre-existing HTML_QuickForm object.
  1639.     * 
  1640.     * @access public
  1641.     * 
  1642.     * @param object &$form An HTML_QuickForm object.
  1643.     * 
  1644.     * @param array $columns A sequential array of column names to use in
  1645.     * the form; if null, uses all columns.
  1646.     *
  1647.     * @param string $array_name By default, the form will use the names
  1648.     * of the columns as the names of the form elements.  If you pass
  1649.     * $array_name, the column names will become keys in an array named
  1650.     * for this parameter.
  1651.     * 
  1652.     * @return void
  1653.     * 
  1654.     * @see HTML_QuickForm
  1655.     * 
  1656.     * @see DB_Table_QuickForm
  1657.     * 
  1658.     */
  1659.     
  1660.     function addFormElements(&$form, $columns = null, $array_name = null)
  1661.     {
  1662.         include_once 'DB/Table/QuickForm.php';
  1663.         $coldefs = $this->_getFormColDefs($columns);
  1664.         DB_Table_QuickForm::addElements($form$coldefs$array_name);
  1665.         DB_Table_QuickForm::addRules($form$coldefs$array_name);
  1666.     }
  1667.     
  1668.     
  1669.     /**
  1670.     * 
  1671.     * Creates and returns an array of QuickForm elements based on an
  1672.     * array of DB_Table column names.
  1673.     * 
  1674.     * @access public
  1675.     * 
  1676.     * @param array $columns A sequential array of column names to use in
  1677.     * the form; if null, uses all columns.
  1678.     * 
  1679.     * @param string $array_name By default, the form will use the names
  1680.     * of the columns as the names of the form elements.  If you pass
  1681.     * $array_name, the column names will become keys in an array named
  1682.     * for this parameter.
  1683.     * 
  1684.     * @return array An array of HTML_QuickForm_Element objects.
  1685.     * 
  1686.     * @see HTML_QuickForm
  1687.     * 
  1688.     * @see DB_Table_QuickForm
  1689.     * 
  1690.     */
  1691.     
  1692.     function &getFormGroup($columns = null, $array_name = null)
  1693.     {
  1694.         include_once 'DB/Table/QuickForm.php';
  1695.         $coldefs = $this->_getFormColDefs($columns);
  1696.         return DB_Table_QuickForm::getGroup($coldefs$array_name);
  1697.     }
  1698.     
  1699.     
  1700.     /**
  1701.     * 
  1702.     * Creates and returns a single QuickForm element based on a DB_Table
  1703.     * column name.
  1704.     * 
  1705.     * @access public
  1706.     * 
  1707.     * @param string $column A DB_Table column name.
  1708.     * 
  1709.     * @param string $elemname The name to use for the generated QuickForm
  1710.     * element.
  1711.     * 
  1712.     * @return object HTML_QuickForm_Element
  1713.     * 
  1714.     * @see HTML_QuickForm
  1715.     * 
  1716.     * @see DB_Table_QuickForm
  1717.     * 
  1718.     */
  1719.     
  1720.     function &getFormElement($column, $elemname)
  1721.     {
  1722.         include_once 'DB/Table/QuickForm.php';
  1723.         $coldef = $this->_getFormColDefs($column);
  1724.         return DB_Table_QuickForm::getElement($coldef$elemname);
  1725.     }
  1726.     
  1727.     
  1728.     /**
  1729.     * 
  1730.     * Creates a column definition array suitable for DB_Table_QuickForm.
  1731.     * 
  1732.     * @access public
  1733.     * 
  1734.     * @param string|array $column_set A string column name, a sequential
  1735.     * array of columns names, or an associative array where the key is a
  1736.     * column name and the value is the default value for the generated
  1737.     * form element.  If null, uses all columns for this class.
  1738.     * 
  1739.     * @return array An array of columne defintions suitable for passing
  1740.     * to DB_Table_QuickForm.
  1741.     * 
  1742.     */
  1743.     
  1744.     function _getFormColDefs($column_set = null)
  1745.     {
  1746.         if (is_null($column_set)) {
  1747.             // no columns or columns+values; just return the $this->col
  1748.             // array.
  1749.             return $this->getColumns($column_set);
  1750.         }
  1751.         
  1752.         // check to see if the keys are sequential integers.  if so,
  1753.         // the $column_set is just a list of columns.
  1754.         settype($column_set, 'array');
  1755.         $keys = array_keys($column_set);
  1756.         $all_integer = true;
  1757.         foreach ($keys as $val) {
  1758.             if (! is_integer($val)) {
  1759.                 $all_integer = false;
  1760.                 break;
  1761.             }
  1762.         }
  1763.         
  1764.         if ($all_integer) {
  1765.         
  1766.             // the column_set is just a list of columns; get back the $this->col
  1767.             // array elements matching this list.
  1768.             $coldefs = $this->getColumns($column_set);
  1769.             
  1770.         } else {
  1771.             
  1772.             // the columns_set is an associative array where the key is a
  1773.             // column name and the value is the form element value.
  1774.             $coldefs = $this->getColumns($keys);
  1775.             foreach ($coldefs as $key => $val{
  1776.                 $coldefs[$key]['qf_setvalue'] = $column_set[$key];
  1777.             }
  1778.             
  1779.         }
  1780.         
  1781.         return $coldefs;
  1782.     }
  1783.     
  1784.  
  1785. }
  1786.  

Documentation generated on Mon, 11 Mar 2019 10:15:13 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.