Completed
Push — master ( 02745e...0cb812 )
by Valentin
07:17
created

TestLogger::log()   C

Complexity

Conditions 13
Paths 32

Size

Total Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 43
rs 6.6166
c 0
b 0
f 0
cc 13
nc 32
nop 3

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
namespace Cycle\ORM\Promise\Tests;
11
12
use Cycle\ORM\Config\RelationConfig;
13
use Cycle\ORM\Factory;
14
use Cycle\ORM\ORM;
15
use Cycle\ORM\SchemaInterface;
16
use PHPUnit\Framework\TestCase;
17
use Psr\Log\LoggerInterface;
18
use Psr\Log\LoggerTrait;
19
use Psr\Log\LogLevel;
20
use Spiral\Database\Config\DatabaseConfig;
21
use Spiral\Database\Database;
22
use Spiral\Database\DatabaseManager;
23
use Spiral\Database\Driver\Driver;
24
use Spiral\Database\Driver\Handler;
25
use Spiral\Tokenizer\ClassesInterface;
26
use Spiral\Tokenizer\Config\TokenizerConfig;
27
use Spiral\Tokenizer\Tokenizer;
28
29
abstract class BaseTest extends TestCase
30
{
31
    // tests configuration
32
    public static $config;
33
34
    // currently active driver
35
    public const DRIVER = null;
36
37
    // cross test driver cache
38
    public static $driverCache = [];
39
40
    protected static $lastORM;
41
42
    /** @var Driver */
43
    protected $driver;
44
45
    /** @var DatabaseManager */
46
    protected $dbal;
47
48
    /** @var ORM */
49
    protected $orm;
50
51
    /** @var TestLogger */
52
    protected $logger;
53
54
    /** @var ClassesInterface */
55
    protected $locator;
56
57
    /**
58
     * Init all we need.
59
     */
60
    public function setUp()
61
    {
62
        parent::setUp();
63
64
        $this->dbal = new DatabaseManager(new DatabaseConfig(['default' => 'default']));
65
        $this->dbal->addDatabase(new Database(
66
            'default',
67
            '',
68
            $this->getDriver()
69
        ));
70
71
        $this->dbal->addDatabase(new Database(
72
            'secondary',
73
            'secondary_',
74
            $this->getDriver()
75
        ));
76
77
        $this->logger = new TestLogger();
78
        $this->getDriver()->setLogger($this->logger);
79
80
        if (self::$config['debug']) {
81
            $this->logger->display();
82
        }
83
84
        $this->logger = new TestLogger();
85
        $this->getDriver()->setLogger($this->logger);
86
87
        if (self::$config['debug']) {
88
            $this->logger->display();
89
        }
90
91
        $this->orm = new ORM(new Factory(
92
            $this->dbal,
93
            RelationConfig::getDefault()
94
        ));
95
96
        $tokenizer = new Tokenizer(new TokenizerConfig([
97
            'directories' => [__DIR__ . '/Fixtures'],
98
            'exclude'     => [],
99
        ]));
100
101
        $this->locator = $tokenizer->classLocator();
102
    }
103
104
    /**
105
     * Cleanup.
106
     */
107
    public function tearDown()
108
    {
109
        $this->disableProfiling();
110
        $this->dropDatabase($this->dbal->database('default'));
111
        $this->orm = null;
112
        $this->dbal = null;
113
    }
114
115
    /**
116
     * Calculates missing parameters for typecasting.
117
     *
118
     * @param SchemaInterface $schema
119
     *
120
     * @return ORM|\Cycle\ORM\ORMInterface
121
     */
122
    public function withSchema(SchemaInterface $schema)
123
    {
124
        $this->orm = $this->orm->withSchema($schema);
125
126
        return $this->orm;
127
    }
128
129
    /**
130
     * @return Driver
131
     */
132
    public function getDriver(): Driver
133
    {
134
        if (isset(static::$driverCache[static::DRIVER])) {
135
            return static::$driverCache[static::DRIVER];
136
        }
137
138
        $config = self::$config[static::DRIVER];
139
        if (!isset($this->driver)) {
140
            $class = $config['driver'];
141
142
            $this->driver = new $class([
143
                'connection' => $config['conn'],
144
                'username'   => $config['user'],
145
                'password'   => $config['pass'],
146
                'options'    => []
147
            ]);
148
        }
149
150
        $this->driver->setProfiling(true);
151
152
        return static::$driverCache[static::DRIVER] = $this->driver;
153
    }
154
155
    /**
156
     * @return Database
157
     */
158
    protected function getDatabase(): Database
159
    {
160
        return $this->dbal->database('default');
161
    }
162
163
    /**
164
     * @param Database|null $database
165
     */
166
    protected function dropDatabase(Database $database = null)
167
    {
168
        if (empty($database)) {
169
            return;
170
        }
171
172
        foreach ($database->getTables() as $table) {
173
            $schema = $table->getSchema();
174
175
            foreach ($schema->getForeignKeys() as $foreign) {
176
                $schema->dropForeignKey($foreign->getColumn());
177
            }
178
179
            $schema->save(Handler::DROP_FOREIGN_KEYS);
180
        }
181
182
        foreach ($database->getTables() as $table) {
183
            $schema = $table->getSchema();
184
            $schema->declareDropped();
185
            $schema->save();
186
        }
187
    }
188
189
    /**
190
     * For debug purposes only.
191
     */
192
    protected function enableProfiling()
193
    {
194
        if (!is_null($this->logger)) {
195
            $this->logger->display();
196
        }
197
    }
198
199
    /**
200
     * For debug purposes only.
201
     */
202
    protected function disableProfiling()
203
    {
204
        if (!is_null($this->logger)) {
205
            $this->logger->hide();
206
        }
207
    }
208
}
209
210
class TestLogger implements LoggerInterface
211
{
212
    use LoggerTrait;
213
214
    private $display;
215
216
    private $countWrites;
217
    private $countReads;
218
219
    public function __construct()
220
    {
221
        $this->countWrites = 0;
222
        $this->countReads = 0;
223
    }
224
225
    public function countWriteQueries(): int
226
    {
227
        return $this->countWrites;
228
    }
229
230
    public function countReadQueries(): int
231
    {
232
        return $this->countReads;
233
    }
234
235
    public function log($level, $message, array $context = [])
236
    {
237
        if (!empty($context['query'])) {
238
            $sql = strtolower($context['query']);
239
            if (
240
                strpos($sql, 'insert') === 0
241
                || strpos($sql, 'update') === 0
242
                || strpos($sql, 'delete') === 0
243
            ) {
244
                $this->countWrites++;
245
            } else {
246
                if (!$this->isPostgresSystemQuery($sql)) {
247
                    $this->countReads++;
248
                }
249
            }
250
        }
251
252
        if (!$this->display) {
253
            return;
254
        }
255
256
        if ($level == LogLevel::ERROR) {
257
            echo " \n! \033[31m" . $message . "\033[0m";
258
        } elseif ($level == LogLevel::ALERT) {
259
            echo " \n! \033[35m" . $message . "\033[0m";
260
        } elseif (strpos($message, 'SHOW') === 0) {
261
            echo " \n> \033[34m" . $message . "\033[0m";
262
        } else {
263
            if ($this->isPostgresSystemQuery($message)) {
264
                echo " \n> \033[90m" . $message . "\033[0m";
265
266
                return;
267
            }
268
269
            if (strpos($message, 'SELECT') === 0) {
270
                echo " \n> \033[32m" . $message . "\033[0m";
271
            } elseif (strpos($message, 'INSERT') === 0) {
272
                echo " \n> \033[36m" . $message . "\033[0m";
273
            } else {
274
                echo " \n> \033[33m" . $message . "\033[0m";
275
            }
276
        }
277
    }
278
279
    public function display()
280
    {
281
        $this->display = true;
282
    }
283
284
    public function hide()
285
    {
286
        $this->display = false;
287
    }
288
289
    protected function isPostgresSystemQuery(string $query): bool
290
    {
291
        $query = strtolower($query);
292
        if (
293
            strpos($query, 'tc.constraint_name')
294
            || strpos($query, 'pg_indexes')
295
            || strpos($query, 'tc.constraint_name')
296
            || strpos($query, 'pg_constraint')
297
            || strpos($query, 'information_schema')
298
            || strpos($query, 'pg_class')
299
        ) {
300
            return true;
301
        }
302
303
        return false;
304
    }
305
}