|
1
|
|
|
<?php |
|
2
|
|
|
/* For licensing terms, see /license.txt */ |
|
3
|
|
|
|
|
4
|
|
|
use Doctrine\Common\Annotations\AnnotationRegistry; |
|
5
|
|
|
use Doctrine\DBAL\Connection; |
|
6
|
|
|
use Doctrine\DBAL\Driver\Statement; |
|
7
|
|
|
use Doctrine\DBAL\Types\Type; |
|
8
|
|
|
use Doctrine\ORM\EntityManager; |
|
9
|
|
|
|
|
10
|
|
|
/** |
|
11
|
|
|
* Class Database |
|
12
|
|
|
*/ |
|
13
|
|
|
class Database |
|
14
|
|
|
{ |
|
15
|
|
|
/** |
|
16
|
|
|
* @var EntityManager |
|
17
|
|
|
*/ |
|
18
|
|
|
private static $em; |
|
19
|
|
|
private static $connection; |
|
20
|
|
|
public static $utcDateTimeClass; |
|
21
|
|
|
|
|
22
|
|
|
/** |
|
23
|
|
|
* @param EntityManager $em |
|
24
|
|
|
*/ |
|
25
|
|
|
public function setManager($em) |
|
|
|
|
|
|
26
|
|
|
{ |
|
27
|
|
|
self::$em = $em; |
|
28
|
|
|
} |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* @param Connection $connection |
|
32
|
|
|
*/ |
|
33
|
|
|
public function setConnection(Connection $connection) |
|
34
|
|
|
{ |
|
35
|
|
|
self::$connection = $connection; |
|
36
|
|
|
} |
|
37
|
|
|
|
|
38
|
|
|
/** |
|
39
|
|
|
* @return Connection |
|
40
|
|
|
*/ |
|
41
|
|
|
public function getConnection() |
|
42
|
|
|
{ |
|
43
|
|
|
return self::$connection; |
|
44
|
|
|
} |
|
45
|
|
|
|
|
46
|
|
|
/** |
|
47
|
|
|
* @return EntityManager |
|
48
|
|
|
*/ |
|
49
|
|
|
public static function getManager() |
|
50
|
|
|
{ |
|
51
|
|
|
return self::$em; |
|
52
|
|
|
} |
|
53
|
|
|
|
|
54
|
|
|
/** |
|
55
|
|
|
* Returns the name of the main database. |
|
56
|
|
|
* |
|
57
|
|
|
* @return string |
|
58
|
|
|
*/ |
|
59
|
|
|
public static function get_main_database() |
|
60
|
|
|
{ |
|
61
|
|
|
return self::getManager()->getConnection()->getDatabase(); |
|
62
|
|
|
} |
|
63
|
|
|
|
|
64
|
|
|
/** |
|
65
|
|
|
* Get main table |
|
66
|
|
|
* |
|
67
|
|
|
* @param string $table |
|
68
|
|
|
* |
|
69
|
|
|
* @return mixed |
|
70
|
|
|
*/ |
|
71
|
|
|
public static function get_main_table($table) |
|
72
|
|
|
{ |
|
73
|
|
|
return $table; |
|
74
|
|
|
} |
|
75
|
|
|
|
|
76
|
|
|
/** |
|
77
|
|
|
* Get course table |
|
78
|
|
|
* |
|
79
|
|
|
* @param string $table |
|
80
|
|
|
* |
|
81
|
|
|
* @return string |
|
82
|
|
|
*/ |
|
83
|
|
|
public static function get_course_table($table) |
|
84
|
|
|
{ |
|
85
|
|
|
return DB_COURSE_PREFIX.$table; |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
/** |
|
89
|
|
|
* Counts the number of rows in a table |
|
90
|
|
|
* @param string $table The table of which the rows should be counted |
|
91
|
|
|
* |
|
92
|
|
|
* @return int The number of rows in the given table. |
|
93
|
|
|
* @deprecated |
|
94
|
|
|
*/ |
|
95
|
|
|
public static function count_rows($table) |
|
96
|
|
|
{ |
|
97
|
|
|
$obj = self::fetch_object(self::query("SELECT COUNT(*) AS n FROM $table")); |
|
|
|
|
|
|
98
|
|
|
|
|
99
|
|
|
return $obj->n; |
|
100
|
|
|
} |
|
101
|
|
|
|
|
102
|
|
|
/** |
|
103
|
|
|
* Returns the number of affected rows in the last database operation. |
|
104
|
|
|
* @param Statement $result |
|
105
|
|
|
* |
|
106
|
|
|
* @return int |
|
107
|
|
|
*/ |
|
108
|
|
|
public static function affected_rows(Statement $result) |
|
109
|
|
|
{ |
|
110
|
|
|
return $result->rowCount(); |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
/** |
|
114
|
|
|
* @return string |
|
115
|
|
|
*/ |
|
116
|
|
|
public static function getUTCDateTimeTypeClass() |
|
117
|
|
|
{ |
|
118
|
|
|
return isset(self::$utcDateTimeClass) ? self::$utcDateTimeClass : |
|
119
|
|
|
'Application\DoctrineExtensions\DBAL\Types\UTCDateTimeType'; |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
/** |
|
123
|
|
|
* Connect to the database sets the entity manager. |
|
124
|
|
|
* |
|
125
|
|
|
* @param array $params |
|
126
|
|
|
* @param string $sysPath |
|
127
|
|
|
* @param string $entityRootPath |
|
128
|
|
|
* |
|
129
|
|
|
* @throws \Doctrine\ORM\ORMException |
|
130
|
|
|
*/ |
|
131
|
|
|
public function connect($params = array(), $sysPath = '', $entityRootPath = '') |
|
132
|
|
|
{ |
|
133
|
|
|
$config = self::getDoctrineConfig($entityRootPath); |
|
134
|
|
|
$config->setAutoGenerateProxyClasses(true); |
|
135
|
|
|
|
|
136
|
|
|
$config->setEntityNamespaces( |
|
137
|
|
|
array( |
|
138
|
|
|
'ChamiloUserBundle' => 'Chamilo\UserBundle\Entity', |
|
139
|
|
|
'ChamiloCoreBundle' => 'Chamilo\CoreBundle\Entity', |
|
140
|
|
|
'ChamiloCourseBundle' => 'Chamilo\CourseBundle\Entity' |
|
141
|
|
|
) |
|
142
|
|
|
); |
|
143
|
|
|
|
|
144
|
|
|
$params['charset'] = 'utf8'; |
|
145
|
|
|
$entityManager = EntityManager::create($params, $config); |
|
146
|
|
|
$sysPath = !empty($sysPath) ? $sysPath : api_get_path(SYS_PATH); |
|
147
|
|
|
|
|
148
|
|
|
// Registering Constraints |
|
149
|
|
|
AnnotationRegistry::registerAutoloadNamespace( |
|
150
|
|
|
'Symfony\Component\Validator\Constraint', |
|
151
|
|
|
$sysPath."vendor/symfony/validator" |
|
152
|
|
|
); |
|
153
|
|
|
|
|
154
|
|
|
AnnotationRegistry::registerFile( |
|
155
|
|
|
$sysPath."vendor/symfony/doctrine-bridge/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php" |
|
156
|
|
|
); |
|
157
|
|
|
|
|
158
|
|
|
// Registering gedmo extensions |
|
159
|
|
|
AnnotationRegistry::registerAutoloadNamespace( |
|
160
|
|
|
'Gedmo\Mapping\Annotation', |
|
161
|
|
|
$sysPath."vendor/gedmo/doctrine-extensions/lib" |
|
162
|
|
|
); |
|
163
|
|
|
|
|
164
|
|
|
Type::overrideType( |
|
165
|
|
|
Type::DATETIME, |
|
166
|
|
|
self::getUTCDateTimeTypeClass() |
|
167
|
|
|
); |
|
168
|
|
|
|
|
169
|
|
|
$listener = new \Gedmo\Timestampable\TimestampableListener(); |
|
170
|
|
|
$entityManager->getEventManager()->addEventSubscriber($listener); |
|
171
|
|
|
|
|
172
|
|
|
$listener = new \Gedmo\Tree\TreeListener(); |
|
173
|
|
|
$entityManager->getEventManager()->addEventSubscriber($listener); |
|
174
|
|
|
|
|
175
|
|
|
$listener = new \Gedmo\Sortable\SortableListener(); |
|
176
|
|
|
$entityManager->getEventManager()->addEventSubscriber($listener); |
|
177
|
|
|
$connection = $entityManager->getConnection(); |
|
178
|
|
|
$connection->executeQuery('set sql_mode=""'); |
|
179
|
|
|
$this->setConnection($connection); |
|
180
|
|
|
$this->setManager($entityManager); |
|
181
|
|
|
} |
|
182
|
|
|
|
|
183
|
|
|
/** |
|
184
|
|
|
* Escape MySQL wildchars _ and % in LIKE search |
|
185
|
|
|
* @param string $text The string to escape |
|
186
|
|
|
* |
|
187
|
|
|
* @return string The escaped string |
|
188
|
|
|
*/ |
|
189
|
|
|
public static function escape_sql_wildcards($text) |
|
190
|
|
|
{ |
|
191
|
|
|
$text = api_preg_replace("/_/", "\_", $text); |
|
192
|
|
|
$text = api_preg_replace("/%/", "\%", $text); |
|
193
|
|
|
|
|
194
|
|
|
return $text; |
|
195
|
|
|
} |
|
196
|
|
|
|
|
197
|
|
|
/** |
|
198
|
|
|
* Escapes a string to insert into the database as text |
|
199
|
|
|
* |
|
200
|
|
|
* @param string $string |
|
201
|
|
|
* |
|
202
|
|
|
* @return string |
|
203
|
|
|
*/ |
|
204
|
|
|
public static function escape_string($string) |
|
205
|
|
|
{ |
|
206
|
|
|
$string = self::getManager()->getConnection()->quote($string); |
|
207
|
|
|
|
|
208
|
|
|
return trim($string, "'"); |
|
209
|
|
|
} |
|
210
|
|
|
|
|
211
|
|
|
/** |
|
212
|
|
|
* Gets the array from a SQL result (as returned by Database::query) |
|
213
|
|
|
* |
|
214
|
|
|
* @param Statement $result |
|
215
|
|
|
* @param string $option Optional: "ASSOC","NUM" or "BOTH" |
|
216
|
|
|
* |
|
217
|
|
|
* @return array|mixed |
|
218
|
|
|
*/ |
|
219
|
|
|
public static function fetch_array(Statement $result, $option = 'BOTH') |
|
220
|
|
|
{ |
|
221
|
|
|
if ($result === false) { |
|
222
|
|
|
return array(); |
|
223
|
|
|
} |
|
224
|
|
|
|
|
225
|
|
|
return $result->fetch(self::customOptionToDoctrineOption($option)); |
|
226
|
|
|
} |
|
227
|
|
|
|
|
228
|
|
|
/** |
|
229
|
|
|
* Gets an associative array from a SQL result (as returned by Database::query). |
|
230
|
|
|
* |
|
231
|
|
|
* @param Statement $result |
|
232
|
|
|
* |
|
233
|
|
|
* @return array |
|
234
|
|
|
*/ |
|
235
|
|
|
public static function fetch_assoc(Statement $result) |
|
236
|
|
|
{ |
|
237
|
|
|
return $result->fetch(PDO::FETCH_ASSOC); |
|
238
|
|
|
} |
|
239
|
|
|
|
|
240
|
|
|
/** |
|
241
|
|
|
* Gets the next row of the result of the SQL query |
|
242
|
|
|
* (as returned by Database::query) in an object form |
|
243
|
|
|
* |
|
244
|
|
|
* @param Statement $result |
|
245
|
|
|
* |
|
246
|
|
|
* @return mixed |
|
247
|
|
|
*/ |
|
248
|
|
|
public static function fetch_object(Statement $result) |
|
249
|
|
|
{ |
|
250
|
|
|
return $result->fetch(PDO::FETCH_OBJ); |
|
251
|
|
|
} |
|
252
|
|
|
|
|
253
|
|
|
/** |
|
254
|
|
|
* Gets the array from a SQL result (as returned by Database::query) |
|
255
|
|
|
* help achieving database independence |
|
256
|
|
|
* |
|
257
|
|
|
* @param Statement $result |
|
258
|
|
|
* |
|
259
|
|
|
* @return mixed |
|
260
|
|
|
*/ |
|
261
|
|
|
public static function fetch_row(Statement $result) |
|
262
|
|
|
{ |
|
263
|
|
|
return $result->fetch(PDO::FETCH_NUM); |
|
264
|
|
|
} |
|
265
|
|
|
|
|
266
|
|
|
/** |
|
267
|
|
|
* Frees all the memory associated with the provided result identifier. |
|
268
|
|
|
* @return bool Returns TRUE on success or FALSE on failure. |
|
269
|
|
|
* Notes: Use this method if you are concerned about how much memory is being used for queries that return large result sets. |
|
270
|
|
|
* Anyway, all associated result memory is automatically freed at the end of the script's execution. |
|
271
|
|
|
*/ |
|
272
|
|
|
public static function free_result(Statement $result) |
|
273
|
|
|
{ |
|
274
|
|
|
$result->closeCursor(); |
|
275
|
|
|
} |
|
276
|
|
|
|
|
277
|
|
|
/** |
|
278
|
|
|
* Gets the ID of the last item inserted into the database |
|
279
|
|
|
* |
|
280
|
|
|
* @return string |
|
281
|
|
|
*/ |
|
282
|
|
|
public static function insert_id() |
|
283
|
|
|
{ |
|
284
|
|
|
return self::getManager()->getConnection()->lastInsertId(); |
|
285
|
|
|
} |
|
286
|
|
|
|
|
287
|
|
|
/** |
|
288
|
|
|
* @param Statement $result |
|
289
|
|
|
* |
|
290
|
|
|
* @return int |
|
291
|
|
|
*/ |
|
292
|
|
|
public static function num_rows(Statement $result) |
|
293
|
|
|
{ |
|
294
|
|
|
return $result->rowCount(); |
|
295
|
|
|
} |
|
296
|
|
|
|
|
297
|
|
|
/** |
|
298
|
|
|
* Acts as the relative *_result() function of most DB drivers and fetches a |
|
299
|
|
|
* specific line and a field |
|
300
|
|
|
* |
|
301
|
|
|
* @param Statement $resource |
|
302
|
|
|
* @param int $row |
|
303
|
|
|
* @param string $field |
|
304
|
|
|
* |
|
305
|
|
|
* @return mixed |
|
306
|
|
|
*/ |
|
307
|
|
|
public static function result(Statement $resource, $row, $field = '') |
|
308
|
|
|
{ |
|
309
|
|
|
if ($resource->rowCount() > 0) { |
|
310
|
|
|
$result = $resource->fetchAll(PDO::FETCH_BOTH); |
|
311
|
|
|
|
|
312
|
|
|
return $result[$row][$field]; |
|
313
|
|
|
} |
|
314
|
|
|
} |
|
315
|
|
|
|
|
316
|
|
|
/** |
|
317
|
|
|
* @param string $query |
|
318
|
|
|
* |
|
319
|
|
|
* @return Statement |
|
320
|
|
|
* |
|
321
|
|
|
* @throws \Doctrine\DBAL\DBALException |
|
322
|
|
|
*/ |
|
323
|
|
|
public static function query($query) |
|
324
|
|
|
{ |
|
325
|
|
|
$connection = self::getManager()->getConnection(); |
|
326
|
|
|
|
|
327
|
|
|
if (api_get_setting('server_type') == 'test') { |
|
328
|
|
|
$result = $connection->executeQuery($query); |
|
329
|
|
|
} else { |
|
330
|
|
|
try { |
|
331
|
|
|
$result = $connection->executeQuery($query); |
|
332
|
|
|
} catch (Exception $e) { |
|
333
|
|
|
error_log($e->getMessage()); |
|
334
|
|
|
api_not_allowed(false, get_lang('GeneralError')); |
|
335
|
|
|
|
|
336
|
|
|
exit; |
|
337
|
|
|
} |
|
338
|
|
|
} |
|
339
|
|
|
|
|
340
|
|
|
return $result; |
|
341
|
|
|
} |
|
342
|
|
|
|
|
343
|
|
|
/** |
|
344
|
|
|
* @param string $option |
|
345
|
|
|
* |
|
346
|
|
|
* @return int |
|
347
|
|
|
*/ |
|
348
|
|
|
public static function customOptionToDoctrineOption($option) |
|
349
|
|
|
{ |
|
350
|
|
|
switch ($option) { |
|
351
|
|
|
case 'ASSOC': |
|
352
|
|
|
return PDO::FETCH_ASSOC; |
|
353
|
|
|
break; |
|
354
|
|
|
case 'NUM': |
|
355
|
|
|
return PDO::FETCH_NUM; |
|
356
|
|
|
break; |
|
357
|
|
|
case 'BOTH': |
|
358
|
|
|
default: |
|
359
|
|
|
return PDO::FETCH_BOTH; |
|
360
|
|
|
break; |
|
361
|
|
|
} |
|
362
|
|
|
} |
|
363
|
|
|
|
|
364
|
|
|
/** |
|
365
|
|
|
* Stores a query result into an array. |
|
366
|
|
|
* |
|
367
|
|
|
* @author Olivier Brouckaert |
|
368
|
|
|
* @param Statement $result - the return value of the query |
|
369
|
|
|
* @param string $option BOTH, ASSOC, or NUM |
|
370
|
|
|
* |
|
371
|
|
|
* @return array - the value returned by the query |
|
372
|
|
|
*/ |
|
373
|
|
|
public static function store_result(Statement $result, $option = 'BOTH') |
|
374
|
|
|
{ |
|
375
|
|
|
return $result->fetchAll(self::customOptionToDoctrineOption($option)); |
|
376
|
|
|
} |
|
377
|
|
|
|
|
378
|
|
|
/** |
|
379
|
|
|
* Database insert |
|
380
|
|
|
* @param string $table_name |
|
381
|
|
|
* @param array $attributes |
|
382
|
|
|
* @param bool $show_query |
|
383
|
|
|
* |
|
384
|
|
|
* @return bool|int |
|
385
|
|
|
*/ |
|
386
|
|
|
public static function insert($table_name, $attributes, $show_query = false) |
|
387
|
|
|
{ |
|
388
|
|
|
if (empty($attributes) || empty($table_name)) { |
|
389
|
|
|
return false; |
|
390
|
|
|
} |
|
391
|
|
|
|
|
392
|
|
|
$params = array_keys($attributes); |
|
393
|
|
|
|
|
394
|
|
|
if (!empty($params)) { |
|
395
|
|
|
$sql = 'INSERT INTO '.$table_name.' ('.implode(',', $params).') |
|
396
|
|
|
VALUES (:'.implode(', :' ,$params).')'; |
|
397
|
|
|
|
|
398
|
|
|
$statement = self::getManager()->getConnection()->prepare($sql); |
|
399
|
|
|
$result = $statement->execute($attributes); |
|
400
|
|
|
|
|
401
|
|
|
if ($show_query) { |
|
402
|
|
|
var_dump($sql); |
|
|
|
|
|
|
403
|
|
|
error_log($sql); |
|
404
|
|
|
} |
|
405
|
|
|
|
|
406
|
|
|
if ($result) { |
|
407
|
|
|
return self::getManager()->getConnection()->lastInsertId(); |
|
408
|
|
|
} |
|
409
|
|
|
} |
|
410
|
|
|
|
|
411
|
|
|
return false; |
|
412
|
|
|
} |
|
413
|
|
|
|
|
414
|
|
|
/** |
|
415
|
|
|
* @param string $table_name use Database::get_main_table |
|
416
|
|
|
* @param array $attributes Values to updates |
|
417
|
|
|
* Example: $params['name'] = 'Julio'; $params['lastname'] = 'Montoya'; |
|
418
|
|
|
* @param array $where_conditions where conditions i.e array('id = ?' =>'4') |
|
419
|
|
|
* @param bool $show_query |
|
420
|
|
|
* |
|
421
|
|
|
* @return bool|int |
|
422
|
|
|
*/ |
|
423
|
|
|
public static function update( |
|
424
|
|
|
$table_name, |
|
425
|
|
|
$attributes, |
|
426
|
|
|
$where_conditions = array(), |
|
427
|
|
|
$show_query = false |
|
428
|
|
|
) { |
|
429
|
|
|
if (!empty($table_name) && !empty($attributes)) { |
|
430
|
|
|
$update_sql = ''; |
|
431
|
|
|
//Cleaning attributes |
|
432
|
|
|
$count = 1; |
|
433
|
|
|
|
|
434
|
|
|
foreach ($attributes as $key => $value) { |
|
435
|
|
|
$update_sql .= "$key = :$key "; |
|
436
|
|
|
if ($count < count($attributes)) { |
|
437
|
|
|
$update_sql.=', '; |
|
438
|
|
|
} |
|
439
|
|
|
$count++; |
|
440
|
|
|
} |
|
441
|
|
|
|
|
442
|
|
|
if (!empty($update_sql)) { |
|
443
|
|
|
//Parsing and cleaning the where conditions |
|
444
|
|
|
$where_return = self::parse_where_conditions($where_conditions); |
|
445
|
|
|
|
|
446
|
|
|
$sql = "UPDATE $table_name SET $update_sql $where_return "; |
|
447
|
|
|
|
|
448
|
|
|
$statement = self::getManager()->getConnection()->prepare($sql); |
|
449
|
|
|
$result = $statement->execute($attributes); |
|
450
|
|
|
|
|
451
|
|
|
if ($show_query) { |
|
452
|
|
|
var_dump($sql); |
|
|
|
|
|
|
453
|
|
|
} |
|
454
|
|
|
|
|
455
|
|
|
if ($result) { |
|
456
|
|
|
|
|
457
|
|
|
return $statement->rowCount(); |
|
458
|
|
|
} |
|
459
|
|
|
} |
|
460
|
|
|
} |
|
461
|
|
|
|
|
462
|
|
|
return false; |
|
463
|
|
|
} |
|
464
|
|
|
|
|
465
|
|
|
/** |
|
466
|
|
|
* Experimental useful database finder |
|
467
|
|
|
* @todo lot of stuff to do here |
|
468
|
|
|
* @todo known issues, it doesn't work when using LIKE conditions |
|
469
|
|
|
* @example array('where'=> array('course_code LIKE "?%"')) |
|
470
|
|
|
* @example array('where'=> array('type = ? AND category = ?' => array('setting', 'Plugins')) |
|
471
|
|
|
* @example array('where'=> array('name = "Julio" AND lastname = "montoya"')) |
|
472
|
|
|
*/ |
|
473
|
|
|
public static function select($columns, $table_name, $conditions = array(), $type_result = 'all', $option = 'ASSOC') |
|
474
|
|
|
{ |
|
475
|
|
|
$conditions = self::parse_conditions($conditions); |
|
476
|
|
|
|
|
477
|
|
|
//@todo we could do a describe here to check the columns ... |
|
478
|
|
|
if (is_array($columns)) { |
|
479
|
|
|
$clean_columns = implode(',', $columns); |
|
480
|
|
|
} else { |
|
481
|
|
|
if ($columns == '*') { |
|
482
|
|
|
$clean_columns = '*'; |
|
483
|
|
|
} else { |
|
484
|
|
|
$clean_columns = (string)$columns; |
|
485
|
|
|
} |
|
486
|
|
|
} |
|
487
|
|
|
|
|
488
|
|
|
$sql = "SELECT $clean_columns FROM $table_name $conditions"; |
|
489
|
|
|
$result = self::query($sql); |
|
490
|
|
|
$array = array(); |
|
491
|
|
|
|
|
492
|
|
|
if ($type_result == 'all') { |
|
493
|
|
|
while ($row = self::fetch_array($result, $option)) { |
|
494
|
|
|
if (isset($row['id'])) { |
|
495
|
|
|
$array[$row['id']] = $row; |
|
496
|
|
|
} else { |
|
497
|
|
|
$array[] = $row; |
|
498
|
|
|
} |
|
499
|
|
|
} |
|
500
|
|
|
} else { |
|
501
|
|
|
$array = self::fetch_array($result, $option); |
|
502
|
|
|
} |
|
503
|
|
|
|
|
504
|
|
|
return $array; |
|
505
|
|
|
} |
|
506
|
|
|
|
|
507
|
|
|
/** |
|
508
|
|
|
* Parses WHERE/ORDER conditions i.e array('where'=>array('id = ?' =>'4'), 'order'=>'id DESC')) |
|
509
|
|
|
* @todo known issues, it doesn't work when using |
|
510
|
|
|
* LIKE conditions example: array('where'=>array('course_code LIKE "?%"')) |
|
511
|
|
|
* @param array $conditions |
|
512
|
|
|
*/ |
|
513
|
|
|
public static function parse_conditions($conditions) |
|
514
|
|
|
{ |
|
515
|
|
|
if (empty($conditions)) { |
|
516
|
|
|
return ''; |
|
517
|
|
|
} |
|
518
|
|
|
$return_value = $where_return = ''; |
|
519
|
|
|
foreach ($conditions as $type_condition => $condition_data) { |
|
520
|
|
|
if ($condition_data == false) { |
|
521
|
|
|
continue; |
|
522
|
|
|
} |
|
523
|
|
|
$type_condition = strtolower($type_condition); |
|
524
|
|
|
switch ($type_condition) { |
|
525
|
|
|
case 'where': |
|
|
|
|
|
|
526
|
|
|
|
|
527
|
|
|
foreach ($condition_data as $condition => $value_array) { |
|
528
|
|
|
if (is_array($value_array)) { |
|
529
|
|
|
$clean_values = array(); |
|
530
|
|
|
foreach($value_array as $item) { |
|
531
|
|
|
$item = Database::escape_string($item); |
|
532
|
|
|
$clean_values[]= $item; |
|
533
|
|
|
} |
|
534
|
|
|
} else { |
|
535
|
|
|
$value_array = Database::escape_string($value_array); |
|
536
|
|
|
$clean_values = $value_array; |
|
537
|
|
|
} |
|
538
|
|
|
|
|
539
|
|
|
if (!empty($condition) && $clean_values != '') { |
|
540
|
|
|
$condition = str_replace('%',"'@percentage@'", $condition); //replace "%" |
|
541
|
|
|
$condition = str_replace("'?'","%s", $condition); |
|
542
|
|
|
$condition = str_replace("?","%s", $condition); |
|
543
|
|
|
|
|
544
|
|
|
$condition = str_replace("@%s@","@-@", $condition); |
|
545
|
|
|
$condition = str_replace("%s","'%s'", $condition); |
|
546
|
|
|
$condition = str_replace("@-@","@%s@", $condition); |
|
547
|
|
|
|
|
548
|
|
|
// Treat conditions as string |
|
549
|
|
|
$condition = vsprintf($condition, $clean_values); |
|
550
|
|
|
$condition = str_replace('@percentage@','%', $condition); //replace "%" |
|
551
|
|
|
$where_return .= $condition; |
|
552
|
|
|
} |
|
553
|
|
|
} |
|
554
|
|
|
|
|
555
|
|
|
if (!empty($where_return)) { |
|
556
|
|
|
$return_value = " WHERE $where_return" ; |
|
557
|
|
|
} |
|
558
|
|
|
break; |
|
559
|
|
|
case 'order': |
|
560
|
|
|
$order_array = $condition_data; |
|
561
|
|
|
|
|
562
|
|
|
if (!empty($order_array)) { |
|
563
|
|
|
// 'order' => 'id desc, name desc' |
|
564
|
|
|
$order_array = self::escape_string($order_array, null, false); |
|
565
|
|
|
$new_order_array = explode(',', $order_array); |
|
566
|
|
|
$temp_value = array(); |
|
567
|
|
|
|
|
568
|
|
|
foreach($new_order_array as $element) { |
|
569
|
|
|
$element = explode(' ', $element); |
|
570
|
|
|
$element = array_filter($element); |
|
571
|
|
|
$element = array_values($element); |
|
572
|
|
|
|
|
573
|
|
|
if (!empty($element[1])) { |
|
574
|
|
|
$element[1] = strtolower($element[1]); |
|
575
|
|
|
$order = 'DESC'; |
|
576
|
|
|
if (in_array($element[1], array('desc', 'asc'))) { |
|
577
|
|
|
$order = $element[1]; |
|
578
|
|
|
} |
|
579
|
|
|
$temp_value[]= $element[0].' '.$order.' '; |
|
580
|
|
|
} else { |
|
581
|
|
|
//by default DESC |
|
582
|
|
|
$temp_value[]= $element[0].' DESC '; |
|
583
|
|
|
} |
|
584
|
|
|
} |
|
585
|
|
|
if (!empty($temp_value)) { |
|
586
|
|
|
$return_value .= ' ORDER BY '.implode(', ', $temp_value); |
|
587
|
|
|
} else { |
|
|
|
|
|
|
588
|
|
|
//$return_value .= ''; |
|
589
|
|
|
} |
|
590
|
|
|
} |
|
591
|
|
|
break; |
|
592
|
|
|
case 'limit': |
|
593
|
|
|
$limit_array = explode(',', $condition_data); |
|
594
|
|
|
if (!empty($limit_array)) { |
|
595
|
|
|
if (count($limit_array) > 1) { |
|
596
|
|
|
$return_value .= ' LIMIT '.intval($limit_array[0]).' , '.intval($limit_array[1]); |
|
597
|
|
|
} else { |
|
598
|
|
|
$return_value .= ' LIMIT '.intval($limit_array[0]); |
|
599
|
|
|
} |
|
600
|
|
|
} |
|
601
|
|
|
break; |
|
602
|
|
|
} |
|
603
|
|
|
} |
|
604
|
|
|
|
|
605
|
|
|
return $return_value; |
|
606
|
|
|
} |
|
607
|
|
|
|
|
608
|
|
|
/** |
|
609
|
|
|
* @param array $conditions |
|
610
|
|
|
* |
|
611
|
|
|
* @return string |
|
612
|
|
|
*/ |
|
613
|
|
|
public static function parse_where_conditions($conditions) |
|
614
|
|
|
{ |
|
615
|
|
|
return self::parse_conditions(array('where' => $conditions)); |
|
616
|
|
|
} |
|
617
|
|
|
|
|
618
|
|
|
/** |
|
619
|
|
|
* @param string $table_name |
|
620
|
|
|
* @param array $where_conditions |
|
621
|
|
|
* @param bool $show_query |
|
622
|
|
|
* |
|
623
|
|
|
* @return int |
|
624
|
|
|
*/ |
|
625
|
|
|
public static function delete($table_name, $where_conditions, $show_query = false) |
|
626
|
|
|
{ |
|
627
|
|
|
$where_return = self::parse_where_conditions($where_conditions); |
|
628
|
|
|
$sql = "DELETE FROM $table_name $where_return "; |
|
629
|
|
|
if ($show_query) { echo $sql; echo '<br />'; } |
|
630
|
|
|
$result = self::query($sql); |
|
631
|
|
|
$affected_rows = self::affected_rows($result); |
|
632
|
|
|
//@todo should return affected_rows for |
|
633
|
|
|
return $affected_rows; |
|
634
|
|
|
} |
|
635
|
|
|
|
|
636
|
|
|
/** |
|
637
|
|
|
* Get Doctrine configuration |
|
638
|
|
|
* @param string $path |
|
639
|
|
|
* |
|
640
|
|
|
* @return \Doctrine\ORM\Configuration |
|
641
|
|
|
*/ |
|
642
|
|
|
public static function getDoctrineConfig($path) |
|
643
|
|
|
{ |
|
644
|
|
|
$isDevMode = false; |
|
645
|
|
|
$isSimpleMode = false; // related to annotations @Entity |
|
646
|
|
|
$cache = null; |
|
647
|
|
|
$path = !empty($path) ? $path : api_get_path(SYS_PATH); |
|
648
|
|
|
|
|
649
|
|
|
$paths = array( |
|
650
|
|
|
$path.'src/Chamilo/CoreBundle/Entity', |
|
651
|
|
|
$path.'src/Chamilo/UserBundle/Entity', |
|
652
|
|
|
$path.'src/Chamilo/CourseBundle/Entity' |
|
653
|
|
|
); |
|
654
|
|
|
|
|
655
|
|
|
$proxyDir = $path.'app/cache/'; |
|
656
|
|
|
|
|
657
|
|
|
return \Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration( |
|
658
|
|
|
$paths, |
|
659
|
|
|
$isDevMode, |
|
660
|
|
|
$proxyDir, |
|
661
|
|
|
$cache, |
|
662
|
|
|
$isSimpleMode |
|
663
|
|
|
); |
|
664
|
|
|
} |
|
665
|
|
|
|
|
666
|
|
|
/** |
|
667
|
|
|
* @param string $table |
|
668
|
|
|
* |
|
669
|
|
|
* @return bool |
|
670
|
|
|
*/ |
|
671
|
|
|
public static function tableExists($table) |
|
672
|
|
|
{ |
|
673
|
|
|
return self::getManager()->getConnection()->getSchemaManager()->tablesExist($table); |
|
674
|
|
|
} |
|
675
|
|
|
} |
|
676
|
|
|
|
The
EntityManagermight become unusable for example if a transaction is rolled back and it gets closed. Let’s assume that somewhere in your application, or in a third-party library, there is code such as the following:If that code throws an exception and the
EntityManageris closed. Any other code which depends on the same instance of theEntityManagerduring this request will fail.On the other hand, if you instead inject the
ManagerRegistry, thegetManager()method guarantees that you will always get a usable manager instance.