← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 18:42:36 2015
Reported on Fri Jul 31 18:48:15 2015

Filename/var/www/foswikidev/core/lib/Foswiki/Contrib/MailerContrib/Subscription.pm
StatementsExecuted 383 statements in 2.53ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
62111.58ms1.58msFoswiki::Contrib::MailerContrib::Subscription::::newFoswiki::Contrib::MailerContrib::Subscription::new
11117µs31µsFoswiki::Contrib::MailerContrib::Subscription::::BEGIN@15Foswiki::Contrib::MailerContrib::Subscription::BEGIN@15
11110µs40µsFoswiki::Contrib::MailerContrib::Subscription::::BEGIN@17Foswiki::Contrib::MailerContrib::Subscription::BEGIN@17
1119µs14µsFoswiki::Contrib::MailerContrib::Subscription::::BEGIN@16Foswiki::Contrib::MailerContrib::Subscription::BEGIN@16
1119µs44µsFoswiki::Contrib::MailerContrib::Subscription::::BEGIN@20Foswiki::Contrib::MailerContrib::Subscription::BEGIN@20
1119µs37µsFoswiki::Contrib::MailerContrib::Subscription::::BEGIN@23Foswiki::Contrib::MailerContrib::Subscription::BEGIN@23
0000s0sFoswiki::Contrib::MailerContrib::Subscription::::_sameTopicsFoswiki::Contrib::MailerContrib::Subscription::_sameTopics
0000s0sFoswiki::Contrib::MailerContrib::Subscription::::coversFoswiki::Contrib::MailerContrib::Subscription::covers
0000s0sFoswiki::Contrib::MailerContrib::Subscription::::equalsFoswiki::Contrib::MailerContrib::Subscription::equals
0000s0sFoswiki::Contrib::MailerContrib::Subscription::::filterExactFoswiki::Contrib::MailerContrib::Subscription::filterExact
0000s0sFoswiki::Contrib::MailerContrib::Subscription::::getModeFoswiki::Contrib::MailerContrib::Subscription::getMode
0000s0sFoswiki::Contrib::MailerContrib::Subscription::::matchesFoswiki::Contrib::MailerContrib::Subscription::matches
0000s0sFoswiki::Contrib::MailerContrib::Subscription::::stringifyFoswiki::Contrib::MailerContrib::Subscription::stringify
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2
3=begin TML
4
5---+ package Foswiki::Contrib::MailerContrib::Subscription
6Object that represents a subscription to notification on a set of pages.
7A subscription is expressed as a set of page specs (each of which may
8contain wildcards) and a depth of children of matching pages that the
9user is subscribed to.
10
11=cut
12
13package Foswiki::Contrib::MailerContrib::Subscription;
14
15232µs244µs
# spent 31µs (17+14) within Foswiki::Contrib::MailerContrib::Subscription::BEGIN@15 which was called: # once (17µs+14µs) by Foswiki::Contrib::MailerContrib::WebNotify::BEGIN@23 at line 15
use strict;
# spent 31µs making 1 call to Foswiki::Contrib::MailerContrib::Subscription::BEGIN@15 # spent 14µs making 1 call to strict::import
16224µs218µs
# spent 14µs (9+4) within Foswiki::Contrib::MailerContrib::Subscription::BEGIN@16 which was called: # once (9µs+4µs) by Foswiki::Contrib::MailerContrib::WebNotify::BEGIN@23 at line 16
use warnings;
# spent 14µs making 1 call to Foswiki::Contrib::MailerContrib::Subscription::BEGIN@16 # spent 4µs making 1 call to warnings::import
17231µs269µs
# spent 40µs (10+30) within Foswiki::Contrib::MailerContrib::Subscription::BEGIN@17 which was called: # once (10µs+30µs) by Foswiki::Contrib::MailerContrib::WebNotify::BEGIN@23 at line 17
use Assert;
# spent 40µs making 1 call to Foswiki::Contrib::MailerContrib::Subscription::BEGIN@17 # spent 30µs making 1 call to Exporter::import
18
19# Always mail out this subscription, even if there have been no changes
20231µs278µs
# spent 44µs (9+34) within Foswiki::Contrib::MailerContrib::Subscription::BEGIN@20 which was called: # once (9µs+34µs) by Foswiki::Contrib::MailerContrib::WebNotify::BEGIN@23 at line 20
use constant ALWAYS => 1;
# spent 44µs making 1 call to Foswiki::Contrib::MailerContrib::Subscription::BEGIN@20 # spent 34µs making 1 call to constant::import
21
22# Always mail out the full topic, not just the changes
232729µs265µs
# spent 37µs (9+28) within Foswiki::Contrib::MailerContrib::Subscription::BEGIN@23 which was called: # once (9µs+28µs) by Foswiki::Contrib::MailerContrib::WebNotify::BEGIN@23 at line 23
use constant FULL_TOPIC => 2;
# spent 37µs making 1 call to Foswiki::Contrib::MailerContrib::Subscription::BEGIN@23 # spent 28µs making 1 call to constant::import
24
25# in the page spec these correspond as follows:
26# ? = FULL_TOPIC
27# ! = FULL_TOPIC | ALWAYS
28
29=begin TML
30
31---++ ClassMethod new($pages, $childDepth, $options)
32 * =$pages= - Wildcarded expression matching subscribed pages.
33 * =$childDepth= - Depth of children of $topic to notify changes
34 for. Defaults to 0
35 * =$options= - bitmask of Foswiki::Contrib::MailerContrib::Subscription options
36Create a new subscription.
37
38=cut
39
40
# spent 1.58ms within Foswiki::Contrib::MailerContrib::Subscription::new which was called 62 times, avg 26µs/call: # 62 times (1.58ms+0s) by Foswiki::Contrib::MailerContrib::WebNotify::subscribe at line 158 of /var/www/foswikidev/core/lib/Foswiki/Contrib/MailerContrib/WebNotify.pm, avg 26µs/call
sub new {
416239µs my ( $class, $topics, $depth, $opts ) = @_;
42
43 ASSERT( defined($opts) && $opts =~ /^\d*$/ ) if DEBUG;
44
456213µs my $tre = $topics;
4662121µs $tre =~ s/ +/|/g; # space means alternate
476259µs $tre =~ s/\*/\.\*\?/g; # convert wildcards to perl RE syntax
48621.27ms my $this = bless(
49 {
50 topics => [ split( /\s+/, $topics ) ],
51 depth => $depth || 0,
52 options => $opts || 0,
53 topicsRE => qr/^(?:$tre)$/
54 },
55 $class
56 );
5762179µs return $this;
58}
59
60=begin TML
61
62---++ stringify() -> string
63Return a string representation of this object, in Web<nop>Notify format.
64
65=cut
66
67sub stringify {
68 my $this = shift;
69 my $record = join(
70 ' ',
71 map {
72
73 # Protect single and double quotes in topic names
74 ( $_ =~ /'/ ) ? "\"$_\"" : ( ( $_ =~ /"/ ) ? "'$_'" : $_ );
75 } @{ $this->{topics} }
76 );
77 $record .= $this->getMode();
78 $record .= " ($this->{depth})" if ( $this->{depth} );
79 return $record;
80}
81
82=begin TML
83
84---++ ObjectMethod matches($topic, $db, $depth) -> boolean
85 * =$topic= - Topic names we are checking (may be an array ref)
86 * =$db= - Foswiki::Contrib::MailerContrib::UpData database of parent names
87 * =$depth= - If non-zero, check if the parent of the given topic matches as well. undef = 0.
88Check if we match this topic. Recurses up the parenthood tree seeing if
89this is a child of a parent that matches within the depth range.
90
91TODO: '*' should match alot of things..
92
93=cut
94
95sub matches {
96 my ( $this, $topics, $db, $depth ) = @_;
97
98 return 0 unless ($topics);
99
100 unless ( ref $topics ) {
101 $topics = [$topics];
102 }
103
104 foreach my $topic (@$topics) {
105 return 1 if ( $topic =~ $this->{topicsRE} );
106
107 $depth = $this->{depth} unless defined($depth);
108 $depth ||= 0;
109
110 if ( $depth && $db ) {
111 my $parent = $db->getParent($topic);
112 $parent =~ s/^.*\.//;
113 return $this->matches( $parent, $db, $depth - 1 ) if ($parent);
114 }
115 }
116
117 return 0;
118}
119
120=begin TML
121
122---++ ObjectMethod covers($other, $db) -> $boolean
123 * =$other= - Other subscription object we are checking
124 * =$db= - Foswiki::Contrib::MailerContrib::UpData database of parent names
125Return true if this subscription already covers all the topics
126specified by another subscription. Thus:
127 * A&#2A;B _covers_ AB, AxB
128 * A&#2A; _covers_ A&#2A;B
129 * &#2A;B _does not cover_ A&#2A;
130
131=cut
132
133sub covers {
134 my ( $this, $tother, $db ) = @_;
135
136 # Does the mode cover the other subscription?
137 # ALWAYS covers (ALWAYS and not ALWAYS).
138 # FULL_TOPIC covers (FULL_TOPIC and not FULL_TOPIC)
139 return 0
140 unless ( $this->{options} & $tother->{options} ) == $tother->{options};
141
142 # A * always covers if the options match
143 foreach my $t ( @{ $this->{topics} } ) {
144 return 1 if ( $t eq '*' );
145 }
146
147 # do they match without taking into account the depth?
148 return 0 unless ( $this->matches( $tother->{topics}, undef, 0 ) );
149
150 # if we have a depth and they don't, that's already catered for
151 # by the matches test above
152
153 # if we don't have a depth and they do, then we might be covered
154 # by them, but that's irrelevant
155
156 # if we have a depth and they have a depth, then there is coverage
157 # if our depth is >= their depth
158 return 0 unless ( $this->{depth} >= $tother->{depth} );
159
160 return 1;
161}
162
163=begin TML
164
165---++ ObjectMethod filterExact( \@pages ) -> $boolean
166If this subscription has an exact (string) match to any of the page expressions passed,
167remove it and return true.
168 * \@pages - list of page expressions to filter
169
170=cut
171
172sub filterExact {
173 my ( $this, $pages ) = @_;
174 my $removed = 0;
175 KNOWN:
176 for ( my $i = $#{ $this->{topics} } ; $i >= 0 ; $i-- ) {
177 foreach my $j ( @{$pages} ) {
178 if ( $j eq $this->{topics}[$i] ) {
179 splice( @{ $this->{topics} }, $i, 1 );
180 $removed = 1;
181 next KNOWN;
182 }
183 }
184 }
185 return $removed;
186}
187
188=begin TML
189
190---++ ObjectMethod getMode() -> $mode
191Get the newsletter mode of this subscription ('', '?' or '!') as
192specified in WebNotify.
193
194=cut
195
196sub getMode {
197 my $this = shift;
198
199 if ( $this->{options} & FULL_TOPIC ) {
200 return '!'
201 if ( $this->{options} & ALWAYS );
202 return '?';
203 }
204 return '';
205}
206
207sub _sameTopics {
208 my ( $a, $b ) = @_;
209 my @aa = sort @$a;
210 my @bb = sort @$b;
211 my $i = scalar(@aa);
212 return 0 unless scalar(@bb) == $i;
213 while ($i) {
214 $i--;
215 return 0 unless $aa[$i] eq $bb[$i];
216 }
217 return 1;
218}
219
220=begin TML
221
222---++ ObjectMethod equals($other) -> $boolean
223Compare two subscriptions.
224
225=cut
226
227sub equals {
228 my ( $this, $tother ) = @_;
229 return 0 unless ( $this->{options} eq $tother->{options} );
230 return 0 unless ( $this->{depth} == $tother->{depth} );
231 return 0 unless ( _sameTopics( $this->{topics}, $tother->{topics} ) );
232}
233
23412µs1;
235__END__