ptut-vhost/build/database/core/PDOWrapper/PDOWrapper.php

198 lines
4.6 KiB
PHP
Raw Permalink Normal View History

<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 30/08/16
* Time: 17:26
*/
namespace database\core\PDOWrapper;
class PDOWrapper extends \PDO
{
2018-03-11 15:14:12 +00:00
/** @var PDOStatementWrapper[] */
private $statements = [];
2018-03-11 15:14:12 +00:00
/** @var bool */
private $stacking = false;
2018-03-11 15:14:12 +00:00
/** @var array */
2018-03-08 19:53:40 +00:00
private $debug = [];
2018-03-11 15:14:12 +00:00
/** @var bool */
2018-03-08 19:53:40 +00:00
private $debugEnabled = false;
2018-03-11 15:14:12 +00:00
/**
* PDOWrapper constructor.
* @param String $dsn
* @param String $username
* @param String $passwd
* @param array $options
*/
public function __construct(String $dsn, String $username, String $passwd, array $options = [])
{
parent::__construct($dsn, $username, $passwd, $options);
}
2018-03-11 15:14:12 +00:00
/**
* @param string $statement
* @param array $options
* @return \PDOStatement
*/
public function prepare($statement, $options = []) : \PDOStatement
{
2018-03-08 19:53:40 +00:00
if($this->debugEnabled){
$this->storeDebug();
}
if($this->stacking){
return new PDOStatementWrapper($statement, $this);
}else{
2018-05-10 13:09:40 +00:00
$st = parent::prepare($statement, $options);
if($st === false){
throw new \PDOException("There is an error in your SQL statement");
}
return $st;
}
}
2018-03-11 15:14:12 +00:00
/**
* @throws \ReflectionException
*
* @return void
*/
2018-03-08 19:53:40 +00:00
private function storeDebug(){
//get all the debug info about the repo
$prepareStack = debug_backtrace(0,3)[1];
$stack = debug_backtrace(0,3)[2];
//create the reflection object
$f = new \ReflectionMethod($stack["class"],$stack["function"]);
//get only the repo name
$className = explode("\\",$stack["class"]);
$className = $className[count($className)-1];
$result = [];
//if we are flushing a stack, just count the number of request stacked
if($stack["function"] == "executeStack"){
$result["StackedRequest"] = true;
$result["numberOfStackedRequest"] = substr_count($prepareStack["args"][0],";");
//if we are not stacking, log the repo call
}else if(!$this->stacking){
//store results
$result["repoName"] = $className;
$result["methodName"] = $stack["function"];
$result["args"] = [];
foreach ($f->getParameters() as $key => $param) {
$result["args"][$param->name] = $stack["args"][$key];
}
//else we are stacking a request, we should not log it
}else{
return;
}
$this->debug[] = $result;
}
2018-03-11 15:14:12 +00:00
/**
* @return array
*/
2018-03-08 19:53:40 +00:00
public function getDebug() : array{
return $this->debug;
}
2018-03-11 15:14:12 +00:00
/**
* Enable request stacking
*/
public function enableStacking(){
$this->stacking = true;
}
2018-03-11 15:14:12 +00:00
/**
* @return bool
*/
2018-03-08 19:53:40 +00:00
public function isDebugEnabled() : bool{
return $this->debugEnabled;
}
2018-03-11 15:14:12 +00:00
/**
* @param PDOStatementWrapper $st
*/
public function stackStatement(PDOStatementWrapper $st){
array_push($this->statements,$st);
}
2018-03-11 15:14:12 +00:00
/**
* Enable repo debug
*/
2018-03-08 19:53:40 +00:00
public function enableDebug(){
$this->debugEnabled = true;
}
2018-03-11 15:14:12 +00:00
/**
* disable repo debug
*/
2018-03-08 19:53:40 +00:00
public function disableDebug(){
$this->debugEnabled = false;
}
2018-03-11 15:14:12 +00:00
/** Execute the stored request stack
* @return bool
*/
public function executeStack(){
//init the statements and the generator of number
$finalStatement = '';
$finalExecute = [];
$i = 0;
//for each request stacked
foreach ($this->statements as $request){
$statement = $request->getStatement();
// we have to modify the parameters index at the same time that we modify the request, so we use static class attribute
$tempParametes = $request->getParameters();
//find the given pattern in the request, then call our function and replace the matched string by the return value of our function
$finalStatement .= rtrim(preg_replace_callback("/(:[a-z_\-0-9]*)/is",function($matches) use (&$i,&$tempParametes){
2018-03-11 15:14:12 +00:00
//copy the parameter with the modified index
$tempParametes[":$i"] = $tempParametes[$matches[0]];
2018-03-11 15:14:12 +00:00
//delete the old index
unset($tempParametes[$matches[0]]);
2018-03-11 15:14:12 +00:00
//return the modified string for replacement
return ":".$i++;
},$statement),';').';';
$finalExecute += $tempParametes;
}
//disable stacking
$this->stacking = false;
2018-03-11 15:14:12 +00:00
//enable prepare emulation (native prepare do not accept stacked requests
parent::setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
$this->beginTransaction();
$req = $this->prepare($finalStatement);
$success = $req->execute($finalExecute);
//as we execute multiple query that we don't fetch, we have to close the cursor if we want to do other requests later
$req->closeCursor();
$this->commit();
2018-03-11 15:14:12 +00:00
//using beginTransaction/commit disable the autocommit, we re-activate it
$this->setAttribute(\PDO::ATTR_AUTOCOMMIT,1);
parent::setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
2018-03-11 15:14:12 +00:00
return $success;
}
}