Passed
Push — master ( 565006...c30de3 )
by Andreas
05:23 queued 01:38
created

connection::invalidate_cache()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 2
b 0
f 0
nc 2
nop 0
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 2
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
use Doctrine\DBAL\Logging\Middleware;
26
27
class connection
28
{
29
    private static ?Logger $logger = null;
30
31
    /**
32
     * Loglevel translation table.
33
     *
34
     * The semantics of info and notice/message are unfortunately reversed between Monolog
35
     * and Midgard, so it looks a bit confusing..
36
     */
37
    private static array $loglevels = [
38
        'error' => Logger::ERROR,
39
        'warn' => Logger::WARNING,
40
        'warning' => Logger::WARNING,
41
        'info' => Logger::NOTICE,
42
        'message' => Logger::INFO,
43
        'debug' => Logger::DEBUG
44
    ];
45
46
    /**
47
     * Flag for automatically starting up during initialize
48
     */
49
    private static bool $autostart = true;
50
51
    /**
52
     * Initialization parameters
53
     */
54
    private static array $parameters = [];
55
56
    private ?user $user = null;
57
58
    private string $namespace;
59
60
    protected EntityManager $em;
61
62
    protected static ?self $instance = null;
63
64 7
    public function __construct(EntityManager $em, string $namespace)
65
    {
66 7
        $this->em = $em;
67 7
        $this->namespace = $namespace;
68
    }
69
70 168
    public static function get_em() : EntityManager
71
    {
72 168
        if (self::$instance === null) {
73
            throw new \Exception('Not initialized');
74
        }
75 168
        return self::$instance->em;
76
    }
77
78 102
    public static function get_user() : ?user
79
    {
80 102
        return self::$instance->user;
81
    }
82
83 8
    public static function set_user(user $user = null)
84
    {
85 8
        if (self::$instance === null) {
86
            throw new \Exception('Not initialized');
87
        }
88 8
        self::$instance->user = $user;
89
    }
90
91 172
    public static function get_fqcn(string $classname) : string
92
    {
93 172
        if (self::$instance->namespace) {
94 172
            return self::$instance->namespace . '\\' . $classname;
95
        }
96
        return $classname;
97
    }
98
99
    /**
100
     * Generate a new GUID
101
     */
102 118
    public static function generate_guid() : string
103
    {
104 118
        return bin2hex(random_bytes(16));
105
    }
106
107
    /**
108
     * Invalidate ClassMetadata cache
109
     */
110 1
    public static function invalidate_cache()
111
    {
112 1
        if ($cache = self::get_em()->getConfiguration()->getMetadataCache()) {
113 1
            $cache->clear();
114
        }
115
    }
116
117
    /**
118
     * Toggle autostart
119
     */
120 1
    public static function set_autostart(bool $autostart)
121
    {
122 1
        self::$autostart = $autostart;
123
    }
124
125
    /**
126
     * Initialize Midgard connection
127
     */
128 10
    public static function initialize(driver $driver, array $db_config, bool $dev_mode = false)
129
    {
130 10
        $vardir = $driver->get_vardir();
131
132 10
        $mgd_config = new config;
133 10
        $mgd_config->vardir = $vardir;
134 10
        $mgd_config->cachedir = $vardir . '/cache';
135 10
        $mgd_config->blobdir = $vardir . '/blobs';
136 10
        $mgd_config->sharedir = $vardir . '/schemas';
137 10
        $mgd_config->logfilename = $vardir . '/log/midgard-portable.log';
138
        // TODO: Set rest of config values from $config and $driver
139
140
        // we open the config before startup to have logfile available
141 10
        midgard_connection::get_instance()->open_config($mgd_config);
142
143 10
        self::$parameters = ['driver' => $driver, 'db_config' => $db_config, 'dev_mode' => $dev_mode];
144 10
        if (self::$autostart) {
145 6
            static::startup();
146
        }
147
    }
148
149 1
    public static function get_parameter(string $name)
150
    {
151 1
        if (!array_key_exists($name, self::$parameters)) {
152
            throw new \RuntimeException('Parameter "' . $name . '" is not available');
153
        }
154 1
        return self::$parameters[$name];
155
    }
156
157
    /**
158
     * Start the API emulation layer
159
     */
160 7
    public static function startup()
161
    {
162 7
        if (empty(self::$parameters)) {
163
            throw new \RuntimeException('Not initialized');
164
        }
165 7
        $driver = self::$parameters['driver'];
166 7
        $db_config = self::$parameters['db_config'];
167 7
        $dev_mode = self::$parameters['dev_mode'];
168 7
        $vardir = $driver->get_vardir();
169
        // generate and include entities file if its a fresh namespace
170
        // otherwise it should be included already
171 7
        if ($driver->is_fresh_namespace()) {
172 7
            $entityfile = $vardir . '/mgdschema_classes.php';
173 7
            if ($dev_mode || !file_exists($entityfile)) {
174 7
                $classgenerator = new classgenerator($driver->get_manager(), $entityfile, $dev_mode);
175 7
                $classgenerator->write($driver->get_namespace());
176
            }
177 7
            require $entityfile;
178
        }
179
180 7
        $config = ORMSetup::createConfiguration($dev_mode, $vardir . '/cache');
181 7
        $config->addFilter('softdelete', softdelete::class);
182 7
        $config->setMetadataDriverImpl($driver);
183 7
        $config->setClassMetadataFactoryName(factory::class);
184
185 7
        $midgard = midgard_connection::get_instance();
186 7
        $level = self::$loglevels[$midgard->get_loglevel()];
187 7
        if ($level === Logger::DEBUG) {
188
            $logger = new Logger('doctrine');
189
            $logger->pushHandler(new StreamHandler($midgard->config->logfilename, $level));
190
            $config->setMiddlewares([new Middleware($logger)]);
191
        }
192
193 7
        if (!array_key_exists('charset', $db_config)) {
194 7
            $db_config['charset'] = 'utf8';
195
        }
196
197 7
        $connection = \Doctrine\DBAL\DriverManager::getConnection($db_config, $config);
198 7
        $em = new EntityManager($connection, $config);
199 7
        $em->getFilters()->enable('softdelete');
200 7
        $em->getEventManager()->addEventSubscriber(new subscriber);
201
202 7
        Type::overrideType(Types::DATETIME_MUTABLE, datetime::class);
203
204 7
        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