Multidoc Page 11 of 27

soo_multidoc Source code

  1 : if(class_exists('\Textpattern\Tag\Registry')) {
  2 :     Txp::get('\Textpattern\Tag\Registry')
  3 :         ->register('soo_multidoc_link')
  4 :         ->register('soo_multidoc_pager')
  5 :         ->register('soo_multidoc_page_number')
  6 :         ->register('soo_multidoc_toc')
  7 :         ->register('soo_multidoc_page_title')
  8 :         ->register('soo_multidoc_breadcrumbs')
  9 :         ->register('soo_if_multidoc')
 10 :         ->register('soo_if_multidoc_linear')
 11 :         ->register('soo_if_multidoc_link')
 12 :         ;
 13 : }
 14 : 
 15 : require_plugin('soo_txp_obj');
 16 : @require_plugin('soo_plugin_pref');     // optional
 17 : 
 18 :   //---------------------------------------------------------------------//
 19 :  //                                 Globals                             //
 20 : //---------------------------------------------------------------------//
 21 : 
 22 : if ( @txpinterface == 'admin' )
 23 : {
 24 :     add_privs('plugin_prefs.soo_multidoc','1,2');
 25 :     add_privs('plugin_lifecycle.soo_multidoc','1,2');
 26 :     register_callback('soo_multidoc_prefs''plugin_prefs.soo_multidoc');
 27 :     register_callback('soo_multidoc_prefs''plugin_lifecycle.soo_multidoc');
 28 : }
 29 : 
 30 : global $soo_multidoc;
 31 : $soo_multidoc function_exists('soo_plugin_pref_vals') ?
 32 :     array_merge(soo_multidoc_defaults(true), soo_plugin_pref_vals('soo_multidoc'))
 33 :     : soo_multidoc_defaults(true);
 34 : $soo_multidoc array_merge($soo_multidoc, array(
 35 :     'init'      =>  false,
 36 :     'status'    =>  false,
 37 :     'id_parent' =>  '',
 38 :     'data'      =>  '',
 39 : ));
 40 : 
 41 : function soo_multidoc_prefs$event$step )
 42 : {
 43 :     if ( function_exists('soo_plugin_pref') )
 44 :         return soo_plugin_pref($event$stepsoo_multidoc_defaults());
 45 :     if ( substr($event012) == 'plugin_prefs' ) {
 46 :         $plugin substr($event12);
 47 :         $message '<p><br /><strong>' gTxt('edit') . $plugin " .
 48 :             gTxt('edit_preferences') . ':</strong><br />' gTxt('install_plugin') .
 49 :             ' <a href="http://ipsedixit.net/txp/92/soo_plugin_pref">soo_plugin_pref</a></p>';
 50 :         pagetop(gTxt('edit_preferences') . " &#8250; $plugin"$message);
 51 :     }
 52 : }
 53 : 
 54 : function soo_multidoc_defaults$vals_only false )
 55 : {
 56 :     $defaults = array(
 57 :         'list_all'  =>  array(
 58 :             'val'   =>  0,
 59 :             'html'  =>  'yesnoradio',
 60 :             'text'  =>  'Show Multidoc sub-pages in article lists?',
 61 :         ),
 62 :         'posted_time'   =>  array(
 63 :             'val'   =>  'past',
 64 :             'html'  =>  'text_input',
 65 :             'text'  =>  'Show articles posted &lsquo;past&rsquo;, &lsquo;future&rsquo;, or &lsquo;any&rsquo;',
 66 :         ),
 67 :     );
 68 :     if ( $vals_only )
 69 :         foreach ( $defaults as $name => $arr )
 70 :             $defaults[$name] = $arr['val'];
 71 :     return $defaults;
 72 : }
 73 : 
 74 :   //---------------------------------------------------------------------//
 75 :  //                         MLP Pack definitions                        //
 76 : //---------------------------------------------------------------------//
 77 : 
 78 : define('SOO_MULTIDOC_PREFIX''soo_mdoc');
 79 : global $soo_multidoc_strings;
 80 : $soo_multidoc_strings = array(
 81 :     'start' =>  'start',
 82 :     'up'    =>  'up',
 83 :     'next'  =>  'next',
 84 :     'prev'  =>  'prev',
 85 : );
 86 : 
 87 : register_callback('soo_multidoc_enumerate_strings''l10n.enumerate_strings');
 88 : 
 89 : function soo_multidoc_enumerate_strings$event$step ''$pre )
 90 : {
 91 :     global $soo_multidoc_strings;
 92 :     $r = array(
 93 :         'owner'     => 'soo_multidoc',
 94 :         'prefix'    => SOO_MULTIDOC_PREFIX,
 95 :         'lang'      => 'en-us',
 96 :         'event'     => 'public',
 97 :         'strings'   => $soo_multidoc_strings,
 98 :                 );
 99 :     return $r;
100 : }
101 : 
102 : function soo_multidoc_gTxt$what $args = array() )
103 : {
104 :     global $textarray;
105 :     global $soo_multidoc_strings;
106 : 
107 :     $key SOO_MULTIDOC_PREFIX '-' $what;
108 :     $key strtolower($key);
109 : 
110 :     if(isset($textarray[$key]))
111 :         $str $textarray[$key];
112 : 
113 :     else
114 :     {
115 :         $key strtolower($what);
116 : 
117 :         if( isset( $soo_multidoc_strings[$key] ) )
118 :             $str $soo_multidoc_strings[$key];
119 :         else
120 :             $str $what;
121 :     }
122 : 
123 :     if( !empty($args) )
124 :         $str strtr$str $args );
125 : 
126 :     return $str;
127 : }
128 : 
129 : 
130 :   //---------------------------------------------------------------------//
131 :  //                                 Classes                             //
132 : //---------------------------------------------------------------------//
133 : 
134 : class soo_multidoc_rowset extends soo_nested_set
135 : {
136 :     public function has_subnode$a$b )
137 :     // Boolean: is $b a subnode of $a?
138 :     {
139 :         return ( $this->$b->lft $this->$a->lft and $this->$b->rgt $this->$a->rgt );
140 :     }
141 : 
142 :     public function find_by_link_type$link_type$current null$dir 'next' )
143 :     {
144 :         $rs $this->rows;
145 :         if ( $dir == 'prev' )
146 :             $rs array_reverse($rstrue);
147 :         $ids array_keys($rs);
148 :         $link_type strtolower($link_type);
149 : 
150 :         if ( $current and in_array($current$ids) )
151 :         {
152 :             $id_position array_search($current$ids);
153 :             if ( $dir == 'prev' )
154 :                 $id_position++;
155 :             $searchable_ids array_flip(array_slice($ids$id_position));
156 :             $rs array_intersect_key($rs$searchable_ids);
157 :         }
158 : 
159 :         foreach ( $rs as $k => $r )
160 :             if ( $r->link_type == $link_type )
161 :                 return $k;
162 :     }
163 : }
164 : 
165 :   //---------------------------------------------------------------------//
166 :  //                                 Tags                                //
167 : //---------------------------------------------------------------------//
168 : 
169 : function soo_multidoc_link$atts$thing null )
170 : {
171 : // Output tag: display an HTML anchor
172 : // Requires article context
173 : 
174 :     extract(lAtts(array(
175 :         'rel'           =>  '',
176 :         'add_title'     =>  '',
177 : 
178 :         // {rel} and {title} available as tokens
179 :         'text'          =>  '{rel}',
180 :         'html_id'       =>  '',
181 :         'class'         =>  '',
182 :         'active_class'  =>  '',
183 :         'wraptag'       =>  '',
184 :     ), $atts));
185 : 
186 :     global $soo_multidoc;
187 :     if ( ! ( _soo_multidoc_init() and $soo_multidoc['status'] ) ) return false;
188 : 
189 :     foreach ( array('start''up''next''prev') as $type )
190 :         $reserved_rel[$type] = $$type strtolower(soo_multidoc_gTxt($type));
191 : 
192 :     global $thisarticle;
193 :     $rowset = &$soo_multidoc['rowset'];
194 :     $thisid $thisarticle['thisid'];
195 :     $rel trim($rel);
196 : 
197 :     // $rel value may be space-separated list of link types
198 :     // this tag allows only 'prev' or 'next' in combination with another type
199 :     if ( preg_match("/^($next|$prev)\s+(\w+)/i"$rel$match) )
200 :     {
201 :         $rel_dir strtolower($match[1]);
202 :         $rel_type strtolower($match[2]);
203 :         $link_id $rowset->find_by_link_type($rel_type$thisid$rel_dir);
204 : 
205 :         // if I have an ancestor of the requested link type, that ancestor will
206 :         // be the prev link of that type, which isn't what the user wants.
207 :         // So continue back one more step.
208 :         if ( $rel_dir == 'prev' and $rowset->has_subnode($link_id$thisid) )
209 :         {
210 :             $next_link $rowset->find_by_link_type($rel_type$link_id$rel_dir);
211 :             if ( $next_link != $link_id and is_numeric($next_link) )
212 :                 $link_id $next_link;
213 :             else
214 :                 unset($link_id);
215 :         }
216 :     }
217 :     elseif ( in_array($relcomp strtolower($rel), $reserved_rel) )
218 :     {
219 :         if ( $relcomp == $start )
220 :             $link_id $soo_multidoc['id_root'][$thisid];
221 :         elseif ( $relcomp == $up )
222 :         {
223 :             $link_id $soo_multidoc['id_parent'][$thisid];
224 :             if ( ! intval($link_id) )
225 :                 $link_id 0;
226 :         }
227 :         else    // next or prev
228 :         {
229 :             $next_array $soo_multidoc['next_array'];
230 :             if ( $relcomp == $prev )
231 :                 $next_array array_reverse($next_array);
232 :             $i array_search($thisid$next_array);
233 :             $link_id = isset($next_array[$i 1]) ? $next_array[$i 1] : 0;
234 :         }
235 : 
236 :     }
237 :     else
238 :         $link_id $rowset->find_by_link_type($rel);
239 : 
240 :     if ( ! empty($link_id) )
241 :         $url $soo_multidoc['data'][$link_id]['url'];
242 : 
243 :     if ( ! isset($url) ) return false;
244 : 
245 :     if ( $add_title )
246 :         $thing .= $rowset->$link_id->title;
247 : 
248 :     if ( ! $thing )
249 :         $thing str_replace(array('{rel}''{title}'), array($rel$rowset->$link_id->title), $text);
250 : 
251 :     if ( $link_id == $thisid )
252 :         $tag = new soo_html_span(array('class' => $active_class));
253 : 
254 :     else
255 :         $tag = new soo_html_anchor(array('href' => $url'rel' => $rel));
256 : 
257 :     $tag->contents(parse($thing));
258 : 
259 :     if ( $wraptag and class_exists($tag_class 'soo_html_' $wraptag) )
260 :     {
261 :         $wraptag = new $tag_class;
262 :         return $wraptag->contents($tag)->class($class)->
263 :             id($html_id)->
264 :             tag();
265 :     }
266 :     else
267 :     {
268 :         $tag->id($html_id);
269 :         if ( $link_id != $thisid )
270 :             $tag->class($class);
271 :         return $tag->tag();
272 :     }
273 : }
274 : ///////////////////// end of soo_multidoc_link() ///////////////////////
275 : 
276 : function soo_multidoc_pager$atts )
277 : {
278 : // Output tag: display a simple list of page links
279 : // Requires article context
280 : 
281 :     extract(lAtts(array(
282 :         'limit'         =>  0,
283 :         'placeholder'   =>  ' &hellip; ',
284 :         'html_id'       =>  '',
285 :         'class'         =>  '',
286 :         'active_class'  =>  '',
287 :         'wraptag'       =>  '',
288 :         'wrapclass'     =>  '',
289 :         'break'         =>  '',
290 :         'breakclass'    =>  '',
291 :     ), $atts));
292 : 
293 :     global $soo_multidoc;
294 :     if ( ! ( _soo_multidoc_init() and $soo_multidoc['status'] ) ) return false;
295 : 
296 :     global $thisarticle;
297 :     $thisid $thisarticle['thisid'];
298 : 
299 :     $wraptag trim(strtolower($wraptag));
300 :     if ( $wraptag == 'table' )
301 :         $break 'td';
302 :     elseif ( $wraptag == 'ul' or $wraptag == 'ol' )
303 :         $break 'li';
304 : 
305 :     if ( $break )
306 :     {
307 :         $break_obj 'soo_html_' trim(strtolower($break));
308 :         if ( ! class_exists($break_obj) )
309 :             $break_obj null;
310 :         else {
311 :             $break '';
312 :             $test_obj = new $break_obj;
313 :             $empty_break $test_obj->is_empty;
314 :         }
315 :     }
316 :     else
317 :         $break_obj null;
318 : 
319 :     $page_ids $soo_multidoc['next_array'];
320 : 
321 :     $total count($page_ids);
322 :     $page_nums array_combine($page_idsrange(1$total));
323 :     $this_num $page_nums[$thisid];
324 : 
325 :     $w_start max(1,
326 :         min($this_num $limit$total - ( $limit ) + 1));
327 :     $w_end min($w_start + ( $limit ) - 1$total);
328 : 
329 :     $show_nums array_unique(array_merge(
330 :         array(1), range($w_start$w_end), array($total)
331 :     ));
332 : 
333 :     $objs = array();
334 : 
335 :     while ( $n array_shift($show_nums) )
336 :     {
337 :         if ( $n == $this_num )
338 :             $objs[] = new soo_html_span(array('class' => $active_class), $n);
339 :         else
340 :             $objs[] = new soo_html_anchor(array(
341 :                 'href' => $soo_multidoc['data'][$page_ids[$n 1]]['url'],
342 :                 'class' => $class), $n)
343 :             ;
344 : 
345 :         $fill $show_nums ?
346 :             ( $show_nums[0] > $n $placeholder $break ) : '';
347 :         if ( $fill )
348 :             $objs[] = new soo_html_span(''$fill);
349 :     }
350 : 
351 :     if ( $break_obj )
352 :     {
353 :         if ( $empty_break )
354 :         {
355 :             while ( $objs )
356 :             {
357 :                 $broken_objs[] = array_shift($objs);
358 :                 $broken_objs[] = new $break_obj;
359 :             }
360 :             array_pop($broken_objs);
361 :             $objs $broken_objs;
362 :         }
363 :         else
364 :             foreach ( $objs as $i => $obj )
365 :                 $objs[$i] = new $break_obj(''$obj);
366 :         foreach ( $objs as $obj )
367 :             if ( $obj instanceof $break_obj )
368 :                 $obj->class($breakclass);
369 :     }
370 : 
371 :     if ( $wraptag == 'table' )
372 :         $wrap_obj = new soo_html_tr;
373 : 
374 :     else {
375 :         $wrap_obj_class 'soo_html_' $wraptag;
376 :         if ( class_exists($wrap_obj_class) )
377 :             $wrap_obj = new $wrap_obj_class;
378 :     }
379 :     if ( isset($wrap_obj) )
380 :     {
381 :         $wrap_obj->class($wrapclass);
382 :         foreach ( $objs as $obj )
383 :             $wrap_obj->contents($obj);
384 : 
385 :         if ( $wraptag == 'table' )
386 :         {
387 :             $table = new soo_html_table(array('id' => $html_id),
388 :                 new soo_html_tbody(''$wrap_obj));
389 :             return $table->tag();
390 :         }
391 :         else
392 :             return $wrap_obj->id($html_id)->tag();
393 :     }
394 :     else
395 :     {
396 :         $out = array();
397 :         foreach ( $objs as $obj )
398 :             $out[] = $obj->tag();
399 :         return implode("\n"$out);
400 :     }
401 : }
402 : ///////////////////// end of soo_multidoc_pager() ///////////////////////
403 : 
404 : function soo_multidoc_page_number$atts )
405 : {
406 : // Output tag: display current page number
407 : // Requires article context
408 : 
409 :     extract(lAtts(array(
410 :         'html_id'       =>  '',
411 :         'class'         =>  '',
412 :         'wraptag'       =>  'span',
413 :         'format'        =>  'Page {page} of {total}',
414 :     ), $atts));
415 : 
416 :     global $soo_multidoc;
417 :     if ( ! ( _soo_multidoc_init() and $soo_multidoc['status'] ) ) return false;
418 : 
419 :     global $thisarticle;
420 :     $thisid $thisarticle['thisid'];
421 : 
422 :     $page_ids $soo_multidoc['next_array'];
423 : 
424 :     $num_pages count($page_ids);
425 :     $page_nums array_flip($page_ids);
426 :     $this_page $page_nums[$thisid] + 1;
427 : 
428 :     $format str_replace('{page}'$this_page$format);
429 :     $format str_replace('{total}'$num_pages$format);
430 : 
431 :     return doWrap(array($format), $wraptag''$class''''''$html_id);
432 : 
433 : }
434 : 
435 : function soo_multidoc_toc$atts )
436 : {
437 : // Output tag: display table of contents as tiered list
438 : // Requires article context
439 : 
440 :     extract(lAtts(array(
441 :         'wraptag'       =>  'ul',
442 :         'root'          =>  '',
443 :         'add_start'     =>  false,
444 :         'html_id'       =>  '',
445 :         'class'         =>  '',
446 :         'active_class'  =>  '',
447 :     ), $atts));
448 : 
449 :     global $soo_multidoc;
450 :     if ( ! ( _soo_multidoc_init() and $soo_multidoc['status'] ) ) return false;
451 : 
452 :     global $thisarticle;
453 : 
454 :     if ( $root )
455 :     {
456 :         $start_id is_numeric($root) ? intval($root) : $thisarticle['thisid'];
457 :         $object_array $soo_multidoc['rowset']->subtree($start_id'id')->as_object_array();
458 :     }
459 :     else
460 :         $object_array $soo_multidoc['rowset']->as_object_array();
461 : 
462 :     if ( ! $add_start )
463 :         $object_array $object_array[1];
464 : 
465 :     array_walk_recursive($object_array'_soo_multidoc_toc_prep', array('id' => $thisarticle['thisid'], 'class' => $active_class));
466 : 
467 :     $wraptag trim(strtolower($wraptag));
468 :     if ( ! in_array($wraptag, array('ul''ol')) )
469 :         return false;
470 :     $wrap_obj_class 'soo_html_' $wraptag;
471 : 
472 :     $out = new $wrap_obj_class(array(), $object_array);
473 :     return $out->class($class)->id($html_id)->tag();
474 : 
475 : }
476 : 
477 : function soo_multidoc_page_title$atts )
478 : {
479 : // Output tag: replacement for <txp:page_title />
480 : // Requires article context
481 : // If a Multidoc non-Start page, Start title will be added to output.
482 : // Otherwise standard page_title() is returned
483 : 
484 :     extract(lAtts(array(
485 :         'separator'     =>  ': ',
486 :     ), $atts));
487 : 
488 :     global $soo_multidoc$sitename$thisarticle;
489 :     if ( ! ( _soo_multidoc_init() and $soo_multidoc['status'] ) )
490 :         return page_title($atts);
491 : 
492 :     $thisid $thisarticle['thisid'];
493 :     $rs = &$soo_multidoc['rowset']->rows;
494 :     $root $soo_multidoc['id_root'][$thisid];
495 : 
496 :     return htmlspecialchars($sitename $separator $rs[$root]->title .
497 :         ( $root != $thisid $separator $rs[$thisid]->title '' )
498 :     );
499 : }
500 : 
501 : function soo_multidoc_breadcrumbs$atts )
502 : {
503 : // Output tag: show higher levels in Collection
504 : // Requires article context
505 : 
506 :     extract(lAtts(array(
507 :         'separator'     =>  ': ',
508 :     ), $atts));
509 : 
510 :     global $soo_multidoc$thisarticle;
511 :     if ( ! ( _soo_multidoc_init() and $soo_multidoc['status'] ) )
512 :         return;
513 : 
514 :     $data = &$soo_multidoc['data'];
515 :     $this_id $thisarticle['thisid'];
516 :     $crumbs[] = $data[$this_id]['title'];
517 : 
518 :     while ( $this_id $soo_multidoc['id_parent'][$this_id] and intval($this_id) )
519 :     {
520 :         $tag = new soo_html_anchor(array('href' => $data[$this_id]['url']),
521 :             escape_title($data[$this_id]['title']));
522 :         array_unshift($crumbs$tag->tag());
523 :     }
524 : 
525 :     return implode($separator$crumbs);
526 : }
527 : 
528 : function soo_if_multidoc$atts$thing )
529 : {
530 : // Conditional: does current page belong to one of the specified Multidoc collections?
531 : // If no collections specified, looks for any Multidoc collection
532 : // Requires article context.
533 : 
534 :     extract(lAtts(array(
535 :         'start_id'      =>  '',
536 :     ), $atts));
537 : 
538 :     global $soo_multidoc;
539 :     if ( ! ( _soo_multidoc_init() and $soo_multidoc['status'] ) )
540 :         return parse(EvalElse($thingfalse));
541 : 
542 :     global $thisarticle;
543 :     $thisid $thisarticle['thisid'];
544 :     $start_ids do_list($start_id);
545 : 
546 :     $ok = ( ! $start_id or in_array($soo_multidoc['id_root'][$thisid], $start_ids) );
547 : 
548 :     return parse(EvalElse($thing$ok));
549 : }
550 : 
551 : function soo_if_multidoc_linear$atts$thing )
552 : {
553 :     global $soo_multidoc;
554 : 
555 :     if ( ! ( _soo_multidoc_init() and $soo_multidoc['status'] ) )
556 :         return parse(EvalElse($thingfalse));
557 :     $is_linear count(array_unique($soo_multidoc['id_parent'])) == 2;
558 :     return parse(EvalElse($thing$is_linear));
559 : }
560 : 
561 : function soo_if_multidoc_link$atts$thing )
562 : {
563 :     extract(lAtts(array(
564 :         'rel'           =>  '',
565 :         'id'            =>  '',
566 :         'link_type'     =>  '',
567 :     ), $atts));
568 : 
569 :     $rel strtolower($rel);
570 :     global $soo_multidoc;
571 : 
572 :     if ( ! (
573 :         $rel && in_array($rel, array('up''next''prev')) &&
574 :         ( $id || $link_type ) &&
575 :         _soo_multidoc_init() &&
576 :         $soo_multidoc['status']
577 :     ) )
578 :         return parse(EvalElse($thingfalse));
579 : 
580 :     global $thisarticle;
581 :     $this_id $thisarticle['thisid'];
582 : 
583 :     switch ( $rel )
584 :     {
585 :         case 'up':
586 :             $link_id $soo_multidoc['id_parent'][$this_id];
587 :             break;
588 :         case 'next':
589 :             $link_id $soo_multidoc['data'][$this_id]['next'];
590 :             break;
591 :         case 'prev':
592 :             $pos array_search($this_id$soo_multidoc['next_array']);
593 :             $link_id $pos $soo_multidoc['next_array'][$pos 1] : 0;
594 :     }
595 :     if ( $id )
596 :         $match $link_id == $id;
597 :     elseif ( is_numeric($link_id) )
598 :         $match strcasecmp($link_type$soo_multidoc['rowset']->$link_id->link_type) === 0;
599 :     else
600 :         $match false;
601 : 
602 :     return parse(EvalElse($thing$match));
603 : }
604 : 
605 :   //---------------------------------------------------------------------//
606 :  //                         Support Functions                           //
607 : //---------------------------------------------------------------------//
608 : 
609 : function _soo_multidoc_init()
610 : {
611 : // Initialization controller. Most Multidoc tags will return blank if this
612 : // function returns false.
613 : 
614 :     global $soo_multidoc;
615 : 
616 :     // only run init() once per page
617 :     if ( $soo_multidoc['init'] ) return true;
618 :     $soo_multidoc['init'] = true;
619 : 
620 :     global $is_article_list$thisarticle;
621 : 
622 :     // Multidoc tags not allowed in lists
623 :     if ( $is_article_list ) return false;
624 : 
625 :     // article context check
626 :     assert_article();
627 :     if ( empty($thisarticle) ) return false;
628 : 
629 :     // populate global arrays of Multidoc article IDs
630 :     _soo_multidoc_ids_init($thisid $thisarticle['thisid']);
631 : 
632 :     // is this a Multidoc article?
633 :     if ( empty($soo_multidoc['id_parent'][$thisid]) ) return false;
634 : 
635 :     // All systems go!!!
636 :     return $soo_multidoc['status'] = true;
637 : }
638 : 
639 : function _soo_multidoc_ids_init$thisid null$force false )
640 : {
641 : // populate $soo_multidoc global arrays
642 : // if $thisid is set, populate global data array for this article's collection
643 : 
644 :     global $soo_multidoc;
645 : 
646 :     if ( is_array($soo_multidoc['id_parent']) and ! $force )
647 :         return true;
648 : 
649 :     $query = new soo_txp_left_join('soo_multidoc''textpattern''id''ID');
650 :     $query->select(array('id''root''lft''rgt''children''type as link_type'))
651 :         ->select_join(array('ID''Title as title''url_title''Section''Posted'))
652 :         ->order_by(array('root''lft'));
653 : 
654 :     // Draft or hidden articles visible in admin only
655 :     if ( @txpinterface != 'admin' )
656 :         $query->where_join('Status'3'>');   // live or sticky status
657 : 
658 :     if ( ! get_pref('publish_expired_articles') )
659 :         $query->where_clause('(now() <= Expires OR Expires IS NULL)');
660 : 
661 :     if ( $thisid )
662 :     {
663 :         $root_query = new soo_txp_select('soo_multidoc', array('id' => $thisid), 'root');
664 :         $query->in('root'$root_query);
665 :     }
666 : 
667 :     switch ( $soo_multidoc['posted_time'] )
668 :     {
669 :         case 'past':
670 :             $query->where_clause('Posted <= now()');
671 :             break;
672 :         case 'future':
673 :             $query->where_clause('Posted > now()');
674 :     }
675 : 
676 :     if ( ! $join_count $query->count() )
677 :         return false;
678 : 
679 :     // TODO: need to deal with missing articles
680 : //  if ( $thisid )
681 : //  {
682 : //      $thisid_root = current($root_query->row());
683 : //      $collection_query = new soo_txp_select('soo_multidoc', array('root' => $thisid_root), 'id');
684 : //      $collection_count = $collection_query->count();
685 : //      if ( $diff = $collection_count - $join_count )
686 : //          echo $diff, ' missing record(s)';
687 : //
688 : //      $collection_rowset = new soo_txp_rowset( $collection_query->order_by('lft'));
689 : //      $collection_records = $collection_rowset->field_vals('id');
690 : //  }
691 : 
692 :     $rs = new soo_multidoc_rowset($query);
693 :     $ids $rs->field_vals('id');
694 :     $rs->rows array_combine($ids$rs->rows);
695 :     $id_parent = array();
696 :     $id_children = array();
697 : 
698 :     foreach ( $rs->rows as $r )
699 :     {
700 :         if ( $r->link_type == 'start' )
701 :             $id_parent[$r->id] = 'Start';
702 :         if ( $r->children )
703 :         {
704 :             $id_children[$r->id] = do_list($r->children);
705 :             foreach ( $id_children[$r->id] as $child )
706 :                 $id_parent[$child] = $r->id;
707 :         }
708 :         else
709 :             $id_children[$r->id] = array();
710 :     }
711 : 
712 :     $soo_multidoc['id_parent'] = $id_parent;    // key = id, value = parent id
713 :     $soo_multidoc['id_children'] = $id_children;        // key = id, value = array
714 :     $soo_multidoc['id_root'] = $rs->field_vals('root''id');   // key = id, value = root id
715 :     $soo_multidoc['id_link_type'] = $rs->field_vals('link_type''id'); // key = id, value = link_type
716 :     $soo_multidoc['rowset'] = $rs;
717 : 
718 :     // if individual article context, populate data array for this collection
719 :     if ( $thisid and array_key_exists($thisid$id_parent) )
720 :     {
721 :         $next $soo_multidoc['rowset']->field_vals('id');
722 :         $soo_multidoc['next_array'] = $next;
723 :         array_shift($next);
724 :         $soo_multidoc['data'] = [];
725 :         foreach ( $soo_multidoc['rowset']->rows as $id => $r )
726 :             $soo_multidoc['data'][$id] = array_merge($r->data, array(
727 :                 'parent' => $id_parent[$id],
728 :                 'url' => permlinkurl($r->data),
729 :                 'next' => array_shift($next),
730 :             ));
731 :     }
732 :     return true;
733 : }
734 : 
735 : /// Convert a row object to an html element object.
736 : //  Intended for use with array_walk_recursive()
737 : function _soo_multidoc_toc_prep ( &$row$k$active )
738 : {
739 :     global $soo_multidoc;
740 :     if ( $row->id == $active['id'] )
741 :         $row = new soo_html_span(array('class' => $active['class']), $row->title);
742 :     else
743 :         $row = new soo_html_anchor(array('href' => $soo_multidoc['data'][$row->id]['url']), $row->title);
744 : }
745 : 
746 : function _soo_multidoc_temp_table ( )
747 : {
748 : // MySQL temporary table to filter Multidoc interior pages from article lists
749 :     global $pretext$is_article_list$soo_multidoc;
750 :     if ( ! $is_article_list or
751 :         $pretext['q'] or
752 :         ! empty($soo_multidoc['list_all']) or
753 :         ! getRow("show tables like 'soo_multidoc'") or
754 :         ! _soo_multidoc_ids_init()
755 :     )
756 :         return;
757 :     $t1 safe_pfx('textpattern');
758 :     $t2 safe_pfx('soo_multidoc');
759 :     safe_query(
760 :         "create temporary table $t1 select * from $t1 where ID not in (select id from $t2 where id != root)");
761 : }
762 : 
763 : register_callback('_soo_multidoc_temp_table''pretext_end');