soo_plugin_display Page 2 of 2

soo_plugin_display Source code

  1 : //---------------------------------------------------------------------//
  2 :  //                     soo_plugin_pref compatibility                   //
  3 : //---------------------------------------------------------------------//
  4 : 
  5 : @require_plugin('soo_plugin_pref');             // optional
  6 : 
  7 : // Plugin init not needed on admin side
  8 : if ( @txpinterface == 'public' )
  9 : {
 10 :     global $soo_plugin_display_prefs;
 11 :     $soo_plugin_display_prefs function_exists('soo_plugin_pref_vals') ?
 12 :         array_merge(soo_plugin_display_defaults(true), soo_plugin_pref_vals('soo_plugin_display'))
 13 :         : soo_plugin_display_defaults(true);
 14 : }
 15 : elseif ( @txpinterface == 'admin' )
 16 : {
 17 :     add_privs('plugin_prefs.soo_plugin_display','1,2');
 18 :     add_privs('plugin_lifecycle.soo_plugin_display','1,2');
 19 :     register_callback('soo_plugin_display_prefs''plugin_prefs.soo_plugin_display');
 20 :     register_callback('soo_plugin_display_prefs''plugin_lifecycle.soo_plugin_display');
 21 : }
 22 : 
 23 :     // callback for plugin_prefs/plugin_lifecycle events
 24 : function soo_plugin_display_prefs$event$step ) {
 25 :     if ( function_exists('soo_plugin_pref') )
 26 :         return soo_plugin_pref($event$stepsoo_plugin_display_defaults());
 27 : 
 28 :         // message to install soo_plugin_pref
 29 :     if ( substr($event012) == 'plugin_prefs' ) {
 30 :         $plugin substr($event13);
 31 :         $message '<p><br /><strong>' gTxt('edit') . " $plugin " .
 32 :             gTxt('edit_preferences') . ':</strong><br />' gTxt('install_plugin') .
 33 :             ' <a href="http://ipsedixit.net/txp/92/soo_plugin_pref">soo_plugin_pref</a></p>';
 34 :         pagetop(gTxt('edit_preferences') . " &#8250; $plugin"$message);
 35 :     }
 36 : }
 37 : 
 38 : function soo_plugin_display_defaults$vals_only false ) {
 39 :     $defaults = array(
 40 :         'default_form'      =>  array(
 41 :             'val'   =>  '',
 42 :             'html'  =>  'text_input',
 43 :             'text'  =>  'Default output form for <b>soo_plugin_display</b> tag',
 44 :         ),
 45 :         'strip_style'       =>  array(
 46 :             'val'   =>  0,
 47 :             'html'  =>  'yesnoradio',
 48 :             'text'  =>  'Remove leading &lt;style&gt; element from Help text?',
 49 :         ),
 50 :         'strip_title'       =>  array(
 51 :             'val'   =>  0,
 52 :             'html'  =>  'yesnoradio',
 53 :             'text'  =>  'Remove first &lt;h1&gt; element from Help text?',
 54 :         ),
 55 :         'size_format'       =>  array(
 56 :             'val'   =>  '{size}&nbsp;KB',
 57 :             'html'  =>  'text_input',
 58 :             'text'  =>  'Default format string for <b>soo_plugin_size</b>',
 59 :         ),
 60 :         'highlight'         =>  array(
 61 :             'val'   =>  1,
 62 :             'html'  =>  'yesnoradio',
 63 :             'text'  =>  'Add syntax highlighting to <b>soo_plugin_code</b>?',
 64 :         ),
 65 :         'show_line_numbers' =>  array(
 66 :             'val'   =>  ':',
 67 :             'html'  =>  'text_input',
 68 :             'text'  =>  'Text to append to line numbers (leave blank to hide numbers)',
 69 :         ),
 70 :         'tab_stop'          =>  array(
 71 :             'val'   =>  4,
 72 :             'html'  =>  'text_input',
 73 :             'text'  =>  'Spaces per tab in plugin code',
 74 :         ),
 75 :     );
 76 :     if ( $vals_only )
 77 :         foreach ( $defaults as $name => $arr )
 78 :             $defaults[$name] = $arr['val'];
 79 :     return $defaults;
 80 : }
 81 : 
 82 :   //---------------------------------------------------------------------//
 83 :  //                                 Tags                                //
 84 : //---------------------------------------------------------------------//
 85 : 
 86 :     // tag to select plugin(s) for display
 87 :     // can be used as single w/form or container
 88 :     // for plugin lists code and help are not retrieved
 89 : function soo_plugin_display$atts$thing '' ) {
 90 :     global $soo_plugin_display$soo_plugin_display_prefs;
 91 :     extract(lAtts(array(
 92 :         'name'          =>  '',
 93 :         'prefix'        =>  '',
 94 :         'form'          =>  $soo_plugin_display_prefs['default_form'],
 95 :         'show_inactive' =>  0,
 96 :         'sort'          =>  'name asc',
 97 :         'wraptag'       =>  '',
 98 :         'break'         =>  '',
 99 :         'class'         =>  '',
100 :         'html_id'       =>  '',
101 :     ), $atts));
102 : 
103 :     $columns 'author, author_uri, version, description, name, ' .
104 :         'round(char_length(code)/1024, 1) as size' . ( $name ', help, code' '' );
105 : 
106 :     if ( $name or $prefix )
107 :         $where = ( $name "name = '$name'" "name like '$prefix%'" )
108 :             . ( ( $show_inactive or $name ) ? '' ' and status = 1' );
109 :     else
110 :         $where $show_inactive 'status = 1';
111 :     $where .= " order by $sort";
112 : 
113 :     if ( ! $data safe_rows($columns'txp_plugin'$where) )
114 :         return;
115 : 
116 :     foreach ( $data as $r ) {
117 :         $soo_plugin_display $r;
118 :         $out[] = $thing parse($thing) : parse_form($form);
119 :     }
120 : 
121 :     if ( isset($out) )
122 :         return doWrap($out$wraptag$break$class''''''$html_id);
123 : }
124 : 
125 :     // basic output tags: display field direct from database
126 : function soo_plugin_author_uri( ) { return _soo_plugin_field('author_uri'); }
127 : function soo_plugin_version( ) { return _soo_plugin_field('version'); }
128 : function soo_plugin_description( ) { return _soo_plugin_field('description'); }
129 : 
130 :     // as above, but with option to make output a link to author's website
131 : function soo_plugin_author$atts ) { return _soo_plugin_field('author_uri'$atts); }
132 : function soo_plugin_name$atts ) { return _soo_plugin_field('name'$atts); }
133 : 
134 :     // display plugin help, with options to remove leading style and/or h1 elements,
135 :     // and option to restrict display to named section
136 : function soo_plugin_help$atts ) {
137 :     global $soo_plugin_display_prefs;
138 :     extract(lAtts(array(
139 :         'strip_style'   =>  $soo_plugin_display_prefs['strip_style'],
140 :         'strip_title'   =>  $soo_plugin_display_prefs['strip_title'],
141 :         'section_id'    =>  '',     // HTML id for header element to display
142 :         'h_plus'        =>  0,      // transpose header levels by this amount
143 :     ), $atts));
144 :     $help _soo_plugin_field('help');
145 : 
146 :         // remove leading <style> element
147 :     if ( $strip_style and preg_match('/^<style/'$help) )
148 :         $help preg_replace('/^[\s\S]+?<\/style>([\s\S]+)$/''$1'$help);
149 : 
150 :         // remove leading <h1> element
151 :     if ( $strip_title )
152 :         $help preg_replace('/^([\s\S]+?)<h1[\s\S]+?<\/h1>([\s\S]+)$/''$1$2'$help);
153 : 
154 :         // display from named header element to next header with same or lower h-level
155 :     if ( $section_id ) {
156 :         $pattern "/^([\s\S]+)<h(\d)([^>]+id=['\"]$section_id('|\").+?>[\s\S]+)$/";
157 :         if ( preg_match($pattern$help$match) ) {
158 :             list( , , $h_num$remainder) = $match;
159 :             $help '';
160 :             $pattern '/^([\s\S]+?)<h(\d)([\s\S]+)$/';
161 :             $remainder "<h$h_num$remainder";
162 :             while ( preg_match($pattern$remainder$match) ) {
163 :                 list( , $keep$next_h$remainder) = $match;
164 :                 $help .= $keep;
165 :                 $remainder "<h$next_h$remainder";
166 :                 if ( $h_num >= $next_h )
167 :                     $remainder '';
168 :             }
169 :             if ( ! $help )
170 :                 $help $remainder;
171 :         }
172 :     }
173 : 
174 :         // transpose HTML header levels.
175 :     if ( $h_plus ) {
176 :         for ( $i 1$i <= 6$i++ ) {
177 :             $j $i $h_plus;
178 :             if ( $j $j 1;
179 :             if ( $j $j 6;
180 :             $old_tag[] = "<h$i";
181 :             $old_tag[] = "</h$i";
182 :             $new_tag[] = "<h$j";
183 :             $new_tag[] = "</h$j";
184 :         }
185 :         $help str_replace($old_tag$new_tag$help);
186 :     }
187 : 
188 :     return $help;
189 : }
190 : 
191 :     // display installed code size in KB
192 : function soo_plugin_size$atts ) {
193 :     global $soo_plugin_display_prefs;
194 :     extract(lAtts(array(
195 :         'format'    =>  $soo_plugin_display_prefs['size_format'],
196 :     ), $atts));
197 :     $size _soo_plugin_field('size');
198 :     return str_replace('{size}'$size$format);
199 : }
200 : 
201 :     // display plugin source code
202 :     // code highlighting with named classes for styling
203 :     // various options for line numbering
204 :     // display full source or named function, class, or method
205 : function soo_plugin_code$atts ) {
206 :     global $soo_plugin_display_prefs;
207 :     extract(lAtts(array(
208 :         'highlight'             =>  $soo_plugin_display_prefs['highlight'],
209 :         'show_line_numbers'     =>  $soo_plugin_display_prefs['show_line_numbers'],
210 :         'reindex_lines'         =>  0,
211 :         'tab_stop'              =>  $soo_plugin_display_prefs['tab_stop'],
212 :         'function'              =>  '',
213 :         'php_class'             =>  '',
214 :         'class'                 =>  'soo_plugin_code',
215 :         'html_id'               =>  '',
216 :     ), $atts));
217 : 
218 :     $raw_code trim(_soo_plugin_field('code'));
219 :     $match_index 2;
220 :     $safety_check true;
221 : 
222 :         // find named method: assumes end brace one tab in from start of line
223 :     if ( $php_class and $function ) {
224 :         $pattern '/([\s\S]*(abstract|)\s*class\s+'
225 :             $php_class '\s+[\s\S]*?\{[\s\S]+?)(\t(public|private|protected)?\s*function\s+'
226 :             $function '\s*\([\s\S]+?\n\t}.*)[\s\S]*/';
227 :         $match_index ++;
228 :     }
229 : 
230 :         // find named function: assumes end brace at start of line
231 :     elseif ( $function )
232 :         $pattern '/([\s\S]*)((public|private|protected)?\s*function\s+'
233 :             $function '\s*\([\s\S]+?\n}.*)/';
234 : 
235 :         // find named class: assumes end brace at start of line
236 :     elseif ( $php_class )
237 :         $pattern '/([\s\S]*?)((abstract|)\s*class\s+'
238 :             $php_class '\s+[\s\S]*?\{[\s\S]+?\n}.*)[\s\S]*/';
239 : 
240 :     else
241 :         $safety_check false;
242 : 
243 :         // safety check is because the preg_match() can take a long time if there is no match
244 :     if ( $safety_check ) {
245 :         if ( $function and ! preg_match("/$function\s*\(/"$raw_code) )
246 :             return;
247 :         if ( $php_class and ! preg_match("/class\s*$php_class\s+/"$raw_code) )
248 :             return;
249 :     }
250 : 
251 :     if ( isset($pattern) ) {
252 :         if ( ! preg_match($pattern$raw_code$match) ) return;
253 :         $raw_code $match[$match_index];
254 :             // if not reindexing, find starting line number in full source code
255 :         $start_line $reindex_lines ?
256 :             $reindex_lines count(explode(n$match[1]));
257 :     }
258 : 
259 :         // convert tabs to spaces, retaining tab stop alignment
260 :     foreach ( explode(n$raw_code) as $line ) {
261 :         $bucket = array();
262 :         foreach ( str_split($line) as $char )
263 :             if ( $char == ) {
264 :                 $add $tab_stop fmod(count($bucket), $tab_stop);
265 :                 while ( $add ) {
266 :                     $bucket[] = ' ';
267 :                     $add --;
268 :                 }
269 :             }
270 :             else
271 :                 $bucket[] = $char;
272 :         $lines[] = implode(''$bucket);
273 :     }
274 : 
275 :     if ( ! $highlight )
276 :         return implode(narray_map('htmlspecialchars'$lines));
277 : 
278 :     $find = array(spbr'<code>''</code>');
279 :     $replace = array(' 'n'''');
280 :         // names of code highlight types from ini_get()
281 :         // highlight_string() output style attributes will be replaced by named classes
282 :     foreach ( array('bg''comment''default''html''keyword''string') as $k ) {
283 :         $find[] = 'style="color: ' ini_get("highlight.$k") . '"';
284 :         $replace[] = "class=\"php_$k\"";
285 :     }
286 : 
287 :     $start_line 1;
288 : 
289 :         // run highlight_string(), clean up
290 :     $h_s highlight_string("<?php\n" implode(n$lines) . "\n?>"true);
291 :     $lines str_replace($find$replaceexplode(br$h_s));
292 :     array_shift($lines);
293 :     $lines[0] = '<span class="php_html">' $lines[0];
294 :     array_pop($lines);
295 :     $lines[count($lines)-1] .= '</span>';
296 : 
297 :         // add line numbers
298 :     $total_lines $start_line count($lines) - 1;
299 :     foreach ( $lines as $i => $line ) {
300 :         if ( $show_line_numbers ) {
301 :             $i += $start_line;
302 :             $line "<span class=\"php_comment\">$i $show_line_numbers</span> $line";
303 :             if ( $i 1000 and $total_lines 999 $line sp $line;
304 :             if ( $i 100 and $total_lines 99 $line sp $line;
305 :             if ( $i 10 $line sp $line;
306 :         }
307 :         $code[] = $line;
308 :     }
309 : 
310 :     $tag_atts = ( $class " class=\"$class\"" '' ) . ( $html_id " id=\"$html_id\"" '' );
311 : 
312 :     return "<pre$tag_atts><code$tag_atts>" implode(n$code) . '</code></pre>';
313 : }
314 : 
315 :   //---------------------------------------------------------------------//
316 :  //                         Support Functions                           //
317 : //---------------------------------------------------------------------//
318 : 
319 : function _soo_plugin_field$field$atts null ) {
320 :     if ( is_array($atts) )
321 :         extract(lAtts(array(
322 :             'link'  =>  1,
323 :         ), $atts));
324 :     global $soo_plugin_display;
325 :     $author_uri $soo_plugin_display['author_uri'];
326 :     if ( isset($soo_plugin_display[$field]) ) {
327 :         $out $soo_plugin_display[$field];
328 :         return ( ! empty($link) and $author_uri ) ? href($out$author_uri) : $out;
329 :     }
330 : }