diff --git a/mozilla/webtools/PLIF/PLIF/DataSource/Strings.pm b/mozilla/webtools/PLIF/PLIF/DataSource/Strings.pm
index a3f88808424..4d8906966df 100644
--- a/mozilla/webtools/PLIF/PLIF/DataSource/Strings.pm
+++ b/mozilla/webtools/PLIF/PLIF/DataSource/Strings.pm
@@ -132,6 +132,8 @@ sub variants {
return $self->variantsCache->{$protocol};
}
+
+# XXX The next four SO have to change...
sub acceptType {
my $self = shift;
my($app, $protocol) = @_;
@@ -156,9 +158,14 @@ sub acceptLanguage {
return $app->input->acceptLanguage;
}
+
+# "Low Level" API
+
sub getString {
my $self = shift;
+ # my($app, $variant, $string) = @_;
$self->notImplemented();
+ # return data
}
sub getDefaultString {
@@ -169,6 +176,50 @@ sub getDefaultString {
sub getVariants {
my $self = shift;
+ # my($app, $protocol) = @_;
+ $self->notImplemented();
+ # return id, quality, type, encoding, charset, language
+}
+
+sub getVariant {
+ my $self = shift;
+ # my($app, $id) = @_;
+ $self->notImplemented();
+ # return name, protocol, quality, type, encoding, charset, language, description, translator
+}
+
+sub getVariantStrings {
+ my $self = shift;
+ # my($app, $variant) = @_;
+ $self->notImplemented();
+ # return ( string => data )*;
+}
+
+sub getStringVariants {
+ my $self = shift;
+ # my($app, $string) = @_;
+ $self->notImplemented();
+ # return { name, protocol, quality, type, encoding, charset, language, description, translator, string }*;
+}
+
+sub getDescribedVariants {
+ my $self = shift;
+ # my($app) = @_;
+ $self->notImplemented();
+ # return [id, name, protocol, quality, type, encoding, charset, language, description, translator]*
+}
+
+# an undefined $id means "add me please"
+sub setVariant {
+ my $self = shift;
+ # my($app, $id, $name, $protocol, $quality, $type, $encoding, $charset, $language, $description, $translator) = @_;
+ $self->notImplemented();
+}
+
+sub setString {
+ my $self = shift;
+ # my($app, $variant, $string, $data) = @_;
+ # if $data = '' then delete the relevant string from the database
$self->notImplemented();
}
diff --git a/mozilla/webtools/PLIF/PLIF/DataSource/Strings/MySQL.pm b/mozilla/webtools/PLIF/PLIF/DataSource/Strings/MySQL.pm
index 068ad9a75fb..bf3d372465c 100644
--- a/mozilla/webtools/PLIF/PLIF/DataSource/Strings/MySQL.pm
+++ b/mozilla/webtools/PLIF/PLIF/DataSource/Strings/MySQL.pm
@@ -49,7 +49,68 @@ sub getVariants {
return $self->database($app)->execute('SELECT id, quality, type, encoding, charset, language FROM stringVariants WHERE protocol = ?', $protocol)->rows;
}
-# XXX setters would be nice too!
+sub getDescribedVariants {
+ my $self = shift;
+ my($app) = @_;
+ return $self->database($app)->execute('SELECT id, name, protocol, quality, type, encoding, charset, language, description, translator FROM stringVariants')->rows;
+}
+
+sub getVariant {
+ my $self = shift;
+ my($app, $id) = @_;
+ return $self->database($app)->execute('SELECT name, protocol, quality, type, encoding, charset, language, description, translator FROM stringVariants WHERE id = ?', $id)->row;
+}
+
+sub getVariantStrings {
+ my $self = shift;
+ my($app, $variant) = @_;
+ my %result = ();
+ foreach my $string ($self->database($app)->execute('SELECT name, data FROM strings WHERE variant = ?', $variant)->rows) {
+ $result{$string->[0]} = $string->[1];
+ }
+ return %result;
+}
+
+sub getStringVariants {
+ my $self = shift;
+ my($app, $string) = @_;
+ my @result = ();
+ foreach my $variant ($self->database($app)->execute('SELECT variant.name, variant.protocol, variant.quality, variant.type, variant.encoding, variant.charset, variant.language, variant.description, variant.translator, strings.data FROM stringVariants AS variant, strings WHERE strings.name = ? AND strings.variant = variant.name', $string)->rows) {
+ push(@result, {
+ 'name' => $variant->[0],
+ 'protocol' => $variant->[1],
+ 'quality' => $variant->[2],
+ 'type' => $variant->[3],
+ 'encoding' => $variant->[4],
+ 'charset' => $variant->[5],
+ 'language' => $variant->[6],
+ 'description' => $variant->[7],
+ 'translator' => $variant->[8];
+ 'string' => $variant->[9];
+ });
+ }
+ return @result;
+}
+
+sub setVariant {
+ my $self = shift;
+ my($app, $id, $name, $protocol, $quality, $type, $encoding, $charset, $language, $description, $translator) = @_;
+ if (defined($id)) {
+ $self->database($app)->execute('UPDATE stringVariants SET name=?, protocol=?, quality=?, type=?, encoding=?, charset=?, language=?, description=?, translator=? WHERE id = ?', $name, $protocol, $quality, $type, $encoding, $charset, $language, $description, $translator, $id);
+ } else {
+ return $self->database($app)->execute('INSERT INTO stringVariants SET name=?, protocol=?, quality=?, type=?, encoding=?, charset=?, language=?, description=?, translator=?', $name, $protocol, $quality, $type, $encoding, $charset, $language, $description, $translator)->MySQLID;
+ }
+}
+
+sub setString {
+ my $self = shift;
+ my($app, $variant, $string, $data) = @_;
+ if ((defined($data)) and (length($data) > 0)) {
+ $self->database($app)->execute('REPLACE INTO stringVariants SET variant=?, string=?, data=?', $variant, $string, $data);
+ } else {
+ $self->database($app)->execute('DELETE FROM stringVariants WHERE variant = ? AND string = ?', $variant, $string);
+ }
+}
sub setupInstall {
my $self = shift;
diff --git a/mozilla/webtools/PLIF/PLIF/DataSource/User/MySQL.pm b/mozilla/webtools/PLIF/PLIF/DataSource/User/MySQL.pm
index 4fad03c11db..67b03759975 100644
--- a/mozilla/webtools/PLIF/PLIF/DataSource/User/MySQL.pm
+++ b/mozilla/webtools/PLIF/PLIF/DataSource/User/MySQL.pm
@@ -110,7 +110,7 @@ sub setUser {
WHERE userID = ?', $mode, $password, $adminMessage, $newFieldID, $newFieldValue, $newFieldKey, $userID);
} else {
return $self->database($app)->execute('INSERT INTO user SET mode=?, password=?, adminMessage=?, newFieldID=?, newFieldValue=?, newFieldKey=?',
- $mode, $password, $adminMessage, $newFieldID, $newFieldValue, $newFieldKey)->ID;
+ $mode, $password, $adminMessage, $newFieldID, $newFieldValue, $newFieldKey)->MySQLID;
}
}
@@ -181,7 +181,7 @@ sub setField {
$category, $name, $type, $data, $mode, $fieldID);
} else {
return $self->database($app)->execute('INSERT INTO userDataTypes SET category=?, name=?, type=?, data=?, mode=?',
- $category, $name, $type, $data, $mode)->ID;
+ $category, $name, $type, $data, $mode)->MySQLID;
}
}
@@ -235,7 +235,7 @@ sub setGroup {
'Invalid arguments to DataSource::User::setGroup: \'groupID\' and \'groupName\' both undefined');
if (not defined($groupID)) {
# add a new record
- $groupID = $self->database($app)->execute('INSERT INTO groups SET name=?', $groupName)->ID;
+ $groupID = $self->database($app)->execute('INSERT INTO groups SET name=?', $groupName)->MySQLID;
} elsif (defined($groupName)) {
# replace the existing record
$self->database($app)->execute('UPDATE groups SET name=? WHERE groupID = ?', $groupName, $groupID);
@@ -264,7 +264,7 @@ sub addRight {
my $self = shift;
my($app, $name) = @_;
# only adds $name if it isn't there already, because name is a unique index
- my $rightID = $self->database($app)->execute('INSERT INTO rights SET name=?', $name)->ID;
+ my $rightID = $self->database($app)->execute('INSERT INTO rights SET name=?', $name)->MySQLID;
}
diff --git a/mozilla/webtools/PLIF/PLIF/Database/ResultsFrame/DBI.pm b/mozilla/webtools/PLIF/PLIF/Database/ResultsFrame/DBI.pm
index 389309141b5..9f00ee0d258 100644
--- a/mozilla/webtools/PLIF/PLIF/Database/ResultsFrame/DBI.pm
+++ b/mozilla/webtools/PLIF/PLIF/Database/ResultsFrame/DBI.pm
@@ -66,9 +66,10 @@ sub reexecute {
}
}
-sub ID {
+# This should only be used by MySQL-specific DBI data sources
+sub MySQLID {
my $self = shift;
- return $self->handle->database->{'mysql_insertid'}
+ return $self->handle->database->{'mysql_insertid'};
}
# other possible APIs:
diff --git a/mozilla/webtools/PLIF/PLIF/Output/Generic.pm b/mozilla/webtools/PLIF/PLIF/Output/Generic.pm
index 428a9adde19..31d945aae21 100644
--- a/mozilla/webtools/PLIF/PLIF/Output/Generic.pm
+++ b/mozilla/webtools/PLIF/PLIF/Output/Generic.pm
@@ -89,7 +89,7 @@ use PLIF::Output;
# changing the underlying code.
# To find the list of strings required, do this:
-# my %strings = @{$self->getCollectingServiceList('dispatcher.output')->strings};
+# my %strings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
sub protocol {
return 'generic';
diff --git a/mozilla/webtools/PLIF/PLIF/Service/Components/CosesEditor.pm b/mozilla/webtools/PLIF/PLIF/Service/Components/CosesEditor.pm
index d0b974a31f8..3dfe4bf0566 100644
--- a/mozilla/webtools/PLIF/PLIF/Service/Components/CosesEditor.pm
+++ b/mozilla/webtools/PLIF/PLIF/Service/Components/CosesEditor.pm
@@ -45,23 +45,224 @@ sub provides {
# dispatcher.commands
sub cmdCosesEditor {
+ # warning: this is also called from other methods below
my $self = shift;
my($app) = @_;
- $app->output->cosesEditor(0);
+ my %variants = $app->getService('dataSource.strings')->getDescribedVariants();
+ my $variantsSortColumn = $app->input->getArgument('cosesEditorVariantsSortColumn');
+ my %strings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
+ my $stringsSortColumn = $app->input->getArgument('cosesEditorStringsSortColumn');
+ my $user = $app->getObject('user');
+ if (defined($user)) {
+ # XXX have to register these settings
+ $user->setting(\$variantsSortColumn, 'cosesEditor.index.variantsSortColumn');
+ $user->setting(\$stringsSortColumn, 'cosesEditor.index.stringsSortColumn');
+ }
+ $app->output->cosesEditorIndex(\%variants, $variantsSortColumn, \%strings, $stringsSortColumn);
}
+# dispatcher.commands
+sub cmdCosesVariantAdd {
+ my $self = shift;
+ my($app) = @_;
+ my @data = ('', '', 1.0, '', '', '', '', '', '');
+ my $id = $app->getService('dataSource.strings')->setVariant($app, undef, @data);
+ my %expectedStrings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
+ $app->output->cosesEditorVariant($id, @data, \%expectedStrings, {});
+}
+
+# dispatcher.commands
+sub cmdCosesVariantEdit {
+ my $self = shift;
+ my($app) = @_;
+ my $id = $app->input->getArgument('cosesEditorVariantID');
+ my $dataSource = $app->getService('dataSource.strings');
+ my @data = $dataSource->getVariant($app, $id);
+ my %expectedStrings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
+ my %variantStrings = $dataSource->getVariantStrings($app, $id);
+ $app->output->cosesEditorVariant($id, @data, \%expectedStrings, \%variantStrings);
+}
+
+# dispatcher.commands
+sub cmdCosesVariantAddString {
+ my $self = shift;
+ my($app) = @_;
+ my %expectedStrings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
+ my($id, $data, $variantStrings) = $self->getVariantEditorArguments($app);
+ $app->output->cosesEditorVariant($id, @$data, \%expectedStrings, $variantStrings);
+}
+
+# dispatcher.commands
+sub cmdCosesVariantCommit {
+ my $self = shift;
+ my($app) = @_;
+ my($id, $data, $variantStrings) = $self->getVariantEditorArguments($app);
+ my $dataSource = $app->getService('dataSource.strings');
+ $dataSource->setVariant($app, $id, @$data);
+ foreach my $string (keys(%$variantStrings)) {
+ $dataSource->setString($app, $id, $string, $variantStrings->{$string});
+ }
+ $self->cmdCosesEditor($app);
+}
+
+# dispatcher.commands
+sub cmdCosesStringEdit {
+ my $self = shift;
+ my($app) = @_;
+ my $id = $app->input->getArgument('cosesEditorStringID');
+ my %strings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
+ my @variants = $app->getService('dataSource.strings')->getStringVariants($app, $id);
+ $app->output->cosesEditorString($id, $strings{$id}, \@variants);
+}
+
+# dispatcher.commands
+sub cmdCosesStringCommit {
+ my $self = shift;
+ my($app) = @_;
+ my $input = $app->input;
+ my $id = $input->getArgument('cosesEditorStringID');
+ my %variants = ();
+ my $index = 0;
+ while (defined(my $name = $input->getArgument('cosesEditorStringVariant${index}Name'))) {
+ $variants{$name} = $input->getArgument('cosesEditorStringVariant${index}Value');
+ $index += 1;
+ }
+ my $dataSource = $app->getService('dataSource.strings');
+ foreach my $variant (keys(%variants)) {
+ $dataSource->setString($app, $variant, $id, $variants{$variant});
+ }
+ $self->cmdCosesEditor($app);
+}
+
+# dispatcher.commands
+sub cmdCosesVariantExport {
+ my $self = shift;
+ my($app) = @_;
+
+ # get data
+ my $id = $app->input->getArgument('cosesEditorVariantID');
+ my $dataSource = $app->getService('dataSource.strings');
+ my @data = $dataSource->getVariant($app, $id);
+ my %strings = $dataSource->getVariantStrings($app, $id);
+
+ # serialise variant
+ my $XML = $app->getService('service.xml');
+ # note. This namespace is certainly not set in stone. Please make better suggestions. XXX
+ my $result = 'escape(shift(@data));
+ $result .= "\n $name=\"$value\"";
+ }
+ $result .= ">\n";
+ foreach my $string (keys(%strings)) {
+ my $name = $XML->escape($string);
+ my $value = $XML->escape($strings{$string});
+ $result.= " $value\n";
+ }
+ $result .= '';
+ $app->output->cosesExport($id, $result);
+}
+
+# dispatcher.commands
+sub cmdCosesVariantImport {
+ my $self = shift;
+ my($app) = @_;
+
+ # get data
+ my $file = $app->input->getArgument('cosesEditorImportData');
+
+ # parse data
+ my $XML = $app->getService('service.xml');
+ my $data = {
+ 'depth' => 0,
+ 'string' => undef,
+ 'variant' => [], # same at all scopes (because walkNesting() is not a deep copy)
+ 'strings' => {}, # same at all scopes (because walkNesting() is not a deep copy)
+ };
+ $XML->walk($self, $XML->parse($file), $data);
+
+ # use data
+ my $dataSource = $app->getService('dataSource.strings');
+ my $id = $dataSource->setVariant($app, undef, @{$data->{'variant'}});
+ foreach my $string (keys(%{$data->{'strings'}})) {
+ $dataSource->setString($app, $id, $string, $data->{'strings'}->{$string});
+ }
+
+ # display data
+ my %expectedStrings = @{$app->getCollectingServiceList('dispatcher.output')->strings};
+ $app->output->cosesEditorVariant($id, @{$data->{'variant'}}, \%expectedStrings, $data->{'strings'}->{$string});
+}
+
+# service.xml.sink
+sub walkElement {
+ my $self = shift;
+ my($tagName, $attributes, $tree, $data) = @_;
+ if ($tagName eq '{http://bugzilla.mozilla.org/variant/1}variant') {
+ if ($data->{'depth'} == 0) {
+ foreach my $name (qw(protocol quality type encoding charset language description translator)) {
+ if (exists($attributes->{$name})) {
+ push(@{$data->{'variant'}}, $attributes->{$name});
+ } else {
+ $self->error(1, "invalid variant document format - missing attribute '$name' on ");
+ }
+ }
+ } else {
+ $self->error(1, 'invalid variant document format - not root element');
+ }
+ } elsif ($tagName eq '{http://bugzilla.mozilla.org/variant/1}string') {
+ if ($data->{'depth'} == 1) {
+ if (exists($attributes->{'name'})) {
+ $data->{'string'} = $attributes->{'name'};
+ } else {
+ $self->error(1, 'invalid variant document format - missing attribute 'name' on ');
+ }
+ } else {
+ $self->error(1, 'invalid variant document format - not child of ');
+ }
+ } else {
+ $self->error(1, "invalid variant document format - unexpected tag <$tagName>");
+ }
+ $data->{'depth'} += 1;
+}
+
+# service.xml.sink
+sub walkText {
+ my $self = shift;
+ my($text, $data) = @_;
+ if (defined($data->{'string'})) {
+ $data->{'strings'}->{$data->{'string'}} = $text;
+ } elsif ($text !~ /^\w*$/o) {
+ $self->error(1, "invalid variant document format - unexpected text");
+ }
+}
+
+# service.xml.sink
+sub walkNesting {
+ my $self = shift;
+ my($data) = @_;
+ my %data = %$data; # copy first level of data hash
+ return \%data; # return reference to copy
+}
+
+
+# XXXXXX
+
# dispatcher.output.generic
sub outputCosesEditor {
my $self = shift;
- my($app, $output, $right) = @_;
+ my($app, $output, XXX) = @_;
$output->output('cosesEditor', {
});
}
+# dispatcher.output.generic
+# XXX
+
# dataSource.strings.default
sub getDefaultString {
my $self = shift;
my($app, $protocol, $string) = @_;
+ # XXX
if ($protocol eq 'stdout') {
if ($string eq 'cosesEditor') {
return 'COSES Editor
';
@@ -73,3 +274,29 @@ sub getDefaultString {
}
return; # nope, sorry
}
+
+
+
+# Internal Routines
+
+sub getVariantEditorArguments {
+ my $self = shift;
+ my($app) = @_;
+ my $input = $app->input;
+ my $id = $input->getArgument('cosesEditorVariantID');
+ my @data = ();
+ foreach my $argument (qw(name protocol quality type encoding charset language description translator)) {
+ push(@data, $input->getArgument('cosesEditorVariant\u$argument'));
+ }
+ my %variantStrings = ();
+ my $index = 0;
+ while (defined(my $name = $input->getArgument('cosesEditorVariantString${index}Name'))) {
+ $variantStrings{$name} = $input->getArgument('cosesEditorVariantString${index}Value');
+ $index += 1;
+ }
+ my $newName = $input->getArgument('cosesEditorVariantStringNewName');
+ if ((defined($newName)) and ($newName ne '')) {
+ $variantStrings{$newName} = $input->getArgument('cosesEditorVariantStringNewValue');
+ }
+ return ($id, \@data, \%variantStrings);
+}
diff --git a/mozilla/webtools/PLIF/PLIF/Service/Coses.pm b/mozilla/webtools/PLIF/PLIF/Service/Coses.pm
index ed91798f82a..69fb8bbde41 100644
--- a/mozilla/webtools/PLIF/PLIF/Service/Coses.pm
+++ b/mozilla/webtools/PLIF/PLIF/Service/Coses.pm
@@ -30,7 +30,6 @@ package PLIF::Service::Coses;
use strict;
use vars qw(@ISA);
use PLIF::Service;
-use XML::Parser; # DEPENDENCY
@ISA = qw(PLIF::Service);
1;
@@ -44,7 +43,7 @@ sub expand {
my $self = shift;
my($app, $session, $protocol, $string, $data) = @_;
my @index = (); my $index = 0;
- my @stack = (); my $stack = $self->parseString($self->getString($app, $session, $protocol, $string));
+ my @stack = (); my $stack = $app->getService('service.xml')->parseString($self->getString($app, $session, $protocol, $string));
my @scope = (); my $scope = {'data' => $data};
my $result = '';
if (not $scope->{'coses: skip sanitation'}) {
@@ -191,14 +190,6 @@ sub expand {
}
}
-sub parseString {
- my $self = shift;
- my($string) = @_;
- # parse string (it's an XML file)
- my $parser = new XML::Parser(Style => 'Tree');
- return $parser->parse($string);
-}
-
sub getString {
my $self = shift;
my($app, $session, $protocol, $string) = @_;
@@ -390,6 +381,8 @@ sub sort {
} elsif ($order eq 'reverse length') {
return sort { length($a) <=> length($a) } @list;
}
+ # XXX we need to also support:
+ # Sorting by a particular subkey of a hash to sort an array of hashes
}
# else:
return reverse @list;
diff --git a/mozilla/webtools/PLIF/PLIF/Service/User.pm b/mozilla/webtools/PLIF/PLIF/Service/User.pm
index b0d22a00dee..217ff83e544 100644
--- a/mozilla/webtools/PLIF/PLIF/Service/User.pm
+++ b/mozilla/webtools/PLIF/PLIF/Service/User.pm
@@ -221,6 +221,22 @@ sub resetAddressChange {
return defined($self->doAddressChange());
}
+# a convenience method for either setting a user setting from a new
+# value or getting the user's prefs
+sub setting {
+ my $self = shift;
+ my($variable, $setting) = @_;
+ $self->assert(ref($variable) eq 'SCALAR', 1, 'Internal Error: User object was expecting a scalar ref for setting() but didn\'t get one');
+ if (defined($$variable)) {
+ $self->getField('settings', $setting)->data($$variable);
+ } else {
+ my $field = $self->hasField('settings', $setting);
+ if (defined($field)) {
+ $$variable = $field->data;
+ }
+ }
+}
+
sub hash {
my $self = shift;
my $result = $self->SUPER::hash();