PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 3.1.3
WP STAGING – WordPress Backup, Restore, Migration & Clone v3.1.3
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 2 years ago Scanning 5 years ago DebugLogReader.php 2 years ago DirectoryListing.php 3 years ago DiskWriteCheck.php 3 years ago FileObject.php 2 years ago Filesystem.php 2 years ago FilesystemExceptions.php 5 years ago FilterableDirectoryIterator.php 3 years ago LogCleanup.php 2 years ago LogFiles.php 2 years ago MissingFileException.php 3 years ago PathChecker.php 2 years ago PathIdentifier.php 2 years ago Permissions.php 5 years ago WpUploadsFolderSymlinker.php 4 years ago
DebugLogReader.php
163 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 $errors = '';
88
89 if ($withWpstgDebugLog) {
90 if (defined('WPSTG_DEBUG_LOG_FILE')) {
91 if ($this->filesystem->isReadableFile(WPSTG_DEBUG_LOG_FILE)) {
92 $errors .= sprintf(
93 "--- WP STAGING Debug Logs\nFile: %s\nTotal file size: %s\nShowing last: %s\n\n=== START ===\n\n",
94 WPSTG_DEBUG_LOG_FILE,
95 size_format(filesize(WPSTG_DEBUG_LOG_FILE)),
96 size_format($maxSizeEach)
97 );
98 $errors .= $this->getDebugLogLines(WPSTG_DEBUG_LOG_FILE, $maxSizeEach);
99 $errors .= "=== END ===\n\n";
100 } else {
101 $errors .= "\n=== File WPSTG_DEBUG_LOG_FILE is not readable or does not exist ===\n";
102 }
103 } else {
104 $errors .= "\n=== WPSTG_DEBUG_LOG_FILE NOT DEFINED ===\n";
105 }
106 }
107
108 if ($withPhpDebugLog) {
109 /** @see \wp_debug_mode to understand why it uses ini_get() */
110 $phpDebugLogFile = ini_get('error_log');
111
112 if ($this->filesystem->isReadableFile($phpDebugLogFile)) {
113 $errors .= sprintf(
114 "--- PHP debug.log \nFile: %s\nTotal file size: %s\nShowing last: %s\n\n=== START ===\n\n",
115 $phpDebugLogFile,
116 size_format(filesize($phpDebugLogFile)),
117 size_format($maxSizeEach)
118 );
119 $errors .= $this->getDebugLogLines($phpDebugLogFile, $maxSizeEach);
120 $errors .= "=== END ===\n\n";
121 } else {
122 $errors .= "\n=== PHP DEBUG LOG FILE IS NOT A FILE OR IS NOT READABLE ===\n";
123 }
124 }
125
126 return $errors;
127 }
128
129 /**
130 * @param $debugLogPath
131 * @param $maxSize
132 * @return string
133 */
134 protected function getDebugLogLines($debugLogPath, $maxSize): string
135 {
136 if (!is_file($debugLogPath) || !is_readable($debugLogPath)) {
137 return '';
138 }
139
140 try {
141 $debugFile = new FileObject($debugLogPath, 'r');
142
143 $negativeOffset = $maxSize;
144
145 // Set the pointer to the end of the file, minus the negative offset for which to start looking for errors.
146 $debugFile->fseek(max($debugFile->getSize() - $negativeOffset, 0), SEEK_SET);
147
148 $debugLines = [];
149
150 do {
151 $line = trim($debugFile->readAndMoveNext());
152 $line = html_entity_decode($line);
153 $line = sanitize_text_field($line);
154 $debugLines[] = $line;
155 } while ($debugFile->valid());
156
157 return implode("\n", $debugLines);
158 } catch (\Exception $e) {
159 return '';
160 }
161 }
162 }
163