PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 4.9.0
WP STAGING – WordPress Backup, Restore, Migration & Clone v4.9.0
4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Framework / Filesystem / DebugLogReader.php
wp-staging / Framework / Filesystem Last commit date
Filters 6 months ago Scanning 5 years ago AbstractFileObject.php 1 year ago AbstractFilesystemScanner.php 2 months ago DebugLogReader.php 2 years ago DirectoryListing.php 5 months ago DiskWriteCheck.php 5 months ago FileObject.php 1 year ago Filesystem.php 6 months ago FilesystemExceptions.php 5 years ago FilesystemScanner.php 1 week ago FilesystemScannerDto.php 1 week ago FilterableDirectoryIterator.php 1 year ago LegacyFileRulesTrait.php 1 week ago LogCleanup.php 5 months ago LogFiles.php 1 year ago MissingFileException.php 3 years ago OPcache.php 5 months ago PartIdentifier.php 8 months ago PathChecker.php 2 years ago PathIdentifier.php 6 months ago Permissions.php 5 months ago WpUploadsFolderSymlinker.php 1 week ago
DebugLogReader.php
193 lines
1 <?php
2
3 namespace WPStaging\Framework\Filesystem;
4
5 use WPStaging\Framework\Security\Capabilities;
6 use WPStaging\Framework\Adapter\Directory;
7
8 class DebugLogReader extends LogFiles
9 {
10 /**
11 * @var Filesystem
12 */
13 protected $filesystem;
14
15 /**
16 * @param Filesystem $filesystem
17 * @param Directory $logsDirectory
18 */
19 public function __construct(Filesystem $filesystem, Directory $logsDirectory)
20 {
21 parent::__construct($logsDirectory);
22 $this->filesystem = $filesystem;
23 }
24
25 /**
26 * Deletes a log file if requested.
27 * Used by WPStaging\Framework\CommonServiceProvider::registerClasses()
28 */
29 public function listenDeleteLogRequest()
30 {
31 if (!isset($_GET['deleteLog']) || !isset($_GET['deleteLogNonce'])) {
32 return;
33 }
34
35 if (!current_user_can((new Capabilities())->manageWPSTG()) || !wp_verify_nonce($_GET['deleteLogNonce'], 'wpstgDeleteLogNonce')) {
36 return;
37 }
38
39 if ($_GET['deleteLog'] === 'wpstaging') {
40 $this->deleteWpStagingDebugLogFile();
41 }
42
43 if ($_GET['deleteLog'] === 'php') {
44 $this->deletePhpDebugLogFile();
45 }
46
47 // Redirect to prevent refresh from deleting the log again
48 wp_redirect(admin_url() . 'admin.php?page=wpstg-tools&tab=system-info');
49 exit;
50 }
51
52 /**
53 * @return bool|null Whether the log file was deleted or not.
54 */
55 public function deletePhpDebugLogFile()
56 {
57 $phpDebugLogFile = ini_get('error_log');
58
59 if (file_exists($phpDebugLogFile) && is_writable($phpDebugLogFile)) {
60 return unlink($phpDebugLogFile);
61 }
62
63 return null;
64 }
65
66 /**
67 * @return bool|null
68 */
69 public function deleteWpStagingDebugLogFile()
70 {
71 if (file_exists(WPSTG_DEBUG_LOG_FILE) && is_writable(WPSTG_DEBUG_LOG_FILE)) {
72 return unlink(WPSTG_DEBUG_LOG_FILE);
73 }
74
75 return null;
76 }
77
78 /**
79 * @param int $maxSizeEach Max size in bytes to fetch from each log.
80 * @param bool $withWpstgDebugLog Whether to include WP STAGING custom log entries.
81 * @param bool $withPhpDebugLog Whether to include PHP error_log entries.
82 *
83 * @return string A formatted text with the last log entries from the debug log files.
84 */
85 public function getLastLogEntries(int $maxSizeEach, bool $withWpstgDebugLog = true, bool $withPhpDebugLog = true): string
86 {
87 $content = '';
88
89 if ($withWpstgDebugLog) {
90 if (defined('WPSTG_DEBUG_LOG_FILE')) {
91 $wpstgDebugLogFile = WPSTG_DEBUG_LOG_FILE;
92
93 if ($this->filesystem->isReadableFile($wpstgDebugLogFile)) {
94 $wpstgDebugLogFileSize = filesize($wpstgDebugLogFile);
95
96 $content .= sprintf(
97 "--- WP STAGING Debug Logs\nFile: %s\nTotal file size: %s\nShowing last: %s\n\n=== START ===\n\n",
98 $wpstgDebugLogFile,
99 size_format($wpstgDebugLogFileSize),
100 size_format($maxSizeEach)
101 );
102
103 if ($wpstgDebugLogFileSize > $maxSizeEach) {
104 $content .= $this->getDebugLogLines($wpstgDebugLogFile, $maxSizeEach);
105 } else {
106 $content .= file_get_contents($wpstgDebugLogFile);
107 }
108 $content .= "=== END ===\n\n";
109 } else {
110 $content .= "\n=== File WPSTG_DEBUG_LOG_FILE is not readable or does not exist ===\n";
111 }
112 } else {
113 $content .= "\n=== WPSTG_DEBUG_LOG_FILE NOT DEFINED ===\n";
114 }
115 }
116
117 if ($withPhpDebugLog) {
118 /** @see \wp_debug_mode to understand why it uses ini_get() */
119 $phpDebugLogFile = ini_get('error_log');
120
121 if ($this->filesystem->isReadableFile($phpDebugLogFile)) {
122 $phpDebugLogFileSize = filesize($phpDebugLogFile);
123
124 $content .= sprintf(
125 "--- PHP debug.log \nFile: %s\nTotal file size: %s\nShowing last: %s\n\n=== START ===\n\n",
126 $phpDebugLogFile,
127 size_format($phpDebugLogFileSize),
128 size_format($maxSizeEach)
129 );
130
131 if ($phpDebugLogFileSize > $maxSizeEach) {
132 $content .= $this->getDebugLogLines($phpDebugLogFile, $maxSizeEach);
133 } else {
134 $content .= file_get_contents($phpDebugLogFile);
135 }
136
137 $content .= "=== END ===\n\n";
138 } else {
139 $content .= "\n=== PHP DEBUG LOG FILE IS NOT A FILE OR IS NOT READABLE ===\n";
140 }
141 }
142
143 return $content;
144 }
145
146 /**
147 * @param $debugLogPath
148 * @param $maxSize
149 * @return string
150 */
151 protected function getDebugLogLines($debugLogPath, $maxSize): string
152 {
153 if (!is_file($debugLogPath) || !is_readable($debugLogPath)) {
154 return '';
155 }
156
157 try {
158 $debugFile = new FileObject($debugLogPath, 'r');
159
160 $negativeOffset = $maxSize;
161
162 // Set the pointer to the end of the file, minus the negative offset for which to start looking for errors.
163 $debugFile->fseek(max($debugFile->getSize() - $negativeOffset, 0), SEEK_SET);
164
165 $debugLines = [];
166
167 do {
168 $line = trim($debugFile->readAndMoveNext());
169 $line = html_entity_decode($line);
170 $line = sanitize_text_field($line);
171 $debugLines[] = $line;
172 } while ($debugFile->valid());
173
174 return implode("\n", $debugLines);
175 } catch (\Exception $e) {
176 return '';
177 }
178 }
179
180 /**
181 * @return string
182 */
183 public function maybeFixHtmlEntityDecode(string $content): string
184 {
185 if (empty($content)) {
186 return $content;
187 }
188
189 $content = esc_html(wp_strip_all_tags($content));
190 return str_replace(['&quot;', '&#039;', '&amp;'], ['"', "'", "&"], $content);
191 }
192 }
193