Multidoc Page 11 of 27

soo_multidoc Source code

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