| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# Copyright 2014-2016 - Giovanni Simoni |
|
2
|
|
|
|
|
|
|
# |
|
3
|
|
|
|
|
|
|
# This file is part of PFT. |
|
4
|
|
|
|
|
|
|
# |
|
5
|
|
|
|
|
|
|
# PFT is free software: you can redistribute it and/or modify it under the |
|
6
|
|
|
|
|
|
|
# terms of the GNU General Public License as published by the Free |
|
7
|
|
|
|
|
|
|
# Software Foundation, either version 3 of the License, or (at your |
|
8
|
|
|
|
|
|
|
# option) any later version. |
|
9
|
|
|
|
|
|
|
# |
|
10
|
|
|
|
|
|
|
# PFT is distributed in the hope that it will be useful, but WITHOUT ANY |
|
11
|
|
|
|
|
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
12
|
|
|
|
|
|
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
13
|
|
|
|
|
|
|
# for more details. |
|
14
|
|
|
|
|
|
|
# |
|
15
|
|
|
|
|
|
|
# You should have received a copy of the GNU General Public License along |
|
16
|
|
|
|
|
|
|
# with PFT. If not, see . |
|
17
|
|
|
|
|
|
|
# |
|
18
|
|
|
|
|
|
|
package PFT::Map::Node v1.3.0; |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=encoding utf8 |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 NAME |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
PFT::Map::Node - Node of a PFT site map |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
PFT::Map::Node->new($seqnr, $id, $content); |
|
29
|
|
|
|
|
|
|
PFT::Map::Node->new($seqnr, $id, undef, $header); |
|
30
|
|
|
|
|
|
|
PFT::Map::Node->new($seqnr, $id, $content, $header); |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
Objects of type C are nodes of the site map. They are |
|
35
|
|
|
|
|
|
|
created within a C object. Each node is identified by a unique |
|
36
|
|
|
|
|
|
|
sequence number and by a mnemonic identifier. |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
The first form of constructor in the B creates a |
|
39
|
|
|
|
|
|
|
C without providing a header. This is possible because a |
|
40
|
|
|
|
|
|
|
content item (C instance) is provided. The |
|
41
|
|
|
|
|
|
|
constructor will make an attempt to read the header. |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
The second and third forms shall be used when the header is already |
|
44
|
|
|
|
|
|
|
available (as optimization to avoid the system to fetch it again), or in |
|
45
|
|
|
|
|
|
|
those situation in which the header cannot be retrieved. |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
The header cannot be retrieved from entries which do not correspond to a |
|
48
|
|
|
|
|
|
|
real file (I). Nodes referring to I |
|
49
|
|
|
|
|
|
|
are called I. They represent an auto-generated pages within |
|
50
|
|
|
|
|
|
|
a PFT site (typical case: I and I. |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
See the C implementation for further details. |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=cut |
|
55
|
|
|
|
|
|
|
|
|
56
|
3
|
|
|
3
|
|
18
|
use utf8; |
|
|
3
|
|
|
|
|
122
|
|
|
|
3
|
|
|
|
|
20
|
|
|
57
|
3
|
|
|
3
|
|
98
|
use v5.16; |
|
|
3
|
|
|
|
|
10
|
|
|
58
|
3
|
|
|
3
|
|
13
|
use strict; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
52
|
|
|
59
|
3
|
|
|
3
|
|
12
|
use warnings; |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
82
|
|
|
60
|
|
|
|
|
|
|
|
|
61
|
3
|
|
|
3
|
|
1180
|
use PFT::Text; |
|
|
3
|
|
|
|
|
10
|
|
|
|
3
|
|
|
|
|
95
|
|
|
62
|
|
|
|
|
|
|
|
|
63
|
3
|
|
|
3
|
|
20
|
use Carp; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
160
|
|
|
64
|
3
|
|
|
3
|
|
18
|
use Scalar::Util qw/weaken/; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
4617
|
|
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub new { |
|
67
|
25
|
|
|
25
|
0
|
65
|
my($cls, $seqnr, $id, $cont, $hdr) = @_; |
|
68
|
25
|
50
|
33
|
|
|
134
|
confess 'Need content or header' unless $cont || $hdr; |
|
69
|
25
|
50
|
|
|
|
141
|
confess "Not content: $cont" unless $cont->isa('PFT::Content::Base'); |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
bless { |
|
72
|
|
|
|
|
|
|
seqnr => $seqnr, |
|
73
|
|
|
|
|
|
|
id => $id, |
|
74
|
|
|
|
|
|
|
cont => $cont, |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# Rule of the game: header might be obtained by content, but if |
|
77
|
|
|
|
|
|
|
# content is virtual (i.e. !$coontent->exists) it must be |
|
78
|
|
|
|
|
|
|
# provided. Only PFT::Content::Entry object have headers. |
|
79
|
|
|
|
|
|
|
hdr => defined $hdr |
|
80
|
|
|
|
|
|
|
? $hdr |
|
81
|
|
|
|
|
|
|
: $cont->isa('PFT::Content::Entry') |
|
82
|
25
|
100
|
|
|
|
124
|
? do { |
|
|
|
100
|
|
|
|
|
|
|
83
|
15
|
50
|
|
|
|
38
|
$cont->exists or confess |
|
84
|
|
|
|
|
|
|
"No header for virtual content $cont"; |
|
85
|
15
|
|
|
|
|
64
|
$cont->header |
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
: undef |
|
88
|
|
|
|
|
|
|
}, $cls |
|
89
|
|
|
|
|
|
|
} |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=head2 Properties |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=over 1 |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=item header |
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
Header associated with this node. |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
This property could return C if the node is associated with a |
|
100
|
|
|
|
|
|
|
non-textual content (something which C but not a |
|
101
|
|
|
|
|
|
|
C). |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=cut |
|
104
|
|
|
|
|
|
|
|
|
105
|
105
|
|
|
105
|
1
|
242
|
sub header { shift->{hdr} } |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=item content |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
The content associated with this node. |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
This property could return undefined for the nodes which do not correspond |
|
112
|
|
|
|
|
|
|
to any content. |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=cut |
|
115
|
|
|
|
|
|
|
|
|
116
|
20
|
|
|
20
|
1
|
98
|
sub content { shift->{cont} } |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=item date |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
Returns the date of the content, or undef if the content is not recording |
|
121
|
|
|
|
|
|
|
any date. |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=cut |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub date { |
|
126
|
50
|
|
|
50
|
1
|
80
|
my $hdr = shift->header; |
|
127
|
50
|
50
|
|
|
|
154
|
$hdr ? $hdr->date : undef |
|
128
|
|
|
|
|
|
|
} |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=item seqnr |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
Returns the sequential id of the node. |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
Reported verbatim as by constructor parameter. |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=cut |
|
137
|
|
|
|
|
|
|
|
|
138
|
43
|
|
|
43
|
1
|
178
|
sub seqnr { shift->{seqnr} } |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=item id |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
Returns the mnemonic identifier, unique for the whole site. |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
Reported verbatim as by constructor parameter. |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=cut |
|
147
|
|
|
|
|
|
|
|
|
148
|
62
|
|
|
62
|
1
|
223
|
sub id { shift->{id} } |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=item title |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
Returns the title of the content. |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
The title is retrieved from the header. Content items like pictures do not |
|
155
|
|
|
|
|
|
|
have a header, so they don't have a title: C is returned if this is |
|
156
|
|
|
|
|
|
|
the case. |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=cut |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
sub title { |
|
161
|
13
|
|
|
13
|
1
|
74
|
my $self = shift; |
|
162
|
13
|
|
|
|
|
25
|
my $hdr = $self->header; |
|
163
|
13
|
100
|
|
|
|
29
|
unless (defined $hdr) { return undef } |
|
|
2
|
|
|
|
|
7
|
|
|
164
|
11
|
|
|
|
|
23
|
my $title = $hdr->title; |
|
165
|
11
|
100
|
66
|
|
|
31
|
if (!defined($title) && $self->content->isa('PFT::Content::Month')) { |
|
166
|
1
|
|
|
|
|
3
|
sprintf("%04d / %02d", @{$hdr->date}[0, 1]) |
|
|
1
|
|
|
|
|
2
|
|
|
167
|
|
|
|
|
|
|
} else { |
|
168
|
10
|
|
|
|
|
45
|
$title; |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=item author |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
Returns the author of the content. |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
The author is retrieved from the header. Content items like pictures do not |
|
177
|
|
|
|
|
|
|
have a header, so they don't have an author: C is returned if this is |
|
178
|
|
|
|
|
|
|
the case. |
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=cut |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
sub author { |
|
183
|
0
|
|
|
0
|
1
|
0
|
my $hdr = shift->header; |
|
184
|
0
|
0
|
|
|
|
0
|
defined $hdr ? $hdr->author : undef |
|
185
|
|
|
|
|
|
|
} |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=item virtual |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
Returns 1 if the node is I. |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=cut |
|
192
|
|
|
|
|
|
|
|
|
193
|
46
|
|
|
46
|
1
|
150
|
sub virtual { !shift->{cont}->exists } |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=item content_type |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Returns the type of the content. Short for C[content)> ] |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
This has nothing to do with HTTP content-type header (nor with HTTP at all). |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=cut |
|
202
|
|
|
|
|
|
|
|
|
203
|
0
|
|
|
0
|
1
|
0
|
sub content_type { ref(shift->content) } |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=back |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=head2 Routing properties |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
Routing properties allow to access other nodes. For instance, the C |
|
210
|
|
|
|
|
|
|
property of a node will correspond to the previous node in chronological |
|
211
|
|
|
|
|
|
|
sense. They can be C (e.g. if the node does not have a |
|
212
|
|
|
|
|
|
|
predecessor). |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
The properties are: |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=over |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=item C: previous node; |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=item C: next node; |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=item C: list of tag nodes, possibly virtual; |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=item C: non-empty only for tag nodes, list of tagged nodes; |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=item C: non-empty only for month nodes, list of days in the month; |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
=item C: list of nodes whose text is pointing to this node; |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=item C: links of node pointed by the text of this node; |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=item C: union of C and C |
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=item C: list of symbols referenced in the text, sorted by |
|
235
|
|
|
|
|
|
|
occourence |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
Other methods are defined as setters for the mentioned properties. They |
|
238
|
|
|
|
|
|
|
are currently not documented, but used in C. |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=back |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=cut |
|
243
|
|
|
|
|
|
|
|
|
244
|
13
|
|
|
13
|
1
|
31
|
sub next { shift->{next} } |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub prev { |
|
247
|
27
|
|
|
27
|
0
|
37
|
my $self = shift; |
|
248
|
27
|
100
|
|
|
|
81
|
return $self->{prev} unless @_; |
|
249
|
|
|
|
|
|
|
|
|
250
|
9
|
|
|
|
|
15
|
my $p = shift; |
|
251
|
9
|
|
|
|
|
24
|
weaken($self->{prev} = $p); |
|
252
|
9
|
|
|
|
|
26
|
weaken($p->{next} = $self); |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
sub month { |
|
256
|
23
|
|
|
23
|
1
|
30
|
my $self = shift; |
|
257
|
23
|
100
|
|
|
|
43
|
unless (@_) { |
|
258
|
13
|
100
|
|
|
|
38
|
exists $self->{month} ? $self->{month} : undef; |
|
259
|
|
|
|
|
|
|
} else { |
|
260
|
|
|
|
|
|
|
confess 'Must be dated and date-complete' |
|
261
|
10
|
50
|
|
|
|
22
|
unless eval{ $self->{hdr}->date->complete }; |
|
|
10
|
|
|
|
|
24
|
|
|
262
|
|
|
|
|
|
|
|
|
263
|
10
|
|
|
|
|
18
|
my $m = shift; |
|
264
|
10
|
|
|
|
|
32
|
weaken($self->{month} = $m); |
|
265
|
|
|
|
|
|
|
|
|
266
|
10
|
|
|
|
|
16
|
push @{$m->{days}}, $self; |
|
|
10
|
|
|
|
|
21
|
|
|
267
|
10
|
|
|
|
|
30
|
weaken($m->{days}[-1]); |
|
268
|
|
|
|
|
|
|
} |
|
269
|
|
|
|
|
|
|
} |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
sub _add { |
|
272
|
19
|
|
|
19
|
|
42
|
my($self, $linked, $ka, $kb) = @_; |
|
273
|
|
|
|
|
|
|
|
|
274
|
19
|
|
|
|
|
25
|
push @{$self->{$ka}}, $linked; |
|
|
19
|
|
|
|
|
64
|
|
|
275
|
19
|
|
|
|
|
70
|
weaken($self->{$ka}[-1]); |
|
276
|
|
|
|
|
|
|
|
|
277
|
19
|
|
|
|
|
27
|
push @{$linked->{$kb}}, $self; |
|
|
19
|
|
|
|
|
38
|
|
|
278
|
19
|
|
|
|
|
98
|
weaken($linked->{$kb}[-1]); |
|
279
|
|
|
|
|
|
|
} |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub add_outlink { |
|
282
|
15
|
|
|
15
|
0
|
30
|
my($self, $node) = @_; |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
# An out-link can be either another node or a string to be placed on |
|
285
|
|
|
|
|
|
|
# the page as it is. It can be also undef, meaning that we were not |
|
286
|
|
|
|
|
|
|
# able to resolve that symbol. |
|
287
|
15
|
100
|
66
|
|
|
38
|
if ($node && $node->isa('PFT::Map::Node')) { |
|
288
|
|
|
|
|
|
|
# Building back-link if a node. |
|
289
|
11
|
|
|
|
|
35
|
$self->_add($node, 'olns', 'inls') |
|
290
|
|
|
|
|
|
|
} else { |
|
291
|
4
|
50
|
|
|
|
10
|
confess "Invalid outlink: $node" if ref($node); |
|
292
|
|
|
|
|
|
|
# Directly adding if a string or undef. |
|
293
|
4
|
|
|
|
|
7
|
push @{$self->{'olns'}}, $node |
|
|
4
|
|
|
|
|
15
|
|
|
294
|
|
|
|
|
|
|
} |
|
295
|
|
|
|
|
|
|
} |
|
296
|
|
|
|
|
|
|
|
|
297
|
8
|
|
|
8
|
0
|
20
|
sub add_tag { shift->_add(shift, 'tags', 'tagged') } |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
sub _list { |
|
300
|
45
|
|
|
45
|
|
87
|
my($self, $name) = @_; |
|
301
|
|
|
|
|
|
|
exists $self->{$name} |
|
302
|
45
|
50
|
|
|
|
131
|
? wantarray ? @{$self->{$name}} : $self->{$name} |
|
|
14
|
50
|
|
|
|
44
|
|
|
|
|
100
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
: wantarray ? () : undef |
|
304
|
|
|
|
|
|
|
} |
|
305
|
|
|
|
|
|
|
|
|
306
|
13
|
|
|
13
|
0
|
22
|
sub tags { shift->_list('tags') } |
|
307
|
13
|
|
|
13
|
1
|
18
|
sub tagged { shift->_list('tagged') } |
|
308
|
13
|
|
|
13
|
1
|
24
|
sub days { shift->_list('days') } |
|
309
|
0
|
|
|
0
|
0
|
0
|
sub inlinks { shift->_list('ilns') } |
|
310
|
6
|
|
|
6
|
0
|
15
|
sub outlinks { shift->_list('olns') } |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub children { |
|
313
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
|
314
|
0
|
|
|
|
|
0
|
$self->_list('tagged'), |
|
315
|
|
|
|
|
|
|
$self->_list('days'), |
|
316
|
|
|
|
|
|
|
} |
|
317
|
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
sub _text { |
|
319
|
23
|
|
|
23
|
|
34
|
my $self = shift; |
|
320
|
23
|
100
|
|
|
|
56
|
if (exists $self->{text}) { |
|
321
|
|
|
|
|
|
|
$self->{text} |
|
322
|
6
|
|
|
|
|
19
|
} else { |
|
323
|
17
|
|
|
|
|
36
|
$self->{text} = PFT::Text->new($self->content) |
|
324
|
|
|
|
|
|
|
} |
|
325
|
|
|
|
|
|
|
} |
|
326
|
|
|
|
|
|
|
|
|
327
|
17
|
|
|
17
|
1
|
40
|
sub symbols { shift->_text->symbols } |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
sub add_symbol_unres { |
|
330
|
4
|
|
|
4
|
0
|
12
|
my($self, $symbol, $reason) = @_; |
|
331
|
|
|
|
|
|
|
|
|
332
|
4
|
|
|
|
|
11
|
$self->{unres_syms_flush} ++; |
|
333
|
4
|
|
|
|
|
7
|
push @{$self->{unres_syms}}, [$symbol, $reason]; |
|
|
4
|
|
|
|
|
22
|
|
|
334
|
|
|
|
|
|
|
} |
|
335
|
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
# NOTE: |
|
337
|
|
|
|
|
|
|
# |
|
338
|
|
|
|
|
|
|
# Unresolved symbols should be notified to the user. Since this is a library, |
|
339
|
|
|
|
|
|
|
# the calling code is responsible for notifying the user. |
|
340
|
|
|
|
|
|
|
# |
|
341
|
|
|
|
|
|
|
# As 'relaxed enforcement' we warn on STDERR if the list of unresolved symbols |
|
342
|
|
|
|
|
|
|
# is never retrieved. |
|
343
|
|
|
|
|
|
|
sub symbols_unres { |
|
344
|
15
|
|
|
15
|
0
|
38
|
my $self = shift; |
|
345
|
15
|
|
|
|
|
20
|
delete $self->{unres_syms_flush}; |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
# Returns a list of pairs [symbol, reason] |
|
348
|
|
|
|
|
|
|
exists $self->{unres_syms} |
|
349
|
15
|
100
|
|
|
|
31
|
? @{$self->{unres_syms}} |
|
|
3
|
|
|
|
|
11
|
|
|
350
|
|
|
|
|
|
|
: () |
|
351
|
|
|
|
|
|
|
} |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
sub DESTROY { |
|
354
|
13
|
|
|
13
|
|
8448
|
my $self = shift; |
|
355
|
13
|
50
|
|
|
|
79
|
return unless exists $self->{unres_syms_flush}; |
|
356
|
0
|
|
|
|
|
0
|
warn 'Unnoticed unresolved symbols for PFT::Map::Node ', $self->id, |
|
357
|
|
|
|
|
|
|
'. Please use PFT::Map::Node::symbols_unres' |
|
358
|
|
|
|
|
|
|
} |
|
359
|
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
=head2 More complex methods |
|
361
|
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=over 1 |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
=item html |
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
Expand HTML of the content, translating outbound links into |
|
367
|
|
|
|
|
|
|
hyper-references (hrefs). |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
Requires as parameter a callback mapping a C object into a |
|
370
|
|
|
|
|
|
|
string representing path within the site. The callback is applied to all |
|
371
|
|
|
|
|
|
|
symbols, and the resulting string will replace the symbol placeholder in |
|
372
|
|
|
|
|
|
|
the HTML. |
|
373
|
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
Returns a string HTML, or an empty string if the node is virtual. |
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
=cut |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
sub html { |
|
379
|
6
|
|
|
6
|
1
|
41
|
my $self = shift; |
|
380
|
6
|
50
|
|
|
|
17
|
return undef if $self->virtual; |
|
381
|
|
|
|
|
|
|
|
|
382
|
6
|
50
|
|
|
|
22
|
my $mkhref = shift or confess "Missing mkref parameter"; |
|
383
|
|
|
|
|
|
|
$self->_text->html_resolved( |
|
384
|
|
|
|
|
|
|
map { |
|
385
|
6
|
0
|
|
|
|
16
|
defined($_) |
|
|
12
|
50
|
|
|
|
51
|
|
|
|
|
100
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
? $_->isa('PFT::Map::Node') |
|
387
|
|
|
|
|
|
|
? $mkhref->($_) # Create reference of node |
|
388
|
|
|
|
|
|
|
: ref($_) |
|
389
|
|
|
|
|
|
|
? confess "Not PFT::Map::Node: $_" |
|
390
|
|
|
|
|
|
|
: $_ # Keep string as it is |
|
391
|
|
|
|
|
|
|
: undef # Symbol could not be resolved. |
|
392
|
|
|
|
|
|
|
} $self->outlinks |
|
393
|
|
|
|
|
|
|
); |
|
394
|
|
|
|
|
|
|
} |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
use overload |
|
397
|
|
|
|
|
|
|
'<=>' => sub { |
|
398
|
75
|
|
|
75
|
|
115
|
my($self, $oth, $swap) = @_; |
|
399
|
75
|
|
|
|
|
100
|
my $out = $self->{seqnr} <=> $oth->{seqnr}; |
|
400
|
75
|
50
|
|
|
|
182
|
$swap ? -$out : $out; |
|
401
|
|
|
|
|
|
|
}, |
|
402
|
|
|
|
|
|
|
'cmp' => sub { |
|
403
|
0
|
|
|
0
|
|
0
|
my($self, $oth, $swap) = @_; |
|
404
|
0
|
|
|
|
|
0
|
my $out = $self->{cont} cmp $oth->{cont}; |
|
405
|
0
|
0
|
|
|
|
0
|
$swap ? -$out : $out; |
|
406
|
|
|
|
|
|
|
}, |
|
407
|
|
|
|
|
|
|
'""' => sub { |
|
408
|
40
|
|
|
40
|
|
73
|
my $self = shift; |
|
409
|
40
|
100
|
|
|
|
87
|
'PFT::Map::Node[id=' . $self->id |
|
410
|
|
|
|
|
|
|
. ', virtual=' . ($self->virtual ? 'yes' : 'no') |
|
411
|
|
|
|
|
|
|
. ']' |
|
412
|
|
|
|
|
|
|
}, |
|
413
|
3
|
|
|
3
|
|
26
|
; |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
37
|
|
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=back |
|
416
|
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
=cut |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
1; |