PluginProbe ʕ •ᴥ•ʔ
Robin Image Optimizer – Unlimited Image Optimization, WebP & AVIF / trunk
Robin Image Optimizer – Unlimited Image Optimization, WebP & AVIF vtrunk
2.0.5 trunk 1.3.7 1.4.0 1.4.1 1.4.2 1.4.6 1.5.0 1.5.3 1.5.6 1.5.8 1.6.5 1.6.6 1.6.9 1.7.0 1.7.4 1.8.1 1.8.2 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4
robin-image-optimizer / libs / factory / logger / includes / class-log-export.php
robin-image-optimizer / libs / factory / logger / includes Last commit date
class-log-export.php 5 months ago class-logger.php 5 months ago
class-log-export.php
258 lines
1 <?php
2
3 namespace WBCR\Factory_Logger_359;
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 if ( ! $zip->open( $zip_save_path, \ZipArchive::CREATE ) ) {
86 $this->logger->error( sprintf( 'Failed to created ZIP archive in path %s. Skipping export...', $zip_save_path ) );
87
88 return false;
89 }
90
91 // Add all logs to ZIP archive
92 $glob_path = $log_base_dir . '*.log';
93 $log_files = glob( $glob_path );
94
95 if ( ! empty( $log_files ) ) {
96 foreach ( $log_files as $file ) {
97 if ( ! $zip->addFile( $file, wp_basename( $file ) ) ) {
98 $this->logger->error( sprintf( 'Failed to add %s to %s archive. Skipping it.', $file, $zip_save_path ) );
99
100 return false;
101 }
102 }
103 }
104
105 $system_info = $this->prepare_system_info();
106
107 if ( ! empty( $system_info ) ) {
108 $system_info_file_name = 'system-info.txt';
109 $system_info_path = $save_base_path . DIRECTORY_SEPARATOR . $system_info_file_name;
110 if ( false !== @file_put_contents( $system_info_path, $system_info ) ) {
111 if ( ! $zip->addFile( $system_info_path, $system_info_file_name ) ) {
112 $this->logger->error( sprintf( 'Failed to add %s to %s archive. Skipping it.', $system_info_file_name, $system_info_path ) );
113 }
114 } else {
115 $this->logger->error( sprintf( 'Failed to save %s in %s', $system_info_file_name, $zip_save_path ) );
116 }
117 }
118
119 if ( ! $zip->close() ) {
120 $this->logger->error( sprintf( 'Failed to close ZIP archive %s for unknown reason. ZipArchive::close() failed.' ) );
121 }
122
123 if ( isset( $system_info_path ) ) {
124 // Clean-up as this is just temp file
125 @unlink( $system_info_path );
126 }
127
128 $this->_archive_save_path = $zip_save_path;
129
130 return true;
131 }
132
133 /**
134 * Prepare generic system information, such as WordPress, PHP version, active plugins, loaded extenstions, etc.
135 *
136 * @return string
137 */
138 public function prepare_system_info() {
139
140 $space = PHP_EOL . PHP_EOL;
141 $nl = PHP_EOL;
142
143 $report = 'Plugin version: ' . $this->logger->plugin->getPluginVersion() . $nl;
144
145 global $wp_version;
146
147 $report .= 'WordPress Version: ' . $wp_version . $nl;
148 $report .= 'PHP Version: ' . PHP_VERSION . $nl;
149 $report .= 'Locale: ' . get_locale() . $nl;
150 $report .= 'HTTP Accept: ' . ( isset( $_SERVER['HTTP_ACCEPT'] ) ? $_SERVER['HTTP_ACCEPT'] : '*empty*' ) . $nl;
151 $report .= 'HTTP User Agent: ' . ( isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '*empty*' ) . $nl;
152 $report .= 'Server software: ' . ( isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '*empty*' ) . $nl;
153
154 $report .= $space;
155
156 $active_plugins = get_option( 'active_plugins', null );
157
158 if ( $active_plugins !== null ) {
159
160 $prepared_plugins = [];
161
162 $all_plugins = get_plugins();
163
164 foreach ( $active_plugins as $active_plugin ) {
165 if ( isset( $all_plugins[ $active_plugin ] ) ) {
166 $advanced_info = $all_plugins[ $active_plugin ];
167 $name = isset( $advanced_info['Name'] ) ? $advanced_info['Name'] : '';
168 $version = isset( $advanced_info['Version'] ) ? $advanced_info['Version'] : '';
169 $prepared_plugins[] = sprintf( '%s (%s)', $name, $version );
170 }
171 }
172
173 $report .= 'Active plugins:' . PHP_EOL;
174 $report .= implode( PHP_EOL, $prepared_plugins );
175 }
176
177 if ( function_exists( 'get_loaded_extensions' ) ) {
178
179 $report .= PHP_EOL . PHP_EOL;
180 $report .= 'Active extensions: ' . $nl;
181 $report .= implode( ', ', get_loaded_extensions() );
182 }
183
184 $report .= $space;
185
186 $report .= 'Generated at: ' . date( 'c' );
187
188 return $report;
189 }
190
191 /**
192 * Download saved ZIP archive.
193 *
194 * It sets download headers, which streams content of the ZIP archive.
195 *
196 * Additionally it cleans-up by deleting the archive if `$and_delete` set to true.
197 *
198 * @param bool $should_clean_up Allows to delete temp ZIP archive if required.
199 *
200 * @return bool
201 */
202 public function download( $should_clean_up = true ) {
203
204 $zip_save_path = $this->_archive_save_path;
205
206 if ( empty( $zip_save_path ) ) {
207 return false;
208 }
209
210 $zip_content = @file_get_contents( $zip_save_path );
211
212 if ( $zip_save_path === false ) {
213 $this->logger->error( sprintf( 'Failed to get ZIP %s content as file_get_contents() returned false', $zip_save_path ) );
214
215 return false;
216 }
217
218 if ( $should_clean_up ) {
219 // Delete as ZIP is just for temporary usage
220 @unlink( $zip_save_path );
221 }
222
223 $archive_name = str_replace( '{datetime}', date( 'c' ), $this->_archive_name );
224
225 // Set-up headers to download export file
226 header( 'Content-Description: File Transfer' );
227 header( 'Content-Type: application/zip' );
228 header( 'Content-Disposition: attachment; filename=' . $archive_name );
229 header( 'Content-Transfer-Encoding: binary' );
230 header( 'Connection: Keep-Alive' );
231 header( 'Expires: 0' );
232 header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
233 header( 'Pragma: public' );
234 header( 'Content-Length: ' . strlen( $zip_content ) );
235
236 echo $zip_content;
237 exit();
238 }
239
240 /**
241 * Get temporary stored archive path.
242 *
243 * @return string
244 */
245 public function get_temp_archive_path() {
246 return $this->_archive_save_path;
247 }
248
249 /**
250 * Delete temporary stored archive path.
251 *
252 * @return bool
253 */
254 public function delete_temp_archive() {
255 return @unlink( $this->get_temp_archive_path() );
256 }
257 }
258