123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- <?php
- namespace Juju;
- require_once('Data/securestring.class.php');
- require_once('PDO/transaction.class.php');
- require_once('PDO/table.class.php');
- use Juju\{Data\SecureString, PDO\Table, PDO\Transaction};
- class PDO {
- public static function from(string $dsnstring){
- $parts = explode(':', $dsnstring);
- $dsnstring = $parts[1];
- $dsn = explode(';', $dsnstring);
- $dsn = array_reduce($dsn, function($dsn, $item){
- $item = explode('=', $item);
- $dsn[$item[0]] = $item[1];
- return $dsn;
- });
- if(!isset($dsn['host'])){
- throw new \Exception("DSN '{$dsnstring}' missing host");
- }
- if(!isset($dsn['dbname'])){
- throw new \Exception("DSN '{$dsnstring}' missing dbname");
- }
- if(!isset($dsn['user'])){
- $user = $dsn['dbname'];
- }else{
- $user = $dsn['user'];
- }
- if(!isset($dsn['pass'])){
- $dsn['pass'] = $user;
- }
- $pass = SecureString::from($dsn['pass']);
- unset($dsn['pass'], $dsn['user']);
- $dsn = array_reduce(array_keys($dsn), function($a, $key) use($dsn){
- $a[] = "{$key}={$dsn[$key]}";
- return $a;
- });
- $dsnstring = $parts[0].':'.implode(';', $dsn);
- return new PDO($dsnstring, $user, $pass);
- }
- private $pdo;
- private function __construct(string $dsn, string $user, SecureString $pass){
- $mysql = explode(':', $dsn)[0] === 'mysql';
- $options = [];
- if($mysql){
- $options[\PDO::MYSQL_ATTR_INIT_COMMAND] = "SET NAMES 'UTF8'";
- $options[\PDO::MYSQL_ATTR_MULTI_STATEMENTS] = false;
- $options[\PDO::MYSQL_ATTR_FOUND_ROWS] = true;
- }
- $pdo = new \PDO($dsn, $user, (string)$pass, $options);
- $pdo->setAttribute(\PDO::ATTR_AUTOCOMMIT, true);
- $pdo->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_LOWER);
- $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
- $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
- $this->pdo = $pdo;
- }
- public function transaction(callable $fn){
- $pdo = $this->pdo;
- if($pdo->inTransaction()){
- throw new \Exception("Unable to start a new transaction");
- }
- $transaction = new Transaction($this);
- if($fn($transaction) === false){
- do{
- $transaction->rollback();
- }while($transaction->savepoint);
- $pdo->rollback();
- }else{
- $transaction->commit();
- if($pdo->inTransaction()){
- $pdo->commit();
- }
- }
- unset($transaction);
- $pdo->setAttribute(\PDO::ATTR_AUTOCOMMIT, true);
- return $this;
- }
- public function table(string $name){
- return new Table($this, $name);
- }
- public function prepare(string $statement, array $options = []){
- $pdo = $this->pdo;
- if($pdo->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'mysql'){
- $options[\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY] = true;
- }
- $query = $pdo->prepare($statement);
- if($query === false){
- throw $this->getError();
- }
- return $query;
- }
- public function exec(string $statement){
- $query = $this->prepare($statement);
- $count = 0;
- $query->execute();
- while($query->fetch() !== false){
- $count++;
- }
- if($count == 0){
- $count = $query->rowCount();
- }
- $query->closeCursor();
- return $count;
- }
- public function query(string $statement, int $mode = null, ...$args){
- $query = $this->prepare($statement);
- if(!is_null($mode)){
- $query->setFetchMode($mode, ...$args);
- }
- $query->execute();
- return $query;
- }
- public function quote(...$args){
- return $this->pdo->quote(...$args);
- }
- public function beginTransaction(...$args){
- return $this->pdo->beginTransaction(...$args);
- }
- public function setAttribute(...$args){
- return $this->pdo->setAttribute(...$args);
- }
- public function getAttribute(...$args){
- return $this->pdo->getAttribute(...$args);
- }
- public function lastInsertId(...$args){
- return $this->pdo->lastInsertId(...$args);
- }
- public function getError(){
- $error = $this->pdo->errorInfo();
- return new \Exception($error[2], $error[1]);
- }
- }
- ?>
|