PluginProbe ʕ •ᴥ•ʔ
Disable Admin Notices – Hide Dashboard Notifications / trunk
Disable Admin Notices – Hide Dashboard Notifications vtrunk
1.4.5 trunk 1.0.0 1.0.2 1.0.3 1.0.5 1.0.6 1.1.1 1.1.3 1.1.4 1.2.0 1.2.2 1.2.3 1.2.4 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4
disable-admin-notices / libs / factory / logger / includes / class-log-export.php
disable-admin-notices / libs / factory / logger / includes Last commit date
class-log-export.php 1 year ago class-logger.php 1 year ago
class-log-export.php
259 lines
1 <?php
2
3 namespace WBCR\Factory_Logger_149;
4
5 /**
6 * Prepares export files, ZIPs them and allows to download the package.
7 *
8 * Usage example:
9 *
10 * ```php
11 * $export_model = new Log_Export('package.zip');
12 * $prepared = $export_model->prepare();
13 *
14 * if($prepared) {
15 * // start streaming ZIP archive to be downloaded
16 * $export_model->download();
17 * }
18 * ```
19 */
20 class Log_Export {
21
22 /**
23 * @var Logger Logger class
24 */
25 private $logger;
26
27 /**
28 * @var string Default archive name on download. {datetime} will be replaced with current m-d-Y.
29 */
30 private $_archive_name = 'plugin_log_export-{datetime}.zip';
31
32 /**
33 * @var string|null Archive save path.
34 */
35 private $_archive_save_path;
36
37 /**
38 * Log_Export constructor.
39 *
40 * @param Logger $logger
41 * @param null|string $archive_name
42 */
43 public function __construct( $logger, $archive_name = null ) {
44 $this->logger = $logger;
45 if ( $archive_name !== null ) {
46 $this->_archive_name = $archive_name;
47 }
48 }
49
50 /**
51 * Prepare export.
52 *
53 * @return bool
54 */
55 public function prepare() {
56
57 if ( ! class_exists( '\ZipArchive' ) ) {
58 $this->logger->error( 'App does not have \ZipArchive class available. It is not possible to prepare export' );
59
60 return false;
61 }
62
63 $zip = new \ZipArchive();
64
65 $log_base_dir = $this->logger->get_base_dir();
66
67 if ( $log_base_dir === false ) {
68 $this->logger->error( sprintf( 'Failed to get log path %s', $log_base_dir ) );
69
70 return false;
71 }
72
73 $uploads = wp_get_upload_dir();
74
75 if ( isset( $uploads['error'] ) && $uploads['error'] !== false ) {
76 $this->logger->error( 'Unable to get save path of ZIP archive from wp_get_upload_dir()' );
77
78 return false;
79 }
80
81 $save_base_path = isset( $uploads['basedir'] ) ? $uploads['basedir'] : null;
82 $zip_archive_name = 'wplugin_export.zip';
83 $zip_save_path = $save_base_path . DIRECTORY_SEPARATOR . $zip_archive_name;
84
85
86 if ( ! $zip->open( $zip_save_path, \ZipArchive::CREATE ) ) {
87 $this->logger->error( sprintf( 'Failed to created ZIP archive in path %s. Skipping export...', $zip_save_path ) );
88
89 return false;
90 }
91
92 // Add all logs to ZIP archive
93 $glob_path = $log_base_dir . '*.log';
94 $log_files = glob( $glob_path );
95
96 if ( ! empty( $log_files ) ) {
97 foreach ( $log_files as $file ) {
98 if ( ! $zip->addFile( $file, wp_basename( $file ) ) ) {
99 $this->logger->error( sprintf( 'Failed to add %s to %s archive. Skipping it.', $file, $zip_save_path ) );
100
101 return false;
102 }
103 }
104 }
105
106 $system_info = $this->prepare_system_info();
107
108 if ( ! empty( $system_info ) ) {
109 $system_info_file_name = 'system-info.txt';
110 $system_info_path = $save_base_path . DIRECTORY_SEPARATOR . $system_info_file_name;
111 if ( false !== @file_put_contents( $system_info_path, $system_info ) ) {
112 if ( ! $zip->addFile( $system_info_path, $system_info_file_name ) ) {
113 $this->logger->error( sprintf( 'Failed to add %s to %s archive. Skipping it.', $system_info_file_name, $system_info_path ) );
114 }
115 } else {
116 $this->logger->error( sprintf( 'Failed to save %s in %s', $system_info_file_name, $zip_save_path ) );
117 }
118 }
119
120 if ( ! $zip->close() ) {
121 $this->logger->error( sprintf( 'Failed to close ZIP archive %s for unknown reason. ZipArchive::close() failed.' ) );
122 }
123
124 if ( isset( $system_info_path ) ) {
125 // Clean-up as this is just temp file
126 @unlink( $system_info_path );
127 }
128
129 $this->_archive_save_path = $zip_save_path;
130
131 return true;
132 }
133
134 /**
135 * Prepare generic system information, such as WordPress, PHP version, active plugins, loaded extenstions, etc.
136 *
137 * @return string
138 */
139 public function prepare_system_info() {
140
141 $space = PHP_EOL . PHP_EOL;
142 $nl = PHP_EOL;
143
144 $report = 'Plugin version: ' . $this->logger->plugin->getPluginVersion() . $nl;
145
146 global $wp_version;
147
148 $report .= 'WordPress Version: ' . $wp_version . $nl;
149 $report .= 'PHP Version: ' . PHP_VERSION . $nl;
150 $report .= 'Locale: ' . get_locale() . $nl;
151 $report .= 'HTTP Accept: ' . ( isset( $_SERVER['HTTP_ACCEPT'] ) ? $_SERVER['HTTP_ACCEPT'] : '*empty*' ) . $nl;
152 $report .= 'HTTP User Agent: ' . ( isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '*empty*' ) . $nl;
153 $report .= 'Server software: ' . ( isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '*empty*' ) . $nl;
154
155 $report .= $space;
156
157 $active_plugins = get_option( 'active_plugins', null );
158
159 if ( $active_plugins !== null ) {
160
161 $prepared_plugins = [];
162
163 $all_plugins = get_plugins();
164
165 foreach ( $active_plugins as $active_plugin ) {
166 if ( isset( $all_plugins[ $active_plugin ] ) ) {
167 $advanced_info = $all_plugins[ $active_plugin ];
168 $name = isset( $advanced_info['Name'] ) ? $advanced_info['Name'] : '';
169 $version = isset( $advanced_info['Version'] ) ? $advanced_info['Version'] : '';
170 $prepared_plugins[] = sprintf( "%s (%s)", $name, $version );
171 }
172 }
173
174 $report .= 'Active plugins:' . PHP_EOL;
175 $report .= implode( PHP_EOL, $prepared_plugins );
176 }
177
178 if ( function_exists( 'get_loaded_extensions' ) ) {
179
180 $report .= PHP_EOL . PHP_EOL;
181 $report .= 'Active extensions: ' . $nl;
182 $report .= implode( ', ', get_loaded_extensions() );
183 }
184
185 $report .= $space;
186
187 $report .= 'Generated at: ' . date( 'c' );
188
189 return $report;
190 }
191
192 /**
193 * Download saved ZIP archive.
194 *
195 * It sets download headers, which streams content of the ZIP archive.
196 *
197 * Additionally it cleans-up by deleting the archive if `$and_delete` set to true.
198 *
199 * @param bool $should_clean_up Allows to delete temp ZIP archive if required.
200 *
201 * @return bool
202 */
203 public function download( $should_clean_up = true ) {
204
205 $zip_save_path = $this->_archive_save_path;
206
207 if ( empty( $zip_save_path ) ) {
208 return false;
209 }
210
211 $zip_content = @file_get_contents( $zip_save_path );
212
213 if ( $zip_save_path === false ) {
214 $this->logger->error( sprintf( 'Failed to get ZIP %s content as file_get_contents() returned false', $zip_save_path ) );
215
216 return false;
217 }
218
219 if ( $should_clean_up ) {
220 // Delete as ZIP is just for temporary usage
221 @unlink( $zip_save_path );
222 }
223
224 $archive_name = str_replace( '{datetime}', date( 'c' ), $this->_archive_name );
225
226 // Set-up headers to download export file
227 header( 'Content-Description: File Transfer' );
228 header( 'Content-Type: application/zip' );
229 header( 'Content-Disposition: attachment; filename=' . $archive_name );
230 header( 'Content-Transfer-Encoding: binary' );
231 header( 'Connection: Keep-Alive' );
232 header( 'Expires: 0' );
233 header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
234 header( 'Pragma: public' );
235 header( 'Content-Length: ' . strlen( $zip_content ) );
236
237 echo $zip_content;
238 exit();
239 }
240
241 /**
242 * Get temporary stored archive path.
243 *
244 * @return string
245 */
246 public function get_temp_archive_path() {
247 return $this->_archive_save_path;
248 }
249
250 /**
251 * Delete temporary stored archive path.
252 *
253 * @return bool
254 */
255 public function delete_temp_archive() {
256 return @unlink( $this->get_temp_archive_path() );
257 }
258 }
259