Passed
Branch beta (bd6a7b)
by Brayan
02:19
created

Database::motor_oracle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 1
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the Ocrend Framewok 2 package.
5
 *
6
 * (c) Ocrend Software <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ocrend\Kernel\Database;
13
14
/**
15
 * Clase para conectar todos los modelos del sistema y compartir la configuración.
16
 * Inicializa elementos escenciales como la conexión con la base de datos.
17
 *
18
 * @author Brayan Narváez <[email protected]>
19
 */
20
21
 class Database extends \PDO {
22
23
   /**
24
     * Contiene la instancia de conexión a la base de datos
25
     * 
26
     * @var Database
27
   */
28
   private static $inst;
29
30
  /**
31
    * Inicia la instancia de conexión, si esta ya ha sido declarada antes, no la duplica y ahorra memoria.
32
    *
33
    * @param string|null $name : Nombre de la base de datos a conectar
34
    * @param string|null $motor: Motor de la base de datos a conectar
35
    * @param bool $new_instance: true para iniciar una nueva instancia (al querer conectar a una DB distinta)
36
    *
37
    * @return Database : Instancia de conexión
38
  */
39
  final public static function Start($name = null, $motor = null, bool $new_instance = false) : Database {
40
    global $config;
41
42
    if(!self::$inst instanceof self or $new_instance) {
43
      self::$inst = new self(
44
          null === $name ? $config['database']['name'] : $name,
45
          null === $motor ? $config['database']['motor'] : $motor
46
        );
47
    }
48
49
    return self::$inst;
50
  }
51
52
  /**
53
    * Motor de base de datos MySQL
54
    *
55
    * @param array $params: Lista de parámetros de configuración
56
  */
57
  final private function motor_mysql(array $params) {
58
    parent::__construct('mysql:host='.$params['host'].';dbname='.$params['name'],
59
    $params['user'],
60
    $params['pass'],
61
    array(\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', 
62
      \PDO::ATTR_EMULATE_PREPARES => false,
63
      \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
64
    ));
65
  }
66
  
67
  /**
68
    * Motor de base de datos SQLite
69
    *
70
    * @param array $params: Lista de parámetros de configuración
71
  */
72
  final private function motor_sqlite(array $params) {
73
    parent::__construct('sqlite:'.$params['name']);
74
  }
75
76
  /**
77
    * Motor de base de datos Cubrid
78
    *
79
    * @param array $params: Lista de parámetros de configuración
80
  */
81 View Code Duplication
  final private function motor_cubrid(array $params) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
82
    parent::__construct('cubrid:host='.$params['host'].';dbname='.$params['name'].';port='.$params['port'],
83
    $params['user'],
84
    $params['pass'],array(
85
      \PDO::ATTR_EMULATE_PREPARES => false,
86
      \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
87
    ));
88
  }
89
90
  /**
91
    * Motor de base de datos Firebird
92
    *
93
    * @param array $params: Lista de parámetros de configuración
94
  */
95
  final private function motor_firebird(array $params) {
96
    parent::__construct('firebird:dbname='.$params['host'].':'.$params['name'],
97
    $params['user'],
98
    $params['pass'],array(
99
      \PDO::ATTR_EMULATE_PREPARES => false,
100
      \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
101
    ));
102
  }
103
104
  /**
105
    * Motor de base de datos ODBC
106
    *
107
    * @param array $params: Lista de parámetros de configuración
108
  */
109
  final private function motor_odbc(array $params) {
110
    parent::__construct('odbc:'.$params['name'],
111
      $params['user'],
112
      $params['pass']
113
    ); 
114
  }
115
116
  /**
117
    * Motor de base de datos Oracle
118
    *
119
    * @param array $params: Lista de parámetros de configuración
120
  */
121
  final private function motor_oracle(array $params) {
122
    parent::__construct('oci:dbname=(DESCRIPTION =
123
    (ADDRESS_LIST =
124
      (ADDRESS = (PROTOCOL = '.$params['protocol'].')(HOST = '.$params['host'].')(PORT = '.$params['port'].'))
125
    )
126
    (CONNECT_DATA =
127
      (SERVICE_NAME = '.$params['name'].')
128
    )
129
    );charset=utf8',$params['database']['user'],$params['database']['pass'],
130
    array(\PDO::ATTR_EMULATE_PREPARES => false,
131
      \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
132
      \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC
133
    ));
134
  }
135
136
  /**
137
    * Motor de base de datos PostgreSQL
138
    *
139
    * @param array $params: Lista de parámetros de configuración
140
  */
141 View Code Duplication
  final private function motor_postgresql(array $params) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
142
    parent::__construct('pgsql:host='.$params['host'].';dbname='.$params['name'].';charset=utf8',
143
    $params['user'],
144
    $params['pass'],array(
145
      \PDO::ATTR_EMULATE_PREPARES => false,
146
      \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
147
    ));
148
  }
149
150
  /**
151
    * Motor de base de datos MSSQL
152
    * Añadido por marc2684 https://github.com/prinick96/Ocrend-Framework/issues/7
153
    *
154
    * @param array $params: Lista de parámetros de configuración
155
  */
156 View Code Duplication
  final private function motor_mssql(array $params) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
157
    parent::__construct('sqlsrv:Server='.$params['host'].';Database='.$params['name'].';ConnectionPooling=0',
158
    $params['user'],
159
    $params['pass'],array(\PDO::ATTR_EMULATE_PREPARES => false,
160
      \PDO::SQLSRV_ENCODING_UTF8,
0 ignored issues
show
Bug introduced by
The constant PDO::SQLSRV_ENCODING_UTF8 was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
161
      \PDO::ATTR_ERRMODE =>
162
      \PDO::ERRMODE_EXCEPTION
163
    ));
164
  }
165
166
  /**
167
    * Inicia la conexión con la base de datos seleccionada
168
    *
169
    * @param string|null $name : Nombre de la base de datos a conectar
170
    * @param string|null $motor: Motor de la base de datos a conectar
171
    * @param bool $new_instance: true para iniciar una nueva instancia (al querer conectar a una DB distinta)
172
    *
173
    * @throws \RuntimeException si el motor no existe
174
    * @throws \RuntimeException si existe algún problema de conexión con la base de datos
175
    * @return Database : Instancia de conexión
176
  */
177
  final public function __construct(string $name, string $motor) {
178
    global $config;
179
180
    try {
181
      # Verificar existencia del motor
182
      if(method_exists($this,'motor_' . $motor)) {
183
        $this->{'motor_' . $motor}(array(
184
          'host' => $config['database']['host'],
185
          'name' => $name,
186
          'user' => $config['database']['user'],
187
          'pass' => $config['database']['pass'],
188
          'port' => $config['database']['port'],
189
          'protocol' => $config['database']['protocol']
190
        ));
191
      } else {
192
        throw new \RuntimeException('Motor '. $motor .' de conexión no identificado.');
193
      }
194
    } catch(\PDOException $e) {
195
      throw new \RuntimeException('Problema al conectar con la base de datos: ' . $e->getMessage());
196
    } 
197
  }
198
199
  /**
200
    * Convierte en arreglo asociativo de todos los resultados arrojados por una query
201
    *
202
    * @param object \PDOStatement $query, valor devuelto de la query
203
    *
204
    * @return array arreglo asociativo
205
  */
206
  final public function fetch_array(\PDOStatement $query) : array {
207
    return $query->fetchAll(\PDO::FETCH_ASSOC);
208
  }
209
210
   /**
211
    * Cantidad de filas encontradas después de un SELECT
212
    *
213
    * @param object \PDOStatement $query, valor devuelto de la query
214
    *
215
    * @return int numero de filas encontradas
216
  */
217
  final public function rows(\PDOStatement $query) : int {
218
    return $query->rowCount();
219
  }
220
221
  /**
222
    * Sana un valor para posteriormente ser introducido en una query
223
    *
224
    * @param null/string/int/float a sanar
225
    *
226
    * @return mixed elemento sano
227
  */
228
  final public function scape($e) {
229
    if(null === $e) {
230
      return '';
231
    }
232
233
    if(is_numeric($e) and $e <= 2147483647) {
234
      if(explode('.',$e)[0] != $e) {
235
        return (float) $e;
236
      }
237
      return (int) $e;
238
    }
239
240
    return (string) trim(str_replace(['\\',"\x00",'\n','\r',"'",'"',"\x1a"],['\\\\','\\0','\\n','\\r',"\'",'\"','\\Z'],$e));
241
  }
242
243
  /**
244
    * Borra una serie de elementos de forma segura de una tabla en la base de datos
245
    *
246
    * @param string $table: Tabla a la cual se le quiere remover un elemento
247
    * @param string $where: Condición de borrado que define quien/quienes son dichos elementos
248
    * @param string $limit: Por defecto se limita a borrar un solo elemento que cumpla el $where
249
    *
250
    * @return \PDOStatement
251
  */
252
  final public function delete(string $table, string $where, string $limit = 'LIMIT 1') : \PDOStatement {
253
    return $this->query("DELETE FROM $table WHERE $where $limit;");
254
  }
255
256
  /**
257
    * Inserta una serie de elementos a una tabla en la base de datos
258
    *
259
    * @param string $table: Tabla a la cual se le va a insertar elementos
260
    * @param array $e: Arreglo asociativo de elementos, con la estrctura 'campo_en_la_tabla' => 'valor_a_insertar_en_ese_campo',
261
    *                  todos los elementos del arreglo $e, serán sanados por el método sin necesidad de hacerlo manualmente al crear el arreglo
262
    *
263
    * @throws \RuntimeException si el arreglo está vacío
264
    * @return \PDOStatement
265
  */
266
  final public function insert(string $table, array $e) : \PDOStatement {
267
      if (sizeof($e) == 0) {
268
          throw new \RuntimeException('El arreglo pasado por $this->db->insert(\''.$table.'\',...) está vacío.');
269
      }
270
271
      $query = "INSERT INTO $table (";
272
      $values = '';
273
      foreach ($e as $campo => $v) {
274
          $query .= $campo . ',';
275
          $values .= '\'' . $this->scape($v) . '\',';
276
      }
277
      $query[strlen($query) - 1] = ')';
278
      $values[strlen($values) - 1] = ')';
279
      $query .= ' VALUES (' . $values . ';';
280
281
      return $this->query($query);  
282
  }
283
284
  /**
285
    * Actualiza elementos de una tabla en la base de datos según una condición
286
    *
287
    * @param string $table: Tabla a actualizar
288
    * @param array $e: Arreglo asociativo de elementos, con la estrctura 'campo_en_la_tabla' => 'valor_a_insertar_en_ese_campo',
289
    *                  todos los elementos del arreglo $e, serán sanados por el método sin necesidad de hacerlo manualmente al crear el arreglo
290
    * @param string $where: Condición que indica quienes serán modificados
291
    * @param string $limite: Límite de elementos modificados, por defecto los modifica a todos
292
    *
293
    * @throws \RuntimeException si el arreglo está vacío
294
    * @return \PDOStatement
295
  */
296
  final public function update(string $table, array $e, string $where, string $limit = '') : \PDOStatement {
297
      if (sizeof($e) == 0) {
298
          throw new \RuntimeException('El arreglo pasado por $this->db->update(\''.$table.'\'...) está vacío.');
299
      }
300
301
      $query = "UPDATE $table SET ";
302
      foreach ($e as $campo => $valor) {
303
          $query .= $campo . '=\'' . $this->scape($valor) . '\',';
304
      }
305
      $query[strlen($query) - 1] = ' ';
306
      $query .= "WHERE $where $limit;";
307
308
      return $this->query($query);
309
  }
310
311
  /**
312
    * Selecciona y lista en un arreglo asociativo/numérico los resultados de una búsqueda en la base de datos
313
    *
314
    * @param string $e: Elementos a seleccionar separados por coma
315
    * @param string $tbale: Tabla de la cual se quiere extraer los elementos $e
316
    * @param string $where: Condición que indica quienes son los que se extraen, si no se coloca extrae todos
317
    * @param string $limite: Límite de elemntos a traer, por defecto trae TODOS los que cumplan $where
318
    *
319
    * @return mixed false si no encuentra ningún resultado, array asociativo/numérico si consigue al menos uno
320
  */
321
  final public function select(string $e, string $table, string $where = '1 = 1', string $limit = "") {    
322
    return $this->query_select("SELECT $e FROM $table WHERE $where $limit;");
323
  }
324
325
   /**
326
    * Realiza una query, ideal para trabajar con SELECTS, JOINS, etc
327
    *
328
    * @return array|false si no encuentra ningún resultado, array asociativo/numérico si consigue al menos uno
329
  */
330
  final public function query_select(string $query) {
331
    $sql = $this->query($query);
332
    $result = $sql->fetchAll();
333
    $sql->closeCursor();
334
335
    if(sizeof($result) > 0) {
336
      return $result;
337
    }
338
339
    return false;
340
  }
341
342
  /**
343
    * Alert para evitar clonaciones
344
    *
345
    * @throws \RuntimeException si se intenta clonar la conexión
346
    * @return void
347
  */
348
  final public function __clone() {
349
    throw new \RuntimeException('Estás intentando clonar la Conexión');
350
  }
351
352
 }