1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Framework\Setup\Declaration\Schema;
use Magento\Framework\App\Filesystem\DirectoryList;
/**
* This class is responsible for logging dry run SQL`s
* By default it logs them into filesystem, but it can be extended and you can log them in CLI
* Current problem with logging output to CLI, is that we have redudant things in CLI output, like modules progress
*/
class DryRunLogger
{
/**
* We will run installation or upgrade in Dry Run mode
*/
const INPUT_KEY_DRY_RUN_MODE = 'dry-run';
/**
* File name, where all dry-run SQL`s will be puted
*/
const FILE_NAME = 'dry-run-installation.log';
/**
* Allows to separate 2 different sql statements with this separator
* Be default is used 2 empty lines
*/
const LINE_SEPARATOR = "\n\n";
/**
* @var \Magento\Framework\Filesystem\Driver\File
*/
private $fileDriver;
/**
* @var DirectoryList
*/
private $directoryList;
/**
* @param \Magento\Framework\Filesystem\Driver\File $fileDriver
* @param DirectoryList $directoryList
*/
public function __construct(
\Magento\Framework\Filesystem\Driver\File $fileDriver,
DirectoryList $directoryList
) {
$this->fileDriver = $fileDriver;
$this->directoryList = $directoryList;
}
/**
* Create log directory if it doest not exists
*
* @param string $logFolderPath
* @throws \Exception
*/
private function assertLogFolderExists($logFolderPath)
{
if (!$this->fileDriver->isDirectory($logFolderPath)) {
$this->fileDriver->createDirectory($logFolderPath);
}
if (!$this->fileDriver->isDirectory($logFolderPath)) {
throw new \Exception(sprintf("Can`t create log directory: %s", $logFolderPath));
}
}
/**
* @param string $fileName
* @throws \Exception
*/
private function assertFileExists($fileName)
{
if (!$this->fileDriver->isExists($fileName)) {
$this->fileDriver->touch($fileName);
}
if (!$this->fileDriver->isExists($fileName)) {
throw new \Exception(sprintf("Can`t create file %s", $fileName));
}
}
/**
* Make file empty from request to request
* @throws \Exception
* @return void
*/
public function prepareToDryRun()
{
if ($this->fileDriver->isExists($this->getLoggerFile())) {
if (!$this->fileDriver->isWritable($this->getLoggerFile())) {
throw new \Exception(sprintf('Dry run logger file is not writable'));
}
$this->fileDriver->deleteFile($this->getLoggerFile());
$this->fileDriver->touch($this->getLoggerFile());
}
}
/**
* Return folder path, where dry run logged file will be placed
*
* @return string
*/
private function getLoggerFolder()
{
return $this->directoryList->getPath(DirectoryList::VAR_DIR) .
DIRECTORY_SEPARATOR . 'log';
}
/**
* Return dry run logger file
*
* @return string
*/
private function getLoggerFile()
{
return $this->getLoggerFolder() . DIRECTORY_SEPARATOR . self::FILE_NAME;
}
/**
* Do log of SQL query, 2 different SQL`s will be divided by one empty line
*
* @param string $sql
* @throws \Exception
* @return void
*/
public function log($sql)
{
$loggerFolder = $this->getLoggerFolder();
$loggerFile = $this->getLoggerFile();
$this->assertLogFolderExists($loggerFolder);
$this->assertFileExists($loggerFile);
if ($this->fileDriver->isWritable($loggerFile)) {
$fd = $this->fileDriver->fileOpen($loggerFile, 'a');
$this->fileDriver->fileWrite($fd, $sql . self::LINE_SEPARATOR);
} else {
throw new \Exception(sprintf('Can`t write to file %s', $loggerFile));
}
}
}