soo_plugin_display Page 2 of 2

soo_plugin_display Source code

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