Model.php 6.1 KB
<?php
/**
 *
 * @author Adhidarma <adhisimon@gmail.com>
 */
abstract class Model extends BaseF3nr {
    const DB_FUNCTION_NOW = "__DB_FUNCTION_NOW__";

    protected $f3;
    private $_db = null;
    protected $table_name;
    protected $table_fields = array();
    protected $table_indexes = array();
    protected $initial_rows = array();

    protected function connectToDb() {
        $db = new \DB\SQL(
            $this->f3->get('db_dsn'),
            $this->f3->get('db_user'),
            $this->f3->get('db_pass')
        );

        $this->setDb($db);
        return $db;
    }

    final protected function setDb($db) {
        $this->_db = $db;
    }

    final protected function getDb() {
        $db = $this->_db;
        if (!$db) {
            return $this->connectToDb();
        }
        return $db;
    }

    protected function getSchema($db = null) {
        if (!$db) {
            $db = $this->getDb();
        }

        $schema = new \DB\SQL\Schemanr($db);
        return $schema;
    }

    final public function getTableName() {
        return $this->table_name;
    }

    public function isTableExists($table_name = null) {
        if (!$table_name) {
            $table_name = $this->getTableName();
        }

        $db = $this->getDb();

        $tables = $this->getSchema($db)->getTables();
        return in_array($table_name, $tables);
    }

    protected function createTable($simulate = null) {
        if ($this->isTableExists($this->getTableName())) {
            return false;
        }

        $schema = $this->getSchema();
        $table = $schema->createTable($this->table_name);

        foreach ($this->table_fields as $key => $properties) {
            $table->addColumn($key, $properties);
        }

        foreach ($this->table_indexes as $item) {
            $table->addIndex($item['columns'], $item['unique']);
        }

        $retval = $table->build(!$simulate);

        if ($simulate) {
            return $retval;
        } else {
            return $this->isTableExists($this->getTableName());
        }
    }

    public function dropTable($simulate = null) {
        $schema = $this->getSchema();
        $retval = $schema->dropTable($this->getTableName(), !$simulate);

        if ($simulate) {
            return retval;
        } else {
            return true;
        }
    }

    /**
     * Mengembalikan mapper database terkait.
     * 
     * @return \DB\SQL\Mapper
     */
    public function getMapper() {
        return new DB\SQL\Mapper($this->getDb(), $this->getTableName());
    }

    public function uninstall() {
        $test = new Test();

        $test->expect(
            $this->dropTable(),
            'Drop table "' . $this->getTableName() . '"'
        );


        $test->expect(
            !$this->isTableExists(),
            'Tabel "' . $this->getTableName() . '" does not exist'
        );

        $this->dumpTestResult($test);
    }

    public function install() {
        $test = new Test();

        if ($this->isTableExists()) {
            $test->expect(
                true,
                'Table ' . $this->getTableName() . ' already exists, skipping it'
            );

            $this->dumpTestResult($test);
            return;
        }

        $test->expect(
            !$this->isTableExists(),
            'Tabel "' . $this->getTableName() . '"does not exists'
        );

        $test->expect(
            $this->createTable(),
            'Create table "' . $this->getTableName() . '"'
        );

        $test->expect(
            $this->isTableExists(),
            'Tabel "' . $this->getTableName() . '" exists'
        );

        if (!empty($this->initial_rows)) {

            $test->expect(
                'true',
                'Found one or more initial rows to insert to table "' . $this->getTableName() . '"'
            );

            $test->expect(
                $this->populateInitialRows(),
                'Populating initial rows on table "' . $this->getTableName() . '"'
            );

        } else {

            $test->expect(
                'true',
                'Empty array, skip populating initial rows on table "' . $this->getTableName() . '"'
            );

        }

        $this->dumpTestResult($test);
    }

    public function test($f3 = null) {
        if (!$f3) { $f3 = $this->f3; }

        //$this->testDropAndCreateTable();
        $this->testTableHealth();
        $this->dumpTestResult();
    }

    protected function testTableHealth() {
        $test = $this->test;

        $test->expect(
            $this->isTableExists(),
            'Table ' . $this->getTableName() . ' is exists'
        );
    }

    protected function populateInitialRows() {
        if (empty($this->initial_rows)) {
            return false;
        }

        foreach ($this->initial_rows as $row) {
            $user = $this->getMapper();
            foreach ($row as $field_name => $field_value) {
                if ($field_value == self::DB_FUNCTION_NOW) {
                    $field_value = date('Y-m-d H:i:s');
                }
                $user[$field_name] = $field_value;
            }
            $user->save();
        }
        return true;
    }

    public function getMapperItemByFieldValue($field, $value) {
        $item = $this->getMapper();
        $item->load(array("$field=?", $value));
        return $item;
    }

    
    /**
     * Mengambil item dengan kriteria berdasarkan suatu field.
     * 
     * @param string $field nama field
     * @param mixed $value nilai field
     * @return array|NULL item terkait dalam bentuk array atau NULL jika tidak tersedia. 
     */
    public function getItemByFieldValue($field, $value) {
        $item = $this->getMapperItemByFieldValue($field, $value);

        if ($item->dry()) {
            return null;
        }

        return $item->cast();
    }

    public function getItemById($id) {
        return $this->getItemByFieldValue('id', $id);
    }

    /**
     * Mengambil item dengan id tertentu.
     * 
     * @param mixed $id
     * @return array|NULL item terkait dalam bentuk array atau NULL jika tidak tersedia.
     */
    public function getById($id) {
        return $this->getItemById($id);
    }

}