schema/mysql_build.pl # builds site/util/mysql.str
site/cgi-bin/admin/add.pl
site/cgi-bin/admin/admin.pl
+site/cgi-bin/admin/admin_seminar.pl
site/cgi-bin/admin/adminusers.pl
site/cgi-bin/affiliate.pl
site/cgi-bin/admin/changepw.pl
site/cgi-bin/modules/BSE/Edit/Base.pm
site/cgi-bin/modules/BSE/Edit/Catalog.pm
site/cgi-bin/modules/BSE/Edit/Product.pm
+site/cgi-bin/modules/BSE/Edit/Seminar.pm
site/cgi-bin/modules/BSE/Edit/Site.pm
site/cgi-bin/modules/BSE/EmailBlackEntry.pm
site/cgi-bin/modules/BSE/EmailBlacklist.pm
site/cgi-bin/modules/BSE/EmailRequest.pm
site/cgi-bin/modules/BSE/EmailRequests.pm
site/cgi-bin/modules/BSE/Formatter.pm
+site/cgi-bin/modules/BSE/Generate/Seminar.pm
# site/cgi-bin/modules/BSE/FileEditor.pm
site/cgi-bin/modules/BSE/Mail.pm
site/cgi-bin/modules/BSE/Mail/SMTP.pm
site/cgi-bin/modules/BSE/TB/AdminPerms.pm
site/cgi-bin/modules/BSE/TB/AdminUser.pm
site/cgi-bin/modules/BSE/TB/AdminUsers.pm
+site/cgi-bin/modules/BSE/TB/Location.pm
+site/cgi-bin/modules/BSE/TB/Locations.pm
site/cgi-bin/modules/BSE/TB/Order.pm
site/cgi-bin/modules/BSE/TB/Orders.pm
site/cgi-bin/modules/BSE/TB/OrderItem.pm
site/cgi-bin/modules/BSE/TB/OrderItems.pm
+site/cgi-bin/modules/BSE/TB/Seminar.pm
+site/cgi-bin/modules/BSE/TB/Seminars.pm
site/cgi-bin/modules/BSE/TB/Subscription.pm
site/cgi-bin/modules/BSE/TB/Subscription/Calc.pm
site/cgi-bin/modules/BSE/TB/Subscriptions.pm
site/cgi-bin/modules/BSE/Template.pm
site/cgi-bin/modules/BSE/Thumb/Imager.pm
site/cgi-bin/modules/BSE/UI/AdminDispatch.pm
+site/cgi-bin/modules/BSE/UI/AdminSeminar.pm
site/cgi-bin/modules/BSE/UI/Affiliate.pm
site/cgi-bin/modules/BSE/UI/Dispatch.pm
site/cgi-bin/modules/BSE/UI/Formmail.pm
site/cgi-bin/modules/BSE/Util/Secure.pm
site/cgi-bin/modules/BSE/Util/Tags.pm
site/cgi-bin/modules/BSE/Util/Valid.pm
+site/cgi-bin/modules/BSE/Validate.pm
site/cgi-bin/modules/BSE/Version.pm
site/cgi-bin/modules/BSE/WebUtil.pm
site/cgi-bin/modules/Constants.pm
# site/templates/admin/edit_5.tmpl
site/templates/admin/edit_catalog.tmpl
site/templates/admin/edit_product.tmpl
+site/templates/admin/edit_seminar.tmpl
site/templates/admin/edit_steps.tmpl
site/templates/admin/filelist.tmpl
site/templates/admin/grouplist.tmpl
site/templates/admin/menu_adv.tmpl
# site/templates/admin/menu_custom.tmpl
site/templates/admin/interestemail.tmpl
+site/templates/admin/locations/add.tmpl
+site/templates/admin/locations/delete.tmpl
+site/templates/admin/locations/edit.tmpl
+site/templates/admin/locations/list.tmpl
site/templates/admin/order_detail.tmpl
site/templates/admin/order_list.tmpl
site/templates/admin/order_list_filled.tmpl
summaryLength smallint(5) unsigned DEFAULT '200' NOT NULL,
-- the class whose generate() method generates the page
- generator varchar(20) not null default 'article',
+ generator varchar(40) not null default 'article',
-- the level of the article, 1 for top-level
level smallint not null,
-- order was completed by the customer
complete integer not null default 1,
+ delivOrganization varchar(127) not null default '',
+ billOrganization varchar(127) not null default '',
+
+ delivStreet2 varchar(127) not null default '',
+ billStreet2 varchar(127) not null default '',
+
primary key (id),
index order_cchash(ccNumberHash),
index order_userId(userId, orderDate)
delivMobile varchar(80) not null default '',
billMobile varchar(80) not null default '',
+ delivStreet2 varchar(127) not null default '',
+ billStreet2 varchar(127) not null default '',
+
+ billOrganization varchar(127) not null default '',
+
primary key (id),
unique (userId),
index (affiliate_name)
primary key(siteuser_id, image_id)
);
+drop table if exists bse_locations;
+create table bse_locations (
+ id integer not null auto_increment,
+ description varchar(255) not null,
+ room varchar(40) not null,
+ street1 varchar(255) not null,
+ street2 varchar(255) not null,
+ suburb varchar(255) not null,
+ state varchar(80) not null,
+ country varchar(80) not null,
+ postcode varchar(40) not null,
+ public_notes text not null,
+
+ bookings_name varchar(80) not null,
+ bookings_phone varchar(80) not null,
+ bookings_fax varchar(80) not null,
+ bookings_url varchar(255) not null,
+ facilities_name varchar(255) not null,
+ facilities_phone varchar(80) not null,
+
+ admin_notes text not null,
+
+ disabled integer not null default 0,
+
+ primary key(id)
+);
+
+drop table if exists bse_seminars;
+create table bse_seminars (
+ seminar_id integer not null primary key,
+ duration integer not null
+);
+
+drop table if exists bse_seminar_sessions;
+create table bse_seminar_sessions (
+ id integer not null auto_increment,
+ seminar_id integer not null,
+ location_id integer not null,
+ when_at datetime not null,
+
+ primary key (id),
+ unique (seminar_id, location_id, when_at),
+ index (seminar_id),
+ index (location_id)
+);
+
#!/usr/bin/perl -w
# -d:ptkdb
-#BEGIN { $ENV{DISPLAY} = '192.168.32.97:0.0' }
+#BEGIN { $ENV{DISPLAY} = '192.168.32.15:0.0' }
use strict;
use FindBin;
use CGI::Carp 'fatalsToBrowser';
--- /dev/null
+#!/usr/bin/perl -w
+# -d:ptkdb
+BEGIN { $ENV{DISPLAY} = '192.168.32.15:0.0' }
+use strict;
+use FindBin;
+use lib "$FindBin::Bin/../modules";
+use BSE::DB;
+use BSE::Request;
+use BSE::Template;
+use Carp 'confess';
+use BSE::UI::AdminSeminar;
+
+$SIG{__DIE__} = sub { confess $@ };
+
+my $req = BSE::Request->new;
+
+my $result = BSE::UI::AdminSeminar->dispatch($req);
+BSE::Template->output_result($req, $result);
Orders => 'select * from orders',
getOrderByPkey => 'select * from orders where id = ?',
getOrderItemByOrderId => 'select * from order_item where orderId = ?',
- addOrder => 'insert orders values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
- replaceOrder => 'replace orders values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+ addOrder => 'insert orders values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+ replaceOrder => 'replace orders values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
addOrderItem => 'insert order_item values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
getOrderByUserId => 'select * from orders where userId = ?',
deleteOrdersItems => 'delete from order_item where orderId = ?',
'select * from site_users where id = ?',
getSiteUserByAffiliate_name =>
'select * from site_users where affiliate_name = ?',
- addSiteUser => 'insert site_users values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
- replaceSiteUser => 'replace site_users values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+ addSiteUser => 'insert site_users values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+ replaceSiteUser => 'replace site_users values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
'SiteUsers.removeSubscriptions'=>
'delete from subscribed_users where userId = ?',
'SiteUsers.removeSub'=>
where us.siteuser_id = ? and us.subscription_id = su.subscription_id
and us.ends_at >= curdate()
SQL
+
+ addLocation => <<SQL,
+insert bse_locations values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
+SQL
+ replaceLocation => <<SQL,
+replace bse_locations values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
+SQL
+ getLocationByPkey => 'select * from bse_locations where id = ?',
+ deleteLocation => 'delete from bse_locations where id = ?',
+ Locations => 'select * from bse_locations order by description',
+
+ Seminars => <<SQL,
+select ar.*, pr.*, se.*
+ from article ar, product pr, bse_seminars se
+ where ar.id = pr.articleId and ar.id = se.articleId
+SQL
+ addSeminar => 'insert bse_seminars values(?,?)',
+ replaceSeminar => 'replace bse_seminars values(?,?)',
+ getSeminarByPkey => <<SQL,
+select ar.*, pr.*, se.*
+ from article ar, product pr, bse_seminars se
+ where id = ? and ar.id = pr.articleId and ar.id = se.seminar_id
+SQL
);
sub _single
or $data{$col} = $self->default_value($req, \%data, $col);
}
+ print STDERR "release cgi ", $cgi->param('release'), " data $data{release}\n";
# these columns are handled a little differently
for my $col (qw(release expire threshold summaryLength )) {
$data{$col}
or $data{$col} = $self->default_value($req, \%data, $col);
}
+ for my $col (qw(release expire)) {
+ $data{$col} = sql_date($data{$col});
+ }
+
shift @columns;
my $article = $table_object->add(@data{@columns});
}
sub child_types {
- return qw(BSE::Edit::Product BSE::Edit::Catalog);
+ return qw(BSE::Edit::Product BSE::Edit::Seminar BSE::Edit::Catalog);
}
sub default_template {
--- /dev/null
+package BSE::Edit::Seminar;
+use strict;
+use base 'BSE::Edit::Product';
+use BSE::TB::Seminars;
+use BSE::Util::Tags qw(tag_hash tag_hash_mbcs);
+
+sub base_template_dirs {
+ return ( "seminar" );
+}
+
+sub edit_template {
+ my ($self, $article, $cgi) = @_;
+
+ my $base = 'seminar';
+ my $t = $cgi->param('_t');
+ if ($t && $t =~ /^\w+$/) {
+ $base = $t;
+ }
+ return $self->{cfg}->entry('admin templates', $base,
+ "admin/edit_$base");
+}
+
+sub generator { "BSE::Generate::Seminar" }
+
+sub default_template {
+ my ($self, $article, $cfg, $templates) = @_;
+
+ my $template = $cfg->entry('seminars', 'template');
+ return $template
+ if $template && grep $_ eq $template, @$templates;
+
+ return $self->SUPER::default_template($article, $cfg, $templates);
+}
+
+sub flag_sections {
+ my ($self) = @_;
+
+ return ( 'seminar flags', $self->SUPER::flag_sections );
+}
+
+sub type_default_value {
+ my ($self, $req, $col) = @_;
+
+ my $value = $req->cfg->entry('seminar defaults', $col);
+ defined $value and return $value;
+
+ return $self->SUPER::type_default_value($req, $col);
+}
+
+sub add_template {
+ my ($self, $article, $cgi) = @_;
+
+ return $self->{cfg}->entry('admin templates', 'add_seminar',
+ 'admin/edit_seminar');
+}
+
+sub table_object {
+ my ($self, $articles) = @_;
+
+ 'BSE::TB::Seminars';
+}
+
+sub low_edit_tags {
+ my ($self, $acts, $req, $article, $articles, $msg, $errors) = @_;
+
+ my $cfg = $req->cfg;
+ my $mbcs = $cfg->entry('html', 'mbcs', 0);
+ my $tag_hash = $mbcs ? \&tag_hash_mbcs : \&tag_hash;
+ my $it = BSE::Util::Iterate->new;
+ return
+ (
+ seminar => [ $tag_hash, $article ],
+ $self->SUPER::low_edit_tags($acts, $req, $article, $articles, $msg,
+ $errors),
+ );
+}
+
+sub get_article {
+ my ($self, $articles, $article) = @_;
+
+ return BSE::TB::Seminars->getByPkey($article->{id});
+}
+
+my %defaults =
+ (
+ duration => 60,
+ );
+
+sub default_value {
+ my ($self, $req, $article, $col) = @_;
+
+ my $value = $self->SUPER::default_value($req, $article, $col);
+ defined $value and return $value;
+
+ exists $defaults{$col} and return $defaults{$col};
+
+ return;
+}
+
+sub _fill_seminar_data {
+ my ($self, $req, $data, $src) = @_;
+
+ if (exists $src->{duration}) {
+ $data->{duration} = $src->{duration};
+ }
+}
+
+sub fill_new_data {
+ my ($self, $req, $data, $articles) = @_;
+
+ $self->_fill_seminar_data($req, $data, $data);
+
+ return $self->SUPER::fill_new_data($req, $data, $articles);
+}
+
+sub fill_old_data {
+ my ($self, $req, $article, $src) = @_;
+
+ $self->_fill_seminar_data($req, $article, $src);
+
+ return $self->SUPER::fill_old_data($req, $article, $src);
+}
+
+sub _validate_common {
+ my ($self, $data, $articles, $errors) = @_;
+
+ my $duration = $data->{duration};
+ if (defined $duration && $duration !~ /^\d+\s*$/) {
+ $errors->{duration} = "Duration invalid";
+ }
+
+ return $self->SUPER::_validate_common($data, $articles, $errors);
+}
+
+1;
+
--- /dev/null
+package BSE::Generate::Seminar;
+use strict;
+use base 'Generate::Product';
+use BSE::TB::Seminars;
+use DevHelp::HTML;
+use BSE::Util::Tags qw(tag_hash);
+
+sub baseActs {
+ my ($self, $articles, $acts, $seminar, $embedded) = @_;
+
+ unless ($seminar->isa('BSE::TB::Seminar')) {
+ $seminar = BSE::TB::Seminars->getByPkey($seminar->{id});
+ }
+ return
+ (
+ $self->SUPER::baseActs($articles, $acts, $seminar, $embedded),
+ seminar => [ \&tag_hash, $seminar ],
+ admin => [ tag_admin => $self, $seminar, 'seminar', $embedded ],
+ );
+}
+
+1;
}
return BSE::Template->get_response($template, $req->cfg, $acts,
- $base_template);
+ $base_template);
}
sub response {
}
}
+sub validate {
+ my ($req, %options) = @_;
+
+ $options{rules} ||= {};
+
+ require BSE::Validate;
+ BSE::Validate::bse_validate($req->cgi, $options{errors},
+ {
+ fields => $options{fields},
+ rules => $options{rules},
+ },
+ $req->cfg, $options{section});
+}
+
+sub validate_hash {
+ my ($req, %options) = @_;
+
+ $options{rules} ||= {};
+
+ require BSE::Validate;
+ BSE::Validate::bse_validate_hash($options{data}, $options{errors},
+ {
+ fields=>$options{fields},
+ rules => $options{rules},
+ },
+ $req->cfg, $options{section});
+}
+
+sub configure_fields {
+ my ($self, $fields, $section) = @_;
+
+ my $cfg = $self->cfg;
+ require BSE::Validate;
+ BSE::Validate::bse_configure_fields($fields, $cfg, $section);
+
+ for my $name (keys %$fields) {
+ for my $cfg_name (qw/htmltype type width height size maxlength/) {
+ my $value = $cfg->entry($section, "${name}_${cfg_name}");
+ defined $value and $fields->{$name}{$cfg_name} = $value;
+ }
+ }
+}
+
sub DESTROY {
my ($self) = @_;
if ($self->{session}) {
--- /dev/null
+package BSE::TB::Location;
+use strict;
+use base qw(Squirrel::Row);
+
+sub columns {
+ return qw/id
+ description
+ room street1 street2 suburb state country postcode
+ public_notes
+ bookings_name bookings_phone bookings_fax bookings_url
+ facilities_name facilities_phone
+ admin_notes disabled/;
+}
+
+sub valid_fields {
+ return
+ (
+ description => { description => "Description",
+ rules => 'required', maxlength=>255, width=>60 },
+ room => { description => 'Room', maxlength=>40, width=>20 },
+ street1 => { description => 'Street Address 1', required => 1,
+ maxlength=>255, width=>50 },
+ street2 => { description => 'Street Address 2',
+ maxlength=>255, width=>50 },
+ suburb => { description => 'Suburb', required => 1,
+ maxlength=>255, width=>50 },
+ state => { description => 'State', required => 1,
+ maxlength=>80, width=>15 },
+ country => { description => 'Country', maxlength=>80 },
+ postcode => { description => 'Post Code',
+ rules => 'postcode',
+ required => 1, maxlength=>40, width=>5 },
+ public_notes => { description => 'Notes', width=>60, height=>10 },
+ bookings_name => { description => 'Bookings Contact Name',
+ maxlength=>80, width=>50 },
+ bookings_phone => { description => 'Bookings Contact Phone',
+ rules => 'phone',
+ maxlength=>80, width=>30 },
+ bookings_fax => { description => 'Bookings Contact Fax',
+ rules => 'phone',
+ maxlength=>80, width=>30 },
+ bookings_url => { description => 'Bookings URL',
+ rules => 'weburl',
+ maxlength=>255, width=>60 },
+ facilities_name => { description => 'Facilities Contact Name',
+ maxlength=>255, width=>60 },
+ facilities_phone => { description => 'Facilities Contact Phone',
+ rules => 'phone',
+ maxlength=>80, width=>30 },
+ admin_notes => { description => 'Administration Notes',
+ width=>60, height=>10},
+ );
+}
+
+sub valid_rules {
+ # no rules yet
+ return;
+}
+
+sub is_removable {
+ my ($self) = @_;
+
+ return 1; # this will change
+}
+
+1;
--- /dev/null
+package BSE::TB::Locations;
+use strict;
+use Squirrel::Table;
+use vars qw(@ISA $VERSION);
+@ISA = qw(Squirrel::Table);
+use BSE::TB::Location;
+
+sub rowClass {
+ return 'BSE::TB::Location';
+}
+
+1;
siteuser_id affiliate_code shipping_cost
delivMobile billMobile
ccOnline ccSuccess ccReceipt ccStatus ccStatusText
- ccStatus2 ccTranId complete/;
+ ccStatus2 ccTranId complete delivOrganization billOrganization
+ delivStreet2 billStreet2/;
}
=item siteuser
my %fields =
(
- delivFirstName => { description=>'Delivery First Name', },
- delivLastName => { description => 'Delivery Last Name' },
- delivStreet => { description => 'Delivery Street' },
- delivState => { description => 'Delivery State' },
- delivSuburb => { description => 'Delivery Suburb' },
- delivPostCode => { description => 'Delivery Post Code' },
- delivCountry => { description => 'Delivery Country' },
- billFirstName => { description => 'Billing First Name' },
- billLastName => { description => 'Billing Last Name' },
- billStreet => { description => 'Billing First Name' },
- billSuburb => { description => 'Billing First Name' },
- billState => { description => 'Billing First Name' },
- billPostCode => { description => 'Billing First Name' },
- billCountry => { description => 'Billing First Name' },
+ delivFirstName => { description=>'Delivery First Name',
+ rules=>'dh_one_line' },
+ delivLastName => { description => 'Delivery Last Name',
+ rules=>'dh_one_line' },
+ delivOrganization => { description => 'Delivery Organization',
+ rules=>'dh_one_line' },
+ delivStreet => { description => 'Delivery Street',
+ rules=>'dh_one_line' },
+ delivStreet2 => { description => 'Delivery Street 2',
+ rules=>'dh_one_line' },
+ delivState => { description => 'Delivery State',
+ rules=>'dh_one_line' },
+ delivSuburb => { description => 'Delivery Suburb',
+ rules=>'dh_one_line' },
+ delivPostCode => { description => 'Delivery Post Code',
+ rules=>'dh_one_line;postcode' },
+ delivCountry => { description => 'Delivery Country',
+ rules=>'dh_one_line' },
+ billFirstName => { description => 'Billing First Name',
+ rules=>'dh_one_line' },
+ billLastName => { description => 'Billing Last Name',
+ rules=>'dh_one_line' },
+ billOrganization => { description => 'Billing Organization',
+ rules=>'dh_one_line' },
+ billStreet => { description => 'Billing Street',
+ rules=>'dh_one_line' },
+ billStreet2 => { description => 'Billing Street 2',
+ rules=>'dh_one_line' },
+ billSuburb => { description => 'Billing Suburb',
+ rules=>'dh_one_line' },
+ billState => { description => 'Billing State',
+ rules=>'dh_one_line' },
+ billPostCode => { description => 'Billing Post Code',
+ rules=>'dh_one_line;postcode' },
+ billCountry => { description => 'Billing First Name',
+ rules=>'dh_one_line' },
telephone => { description => 'Telephone Number',
rules => "phone" },
facsimile => { description => 'Facsimile Number',
--- /dev/null
+package BSE::TB::Seminar;
+use strict;
+# represents a seminar from the database
+use Product;
+use vars qw/@ISA/;
+@ISA = qw/Product/;
+
+# subscription_usage values
+use constant SUBUSAGE_START_ONLY => 1;
+use constant SUBUSAGE_RENEW_ONLY => 2;
+use constant SUBUSAGE_EITHER => 3;
+
+sub columns {
+ return ($_[0]->SUPER::columns(),
+ qw/seminar_id duration/ );
+}
+
+sub bases {
+ return { seminar_id=>{ class=>'Product'} };
+}
+
+1;
--- /dev/null
+package BSE::TB::Seminars;
+use strict;
+use Squirrel::Table;
+use vars qw(@ISA $VERSION);
+@ISA = qw(Squirrel::Table);
+use BSE::TB::Seminar;
+
+sub rowClass {
+ return 'BSE::TB::Seminar';
+}
+
+1;
--- /dev/null
+package BSE::UI::AdminSeminar;
+use strict;
+use base qw(BSE::UI::AdminDispatch);
+use BSE::Util::Tags qw(tag_hash tag_error_img);
+use BSE::Util::DynSort qw(sorter tag_sorthelp);
+use BSE::Template;
+use BSE::Util::Iterate;
+use BSE::TB::Locations;
+use DevHelp::HTML;
+use constant SECT_LOCATION_VALIDATION => "BSE Location Validation";
+
+my %rights =
+ (
+ loclist => 'bse_location_list',
+ locaddform => 'bse_location_add',
+ locadd => 'bse_location_add',
+ locedit => 'bse_location_edit',
+ locsave => 'bse_location_edit',
+ locdelask => 'bse_location_delete',
+ locdelete => 'bse_location_delete',
+# detail => 'bse_subscr_detail',
+# update => 'bse_subscr_update',
+ );
+
+sub actions { \%rights }
+
+sub rights { \%rights }
+
+sub default_action { 'loclist' }
+
+sub req_loclist {
+ my ($class, $req, $errors) = @_;
+
+ my $msg = $req->message($errors);
+ my $cgi = $req->cgi;
+ my @locations = BSE::TB::Locations->all;
+ my ($sortby, $reverse) =
+ sorter(data=>\@locations, cgi=>$cgi, sortby=>'description',
+ session=>$req->session,
+ name=>'locations', fields=> { id => {numeric => 1 } });
+ my $it = BSE::Util::Iterate->new;
+ my $current_loc;
+
+ my %acts;
+ %acts =
+ (
+ BSE::Util::Tags->basic(\%acts, $req->cgi, $req->cfg),
+ BSE::Util::Tags->admin(\%acts, $req->cfg),
+ BSE::Util::Tags->secure($req),
+ msg => $msg,
+ message => $msg,
+ $it->make_paged_iterator('ilocation', 'locations', \@locations, undef,
+ $cgi, undef, 'pp=20', $req->session,
+ 'locations', \$current_loc),
+ sorthelp => [ \&tag_sorthelp, $sortby, $reverse ],
+ sortby=>$sortby,
+ reverse=>$reverse,
+ ifRemovable => [ \&tag_ifRemovable, \$current_loc ],
+ );
+
+ return $req->dyn_response('admin/locations/list', \%acts);
+}
+
+sub tag_ifRemovable {
+ my ($rlocation) = @_;
+
+ $$rlocation or return;
+
+ $$rlocation->is_removable;
+}
+
+sub tag_field {
+ my ($fields, $args) = @_;
+
+ my ($name, $parm) = split ' ', $args;
+
+ exists $fields->{$name}
+ or return "** Unknown field $name **";
+ exists $fields->{$name}{$parm}
+ or return '';
+
+ return escape_html($fields->{$name}{$parm});
+}
+
+sub req_locaddform {
+ my ($class, $req, $errors) = @_;
+
+ my $msg = $req->message($errors);
+
+ my %fields = BSE::TB::Location->valid_fields();
+ $req->configure_fields(\%fields, SECT_LOCATION_VALIDATION);
+
+ my %acts;
+ %acts =
+ (
+ BSE::Util::Tags->basic(\%acts, $req->cgi, $req->cfg),
+ BSE::Util::Tags->admin(\%acts, $req->cfg),
+ BSE::Util::Tags->secure($req),
+ msg => $msg,
+ message => $msg,
+ error_img => [ \&tag_error_img, $req->cfg, $errors ],
+ field => [ \&tag_field, \%fields ],
+ );
+
+ return $req->dyn_response('admin/locations/add', \%acts);
+}
+
+sub req_locadd {
+ my ($class, $req) = @_;
+
+ my $cgi = $req->cgi;
+ my $cfg = $req->cfg;
+ my %fields = BSE::TB::Location->valid_fields($cfg);
+ my %rules = BSE::TB::Location->valid_rules($cfg);
+ my %errors;
+ $req->validate(errors=> \%errors,
+ fields=> \%fields,
+ rules => \%rules,
+ section => SECT_LOCATION_VALIDATION);
+
+ keys %errors
+ and return $class->req_locaddform($req, \%errors);
+
+ my %location;
+ for my $field (keys %fields) {
+ $location{$field} = $cgi->param($field);
+ }
+ $location{disabled} = 0;
+ my @cols = BSE::TB::Location->columns;
+ shift @cols;
+ my $loc = BSE::TB::Locations->add(@location{@cols});
+
+ my $r = $class->_loclist_refresh($req, "Location $location{description} added");
+
+ return BSE::Template->get_refresh($r, $req->cfg);
+}
+
+sub _loc_show_common {
+ my ($class, $req, $errors, $template) = @_;
+
+ my $loc_id = $req->cgi->param('id');
+ $loc_id && $loc_id =~ /^\d+/
+ or return $class->req_loclist
+ ($req, { id=>'Missing or invalid location id' });
+ my $location = BSE::TB::Locations->getByPkey($loc_id);
+ $location
+ or return $class->req_loclist
+ ($req, { id=>'Unknown location id' });
+
+ my $msg = $req->message($errors);
+
+ my %fields = BSE::TB::Location->valid_fields();
+ $req->configure_fields(\%fields, SECT_LOCATION_VALIDATION);
+
+ my %acts;
+ %acts =
+ (
+ BSE::Util::Tags->basic(\%acts, $req->cgi, $req->cfg),
+ BSE::Util::Tags->admin(\%acts, $req->cfg),
+ BSE::Util::Tags->secure($req),
+ msg => $msg,
+ message => $msg,
+ error_img => [ \&tag_error_img, $req->cfg, $errors ],
+ location => [ \&tag_hash, $location ],
+ field => [ \&tag_field, \%fields ],
+ );
+
+ return $req->dyn_response($template, \%acts);
+}
+
+sub req_locedit {
+ my ($class, $req, $errors) = @_;
+
+ return $class->_loc_show_common($req, $errors, 'admin/locations/edit');
+}
+
+sub req_locsave {
+ my ($class, $req) = @_;
+
+ my $loc_id = $req->cgi->param('id');
+ $loc_id && $loc_id =~ /^\d+/
+ or return $class->req_loclist
+ ($req, { id=>'Missing or invalid location id' });
+ my $location = BSE::TB::Locations->getByPkey($loc_id);
+ $location
+ or return $class->req_loclist
+ ($req, { id=>'Unknown location id' });
+
+ my $cgi = $req->cgi;
+ my $cfg = $req->cfg;
+ my %fields = $location->valid_fields($cfg);
+ my %rules = $location->valid_rules($cfg);
+ my %errors;
+ $req->validate(errors=> \%errors,
+ fields=> \%fields,
+ rules => \%rules,
+ section => SECT_LOCATION_VALIDATION);
+
+ keys %errors
+ and return $class->req_locedit($req, \%errors);
+
+ for my $field (keys %fields) {
+ my $value = $cgi->param($field);
+ $location->{$field} = $value if defined $value;
+ }
+
+ if ($cgi->param('save_disabled')) {
+ $location->{disabled} = $cgi->param('disabled') ? 1 : 0;
+ }
+
+ $location->save;
+
+ my $r = $class->_loclist_refresh($req,
+ "Location $location->{description} saved");
+
+ return BSE::Template->get_refresh($r, $req->cfg);
+}
+
+sub req_locdelask {
+ my ($class, $req, $errors) = @_;
+
+ return $class->_loc_show_common($req, $errors, 'admin/locations/delete');
+}
+
+sub req_locdelete {
+ my ($class, $req) = @_;
+
+ my $loc_id = $req->cgi->param('id');
+ $loc_id && $loc_id =~ /^\d+/
+ or return $class->req_loclist
+ ($req, { id=>'Missing or invalid location id' });
+ my $location = BSE::TB::Locations->getByPkey($loc_id);
+ $location
+ or return $class->req_loclist
+ ($req, { id=>'Unknown location id' });
+
+ $location->is_removable
+ or return $class->req_loclist
+ ($req, { id=>"Location $location->{description} cannot be removed" });
+
+ my $description = $location->{description};
+ $location->remove;
+
+ my $r = $class->_loclist_refresh($req,
+ "Location $description removed");
+
+ return BSE::Template->get_refresh($r, $req->cfg);
+}
+
+sub _loclist_refresh {
+ my ($class, $req, $msg) = @_;
+
+ my $r = $req->cgi->param('r') || $req->cgi->param('refreshto');
+ unless ($r) {
+ $r = "/cgi-bin/admin/admin_seminar.pl";
+ }
+ if ($msg && $r !~ /[&?]m=/) {
+ my $sep = $r =~ /\?/ ? '&' : '?';
+
+ $r .= $sep . "m=" . escape_uri($msg);
+ }
+
+ return $r;
+}
+
+1;
name1 => 'delivFirstName',
name2 => 'delivLastName',
address => 'delivStreet',
+ organization => 'delivOrganization',
city => 'delivSuburb',
postcode => 'delivPostCode',
state => 'delivState',
my $sub = $product->subscription;
if ($product->is_renew_sub_only) {
unless ($user->subscribed_to_grace($sub)) {
- return show_cart("This product can only be used to renew your subscription to $sub->{title} and you are not subscribed nor within the renewal grace period");
+ return $class->req_cart($req, "This product can only be used to renew your subscription to $sub->{title} and you are not subscribed nor within the renewal grace period");
}
}
elsif ($product->is_start_sub_only) {
if ($user->subscribed_to_grace($sub)) {
- return show_cart("This product can only be used to start your subscription to $sub->{title} and you are already subscribed or within the grace period");
+ return $class->req_cart($req, "This product can only be used to start your subscription to $sub->{title} and you are already subscribed or within the grace period");
}
}
}
use DevHelp::Tags;
use DevHelp::HTML qw(:default escape_xml);
use vars qw(@EXPORT_OK @ISA);
-@EXPORT_OK = qw(tag_error_img tag_hash tag_hash_plain);
+@EXPORT_OK = qw(tag_error_img tag_hash tag_hash_plain tag_hash_mbcs);
@ISA = qw(Exporter);
require Exporter;
$hour = $min = $sec = 0 unless defined $sec;
$year -= 1900;
--$month;
- return POSIX::strftime($fmt, $sec, $min, $hour, $day, $month, $year);
+ # passing the isdst as 0 seems to provide a more accurate result than
+ # -1 on glibc.
+ return POSIX::strftime($fmt, $sec, $min, $hour, $day, $month, $year, -1, -1, 0);
+ # the following breaks some of our defaults
+# # pass the time through mktime() since the perl strftime()
+# # doesn't actually do it.
+# my $time = POSIX::mktime($sec, $min, $hour, $day, $month, $year);
+# return POSIX::strftime($fmt, localtime $time);
},
today => \&tag_today,
money =>
my $value = $hash->{$args};
defined $value or $value = '';
+ if ($value =~ /\cJ/ && $value =~ /\cM/) {
+ $value =~ tr/\cM//d;
+ }
escape_html($value);
}
+sub tag_hash_mbcs {
+ my ($object, $args) = @_;
+
+ my $value = $object->{$args};
+ defined $value or $value = '';
+ if ($value =~ /\cJ/ && $value =~ /\cM/) {
+ $value =~ tr/\cM//d;
+ }
+ escape_html($value, '<>&"');
+}
+
sub tag_hash_plain {
my ($hash, $args) = @_;
--- /dev/null
+package BSE::Validate;
+use strict;
+use base 'DevHelp::Validate';
+use DevHelp::Validate qw(dh_validate dh_validate_hash dh_configure_fields);
+use vars qw(@EXPORT @EXPORT_OK);
+@EXPORT = ();
+@EXPORT_OK = qw(bse_validate bse_validate_hash bse_configure_fields);
+
+sub bse_validate {
+ return dh_validate(@_);
+}
+
+sub bse_validate_hash {
+ return dh_validate_hash(@_);
+}
+
+sub bse_configure_fields {
+ return dh_configure_fields(@_);
+}
+
+1;
+
+=head1 NAME
+
+BSE::Validate - intended for future BSE specific expansion of
+DevHelp::Validate.
+
+=head1 SYNOPSIS
+
+ $req->validate(fields=>$fields, rules=>$rules, errors=>\%errors);
+ $req->validate_hash(fields=>$fields, rules=>$rules, errors=>\%errors,
+ data=>\%hash)
+
+=head1 DESCRIPTION
+
+
+
+=cut
and next TRY;
$part =~ s#style\[([^\]\[\|]+)\|([^\]\[]+)\]#$2#ig
and next TRY;
+ $part =~ s!(?<=\W)\[([^\]\[]+)\]!\x01$1\x02!g
+ and next TRY;
last TRY;
}
+ $part =~ tr/\x01\x02/[]/; # put back the bare []
$out .= $part;
}
}
my @stepprods = $article->visible_stepkids;
my $stepprod_index;
my @allkids = $article->all_visible_kids;
- require 'Generate/Product.pm';
+ # make sure we have all of the inheritance info
+ my %generate = map { $_->{generator} => 1 } @allkids;
+ for my $gen (keys %generate) {
+ (my $file = $gen . ".pm") =~ s!::!/!g;
+ require $file;
+ }
my @allprods = grep UNIVERSAL::isa($_->{generator}, 'Generate::Product'),
@allkids;
for (@allprods) {
billEmail adminNotes disabled flags
customText1 customText2 customText3
customStr1 customStr2 customStr3
- affiliate_name delivMobile billMobile/;
+ affiliate_name delivMobile billMobile
+ delivStreet2 billStreet2
+ billOrganization/;
}
sub valid_fields {
maxlen=>127 },
delivMobile => { description => "Mobile", rules=>"phone",
maxlen => 80 },
+ delivStreet2 => { description => 'Address2', rules => "dh_one_line",
+ maxlen=> 127 },
textOnlyEmail => { description => "Text Only Email", type=>"boolean" },
referral => { description=>'Referral', rules=>"natural" },
otherReferral => { description=>'Other Referral', rules=>"dh_one_line",
billLastName => { descriptin=>"Billing Last Name", rules=>"dh_one_line" },
billStreet => { description => "Billing Street Address",
rules=>"dh_one_line", maxlen=>127 },
+ billStreet2 => { description => 'Billing Street Address 2',
+ rules => "dh_one_line", maxlen=> 127 },
billSuburb => { description => "Billing Suburb", rules=>"dh_one_line",
maxlen=>127 },
billState => { description => "Billing State", rules=>"dh_one_line",
maxlen=>255 },
billMobile => { description => "Billing Mobile", rules=>"phone",
maxlen => 80 },
+ billOrganization => { description => "Billing Organization",
+ rules=>"dh_one_line", maxlen => 127 },
customText1 => { description => "Custom Text 1" },
customText2 => { description => "Custom Text 2" },
customText3 => { description => "Custom Text 3" },
unless (defined $self->{$primary[0]}) {
my $bases = $class->bases;
if (keys %$bases) {
- keys %$bases == 1
- or confess "I don't know how to handle more than one base for $class";
- my ($my_col) = keys %$bases;
- my $base_class = $bases->{$my_col}{class};
+ my @bases = $class->_get_bases;
+ my $base_base = $bases[0];
+ my $base_class = $base_base->[1];
my $sth = $dh->stmt("add$base_class")
or confess "No add$base_class member in DatabaseHandle";
-
+
# extract the base class columns
my @base_cols = $base_class->columns;
my %data;
@data{$class->columns} = @values;
$sth->execute(@data{@base_cols[1..$#base_cols]})
or confess "Could not add $class/$base_class(undef, @data{@base_cols[1..$#base_cols]} )";
- $self->{$primary[0]} = $self->{$my_col} =
- $data{$my_col} = $data{$primary[0]} = $dh->insert_id($sth);
-
- # now do this class
- # what do we store
- my %saved;
- @saved{@base_cols} = @base_cols;
- delete $saved{$my_col}; # make sure we save this
- my @save_cols = grep !$saved{$_}, @columns;
- $sth = $dh->stmt("add$class")
- or confess "No add$class member in DatabaseHandle";
- $sth->execute(@data{@save_cols})
- or confess "Could not add $class(@data{1..$#save_cols})";
+ my $primary_value = $dh->insert_id($sth);
+
+ $self->{$primary[0]} = $primary_value;
+ my $used_cols = @base_cols;
+
+ # now do the derived classes and ourselves
+ for my $derived (@bases) {
+ my ($my_col, $base_class, $parent_class) = @$derived;
+
+ $self->{$my_col} = $primary_value;
+
+ my @cols = $parent_class->columns;
+ splice(@cols, 0, $used_cols); # strip base column names
+ $used_cols += @cols;
+
+ $sth = $dh->stmt("add$parent_class")
+ or confess "No add$parent_class member in DatabaseHandle";
+ $sth->execute(@$self{@cols})
+ or confess "Could not add $parent_class(@$self{@cols})";
+ }
}
else {
my $sth = $dh->stmt("add$class")
confess "Undefined primary key fields in ${class}::new"
if grep !defined, @$self{@primary};
- my $foreign = $self->foreign;
- for my $key (keys %$foreign) {
- my $module = $foreign->{$key}{module};
- my $version = $foreign->{$key}{version};
-
- next unless defined $module;
-
- next if !defined($self->{$key}) && exists $foreign->{$key}{null};
-
- require $module.'.pm';
-
- $module->VERSION($version) if defined $version;
-
- my $mod = $module->new;
-
- confess "Bad FK field $class($key) ($self->{$key})"
- unless $self->{$key} = $mod->getByPkey($self->{$key});
- }
-
$self->{pkey} = join("", @$self{@primary});
$self->{changed} = 0;
my %saved;
my $bases = $self->bases;
if (keys %$bases) {
- # save to the bases
- # this should probably recurse at some point
- for my $base_key (keys %$bases) {
- # we have bases, update them
- my $base_class = $bases->{$base_key}{class};
- my @base_cols = $base_class->columns;
- my $sth = $dh->stmt('replace'.$base_class)
- or confess "No replace$base_class member in DatabaseHandle";
- my @data;
- for my $col (@base_cols) {
- push(@data, ref $self->{$col} ? $self->{$col}{pkey} : $self->{$col});
- ++$saved{$col};
- }
- $sth->execute(@data)
- or confess "Cannot save $base_class part of ",ref $self,":",
- $sth->errstr;
+ my @bases = $self->_get_bases;
+ my $base_base = $bases[0];
+ my $base_class = $base_base->[1];
+ my $sth = $dh->stmt("replace$base_class")
+ or confess "No replace$base_class member in DatabaseHandle";
+
+ my @base_cols = $base_class->columns;
+ $sth->execute(@$self{@base_cols})
+ or confess "Cannot save $base_class part of ref $self:", $sth->errstr;
+
+ # save the derived
+ for my $derived (@bases) {
+ my ($key_col, $base_class, $parent_class) = @$derived;
+
+ my $base_cols = () = $base_class->columns;
+ my @parent_cols = $parent_class->columns;
+ splice(@parent_cols, 0, $base_cols);
+
+ my $sth = $dh->stmt('replace'.$parent_class)
+ or confess "No replace$parent_class statement available";
+ $sth->execute(@$self{@parent_cols})
+ or confess "Cannot save $parent_class part of ",ref $self,":",
+ $sth->errstr
}
}
-
- my $sth = $dh->stmt('replace'.ref $self)
- or confess "No replace",ref $self," member in DatabaseHandle";
- my @data;
- for my $col ($self->columns) {
- push(@data, ref $self->{$col} ? $self->{$col}{pkey} : $self->{$col})
- unless $saved{$col};
+ else {
+ my $sth = $dh->stmt('replace'.ref $self)
+ or confess "No replace",ref $self," member in DatabaseHandle";
+ $sth->execute(@$self{$self->columns})
+ or confess "Cannot save ",ref $self,":",$sth->errstr;
}
- $sth->execute(@data)
- or confess "Cannot save ",ref $self,":",$sth->errstr;
$self->{changed} = 0;
}
ref $_[0],'"';
}
+sub _get_bases {
+ my ($class) = @_;
+
+ # make sure we have a class name
+ ref $class and $class = ref $class;
+
+ my @bases;
+ my $parent;
+ my $base = $class;
+ my $bases = $class->bases;
+ while ($bases && keys %$bases) {
+ keys %$bases == 1
+ or confess "I don't know how to handle more than one base for $class";
+
+ my ($my_col) = keys %$bases;
+ $parent = $base;
+ $base = $bases->{$my_col}{class};
+ unshift @bases, [ $my_col, $base, $parent ];
+ $bases = $base->bases;
+ }
+
+ @bases;
+}
+
# in case someone tries AUTOLOAD tricks
sub DESTROY {
}
=head1 CHANGES
+=head2 0.15_13
+
+This is a development release, not intended for production.
+
+=over
+
+=item *
+
+location maintenance at the basic level is in, accessible via
+http://example.com/cgi-bin/admin/admin_seminar.pl
+
+=item *
+
+you can create seminars, though there's no sessions or related data
+yet.
+
+=item *
+
+the generator field in articles has been expanded in size, so
+BSE::Generate::Whatever will fit in.
+
+=item *
+
+orders now accept delivery and billing organization names, and a
+second street line for the delivery and billing addresses
+
+=item *
+
+members can now have a second street address line in their billing and
+delivery addresses. They can also have a billing organization.
+
+=item *
+
+the release and expiry dates for articles when creating a new article
+seem to have been handled incorrectly for a long time. We now
+properly parse them when adding a new article (or product, etc)
+
+=item *
+
+in some cases the date tage %z value would be omitted under Linux.
+I'm not sure why this was happening, and the fix is pretty empirical.
+
+=item *
+
+we now attempt to handle nested non-tag [] when removing tags from
+body text.
+
+=item *
+
+t/t40images.t now uses the links() method instead of the internal
+extract_links() method.
+
+=back
+
=head2 0.15_12
=over
<:or New:>
<:if UserCan edit_add_child:article:>
<p>
-<form action="/cgi-bin/admin/add.pl" method="POST">
+<form action="/cgi-bin/admin/add.pl" method="get">
<input type=hidden name="parentid" value="<:article id:>">
<input type=hidden name="type" value="Catalog">
<input type=submit value="Add Sub-catalog">
</form>
-<form action="/cgi-bin/admin/add.pl" method="POST">
+<form action="/cgi-bin/admin/add.pl" method="get">
<input type=hidden name="parentid" value="<:article id:>">
-<input type=hidden name="parentid" value="Product">
+<input type=hidden name="type" value="Product">
<input type=submit value="Add Product">
+</form>
+<form action="/cgi-bin/admin/add.pl" method="get">
+<input type="hidden" name="parentid" value="<:article id:>">
+<input type="hidden" name="type" value="Seminar">
+ <input type=submit value="Add Seminar">
</form><:or UserCan:><:eif UserCan:></p>
<:eif New:> <:or HaveChildType:> <:eif HaveChildType:>
<p><font size="-1">BSE Release <:release:></font></p>
--- /dev/null
+<html><head><title><:ifNew:>Add<:or:>Edit<:eif:> seminar - Shop administration</title>
+ <link rel="stylesheet" type="text/css" href="/css/admin.css">
+</head>
+<body>
+<h1>Shop Administration</h1>
+<:ifMessage:>
+<p><b><:message:></b></p>
+<:or:><:eif:>
+<p>| <a href="/cgi-bin/admin/menu.pl">Admin menu</a> | <:if New:><:or New:><a href="<:seminar admin:>">See
+ seminar</a> | <a href="/cgi-bin/admin/add.pl?id=<:seminar parentid:>">Edit
+ parent</a>
+ |<:eif New:> <a href="/cgi-bin/admin/shopadmin.pl">Manage catalogs</a> |<:if
+ New:><:or New:><:if UserCan edit_save:seminar,edit_field_edit_listed:seminar
+ :> <a href="/cgi-bin/admin/add.pl?id=<:seminar id:>&_t=steps">Manage
+ step parents</a> | <:if Seminar listed:> <a href="<:script:>?id=<:seminar id:>&hide=1&r=<:script:>?id=<:seminar id:>">Hide
+ seminar</a> |<:or Seminar:> <a href="<:script:>?id=<:seminar id:>&unhide=1&r=<:script:>?id=<:seminar id:>">Show
+ seminar</a> |<:eif Seminar:><:or UserCan:><:eif UserCan:><:ifSeminar listed:><:or:> Hidden<:eif:><:eif
+ New:></p>
+ <h2>Seminar Details</h2>
+<:ifNew:><:or:><:if Or [iadminuser_count] [iadmingroup_count]:>
+ <form action="/cgi-bin/admin/adminusers.pl">
+ <input type="hidden" name=id value="<: article id:>" />
+ <table border="0" cellspacing="0" cellpadding="0" bgcolor="#000000" class="table">
+ <tr>
+ <td>
+ <table cellpadding="6" cellspacing="1" border="0" width="100%">
+ <tr>
+ <th nowrap>
+
+ <font size=2>Manage access:</font>
+ </th>
+ <td bgcolor="#FFFFFF">
+ <select name=adminid>
+<:iterator begin adminusers:>
+<option value=<:iadminuser id:>>User <:iadminuser logon:>
+<:iterator end adminusers:>
+<:iterator begin admingroups:>
+<option value=<:iadmingroup id:>>Group <:iadmingroup name:>
+<:iterator end admingroups:>
+ </select>
+ <input type=submit name="a_showobjectart" value="Manage">
+ </td>
+ <td bgcolor="#FFFFFF"><:help access manage:>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </form>
+<br>
+<:or Or:><:eif Or:><:eif:>
+<form action="<:script:>" enctype="multipart/form-data" method="POST">
+ <input type="hidden" name="id" value="<:seminar id:>" />
+ <input type="hidden" name="type" value="Seminar" />
+ <table border="0" cellspacing="0" cellpadding="0" bgcolor="#000000" class="table">
+ <tr>
+ <td>
+ <table border=0 cellpadding="6" cellspacing="1" width="100%">
+ <tr>
+ <th align="left" bgcolor="#FFFFFF">Catalog:</th>
+ <td bgcolor="#FFFFFF">
+<:ifFieldPerm parentid:><select name="parentid"><:list:></select><:or:><:parent title:> (<:parent id:>)<:eif:></td>
+ <td nowrap bgcolor="#FFFFFF"><:help product catalog:> <:error_img
+ parentid:></td>
+ </tr>
+ <tr>
+ <th align="left" bgcolor="#FFFFFF">Title*:</th>
+ <td bgcolor="#FFFFFF"><:ifFieldPerm title:><input type="text" name="title" value="<:old title default title:>" size="60"><:or:><:seminar title:><:eif:> </td>
+ <td nowrap bgcolor="#FFFFFF"><:help product title:> <:error_img title:></td>
+ </tr>
+ <tr>
+ <th nowrap align="left" bgcolor="#FFFFFF">Summary*:</th>
+ <td nowrap bgcolor="#FFFFFF"><:ifFieldPerm summary:><input type="text" name="summary" value="<:old summary default summary:>" size=60><:or:><:seminar summary:><:eif:> </td>
+ <td nowrap bgcolor="#FFFFFF"><:help product summary:> <:error_img
+ summary:></td>
+ </tr>
+ <tr>
+ <th align="left" bgcolor="#FFFFFF" valign="top"> Body:</th>
+ <td bgcolor="#FFFFFF">
+ <:ifFieldPerm body:><textarea name=body rows=15 cols=60 wrap=virtual><:old body default body:></textarea><:or:><:bodytext seminar body:><:eif:>
+ </td>
+ <td nowrap bgcolor="#FFFFFF" valign="top"><:help body body:> <:error_img
+ body:></td>
+ </tr>
+ <tr>
+ <th nowrap align="left" bgcolor="#FFFFFF"><:cfg "seminar fields" duration "Duration":>:</th>
+ <td nowrap bgcolor="#FFFFFF"><:ifFieldPerm duration:><input type="text" name="duration" value="<:old duration default duration:>" size="10" /> minutes<:or:><:seminar duration:><:eif:></td>
+ <td nowrap bgcolor="#FFFFFF"><:help product duration:> <:error_img
+ duration:></td>
+ </tr>
+ <tr>
+ <th nowrap align="left" bgcolor="#FFFFFF">Template:</th>
+ <td nowrap bgcolor="#FFFFFF"><:ifFieldPerm template:><:templates:><:or:><:seminar template:><:eif:></td>
+ <td nowrap bgcolor="#FFFFFF"><:help product template:> <:error_img
+ template:></td>
+ </tr>
+ <tr>
+ <th nowrap bgcolor="#FFFFFF" align="left">List article:</th>
+ <td bgcolor="#FFFFFF" width="100%"> <:if FieldPerm listed:><:list listed:><:or FieldPerm:><:if Article listed:><:ifEq [article listed] "1":>Yes<:or:>In Sections, but not menu<:eif:><:or Article:>No<:eif Article:><:eif FieldPerm:> </td>
+ <td bgcolor="#FFFFFF"><:help edit listed:> <:error_img listed:></td>
+ </tr>
+ <tr>
+ <th nowrap bgcolor="#FFFFFF" align="left">Flags:</th>
+ <td bgcolor="#FFFFFF" width="100%"><:iterator begin flags:><:if FieldPerm flags:>
+ <input type=checkbox name=flags value="<:flag id:>" <:ifFlagSet [flag id]:>checked<:or:>
+ <:eif:>><:or FieldPerm:><:ifFlagSet [flag id]:>Yes<:or:>No<:eif:>
+ <:eif FieldPerm:><:flag desc:><:iterator separator flags:><br /><:iterator end flags:></td>
+ <td bgcolor="#FFFFFF"><:help edit flags:> <:error_img flags:></td>
+ </tr>
+ <tr>
+ <th nowrap align="left" bgcolor="#FFFFFF">Lead time:</th>
+ <td nowrap bgcolor="#FFFFFF">
+ <:ifFieldPerm leadTime:>
+ <input type="text" name="leadTime" value="<:old leadTime default leadTime:>" size=5><:or:><:seminar leadTime:><:eif:>
+ days</td>
+ <td nowrap bgcolor="#FFFFFF"><:help product leadtime:> <:error_img
+ leadTime:></td>
+ </tr>
+ <tr>
+ <th align="left" bgcolor="#FFFFFF"><:cfg "product fields" retailPrice "Retail price":>:</th>
+ <td bgcolor="#FFFFFF">$
+ <:ifFieldPerm retailPrice:><input type="text" name="retailPrice" value="<:old retailPrice money default retailPrice:>" size=7>
+ (0.00)<:or:><:money seminar retailPrice:><:eif:> </td>
+ <td nowrap bgcolor="#FFFFFF"><:help product retail:> <:error_img retailPrice:></td>
+ </tr>
+ <tr>
+ <th align="left" bgcolor="#FFFFFF">Wholesale price:</th>
+ <td bgcolor="#FFFFFF">$
+ <:ifFieldPerm wholesalePrice:><input type="text" name="wholesalePrice" value="<:old wholesalePrice money default wholesalePrice:>" size=7>
+ (0.00)<:or:><:money seminar wholesalePrice:><:eif:></td>
+ <td nowrap bgcolor="#FFFFFF"><:help product wholesale:> <:error_img wholesalePrice:></td>
+ </tr>
+ <tr>
+ <th align="left" bgcolor="#FFFFFF">GST:</th>
+ <td bgcolor="#FFFFFF">$
+ <:ifFieldPerm gst:><input type="text" name="gst" value="<:old gst money default gst:>" size=7>
+ (0.00)<:or:><:money seminar gst:><:eif:></td>
+ <td nowrap bgcolor="#FFFFFF"><:help product gst:> <:error_img gst:></td>
+ </tr>
+ <tr>
+ <th align="left" bgcolor="#FFFFFF">Release date:</th>
+ <td bgcolor="#FFFFFF">
+ <:ifFieldPerm release:><input type="text" name="release" value="<:old release date "%d/%m/%Y" default release:>" size=11>
+ (dd/mm/yyyy)<:or:><:date "%d/%m/%Y" seminar release:><:eif:></td>
+ <td nowrap bgcolor="#FFFFFF"><:help product release:> <:error_img
+ release:></td>
+ </tr>
+ <tr>
+ <th align="left" bgcolor="#FFFFFF">Expiry date:</th>
+ <td bgcolor="#FFFFFF">
+ <:ifFieldPerm expire:><input type="text" name="expire" value="<:old expire date "%d/%m/%Y" default expire:>" size=11>
+ (dd/mm/yyyy)<:or:><:date "%d/%m/%Y" seminar expire:><:eif:></td>
+ <td nowrap bgcolor="#FFFFFF"><:help product expire:> <:error_img
+ expire:></td>
+ </tr>
+ <tr>
+ <th nowrap align="left" bgcolor="#FFFFFF">Summary length:</th>
+ <td nowrap bgcolor="#FFFFFF">
+ <:ifFieldPerm summaryLength:><input type="text" name="summaryLength" size="10" maxlength="10" value="<:old summaryLength default summaryLength:>"><:or:><:seminar summaryLength:><:eif:>
+ </td>
+ <td nowrap bgcolor="#FFFFFF"><:help product summary:> <:error_img
+ summaryLength:></td>
+ </tr>
+ <tr>
+ <th nowrap align="left" bgcolor="#FFFFFF">Display threshold:</th>
+ <td nowrap bgcolor="#FFFFFF">
+ <:ifFieldPerm threshold:><input type="text" name="threshold" size=10 maxlength=10 value="<:old threshold default threshold:>"><:or:><:seminar threshold:><:eif:>
+ </td>
+ <td nowrap bgcolor="#FFFFFF"><:help product threshold:> <:error_img
+ threshold:></td>
+ </tr>
+ <tr>
+ <th align="left" bgcolor="#FFFFFF">Options:</th>
+ <td bgcolor="#FFFFFF">
+ <:ifFieldPerm options:><input type="text" name="options" value="<:old options default options:>" size=30>
+ (<:alloptions:>)<:or:><:seminar options:><:eif:> </td>
+ <td bgcolor="#FFFFFF"><:help product options:> <:error_img options:></td>
+ </tr>
+<:include admin/seminar_custom.tmpl optional:>
+ <tr>
+ <th nowrap align="left" bgcolor="#FFFFFF" valign="top">Thumbnail image:</th>
+ <td nowrap bgcolor="#FFFFFF">
+ <:ifFieldPerm thumbImage:><input type="file" name="thumbnail"><:or:><:eif:>
+ <:ifSeminar thumbImage:><img src="/images/<:seminar thumbImage:>">
+ <:if FieldPerm thumbImage:><input type=checkbox name="remove_thumb">
+ Remove<:or FieldPerm:><:eif FieldPerm:><:or:><:eif:> </td>
+ <td nowrap bgcolor="#FFFFFF" valign="top"><:help product thumb:> <:error_img
+ thumbImage:></td>
+ </tr>
+ <:if Article id:>
+ <tr>
+ <th nowrap align="left" bgcolor="#FFFFFF" valign="top"><a name="files"></a>Files:</th>
+ <td nowrap bgcolor="#FFFFFF"> <:if Files:>
+ <table cellpadding="0" cellspacing="0" border="0" bgcolor="#333333">
+ <tr>
+ <td>
+ <table cellpadding="5" cellspacing="1" border="0">
+ <tr bgcolor="#FFFFFF">
+ <th>Filename</th>
+ <th>Size</th>
+ <th>Type</th>
+ <th>D/l</th>
+ <th>Pay</th>
+ <th>User</th>
+ </tr>
+ <:iterator begin files:>
+ <tr bgcolor="#FFFFFF">
+ <td><:file displayName:></td>
+ <td align="center"><:kb file sizeInBytes:></td>
+ <td><:file contentType:></td>
+ <td align=center><:ifFile download:>Yes<:or:>No<:eif:></td>
+ <td align=center><:ifFile forSale:>Yes<:or:>No<:eif:></td>
+ <td align=center><:ifFile requireUser:>Yes<:or:>No<:eif:></td>
+ </tr>
+ <:iterator end files:>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <p><a href="<:script:>?filelist=1&id=<:article id:>"><b>Manage Files</b></a>
+ </p>
+ <:or Files:>
+ <p>No files are attached to this article. <a href="<:script:>?filelist=1&id=<:article id:>"><b>Manage Files</b></a></p><:eif Files:>
+ </td>
+ <td nowrap bgcolor="#FFFFFF" valign="top"><:help product
+ files:> <:error_img files:></td>
+ </tr>
+ <tr>
+ <th valign="top" nowrap bgcolor="#FFFFFF" align="left"> Images:
+ </th>
+ <td align="center" bgcolor="#FFFFFF"> <:if Images:> <:iterator begin
+ images:> <img src="/images/<: image image :>" alt="<:image alt :>" width=
+ <:image width:> height=<:image height:>> <:iterator separator images:>
+ <hr noshade size="1">
+ <: iterator end images :>
+ <p align="left"><a href="<:script:>?id=<:article id:>&showimages=1"><b>Manage Images</b></a></p>
+ <:or Images:><p align="left">No images are attached to this article. <a href="<:script:>?id=<:article id:>&showimages=1"><b>Manage Images</b></a></p>
+ <:eif Images:>
+ </td>
+ <td valign="top" bgcolor="#FFFFFF"><:help product images:> <:error_img
+ images:></td>
+ </tr>
+ <:or Article:><:eif Article:>
+ <tr>
+ <th nowrap align="left" bgcolor="#FFFFFF">Purchase subscribes to:</th>
+ <td nowrap bgcolor="#FFFFFF">
+ <select name="subscription_id">
+ <option value="-1"<:ifEq [old subscription_id] "-1":> selected="selected"<:or:><:eif:>>(nothing)</option>
+<:iterator begin subscriptions:>
+ <option value="<:subscription subscription_id:>"<:ifEq [old subscription_id] [subscription subscription_id]:> selected="selected"<:or:><:eif:>><:subscription title:></option>
+<:iterator end subscriptions:>
+ </select> for <input type="text" name="subscription_period" value="<:ifEq [old subscription_period] "":><:default subscription_period:><:or:><:old subscription_period:><:eif:>" size="3" /><:error_img subscription_period:> months.
+ </td>
+ <td nowrap bgcolor="#FFFFFF"><:help product subscription_id:></td>
+ </tr>
+ <tr>
+ <th nowrap align="left" bgcolor="#FFFFFF">Can be used to:</th>
+ <td nowrap bgcolor="#FFFFFF">
+ <select name="subscription_usage">
+ <option value="3"<:ifEq [old subscription_usage] "3":> selected="selected"<:or:><:eif:>>Start or renew a subscription</option>
+ <option value="1"<:ifEq [old subscription_usage] "1":> selected="selected"<:or:><:eif:>>Start a subscription only</option>
+ <option value="2"<:ifEq [old subscription_usage] "2":> selected="selected"<:or:><:eif:>>Renew a subscription only</option>
+ </select>
+ </td>
+ <td nowrap bgcolor="#FFFFFF"><:help product subscription_usage:></td>
+ </tr>
+ <tr>
+ <th nowrap align="left" bgcolor="#FFFFFF">User must be subscribed to:</th>
+ <td nowrap bgcolor="#FFFFFF">
+ <select name="subscription_required">
+ <option value="-1"<:ifEq [old subscription_required] "-1":> selected="selected"<:or:><:eif:>>(nothing)</option>
+<:iterator begin subscriptions:>
+ <option value="<:subscription subscription_id:>"<:ifEq [old subscription_required] [subscription subscription_id]:> selected="selected"<:or:><:eif:>><:subscription title:></option>
+<:iterator end subscriptions:>
+ </select> to purchase this product
+ </td>
+ <td nowrap bgcolor="#FFFFFF"><:help product subscription_id:></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <p><font size="-1">*These fields cannot be modified once this seminar has been
+ included in an order.</font></p>
+ <:if UserCan edit_save:article:>
+ <p>
+ <:ifNew:><input type=submit name="save" value="Add Seminar"><:or:><input type=submit name="save" value="Update Seminar"><:eif:>
+ </p><:or UserCan:><:eif UserCan:>
+</form>
+
+<p><font size="-1">BSE Release <:release:></font></p>
+</body>
+</html>
--- /dev/null
+<:wrap admin/xbase.tmpl title=>"Add Location":>
+<h1>Add Location</h1>
+<p>
+| <a href="/cgi-bin/admin/menu.pl">Admin menu</a> |
+<:if UserCan bse_location_list :>
+<a href="<:script:>?a_loclist=1">List Locations</a> |<:or UserCan:><:eif UserCan:>
+<:ifMessage:>
+<p><b><:message:></b></p>
+<:or:><:eif:>
+
+<form action="<:script:>" method="post" name="addlocation">
+<table>
+<tr>
+ <th><:field description description:>:</th>
+ <td><input type="text" name="description" value="<:old description:>" maxlength="<:field description maxlength:>" size="<:field description width:>" />*</td>
+ <td><:error_img description:><:help addlocation description:></td>
+</tr>
+<tr>
+ <th><:field room description:>:</th>
+ <td><input type="text" name="room" value="<:old room:>" maxlength="<:field room maxlength:>" size="<:field room width:>" /><:ifField room required:>*<:or:><:eif:></td>
+ <td><:error_img room:><:help addlocation room:></td>
+</tr>
+<tr>
+ <th><:field street1 description:>:</th>
+ <td><input type="text" name="street1" value="<:old street1:>" maxlength="<:field street1 maxlength:>" size="<:field street1 width:>" /><:ifField street1 required:>*<:or:><:eif:></td>
+ <td><:error_img street1:><:help addlocation street1:></td>
+</tr>
+<tr>
+ <th><:field street2 description:>:</th>
+ <td><input type="text" name="street2" value="<:old street2:>" maxlength="<:field street2 maxlength:>" size="<:field street2 width:>" /><:ifField street2 required:>*<:or:><:eif:></td>
+ <td><:error_img street2:><:help addlocation street2:></td>
+</tr>
+<tr>
+ <th><:field suburb description:>:</th>
+ <td><input type="text" name="suburb" value="<:old suburb:>" maxlength="<:field suburb maxlength:>" size="<:field suburb width:>" /><:ifField street2 required:>*<:or:><:eif:></td>
+ <td><:error_img suburb:><:help addlocation suburb:></td>
+</tr>
+<tr>
+ <th><:field state description:>:</th>
+ <td><input type="text" name="state" value="<:old state:>" maxlength="<:field state maxlength:>" size="<:field state width:>" /><:ifField state required:>*<:or:><:eif:></td>
+ <td><:error_img state:><:help addlocation state:></td>
+</tr>
+<tr>
+ <th><:field country description:>:</th>
+ <td><input type="text" name="country" value="<:old country:>" maxlength="<:field country maxlength:>" size="<:field country width:>" /><:ifField country required:>*<:or:><:eif:></td>
+ <td><:error_img country:><:help addlocation country:></td>
+</tr>
+<tr>
+ <th><:field postcode description:>:</th>
+ <td><input type="text" name="postcode" value="<:old postcode:>" maxlength="<:field postcode maxlength:>" size="<:field postcode width:>" /><:ifField postcode required:>*<:or:><:eif:></td>
+ <td><:error_img postcode:><:help addlocation postcode:></td>
+</tr>
+<tr>
+ <th><:field public_notes description:>:</th>
+ <td><textarea name="public_notes" rows="<:field public_notes height:>" cols="<:field public_notes width:>" wrap="virtual"><:old public_notes:></textarea></td>
+ <td><:error_img public_notes:><:help addlocation public_notes:></td>
+</tr>
+<tr>
+ <th colspan="2">Bookings</th>
+</tr>
+<tr>
+ <th><:field bookings_name description:>:</th>
+ <td><input type="text" name="bookings_name" value="<:old bookings_name:>" maxlength="<:field bookings_name maxlength:>" size="<:field bookings_name width:>" /><:ifField bookings_name required:>*<:or:><:eif:></td>
+ <td><:error_img bookings_name:><:help addlocation bookings_name:></td>
+</tr>
+<tr>
+ <th><:field bookings_phone description:>:</th>
+ <td><input type="text" name="bookings_phone" value="<:old bookings_phone:>" maxlength="<:field bookings_phone maxlength:>" size="<:field bookings_phone width:>" /><:ifField bookings_phone required:>*<:or:><:eif:></td>
+ <td><:error_img bookings_phone:><:help addlocation bookings_phone:></td>
+</tr>
+<tr>
+ <th><:field bookings_fax description:>:</th>
+ <td><input type="text" name="bookings_fax" value="<:old bookings_fax:>" maxlength="<:field bookings_fax maxlength:>" size="<:field bookings_fax width:>" /><:ifField bookings_fax required:>*<:or:><:eif:></td>
+ <td><:error_img bookings_fax:><:help addlocation bookings_fax:></td>
+</tr>
+<tr>
+ <th><:field bookings_url description:>:</th>
+ <td><input type="text" name="bookings_url" value="<:old bookings_url:>" maxlength="<:field bookings_url maxlength:>" size="<:field bookings_url width:>" /><:ifField bookings_url required:>*<:or:><:eif:></td>
+ <td><:error_img bookings_url:><:help addlocation bookings_url:></td>
+</tr>
+<tr>
+ <th colspan="2">Facilities</th>
+</tr>
+<tr>
+ <th><:field facilities_name description:>:</th>
+ <td><input type="text" name="facilities_name" value="<:old facilities_name:>" maxlength="<:field facilities_name maxlength:>" size="<:field facilities_name width:>" /><:ifField facilities_name required:>*<:or:><:eif:></td>
+ <td><:error_img facilities_name:><:help addlocation facilities_name:></td>
+</tr>
+<tr>
+ <th><:field facilities_phone description:>:</th>
+ <td><input type="text" name="facilities_phone" value="<:old facilities_phone:>" maxlength="<:field facilities_phone maxlength:>" size="<:field facilities_phone width:>" /><:ifField facilities_phone required:>*<:or:><:eif:></td>
+ <td><:error_img facilities_phone:><:help addlocation facilities_phone:></td>
+</tr>
+<tr>
+ <th><:field admin_notes description:>:</th>
+ <td><textarea name="admin_notes" rows="<:field admin_notes height:>" cols="<:field admin_notes width:>" wrap="virtual"><:old admin_notes:></textarea></td>
+ <td><:error_img admin_notes:><:help addlocation admin_notes:></td>
+</tr>
+
+<tr>
+ <td colspan="2"><input type="submit" name="a_locadd" value="Add Location" /></td>
+ <td> </td>
+</tr>
+</table>
+</form>
\ No newline at end of file
--- /dev/null
+<:wrap admin/xbase.tmpl title=>"Delete Location: [location description]":>
+<h1>Delete Location: <:location description:></h1>
+<p>
+| <a href="/cgi-bin/admin/menu.pl">Admin menu</a> |
+<:if UserCan bse_location_list :><a href="<:script:>?a_loclist=1">List Locations</a> |<:or UserCan:><:eif UserCan:>
+<:if UserCan bse_location_edit :>
+<a href="<:script:>?a_locedit=1&id=<:location id:>">Edit Location</a> |<:or UserCan:><:eif UserCan:>
+<:if UserCan bse_location_add :>
+<a href="<:script:>?a_locaddform=1">Add Location</a> |<:or UserCan:><:eif UserCan:>
+<:ifMessage:>
+<p><b><:message:></b></p>
+<:or:><:eif:>
+
+<form action="<:script:>" method="POST">
+<input type="hidden" name="id" value="<:location id:>" />
+<table>
+<tr>
+ <th><:field description description:>:</th>
+ <td><:location description:></td>
+</tr>
+<tr>
+ <td colspan="2"><input type="submit" name="a_locdelete" value="Delete Location" /></td>
+</tr>
+</table>
+</form>
--- /dev/null
+<:wrap admin/xbase.tmpl title=>"Edit Location":>
+<h1>Edit Location</h1>
+<p>
+| <a href="/cgi-bin/admin/menu.pl">Admin menu</a> |
+<:if UserCan bse_location_list :>
+<a href="<:script:>?a_loclist=1">List Locations</a> |<:or UserCan:><:eif UserCan:>
+<:ifMessage:>
+<p><b><:message:></b></p>
+<:or:><:eif:>
+
+<form action="<:script:>" method="post" name="editlocation">
+<input type="hidden" name="id" value="<:location id:>" />
+<table>
+<tr>
+ <th><:field description description:>:</th>
+ <td><input type="text" name="description" value="<:old description location description:>" maxlength="<:field description maxlength:>" size="<:field description width:>" />*</td>
+ <td><:error_img description:><:help addlocation description:></td>
+</tr>
+<tr>
+ <th><:field room description:>:</th>
+ <td><input type="text" name="room" value="<:old room location room:>" maxlength="<:field room maxlength:>" size="<:field room width:>" /><:ifField room required:>*<:or:><:eif:></td>
+ <td><:error_img room:><:help addlocation room:></td>
+</tr>
+<tr>
+ <th><:field street1 description:>:</th>
+ <td><input type="text" name="street1" value="<:old street1 location street1:>" maxlength="<:field street1 maxlength:>" size="<:field street1 width:>" /><:ifField street1 required:>*<:or:><:eif:></td>
+ <td><:error_img street1:><:help addlocation street1:></td>
+</tr>
+<tr>
+ <th><:field street2 description:>:</th>
+ <td><input type="text" name="street2" value="<:old street2 location street2:>" maxlength="<:field street2 maxlength:>" size="<:field street2 width:>" /><:ifField street2 required:>*<:or:><:eif:></td>
+ <td><:error_img street2:><:help addlocation street2:></td>
+</tr>
+<tr>
+ <th><:field suburb description:>:</th>
+ <td><input type="text" name="suburb" value="<:old suburb location suburb:>" maxlength="<:field suburb maxlength:>" size="<:field suburb width:>" /><:ifField street2 required:>*<:or:><:eif:></td>
+ <td><:error_img suburb:><:help addlocation suburb:></td>
+</tr>
+<tr>
+ <th><:field state description:>:</th>
+ <td><input type="text" name="state" value="<:old state location state:>" maxlength="<:field state maxlength:>" size="<:field state width:>" /><:ifField state required:>*<:or:><:eif:></td>
+ <td><:error_img state:><:help addlocation state:></td>
+</tr>
+<tr>
+ <th><:field country description:>:</th>
+ <td><input type="text" name="country" value="<:old country location country:>" maxlength="<:field country maxlength:>" size="<:field country width:>" /><:ifField country required:>*<:or:><:eif:></td>
+ <td><:error_img country:><:help addlocation country:></td>
+</tr>
+<tr>
+ <th><:field postcode description:>:</th>
+ <td><input type="text" name="postcode" value="<:old postcode location postcode:>" maxlength="<:field postcode maxlength:>" size="<:field postcode width:>" /><:ifField postcode required:>*<:or:><:eif:></td>
+ <td><:error_img postcode:><:help addlocation postcode:></td>
+</tr>
+<tr>
+ <th><:field public_notes description:>:</th>
+ <td><textarea name="public_notes" rows="<:field public_notes height:>" cols="<:field public_notes width:>" wrap="virtual"><:old public_notes location public_notes:></textarea></td>
+ <td><:error_img public_notes:><:help addlocation public_notes:></td>
+</tr>
+<tr>
+ <th>Disabled:</th>
+ <td><input type="checkbox" name="disabled" value="1" <:ifLocation disabled:>checked="checked" <:or:><:eif:>/><input type="hidden" name="save_disabled" value="1" /></td>
+ <td><:help addlocation disabled:></td>
+</tr>
+<tr>
+ <th colspan="2">Bookings</th>
+</tr>
+<tr>
+ <th><:field bookings_name description:>:</th>
+ <td><input type="text" name="bookings_name" value="<:old bookings_name location bookings_name:>" maxlength="<:field bookings_name maxlength:>" size="<:field bookings_name width:>" /><:ifField bookings_name required:>*<:or:><:eif:></td>
+ <td><:error_img bookings_name:><:help addlocation bookings_name:></td>
+</tr>
+<tr>
+ <th><:field bookings_phone description:>:</th>
+ <td><input type="text" name="bookings_phone" value="<:old bookings_phone location bookings_phone:>" maxlength="<:field bookings_phone maxlength:>" size="<:field bookings_phone width:>" /><:ifField bookings_phone required:>*<:or:><:eif:></td>
+ <td><:error_img bookings_phone:><:help addlocation bookings_phone:></td>
+</tr>
+<tr>
+ <th><:field bookings_fax description:>:</th>
+ <td><input type="text" name="bookings_fax" value="<:old bookings_fax location bookings_fax:>" maxlength="<:field bookings_fax maxlength:>" size="<:field bookings_fax width:>" /><:ifField bookings_fax required:>*<:or:><:eif:></td>
+ <td><:error_img bookings_fax:><:help addlocation bookings_fax:></td>
+</tr>
+<tr>
+ <th><:field bookings_url description:>:</th>
+ <td><input type="text" name="bookings_url" value="<:old bookings_url location bookings_url:>" maxlength="<:field bookings_url maxlength:>" size="<:field bookings_url width:>" /><:ifField bookings_url required:>*<:or:><:eif:></td>
+ <td><:error_img bookings_url:><:help addlocation bookings_url:></td>
+</tr>
+<tr>
+ <th colspan="2">Facilities</th>
+</tr>
+<tr>
+ <th><:field facilities_name description:>:</th>
+ <td><input type="text" name="facilities_name" value="<:old facilities_name location facilities_name:>" maxlength="<:field facilities_name maxlength:>" size="<:field facilities_name width:>" /><:ifField facilities_name required:>*<:or:><:eif:></td>
+ <td><:error_img facilities_name:><:help addlocation facilities_name:></td>
+</tr>
+<tr>
+ <th><:field facilities_phone description:>:</th>
+ <td><input type="text" name="facilities_phone" value="<:old facilities_phone location facilities_phone:>" maxlength="<:field facilities_phone maxlength:>" size="<:field facilities_phone width:>" /><:ifField facilities_phone required:>*<:or:><:eif:></td>
+ <td><:error_img facilities_phone:><:help addlocation facilities_phone:></td>
+</tr>
+<tr>
+ <th><:field admin_notes description:>:</th>
+ <td><textarea name="admin_notes" rows="<:field admin_notes height:>" cols="<:field admin_notes width:>" wrap="virtual"><:old admin_notes location admin_notes:></textarea></td>
+ <td><:error_img admin_notes:><:help addlocation admin_notes:></td>
+</tr>
+
+<tr>
+ <td colspan="2"><input type="submit" name="a_locsave" value="Save Location" /></td>
+ <td> </td>
+</tr>
+</table>
+</form>
\ No newline at end of file
--- /dev/null
+<:wrap admin/xbase.tmpl title=>"Location List":>
+<h1>Location List</h1>
+
+<:ifMessage:><p><b><:message:></b></p><:or:><:eif:>
+
+<p>| <a href="/cgi-bin/admin/menu.pl">Admin menu</a> |<:ifUserCan bse_location_add:>
+<a href="<:script:>?a_locaddform=1">Add Location</a> |<:or:><:eif:></p>
+
+<table cellpadding="6" border="0" cellspacing="1">
+ <tr bgcolor="#FFFFFF">
+ <th>Description</th>
+ <th>Room</th>
+ <th>Street</th>
+ <th>Suburb</th>
+ <th>Disabled?</th>
+ <th>Modify</th>
+ </tr>
+<:if Locations:>
+<:iterator begin locations:>
+ <tr bgcolor="#FFFFFF">
+ <td><:ilocation description:></td>
+ <td><:ilocation room:></td>
+ <td><:ilocation street1:> <:ilocation street2:></td>
+ <td><:ilocation suburb:></td>
+ <td align="center"><:ifIlocation disabled:>Disabled<:or:><:eif:></td>
+ <td><:ifUserCan bse_location_edit:><a href="<:script:>?a_locedit=1&id=<:ilocation id:>">Edit</a><:or:><:eif:> <:ifAnd [ifRemovable] [ifUserCan bse_location_delete]:><a href="<:script:>?a_locdelask=1&id=<:ilocation id:>">Delete</a><:or:><:eif:></td>
+ </tr>
+<:iterator end locations:>
+<:or Locations:>
+ <tr bgcolor="#FFFFFF">
+ <td colspan="7" align="center">You don't have any locations defined</td>
+ </tr>
+<:eif Locations:>
+</table>
<tr>
<td align="left"><b>Delivery:</b></td>
<td><:order delivFirstName:> <:order delivLastName:></td>
- <td rowspan=4> </td>
+ <td rowspan="6"> </td>
<td align="left"><b>Billing:</b></td>
<td><:order billFirstName:> <:order billLastName:></td>
</tr>
<tr>
- <td rowspan=3> </td>
+ <td rowspan="5"> </td>
+ <td><:order delivOrganization:></td>
+ <td rowspan="5"> </td>
+ <td><:order billOrganization:></td>
+ </tr>
+ <tr>
<td><:order delivStreet:></td>
- <td rowspan=3> </td>
<td><:order billStreet:></td>
</tr>
+ <tr>
+ <td><:order delivStreet2:></td>
+ <td><:order billStreet2:></td>
+ </tr>
<tr>
<td><:order delivSuburb:> <:order delivState:> <:order delivPostCode:></td>
<td><:order billSuburb:> <:order billState:> <:order billPostCode:></td>
<input type="Text" name="delivLastName" size=34 value="<:old delivLastName:>"><:error_img delivLastName:>
*</font></td>
</tr>
+ <tr>
+ <td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2"> Organization:</font></td>
+ <td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2">
+ <input type="Text" name="delivOrganization" size=34 value="<:old delivOrganization:>" /><:error_img delivOrganization:>
+ *</font></td>
+ </tr>
<tr>
<td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2"> Address:</font></td>
<td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2">
<input type="Text" name="delivStreet" size=34 value="<:old delivStreet:>" /><:error_img delivStreet:>
*</font></td>
</tr>
+ <tr>
+ <td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2"> </font></td>
+ <td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2">
+ <input type="Text" name="delivStreet2" size=34 value="<:old delivStreet2:>" /><:error_img delivStreet2:>
+ </font></td>
+ </tr>
<tr>
<td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2"> City:</font></td>
<td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2">
<input type="Text" name="billLastName" size=34 value="<:old billLastName:>"><:error_img billLastName:>
*</font></td>
</tr>
+ <tr>
+ <td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2"> Organization:</font></td>
+ <td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2">
+ <input type="Text" name="billOrganization" size=34 value="<:old billOrganization:>"><:error_img billOrganization:>
+ *</font></td>
+ </tr>
<tr>
<td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2"> Address:</font></td>
<td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2">
<input type="Text" name="billStreet" size=34 value="<:old billStreet:>"><:error_img billStreet:>
*</font></td>
</tr>
+ <tr>
+ <td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2"> </font></td>
+ <td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2">
+ <input type="Text" name="billStreet2" size=34 value="<:old billStreet2:>"><:error_img billStreet2:>
+ </font></td>
+ </tr>
<tr>
<td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2"> City:</font></td>
<td> <font face="Verdana, Arial, Helvetica, sans-serif" size="2">
<input type="text" name="address" value="<:last address:>" size="40" maxlength="127" /><:error_img address:>
</td>
</tr>
+ <tr>
+ <th nowrap="nowrap" align="left"><b><font face="Verdana, Arial, Helvetica, sans-serif" size="-2"></font></b></th>
+ <td width="100%" nowrap="nowrap">
+ <input type="text" name="delivStreet2" value="<:last delivStreet2:>" size="40" maxlength="127" /><:error_img delivStreet2:>
+ </td>
+ </tr>
<tr>
<th nowrap="nowrap" align="left"><b><font face="Verdana, Arial, Helvetica, sans-serif" size="-2">Suburb:</font></b></th>
<td width="100%" nowrap="nowrap">
<input type="text" name="billLastName" value="<:last billLastName:>" size="40" maxlength="127" /><:error_img billLastName:>
</td>
</tr>
+ <tr>
+ <th>Organization:</th>
+ <td width="100%" nowrap="nowrap">
+ <input type="text" name="billOrganization" value="<:last billOrganization:>" size="40" maxlength="127" /><:error_img billOrganization:>
+ </td>
+ </tr>
<tr>
<th>Street:</th>
<td width="100%" nowrap="nowrap">
<input type="text" name="billStreet" value="<:last billStreet:>" size="40" maxlength="127" /><:error_img billStreet:>
</td>
</tr>
+ <tr>
+ <th></th>
+ <td width="100%" nowrap="nowrap">
+ <input type="text" name="billStreet2" value="<:last billStreet2:>" size="40" maxlength="127" /><:error_img billStreet2:>
+ </td>
+ </tr>
<tr>
<th>Suburb:</th>
<td width="100%" nowrap="nowrap">
<input type="text" name="address" value="<:old address:>" size="40" maxlength="127" /> <:error_img address:><:ifRequired address:><font face="Verdana, Arial, Helvetica, sans-serif" size="-2">*</font><:or:><:eif:>
</td>
</tr>
+ <tr>
+ <th nowrap align="left"><b><font face="Verdana, Arial, Helvetica, sans-serif" size="-2"></font></b></th>
+ <td width="100%" nowrap="nowrap">
+ <input type="text" name="delivStreet2" value="<:old delivStreet2:>" size="40" maxlength="127" /> <:error_img delivStreet2:><:ifRequired delivStreet2:><font face="Verdana, Arial, Helvetica, sans-serif" size="-2">*</font><:or:><:eif:>
+ </td>
+ </tr>
<tr>
<th nowrap align="left"><b><font face="Verdana, Arial, Helvetica, sans-serif" size="-2">Suburb:</font></b></th>
<td width="100%" nowrap="nowrap">
#!perl -w
use strict;
-use Test::More tests => 62;
+use Test::More tests => 64;
sub format_test($$$;$);
+sub noformat_test($$$;$);
my $gotmodule = require_ok('DevHelp::Formatter');
SKIP: {
- skip "couldn't load module", 41 unless $gotmodule;
+ skip "couldn't load module", 63 unless $gotmodule;
format_test 'acronym[hello]', '<p><acronym>hello</acronym></p>', 'acronym';
format_test 'acronym[|hello]', '<p><acronym>hello</acronym></p>', 'acronym with empty title';
format_test 'acronym[foo|hello]', '<p><acronym title="foo">hello</acronym></p>', 'acronym with title';
<p>bar</p>
<h2>quux</h2></div>
EOS
+
+ # remove_format() tests
+ noformat_test 'image[foo]', '', 'image';
+ noformat_test 'code[something [bar]]', 'something [bar]', 'nested []';
}
sub format_test ($$$;$) {
is($result, $out, $desc);
}
+
+sub noformat_test($$$;$) {
+ my ($in, $out, $desc, $stripnl) = @_;
+
+ $stripnl ||= 'none';
+ $in =~ s/\n$// if $stripnl eq 'in' || $stripnl eq 'both';
+ $out =~ s/\n$// if $stripnl eq 'out' || $stripnl eq 'both';
+
+ my $formatter = DevHelp::Formatter->new;
+
+ my $result = $formatter->remove_format($in);
+
+ is($result, $out, $desc);
+}
#!perl -w
use strict;
use BSE::Test ();
-use Test::More tests=>64;
+use Test::More tests=>67;
use File::Spec;
use FindBin;
my $cgidir = File::Spec->catdir(BSE::Test::base_dir, 'cgi-bin');
EXPECTED
+template_test "quotedreplace", $parent, <<'TEMPLATE', <<EXPECTED;
+<:date "%FT%T%z" article lastModified:>
+<meta name="DC.title" content="<:article title:>" />
+<meta name="DC.date" content="<:replace [date "%FT%T%z" article lastModified] "(\d\d)$" ":$1":>" />
+<meta name="DC.format" content="<:cfg site format "text/html":>" />
+TEMPLATE
+2004-09-23T06:00:00+1000
+<meta name="DC.title" content="Parent" />
+<meta name="DC.date" content="2004-09-23T06:00:00+10:00" />
+<meta name="DC.format" content="text/html" />
+EXPECTED
+
BSE::Admin::StepParents->del($parent, $parent);
for my $kid (reverse @kids) {
my $name = $kid->{title};
# since there may have been other global images, we need to be a bit
# more careful here
-my $links = $ua->extract_links;
-my @links = grep $_->[1] eq 'Delete', @$links;
+my $links = $ua->links;
+my @links = grep $_->text eq 'Delete', @$links;
print "# link #", scalar(@links), "\n";
follow_ok($ua, "delete global image",
{ n=>scalar(@links), text=>"Delete" },
payment type names.12=EmailProForma
payment type required.11=facsimile
-#paths.local_templates=/home/tony/dev/bse/work/templates/
+paths.local_templates=/home/tony/dev/bse/work/templates/
affiliate.prompt_name=1
site users.require_affiliate_name=0