Passed
Push — develop ( 6fe1b7...4c812d )
by Nikolay
05:04
created

DatabaseProviderBase::recreateDBConnections()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 11
c 0
b 0
f 0
dl 0
loc 19
rs 9.9
cc 2
nc 2
nop 0
1
<?php
2
/*
3
 * MikoPBX - free phone system for small business
4
 * Copyright (C) 2017-2020 Alexey Portnov and Nikolay Beketov
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with this program.
17
 * If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
declare(strict_types=1);
21
22
namespace MikoPBX\Common\Providers;
23
24
25
use MikoPBX\Core\Providers\EventsLogDatabaseProvider;
26
use MikoPBX\Core\System\Util;
27
use Phalcon\Di;
28
use Phalcon\Di\DiInterface;
29
use Phalcon\Events\Manager as EventsManager;
30
use Phalcon\Logger;
31
use Phalcon\Logger\Adapter\Stream as FileLogger;
32
33
/**
34
 * Main database connection is created based in the parameters defined in the configuration file
35
 */
36
abstract class DatabaseProviderBase
37
{
38
    /**
39
     * Register db service provider
40
     *
41
     * @param string                  $serviceName Injection service name
42
     * @param \Phalcon\Di\DiInterface $di
43
     * @param array         $dbConfig
44
     */
45
    public function registerDBService(string $serviceName, DiInterface $di, array $dbConfig): void
46
    {
47
        $di->setShared(
48
            $serviceName,
49
            function () use ($dbConfig) {
50
                $dbclass    = 'Phalcon\Db\Adapter\Pdo\\' . $dbConfig['adapter'];
51
52
                $folderWithDB = dirname($dbConfig['dbfile']);
53
                if (!is_dir($folderWithDB)){
54
                    Util::mwMkdir($folderWithDB, true);
55
                }
56
57
                $connection = new $dbclass(
58
                    [
59
                        'dbname' => $dbConfig['dbfile'],
60
                    ]
61
                );
62
                $connection->setNestedTransactionsWithSavepoints(true);
63
                if ($dbConfig['debugMode']) {
64
                    $adapter       = new FileLogger($dbConfig['debugLogFile']);
65
                    $logger        = new Logger(
66
                        'messages',
67
                        [
68
                            'main' => $adapter,
69
                        ]
70
                    );
71
                    $eventsManager = new EventsManager();
72
                    // Слушаем все события базы данных
73
                    $eventsManager->attach(
74
                        'db',
75
                        function ($event, $connection) use ($logger) {
76
                            if ($event->getType() === 'beforeQuery') {
77
                                $statement = $connection->getSQLStatement();
78
                                $variables = $connection->getSqlVariables();
79
                                if (is_array($variables)) {
80
                                    foreach ($variables as $variable => $value) {
81
                                        if (is_array($value)) {
82
                                            $value = '(' . implode(', ', $value) . ')';
83
                                        }
84
                                        $variable  = str_replace(':', '', $variable);
85
                                        $statement = str_replace(":$variable", "'$value'", $statement);
86
                                        $statement = preg_replace('/= \?/', " = '{$value}'", $statement, 1);
87
                                      //  $statement = preg_replace('/\?/', " = '{$value}'", $statement, 1);
88
                                    }
89
                                }
90
                                $callStack = json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,50), JSON_PRETTY_PRINT);
91
                                $logger->debug("Request: \n {$statement}\nCall stack:\n{$callStack} \n\n\n\n");
92
                            }
93
                        }
94
                    );
95
96
                    // Назначаем EventsManager экземпляру адаптера базы данных
97
                    $connection->setEventsManager($eventsManager);
98
                }
99
100
                return $connection;
101
            }
102
        );
103
    }
104
105
    /**
106
     * Recreate DB connections after table structure changes
107
     */
108
    public static function recreateDBConnections(): void
109
    {
110
        $dbProvidersList = [
111
            ModelsCacheProvider::class, // Always recreate it before change DB providers
112
113
            MainDatabaseProvider::class,
114
            CDRDatabaseProvider::class,
115
            EventsLogDatabaseProvider::class,
116
117
            ModelsMetadataProvider::class,
118
            ModelsAnnotationsProvider::class,
119
        ];
120
121
        $di = Di::getDefault();
122
123
        foreach ($dbProvidersList as $provider) {
124
            // Delete previous provider
125
            $di->remove($provider::SERVICE_NAME);
126
            $di->register(new $provider());
127
        }
128
    }
129
}