<?php
/**
 * SIE ASESORIAS - Plugin BEZ (Helper Component)
 * Sistema de gestion de proyectos de auditoria
 *
 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
 * @author  SIE ASESORIAS <soporte@sieasesorias.com>
 */

// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();

require_once(dirname(__DIR__) . '/meta/path_helper.php');

class helper_plugin_bez_db extends DokuWiki_Plugin {
    /** @var helper_plugin_sqlite */
    protected $sqlite;

    /**
     * helper_plugin_bez_db constructor.
     */
    public function __construct() {
        $this->init();
    }

    /**
     * Initialize the database
     *
     * @throws Exception
     */
    protected function init() {
        /** @var helper_plugin_sqlite $sqlite */
        $this->sqlite = plugin_load('helper', 'sqlite');
        if(!$this->sqlite) {
            if(defined('DOKU_UNITTEST')) throw new \Exception('Couldn\'t load sqlite.');
            return;
        }

        if($this->sqlite->getAdapter()->getName() != DOKU_EXT_PDO) {
            if(defined('DOKU_UNITTEST')) throw new \Exception('Couldn\'t load PDO sqlite.');
            $this->sqlite = null;
            return;
        }
        $this->sqlite->getAdapter()->setUseNativeAlter(true);

        // initialize the database connection
        if(!$this->sqlite->init('b3p', bez_plugin_base() . 'bez/db/')) {
            if(defined('DOKU_UNITTEST')) throw new \Exception('Couldn\'t init sqlite.');
            $this->sqlite = null;
            return;
        }


    }

    /**
     * @param bool $throw throw an Exception when sqlite not available?
     * @return helper_plugin_sqlite|null
     */
    public function getDB($throw=true) {
        global $conf;
        $len = strlen($conf['metadir']);
        if ($this->sqlite && $conf['metadir'] != substr($this->sqlite->getAdapter()->getDbFile(),0,$len)) {
            $this->init();
        }
        if(!$this->sqlite && $throw) {
            throw new \Exception('no sqlite');
        }
        return $this->sqlite;
    }

    /**
     * Inicializa la conexión DB y opcionalmente una Factory.
     * Uso: list($sqlite, $factory) = helper_plugin_bez_db::initAdmin('AdminThreadFactory', true, true);
     *
     * @param string|null $factoryClass  Nombre de clase (sin namespace): 'AdminThreadFactory' o 'AdminControlHelper'
     * @param bool        $ensureTables  Llamar ensureTables() en la factory (si existe el método)
     * @param bool        $ensureDefault Llamar ensureDefaultProject() en la factory (si existe el método)
     * @return array [$sqlite, $factory|null]
     * @throws \Exception si no se puede conectar
     */
    public static function initAdmin($factoryClass = null, $ensureTables = false, $ensureDefault = false) {
        $db_helper = plugin_load('helper', 'bez_db');
        if (!$db_helper) {
            throw new \Exception('No se pudo cargar el helper de base de datos BEZ');
        }

        $sqlite = $db_helper->getDB();
        if (!$sqlite) {
            throw new \Exception('No se pudo conectar a la base de datos');
        }

        $factory = null;
        if ($factoryClass) {
            $file = bez_plugin_base() . 'bez/mdl/' . $factoryClass . '.php';
            if (!file_exists($file)) {
                throw new \Exception("Archivo de factory no encontrado: $factoryClass");
            }
            require_once($file);
            $fullClass = 'dokuwiki\\plugin\\bez\\mdl\\' . $factoryClass;
            if (class_exists($fullClass)) {
                $factory = new $fullClass($sqlite);
            } else {
                $factory = new $factoryClass($sqlite);
            }

            if ($ensureTables && method_exists($factory, 'ensureTables')) {
                $factory->ensureTables();
            }
            if ($ensureDefault && method_exists($factory, 'ensureDefaultProject')) {
                $factory->ensureDefaultProject();
            }
        }

        return [$sqlite, $factory];
    }

    /**
     * Completely remove the database and reinitialize it
     *
     * You do not want to call this except for testing!
     */
    public function resetDB() {
        if(!$this->sqlite) return;
        $file = $this->sqlite->getAdapter()->getDbFile();
        if(!$file) return;
        unlink($file);
        clearstatcache(true, $file);
        $this->init();
    }
}

// vim:ts=4:sw=4:et:
