php-vivace/db

View on GitHub
src/sql/Driver.php

Summary

Maintainability
B
4 hrs
Test Coverage
<?php
/**
 * Created by PhpStorm.
 * User: macbookpro
 * Date: 14.02.2018
 * Time: 14:18
 */

namespace vivace\db\sql;


use vivace\db\sql\Statement\Columns;

abstract class Driver
{
    protected $schemas;

    /**
     * @param \vivace\db\sql\Statement\Statement|array $statement
     *
     * @return array [string $query, array $params]
     */
    abstract public function build($statement): array;

    /**
     * @param \vivace\db\sql\Statement\Read $query
     *
     * @return \vivace\db\sql\Fetcher
     */
    abstract public function fetch(Statement\Read $query): Fetcher;

    abstract public function execute(Statement\Modifier $query): Result;

    /**
     * Type casting for the value passed to the store
     *
     * @param \vivace\db\sql\Field $field
     * @param $value
     *
     * @return mixed
     */
    function typecastIn(Field $field, $value)
    {
        switch ($field->getType()) {
            case Field::TYPE_BOOL:
            case Field::TYPE_INT:
            case Field::TYPE_STRING:
            case Field::TYPE_FLOAT:
                settype($value, $field->getType());
                break;
            case Field::TYPE_TIMESTAMP;
                if ($value instanceof \DateTime) {
                    $value = $value->format(\DateTime::ISO8601);
                }
                break;
        }

        return $value;
    }


    /**
     * Type casting for the received value from the store
     *
     * @param \vivace\db\sql\Field $field
     * @param $value
     *
     * @return mixed
     */
    function typecastOut(Field $field, $value)
    {
        switch ($field->getType()) {
            case Field::TYPE_BOOL:
            case Field::TYPE_INT:
            case Field::TYPE_STRING:
            case Field::TYPE_FLOAT:
                settype($value, $field->getType());
                break;
            case Field::TYPE_TIMESTAMP;
                $value = new \DateTime($value);
                break;
        }

        return $value;
    }

    /**
     * @param string $source
     * @param bool $refresh
     *
     * @return \vivace\db\sql\Schema|\vivace\db\sql\Field[]
     */
    public function schema(string $source, bool $refresh = false): Schema
    {
        if (!$refresh && isset($this->schemas[$source])) {
            return $this->schemas[$source];
        }

        $fields = [];
        foreach ($this->fetch(new Columns($source))->all() as $item) {
            $fields[$item['name']] = $item;
        }

        return $this->schemas[$source] = new class ($fields) implements Schema
        {
            /** @var Field[] */
            protected $fields = [];
            /** @var \vivace\db\sql\Field|null */
            protected $autoincrement;
            /** @var \vivace\db\sql\Field[] */
            protected $primary = [];
            /** @var \vivace\db\sql\Field[] */
            protected $unique = [];

            public function __construct($fieldsArr)
            {
                foreach ($fieldsArr as $name => $fieldArr) {
                    $field = new class($fieldArr) implements Field
                    {
                        /**
                         * @var array
                         */
                        protected $field;


                        public function __construct($field)
                        {
                            $this->field = $field;
                        }

                        public function getName(): string
                        {
                            return $this->field['name'];
                        }

                        public function getType(): string
                        {
                            return $this->field['type'];
                        }

                        public function isPrimary(): bool
                        {
                            return (bool)$this->field['primary'];
                        }

                        public function isUnique(): bool
                        {
                            return (bool)$this->field['unique'];
                        }

                        public function isNullable(): bool
                        {
                            return (bool)$this->field['nullable'];
                        }

                        public function isDefault(): bool
                        {
                            return $this->field['default'] !== null || $this->isNullable();
                        }

                        public function isAutoincrement(): bool
                        {
                            return (bool)$this->field['autoincrement'];
                        }

                        public function getDefault()
                        {
                            return $this->field['default'];
                        }


                    };

                    if ($field->isAutoincrement()) {
                        $this->autoincrement = $field;
                    }
                    if ($field->isPrimary()) {
                        $this->primary[] = $field;
                    }
                    if ($field->isUnique()) {
                        $this->unique[] = $field;
                    }
                    $this->fields[$name] = $field;
                }
            }

            public function getAutoincrement(): ?Field
            {
                return $this->autoincrement;
            }


            /** @inheritdoc */
            public function getIterator()
            {
                return new \ArrayIterator($this->fields);
            }

            /** @inheritdoc */
            public function getPrimary(): ?array
            {
                return $this->primary;
            }

            /** @inheritdoc */
            public function get(string $key): Field
            {
                return $this->fields[$key];
            }

            /** @inheritdoc */
            public function has(string $key): bool
            {
                return isset($this->fields[$key]);
            }

            /** @inheritdoc */
            public function count()
            {
                return count($this->fields);
            }

            public function getNames(): array
            {
                return array_keys($this->fields);
            }

            /** @inheritdoc */
            public function getUnique(): ?array
            {
                return $this->unique;
            }
        };
    }
}