Passed
Branch master (f20f08)
by Brayan
04:46 queued 02:24
created

Database::motor_odbc()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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