Passed
Push — master ( 8e3077...24a79d )
by Andreas
03:41
created

connection::get_em()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 6
ccs 3
cts 4
cp 0.75
crap 2.0625
rs 10
1
<?php
2
/**
3
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
4
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
6
 */
7
8
namespace midgard\portable\storage;
9
10
use midgard\portable\driver;
11
use midgard\portable\classgenerator;
12
use midgard\portable\api\user;
13
use midgard\portable\api\config;
14
use midgard\portable\api\error\exception;
15
use midgard\portable\storage\type\datetime;
16
use Doctrine\ORM\EntityManager;
17
use Doctrine\DBAL\Types\Type;
18
use Monolog\Logger;
19
use Monolog\Handler\StreamHandler;
20
use midgard_connection;
21
use midgard\portable\storage\filter\softdelete;
22
use midgard\portable\mapping\factory;
23
use Doctrine\DBAL\Types\Types;
24
use Doctrine\ORM\ORMSetup;
25
26
class connection
27
{
28
    private static ?Logger $logger = null;
29
30
    /**
31
     * Loglevel translation table.
32
     *
33
     * The semantics of info and notice/message are unfortunately reversed between Monolog
34
     * and Midgard, so it looks a bit confusing..
35
     */
36
    private static array $loglevels = [
37
        'error' => Logger::ERROR,
38
        'warn' => Logger::WARNING,
39
        'warning' => Logger::WARNING,
40
        'info' => Logger::NOTICE,
41
        'message' => Logger::INFO,
42
        'debug' => Logger::DEBUG
43
    ];
44
45
    /**
46
     * Flag for automatically starting up during initialize
47
     */
48
    private static bool $autostart = true;
49
50
    /**
51
     * Initialization parameters
52
     */
53
    private static array $parameters = [];
54
55
    private ?user $user = null;
56
57
    private string $namespace;
58
59
    protected EntityManager $em;
60
61
    protected static ?self $instance = null;
62
63 9
    public function __construct(EntityManager $em, string $namespace)
64
    {
65 9
        $this->em = $em;
66 9
        $this->namespace = $namespace;
67
    }
68
69 166
    public static function get_em() : EntityManager
70
    {
71 166
        if (self::$instance === null) {
72
            throw new \Exception('Not initialized');
73
        }
74 166
        return self::$instance->em;
75
    }
76
77 100
    public static function get_user() : ?user
78
    {
79 100
        return self::$instance->user;
80
    }
81
82 8
    public static function set_user(user $user = null)
83
    {
84 8
        if (self::$instance === null) {
85
            throw new \Exception('Not initialized');
86
        }
87 8
        self::$instance->user = $user;
88
    }
89
90 170
    public static function get_fqcn(string $classname) : string
91
    {
92 170
        if (self::$instance->namespace) {
93 170
            return self::$instance->namespace . '\\' . $classname;
94
        }
95
        return $classname;
96
    }
97
98
    /**
99
     * Generate a new GUID
100
     */
101 116
    public static function generate_guid() : string
102
    {
103 116
        return bin2hex(random_bytes(16));
104
    }
105
106
    /**
107
     * Invalidate ClassMetadata cache
108
     */
109
    public static function invalidate_cache()
110
    {
111
        if ($cache = self::get_em()->getConfiguration()->getMetadataCache()) {
112
            $cache->clear();
113
        }
114
    }
115
116
    /**
117
     * Toggle autostart
118
     */
119
    public static function set_autostart(bool $autostart)
120
    {
121
        self::$autostart = $autostart;
122
    }
123
124
    /**
125
     * Initialize Midgard connection
126
     */
127 9
    public static function initialize(driver $driver, array $db_config, bool $dev_mode = false)
128
    {
129 9
        $vardir = $driver->get_vardir();
130
131 9
        $mgd_config = new config;
132 9
        $mgd_config->vardir = $vardir;
133 9
        $mgd_config->cachedir = $vardir . '/cache';
134 9
        $mgd_config->blobdir = $vardir . '/blobs';
135 9
        $mgd_config->sharedir = $vardir . '/schemas';
136 9
        $mgd_config->logfilename = $vardir . '/log/midgard-portable.log';
137
        // TODO: Set rest of config values from $config and $driver
138
139
        // we open the config before startup to have logfile available
140 9
        midgard_connection::get_instance()->open_config($mgd_config);
141
142 9
        self::$parameters = ['driver' => $driver, 'db_config' => $db_config, 'dev_mode' => $dev_mode];
143 9
        if (self::$autostart) {
144 9
            static::startup();
145
        }
146
    }
147
148
    public static function get_parameter(string $name)
149
    {
150
        if (!array_key_exists($name, self::$parameters)) {
151
            throw new \RuntimeException('Parameter "' . $name . '" is not available');
152
        }
153
        return self::$parameters[$name];
154
    }
155
156
    /**
157
     * Start the API emulation layer
158
     */
159 9
    public static function startup()
160
    {
161 9
        if (empty(self::$parameters)) {
162
            throw new \RuntimeException('Not initialized');
163
        }
164 9
        $driver = self::$parameters['driver'];
165 9
        $db_config = self::$parameters['db_config'];
166 9
        $dev_mode = self::$parameters['dev_mode'];
167 9
        $vardir = $driver->get_vardir();
168
        // generate and include entities file if its a fresh namespace
169
        // otherwise it should be included already
170 9
        if ($driver->is_fresh_namespace()) {
171 9
            $entityfile = $vardir . '/mgdschema_classes.php';
172 9
            if ($dev_mode || !file_exists($entityfile)) {
173 9
                $classgenerator = new classgenerator($driver->get_manager(), $entityfile, $dev_mode);
174 9
                $classgenerator->write($driver->get_namespace());
175
            }
176 9
            require $entityfile;
177
        }
178
179 9
        $config = ORMSetup::createConfiguration($dev_mode, $vardir . '/cache');
180 9
        $config->addFilter('softdelete', softdelete::class);
181 9
        $config->setMetadataDriverImpl($driver);
182 9
        $config->setClassMetadataFactoryName(factory::class);
183
184 9
        if (!array_key_exists('charset', $db_config)) {
185 9
            $db_config['charset'] = 'utf8';
186
        }
187
188 9
        $em = \Doctrine\ORM\EntityManager::create($db_config, $config);
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\ORM\EntityManager::create() has been deprecated: Use {@see DriverManager::getConnection()} to bootstrap the connection and call the constructor. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

188
        $em = /** @scrutinizer ignore-deprecated */ \Doctrine\ORM\EntityManager::create($db_config, $config);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
189 9
        $em->getFilters()->enable('softdelete');
190 9
        $em->getEventManager()->addEventSubscriber(new subscriber);
191
192 9
        Type::overrideType(Types::DATETIME_MUTABLE, datetime::class);
193 9
        Type::overrideType(Types::DATE_MUTABLE, datetime::class);
194
195 9
        $midgard = midgard_connection::get_instance();
196 9
        $level = self::$loglevels[$midgard->get_loglevel()];
197 9
        if ($level === Logger::DEBUG) {
198
            $logger = new Logger('doctrine');
199
            $logger->pushHandler(new StreamHandler($midgard->config->logfilename, $level));
200
201
            $em->getConnection()->getConfiguration()->setSQLLogger(new sqllogger($logger));
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Configuration::setSQLLogger() has been deprecated: Use {@see setMiddlewares()} and {@see \Doctrine\DBAL\Logging\Middleware} instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

201
            /** @scrutinizer ignore-deprecated */ $em->getConnection()->getConfiguration()->setSQLLogger(new sqllogger($logger));

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
202
        }
203
204 9
        self::$instance = new static($em, $driver->get_namespace());
205
    }
206
207
    /**
208
     * Get Logger instance
209
     */
210 3
    public static function log() : Logger
211
    {
212 3
        if (self::$logger === null) {
213 1
            $midgard = midgard_connection::get_instance();
214 1
            if ($midgard->config->logfilename) {
215 1
                $logdir = dirname($midgard->config->logfilename);
216 1
                if (   !is_dir($logdir)
217 1
                    && !mkdir($logdir, 0777, true)) {
218
                    throw exception::user_data('Log directory could not be created');
219
                }
220 1
                self::$logger = new Logger('midgard-portable');
221 1
                self::$logger->pushHandler(new StreamHandler($midgard->config->logfilename, self::$loglevels[$midgard->get_loglevel()]));
0 ignored issues
show
Bug introduced by
The method pushHandler() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

221
                self::$logger->/** @scrutinizer ignore-call */ 
222
                               pushHandler(new StreamHandler($midgard->config->logfilename, self::$loglevels[$midgard->get_loglevel()]));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
222
            } else {
223
                throw exception::user_data('log filename not set in config');
224
            }
225
        }
226 3
        return self::$logger;
227
    }
228
}
229