WordPress.org

Make WordPress Core

Ticket #42527: test.admin.menu.php

File test.admin.menu.php, 8.4 KB (added by darkskipper, 3 years ago)

Must-use plugin to demonstrate the issue.

Line 
1<?php
2/*****************************************************
3       File: test.admin.menu.php
4Plugin name: Test Admin Menus
5    Version: 0.0.1
6Description: Testing issues with administration menus.
7     Author: Kevin Machin.
8 Author URI: //darkskipper.com/
9*****************************************************/
10
11TestAdminMenu::init ();
12
13///////////////////////////////////////////
14// Class: TestAdminMenu
15//  Desc: For testing administration menus.
16///////////////////////////////////////////
17
18class TestAdminMenu
19{
20    // Plugin info
21    const   TAM_NAME = 'Test Administration Menus',
22            TAM_VERS = '0.0.1';
23
24    // Slugs/URIs for menus and items
25    const   M_SLUG = 'tam-menu',
26            I_SLUG = 'tam-info',
27            U_NANO = 'https://nanowrimo.org/';
28
29    private $aErrs; // List of detected errors
30
31    // Constructor
32    final private function __construct ()
33    {
34        // Restrict file access to everything from top directory down
35        $sDire = str_replace ('\\', '/', __FILE__);
36        $sDire = preg_replace ('#^(([A-Z]:|//[^/]+)?/).*$#i', '$1', $sDire); // Allow drive letter or share name
37        ini_set ('open_basedir', $sDire);
38
39        // Empty the errors array
40        $this->aErrs = [];
41    }
42    // End of constructor
43
44    ////////////////////////////////
45    // Meth: handErr
46    // Desc: Error handler.
47    // Retn: Boolean "handled" flag.
48    ////////////////////////////////
49
50    final public function handErr ($piCode, $psMess, $psFile, $piLine)
51    {
52        $aErr = // Store the details for later rendering
53        [
54            'code' => $piCode,
55            'mess' => $psMess,
56            'file' => $psFile,
57            'line' => $piLine
58        ];
59        $this->aErrs[] = $aErr;
60        return (FALSE); // Not handled, so we log the messages as well
61    }
62    // End of handErr
63
64    ////////////////////
65    // Meth: init
66    // Desc: Initialise.
67    ////////////////////
68
69    final public static function init ()
70    {
71        $sKind = __CLASS__;
72        $oMain = new $sKind ();
73        add_action ('admin_menu',   [$oMain, 'actMenu']);
74        add_action ('adminmenu',    [$oMain, 'actTidy']);
75        add_filter ('submenu_file', [$oMain, 'filtItem'], 10, 2);
76    }
77    // End of init
78
79    ///////////////////////////////////////
80    // Meth: actMenu
81    // Desc: Add some administration menus.
82    // Note: Called for 'admin_menu' hook.
83    ///////////////////////////////////////
84
85    final public function actMenu ()
86    {
87
88        $sMenu = self::M_SLUG;
89        $sItem = self::I_SLUG;
90        $sSite = self::U_NANO;
91        $sCapa = 'read';
92        $sHead = 'NaNoWriMo &ndash; Information';
93        $mShow = [$this, 'rend'];
94        add_menu_page    ($sHead, 'NaNoWriMo', $sCapa, $sMenu, $mShow);
95        add_submenu_page ($sMenu, $sHead, 'Info',    $sCapa, $sItem, $mShow);
96      //add_submenu_page ($sMenu, $sHead, 'Drive',   $sCapa, 'A:/floppy');
97        add_submenu_page ($sMenu, $sHead, 'Website', $sCapa, $sSite);
98        remove_submenu_page ($sMenu, $sMenu);
99    }
100    // End of actMenu
101
102    //////////////////////////////////////////////////////
103    // Meth: filtItem
104    // Desc: Filter sub-menu items.
105    // Retn: Filtered item.
106    // Mote: This is called before the menus are rendered,
107    //       giving us an opportunity to look for errors.
108    //       Called for 'submenu_file' hook.
109    //////////////////////////////////////////////////////
110
111    final public function filtItem ($psItem, $psMenu)
112    {
113        if ($psMenu === self::M_SLUG)
114        {
115            // Set error handler
116            set_error_handler ([$this, 'handErr']);
117            //error_reporting (~0);
118            trigger_error ('Test error, please ignore.');
119        }
120        return ($psItem);
121    }
122    // End of filtItem
123
124    /////////////////////////////////////////////////////////////////
125    // Meth: actTidy
126    // Desc: Tidy up after menu pages.
127    // Note: Called after menu rendering, through action 'adminmenu'.
128    /////////////////////////////////////////////////////////////////
129
130    final public function actTidy ()
131    {
132        restore_error_handler ();
133    }
134    // End of actTidy
135
136    ////////////////////////////
137    // Meth: rend
138    // Desc: Render information.
139    ////////////////////////////
140
141    final public function rend ()
142    {
143        // Page markup
144        $sForm = <<<_EOT
145<h1>
146 %s
147 <span style="font-weight:normal">&ndash; Version %s</span>
148</h1>
149<div class="tam">
150 <style type="text/css" scoped="scoped">
151 div.tam, div.tam p, div.tam code
152 {
153  font-size: large;
154 }
155 div.tam div.tac
156 {
157  text-align:    center;
158  background:    #E2EFF3;
159  margin:        0 1em;
160  border-radius: 1em;
161  padding:       1em;
162 }
163 div.tam div.tac *
164 {
165  color:      #674732;
166 }
167 div.tam table, div.tam th, div.tam td
168 {
169  border:          1px solid;
170  border-collapse: collapse;
171  padding:         4px;
172  text-align:      left;
173 }
174 div.tam td
175 {
176  vertical-align: top;
177 }
178 div.tam td.wrap
179 {
180  word-wrap: break-word;
181 }
182 </style>
183 <p>
184  Below is some sample text.
185  The real purpose of this plugin is to demonstrate
186  <a title="See below &darr;" href="#tam-errs">warning messages</a>
187  generated in the WordPress core administration menu routines.
188 </p>
189 <div class="tac">
190  <h2>
191   National Novel Writing Month
192  </h2>
193  <h3>
194   <em>NaNoWriMo</em>
195  </h3>
196  <p>
197   <a title="See the NaNoWriMo website&hellip;" href="%s">National Novel Writing Month</a> is a fun,
198   seat-of-your-pants approach to creative writing.
199  </p>
200  <p>
201   On November 1<sup>st</sup>, participants begin working towards the goal of writing<br />
202   a 50,000 word novel by 11:59&nbsp;pm on November 30<sup>th</sup>.
203  </p>
204  <p>
205   Valuing enthusiasm, determination, and a deadline,<br />
206   NaNoWriMo is for anyone who has ever thought about writing a novel.
207  </p>
208 </div>
209 <h3>
210  Diagnostics
211 </h3>
212 <p>
213  <code>%s = '%s'</code>
214 </p>
215 <p>
216  <code>error_reporting = 0x%X</code>
217 </p>
218 <h4 id="tam-errs">
219  Detected Errors
220 </h4>
221%s
222</div>
223_EOT;
224        // Format the errors
225        $sErrs = NULL;
226        $sErrF = <<<_EOT
227  <tr>
228   <td>%s</td>
229   <td class="wrap">%s</td>
230   <td title="%s">%s</td>
231   <td>%d</td>
232  </tr>
233_EOT;
234        foreach ($this->aErrs as $aErr)
235        {
236            // Display codes as constant names
237            $sCode = $this->errc ($aErr['code']);
238
239            // Zero width non-joiners help with word wrapping for long messages
240            $sMess = preg_replace ('#[\\\\/]#', '/&zwnj;', $aErr['mess']);
241
242            // Display short file names -- hover over for full paths
243            $sFile = $aErr['file'];
244            $sName = basename ($sFile);
245
246            // Each error has a row in a table
247            $sErrs .= sprintf ($sErrF, $sCode, $sMess, $sFile, $sName, $aErr['line']);
248        }
249        if ($sErrs !== NULL)
250        {
251            // Wrap the rows in a table
252            $sErrs = <<<_EOT
253 <table class="err">
254 <thead>
255  <tr>
256   <th>Error</th>
257   <th>Message</th>
258   <th>Source File</th>
259   <th>Line</th>
260  </tr>
261 </thead>
262 <tbody>
263$sErrs
264 </tbody>
265 </table>
266_EOT;
267        }
268
269        // Render the page
270        $sHead = self::TAM_NAME;
271        $sVers = self::TAM_VERS;
272        $sBase = 'open_basedir';
273        printf ($sForm, $sHead, $sVers, self::U_NANO,
274                $sBase, ini_get ($sBase), error_reporting (), $sErrs);
275    }
276    // End of rend
277
278    /////////////////////////////////////////////
279    // Meth: errc
280    // Desc: Convert an error code into a string.
281    // Retn: String, e.g. 'E_USER_WARNING'.
282    /////////////////////////////////////////////
283
284    final private function errc ($piCode)
285    {
286        static $aCode =
287        [
288            'E_NOTICE',
289            'E_WARNING',
290            'E_ERROR',
291            'E_STRICT',
292            'E_DEPRECATED',
293            'E_USER_NOTICE',
294            'E_USER_WARNING',
295            'E_USER_ERROR',
296            'E_USER_DEPRECATED'
297        ];
298        $sCode = sprintf ('%08X', $piCode);
299        foreach ($aCode as $sCons)
300        {
301            $iCode = constant ($sCons);
302            if ($piCode === $iCode)
303            {
304                $sCode = $sCons;
305                break;
306            }
307        }
308        return ($sCode);
309    }
310    // End of errc
311}
312// End of class TestAdminMenu
313// End of file test.admin.menu.php