WordPress.org

Make WordPress Core

Ticket #9175: 9175-options-serialoption-viewer-patch.txt

File 9175-options-serialoption-viewer-patch.txt, 8.1 KB (added by hakre, 7 years ago)

Patch that enables infos and viewing of serialized values

Line 
1### Eclipse Workspace Patch 1.0
2#P wordpress
3Index: wp-admin/options.php
4===================================================================
5--- wp-admin/options.php        (revision 10593)
6+++ wp-admin/options.php        (working copy)
7@@ -83,6 +83,148 @@
8        wp_redirect( $goback );
9        break;
10 
11+case 'serialoption':
12+// viewer for a serialized option value.
13+       
14+       // validate input       
15+       $option_name = isset( $_GET['option_name'] ) ? (string) trim( $_GET['option_name'] ) : null;
16+               
17+       if ( $option_name === null )
18+               wp_die(__('Cheatin’ uh?'));
19+               
20+       $r = preg_match('/^[a-z0-9_]*$/', $option_name);
21+       if ( $r == 0 )
22+               wp_die(__('Cheatin’ uh?'));
23+               
24+       $options_to_update = array(); // nothing to update right now.
25+               
26+       include('admin-header.php'); ?>
27+<div class="wrap">
28+<?php screen_icon(); ?>
29+  <h2><?php printf('%s - %s', $option_name, __('Option')); ?></h2>
30+  <form name="form" action="options.php" method="post" id="all-options">
31+  <?php wp_nonce_field('options-options') ?>
32+  <input type="hidden" name="action" value="serialoption" /> 
33+  <input type='hidden' name='option_page' value='options' /> 
34+<?php
35+       // query option value and validate serialized-ability
36+                       
37+       $options = $wpdb->get_results(sprintf("SELECT * FROM %s WHERE option_name = '%s'", $wpdb->options, $option_name));
38+
39+       // the serialoption page can handle only one value
40+       if ( count($options) != 1)             
41+               wp_die(__('Cheatin&#8217; uh?'));
42+       
43+       $option = $options[0];
44+
45+       // $option must be stdclass to continue
46+       if ( is_object($option) == false )
47+               wp_die(__('Cheatin&#8217; uh?'));
48+       
49+       // not a serialized value? well, handeled in full options page already                 
50+       if ( !is_serialized($option->option_value) )
51+               wp_die(__('Cheatin&#8217; uh?'));
52+
53+       // this case is handeled in the full options page already as well
54+       if ( is_serialized_string($option->option_value) )
55+               wp_die(__('Cheatin&#8217; uh?'));
56+               
57+       // unserialize: false on failure, notice will be given as well (usefull for the admin)
58+       $unserialized = unserialize($option->option_value);
59+       
60+       // serialized scalar makes not much sense right now     
61+       if ( is_scalar($unserialized) )
62+               wp_die(__('Cheatin&#8217; uh?'));
63+                               
64+       // array
65+       // object - will fail/become '__PHP_Incomplete_Class_Name' if class is not defined
66+               
67+       $title = $type = 'UNDEFINED';   
68+       
69+       switch ( true ) {
70+               case is_scalar($unserialized):
71+                       $title = 'SCALAR';
72+                       $type  = 'SCALAR';
73+                       break;
74+                                               
75+               case is_object($unserialized):
76+                       $title = sprintf('OBJECT (%s)', get_class($unserialized));
77+                       $type  = 'OBJECT';
78+                       break;
79+                       
80+               case is_array($unserialized):
81+                       $title = sprintf('ARRAY (%d Elements)', count($unserialized));
82+                       $type = 'ARRAY';                       
83+                       break;
84+                       
85+               case gettype($unserialized) == 'object':
86+                       // this is a fallback since sometime is_object did not make it.
87+                       $title = sprintf('OBJECT (%s)', get_class($unserialized));
88+                       $type  = 'OBJECT';
89+                       break;                 
90+                       
91+               default:
92+                       $title = 'UNKNOWN TYPE ' . gettype($unserialized);
93+                       $type  = 'UNKNOWN';
94+       } // end inner switch
95+       
96+       $values = array('UNDEFINED' => '');
97+
98+       switch ( $type ) {
99+               case 'SCALAR':
100+                       $values = array($type => (string) $unserialized);
101+                       break;
102+                       
103+               case 'OBJECT':
104+                       $values = array(get_class($unserialized) => $unserialized);
105+                       break;
106+                       
107+               case 'ARRAY':
108+                       $values = $unserialized;
109+                       break;
110+                               
111+               default:
112+                       $values = array('UNKNOWN' => '');
113+       } // end inner switch
114+       
115+?>
116+  <h3><?php echo htmlspecialchars($title) ?></h3>
117+  <table class="form-table"> 
118+<?php
119+       foreach ( $values as $key => $value ):
120+                       
121+               $id = sprintf('edit-%s', htmlspecialchars($key));
122+               $html_label = sprintf( '<label for="%s">%s</label>', $id, htmlspecialchars($key));
123+               
124+               // prevent recurisions, stacked arrays and such
125+               if (! is_scalar($value) ) {
126+                       $value = print_r($value, true);
127+               }               
128+       
129+               // put values in form elements for a better editing experience
130+               // $html_input = sprintf('<div>%s</div>', htmlspecialchars(print_r($value, true)) );
131+               if ( strpos($value, "\n") !== false ) {
132+                       $html_input = sprintf('<textarea class="large-text" name="%s" id="%s" rows="10">%s</textarea>', $id, $id, htmlspecialchars($value));
133+               } else {
134+                       $html_input = sprintf('<input class="regular-text" type="text" name="%s" id="%s" value="%s" %s />', $id, $id, htmlspecialchars($value), $disabled);
135+               }
136+?>
137+  <tr>
138+       <th scope="row"><?php echo $html_label ?></th>
139+       <td><?php echo $html_input ?></td>
140+  </tr>
141+<?php endforeach; ?>
142+  </table>
143+  <p class="submit">
144+       <a href="options.php" class="button lbutton"><?php _e('Back'); ?></a>
145+       <input type="hidden" name="page_options" value="<?php echo htmlspecialchars(implode(',', $options_to_update)); ?>" />
146+    <input type="hidden" name="Update-Ex" value="<?php _e('Save Changes') ?>" class="button-primary disabled"  disabled="disabled" />
147+  </p>
148+  </form>
149+</div>
150+<?php
151+       break;
152+       
153 default:
154        include('admin-header.php'); ?>
155 
156@@ -99,38 +241,50 @@
157 
158 foreach ( (array) $options as $option) :
159        $disabled = '';
160+       $more     = false;
161        $option->option_name = attribute_escape($option->option_name);
162        if ( is_serialized($option->option_value) ) {
163                if ( is_serialized_string($option->option_value) ) {
164                        // this is a serialized string, so we should display it
165                        $value = maybe_unserialize($option->option_value);
166                        $options_to_update[] = $option->option_name;
167-                       $class = 'all-options';
168+                       $class = 'all-options';                 
169                } else {
170-                       $value = 'SERIALIZED DATA';
171+                       $value = sprintf('SERIALIZED DATA (~ %s %s)', number_format(strlen($option->option_value)), __('Bytes') );                     
172                        $disabled = ' disabled="disabled"';
173-                       $class = 'all-options disabled';
174-               }
175-       } else {
176+                       $class = 'all-options disabled';                       
177+                       $more  = true;
178+               }               
179+       } else {               
180                $value = $option->option_value;
181-               $options_to_update[] = $option->option_name;
182+               $options_to_update[] = $option->option_name;           
183                $class = 'all-options';
184        }
185-       echo "
186-<tr>
187-       <th scope='row'><label for='$option->option_name'>$option->option_name</label></th>
188-<td>";
189-
190-       if (strpos($value, "\n") !== false) echo "<textarea class='$class' name='$option->option_name' id='$option->option_name' cols='30' rows='5'>" . wp_specialchars($value) . "</textarea>";
191-       else echo "<input class='regular-text $class' type='text' name='$option->option_name' id='$option->option_name' value='" . attribute_escape($value) . "'$disabled />";
192+       
193+       $html_label = sprintf( '<label for="%1$s">%1$s</label>', $option->option_name );
194+       $html_input = '';
195+       if ( strpos($value, "\n") !== false ) {
196+               $html_input = sprintf('<textarea class="%s" name="%s" id="%s" cols="40" rows="10">%s</textarea>', $class, $option->option_name, $option->option_name, wp_specialchars($value));
197+       } else {
198+               $html_input = sprintf('<input class="regular-text %s" type="text" name="%s" id="%s" value="%s" %s />', $class, $option->option_name, $option->option_name, attribute_escape($value), $disabled);
199+       }
200+               
201+       /* more info on seriazlied data, add the expand button to gain access to serialoption */
202+       if ( $more ) {
203+               $html_href  = sprintf('options.php?action=serialoption&option_name=%s', urlencode($option->option_name));
204+               $html_label = sprintf('<a href="%s" class="button">%s</a>',  $html_href, $option->option_name);
205+               // uncommented: for label/expand button combo but I like the other combo more. $html_input .= sprintf(' <a href="%s" class="button-primary">%s</a>',  $html_href, _('Expand'));
206+       }
207 
208-       echo "</td>
209-</tr>";
210-endforeach;
211 ?>
212+<tr>
213+       <th scope="row"><?php echo $html_label ?></th>
214+       <td><?php echo $html_input ?></td>
215+</tr>
216+<?php endforeach; ?>
217   </table>
218 <?php $options_to_update = implode(',', $options_to_update); ?>
219-<p class="submit"><input type="hidden" name="page_options" value="<?php echo $options_to_update; ?>" /><input type="submit" name="Update" value="<?php _e('Save Changes') ?>" class="button-primary" /></p>
220+<p class="submit"><input type="hidden" name="page_options" value="<?php echo htmlspecialchars($options_to_update); ?>" /><input type="submit" name="Update" value="<?php _e('Save Changes') ?>" class="button-primary" /></p>
221   </form>
222 </div>
223