olocalmap.pl 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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 3 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, see <http://www.gnu.org/licenses/>.
  15. # This module adds an action and a link in the UserGotoBar to build
  16. # a Local Site Map starting from the current page. The map is a sort
  17. # of Table Of Contents in which the current page is considered the
  18. # root of the document.
  19. #
  20. # Basic idea got from MoinMoin.
  21. use strict;
  22. use v5.10;
  23. our ($q, %Action, %IndexHash, $FS, $LinkPattern, $FreeLinks, $FreeLinkPattern, $WikiLinks, $BracketWiki, @MyInitVariables, $UserGotoBar);
  24. ##########################################################################
  25. #
  26. # End-user capabilities
  27. #
  28. ##########################################################################
  29. # Actions
  30. $Action{'localmap'} = \&DoLocalMap;
  31. # Variables
  32. our ($LocalMapDefaultDepth);
  33. $LocalMapDefaultDepth = 3 unless defined $LocalMapDefaultDepth;
  34. ##########################################################################
  35. #
  36. # Implementation
  37. #
  38. ##########################################################################
  39. AddModuleDescription('olocalmap.pl');
  40. push(@MyInitVariables, \&InitLocalMap);
  41. sub InitLocalMap {
  42. my $id = GetCurrentPageName();
  43. my $action = lc(GetParam('action', ''));
  44. AllPagesList(); # Build %IndexHash
  45. # Avoid putting stuff in non-pages (like RecentChanges) and in
  46. # the page result of the action
  47. return 0 unless (length($id)
  48. && $IndexHash{$id}
  49. && ($action cmp 'localmap'));
  50. # Add a link to the list of parents
  51. $UserGotoBar .= ScriptLink("action=localmap;id=$id", T('LocalMap')) . ' ';
  52. }
  53. sub DoLocalMap {
  54. my $id = GetParam('id', '');
  55. MyReportError(T('No page id for action localmap'), '400 BAD REQUEST',
  56. undef, GetParam('raw', 0))
  57. unless length($id);
  58. AllPagesList(); # Build %IndexHash
  59. MyReportError(Ts('Requested page %s does not exist', $id),
  60. '503 SERVICE UNAVAILABLE', undef, GetParam('raw', 0))
  61. unless ($IndexHash{FreeToNormal($id)});
  62. print GetHeader('', QuoteHtml(Ts('Local Map for %s', $id)), '');
  63. my $depth = GetParam('depth', $LocalMapDefaultDepth);
  64. $id = FreeToNormal($id);
  65. my %got; # Tracks already hit pages
  66. print($q->ul(LocalMapWorkHorse($id, $depth, \%got)));
  67. PrintFooter();
  68. }
  69. sub LocalMapWorkHorse {
  70. my ($id, $depth, $GotPagesRef) = @_;
  71. $GotPagesRef->{$id} = $depth;
  72. return '' unless exists($IndexHash{$id});
  73. my $name = $id;
  74. $name =~ s/_/ /g;
  75. my $retval_me .= ScriptLink("action=localmap;id=" . UrlEncode($id), $name);
  76. $retval_me .= ' (' . GetPageLink($id, T('view')) . ')';
  77. $retval_me = $q->li($retval_me);
  78. my $retval_children = '';
  79. if ($depth > 0) {
  80. my $data = ParseData(ReadFileOrDie(GetPageFile($id)));
  81. my @flags = split(/$FS/, $data->{'flags'});
  82. my @blocks = split(/$FS/, $data->{'blocks'});
  83. my @subpages;
  84. # Iterate over blocks, operate only on "dirty" ones
  85. for (my $i = 0; $i < @flags; ++$i) {
  86. next unless $flags[$i];
  87. my $sub_id;
  88. local $_ = $blocks[$i];
  89. if ($WikiLinks
  90. && ($BracketWiki && m/\G(\[$LinkPattern\s+([^\]]+?)\])/cg
  91. or m/\G(\[$LinkPattern\])/cg or m/\G($LinkPattern)/cg)) {
  92. $sub_id = $1;
  93. } elsif ($FreeLinks
  94. && (($BracketWiki
  95. && m/\G(\[\[($FreeLinkPattern)\|([^\]]+)\]\])/cg)
  96. or m/\G(\[\[\[($FreeLinkPattern)\]\]\])/cg
  97. or m/\G(\[\[($FreeLinkPattern)\]\])/cg)) {
  98. $sub_id = $2;
  99. }
  100. if ($sub_id) {
  101. $sub_id = FreeToNormal($sub_id);
  102. if (exists $IndexHash{$sub_id}
  103. && ! exists $GotPagesRef->{$sub_id}) {
  104. push(@subpages, $sub_id);
  105. $GotPagesRef->{$sub_id} = $depth - 1;
  106. }
  107. }
  108. }
  109. # Recollect. We cannot do it inside the for loop because otherwise
  110. # we would spoil the hash pointed by $GotPagesRef
  111. foreach my $sub_id (@subpages) {
  112. $retval_children .=
  113. LocalMapWorkHorse($sub_id, $depth - 1, $GotPagesRef);
  114. }
  115. # Enclose all inside an unnumbered list
  116. $retval_children = $q->ul($retval_children) if length($retval_children);
  117. }
  118. # Return the two sections
  119. return $retval_me . $retval_children;
  120. }