]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/support-scripts/sitemap_generator
2758971861ef75dfa32d4e31477481105259ec26
[working/Evergreen.git] / Open-ILS / src / support-scripts / sitemap_generator
1 #!/usr/bin/perl
2 # Copyright (C) 2014 Laurentian University
3 # Author: Dan Scott <dscott@laurentian.ca>
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (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 use strict; use warnings;
16 use XML::LibXML;
17 use File::Copy;
18 use Getopt::Long;
19 use File::Spec;
20 use File::Basename;
21 use DBI qw(:sql_types);
22
23 my ($dbhost, $dbport, $dbname, $dbuser, $dbpw, $help);
24 my $config_file = '';
25 my $sysconfdir = '';
26
27 =item create_sitemaps() - Write the sitemap files
28
29 With a maximum of 50,000 URLs per sitemap, this method
30 automatically increments the sitemap file numbers and
31 generates a corresponding sitemap index that lists all
32 of the individual sitemap files.
33
34 See http://www.sitemaps.org/ for the specification
35
36 =cut
37 sub create_sitemaps {
38     my ($settings, $bibs, $aou_id) = @_;
39
40     my $f_cnt = 1;
41     my $r_cnt = 0;
42     my @sitemaps;
43     my $fn = $settings->{'prefix'} . "sitemap$f_cnt.xml";
44     push(@sitemaps, $fn);
45     open(FH, '>', $fn) or die "Could not write sitemap $f_cnt\n";
46     print FH '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
47     print FH '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
48
49     foreach my $bib (@$bibs) {
50         print FH "<url><loc>" . $settings->{'lib-hostname'} . "/eg/opac/record/" . $bib->[0];
51         if ($aou_id) {
52             print FH "?locg=$aou_id";
53         }
54         print FH "</loc><lastmod>" . $bib->[1] . "</lastmod></url>\n";
55         $r_cnt++;
56         if ($r_cnt % 50000 == 0) {
57             $f_cnt++;
58             print FH "</urlset>\n";
59             close(FH);
60             my $fn = $settings->{'prefix'} . "sitemap$f_cnt.xml";
61             push(@sitemaps, $fn);
62             open(FH, '>', $fn) or die "Could not write bibs\n";
63             print FH '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
64             print FH '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
65         }
66     }
67     print FH "</urlset>\n";
68     close(FH);
69
70     open(INDEXFH, '>', $settings->{'prefix'} . "sitemapindex.xml") or die "Could not write sitemap index\n";
71     print INDEXFH '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
72     print INDEXFH '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
73     foreach my $fn (@sitemaps) {
74         print INDEXFH "<sitemap><loc>" . $settings->{'lib-hostname'} . "/$fn</loc></sitemap>\n";
75     }
76     print INDEXFH "</sitemapindex>\n";
77     close(INDEXFH);
78     
79
80 }
81
82 =item get_settings() - Extracts database settings from opensrf.xml
83 =cut
84 sub get_settings {
85     my $settings = shift;
86
87     my $host = "/opensrf/default/apps/open-ils.reporter-store/app_settings/database/host/text()";
88     my $port = "/opensrf/default/apps/open-ils.reporter-store/app_settings/database/port/text()";
89     my $dbname = "/opensrf/default/apps/open-ils.reporter-store/app_settings/database/db/text()";
90     my $user = "/opensrf/default/apps/open-ils.reporter-store/app_settings/database/user/text()";
91     my $pw = "/opensrf/default/apps/open-ils.reporter-store/app_settings/database/pw/text()";
92
93     my $parser = XML::LibXML->new();
94     my $opensrf_config = $parser->parse_file($config_file);
95
96     # If the user passed in settings at the command line,
97     # we don't want to override them
98     $settings->{host} = $settings->{host} || $opensrf_config->findnodes($host);
99     $settings->{port} = $settings->{port} || $opensrf_config->findnodes($port);
100     $settings->{db} = $settings->{db} || $opensrf_config->findnodes($dbname);
101     $settings->{user} = $settings->{user} || $opensrf_config->findnodes($user);
102     $settings->{pw} = $settings->{pw} || $opensrf_config->findnodes($pw);
103 }
104
105 =item get_record_ids() - Gets a list of record IDs
106 =cut
107 sub get_record_ids {
108     my $settings = shift;
109     my $aou_id;
110
111     my $dbh = DBI->connect('dbi:Pg:dbname=' . $settings->{db} . 
112         ';host=' . $settings->{host} . ';port=' . $settings->{port} . ';',
113          $settings->{user} . "", $settings->{pw} . "", {AutoCommit => 1}
114     );
115     if ($dbh->err) {
116         print STDERR "Could not connect to database. ";
117         print STDERR "Error was " . $dbh->errstr . "\n";
118         return;
119     }
120
121     if ($settings->{'lib-shortname'}) {
122         my $stmt = $dbh->prepare("SELECT id FROM actor.org_unit WHERE shortname = ?");
123         $stmt->execute(($settings->{'lib-shortname'}));
124         my $rv = $stmt->bind_columns(\$aou_id);
125         $stmt->fetch();
126     }
127
128     my $q = "
129         SELECT DISTINCT bre.id, edit_date::date AS edit_date
130         FROM biblio.record_entry bre
131             INNER JOIN asset.opac_visible_copies aovc ON bre.id = aovc.record
132     ";
133     if ($aou_id) {
134         $q .= " WHERE circ_lib IN (SELECT id FROM actor.org_unit WHERE id = ? OR parent_ou = ?)";
135     }
136     $q .= " ORDER BY edit_date DESC";
137     my $stmt = $dbh->prepare($q);
138     if ($aou_id) {
139         $stmt->bind_param(1, $aou_id, { TYPE => SQL_INTEGER });
140         $stmt->bind_param(2, $aou_id, { TYPE => SQL_INTEGER });
141         $stmt->execute();
142     } else {
143         $stmt->execute();
144     }
145
146     my $bibs = $stmt->fetchall_arrayref([0, 1]);
147
148     if ($dbh->err) {
149         print STDERR "Error was " . $dbh->errstr . "\n";
150         return;
151     }
152     return ($bibs, $aou_id);
153 }
154
155 my $hostname;
156 my $aou_shortname;
157 my %settings = (
158     prefix => ''
159 );
160
161 GetOptions(
162         "lib-hostname=s" => \$settings{'lib-hostname'},
163         "lib-shortname=s" => \$settings{'lib-shortname'},
164         "prefix=s" => \$settings{'prefix'},
165         "config-file=s" => \$config_file,
166         "user=s" => \$settings{'user'},
167         "password=s" => \$settings{'pw'},
168         "database=s" => \$settings{'db'},
169         "hostname=s" => \$settings{'host'},
170         "port=i" => \$settings{'port'}, 
171         "help" => \$help
172 );
173
174 if (!$config_file) { 
175     my @temp = `eg_config --sysconfdir`;
176     chomp $temp[0];
177     $sysconfdir = $temp[0];
178     $config_file = File::Spec->catfile($sysconfdir, "opensrf.xml");
179 }
180
181 unless (-e $config_file) { die "Error: $config_file does not exist. \n"; }
182
183 if ($settings{'lib-hostname'}) {
184     # Get additional settings from the config file
185     get_settings(\%settings);
186
187     my ($bibs, $aou_id) = get_record_ids(\%settings);
188     create_sitemaps(\%settings, $bibs, $aou_id);
189 } else {
190     $help = 1;
191 }
192
193 if ($help) {
194     print <<HERE;
195
196 SYNOPSIS
197     sitemap_generator [OPTION] ... [COMMAND] ... [CONFIG OPTIONS]
198
199 DESCRIPTION
200     Creates a set of sitemaps for enabling web crawlers to crawl
201     freshly changed bibliographic records.
202
203 OPTIONS
204     --config-file
205         specifies the opensrf.xml file
206
207     --lib-hostname
208         REQUIRED: hostname for the catalog (e.g "https://example.com")
209
210     --prefix
211         filename to add as a prefix to the generated set of sitemap files
212
213     --lib-shortname
214         include all records for the specified library and its children;
215         defaults to all records
216
217 EXAMPLES
218    This script will normally be run as a cron job by the opensrf user from
219    the web root directory.
220
221    sitemap_generator --lib-hostname https://example.com --lib-shortname BR1 \
222       --prefix example_
223
224    This generates a set of sitemap files like so:
225      * example_sitemapindex.xml
226      * example_sitemap1.xml
227      * example_sitemap2.xml
228      * ...
229
230 HERE
231 }
232