<?php
namespace queasy\db;
use BadMethodCallException;
use PDO;
use ArrayAccess;
use Countable;
use Iterator;
use Psr\Log\NullLogger;
use Psr\Log\LoggerInterface;
use Psr\Log\LoggerAwareInterface;
use queasy\db\query\CustomQuery;
use queasy\db\query\CountQuery;
use queasy\db\query\SelectQuery;
use queasy\db\query\UpdateQuery;
use queasy\db\query\DeleteQuery;
class Table implements ArrayAccess, Countable, Iterator, LoggerAwareInterface
{
protected $pdo;
protected $name;
protected $fields;
protected $rows;
/**
* Config instance.
*
* @var array|ArrayAccess
*/
protected $config;
/**
* Logger instance.
*
* @var LoggerInterface
*/
protected $logger;
public function __construct(PDO $pdo, $name, $config = array())
{
$this->logger = new NullLogger();
$this->pdo = $pdo;
$this->name = $name;
$this->fields = array();
$this->rows = null;
$this->config = $config;
}
public function __get($fieldName)
{
return $this[$fieldName];
}
public function count()
{
$query = new CountQuery($this->pdo, $this->name);
$query->setLogger($this->logger);
$statement = $query();
$row = $statement->fetch();
return array_shift($row);
}
public function current()
{
return current($this->rows);
}
public function key()
{
return key($this->rows);
}
public function next()
{
return next($this->rows);
}
public function rewind()
{
$this->all();
}
public function valid()
{
return isset($this->rows[$this->key()]);
}
public function all()
{
$query = new SelectQuery($this->pdo, $this->name);
$statement = $query();
$this->rows = $statement->fetchAll();
return $this->rows;
}
public function insert()
{
$params = (1 === func_num_args())
? func_get_arg(0)
: func_get_args();
if ((null === $params) || !is_array($params)) {
throw new InvalidArgumentException('Wrong rows argument.');
}
$isSingleInsert = true;
$keys = array_keys($params);
if (count($keys) && is_array($params[$keys[0]])) { // Batch inserts
$isSingleInsert = false;
if (!((2 === count($params))
&& is_array($params[1])
&& (0 < count($params[1]))
&& isset($params[1][0])
&& is_array($params[1][0]))) { // Batch insert with field names listed in a separate array
$keys = array_keys($params[$keys[0]]);
$queryClass = (!count($keys) || is_numeric($keys[0]))
? 'queasy\\db\\query\\BatchInsertQuery' // Batch insert
: 'queasy\\db\\query\\BatchNamedInsertQuery'; // Batch insert with field names
} else {
$queryClass = 'queasy\\db\\query\\BatchSeparatelyNamedInsertQuery';
}
} else { // Single inserts
$queryClass = (!count($keys) || is_numeric($keys[0]))
? 'queasy\\db\\query\\SingleInsertQuery' // By order, without field names
: 'queasy\\db\\query\\SingleNamedInsertQuery'; // By field names
}
$query = new $queryClass($this->pdo, $this->name);
$query->setLogger($this->logger);
$statement = $query($params);
return $isSingleInsert
? $this->pdo->lastInsertId()
: $statement->rowCount();
}
public function update(array $params, $fieldName = null, $fieldValue = null, array $options = array())
{
$query = new UpdateQuery($this->pdo, $this->name, $fieldName, $fieldValue);
$query->setLogger($this->logger);
$statement = $query($params, $options);
return $statement->rowCount();
}
public function delete($fieldName = null, $fieldValue = null, array $options = array())
{
$query = new DeleteQuery($this->pdo, $this->name, $fieldName, $fieldValue);
$query->setLogger($this->logger);
$statement = $query(array(), $options);
return $statement->rowCount();
}
public function offsetExists($offset)
{
throw new BadMethodCallException(sprintf('Not implemented.', $offset));
}
public function offsetGet($offset)
{
if (!isset($this->fields[$offset])) {
$field = new Field($this->pdo, $this, $offset);
$field->setLogger($this->logger);
$this->fields[$offset] = $field;
}
return $this->fields[$offset];
}
public function offsetSet($offset, $value)
{
if (null !== $offset) {
throw new BadMethodCallException('Not implemented. Use Field instead of Table to update record.');
}
$this->insert($value);
}
public function offsetUnset($offset)
{
throw new BadMethodCallException(sprintf('Not implemented.', $offset));
}
/**
* Calls an user-defined (in configuration) method
*
* @param string $method Method name
* @param array $args Arguments
*
* @return mixed Return type depends on configuration. It can be a single value, an object, an array, or an array of objects or arrays
*
* @throws DbException On error
*/
public function __call($method, array $args)
{
if (isset($this->config[$method])) {
$query = new CustomQuery($this->pdo, $this->config[$method]);
$query->setLogger($this->logger);
return call_user_func_array(array($query, 'run'), $args);
}
$field = $this[$method];
return $field($args[0]);
}
/**
* Sets a logger.
*
* @param LoggerInterface $logger
*/
public function setLogger(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function getName()
{
return $this->name;
}
}
|