root/trunk/bin/upgrading/texttool.pl @ 1001

Revision 1001, 10.5 KB (checked in by bradfitz, 11 years ago)

(trans) most of command-line upgrading/exporting/etc text tool, and related general files

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#!/usr/bin/perl
2#
3# This program deals with inserting/extracting text/language data
4# from the database.
5#
6
7use strict;
8use Getopt::Long;
9
10my $opt_help = 0;
11my $opt_local_lang;
12exit 1 unless
13GetOptions(
14           "help" => \$opt_help,
15           "local-lang=s" => \$opt_local_lang,
16           );
17
18my $mode = shift @ARGV;
19
20help() if $opt_help or not defined $mode;
21
22sub help
23{
24    die "Usage: texttool.pl <command>
25
26Where 'command' is one of:
27  popstruct    Populate lang data from text[-local].dat into db
28  poptext      Populate text from en.dat, etc into database
29  dumptext     Dump lang text based on text[-local].dat information
30  check        Check validity of text[-local].dat files
31  newitems     Search files in htdocs, cgi-bin, & bin and insert
32               necessary text item codes in database.
33
34               Optionally:
35                  --local-lang=..  If given, works on local site files too
36
37";
38}
39
40## make sure $LJHOME is set so we can load & run everything
41unless (-d $ENV{'LJHOME'}) {
42    die "LJHOME environment variable is not set, or is not a directory.\n".
43        "You must fix this before you can run this database update script.";
44}
45require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
46
47my %dom_id;     # number -> {}
48my %dom_code;   # name   -> {}
49my %lang_id;    # number -> {}
50my %lang_code;  # name   -> {}
51my @lang_domains;
52
53my $set = sub {
54    my ($hash, $key, $val, $errmsg) = @_;
55    die "$errmsg$key\n" if exists $hash->{$key};
56    $hash->{$key} = $val;
57};
58
59foreach my $scope ("general", "local")
60{
61    my $file = $scope eq "general" ? "text.dat" : "text-local.dat";
62    my $ffile = "$ENV{'LJHOME'}/bin/upgrading/$file";
63    unless (-e $ffile) {
64        next if $scope eq "local";
65        die "$file file not found; odd: did you delete it?\n";
66    }
67    open (F, $ffile) or die "Can't open file: $file: $!\n";
68    while (<F>) {
69        s/\s+$//; s/^\#.+//;
70        next unless /\S/;
71        my @vals = split(/:/, $_);
72        my $what = shift @vals;
73
74        # language declaration
75        if ($what eq "lang") {
76            my $lang = {
77                'scope'  => $scope,
78                'lnid'   => $vals[0],
79                'lncode' => $vals[1],
80                'lnname' => $vals[2],
81                'parentlnid' => 0,   # default.  changed later.
82                'parenttype' => 'diff',
83            };
84            $lang->{'parenttype'} = $vals[3] if defined $vals[3];
85            if (defined $vals[4]) {
86                unless (exists $lang_code{$vals[4]}) {
87                    die "Can't declare language $lang->{'lncode'} with missing parent language $vals[4].\n";
88                }
89                $lang->{'parentlnid'} = $lang_code{$vals[4]}->{'lnid'};
90            }
91            $set->(\%lang_id,   $lang->{'lnid'},   $lang, "Language already defined with ID: ");
92            $set->(\%lang_code, $lang->{'lncode'}, $lang, "Language already defined with code: ");
93        }
94
95        # domain declaration
96        if ($what eq "domain") {
97            my $dcode = $vals[1];
98            my ($type, $args) = split(m!/!, $dcode);
99            my $dom = {
100                'scope' => $scope,
101                'dmid' => $vals[0],
102                'type' => $type,
103                'args' => $args || "",
104            };
105            $set->(\%dom_id,   $dom->{'dmid'}, $dom, "Domain already defined with ID: ");
106            $set->(\%dom_code, $dcode, $dom, "Domain already defined with parameters: ");
107        }
108
109        # langdomain declaration
110        if ($what eq "langdomain") {
111            my $ld = {
112                'lnid' =>
113                    (exists $lang_code{$vals[0]} ? $lang_code{$vals[0]}->{'lnid'} :
114                     die "Undefined language: $vals[0]\n"),
115                'dmid' =>
116                    (exists $dom_code{$vals[1]} ? $dom_code{$vals[1]}->{'dmid'} :
117                     die "Undefined domain: $vals[1]\n"),
118                'dmmaster' => $vals[2] ? "1" : "0",
119                };
120            push @lang_domains, $ld;
121        }
122    }
123    close F;
124}
125
126if ($mode eq "check") {
127    print "all good.\n";
128    exit 0;
129}
130
131## make sure we can connect
132my $dbh = LJ::get_dbh("master");
133my $sth;
134unless ($dbh) {
135    die "Can't connect to the database.\n";
136}
137
138popstruct() if $mode eq "popstruct";
139poptext() if $mode eq "poptext";
140dumptext() if $mode eq "dumptext";
141popstruct() if $mode eq "dump";
142newitems() if $mode eq "newitems";
143help();
144
145sub popstruct
146{
147    foreach my $l (values %lang_id) {
148        print "Inserting language: $l->{'lnname'}\n";
149        $dbh->do("INSERT INTO ml_langs (lnid, lncode, lnname, parenttype, parentlnid) ".
150                 "VALUES (" . join(",", map { $dbh->quote($l->{$_}) } qw(lnid lncode lnname parenttype parentlnid)) . ")");
151        die "Error: " . $dbh->errstr if $dbh->err;
152    }
153
154    foreach my $d (values %dom_id) {
155        print "Inserting domain: $d->{'type'}\[$d->{'args'}\]\n";
156        $dbh->do("INSERT INTO ml_domains (dmid, type, args) ".
157                 "VALUES (" . join(",", map { $dbh->quote($d->{$_}) } qw(dmid type args)) . ")");
158        die "Error: " . $dbh->errstr if $dbh->err;
159    }
160
161    print "Inserting language domains ...\n";
162    foreach my $ld (@lang_domains) {
163        $dbh->do("INSERT IGNORE INTO ml_langdomains (lnid, dmid, dmmaster) VALUES ".
164                 "(" . join(",", map { $dbh->quote($ld->{$_}) } qw(lnid dmid dmmaster)) . ")");
165    }
166
167    print "All done.\n";
168    exit 0;
169}
170
171sub dumptext
172{
173    foreach my $lang (keys %lang_code)
174    {
175        print "$lang\n";
176        my $l = $lang_code{$lang};
177        open (D, ">$ENV{'LJHOME'}/bin/upgrading/${lang}.dat")
178            or die "Can't open $lang.dat\n";
179        my $sth = $dbh->prepare("SELECT i.itcode, t.text FROM ".
180                                "ml_items i, ml_latest l, ml_text t ".
181                                "WHERE l.lnid=$l->{'lnid'} AND l.dmid=1 ".
182                                "AND i.dmid=1 AND l.itid=i.itid AND ".
183                                "t.dmid=1 AND t.txtid=l.txtid AND ".
184                                # only export mappings that aren't inherited:
185                                "t.lnid=$l->{'lnid'} ".
186                                "ORDER BY i.itcode");
187        $sth->execute;
188        while (my ($itcode, $text) = $sth->fetchrow_array) {
189            print "$itcode: $text\n";
190        }
191        close D;
192    }
193    exit 1;
194}
195
196sub newitems
197{
198    my $top = $ENV{'LJHOME'};
199    my @files;
200    push @files, qw(htdocs cgi-bin bin);
201    my %items;  # $scope -> $key -> 1;
202    print "Searching htdocs/cgi-bin/bin for referenced text codes...\n";
203    while (@files)
204    {
205        my $file = shift @files;
206        my $ffile = "$top/$file";
207        next unless -e $ffile;
208        if (-d $ffile) {
209            opendir (MD, $ffile) or die "Can't open $file";
210            while (my $f = readdir(MD)) {
211                next if $f eq "." || $f eq ".." ||
212                    $f =~ /^\.\#/ || $f =~ /(\.png|\.gif|~|\#)$/;
213                unshift @files, "$file/$f";
214            }
215            closedir MD;
216        }
217        if (-f $ffile) {
218            my $scope = "local";
219            $scope = "general" if -e "$top/cvs/livejournal/$file";
220
221            open (F, $ffile) or die "Can't open $file";
222            my $line = 0;
223            while (<F>) {
224                $line++;
225                while (/BML::ml\([\"\'](.+?)[\"\']/g) {
226                    $items{$scope}->{$1} = 1;
227                }
228                while (/\(=_ML\s+(.+?)\s+_ML=\)/g) {
229                    my $code = $1;
230                    if ($code =~ /^\./ && $file =~ m!^htdocs/!) {
231                        $code = "$file$code";
232                        $code =~ s!^htdocs!!;
233                    }
234                    $items{$scope}->{$code} = 1;
235                }
236            }
237            close F;
238        }
239    }
240
241    printf("  %d general and %d local found.\n",
242           scalar keys %{$items{'general'}},
243           scalar keys %{$items{'local'}});
244
245    my $register_code = sub
246    {
247        my $it = shift;
248        my $qcode = $dbh->quote($it);
249        $dbh->do("INSERT INTO ml_items (dmid, itid, itcode) ".
250                 "VALUES (1, NULL, $qcode)");
251        my $itid;
252        if ($dbh->err) {
253            $itid = $dbh->selectrow_array("SELECT itid FROM ml_items WHERE ".
254                                          "dmid=1 AND itcode=$qcode");
255        } else {
256            $itid = $dbh->{'mysql_insertid'};
257        }
258        unless ($itid) { die "Couldn't register code: $it\n"; }
259        return $itid;
260    };
261
262    my $set_text = sub
263    {
264        my ($itid, $lnid, $text) = @_;
265        my $qbogustext = $dbh->quote($text);
266        $dbh->do("INSERT INTO ml_text (dmid, txtid, lnid, itid, text, userid) VALUES ".
267                 "(1, NULL, $lnid, $itid, $qbogustext, 0)");
268        my $txtid = $dbh->{'mysql_insertid'};
269        unless ($txtid) { die "Couldn't register bogus text: $text\n"; }
270        $dbh->do("INSERT INTO ml_latest (lnid, dmid, itid, chgtime, txtid, version) VALUES ".
271                 "($lnid, 1, $itid, '0000-00-00', $txtid, 0)");
272    };
273
274    # [ General ]
275    my %e_general;  # code -> 1
276    print "Checking which general items already exist in database...\n";
277    my $sth = $dbh->prepare("SELECT i.itcode FROM ml_items i, ml_latest l WHERE ".
278                            "l.dmid=1 AND l.lnid=1 AND i.dmid=1 AND i.itid=l.itid");
279    $sth->execute;
280    while (my $it = $sth->fetchrow_array) { $e_general{$it} = 1; }
281    printf("  %d found\n", scalar keys %e_general);
282    foreach my $it (keys %{$items{'general'}}) {
283        next if exists $e_general{$it};
284        my $itid = $register_code->($it);
285        print "Added general: $it ($itid)\n";
286        $set_text->($itid, 1, "[no text: $it]");
287    }
288
289    if ($opt_local_lang) {
290        my $ll = $lang_code{$opt_local_lang};
291        die "Bogus --local-lang argument\n" unless $ll;
292        die "Local-lang '$ll->{'lncode'}' parent isn't 'en'\n"
293            unless $ll->{'parentlnid'} == 1;
294        print "Checking which local items already exist in database...\n";
295
296        my %e_local;
297        $sth = $dbh->prepare("SELECT i.itcode FROM ml_items i, ml_latest l WHERE ".
298                             "l.dmid=1 AND l.lnid=$ll->{'lnid'} AND i.dmid=1 AND i.itid=l.itid");
299        $sth->execute;
300        while (my $it = $sth->fetchrow_array) { $e_local{$it} = 1; }
301        printf("  %d found\n", scalar keys %e_local);
302        foreach my $it (keys %{$items{'local'}}) {
303            next if exists $e_general{$it};
304            next if exists $e_local{$it};
305            my $itid = $register_code->($it);
306            print "Added local: $it ($itid)\n";
307            $set_text->($itid, $ll->{'lnid'}, "[no text: $it]");
308        }
309    }
310   
311    #use Data::Dumper;
312    #print Dumper(\%items);
313
314    exit 0;
315}
Note: See TracBrowser for help on using the browser.