<?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;
}
}
|