Passed
Pull Request — 1.11.x (#4061)
by Angel Fernando Quiroz
21:11 queued 10:58
created

Database::fetch_object()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Doctrine\Common\Annotations\AnnotationRegistry;
6
use Doctrine\DBAL\Connection;
7
use Doctrine\DBAL\Driver\Statement;
8
use Doctrine\DBAL\Types\Type;
9
use Doctrine\ORM\EntityManager;
10
use Symfony\Component\Debug\ExceptionHandler;
11
12
/**
13
 * Class Database.
14
 */
15
class Database
16
{
17
    public static $utcDateTimeClass;
18
    /**
19
     * @var EntityManager
20
     */
21
    private static $em;
22
    private static $connection;
23
24
    /**
25
     * Set the DB manager instance.
26
     *
27
     * @param EntityManager $em
28
     */
29
    public function setManager($em)
30
    {
31
        self::$em = $em;
32
    }
33
34
    /**
35
     * Set the DB connection instance.
36
     */
37
    public function setConnection(Connection $connection)
38
    {
39
        self::$connection = $connection;
40
    }
41
42
    /**
43
     * Get the DB connection instance.
44
     *
45
     * @return Connection
46
     */
47
    public function getConnection()
48
    {
49
        return self::$connection;
50
    }
51
52
    /**
53
     * Get the DB manager instance.
54
     *
55
     * @return EntityManager
56
     */
57
    public static function getManager()
58
    {
59
        return self::$em;
60
    }
61
62
    /**
63
     * Returns the name of the main database.
64
     *
65
     * @return string
66
     */
67
    public static function get_main_database()
68
    {
69
        return self::getManager()->getConnection()->getDatabase();
70
    }
71
72
    /**
73
     * Get main table.
74
     *
75
     * @param string $table
76
     *
77
     * @return string
78
     */
79
    public static function get_main_table($table)
80
    {
81
        return $table;
82
    }
83
84
    /**
85
     * Get course table.
86
     *
87
     * @param string $table
88
     *
89
     * @return string
90
     */
91
    public static function get_course_table($table)
92
    {
93
        return DB_COURSE_PREFIX.$table;
94
    }
95
96
    /**
97
     * Counts the number of rows in a table.
98
     *
99
     * @param string $table The table of which the rows should be counted
100
     *
101
     * @return int the number of rows in the given table
102
     *
103
     * @deprecated
104
     */
105
    public static function count_rows($table)
106
    {
107
        $obj = self::fetch_object(self::query("SELECT COUNT(*) AS n FROM $table"));
108
109
        return $obj->n;
110
    }
111
112
    /**
113
     * Returns the number of affected rows in the last database operation.
114
     *
115
     * @return int
116
     */
117
    public static function affected_rows($result)
118
    {
119
        return $result->rowCount();
120
    }
121
122
    /**
123
     * @return string
124
     */
125
    public static function getUTCDateTimeTypeClass()
126
    {
127
        return isset(self::$utcDateTimeClass) ? self::$utcDateTimeClass : 'Application\DoctrineExtensions\DBAL\Types\UTCDateTimeType';
128
    }
129
130
    /**
131
     * Connect to the database sets the entity manager.
132
     *
133
     * @param array  $params
134
     * @param string $sysPath
135
     * @param string $entityRootPath
136
     * @param bool   $returnConnection
137
     * @param bool   $returnManager
138
     *
139
     * @throws \Doctrine\ORM\ORMException
140
     *
141
     * @return
142
     */
143
    public function connect(
144
        $params = [],
145
        $sysPath = '',
146
        $entityRootPath = '',
147
        $returnConnection = false,
148
        $returnManager = false
149
    ) {
150
        $config = self::getDoctrineConfig($entityRootPath);
151
        $config->setAutoGenerateProxyClasses(true);
152
153
        $config->setEntityNamespaces(
154
            [
155
                'ChamiloUserBundle' => 'Chamilo\UserBundle\Entity',
156
                'ChamiloCoreBundle' => 'Chamilo\CoreBundle\Entity',
157
                'ChamiloCourseBundle' => 'Chamilo\CourseBundle\Entity',
158
                'ChamiloSkillBundle' => 'Chamilo\SkillBundle\Entity',
159
                'ChamiloTicketBundle' => 'Chamilo\TicketBundle\Entity',
160
                'ChamiloPluginBundle' => 'Chamilo\PluginBundle\Entity',
161
            ]
162
        );
163
164
        $params['charset'] = 'utf8';
165
        $entityManager = EntityManager::create($params, $config);
166
        $sysPath = !empty($sysPath) ? $sysPath : api_get_path(SYS_PATH);
167
168
        // Registering Constraints
169
        /*AnnotationRegistry::registerAutoloadNamespace(
170
            'Symfony\Component',
171
            $sysPath."vendor/"
172
        );*/
173
174
        AnnotationRegistry::registerLoader(
175
            function ($class) use ($sysPath) {
176
                $file = str_replace("\\", DIRECTORY_SEPARATOR, $class).".php";
177
                $file = str_replace('Symfony/Component/Validator', '', $file);
178
                $file = str_replace('Symfony\Component\Validator', '', $file);
179
                $fileToInclude = $sysPath.'vendor/symfony/validator/'.$file;
180
181
                if (file_exists($fileToInclude)) {
182
                    // file exists makes sure that the loader fails silently
183
                    require_once $fileToInclude;
184
185
                    return true;
186
                }
187
188
                $fileToInclude = $sysPath.'vendor/symfony/validator/Constraints/'.$file;
189
                if (file_exists($fileToInclude)) {
190
                    // file exists makes sure that the loader fails silently
191
                    require_once $fileToInclude;
192
193
                    return true;
194
                }
195
            }
196
        );
197
198
        AnnotationRegistry::registerFile(
199
            $sysPath."vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntity.php"
200
        );
201
202
        // Registering gedmo extensions
203
        AnnotationRegistry::registerAutoloadNamespace(
204
            'Gedmo\Mapping\Annotation',
205
            $sysPath."vendor/gedmo/doctrine-extensions/lib"
206
        );
207
208
        Type::overrideType(
209
            Type::DATETIME,
210
            self::getUTCDateTimeTypeClass()
211
        );
212
213
        $listener = new \Gedmo\Timestampable\TimestampableListener();
214
        $entityManager->getEventManager()->addEventSubscriber($listener);
215
216
        $listener = new \Gedmo\Tree\TreeListener();
217
        $entityManager->getEventManager()->addEventSubscriber($listener);
218
219
        $listener = new \Gedmo\Sortable\SortableListener();
220
        $entityManager->getEventManager()->addEventSubscriber($listener);
221
        $connection = $entityManager->getConnection();
222
        $connection->executeQuery('SET sql_mode = "";');
223
        $connection->executeQuery('SET SESSION sql_mode = ""');
224
225
        if ($returnConnection) {
226
            return $connection;
227
        }
228
229
        if ($returnManager) {
230
            return $entityManager;
231
        }
232
233
        $this->setConnection($connection);
234
        $this->setManager($entityManager);
235
    }
236
237
    /**
238
     * Escape MySQL wildcards _ and % in LIKE search.
239
     *
240
     * @param string $text The string to escape
241
     *
242
     * @return string The escaped string
243
     */
244
    public static function escape_sql_wildcards($text)
245
    {
246
        $text = api_preg_replace("/_/", "\_", $text);
247
        $text = api_preg_replace("/%/", "\%", $text);
248
249
        return $text;
250
    }
251
252
    /**
253
     * Escapes a string to insert into the database as text.
254
     *
255
     * @param string $string
256
     *
257
     * @return string
258
     */
259
    public static function escape_string($string)
260
    {
261
        $string = self::getManager()->getConnection()->quote($string);
262
        // The quote method from PDO also adds quotes around the string, which
263
        // is not how the legacy mysql_real_escape_string() was used in
264
        // Chamilo, so we need to remove the quotes around. Using trim will
265
        // remove more than one quote if they are sequenced, generating
266
        // broken queries and SQL injection risks
267
        return substr($string, 1, -1);
268
    }
269
270
    /**
271
     * Gets the array from a SQL result (as returned by Database::query).
272
     *
273
     * @param string $option Optional: "ASSOC","NUM" or "BOTH"
274
     *
275
     * @return array|mixed
276
     */
277
    public static function fetch_array($result, $option = 'BOTH')
278
    {
279
        if ($result === false) {
280
            return [];
281
        }
282
283
        return $result->fetch(self::customOptionToDoctrineOption($option));
284
    }
285
286
    /**
287
     * Gets an associative array from a SQL result (as returned by Database::query).
288
     *
289
     * @return array
290
     */
291
    public static function fetch_assoc($result)
292
    {
293
        return $result->fetch(PDO::FETCH_ASSOC);
294
    }
295
296
    /**
297
     * Gets the next row of the result of the SQL query
298
     * (as returned by Database::query) in an object form.
299
     *
300
     * @return mixed
301
     */
302
    public static function fetch_object($result)
303
    {
304
        return $result->fetch(PDO::FETCH_OBJ);
305
    }
306
307
    /**
308
     * Gets the array from a SQL result (as returned by Database::query)
309
     * help achieving database independence.
310
     *
311
     * @return mixed
312
     */
313
    public static function fetch_row($result)
314
    {
315
        if ($result === false) {
316
            return [];
317
        }
318
319
        return $result->fetch(PDO::FETCH_NUM);
320
    }
321
322
    /**
323
     * Frees all the memory associated with the provided result identifier.
324
     *
325
     * @return bool|null Returns TRUE on success or FALSE on failure.
326
     *                   Notes: Use this method if you are concerned about how much memory is being used for queries that return large result sets.
327
     *                   Anyway, all associated result memory is automatically freed at the end of the script's execution.
328
     */
329
    public static function free_result($result)
330
    {
331
        $result->closeCursor();
332
    }
333
334
    /**
335
     * Gets the ID of the last item inserted into the database.
336
     *
337
     * @return string
338
     */
339
    public static function insert_id()
340
    {
341
        return self::getManager()->getConnection()->lastInsertId();
342
    }
343
344
    /**
345
     * Wrapper for rowCount().
346
     *
347
     * @return int
348
     */
349
    public static function num_rows($result)
350
    {
351
        if ($result === false) {
352
            return 0;
353
        }
354
355
        return $result->rowCount();
356
    }
357
358
    /**
359
     * Acts as the relative *_result() function of most DB drivers and fetches a
360
     * specific line and a field.
361
     *
362
     * @param int    $row
363
     * @param string $field
364
     *
365
     * @return mixed
366
     */
367
    public static function result($resource, $row, $field = '')
368
    {
369
        if ($resource->rowCount() > 0) {
370
            $result = $resource->fetchAll(PDO::FETCH_BOTH);
371
372
            return $result[$row][$field];
373
        }
374
375
        return false;
376
    }
377
378
    /**
379
     * Wrapper for executeQuery().
380
     *
381
     * @param string $query
382
     *
383
     * @return Statement
384
     */
385
    public static function query($query)
386
    {
387
        $connection = self::getManager()->getConnection();
388
        $result = null;
389
        try {
390
            $result = $connection->executeQuery($query);
391
        } catch (Exception $e) {
392
            self::handleError($e);
393
        }
394
395
        return $result;
396
    }
397
398
    /**
399
     * Deal with exceptions from the database extension.
400
     *
401
     * @param Exception $e
402
     */
403
    public static function handleError($e)
404
    {
405
        $debug = api_get_setting('server_type') == 'test';
406
        if ($debug) {
407
            // We use Symfony exception handler for better error information
408
            $handler = new ExceptionHandler();
409
            $handler->handle($e);
410
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
411
        } else {
412
            $msg = $e->getMessage();
413
            if (preg_match('/Serialization failure:/', $msg)) {
414
                //do nothing except from logging
415
                error_log($msg.' - Reported but otherwise ignored');
416
            } else {
417
                error_log($msg);
418
                api_not_allowed(false, get_lang('GeneralError'));
419
                exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
420
            }
421
        }
422
    }
423
424
    /**
425
     * Transform an SQL option from Chamilo to PDO syntax.
426
     *
427
     * @param string $option
428
     *
429
     * @return int
430
     */
431
    public static function customOptionToDoctrineOption($option)
432
    {
433
        switch ($option) {
434
            case 'ASSOC':
435
                return PDO::FETCH_ASSOC;
436
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
437
            case 'NUM':
438
                return PDO::FETCH_NUM;
439
                break;
440
            case 'BOTH':
441
            default:
442
                return PDO::FETCH_BOTH;
443
                break;
444
        }
445
    }
446
447
    /**
448
     * Stores a query result into an array.
449
     *
450
     * @author Olivier Brouckaert
451
     *
452
     * @param Statement $result - the return value of the query
453
     * @param string    $option BOTH, ASSOC, or NUM
454
     *
455
     * @return array - the value returned by the query
456
     */
457
    public static function store_result($result, $option = 'BOTH')
458
    {
459
        return $result->fetchAll(self::customOptionToDoctrineOption($option));
460
    }
461
462
    /**
463
     * Build an insert query.
464
     *
465
     * @param string $table_name
466
     * @param array  $attributes
467
     * @param bool   $show_query
468
     *
469
     * @return false|int
470
     */
471
    public static function insert($table_name, $attributes, $show_query = false)
472
    {
473
        if (empty($attributes) || empty($table_name)) {
474
            return false;
475
        }
476
477
        $params = array_keys($attributes);
478
479
        if (!empty($params)) {
480
            $sql = 'INSERT INTO '.$table_name.' ('.implode(',', $params).')
481
                    VALUES (:'.implode(', :', $params).')';
482
483
            $statement = self::getManager()->getConnection()->prepare($sql);
484
            $result = $statement->execute($attributes);
485
486
            if ($show_query) {
487
                var_dump($sql);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($sql) looks like debug code. Are you sure you do not want to remove it?
Loading history...
488
                error_log($sql);
489
            }
490
491
            if ($result) {
492
                return (int) self::getManager()->getConnection()->lastInsertId();
493
            }
494
        }
495
496
        return false;
497
    }
498
499
    /**
500
     * Build an update query.
501
     *
502
     * @param string $tableName       use Database::get_main_table
503
     * @param array  $attributes      Values to updates
504
     *                                Example: $params['name'] = 'Julio'; $params['lastname'] = 'Montoya';
505
     * @param array  $whereConditions where conditions i.e array('id = ?' =>'4')
506
     * @param bool   $showQuery
507
     *
508
     * @return bool|int
509
     */
510
    public static function update(
511
        $tableName,
512
        $attributes,
513
        $whereConditions = [],
514
        $showQuery = false
515
    ) {
516
        if (!empty($tableName) && !empty($attributes)) {
517
            $updateSql = '';
518
            $count = 1;
519
520
            foreach ($attributes as $key => $value) {
521
                if ($showQuery) {
522
                    echo $key.': '.$value.PHP_EOL;
523
                }
524
                $updateSql .= "$key = :$key ";
525
                if ($count < count($attributes)) {
526
                    $updateSql .= ', ';
527
                }
528
                $count++;
529
            }
530
531
            if (!empty($updateSql)) {
532
                //Parsing and cleaning the where conditions
533
                $whereReturn = self::parse_where_conditions($whereConditions);
534
535
                $sql = "UPDATE $tableName SET $updateSql $whereReturn ";
536
537
                $statement = self::getManager()->getConnection()->prepare($sql);
538
539
                $result = $statement->execute($attributes);
540
541
                if ($showQuery) {
542
                    var_dump($sql);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($sql) looks like debug code. Are you sure you do not want to remove it?
Loading history...
543
                    var_dump($attributes);
544
                    var_dump($whereConditions);
545
                }
546
547
                if ($result) {
548
                    return $statement->rowCount();
549
                }
550
            }
551
        }
552
553
        return false;
554
    }
555
556
    /**
557
     * Experimental useful database finder.
558
     *
559
     * @todo lot of stuff to do here
560
     * @todo known issues, it doesn't work when using LIKE conditions
561
     *
562
     * @example array('where'=> array('course_code LIKE "?%"'))
563
     * @example array('where'=> array('type = ? AND category = ?' => array('setting', 'Plugins'))
564
     * @example array('where'=> array('name = "Julio" AND lastname = "montoya"'))
565
     *
566
     * @param mixed  $columns     array (or string if only one column)
567
     * @param string $table_name
568
     * @param array  $conditions
569
     * @param string $type_result all|first|count
570
     * @param string $option
571
     * @param bool   $debug
572
     *
573
     * @return array
574
     */
575
    public static function select(
576
        $columns,
577
        $table_name,
578
        $conditions = [],
579
        $type_result = 'all',
580
        $option = 'ASSOC',
581
        $debug = false
582
    ) {
583
        if ($type_result === 'count') {
584
            $conditions['LIMIT'] = null;
585
            $conditions['limit'] = null;
586
        }
587
588
        $conditions = self::parse_conditions($conditions);
589
590
        //@todo we could do a describe here to check the columns ...
591
        if (is_array($columns)) {
592
            $clean_columns = implode(',', $columns);
593
        } else {
594
            if ($columns === '*') {
595
                $clean_columns = '*';
596
            } else {
597
                $clean_columns = (string) $columns;
598
            }
599
        }
600
601
        if ($type_result === 'count') {
602
            $clean_columns = ' count(*) count ';
603
        }
604
605
        $sql = "SELECT $clean_columns FROM $table_name $conditions";
606
        if ($debug) {
607
            var_dump($sql);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($sql) looks like debug code. Are you sure you do not want to remove it?
Loading history...
608
        }
609
        $result = self::query($sql);
610
611
        if ($type_result === 'count') {
612
            $row = self::fetch_array($result, $option);
613
            if ($row) {
614
                return (int) $row['count'];
615
            }
616
617
            return 0;
618
        }
619
620
        $array = [];
621
        if ($type_result === 'all') {
622
            while ($row = self::fetch_array($result, $option)) {
623
                if (isset($row['iid'])) {
624
                    $array[$row['iid']] = $row;
625
                } elseif (isset($row['id'])) {
626
                    $array[$row['id']] = $row;
627
                } else {
628
                    $array[] = $row;
629
                }
630
            }
631
        } else {
632
            $array = self::fetch_array($result, $option);
633
        }
634
635
        return $array;
636
    }
637
638
    /**
639
     * Parses WHERE/ORDER conditions i.e array('where'=>array('id = ?' =>'4'), 'order'=>'id DESC').
640
     *
641
     * @todo known issues, it doesn't work when using
642
     * LIKE conditions example: array('where'=>array('course_code LIKE "?%"'))
643
     *
644
     * @param array $conditions
645
     *
646
     * @return string Partial SQL string to add to longer query
647
     */
648
    public static function parse_conditions($conditions)
649
    {
650
        if (empty($conditions)) {
651
            return '';
652
        }
653
        $return_value = $where_return = '';
654
        foreach ($conditions as $type_condition => $condition_data) {
655
            if ($condition_data == false) {
656
                continue;
657
            }
658
            $type_condition = strtolower($type_condition);
659
            switch ($type_condition) {
660
                case 'where':
661
                    foreach ($condition_data as $condition => $value_array) {
662
                        if (is_array($value_array)) {
663
                            $clean_values = [];
664
                            foreach ($value_array as $item) {
665
                                $item = self::escape_string($item);
666
                                $clean_values[] = $item;
667
                            }
668
                        } else {
669
                            $value_array = self::escape_string($value_array);
670
                            $clean_values = [$value_array];
671
                        }
672
673
                        if (!empty($condition) && $clean_values != '') {
674
                            $condition = str_replace('%', "'@percentage@'", $condition); //replace "%"
675
                            $condition = str_replace("'?'", "%s", $condition);
676
                            $condition = str_replace("?", "%s", $condition);
677
678
                            $condition = str_replace("@%s@", "@-@", $condition);
679
                            $condition = str_replace("%s", "'%s'", $condition);
680
                            $condition = str_replace("@-@", "@%s@", $condition);
681
682
                            // Treat conditions as string
683
                            $condition = vsprintf($condition, $clean_values);
684
                            $condition = str_replace('@percentage@', '%', $condition); //replace "%"
685
                            $where_return .= $condition;
686
                        }
687
                    }
688
689
                    if (!empty($where_return)) {
690
                        $return_value = " WHERE $where_return";
691
                    }
692
                    break;
693
                case 'order':
694
                    $order_array = $condition_data;
695
696
                    if (!empty($order_array)) {
697
                        // 'order' => 'id desc, name desc'
698
                        $order_array = self::escape_string($order_array);
699
                        $new_order_array = explode(',', $order_array);
700
                        $temp_value = [];
701
702
                        foreach ($new_order_array as $element) {
703
                            $element = explode(' ', $element);
704
                            $element = array_filter($element);
705
                            $element = array_values($element);
706
707
                            if (!empty($element[1])) {
708
                                $element[1] = strtolower($element[1]);
709
                                $order = 'DESC';
710
                                if (in_array($element[1], ['desc', 'asc'])) {
711
                                    $order = $element[1];
712
                                }
713
                                $temp_value[] = ' `'.$element[0].'` '.$order.' ';
714
                            } else {
715
                                //by default DESC
716
                                $temp_value[] = ' `'.$element[0].'` DESC ';
717
                            }
718
                        }
719
                        if (!empty($temp_value)) {
720
                            $return_value .= ' ORDER BY '.implode(', ', $temp_value);
721
                        }
722
                    }
723
                    break;
724
                case 'limit':
725
                    $limit_array = explode(',', $condition_data);
726
                    if (!empty($limit_array)) {
727
                        if (count($limit_array) > 1) {
728
                            $return_value .= ' LIMIT '.intval($limit_array[0]).' , '.intval($limit_array[1]);
729
                        } else {
730
                            $return_value .= ' LIMIT '.intval($limit_array[0]);
731
                        }
732
                    }
733
                    break;
734
            }
735
        }
736
737
        return $return_value;
738
    }
739
740
    /**
741
     * @param array $conditions
742
     *
743
     * @return string
744
     */
745
    public static function parse_where_conditions($conditions)
746
    {
747
        return self::parse_conditions(['where' => $conditions]);
748
    }
749
750
    /**
751
     * Build a delete query.
752
     *
753
     * @param string $table_name
754
     * @param array  $where_conditions
755
     * @param bool   $show_query
756
     *
757
     * @return int
758
     */
759
    public static function delete($table_name, $where_conditions, $show_query = false)
760
    {
761
        $where_return = self::parse_where_conditions($where_conditions);
762
        $sql = "DELETE FROM $table_name $where_return ";
763
        if ($show_query) {
764
            echo $sql;
765
            echo '<br />';
766
        }
767
        $result = self::query($sql);
768
        $affected_rows = self::affected_rows($result);
769
        //@todo should return affected_rows for
770
        return $affected_rows;
771
    }
772
773
    /**
774
     * Get Doctrine configuration.
775
     *
776
     * @param string $path
777
     *
778
     * @return \Doctrine\ORM\Configuration
779
     */
780
    public static function getDoctrineConfig($path)
781
    {
782
        $isDevMode = true; // Forces doctrine to use ArrayCache instead of apc/xcache/memcache/redis
783
        $isSimpleMode = false; // related to annotations @Entity
784
        $cache = null;
785
        $path = !empty($path) ? $path : api_get_path(SYS_PATH);
786
787
        $paths = [
788
            //$path.'src/Chamilo/ClassificationBundle/Entity',
789
            //$path.'src/Chamilo/MediaBundle/Entity',
790
            //$path.'src/Chamilo/PageBundle/Entity',
791
            $path.'src/Chamilo/CoreBundle/Entity',
792
            $path.'src/Chamilo/UserBundle/Entity',
793
            $path.'src/Chamilo/CourseBundle/Entity',
794
            $path.'src/Chamilo/TicketBundle/Entity',
795
            $path.'src/Chamilo/SkillBundle/Entity',
796
            $path.'src/Chamilo/PluginBundle/Entity',
797
            //$path.'vendor/sonata-project/user-bundle/Entity',
798
            //$path.'vendor/sonata-project/user-bundle/Model',
799
            //$path.'vendor/friendsofsymfony/user-bundle/FOS/UserBundle/Entity',
800
        ];
801
802
        $proxyDir = $path.'app/cache/';
803
804
        $config = \Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration(
805
            $paths,
806
            $isDevMode,
807
            $proxyDir,
808
            $cache,
809
            $isSimpleMode
810
        );
811
812
        return $config;
813
    }
814
815
    /**
816
     * Check if a given table exists.
817
     *
818
     * @param string $table
819
     *
820
     * @return bool
821
     */
822
    public static function tableExists($table)
823
    {
824
        return self::getManager()->getConnection()->getSchemaManager()->tablesExist($table);
825
    }
826
827
    /**
828
     * List the columns of a given table.
829
     *
830
     * @param string $table
831
     *
832
     * @return \Doctrine\DBAL\Schema\Column[]
833
     */
834
    public static function listTableColumns($table)
835
    {
836
        return self::getManager()->getConnection()->getSchemaManager()->listTableColumns($table);
837
    }
838
839
    public static function escapeField($field)
840
    {
841
        return self::escape_string(preg_replace("/[^a-zA-Z0-9_.]/", '', $field));
842
    }
843
}
844