Subversion Repositories oidplus

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * OIDplus 2.0
  5.  * Copyright 2019 Daniel Marschall, ViaThinkSoft
  6.  *
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *     http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  */
  19.  
  20. if (!defined('IN_OIDPLUS')) die();
  21.  
  22. class OIDplusDataBasePDO extends OIDplusDataBase {
  23.         private $pdo;
  24.         private $last_query;
  25.         private $prepare_cache = array();
  26.  
  27.         public static function name() {
  28.                 return "PDO";
  29.         }
  30.  
  31.         public function query($sql, $prepared_args=null) {
  32.                 $this->last_query = $sql;
  33.                 if (is_null($prepared_args)) {
  34.                         return $this->pdo->query($sql);
  35.                 } else {
  36.  
  37.  
  38.                         // TEST: Emulate the prepared statement
  39. /*
  40.                         foreach ($prepared_args as $arg) {
  41.                                 $needle = '?';
  42.                                 $replace = "'$arg'"; // TODO: types
  43.                                 $pos = strpos($sql, $needle);
  44.                                 if ($pos !== false) {
  45.                                         $sql = substr_replace($sql, $replace, $pos, strlen($needle));
  46.                                 }
  47.                         }
  48.                         return $this->pdo->query($sql);
  49. */
  50.  
  51.  
  52.                         if (!is_array($prepared_args)) {
  53.                                 throw new Exception("'prepared_args' must be either NULL or an ARRAY.");
  54.                         }
  55.                         if (isset($this->prepare_cache[$sql])) {
  56.                                 $ps = $this->prepare_cache[$sql];
  57.                         } else {
  58.                                 $ps = $this->pdo->prepare($sql);
  59.                                 if (!$ps) {
  60.                                         throw new Exception("Cannot prepare statement '$sql'");
  61.                                 }
  62.                                 $this->prepare_cache[$sql] = $ps;
  63.                         }
  64.                         if (!$ps->execute($prepared_args)) {
  65.                                 // Note: Our plugins prepare the configs by trying to insert stuff, which raises a Primary Key exception. So we cannot throw an Exception.
  66.                                 return false;
  67.                         }
  68.                         return $ps;
  69.                 }
  70.         }
  71.         public function num_rows($res) {
  72.                 if (!is_object($res)) {
  73.                         throw new Exception("num_rows called on non object. Last query: ".$this->last_query);
  74.                 } else {
  75.                         return $res->rowCount();
  76.                 }
  77.         }
  78.         public function fetch_array($res) {
  79.                 if (!is_object($res)) {
  80.                         throw new Exception("fetch_array called on non object. Last query: ".$this->last_query);
  81.                 } else {
  82.                         return $res->fetch(PDO::FETCH_ASSOC);
  83.                 }
  84.         }
  85.         public function fetch_object($res) {
  86.                 if (!is_object($res)) {
  87.                         throw new Exception("fetch_object called on non object. Last query: ".$this->last_query);
  88.                 } else {
  89.                         return $res->fetch(PDO::FETCH_OBJ);
  90.                 }
  91.         }
  92.         public function insert_id() {
  93.                 return $this->pdo->lastInsertId();
  94.         }
  95.         public function error() {
  96.                 return $this->pdo->errorInfo()[2];
  97.         }
  98.         public function connect() {
  99.                 $html = OIDPLUS_HTML_OUTPUT;
  100.  
  101.                 try {
  102.                         $options = [
  103.                         #    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
  104.                             PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
  105.                             PDO::ATTR_EMULATE_PREPARES   => true,
  106.                         ];
  107.  
  108.                         // Try connecting to the database
  109.                         $this->pdo = new PDO(OIDPLUS_PDO_DSN, OIDPLUS_PDO_USERNAME, base64_decode(OIDPLUS_PDO_PASSWORD), $options);
  110.                 } catch (PDOException $e) {
  111.                         if ($html) {
  112.                                 echo "<h1>Error</h1><p>Database connection failed! (".$e->getMessage().")</p>";
  113.                                 if (is_dir(__DIR__.'/../../../setup')) {
  114.                                         echo '<p>If you believe that the login credentials are wrong, please run <a href="setup/">setup</a> again.</p>';
  115.                                 }
  116.                         } else {
  117.                                 echo "Error: Database connection failed! (".$e->getMessage().")";
  118.                                 if (is_dir(__DIR__.'/../../../setup')) {
  119.                                         echo ' If you believe that the login credentials are wrong, please run setup again.';
  120.                                 }
  121.                         }
  122.                         die();
  123.                 }
  124.  
  125.                 $this->query("SET NAMES 'utf8'");
  126.                 $this->afterConnect($html);
  127.                 $this->connected = true;
  128.         }
  129.  
  130.         private $intransaction = false;
  131.  
  132.         public function transaction_begin() {
  133.                 if ($this->intransaction) throw new Exception("Nested transactions are not supported by this database plugin.");
  134.                 $this->pdo->beginTransaction();
  135.                 $this->intransaction = true;
  136.         }
  137.  
  138.         public function transaction_commit() {
  139.                 $this->pdo->commit();
  140.                 $this->intransaction = false;
  141.         }
  142.  
  143.         public function transaction_rollback() {
  144.                 $this->pdo->rollBack();
  145.                 $this->intransaction = false;
  146.         }
  147. }
  148.  
  149. OIDplus::registerDatabasePlugin(new OIDplusDataBasePDO());
  150.