Subversion Repositories oidplus

Rev

Rev 224 | 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 OIDplusDataBasePluginPDO extends OIDplusDataBasePlugin {
  23.         private $pdo;
  24.         private $last_query;
  25.         private $prepare_cache = array();
  26.  
  27.         public static function getPluginInformation() {
  28.                 $out = array();
  29.                 $out['name'] = 'PDO';
  30.                 $out['author'] = 'ViaThinkSoft';
  31.                 $out['version'] = null;
  32.                 $out['descriptionHTML'] = null;
  33.                 return $out;
  34.         }
  35.  
  36.         public static function name() {
  37.                 return "PDO";
  38.         }
  39.  
  40.         public function query($sql, $prepared_args=null) {
  41.                 $this->last_query = $sql;
  42.                 if (is_null($prepared_args)) {
  43.                         return $this->pdo->query($sql);
  44.                 } else {
  45.  
  46.  
  47.                         // TEST: Emulate the prepared statement
  48. /*
  49.                         foreach ($prepared_args as $arg) {
  50.                                 $needle = '?';
  51.                                 $replace = "'$arg'"; // TODO: types
  52.                                 $pos = strpos($sql, $needle);
  53.                                 if ($pos !== false) {
  54.                                         $sql = substr_replace($sql, $replace, $pos, strlen($needle));
  55.                                 }
  56.                         }
  57.                         return $this->pdo->query($sql);
  58. */
  59.  
  60.  
  61.                         if (!is_array($prepared_args)) {
  62.                                 throw new Exception("'prepared_args' must be either NULL or an ARRAY.");
  63.                         }
  64.                         if (isset($this->prepare_cache[$sql])) {
  65.                                 $ps = $this->prepare_cache[$sql];
  66.                         } else {
  67.                                 $ps = $this->pdo->prepare($sql);
  68.                                 if (!$ps) {
  69.                                         throw new Exception("Cannot prepare statement '$sql'");
  70.                                 }
  71.                                 $this->prepare_cache[$sql] = $ps;
  72.                         }
  73.                         if (!$ps->execute($prepared_args)) {
  74.                                 // Note: Our plugins prepare the configs by trying to insert stuff, which raises a Primary Key exception. So we cannot throw an Exception.
  75.                                 return false;
  76.                         }
  77.                         return $ps;
  78.                 }
  79.         }
  80.         public function num_rows($res) {
  81.                 if (!is_object($res)) {
  82.                         throw new Exception("num_rows called on non object. Last query: ".$this->last_query);
  83.                 } else {
  84.                         return $res->rowCount();
  85.                 }
  86.         }
  87.         public function fetch_array($res) {
  88.                 if (!is_object($res)) {
  89.                         throw new Exception("fetch_array called on non object. Last query: ".$this->last_query);
  90.                 } else {
  91.                         return $res->fetch(PDO::FETCH_ASSOC);
  92.                 }
  93.         }
  94.         public function fetch_object($res) {
  95.                 if (!is_object($res)) {
  96.                         throw new Exception("fetch_object called on non object. Last query: ".$this->last_query);
  97.                 } else {
  98.                         return $res->fetch(PDO::FETCH_OBJ);
  99.                 }
  100.         }
  101.         public function insert_id() {
  102.                 return $this->pdo->lastInsertId();
  103.         }
  104.         public function error() {
  105.                 return $this->pdo->errorInfo()[2];
  106.         }
  107.         public function connect() {
  108.                 $html = OIDPLUS_HTML_OUTPUT;
  109.  
  110.                 try {
  111.                         $options = [
  112.                         #    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
  113.                             PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
  114.                             PDO::ATTR_EMULATE_PREPARES   => true,
  115.                         ];
  116.  
  117.                         // Try connecting to the database
  118.                         $this->pdo = new PDO(OIDPLUS_PDO_DSN, OIDPLUS_PDO_USERNAME, base64_decode(OIDPLUS_PDO_PASSWORD), $options);
  119.                 } catch (PDOException $e) {
  120.                         if ($html) {
  121.                                 echo "<h1>Error</h1><p>Database connection failed! (".$e->getMessage().")</p>";
  122.                                 if (is_dir(__DIR__.'/../../../setup')) {
  123.                                         echo '<p>If you believe that the login credentials are wrong, please run <a href="setup/">setup</a> again.</p>';
  124.                                 }
  125.                         } else {
  126.                                 echo "Error: Database connection failed! (".$e->getMessage().")";
  127.                                 if (is_dir(__DIR__.'/../../../setup')) {
  128.                                         echo ' If you believe that the login credentials are wrong, please run setup again.';
  129.                                 }
  130.                         }
  131.                         die();
  132.                 }
  133.  
  134.                 $this->query("SET NAMES 'utf8'");
  135.                 $this->afterConnect($html);
  136.                 $this->connected = true;
  137.         }
  138.  
  139.         private $intransaction = false;
  140.  
  141.         public function transaction_begin() {
  142.                 if ($this->intransaction) throw new Exception("Nested transactions are not supported by this database plugin.");
  143.                 $this->pdo->beginTransaction();
  144.                 $this->intransaction = true;
  145.         }
  146.  
  147.         public function transaction_commit() {
  148.                 $this->pdo->commit();
  149.                 $this->intransaction = false;
  150.         }
  151.  
  152.         public function transaction_rollback() {
  153.                 $this->pdo->rollBack();
  154.                 $this->intransaction = false;
  155.         }
  156. }
  157.