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

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