Browse Source

EntryStore: by_prop(), props_for(), all_props(); property hashes

Adds a couple of hashes in the App::WRT::EntryStore::new() constructor
which stash arrays of properties for each entry, and arrays of entries
for each property, as File::Find works its way through the $entry_dir.

Uses props_for() in App::WRT::entry_topic_list() instead of dir_list().
This is maybe a tiny performance gain, but also probably more hassle
than it's worth unless other features are going to be built on these
methods (or other code that calls dir_list() simplified).

This also moves a chunk of logic out of EntryStore::all() and into the
constructor, and directly accesses $self->{source_files} in a couple of
methods instead of tossing around copies of the array.

I'm kind of iffy on whether any of this is worth doing.
Brennen Bearnes 10 months ago
parent
commit
9b7549ba10
3 changed files with 119 additions and 36 deletions
  1. 4
    12
      lib/App/WRT.pm
  2. 87
    23
      lib/App/WRT/EntryStore.pm
  3. 28
    1
      t/wrt_entrystore.t

+ 4
- 12
lib/App/WRT.pm View File

@@ -726,22 +726,14 @@ sub entry_topic_list {
726 726
   my $self = shift;
727 727
   my ($entry) = @_;
728 728
 
729
-  # Location of entry on local filesystem, and its URL:
730
-  my ($entry_loc, $entry_url) = $self->root_locations($entry);
731
-
732
-  my @tag_files;
733
-
734
-  # If it's a directory, look for some tag property files:
735
-  if (-d $entry_loc) {
736
-    @tag_files = dir_list($entry_loc, 'alpha', '^tag-.*[.]prop$');
737
-  }
729
+  my @tags = sort grep { m/^tag-.*/ } $self->{entries}->props_for($entry);
738 730
 
739
-  return '' unless @tag_files;
731
+  return '' unless @tags;
740 732
 
741 733
   return join ', ', map {
742
-    s/^tag-(.*)[.]prop$/$1/;
734
+    s/^tag-(.*)$/$1/;
743 735
     a($_, { href => $self->{url_root} . 'topics/' . $_ })
744
-  } @tag_files;
736
+  } @tags;
745 737
 }
746 738
 
747 739
 =item entry($entry)

+ 87
- 23
lib/App/WRT/EntryStore.pm View File

@@ -46,6 +46,10 @@ App::WRT::EntryStore - model the contents of a wrt repo's entry_dir
46 46
 
47 47
 Get a new EntryStore, using a given $entry_dir.
48 48
 
49
+Finds a list of entries for the given directory, and builds data structures
50
+which can be used to index into entries by depth, property, and next/previous
51
+entry.
52
+
49 53
 =cut
50 54
 
51 55
 sub new {
@@ -60,28 +64,9 @@ sub new {
60 64
 
61 65
   bless $self, $class;
62 66
 
63
-  $self->generate_date_hashes();
64
-
65
-  return $self;
66
-}
67
-
68
-=item all()
69
-
70
-Returns a list of all source files for the current entry archive (excepting
71
-index files, which are a special case - this part could use some work).
72
-
73
-This was originally in App::WRT::Renderer, so there may be some pitfalls here.
74
-
75
-=cut
76
-
77
-sub all {
78
-  my ($self) = shift;
79
-  my $entry_dir = $self->{entry_dir};
80
-
81
-  # Check if we already have a value cached:
82
-  return @{ $self->{source_files} } if defined $self->{source_files};
83
-
84 67
   my @source_files;
68
+  my %entry_properties;
69
+  my %property_entries;
85 70
   find(
86 71
     sub {
87 72
       # We skip index files, because they'll be rendered from the dir path:
@@ -89,6 +74,19 @@ sub all {
89 74
       if ($File::Find::name =~ m{^ \Q$entry_dir\E / (.*) $}x) {
90 75
         my $target = $1;
91 76
         push @source_files, $target;
77
+
78
+        # Build hashes of all properties of entries, and all entries of properties:
79
+        if ($target =~ m{(.*) / (.*) [.]prop $}x) {
80
+          my ($entry, $property) = ($1, $2);
81
+
82
+          $entry_properties{$entry} = []
83
+            unless defined $entry_properties{$entry};
84
+          push @{ $entry_properties{$entry} }, $property;
85
+
86
+          $property_entries{$property} = []
87
+            unless defined $property_entries{$property};
88
+          push @{ $property_entries{$property} }, $entry;
89
+        }
92 90
       }
93 91
     },
94 92
     $entry_dir
@@ -96,8 +94,26 @@ sub all {
96 94
 
97 95
   # Stash arrayref for future use:
98 96
   $self->{source_files} = \@source_files;
97
+  $self->{property_entries}   = \%property_entries;
98
+  $self->{entry_properties}   = \%entry_properties;
99
+
100
+  $self->generate_date_hashes();
101
+
102
+  return $self;
103
+}
104
+
105
+=item all()
106
+
107
+Returns a list of all source files for the current entry archive (excepting
108
+index files, which are a special case - this part could use some work).
109
+
110
+This was originally in App::WRT::Renderer, so there may be some pitfalls here.
99 111
 
100
-  return @source_files;
112
+=cut
113
+
114
+sub all {
115
+  my ($self) = shift;
116
+  return @{ $self->{source_files} };
101 117
 }
102 118
 
103 119
 =item dates_by_depth($depth)
@@ -140,7 +156,7 @@ sub dates_by_depth {
140 156
   my @by_depth = map  { $_->[0] }
141 157
                  sort { $a->[1] cmp $b->[1] }
142 158
                  map  { [$_, sortable_date_from_entry($_)] }
143
-                 grep m{^ $pattern $}x, $self->all();
159
+                 grep m{^ $pattern $}x, @{ $self->{source_files} };
144 160
 
145 161
   # Stash arrayref for future use:
146 162
   $self->{by_depth}->{$depth} = \@by_depth;
@@ -258,6 +274,54 @@ sub next {
258 274
   return $_[0]->{next_dates}->{ $_[1] };
259 275
 }
260 276
 
277
+=item by_prop($property)
278
+
279
+Return an array of any entries for the given property.
280
+
281
+=cut
282
+
283
+sub by_prop {
284
+  my $self = shift;
285
+  my ($property) = @_;
286
+
287
+  my @entries;
288
+  if (defined $self->{property_entries}{$property}) {
289
+    @entries = @{ $self->{property_entries}{$property} };
290
+  }
291
+
292
+  return @entries;
293
+}
294
+
295
+
296
+=item props_for($entry)
297
+
298
+Return an array of any properties for the given entry.
299
+
300
+=cut
301
+
302
+sub props_for {
303
+  my $self = shift;
304
+  my ($entry) = @_;
305
+
306
+  my @props;
307
+  if (defined $self->{entry_properties}{$entry}) {
308
+    @props = @{ $self->{entry_properties}{$entry} };
309
+  }
310
+
311
+  return @props;
312
+}
313
+
314
+=item all_props()
315
+
316
+Return an array of all properties.
317
+
318
+=cut
319
+
320
+sub all_props {
321
+  my $self = shift;
322
+  return keys %{ $self->{property_entries} };
323
+}
324
+
261 325
 =back
262 326
 
263 327
 =cut

+ 28
- 1
t/wrt_entrystore.t View File

@@ -5,7 +5,8 @@ use warnings;
5 5
 
6 6
 use lib 'lib';
7 7
 
8
-use Test::More tests => 7;
8
+use Data::Dumper;
9
+use Test::More tests => 11;
9 10
 use App::WRT;
10 11
 
11 12
 chdir 'example';
@@ -62,3 +63,29 @@ chdir 'example';
62 63
     $w->{entries}->previous('2014/1/2') eq '2014/1/1',
63 64
     'got a prev day for 2014/1/2'
64 65
   );
66
+
67
+# property finding by entry / entry finding by property
68
+  ok(
69
+    ($w->{entries}->by_prop('tag-something'))[0] eq '2014/1/2',
70
+    'found 2014/1/2 for tag-something.prop'
71
+  );
72
+
73
+  # diag(Dumper($w->{entries}->by_prop('something')));
74
+  # diag(scalar($w->{entries}->by_prop('something')));
75
+  ok(
76
+    scalar($w->{entries}->by_prop('something')) == 0,
77
+    'did not find any entries for something.prop'
78
+  );
79
+
80
+  ok(
81
+    'tag-something' eq ($w->{entries}->props_for('2014/1/2'))[0],
82
+    'found tag-something for 2014/1/2'
83
+  );
84
+
85
+  ok(
86
+    scalar($w->{entries}->all_props()) == 1,
87
+    'found 1 property for example repo'
88
+  );
89
+
90
+  # diag(Dumper($w->{entries}->{entry_properties}));
91
+  # diag(Dumper($w->{entries}->{property_entries}));

Loading…
Cancel
Save