sovereignbot/citadel

View on GitHub
src/Lib/Db.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php
namespace Sovereign\Lib;

use League\Container\Container;
use Monolog\Logger;

/**
 * Class Db
 * @package Sovereign\Lib
 */
class Db
{
    /**
     * @var Config
     */
    protected $config;
    /**
     * @var Logger
     */
    protected $log;
    /**
     * @var \PDO
     */
    private $pdo;
    /**
     * @var Container
     */
    private $container;

    /**
     * Db constructor.
     * @param Config $config
     * @param Logger $log
     * @param Container $container
     */
    public function __construct(Config $config, Logger $log, Container $container)
    {
        $this->log = $log;
        $this->config = $config;
        $this->pdo = $this->connect();
        $this->container = $container;
    }

    /**
     * @return array
     * Upon sleeping (which is needed for pthreads to work with pdo) we just return an empty array, which is the default for all the query functions anyway
     * It doesn't really matter what we return tho, since once the thread wakes up, the __wakeup function is ran
     */
    public function __sleep()
    {
        return array();
    }

    /**
     * This is for the pthreads compatibility - for some reason the DB just goes tits up when using pthreads
     * and PDO.. Hence the __wakeup() call, that restarts the database.
     * No numbers on it, but it more than likely adds quite a bit of latency.
     */
    public function __wakeup()
    {
        $this->container = getContainer();
        $this->log = $this->container->get('log');
        $this->config = $this->container->get('config');
        $this->pdo = $this->connect();
    }

    /**
     * @return \PDO
     */
    private function connect()
    {
        $dsn = "mysql:dbname={$this->config->get("dbName", "db")};host={$this->config->get("dbHost", "db")}";
        try {
            $pdo = new \PDO($dsn, $this->config->get("dbUser", "db"), $this->config->get("dbPass", "db"), array(
                \PDO::ATTR_PERSISTENT => false,
                \PDO::ATTR_EMULATE_PREPARES => true,
                \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
                \PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
                \PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = '+00:00',NAMES utf8;"
            ));
        } catch (\Exception $e) {
            $this->log->addCritical("Unable to connect to database: ", [$e->getMessage()]);
            die();
        }

        return $pdo;
    }

    /**
     * @param String $query
     * @param array $parameters
     * @return array
     */
    public function queryRow(String $query, $parameters = array())
    {
        $result = $this->query($query, $parameters);

        if (count($result) >= 1) {
            return $result[0];

    }
        return array();
    }

    /**
     * @param String $query
     * @param array $parameters
     * @return array
     */
    public function query(String $query, $parameters = array())
    {
        try {
            $stmt = $this->pdo->prepare($query);
            $stmt->execute($parameters);

            if ($stmt->errorCode() != 0) {
                return array();
            }

            $result = $stmt->fetchAll(\PDO::FETCH_ASSOC);

            $stmt->closeCursor();

            return $result;
        } catch (\Exception $e) {
            $this->log->addError("There was an error during a query: ", [$e->getMessage()]);
            try {
                $this->pdo = $this->connect();
            } catch (\Exception $e2) {
                $this->log->addCritical("Couldn't reconnect to the database: " . $e->getMessage());
                die(1);
            }
        }
        return array();
    }

    /**
     * @param String $query
     * @param String $field
     * @param array $parameters
     * @return string
     */
    public function queryField(String $query, String $field, $parameters = array())
    {
        $result = $this->query($query, $parameters);

        if (count($result) == 0) {
            return "";
        }

        $resultRow = $result[0];
        return $resultRow[$field];
    }

    /**
     * @param String $query
     * @param array $parameters
     * @return int|null|string
     */
    public function execute(String $query, $parameters = array())
    {
        try {
            $this->pdo->beginTransaction();

            $stmt = $this->pdo->prepare($query);
            $stmt->execute($parameters);

            if ($stmt->errorCode() != 0) {
                $this->pdo->rollBack();
                return 0;
            }

            $returnID = $this->pdo->lastInsertId();
            $this->pdo->commit();
            $stmt->closeCursor();

            return $returnID;
        } catch (\Exception $e) {
            $this->log->addError("There was an error during a query: ", [$e->getMessage()]);
            try {
                $this->pdo = $this->connect();
            } catch (\Exception $e2) {
                $this->log->addCritical("Couldn't reconnect to the database: " . $e->getMessage());
                die(1);
            }
        }
        return null;
    }
}