olocalmap.pl 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. # Copyright (C) 2005 Flavio Poletti <flavio@polettix.it>
  2. #
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 2 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the
  15. # Free Software Foundation, Inc.
  16. # 59 Temple Place, Suite 330
  17. # Boston, MA 02111-1307 USA
  18. # This module adds an action and a link in the UserGotoBar to build
  19. # a Local Site Map starting from the current page. The map is a sort
  20. # of Table Of Contents in which the current page is considered the
  21. # root of the document.
  22. #
  23. # Basic idea got from MoinMoin.
  24. use strict;
  25. use v5.10;
  26. our ($q, %Action, %IndexHash, $FS, $LinkPattern, $FreeLinks, $FreeLinkPattern, $WikiLinks, $BracketWiki, @MyInitVariables, $UserGotoBar);
  27. ##########################################################################
  28. #
  29. # End-user capabilities
  30. #
  31. ##########################################################################
  32. # Actions
  33. $Action{'localmap'} = \&DoLocalMap;
  34. # Variables
  35. our ($LocalMapDefaultDepth);
  36. $LocalMapDefaultDepth = 3 unless defined $LocalMapDefaultDepth;
  37. ##########################################################################
  38. #
  39. # Implementation
  40. #
  41. ##########################################################################
  42. AddModuleDescription('olocalmap.pl');
  43. push(@MyInitVariables, \&InitLocalMap);
  44. sub InitLocalMap {
  45. my $id = GetCurrentPageName();
  46. my $action = lc(GetParam('action', ''));
  47. AllPagesList(); # Build %IndexHash
  48. # Avoid putting stuff in non-pages (like RecentChanges) and in
  49. # the page result of the action
  50. return 0 unless (length($id)
  51. && $IndexHash{$id}
  52. && ($action cmp 'localmap'));
  53. # Add a link to the list of parents
  54. $UserGotoBar .= ScriptLink("action=localmap;id=$id", T('LocalMap')) . ' ';
  55. }
  56. sub DoLocalMap {
  57. my $id = GetParam('id', '');
  58. MyReportError(T('No page id for action localmap'), '400 BAD REQUEST',
  59. undef, GetParam('raw', 0))
  60. unless length($id);
  61. AllPagesList(); # Build %IndexHash
  62. MyReportError(Ts('Requested page %s does not exist', $id),
  63. '503 SERVICE UNAVAILABLE', undef, GetParam('raw', 0))
  64. unless ($IndexHash{FreeToNormal($id)});
  65. print GetHeader('', QuoteHtml(Ts('Local Map for %s', $id)), '');
  66. my $depth = GetParam('depth', $LocalMapDefaultDepth);
  67. $id = FreeToNormal($id);
  68. my %got; # Tracks already hit pages
  69. print($q->ul(LocalMapWorkHorse($id, $depth, \%got)));
  70. PrintFooter();
  71. }
  72. sub LocalMapWorkHorse {
  73. my ($id, $depth, $GotPagesRef) = @_;
  74. $GotPagesRef->{$id} = $depth;
  75. return '' unless exists($IndexHash{$id});
  76. my $name = $id;
  77. $name =~ s/_/ /g;
  78. my $retval_me .= ScriptLink("action=localmap;id=" . UrlEncode($id), $name);
  79. $retval_me .= ' (' . GetPageLink($id, T('view')) . ')';
  80. $retval_me = $q->li($retval_me);
  81. my $retval_children = '';
  82. if ($depth > 0) {
  83. my $data = ParseData(ReadFileOrDie(GetPageFile($id)));
  84. my @flags = split(/$FS/, $data->{'flags'});
  85. my @blocks = split(/$FS/, $data->{'blocks'});
  86. my @subpages;
  87. # Iterate over blocks, operate only on "dirty" ones
  88. for (my $i = 0; $i < @flags; ++$i) {
  89. next unless $flags[$i];
  90. my $sub_id;
  91. local $_ = $blocks[$i];
  92. if ($WikiLinks
  93. && ($BracketWiki && m/\G(\[$LinkPattern\s+([^\]]+?)\])/cg
  94. or m/\G(\[$LinkPattern\])/cg or m/\G($LinkPattern)/cg)) {
  95. $sub_id = $1;
  96. } elsif ($FreeLinks
  97. && (($BracketWiki
  98. && m/\G(\[\[($FreeLinkPattern)\|([^\]]+)\]\])/cg)
  99. or m/\G(\[\[\[($FreeLinkPattern)\]\]\])/cg
  100. or m/\G(\[\[($FreeLinkPattern)\]\])/cg)) {
  101. $sub_id = $2;
  102. }
  103. if ($sub_id) {
  104. $sub_id = FreeToNormal($sub_id);
  105. if (exists $IndexHash{$sub_id}
  106. && ! exists $GotPagesRef->{$sub_id}) {
  107. push(@subpages, $sub_id);
  108. $GotPagesRef->{$sub_id} = $depth - 1;
  109. }
  110. }
  111. }
  112. # Recollect. We cannot do it inside the for loop because otherwise
  113. # we would spoil the hash pointed by $GotPagesRef
  114. foreach my $sub_id (@subpages) {
  115. $retval_children .=
  116. LocalMapWorkHorse($sub_id, $depth - 1, $GotPagesRef);
  117. }
  118. # Enclose all inside an unnumbered list
  119. $retval_children = $q->ul($retval_children) if length($retval_children);
  120. }
  121. # Return the two sections
  122. return $retval_me . $retval_children;
  123. }