olocalmap.pl 5.0 KB

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