/var/www/html_fr/wp-content/plugins/loco-translate/src/error/AdminNotices.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
<?php

class Loco_error_AdminNotices extends Loco_hooks_Hookable {
    
    
/**
     * @var Loco_error_AdminNotices
     */
    
private static $singleton;

    
/**
     * @var Loco_error_Exception[]
     */
    
private $errors = [];

    
/**
     * Inline messages are handled by our own template views
     * @var bool
     */
    
private $inline false;


    
/**
     * @return Loco_error_AdminNotices
     */
    
public static function get(){
        
self::$singleton or self::$singleton = new Loco_error_AdminNotices;
        return 
self::$singleton;
    }


    
/**
     * Enable temporary buffering of PHP errors, reducing error reporting to debug level.
     * Call restore_error_handler to stop capturing.
     * @param int $level PHP error level bit mask, e.g. E_WARNING
     * @return void
     */
    
public static function capture$level ){
        
set_error_handler( [__CLASS__,'handle_error'], $level );
    }


    
/**
     * @internal
     * @param int $errno
     * @param string $errstr
     */
    
public static function handle_error$errno$errstr /*$errfile, $errline*/ ){
        if( 
$errno & (E_ERROR|E_USER_ERROR) ){
            return 
false;
        }
        
$label $errno & (E_WARNING|E_USER_WARNING) ? 'Warning' 'Notice';
        
self::debug'[PHP '.$label.'] '.$errstr );
        return 
true;
    }


    
/**
     * @param Loco_error_Exception $error
     * @return Loco_error_Exception
     */
    
public static function addLoco_error_Exception $error ){
        
$notices self::get();
        
// Skip repeated error messages in same stack
        
foreach( $notices->errors as $previous ){
            if( 
$error->isIdentical($previous) ){
                return 
$previous;
            }
        }
        
// if exception wasn't thrown we have to do some work to establish where it was invoked
        
if( __FILE__ === $error->getRealFile() ){
            
$error->setCallee(1);
        }
        
// write error immediately under WP_CLI
        
if( 'cli' === PHP_SAPI && class_exists('WP_CLI',false) ){
            
$error->logCli();
            return 
$error;
        }
        
// else buffer notices for displaying when UI is ready
        
$notices->errors[] = $error;
        
// do late flush if we missed the boat
        
if( did_action('loco_admin_init') ){
            
$notices->on_loco_admin_init();
        }
        if( 
did_action('admin_notices') ){
            
$notices->on_admin_notices();
        }
        
// Log message automatically if enabled
        
if( $error->loggable() ){
            
$error->log();
        }
        return 
$error;
    }


    
/**
     * Raise a success message
     * @param string $message
     * @return Loco_error_Exception
     */
    
public static function success$message ){
        
$notice = new Loco_error_Success($message);
        return 
self::add$notice->setCallee(1) );
    }


    
/**
     * Raise a failure message
     * @param string $message
     * @return Loco_error_Exception
     */
    
public static function err$message ){
        
$notice = new Loco_error_Exception($message);
        return 
self::add$notice->setCallee(1) );
    }


    
/**
     * Raise a warning message
     * @param string $message
     * @return Loco_error_Exception
     */
    
public static function warn$message ){
        
$notice = new Loco_error_Warning($message);
        return 
self::add$notice->setCallee(1) );
    }


    
/**
     * Raise a generic info message
     * @param string $message
     * @return Loco_error_Exception
     */
    
public static function info$message ){
        
$notice = new Loco_error_Notice($message);
        return 
self::add$notice->setCallee(1) );
    }


    
/**
     * Raise a debug notice, if debug is enabled
     * @param string $message
     * @return Loco_error_Debug
     */
    
public static function debug$message ){
        
$notice = new Loco_error_Debug($message);
        
$notice->setCallee(1);
        
loco_debugging() and self::add$notice );
        return 
$notice;
    }


    
/**
     * Destroy and return buffer
     * @return Loco_error_Exception[]
     */
    
public static function destroy(){
        
$notices self::$singleton;
        if( 
$notices instanceof Loco_error_AdminNotices ){
            
$buffer $notices->errors;
            
$notices->errors = [];
            
self::$singleton null;
            return 
$buffer;
        }
        return [];
    }


    
/**
     * @codeCoverageIgnore 
     * @deprecated Since PHP 5.4 there is no need to cast array via calls to jsonSerialize
     */
    
public static function destroyAjax(){
        
$data = [];
        foreach( 
self::destroy() as $notice ){
            
$data[] = $notice->jsonSerialize();
        }
        return 
$data;
    }

    
    
/**
     * @return void
     */
    
private function flushHtml(){
        if( 
$this->errors ){
            
$htmls = [];
            foreach( 
$this->errors as $error ){
                
$html sprintf (
                    
'<p><strong class="has-icon">%s:</strong> <span>%s</span></p>',
                    
esc_html$error->getTitle() ),
                    
esc_html$error->getMessage() )
                );
                
$styles = [ 'notice''notice-'.$error->getType() ];
                if( 
$this->inline ){
                    
$styles[] = 'inline';
                }
                if( 
$links $error->getLinks() ){
                    
$styles[] = 'has-nav';
                    
$html .= '<nav>'.implode'<span> | </span>'$links ).'</nav>';
                }
                
$htmls[] = '<div class="'.implode(' ',$styles).'">'.$html.'</div>';
            }
            
$this->errors = [];
            echo 
implode("\n"$htmls),"\n";
        }
    }

    
/**
     * @return void
     */
    
private function flushCli(){
        foreach( 
$this->errors as $e ){
            
$e->logCli();
        }
        
$this->errors = [];
    }


    
/**
     * admin_notices action handler.
     */
    
public function on_admin_notices(){
        if( ! 
$this->inline ){
            
$this->flushHtml();
        }
    }


    
/**
     * loco_admin_notices callback.
     * Unlike WordPress "admin_notices" this fires from within template layout at the point we want them, hence they are marked as "inline"
     */
    
public function on_loco_admin_notices(){
        
$this->inline true;
        
$this->flushHtml();
    }


    
/**
     * loco_admin_init callback
     * When we know a Loco admin controller will render the page we will control the point at which notices are printed
     */
    
public function on_loco_admin_init(){
        
$this->inline true;
    }


    
/**
     * @internal
     * Make sure we always see notices if hooks didn't fire
     */
    
public function __destruct(){
        
$this->inline false;
        
$this->flush();
        
// handle situation where test case will have lost the buffer
        
if( $this->errors && 'cli' === PHP_SAPI ){
            throw new 
RuntimeException('Notices not flushed before destruction');
        }
    }


    
/**
     * @param int $level
     * @return Loco_error_Exception[]
     */
    
public function filter$level ){
        
$e = [];
        foreach( 
$this->errors as $error ){
            if( 
$error->getLevel() <= $level ){
                
$e[] = $error;
            }
        }
        return 
$e;
    }


    
/**
     * @internal
     */
    
public function flush(){
        if( 
class_exists('WP_CLI',false) ){
            
$this->flushCli();
        }
        else if( 
loco_doing_ajax() ){
            
$this->errors = [];
        }
        else if( 
'cli' !== PHP_SAPI ){
            
$this->flushHtml();
        }
        
// else probably in unit test and not properly handled, leave significant errors in buffer
        
else {
            
$this->errors $this->filterLoco_error_Exception::LEVEL_WARNING );
        }
        return 
$this;
    }

}