Passed
Push — master ( dd2b6c...573650 )
by Andreas
04:29
created

connection::get_parameter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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