PluginProbe
Elementor Website Builder – more than just a page builder / 4.1.5
Elementor Website Builder – more than just a page builder v4.1.5
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 4.1.5, at core/logger/manager.php

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