1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Bridges\DatabaseDI;
9:
10: use Nette;
11:
12:
13: 14: 15:
16: class DatabaseExtension extends Nette\DI\CompilerExtension
17: {
18: public $databaseDefaults = [
19: 'dsn' => null,
20: 'user' => null,
21: 'password' => null,
22: 'options' => null,
23: 'debugger' => true,
24: 'explain' => true,
25: 'reflection' => null,
26: 'conventions' => 'discovered',
27: 'autowired' => null,
28: ];
29:
30:
31: private $debugMode;
32:
33:
34: public function __construct($debugMode = false)
35: {
36: $this->debugMode = $debugMode;
37: }
38:
39:
40: public function loadConfiguration()
41: {
42: $configs = $this->getConfig();
43: foreach ($configs as $k => $v) {
44: if (is_scalar($v)) {
45: $configs = ['default' => $configs];
46: break;
47: }
48: }
49:
50: $defaults = $this->databaseDefaults;
51: $defaults['autowired'] = true;
52: foreach ((array) $configs as $name => $config) {
53: if (!is_array($config)) {
54: continue;
55: }
56: $config = $this->validateConfig($defaults, $config, $this->prefix($name));
57: $defaults['autowired'] = false;
58: $this->setupDatabase($config, $name);
59: }
60: }
61:
62:
63: private function setupDatabase($config, $name)
64: {
65: $builder = $this->getContainerBuilder();
66:
67: foreach ((array) $config['options'] as $key => $value) {
68: if (is_string($value) && preg_match('#^PDO::\w+\z#', $value)) {
69: $config['options'][$key] = $value = constant($value);
70: }
71: if (preg_match('#^PDO::\w+\z#', $key)) {
72: unset($config['options'][$key]);
73: $config['options'][constant($key)] = $value;
74: }
75: }
76:
77: $connection = $builder->addDefinition($this->prefix("$name.connection"))
78: ->setFactory(Nette\Database\Connection::class, [$config['dsn'], $config['user'], $config['password'], $config['options']])
79: ->setAutowired($config['autowired']);
80:
81: $structure = $builder->addDefinition($this->prefix("$name.structure"))
82: ->setFactory(Nette\Database\Structure::class)
83: ->setArguments([$connection])
84: ->setAutowired($config['autowired']);
85:
86: if (!empty($config['reflection'])) {
87: $conventionsServiceName = 'reflection';
88: $config['conventions'] = $config['reflection'];
89: if (is_string($config['conventions']) && strtolower($config['conventions']) === 'conventional') {
90: $config['conventions'] = 'Static';
91: }
92: } else {
93: $conventionsServiceName = 'conventions';
94: }
95:
96: if (!$config['conventions']) {
97: $conventions = null;
98:
99: } elseif (is_string($config['conventions'])) {
100: $conventions = $builder->addDefinition($this->prefix("$name.$conventionsServiceName"))
101: ->setFactory(preg_match('#^[a-z]+\z#i', $config['conventions'])
102: ? 'Nette\Database\Conventions\\' . ucfirst($config['conventions']) . 'Conventions'
103: : $config['conventions'])
104: ->setArguments(strtolower($config['conventions']) === 'discovered' ? [$structure] : [])
105: ->setAutowired($config['autowired']);
106:
107: } else {
108: $class = method_exists(Nette\DI\Helpers::class, 'filterArguments') ? Nette\DI\Helpers::class : Nette\DI\Compiler::class;
109: $conventions = $class::filterArguments([$config['conventions']])[0];
110: }
111:
112: $builder->addDefinition($this->prefix("$name.context"))
113: ->setFactory(Nette\Database\Context::class, [$connection, $structure, $conventions])
114: ->setAutowired($config['autowired']);
115:
116: if ($config['debugger']) {
117: $connection->addSetup('@Tracy\BlueScreen::addPanel', [
118: 'Nette\Bridges\DatabaseTracy\ConnectionPanel::renderException',
119: ]);
120: if ($this->debugMode) {
121: $connection->addSetup('Nette\Database\Helpers::createDebugPanel', [$connection, !empty($config['explain']), $name]);
122: }
123: }
124:
125: if ($this->name === 'database') {
126: $builder->addAlias($this->prefix($name), $this->prefix("$name.connection"));
127: $builder->addAlias("nette.database.$name", $this->prefix($name));
128: $builder->addAlias("nette.database.$name.context", $this->prefix("$name.context"));
129: }
130: }
131: }
132: