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); |
|
|
|
|
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)); |
|
|
|
|
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()])); |
|
|
|
|
222
|
|
|
} else { |
223
|
|
|
throw exception::user_data('log filename not set in config'); |
224
|
|
|
} |
225
|
|
|
} |
226
|
3 |
|
return self::$logger; |
227
|
|
|
} |
228
|
|
|
} |
229
|
|
|
|
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.