diff --git a/build/api/core/Request.php b/build/api/core/Request.php index dce1f28..f9a9ac3 100755 --- a/build/api/core/Request.php +++ b/build/api/core/Request.php @@ -5,7 +5,8 @@ use \api\core\AuthSystem; use \api\core\ModuleFactory; use \api\core\Config; - use \error\core\Error; +use database\core\Repo; +use \error\core\Error; use \error\core\Err; @@ -503,6 +504,11 @@ /* (3) On ajoute les données */ $response->appendAll($returned); + /* (4) Si le Debug est actif on ajoute le debug des repo */ + if(Repo::isDebugEnabled()){ + $response->append("repoDebug" , Repo::getDebug()); + } + /* (4) On retourne la réponse */ return $response; diff --git a/build/api/module/excelController.php b/build/api/module/excelController.php index e3c4a4d..2e1fb4b 100644 --- a/build/api/module/excelController.php +++ b/build/api/module/excelController.php @@ -63,9 +63,11 @@ class excelController $addEU = function() use (&$UECode,&$allUE,&$UE){ //determine if UE is disabled (if cours+td+tp = 0) $totalVH = 0; - foreach ($UE["groups"] as $groups){ - foreach ($groups as $group){ - $totalVH += $group["VH"]; + if(is_array($UE["groups"]) && count($UE["groups"]) > 0){ + foreach ($UE["groups"] as $groups){ + foreach ($groups as $group){ + $totalVH += $group["VH"]; + } } } @@ -348,6 +350,10 @@ class excelController /** @var tp $tpRepo */ $tpRepo = Repo::getRepo("tp"); + $CoursToLink = []; + $TDToLink = []; + $TPToLink = []; + foreach ($allUE as $codeUE => $UE){ if($UE["defaultFormation"]){ @@ -377,22 +383,25 @@ class excelController switch ($type){ case "Course": - $coursRepo->create( $codeUE, - $allProf[$group["professor"]]["dbId"], - $UE["disabled"] ? $UE["CourseVH"] : $group["VH"], - $formations); + $CoursToLink[] = ["id" => $coursRepo->create( $codeUE, + $allProf[$group["professor"]]["dbId"], + $UE["disabled"] ? $UE["CourseVH"] : $group["VH"], + []), + "form" => $formations]; break; case "TD": - $tdRepo->create($codeUE, - $allProf[$group["professor"]]["dbId"], - $UE["disabled"] ? $UE["TdVH"] : $group["VH"], - $formations); + $TDToLink[] = ["id" => $tdRepo->create($codeUE, + $allProf[$group["professor"]]["dbId"], + $UE["disabled"] ? $UE["TdVH"] : $group["VH"], + []), + "form" => $formations]; break; case "TP": - $tpRepo->create($codeUE, - $allProf[$group["professor"]]["dbId"], - $UE["disabled"] ? $UE["TpVH"] : $group["VH"], - $formations); + $TPToLink[] = ["id" => $tpRepo->create($codeUE, + $allProf[$group["professor"]]["dbId"], + $UE["disabled"] ? $UE["TpVH"] : $group["VH"], + []), + "form" => $formations]; break; } @@ -401,7 +410,28 @@ class excelController } } - return [ 'data' => ["professors" => $allProf, "formations" => $allFormations, "UEs" => $allUE ] ]; + Repo::enableStacking(); + + foreach ($CoursToLink as $cour){ + foreach ($cour["form"] as $formation){ + $coursRepo->linkFormation($formation,$cour["id"]); + } + } + foreach ($TDToLink as $cour){ + foreach ($cour["form"] as $formation){ + $tdRepo->linkFormation($formation,$cour["id"]); + } + } + foreach ($TPToLink as $cour){ + foreach ($cour["form"] as $formation){ + $tpRepo->linkFormation($formation,$cour["id"]); + } + } + + Repo::flushStack(); + + //return [ 'data' => ["professors" => $allProf, "formations" => $allFormations, "UEs" => $allUE ] ]; + return["data" => true]; }catch (Exception $e){ return [ 'error' => new Error(Err::UnknownError) ]; } diff --git a/build/database/core/DatabaseDriver.php b/build/database/core/DatabaseDriver.php index a7553fd..695b06d 100755 --- a/build/database/core/DatabaseDriver.php +++ b/build/database/core/DatabaseDriver.php @@ -11,6 +11,7 @@ **************************/ namespace database\core; + use database\core\PDOWrapper\PDOWrapper; use \error\core\Error; use \error\core\Err; @@ -60,7 +61,7 @@ * @password Database password * */ - private function __construct($host, $dbname, $username, $password){ + private function __construct($host, $dbname, $username, $password, $debug = false){ /* (2) Stores configuration */ $this->host = $host; $this->dbname = $dbname; @@ -69,14 +70,19 @@ try{ - $this->pdo = new \PDO('mysql:host='.$this->host.';dbname='.$this->dbname.';charset=utf8', $this->username, $this->password, [ + $this->pdo = new PDOWrapper('mysql:host='.$this->host.';dbname='.$this->dbname.';charset=utf8', $this->username, $this->password, [ \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC, - \PDO::ATTR_TIMEOUT => 5 + \PDO::ATTR_TIMEOUT => 5, + \PDO::ERRMODE_EXCEPTION => true ]); $this->pdo->setAttribute(\PDO::ATTR_STRINGIFY_FETCHES, false); $this->pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false); + if($debug){ + $this->pdo->enableDebug(); + } + // On signale que tout s'est bien passe $this->error = new Error(Err::Success); @@ -118,7 +124,7 @@ /* (1) If local -> instanciates with local configuration */ // if( !checkdnsrr($_SERVER['SERVER_NAME'], 'NS') ) - self::$instance[$label] = new DatabaseDriver($conf[$label]['local']['host'], $conf[$label]['local']['dbname'], $conf[$label]['local']['user'], $conf[$label]['local']['password']); + self::$instance[$label] = new DatabaseDriver($conf[$label]['local']['host'], $conf[$label]['local']['dbname'], $conf[$label]['local']['user'], $conf[$label]['local']['password'],$conf[$label]['local']['debug']); /* (2) If Remote -> instanciates with Remote configuration */ // else // self::$instance[$label] = new DatabaseDriver($conf[$label]['remote']['host'], $conf[$label]['remote']['dbname'], $conf[$label]['remote']['user'], $conf[$label]['remote']['password']); @@ -194,6 +200,22 @@ ]; } + public function enableStacking(){ + $this->pdo->enableStacking(); + } + + public function flushStack(){ + $this->pdo->executeStack(); + } + + public function getDebug() : array{ + return $this->pdo->getDebug(); + } + + public function isDebugEnabled() : bool { + return $this->pdo->isDebugEnabled(); + } + } diff --git a/build/database/core/PDOWrapper/PDOStatementWrapper.php b/build/database/core/PDOWrapper/PDOStatementWrapper.php new file mode 100644 index 0000000..704d5bb --- /dev/null +++ b/build/database/core/PDOWrapper/PDOStatementWrapper.php @@ -0,0 +1,51 @@ +statement = $statement; + $this->connexion = $connexion; + + + } + + public function execute($input_parameters = []) + { + $this->parameters = $input_parameters; + $this->connexion->stackStatement($this); + return true; + } + + /** + * @return string + */ + public function getStatement() + { + return $this->statement; + } + + /** + * @return array + */ + public function getParameters() + { + return $this->parameters; + } + + + +} \ No newline at end of file diff --git a/build/database/core/PDOWrapper/PDOWrapper.php b/build/database/core/PDOWrapper/PDOWrapper.php new file mode 100644 index 0000000..5674744 --- /dev/null +++ b/build/database/core/PDOWrapper/PDOWrapper.php @@ -0,0 +1,147 @@ +debugEnabled){ + $this->storeDebug(); + } + + if($this->stacking){ + return new PDOStatementWrapper($statement, $this); + }else{ + parent::setAttribute(\PDO::ATTR_EMULATE_PREPARES, true); + return parent::prepare($statement, $options); + + } + } + + 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; + } + public function getDebug() : array{ + return $this->debug; + } + + public function enableStacking(){ + $this->stacking = true; + } + + public function isDebugEnabled() : bool{ + return $this->debugEnabled; + } + + public function stackStatement(PDOStatementWrapper $st){ + array_push($this->statements,$st); + } + + public function enableDebug(){ + $this->debugEnabled = true; + } + + public function disableDebug(){ + $this->debugEnabled = false; + } + + 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){ + //get next number + $i++; + + //delete the ':' at the beginning of the string + $tempKey = ltrim($matches[0],':'); + + //copy the parameter with the modified index + $tempParametes[$tempKey.$i] = $tempParametes[$tempKey]; + + //delete the old index + unset($tempParametes[$tempKey]); + + //return the modified string for replacement + return $matches[0].$i; + },$statement),';').';'; + + $finalExecute = array_merge($finalExecute,$tempParametes); + } + + //disable stacking + $this->stacking = false; + + $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(); + //using beginTransaction/commit disable the autocommit, we re-activate it + $this->setAttribute(\PDO::ATTR_AUTOCOMMIT,1); + parent::setAttribute(\PDO::ATTR_EMULATE_PREPARES, false); + return $success; + } +} \ No newline at end of file diff --git a/build/database/core/Repo.php b/build/database/core/Repo.php index 6a09828..d5d86f3 100644 --- a/build/database/core/Repo.php +++ b/build/database/core/Repo.php @@ -12,6 +12,7 @@ namespace database\core; + use database\core\PDOWrapper\PDOWrapper; use \error\core\Error; use \error\core\Err; @@ -20,6 +21,9 @@ /* (1) Driver ---------------------------------------------------------*/ + /** + * @var DatabaseDriver + */ private static $driver = null; public static function setDriver(DatabaseDriver $driver){ self::$driver = $driver; } @@ -57,6 +61,22 @@ return $instance; } + public static function enableStacking(){ + static::$driver->enableStacking(); + } + + public static function flushStack(){ + static::$driver->flushStack(); + } + + public static function getDebug() : array{ + return static::$driver->getDebug(); + } + + public static function isDebugEnabled() : bool{ + return static::$driver->isDebugEnabled(); + } + diff --git a/config/database-driver.json b/config/database-driver.json index fb2da3c..0c99f5d 100755 --- a/config/database-driver.json +++ b/config/database-driver.json @@ -4,7 +4,8 @@ "host" : "mariadb", "dbname" : "vhost", "user" : "php", - "password" : "4JB1dtbrIC8pT935" + "password" : "4JB1dtbrIC8pT935", + "debug" : true }, "remote": { "host" : "db_remote_host",