<?php 
namespace Jackbooted\DB; 
 
use \Jackbooted\DB\DB; 
use \Jackbooted\Html\Widget; 
use \Jackbooted\Util\DataCache; 
use \Jackbooted\Util\Invocation; 
/** 
 * @copyright Confidential and copyright (c) 2016 Jackbooted Software. All rights reserved. 
 * 
 * Written by Brett Dutton of Jackbooted Software 
 * brett at brettdutton dot com 
 * 
 * This software is written and distributed under the GNU General Public 
 * License which means that its source code is freely-distributed and 
 * available to the general public. 
 */ 
 
/** 
 * This wraps the database fetch into 2D array of values. 
 * 
 * Allows the user to chain together commans without crashing. 
 * eg. getColumn will return an empty array even on bad result set. This 
 * will allow you to call array based functions without error 
 * 
 * Examples of use: 
 * <pre> 
 * echo Lists::select ( DBTable::factory ( 'reg', 'SHOW_TABLES' )->getColumn( 0 ) ); 
 * </pre> 
 * 
 * For more examples 
 * @see classtest_DB_Base 
 * @see classtest_DB_StressTest 
 * @see DB 
 */ 
class DBTable extends \Jackbooted\Util\JB implements \Iterator { 
 
    private static $dataCache; 
 
    public static function init() { 
        self::$dataCache = new DataCache ( __CLASS__, 100 ); 
    } 
 
    /** 
     * Use a static creator so that you can chain the methods together. 
     * 
     * @param object $resultSet PDO Result set. 
     * 
     * @since 1.0 
     * @return DBTable 
     */ 
    public static function create ( $dbh, $qry, $params=null, $fetch=DB::FETCH_BOTH ) { 
        return new DBTable ( $dbh, $qry, $params, $fetch ); 
    } 
    public static function factory ( $dbh, $qry, $params=null, $fetch=DB::FETCH_BOTH ) { 
        return new DBTable ( $dbh, $qry, $params, $fetch ); 
    } 
 
    public static function clearCache () { 
        self::$dataCache->clear (); 
    } 
 
    // Might need a value to return 
    private static $emptyArray =  []; 
    private static $falseValue = false; 
 
    // The array in memory 
    private $table = null; 
    private $fetch; 
 
    /** 
     * Construct a table in memory. 
     * 
     * @param object $resultSet Pass n result set from PDO query. 
     * 
     * @since 1.0 
     */ 
    public function __construct ( $dbh, $qry, $params=null, $fetch=DB::FETCH_BOTH ) { 
        parent::__construct(); 
        $this->fetch = $fetch; 
 
        if ( is_object ( $dbh ) ) { 
            $this->table = $dbh->fetchAll ( $fetch ); 
        } 
        else { 
            $cacheKey = $dbh . ' ' . $qry . ' ' . serialize ( $params ); 
            if ( ( $cacheValue = self::$dataCache->get ( $cacheKey ) ) !== false ) { 
                $this->table = $cacheValue; 
            } 
            else { 
                if ( ( $resultSet = DB::query ( $dbh, $qry, $params ) ) === false ) return; 
                $this->table = $resultSet->fetchAll ( $fetch ); 
                self::$dataCache->set ( $cacheKey, $this->table ); 
            } 
        } 
    } 
 
    /** 
     * Gets a column. 
     * 
     * @param mixed $columnNameOrIndex Index or the name of the column. 
     * 
     * @since 1.0 
     * @return array 
     */ 
    public function getColumn ( $columnNameOrIndex=0 ) { 
        if ( ! $this->ok () ) { 
            return  []; 
        } 
 
        $column =  []; 
        foreach ( $this->table as &$row ) { 
            $column[] = $row[$columnNameOrIndex]; 
        } 
 
        return $column; 
    } 
    /** 
     * Gets a column. 
     * 
     * @param mixed $columnNameOrIndex Index or the name of the column. 
     * 
     * @since 1.0 
     * @return array 
     */ 
    public function getColumnCount ( ) { 
        if ( ! $this->ok () ) { 
            return 0; 
        } 
 
        return count ( $this->getRow ( 0 ) ); 
    } 
 
    /** 
     * Get a pointer to the array. 
     * 
     * @since 1.0 
     * @return array 
     */ 
    public function &getRaw ( ) { 
        if ( ! $this->ok () ) { 
            return self::$emptyArray; 
        } 
 
        return $this->table; 
    } 
 
    /** 
     * Sets one value. 
     * 
     * @param mixed $value The value to set. 
     * @param mixed $columnNameOrIndex Which column do you want. 
     * @param integer $idx Which row do you want. 
     * 
     * @since 1.0 
     * @return mixed 
     */ 
    public function setValue ( $value, $columnNameOrIndex=0, $row=0 ) { 
        if ( ! $this->ok () ) return self::$falseValue; 
 
        $this->table[$row][$columnNameOrIndex] = $value; 
    } 
 
    /** 
     * Gets one value. 
     * 
     * @param mixed $columnNameOrIndex Which column do you want. 
     * @param integer $idx Which row do you want. 
     * 
     * @since 1.0 
     * @return array 
     */ 
    public function &getValue ( $columnNameOrIndex=0, $row=0 ) { 
        if ( ! $this->ok () ) return self::$falseValue; 
 
        $row = $this->getRow ( $row ); 
 
        if ( is_integer ( $columnNameOrIndex ) && ! isset ( $row[$columnNameOrIndex] ) ) { 
            $row = array_values ( $row ); 
        } 
 
        return $row[$columnNameOrIndex]; 
    } 
 
    /** 
     * Gets one row. 
     * 
     * @param integer $idx Which row do you want. 
     * 
     * @since 1.0 
     * @return array 
     */ 
    public function &getRow ( $idx=0 ) { 
        if ( ! $this->ok () || $idx < 0 || $idx >= $this->getRowCount () ) { 
            return self::$emptyArray; 
        } 
 
        return $this->table[$idx]; 
    } 
 
    /** 
     * Gets raw table. 
     * 
     * @since 1.0 
     * @return array 
     */ 
    public function &getTable ( ) { 
        if ( ! $this->ok () ) { 
            return null; 
        } 
 
        return $this->table; 
    } 
 
    /** 
     * Gets the number of rows. 
     * 
     * @since 1.0 
     * @return integer 
     */ 
    public function getRowCount ( ) { 
        if ( ! $this->ok () ) { 
            return 0; 
        } 
 
        return count ( $this->table ); 
    } 
 
    /** 
     * Checks to see if the table was correctly read into memory. 
     * 
     * @since 1.0 
     * @return boolean 
     */ 
    public function ok () { 
        return is_array ( $this->table ); 
    } 
 
    /** 
     * Checks to see if the table was correctly read into memory. 
     * 
     * @since 1.0 
     * @return boolean 
     */ 
    public function isEmpty () { 
        return $this->getRowCount () <= 0; 
    } 
 
    // Pointer to the current row 
    private $currentRow = 0; 
 
    /** 
     * Iterator function. 
     * 
     * @since 1.0 
     * @return array 
     */ 
    public function ¤t ( ) { 
        return $this->getRow ( $this->currentRow ); 
    } 
 
    /** 
     * Iterator function. 
     * 
     * @since 1.0 
     * @return integer 
     */ 
    public function key ( ){ 
        return $this->currentRow; 
    } 
 
    /** 
     * Iterator function. 
     * 
     * @since 1.0 
     * @return void 
     */ 
    public function next ( ){ 
        ++ $this->currentRow; 
    } 
 
    /** 
     * Iterator function. 
     * 
     * @since 1.0 
     * @return void 
     */ 
    public function rewind ( ){ 
        $this->currentRow = 0; 
    } 
 
    /** 
     * Iterator function. 
     * 
     * @since 1.0 
     * @return boolean 
     */ 
    public function valid (){ 
        return $this->currentRow < $this->getRowCount(); 
    } 
 
    public function  __toString() { 
        $id = 'DBTable_' . Invocation::next(); 
 
        $msg = '<table id="' . $id . '">'; 
        if ( $this->getRowCount() == 0 ) { 
            $msg .= '<tr><td>No Rows</td></tr>'; 
        } 
        else { 
            $firstTime = true; 
            foreach ( $this->table as &$row ) { 
                if ( $firstTime ) { 
                    $msg .= '  <tr>'; 
                    foreach ( $row as $key => &$value ) $msg .= '<th>' . $key . '</th>'; 
                    $msg .= '  </tr>'. "\n"; 
                    $firstTime = false; 
                } 
                $msg .= '  <tr>'; 
                foreach ( $row as &$value ) { 
                    $msg .= '<td>' . $value . '</td>'; 
                } 
                $msg .= '  </tr>'. "\n"; 
            } 
        } 
        $msg .= '</table>'. "\n"; 
        return Widget::styleTable ( '#' . $id ) . $msg; 
    } 
}
 
 |