2018-03-08 19:09:02 +00:00
|
|
|
<?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[] */
|
2018-03-08 19:09:02 +00:00
|
|
|
private $statements = [];
|
2018-03-11 15:14:12 +00:00
|
|
|
|
|
|
|
/** @var bool */
|
2018-03-08 19:09:02 +00:00
|
|
|
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-08 19:09:02 +00:00
|
|
|
|
2018-03-11 15:14:12 +00:00
|
|
|
/**
|
|
|
|
* PDOWrapper constructor.
|
|
|
|
* @param String $dsn
|
|
|
|
* @param String $username
|
|
|
|
* @param String $passwd
|
|
|
|
* @param array $options
|
|
|
|
*/
|
2018-03-08 19:09:02 +00:00
|
|
|
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:09:02 +00:00
|
|
|
{
|
2018-03-08 19:53:40 +00:00
|
|
|
if($this->debugEnabled){
|
|
|
|
$this->storeDebug();
|
|
|
|
}
|
|
|
|
|
2018-03-08 19:09:02 +00:00
|
|
|
if($this->stacking){
|
|
|
|
return new PDOStatementWrapper($statement, $this);
|
|
|
|
}else{
|
|
|
|
return parent::prepare($statement, $options);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
*/
|
2018-03-08 19:09:02 +00:00
|
|
|
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
|
|
|
|
*/
|
2018-03-08 19:09:02 +00:00
|
|
|
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
|
|
|
|
*/
|
2018-03-08 19:09:02 +00:00
|
|
|
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
|
|
|
//get next number
|
|
|
|
$i++;
|
2018-03-08 19:09:02 +00:00
|
|
|
|
2018-03-11 15:14:12 +00:00
|
|
|
//delete the ':' at the beginning of the string
|
|
|
|
$tempKey = ltrim($matches[0],':');
|
2018-03-08 19:09:02 +00:00
|
|
|
|
2018-03-11 15:14:12 +00:00
|
|
|
//copy the parameter with the modified index
|
|
|
|
$tempParametes[$tempKey.$i] = $tempParametes[$tempKey];
|
2018-03-08 19:09:02 +00:00
|
|
|
|
2018-03-11 15:14:12 +00:00
|
|
|
//delete the old index
|
|
|
|
unset($tempParametes[$tempKey]);
|
2018-03-08 19:09:02 +00:00
|
|
|
|
2018-03-11 15:14:12 +00:00
|
|
|
//return the modified string for replacement
|
|
|
|
return $matches[0].$i;
|
2018-03-08 19:09:02 +00:00
|
|
|
},$statement),';').';';
|
|
|
|
|
|
|
|
$finalExecute = array_merge($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);
|
|
|
|
|
2018-03-08 19:09:02 +00:00
|
|
|
$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
|
|
|
|
2018-03-08 19:09:02 +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
|
|
|
|
2018-03-08 19:09:02 +00:00
|
|
|
return $success;
|
|
|
|
}
|
|
|
|
}
|