PluginProbe
Elementor Website Builder – more than just a page builder / 3.13.1
Elementor Website Builder – more than just a page builder v3.13.1
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / core / logger / manager.php

manager.php in Elementor Website Builder – more than just a page builder 3.13.1, at core/logger/manager.php

277 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Core\Logger;
3
4 use Elementor\Core\Base\Module as BaseModule;
5 use Elementor\Core\Common\Modules\Ajax\Module;
6 use Elementor\Core\Logger\Loggers\Logger_Interface;
7 use Elementor\Core\Logger\Items\PHP;
8 use Elementor\Core\Logger\Items\JS;
9 use Elementor\Plugin;
10 use Elementor\Modules\System_Info\Module as System_Info;
11 use Elementor\Utils;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit; // Exit if accessed directly
15 }
16
17 class Manager extends BaseModule {
18
19 protected $loggers = [];
20
21 protected $default_logger = '';
22
23 public function get_name() {
24 return 'log';
25 }
26
27 public function shutdown( $last_error = null, $should_exit = false ) {
28 if ( ! $last_error ) {
29 $last_error = error_get_last();
30 }
31
32 if ( ! $last_error ) {
33 return;
34 }
35
36 if ( empty( $last_error['file'] ) ) {
37 return;
38 }
39
40 if ( ! Utils::is_elementor_path( $last_error['file'] ) ) {
41 return;
42 }
43
44 $last_error['type'] = $this->get_log_type_from_php_error( $last_error['type'] );
45 $last_error['trace'] = true;
46
47 $item = new PHP( $last_error );
48
49 $this->get_logger()->log( $item );
50
51 if ( $should_exit ) {
52 exit;
53 }
54 }
55
56 public function rest_error_handler( $error_number, $error_message, $error_file, $error_line ) {
57 // Temporary solution until all PHP notices will be fixed in the core and pro.
58 if ( Utils::is_wp_cli() ) {
59 return null;
60 }
61
62 $error = new \WP_Error( $error_number, $error_message, [
63 'type' => $error_number,
64 'message' => $error_message,
65 'file' => $error_file,
66 'line' => $error_line,
67 ] );
68
69 if ( ! Utils::is_elementor_path( $error_file ) ) {
70 // Do execute PHP internal error handler.
71 return false;
72 }
73
74 $is_an_error = in_array( // It can be notice or warning
75 $error_number,
76 [ E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR ],
77 true
78 );
79
80 $error_data = $error->get_error_data();
81
82 // TODO: This part should be modular, temporary hard-coded.
83 // Notify $e.data.
84 if ( $is_an_error && ! headers_sent() ) {
85 header( 'Content-Type: application/json; charset=UTF-8' );
86
87 http_response_code( 500 );
88
89 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
90 echo wp_json_encode( $error_data );
91 } else {
92 echo wp_json_encode( [
93 'message' => 'Server error, see Elementor => System Info',
94 ] );
95 }
96 }
97
98 $this->shutdown( $error_data, $is_an_error );
99 }
100
101 public function register_error_handler() {
102 set_error_handler( [ $this, 'rest_error_handler' ], E_ALL );
103 }
104
105 public function add_system_info_report() {
106 System_Info::add_report(
107 'log', [
108 'file_name' => __DIR__ . '/log-reporter.php',
109 'class_name' => __NAMESPACE__ . '\Log_Reporter',
110 ]
111 );
112 }
113
114 /**
115 * Javascript log.
116 *
117 * Log Elementor errors and save them in the database.
118 *
119 * Fired by `wp_ajax_elementor_js_log` action.
120 *
121 */
122 public function js_log() {
123 /** @var Module $ajax */
124 $ajax = Plugin::$instance->common->get_component( 'ajax' );
125
126 // PHPCS ignore is added throughout this method because nonce verification happens in the $ajax->verify_request_nonce() method.
127 if ( ! $ajax->verify_request_nonce() || empty( $_POST['data'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
128 wp_send_json_error();
129 }
130
131 // PHPCS - See comment above.
132 $data = Utils::get_super_global_value( $_POST, 'data' ) ?? []; // phpcs:ignore WordPress.Security.NonceVerification.Missing
133
134 array_walk_recursive( $data, function( &$value ) {
135 $value = sanitize_text_field( $value );
136 } );
137
138 // PHPCS - See comment above.
139 foreach ( $data as $error ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
140 $error['type'] = Logger_Interface::LEVEL_ERROR;
141
142 if ( ! empty( $error['customFields'] ) ) {
143 $error['meta'] = $error['customFields'];
144 }
145
146 $item = new JS( $error );
147 $this->get_logger()->log( $item );
148 }
149
150 wp_send_json_success();
151 }
152
153 public function register_logger( $name, $class ) {
154 $this->loggers[ $name ] = $class;
155 }
156
157 public function set_default_logger( $name ) {
158 if ( ! empty( $this->loggers[ $name ] ) ) {
159 $this->default_logger = $name;
160 }
161 }
162
163 public function register_default_loggers() {
164 $this->register_logger( 'db', 'Elementor\Core\Logger\Loggers\Db' );
165 $this->set_default_logger( 'db' );
166 }
167
168 /**
169 * @param string $name
170 *
171 * @return Logger_Interface
172 */
173 public function get_logger( $name = '' ) {
174 $this->register_loggers();
175
176 if ( empty( $name ) || ! isset( $this->loggers[ $name ] ) ) {
177 $name = $this->default_logger;
178 }
179
180 if ( ! $this->get_component( $name ) ) {
181 $this->add_component( $name, new $this->loggers[ $name ]() );
182 }
183
184 return $this->get_component( $name );
185 }
186
187 /**
188 * @param string $message
189 * @param array $args
190 *
191 * @return void
192 */
193 public function log( $message, $args = [] ) {
194 $this->get_logger()->log( $message, $args );
195 }
196
197 /**
198 * @param string $message
199 * @param array $args
200 *
201 * @return void
202 */
203 public function info( $message, $args = [] ) {
204 $this->get_logger()->info( $message, $args );
205 }
206
207 /**
208 * @param string $message
209 * @param array $args
210 *
211 * @return void
212 */
213 public function notice( $message, $args = [] ) {
214 $this->get_logger()->notice( $message, $args );
215 }
216
217 /**
218 * @param string $message
219 * @param array $args
220 *
221 * @return void
222 */
223 public function warning( $message, $args = [] ) {
224 $this->get_logger()->warning( $message, $args );
225 }
226
227 /**
228 * @param string $message
229 * @param array $args
230 *
231 * @return void
232 */
233 public function error( $message, $args = [] ) {
234 $this->get_logger()->error( $message, $args );
235 }
236
237 private function get_log_type_from_php_error( $type ) {
238 $error_map = [
239 E_CORE_ERROR => Logger_Interface::LEVEL_ERROR,
240 E_ERROR => Logger_Interface::LEVEL_ERROR,
241 E_USER_ERROR => Logger_Interface::LEVEL_ERROR,
242 E_COMPILE_ERROR => Logger_Interface::LEVEL_ERROR,
243 E_RECOVERABLE_ERROR => Logger_Interface::LEVEL_ERROR,
244 E_PARSE => Logger_Interface::LEVEL_ERROR,
245 E_STRICT => Logger_Interface::LEVEL_ERROR,
246
247 E_WARNING => Logger_Interface::LEVEL_WARNING,
248 E_USER_WARNING => Logger_Interface::LEVEL_WARNING,
249 E_CORE_WARNING => Logger_Interface::LEVEL_WARNING,
250 E_COMPILE_WARNING => Logger_Interface::LEVEL_WARNING,
251
252 E_NOTICE => Logger_Interface::LEVEL_NOTICE,
253 E_USER_NOTICE => Logger_Interface::LEVEL_NOTICE,
254 E_DEPRECATED => Logger_Interface::LEVEL_NOTICE,
255 E_USER_DEPRECATED => Logger_Interface::LEVEL_NOTICE,
256 ];
257
258 return isset( $error_map[ $type ] ) ? $error_map[ $type ] : Logger_Interface::LEVEL_ERROR;
259 }
260
261 private function register_loggers() {
262 if ( ! did_action( 'elementor/loggers/register' ) ) {
263 do_action( 'elementor/loggers/register', $this );
264 }
265 }
266
267 public function __construct() {
268 register_shutdown_function( [ $this, 'shutdown' ] );
269
270 add_action( 'admin_init', [ $this, 'add_system_info_report' ], 80 );
271
272 add_action( 'wp_ajax_elementor_js_log', [ $this, 'js_log' ] );
273
274 add_action( 'elementor/loggers/register', [ $this, 'register_default_loggers' ] );
275 }
276 }
277