phossa2/query

View on GitHub
src/Query/Builder.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php
/**
 * Phossa Project
 *
 * PHP version 5.4
 *
 * @category  Library
 * @package   Phossa2\Query
 * @copyright Copyright (c) 2016 phossa.com
 * @license   http://mit-license.org/ MIT License
 * @link      http://www.phossa.com/
 */
/*# declare(strict_types=1); */

namespace Phossa2\Query;

use Phossa2\Query\Misc\Raw;
use Phossa2\Query\Dialect\Mysql;
use Phossa2\Query\Misc\Expression;
use Phossa2\Shared\Base\ObjectAbstract;
use Phossa2\Query\Traits\SettingsAwareTrait;
use Phossa2\Query\Traits\DialectAwareTrait;
use Phossa2\Query\Traits\ParameterAwareTrait;
use Phossa2\Query\Interfaces\BuilderInterface;
use Phossa2\Query\Interfaces\DialectInterface;
use Phossa2\Query\Interfaces\StatementInterface;
use Phossa2\Query\Interfaces\Clause\ColInterface;
use Phossa2\Query\Interfaces\Statement\UnionStatementInterface;
use Phossa2\Query\Interfaces\Statement\SelectStatementInterface;
use Phossa2\Query\Interfaces\Statement\InsertStatementInterface;
use Phossa2\Query\Interfaces\Statement\UpdateStatementInterface;
use Phossa2\Query\Interfaces\Statement\DeleteStatementInterface;

/**
 * Builder
 *
 * @package Phossa2\Query
 * @author  Hong Zhang <phossa@126.com>
 * @see     ObjectAbstract
 * @see     BuilderInterface
 * @see     StatementInterface
 * @see     SelectStatementInterface
 * @see     InsertStatementInterface
 * @see     UnionStatementInterface
 * @see     UpdateStatementInterface
 * @see     DeleteStatementInterface
 * @version 2.0.0
 * @since   2.0.0 added
 */
class Builder extends ObjectAbstract implements BuilderInterface
{
    use DialectAwareTrait, SettingsAwareTrait, ParameterAwareTrait;

    /**
     * tables
     *
     * @var    array
     * @access protected
     */
    protected $tables = [];

    /**
     * Constructor
     *
     * ```php
     * // builder with default table `users` and Mysql dialect
     * $users = new Builder('users', new Mysql())
     *
     * // builder with defult tables:  `users` and `accounts` AS `a`
     * $builder = new Builder(['users', 'accounts' => 'a'])
     *
     * // change default settings
     * $builder = new Builder('users', new Mysql(), ['autoQuote' => false]);
     * ```
     *
     * @param  string|array $table table[s] to build upon
     * @param  DialectInterface $dialect default dialect is `Mysql`
     * @param  array $settings builder settings
     * @access public
     */
    public function __construct(
        $table = '',
        DialectInterface $dialect = null,
        array $settings = []
    ) {
        $this
            ->initParameter()
            ->setSettings(array_replace($this->defaultSettings(), $settings))
            ->setDialect($dialect)
            ->table($table);
    }

    /**
     * Change table[s]
     *
     * @param  $table change to table[s]
     * @return $this
     * @access public
     */
    public function __invoke($table)
    {
        return $this->table($table);
    }

    /**
     * {@inheritDoc}
     */
    public function expr()/*# : ExpressionInterface */
    {
        return new Expression($this);
    }

    /**
     * {@inheritDoc}
     */
    public function raw(
        /*# string */ $string,
        array $values = []
    )/*# : OutputInterface */ {
        if (!empty($values)) {
            $string = $this->getParameter()->replaceQuestionMark($string, $values);
        }
        return new Raw($string);
    }

    /**
     * If has existing tables, return a new instance with provided table[s]
     *
     * {@inheritDoc}
     */
    public function table($table, /*# string */ $alias = '')
    {
        $tbl = $this->fixTable($table, $alias);
        $clone = [] === $this->tables ? $this : clone $this;
        $clone->tables = $tbl;
        return $clone;
    }

    /**
     * Append to existing tables
     *
     * {@inheritDoc}
     */
    public function from($table, /*# string */ $alias = '')
    {
        $tbl = $this->fixTable($table, $alias);
        $this->tables = array_merge($this->tables, $tbl);
        return $this;
    }

    /**
     * {@inheritDoc}
     */
    public function select()/*# : SelectStatementInterface */
    {
        /* @var SelectStatementInterface $select */
        $select = $this->getDialect()->select($this);
        return $select->table($this->tables)->col(func_get_args());
    }

    /**
     * {@inheritDoc}
     */
    public function insert(array $values = [])/*# : InsertStatementInterface */
    {
        /* @var InsertStatementInterface $insert */
        $insert = $this->getDialect()->insert($this);
        return $insert->into(current($this->tables))->set($values);
    }

    /**
     * {@inheritDoc}
     */
    public function replace(array $values = [])/*# : InsertStatementInterface */
    {
        /* @var InsertStatementInterface $insert */
        $replace = $this->getDialect()->replace($this);
        return $replace->into(current($this->tables))->set($values);
    }

    /**
     * {@inheritDoc}
     */
    public function update(array $values = [])/*# : UpdateStatementInterface */
    {
        /* @var UpdateStatementInterface $update */
        $update = $this->getDialect()->update($this);
        return $update->from(current($this->tables))->set($values);
    }

    /**
     * {@inheritDoc}
     */
    public function delete()/*# : DeleteStatementInterface */
    {
        /* @var DeleteStatementInterface $delete */
        $delete = $this->getDialect()->delete($this)->from(current($this->tables));

        if ($delete instanceof ColInterface) { // multiple table deletion
            $delete->col(func_get_args());
        }
        return $delete;
    }

    /**
     * {@inheritDoc}
     */
    public function union()/*# : UnionStatementInterface */
    {
        /* @var UnionStatementInterface $union */
        $union = $this->getDialect()->union($this);
        if (func_num_args() > 0) { // acception variable parameters
            $args = func_get_args();
            foreach ($args as $arg) {
                $union->union($arg);
            }
        }
        return $union;
    }

    /**
     * Convert to [$table => alias] or [$table]
     *
     * @param  string|string[] $table
     * @param  string $alias
     * @return array
     * @access protected
     */
    protected function fixTable(
        $table,
        /*# string */ $alias = ''
    )/*# : array */ {
        if (empty($table)) {
            $table = [];
        } elseif (!is_array($table)) {
            $table = empty($alias) ? [$table] : [$table => $alias];
        }
        return $table;
    }

    /**
     * Builder default settings
     *
     * @return array
     * @access protected
     */
    protected function defaultSettings()/*# : array */
    {
        return [
            'autoQuote' => true,
            'positionedParam' => true,
            'namedParam' => false,
            'seperator' => ' ',
            'indent' => '',
            'escapeFunction' => null,
            'useNullAsDefault' => false,
        ];
    }
}