[dw-free] Convert /admin/index to TT
[commit: http://hg.dwscoalition.org/dw-free/rev/61913b5952d1]
http://bugs.dwscoalition.org/show_bug.cgi?id=3164
Use controllers/TT for the admin page. Admin pages written in the new style
can register themselves rather than having to have us manually list them.
Patch by
exor674.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=3164
Use controllers/TT for the admin page. Admin pages written in the new style
can register themselves rather than having to have us manually list them.
Patch by
Files modified:
- cgi-bin/DW/Controller/Admin.pm
- cgi-bin/DW/Controller/Rename.pm
- cgi-bin/DW/Controller/SiteStats.pm
- cgi-bin/DW/Routing.pm
- cgi-bin/DW/Template/Plugin.pm
- cgi-bin/DW/Template/VMethods.pm
- htdocs/admin/index.bml
- htdocs/admin/index.bml.text
- t/routing.t
- views/admin/index.tt
- views/admin/index.tt.text
- views/admin/rename.tt
- views/admin/rename.tt.text
- views/admin/stats.tt.text
--------------------------------------------------------------------------------
diff -r f4fcc06b2940 -r 61913b5952d1 cgi-bin/DW/Controller/Admin.pm
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Controller/Admin.pm Thu Oct 28 11:06:03 2010 +0800
@@ -0,0 +1,319 @@
+#!/usr/bin/perl
+#
+# DW::Controller::Admin
+#
+# Controller for admin action list index pages.
+#
+# Authors:
+# Andrea Nall <anall@andreanall.com>
+# Denise Paolucci <denise@dreamwidth.org>
+# Sophie Hamilton <dw-bugzilla@theblob.org>
+#
+# Copyright (c) 2009-2010 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself. For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+package DW::Controller::Admin;
+
+=head1 NAME
+
+DW::Controller::Admin - Controller for admin action list index pages.
+
+This is for pages like /admin/index which list other pages, displaying only what the current user can do
+
+=head1 API
+
+=cut
+
+use strict;
+use warnings;
+use DW::Controller;
+use DW::Routing;
+use DW::Template;
+
+my $admin_pages = {};
+
+DW::Controller::Admin->register_admin_scope( '/', title_ml => '.admin.title' );
+
+# DO NOT add anything to here
+DW::Controller::Admin->_register_admin_pages_legacy( '/',
+ [ 'capedit', '.admin.capability.link', '.admin.capability.text', [ 'admin:*', sub {
+ return ( $LJ::IS_DEV_SERVER, LJ::Lang::ml( "/admin/index.tt.devserver" ) );
+ } ] ],
+ [ 'clusterstatus',
+ '.admin.cluster.link', '.admin.cluster.text', [ 'supporthelp' ] ],
+ [ 'console/',
+ '.admin.console.link', '.admin.console.text' ],
+ [ 'schema/',
+ '.admin.dbschema.link', '.admin.dbschema.text', [ 'schemadoc' ] ],
+ [ 'dupkiller',
+ '.admin.dupkiller.link', '.admin.dupkiller.text', [ 'supporthelp' ] ],
+ [ 'entryprops',
+ '.admin.entryprops.link', '.admin.entryprops.text', [ 'canview:entryprops', 'canview:*', sub {
+ return ( $LJ::IS_DEV_SERVER, LJ::Lang::ml( "/admin/index.tt.devserver" ) );
+ } ] ],
+ [ 'faq/',
+ '.admin.faq.link', '.admin.faq.text', [ 'faqadd', 'faqedit', 'faqcat' ] ],
+ [ 'fileedit/',
+ '.admin.file_edit.link', '.admin.file_edit.text', [ 'fileedit' ] ],
+ [ 'invites/', '.admin.invites.link', '.admin.invites.text', [ 'finduser:codetrace', 'finduser:*', 'payments' ] ],
+ [ 'logout_user',
+ '.admin.logout_user.link', '.admin.logout_user.text', [ 'suspend' ] ],
+ [ 'memcache',
+ '.admin.memcache.link', '.admin.memcache.text', [ 'siteadmin:memcacheview', 'siteadmin:*' ] ],
+ [ 'memcache_view',
+ '.admin.memcache_view.link', '.admin.memcache_view.text', [ 'siteadmin:memcacheview', 'siteadmin:*', sub {
+ return ( $LJ::IS_DEV_SERVER, LJ::Lang::ml( "/admin/index.tt.devserver" ) );
+ } ] ],
+ [ 'mysql_status',
+ '.admin.mysql.link', '.admin.mysql.text', [ 'siteadmin:mysqlstatus', 'siteadmin:*' ] ],
+ [ 'navtag',
+ '.admin.navtag.link', '.admin.navtag.text', [ 'siteadmin:navtag', 'siteadmin:*' ] ],
+ [ 'pay/',
+ '.admin.pay.link', '.admin.pay.text', [ 'payments' ] ],
+ [ 'priv/',
+ '.admin.priv.link', '.admin.priv.text' ],
+ [ 'propedit',
+ '.admin.propedit.link', '.admin.propedit.text', [ 'canview:userprops', 'canview:*' ] ],
+ [ 'recent_comments',
+ '.admin.recent_comments.link', '.admin.recent_comments.text', [ 'siteadmin:commentview', 'siteadmin:*' ] ],
+ [ 'sitemessages/add',
+ '.admin.sitemessages_add.link', '.admin.sitemessages_add.text', [ 'siteadmin:sitemessages', 'siteadmin:*', sub {
+ return ( $LJ::IS_DEV_SERVER, LJ::Lang::ml( "/admin/index.tt.devserver" ) );
+ } ] ],
+ [ 'sitemessages/manage',
+ '.admin.sitemessages_manage.link', '.admin.sitemessages_manage.text', [ 'siteadmin:sitemessages', 'siteadmin:*', sub {
+ return ( $LJ::IS_DEV_SERVER, LJ::Lang::ml( "/admin/index.tt.devserver" ) );
+ } ] ],
+ [ 'spamreports',
+ '.admin.spamreports.link', '.admin.spamreports.text', [ 'siteadmin:spamreports', 'siteadmin:*' ] ],
+ [ 'statushistory',
+ '.admin.statushistory.link', '.admin.statushistory.text', [ 'historyview', sub {
+ return ( $LJ::IS_DEV_SERVER, LJ::Lang::ml( "/admin/index.tt.devserver" ) );
+ } ] ],
+ [ 'styleinfo',
+ '.admin.styleinfo.link', '.admin.styleinfo.text', [ sub {
+ return ( LJ::Support::has_any_support_priv($_[0]->{remote}),
+ LJ::Lang::ml( "/admin/index.tt.anysupportpriv" ) );
+ }, sub {
+ return ( $LJ::IS_DEV_SERVER, LJ::Lang::ml( "/admin/index.tt.devserver" ) );
+ } ] ],
+ [ 'sysban',
+ '.admin.sysban.link', '.admin.sysban.text', [ 'sysban' ] ],
+ [ 'theschwartz',
+ '.admin.theschwartz.link', '.admin.theschwartz.text', [ 'siteadmin:theschwartz' ] ],
+ [ 'translate/',
+ '.admin.translate.link', '.admin.translate.text' ],
+ [ 'userlog',
+ '.admin.userlog.link', '.admin.userlog.text', [ 'canview:userlog', 'canview:*' ] ],
+);
+
+
+sub admin_handler {
+ my $opts = shift @_;
+ my $r = DW::Request->get;
+
+ my ( $ok, $rv ) = controller();
+ return $rv unless $ok;
+
+ my $remote = $rv->{remote};
+
+ my $args = $opts->args || {};
+ my $scope = $args->{scope} || "/";
+
+ my $data = $admin_pages->{$scope};
+
+ my $vars = $rv;
+
+ $vars->{$_} = $data->{$_} foreach qw( title_ml description_ml ml_scope );
+
+ my @pages;
+ my $adminstar = $remote && $remote->has_priv( 'admin', '*' );
+ foreach my $page ( @{ $data->{pages} } ) {
+ my ( $path, $link_ml, $description_ml, $privs ) = @{$page};
+ my $showpage = 0;
+ my ( @needsprivs, @gotprivs );
+ my $haspriv = 0;
+ foreach my $priv ( @{$privs} ) {
+ my $code_result;
+ $code_result = [
+ $priv->( { remote => $remote } )
+ ] if ref( $priv ) eq "CODE";
+
+ my $result = ( $code_result ?
+ $code_result->[0] :
+ $remote && $remote->has_priv( split( /:/, $priv ) ) );
+ my $displayedpriv = ( $code_result ?
+ $code_result->[1] :
+ $priv );
+ push( @gotprivs, $displayedpriv ) if $result;
+ push( @needsprivs, $displayedpriv ) if !$result;
+ $haspriv = 1 if $result;
+ $showpage = 1 if $adminstar || $result;
+ }
+ if ( @$privs == 0 ) {
+ $showpage = 1;
+ $haspriv = 1;
+ }
+ $path = "/admin$scope$path" unless $path =~ m!^((https?://)|/)!;
+ if ( $showpage ) {
+ push @pages, {
+ path => $path,
+ link_ml => $link_ml,
+ description_ml => $description_ml,
+ haspriv => $haspriv,
+ gotprivs => \@gotprivs,
+ needsprivs => \@needsprivs,
+ };
+ }
+ }
+ $vars->{pages} = \@pages;
+
+ return DW::Template->render_template( 'admin/index.tt', $vars );
+}
+
+=head2 C<< $class->register_regex( $scope, %opts ) >>
+
+Register an admin scope.
+
+Arguments:
+
+=over 4
+
+=item scope
+
+The name of the scope
+
+=back
+
+Additional options:
+
+=over 4
+
+=item ml_scope
+
+The ML scope for the ml strings.
+
+=item title_ml
+
+ML string for title
+
+=item description_ml
+
+ML string for description
+
+=back
+
+=cut
+
+sub register_admin_scope {
+ my ( $class, $scope, %opts ) = @_;
+
+ $admin_pages->{$scope} = \%opts;
+
+ my $url = "/admin" . ( $scope eq '/' ? '' : $scope ) . '/index';
+
+ DW::Routing->register_string( $url, \&admin_handler, args => { scope => $scope } );
+}
+
+=head2 C<< $class->register_admin_page( $scope, %opts ) >>
+
+Register an admin scope.
+
+Arguments:
+
+=over 4
+
+=item scope
+
+The name of the scope
+
+=back
+
+Additional options:
+
+=over 4
+
+=item ml_scope
+
+The ML scope for the ml strings.
+
+=item link_ml
+
+ML string for link text ( defaults to ".admin.link" )
+
+=item description_ml
+
+ML string for description ( defaults to ".admin.text" )
+
+=item path
+
+Path, either relative to the scope ( no leading slash ), relative to the domain ( leading slash ), or a full URI
+
+=item privs
+
+An arrayref of priv names or subroutine refs
+
+The subref needs to return [ $has_priv, $string ]
+
+=back
+
+=cut
+
+sub register_admin_page {
+ my ( $class, $scope, %args ) = @_;
+
+ my ( $path, $link_ml, $desc_ml, $privs );
+
+ $path = $args{path};
+ $privs = $args{privs};
+
+ $link_ml = $args{link_ml} || ".admin.link";
+ $desc_ml = $args{description_ml} || ".admin.text";
+
+ if ( $args{ml_scope} ) {
+ $link_ml = $args{ml_scope} . $link_ml;
+ $desc_ml = $args{ml_scope} . $desc_ml;
+ }
+
+ $scope ||= "/";
+ push @{$admin_pages->{$scope}->{pages}}, [ $path, $link_ml, $desc_ml, $privs ];
+}
+
+# DO NOT USE OUTSIDE THIS FILE!
+# FIXME: Remove once the big scary array up above is gone!
+sub _register_admin_pages_legacy {
+ my ( $class, $scope, @pages ) = @_;
+
+ $scope ||= "/";
+ foreach my $part ( @pages ) {
+ push @{$admin_pages->{$scope}->{pages}}, $part;
+ }
+}
+
+=head1 AUTHOR
+
+=over
+
+=item Andrea Nall <anall@andreanall.com>
+
+=item Denise Paolucci <denise@dreamwidth.org>
+
+=item Sophie Hamilton <dw-bugzilla@theblob.org>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2009-2010 by Dreamwidth Studios, LLC.
+
+This program is free software; you may redistribute it and/or modify it under
+the same terms as Perl itself. For a copy of the license, please reference
+'perldoc perlartistic' or 'perldoc perlgpl'.
+
+=cut
+
+1;
diff -r f4fcc06b2940 -r 61913b5952d1 cgi-bin/DW/Controller/Rename.pm
--- a/cgi-bin/DW/Controller/Rename.pm Thu Oct 28 10:15:22 2010 +0800
+++ b/cgi-bin/DW/Controller/Rename.pm Thu Oct 28 11:06:03 2010 +0800
@@ -21,6 +21,7 @@ use DW::Controller;
use DW::Controller;
use DW::Routing;
use DW::Template;
+use DW::Controller::Admin;
use DW::RenameToken;
use DW::Shop;
@@ -30,10 +31,16 @@ use DW::Shop;
# ideally, should be: /rename, or /rename/(20 character token)
DW::Routing->register_regex( qr!^/rename(?:/([A-Z0-9]*))?$!i, \&rename_handler, app => 1 );
-DW::Routing->register_string( "/admin/rename", \&rename_admin_handler, app => 1 );
+DW::Routing->register_string( "/admin/rename/index", \&rename_admin_handler, app => 1 );
DW::Routing->register_string( "/admin/rename/edit", \&rename_admin_edit_handler, app => 1 );
DW::Routing->register_string( "/admin/rename/new", \&siteadmin_rename_handler, app => 1 );
+
+DW::Controller::Admin->register_admin_page( '/',
+ path => '/admin/rename/',
+ ml_scope => '/admin/rename.tt',
+ privs => [ 'siteadmin:rename' ]
+);
sub rename_handler {
my $r = DW::Request->get;
diff -r f4fcc06b2940 -r 61913b5952d1 cgi-bin/DW/Controller/SiteStats.pm
--- a/cgi-bin/DW/Controller/SiteStats.pm Thu Oct 28 10:15:22 2010 +0800
+++ b/cgi-bin/DW/Controller/SiteStats.pm Thu Oct 28 11:06:03 2010 +0800
@@ -34,6 +34,7 @@ use DW::Template;
use DW::Template;
use DW::StatStore;
use DW::StatData;
+use DW::Controller::Admin;
LJ::ModuleLoader::autouse_subclasses( 'DW::StatData' );
@@ -43,7 +44,11 @@ DW::Routing->register_string( '/admin/st
DW::Routing->register_string( '/admin/stats', \&stats_page, app => 1,
args => [ 'admin/stats.tt', \&admin_data, 0,
'payments' ] );
-
+DW::Controller::Admin->register_admin_page( '/',
+ path => '/admin/stats',
+ ml_scope => '/admin/stats.tt',
+ privs => [ 'payments' ]
+);
=head1 Internals
=head2 C<< DW::Controller::SiteStats::stats_page( $opts ) >>
diff -r f4fcc06b2940 -r 61913b5952d1 cgi-bin/DW/Routing.pm
--- a/cgi-bin/DW/Routing.pm Thu Oct 28 10:15:22 2010 +0800
+++ b/cgi-bin/DW/Routing.pm Thu Oct 28 11:06:03 2010 +0800
@@ -107,13 +107,16 @@ sub get_call_opts {
# us accessors.
my $call_opts = DW::Routing::CallInfo->new( \%opts );
+ my $hash;
+ my $role = $call_opts->role;
+
# try the string options first as they're fast
- my $hash = $string_choices{$call_opts->role . $uri};
+ $hash = $string_choices{$role . $uri};
if ( defined $hash ) {
$call_opts->init_call_opts( $hash );
return $call_opts;
}
-
+
# try the regex choices next
# FIXME: this should be a dynamically sorting array so the most used items float to the top
# for now it doesn't matter so much but eventually when everything is in the routing table
@@ -135,7 +138,6 @@ Calls the raw hash.
Calls the raw hash.
=cut
-
sub call_hash {
my ( $class, $opts ) = @_;
my $r = DW::Request->get;
@@ -147,12 +149,8 @@ sub call_hash {
return $r->call_response_handler( \&_call_hash );
}
-=head2 C<< $class->_call_hash() >>
-
-Perl Response Handler for call_hash
-
-=cut
-
+# INTERNAL METHOD: no POD
+# Perl Response Handler for call_hash
sub _call_hash {
my $r = DW::Request->get;
my $opts = $r->pnote('routing_opts');
@@ -190,7 +188,6 @@ sub _call_hash {
$r->status( 500 );
$r->print(objToJson( { error => $text } ));
return $r->OK;
-
# default error rendering
} else {
$msg = $err->as_html;
@@ -207,14 +204,23 @@ sub _call_hash {
}
}
+# INTERNAL METHOD: no POD
+# controller sub for register_static
sub _static_helper {
my $r = DW::Request->get;
- return DW::Template->render_template( $_[0]->args );
+ return DW::Template->render_template( $_[0]->arg );
+}
+
+# INTERNAL METHOD: no POD
+# controller sub for register_redirect
+sub _redirect_helper {
+ my $r = DW::Request->get;
+ return $r->redirect( $_[0]->args );
}
=head1 Registration API
-=head2 C<< $class->register_static($string, $filename, $opts) >>
+=head2 C<< $class->register_static( $string, $filename, %opts ) >>
Static page helper.
@@ -237,7 +243,7 @@ sub register_static {
$class->register_string( $string, \&_static_helper, %opts );
}
-=head2 C<< $class->register_string($string, $sub, $opts) >>
+=head2 C<< $class->register_string( $string, $sub, %opts ) >>
=over
@@ -276,9 +282,47 @@ sub register_string {
$string_choices{'app' . $string} = $hash if $hash->{app};
$string_choices{'ssl' . $string} = $hash if $hash->{ssl};
$string_choices{'user' . $string} = $hash if $hash->{user};
+
+ if ( $string =~ m!(^(.+)/)index$! && ! exists $opts{no_redirects} ) {
+ my %opts = (
+ app => $hash->{app},
+ ssl => $hash->{ssl},
+ user => $hash->{user},
+ formats => $hash->{formats},
+ format => $hash->{format},
+ no_redirects => 1,
+ );
+ $class->register_redirect( $2, $1, %opts );
+ $string_choices{'app' . $1} = $hash if $hash->{app};
+ $string_choices{'ssl' . $1} = $hash if $hash->{ssl};
+ $string_choices{'user' . $1} = $hash if $hash->{user};
+ }
}
-=head2 C<< $class->register_regex($regex, $sub, $opts) >>
+=head2 C<< $class->register_redirect( $string, $dest, %opts ) >>
+
+Redirect helper.
+
+=over
+
+=item string - path
+
+=item dest - destination
+
+=item Opts ( see register_string )
+
+=back
+
+=cut
+
+sub register_redirect {
+ my ( $class, $string, $dest, %opts ) = @_;
+
+ $opts{args} = $dest;
+ $class->register_string( $string, \&_redirect_helper, %opts );
+}
+
+=head2 C<< $class->register_regex( $regex, $sub, %opts ) >>
=over
@@ -306,7 +350,6 @@ sub register_regex {
# internal method, intentionally no POD
# applies default for opts and hash
-
sub _apply_defaults {
my ( $opts, $hash ) = @_;
diff -r f4fcc06b2940 -r 61913b5952d1 cgi-bin/DW/Template/Plugin.pm
--- a/cgi-bin/DW/Template/Plugin.pm Thu Oct 28 10:15:22 2010 +0800
+++ b/cgi-bin/DW/Template/Plugin.pm Thu Oct 28 11:06:03 2010 +0800
@@ -18,6 +18,7 @@ use strict;
use strict;
use DW::Template::Filters;
+use DW::Template::VMethods;
=head1 NAME
@@ -104,6 +105,26 @@ sub form_auth {
return LJ::form_auth();
}
+=head2 sort_by_key
+
+Sorts an array of hashrefs by given key
+
+=cut
+
+sub sort_by_key {
+ my $k = $_[2];
+ my $md = $_[3] || 'alpha';
+
+ my @r;
+ if ( $md eq 'alpha' ) {
+ @r = sort { $a->{$k} cmp $b->{$k} } @{$_[1]};
+ } else {
+ @r = sort { $a->{$k} <=> $b->{$k} } @{$_[1]};
+ }
+
+ return \@r;
+}
+
=head1 AUTHOR
=over
diff -r f4fcc06b2940 -r 61913b5952d1 cgi-bin/DW/Template/VMethods.pm
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Template/VMethods.pm Thu Oct 28 11:06:03 2010 +0800
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+#
+# DW::Template::VMethods
+#
+# VMethods for the Dreamwidth Template Toolkit plugin
+#
+# Authors:
+# Andrea Nall <anall@andreanall.com>
+#
+# Copyright (c) 2010 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself. For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+package DW::Template::VMethods;
+use strict;
+use Template::Stash;
+
+$Template::Stash::LIST_OPS->{ sort_by_key } = sub {
+ my ( $lst, $k, $type ) = @_;
+
+ my @r = ();
+ $type ||= 'alpha';
+ if ( $type eq 'alpha' ) {
+ @r = sort { $a->{$k} cmp $b->{$k} } @$lst;
+ } elsif ( $type eq 'numeric' ) {
+ @r = sort { $a->{$k} <=> $b->{$k} } @$lst;
+ }
+
+ return \@r;
+};
+
+1;
diff -r f4fcc06b2940 -r 61913b5952d1 htdocs/admin/index.bml
--- a/htdocs/admin/index.bml Thu Oct 28 10:15:22 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-<?_c
-#
-# admin/index.bml
-#
-# Because blank index files annoy me. Lists all pages $remote has privs
-# to view; does not show the link if you can't use it.
-#
-# Authors:
-# Denise Paolucci <denise@dreamwidth.org>
-# Sophie Hamilton <dw-bugzilla@theblob.org>
-#
-# Copyright (c) 2009 by Dreamwidth Studios, LLC.
-#
-# This program is free software; you may redistribute it and/or modify it under
-# the same terms as Perl itself. For a copy of the license, please reference
-# 'perldoc perlartistic' or 'perldoc perlgpl'.
-#
-_c?><?page
-body<=
-<?_code
-{
- use strict;
- use vars qw/ %GET %POST $title $windowtitle @errors @warnings /;
-
- # translated/custom page title can go here
- $title = "<?_ml .admin.title _ml?>";
- $windowtitle = "<?_ml .admin.title _ml?>";
-
- # for pages that require authentication
- my $remote = LJ::get_remote();
- return "<?needlogin?>" unless $remote;
-
- my $ret;
-
- my @adminpages = (
- [ 'capedit',
- '<?_ml .admin.capability.link _ml?>', '<?_ml .admin.capability.text _ml?>', [ 'admin:*', sub {
- return ( $LJ::IS_DEV_SERVER, "<?_ml .devserver _ml?>" );
- } ] ],
- [ 'clusterstatus',
- '<?_ml .admin.cluster.link _ml?>', '<?_ml .admin.cluster.text _ml?>', [ 'supporthelp' ] ],
- [ 'console/',
- '<?_ml .admin.console.link _ml?>', '<?_ml .admin.console.text _ml?>' ],
- [ 'schema/',
- '<?_ml .admin.dbschema.link _ml?>', '<?_ml .admin.dbschema.text _ml?>', [ 'schemadoc' ] ],
- [ 'dupkiller',
- '<?_ml .admin.dupkiller.link _ml?>', '<?_ml .admin.dupkiller.text _ml?>', [ 'supporthelp' ] ],
- [ 'entryprops',
- '<?_ml .admin.entryprops.link _ml?>', '<?_ml .admin.entryprops.text _ml?>', [ 'canview:entryprops', 'canview:*', sub {
- return ( $LJ::IS_DEV_SERVER, "<?_ml .devserver _ml?>" );
- } ] ],
- [ 'faq/',
- '<?_ml .admin.faq.link _ml?>', '<?_ml .admin.faq.text _ml?>', [ 'faqadd', 'faqedit', 'faqcat' ] ],
- [ 'fileedit/',
- '<?_ml .admin.file_edit.link _ml?>', 'Allows you to edit various include files.', [ 'fileedit' ] ],
- [ 'invites/', '<?_ml .admin.invites.link _ml?>', '<?_ml .admin.invites.text _ml?>', [ 'finduser:codetrace', 'finduser:*', 'payments' ] ],
- [ 'logout_user',
- '<?_ml .admin.logout_user.link _ml?>', '<?_ml .admin.logout_user.text _ml?>', [ 'suspend' ] ],
- [ 'memcache',
- '<?_ml .admin.memcache.link _ml?>', '<?_ml .admin.memcache.text _ml?>', [ 'siteadmin:memcacheview', 'siteadmin:*' ] ],
- [ 'memcache_view',
- '<?_ml .admin.memcache_view.link _ml?>', '<?_ml .admin.memcache_view.text _ml?>', [ 'siteadmin:memcacheview', 'siteadmin:*', sub {
- return ( $LJ::IS_DEV_SERVER, "<?_ml .devserver _ml?>" );
- } ] ],
- [ 'mysql_status',
- '<?_ml .admin.mysql.link _ml?>', '<?_ml .admin.mysql.text _ml?>', [ 'siteadmin:mysqlstatus', 'siteadmin:*' ] ],
- [ 'navtag',
- '<?_ml .admin.navtag.link _ml?>', '<?_ml .admin.navtag.text _ml?>', [ 'siteadmin:navtag', 'siteadmin:*' ] ],
- [ 'pay/',
- '<?_ml .admin.pay.link _ml?>', '<?_ml .admin.pay.text _ml?>', [ 'payments' ] ],
- [ 'priv/',
- '<?_ml .admin.priv.link _ml?>', '<?_ml .admin.priv.text _ml?>' ],
- [ 'propedit',
- '<?_ml .admin.propedit.link _ml?>', '<?_ml .admin.propedit.text _ml?>', [ 'canview:userprops', 'canview:*' ] ],
- [ 'recent_comments',
- '<?_ml .admin.recent_comments.link _ml?>', '<?_ml .admin.recent_comments.text _ml?>', [ 'siteadmin:commentview', 'siteadmin:*' ] ],
- [ 'sitemessages/add',
- '<?_ml .admin.sitemessages_add.link _ml?>', '<?_ml .admin.sitemessages_add.text _ml?>', [ 'siteadmin:sitemessages', 'siteadmin:*', sub {
- return ( $LJ::IS_DEV_SERVER, "<?_ml .devserver _ml?>" );
- } ] ],
- [ 'sitemessages/manage',
- '<?_ml .admin.sitemessages_manage.link _ml?>', '<?_ml .admin.sitemessages_manage.text _ml?>', [ 'siteadmin:sitemessages', 'siteadmin:*', sub {
- return ( $LJ::IS_DEV_SERVER, "<?_ml .devserver _ml?>" );
- } ] ],
- [ 'spamreports',
- '<?_ml .admin.spamreports.link _ml?>', '<?_ml .admin.spamreports.text _ml?>', [ 'siteadmin:spamreports', 'siteadmin:*' ] ],
- [ 'stats',
- '<?_ml .admin.stats.link _ml?>', '<?_ml .admin.stats.text _ml?>', [ 'payments' ] ],
- [ 'statushistory',
- '<?_ml .admin.statushistory.link _ml?>', '<?_ml .admin.statushistory.text _ml?>', [ 'historyview', sub {
- return ( $LJ::IS_DEV_SERVER, "<?_ml .devserver _ml?>" );
- } ] ],
- [ 'styleinfo',
- '<?_ml .admin.styleinfo.link _ml?>', '<?_ml .admin.styleinfo.text _ml?>', [ sub {
- return ( LJ::Support::has_any_support_priv($remote), "<?_ml .anysupportpriv _ml?>" );
- }, sub {
- return ( $LJ::IS_DEV_SERVER, "<?_ml .devserver _ml?>" );
- } ] ],
- [ 'sysban',
- '<?_ml .admin.sysban.link _ml?>', '<?_ml .admin.sysban.text _ml?>', [ 'sysban' ] ],
- [ 'theschwartz',
- '<?_ml .admin.theschwartz.link _ml?>', '<?_ml .admin.theschwartz.text _ml?>', [ 'siteadmin:theschwartz' ] ],
- [ 'translate/',
- '<?_ml .admin.translate.link _ml?>', '<?_ml .admin.translate.text _ml?>' ],
- [ 'userlog',
- '<?_ml .admin.userlog.link _ml?>', '<?_ml .admin.userlog.text _ml?>', [ 'canview:userlog', 'canview:*' ] ],
- );
-
- $ret .= "<ul>\n";
-
- my $adminstar = $remote && $remote->has_priv( 'admin', '*' );
- foreach my $page ( @adminpages ) {
- my ( $path, $name, $description, $privs ) = @{$page};
- my $showpage = 0;
- my ( @needsprivs, @gotprivs );
- my $haspriv = 0;
- foreach my $priv ( @{$privs} ) {
- my $result = ( ref( $priv ) eq "CODE" ?
- ( $priv->() )[0] :
- $remote && $remote->has_priv( split( /:/, $priv ) ) );
- my $displayedpriv = ( ref( $priv ) eq "CODE" ? ( $priv->() )[1] : $priv );
- push( @gotprivs, $displayedpriv ) if $result;
- push( @needsprivs, $displayedpriv ) if !$result;
- $haspriv = 1 if $result;
- $showpage = 1 if $adminstar || $result;
- }
- if ( @{$privs} == 0 ) {
- $showpage = 1;
- $haspriv = 1;
- }
- if ( $showpage ) {
- my $needspriv = ( $haspriv ? "" : " needspriv" );
- my $privreason = "";
- if ( @gotprivs || @needsprivs ) {
- my $needpriv = ( @needsprivs > 1 ? "<?_ml .needs_one_of _ml?>" : "<?_ml .needspriv _ml?>" );
- $privreason = ( $haspriv ? "(<b>" . join( "</b>, <b>", @gotprivs ) . "</b>)"
- : "($needpriv: <b>" . join( "</b>, <b>", @needsprivs ) . "</b>)" );
- }
- $ret .= "<li class='item$needspriv'><div class='itemhead'><a href='$path'>$name</a> <span class='itemprivs'>$privreason</span></div><div class='itemdef'>$description</div></li>\n";
- }
- }
-
- $ret .= "</ul>";
-
- return $ret;
-}
-_code?>
-<=body
-title=><?_code return $title; _code?>
-windowtitle=><?_code return $windowtitle; _code?>
-head<=
-<style type="text/css">
-.item {margin-bottom: 15px;}
-.item.needspriv div, .item.needspriv a {color: #A0A0A0;}
-.itemhead {font-size: bigger; font-weight: bold;}
-.itemdef {margin-left: 2em;}
-.itemprivs {font-size: smaller; font-weight: normal; color: #707070;}
-</style>
-<=head
-page?>
diff -r f4fcc06b2940 -r 61913b5952d1 htdocs/admin/index.bml.text
--- a/htdocs/admin/index.bml.text Thu Oct 28 10:15:22 2010 +0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-;; -*- coding: utf-8 -*-
-
-.admin.title=Admin Tools
-
-.admin.capability.link=Capability Edit
-.admin.capability.text=For editing user capabilities.
-
-.admin.cluster.link=Cluster Status
-.admin.cluster.text=Get information on cluster availability.
-
-.admin.console.link=Console
-.admin.console.text=For general input; usable by all users to an extent.
-
-.admin.dbschema.link=Database Schema
-.admin.dbschema.text=Shows the database schema.
-
-.admin.dupkiller.link=Duplicate Entry Killer
-.admin.dupkiller.text=Checks for (and kills) duplicate entries.
-
-.admin.entryprops.link=Entry Properties
-.admin.entryprops.text=View the properties set on a particular entry.
-
-.admin.faq.link=FAQ Tools
-.admin.faq.text=Allows you to manipulate the FAQ.
-
-.admin.file_edit.link=File Edit
-.admin.file_edit.text=Allows you to edit various include files.
-
-.admin.invites.link=Invite Code Management
-.admin.invites.text=View and manage invite codes.
-
-.admin.logout_user.link=Logout User
-.admin.logout_user.text=Logs a user out of the site.
-
-.admin.memcache.link=Memcache Overview
-.admin.memcache.text=Shows current memcache conditions.
-
-.admin.memcache_view.link=Memcache View
-.admin.memcache_view.text=Shows current memcache details.
-
-.admin.mysql.link=MySQL Status
-.admin.mysql.text=Shows current MySQL status.
-
-.admin.navtag.link=Navtag Edit
-.admin.navtag.text=Allows you to tag pages for navigation.
-
-.admin.pay.link=Payment Managements
-.admin.pay.text=Review payment details.
-
-.admin.priv.link=Privilege Management
-.admin.priv.text=View privs by priv or by user. Some priv lists are private.
-
-.admin.propedit.link=User Property Edit
-.admin.propedit.text=Allows you to view and edit userprops.
-
-.admin.recent_comments.link=Recent Comments
-.admin.recent_comments.text=Allows you to view a user's recent comments.
-
-.admin.sitemessages_add.link=Site Messages - Add
-.admin.sitemessages_add.text=Add new site-wide messages.
-
-.admin.sitemessages_manage.link=Site Messages - Manage
-.admin.sitemessages_manage.text=View and manipulate site-wide messages.
-
-.admin.spamreports.link=Spam Reports
-.admin.spamreports.text=View and handle reports of spam.
-
-.admin.stats.link=Business Statistics
-.admin.stats.text=Detailed breakdown of business statistics
-
-.admin.statushistory.link=Statushistory
-.admin.statushistory.text=Shows you a user's statushistory.
-
-.admin.styleinfo.link=Style Info
-.admin.styleinfo.text=Shows you a user's style information.
-
-.admin.sysban.link=Sysban Management
-.admin.sysban.text=Set and manage sysbans.
-
-.admin.theschwartz.link=TheSchwartz Queue/Error Viewer
-.admin.theschwartz.text=View the status of jobs in the TheSchwartz queue.
-
-.admin.translate.link=Translation & Site Copy
-.admin.translate.text=View and edit the site copy and translations.
-
-.admin.userlog.link=Userlog Viewer
-.admin.userlog.text=Shows you a user's logged actions.
-
-.anysupportpriv=any support priv
-.devserver=dev server
-
-.needspriv=needs
-.needs_one_of=needs one of
-
-
-
-
-
-
-
diff -r f4fcc06b2940 -r 61913b5952d1 t/routing.t
--- a/t/routing.t Thu Oct 28 10:15:22 2010 +0800
+++ b/t/routing.t Thu Oct 28 11:06:03 2010 +0800
@@ -1,6 +1,6 @@
# -*-perl-*-
use strict;
-use Test::More tests => 186;
+use Test::More tests => 194;
use lib "$ENV{LJHOME}/cgi-bin";
# don't let DW::Routing load DW::Controller subclasses
@@ -217,7 +217,37 @@ handle_request( "/test app implied_forma
handle_request( "/test app implied_format (app)" , "/test/app/all_format.json", 1, "it_worked_app_af" ); # 3 test
# 186
-use Data::Dumper;
+DW::Routing->register_string( "/xx3/index", \&handler, app => 1, args => "it_worked_redir" );
+
+$expected_format = 'html';
+handle_request( "/xx3" , "/xx3/", 1, "it_worked_redir" ); # 3 tests
+# 189
+
+handle_request( "/xx3" , "/xx3/index", 1, "it_worked_redir" ); # 3 tests
+# 192
+
+handle_redirect( '/xx3', '/xx3/' );
+# 194
+
+sub handle_redirect {
+ my ( $uri, $expected ) = @_;
+
+ $DW::Request::determined = 0;
+ $DW::Request::cur_req = undef;
+
+ my $req = HTTP::Request->new(GET=>"$uri");
+
+ my $opts = DW::Routing->get_call_opts( uri => $uri );
+
+ return fail( "Opts is undef" ) unless $opts;
+
+ my $hash = $opts->call_opts;
+ return fail( "No call opts" ) unless $hash && $hash->{sub};
+
+ is( $hash->{sub}, \&DW::Routing::_redirect_helper );
+ is( $hash->{args}, $expected );
+}
+
sub handle_request {
my ( $name, $uri, $valid, $expected, %opts ) = @_;
diff -r f4fcc06b2940 -r 61913b5952d1 views/admin/index.tt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/views/admin/index.tt Thu Oct 28 11:06:03 2010 +0800
@@ -0,0 +1,37 @@
+[%# admin/index.tt
+
+Admin action list index pages
+
+Authors:
+ Andrea Nall <anall@andreanall.com>
+ Denise Paolucci <denise@dreamwidth.org>
+ Sophie Hamilton <dw-bugzilla@theblob.org>
+
+This program is free software; you may redistribute it and/or modify it under
+the same terms as Perl itself. For a copy of the license, please reference
+'perldoc perlartistic' or 'perldoc perlgpl'.
+
+%][%- sections.title = title_ml | ml -%]
+[%- sections.head = BLOCK %]
+<style type="text/css">
+.item {margin-bottom: 15px;}
+.item.needspriv div, .item.needspriv a {color: #A0A0A0;}
+.itemhead {font-size: bigger; font-weight: bold;}
+.itemdef {margin-left: 2em;}
+.itemprivs {font-size: smaller; font-weight: normal; color: #707070;}
+</style>
+[%- END -%]
+
+[%- IF ml_scope -%][%- CALL dw.ml_scope( ml_scope ) -%][%- END -%]
+[%- IF description_ml -%]<p>[%- description_ml | ml -%][%- END -%]
+
+[%- FOREACH p IN pages -%][%- p.link = p.link_ml | ml -%][%- END -%]
+<ul>[% FOREACH p IN pages.sort_by_key( 'link' ) %]
+<li class='item[%- p.haspriv ? "" : " needspriv" -%]'><div class='itemhead'><a href='[%- p.path -%]'>[%- p.link -%]</a> [%- IF p.gotprivs.size OR p.needsprivs.size -%]<span class='itemprivs'>
+([%- IF p.haspriv -%]
+<b>[%- p.gotprivs.join("</b>, <b>") -%]</b>
+[%- ELSE -%]
+<b>[%- ( p.needsprivs.size > 1 ? '.needs_one_of' : '.needspriv' ) | ml -%]: [%- p.needsprivs.join("</b>, <b>") -%]</b>
+[%- END -%])
+</span>[%- END -%]</div><div class='itemdef'>[%- p.description_ml | ml -%]</div></li>
+[% END %]</ul>
diff -r f4fcc06b2940 -r 61913b5952d1 views/admin/index.tt.text
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/views/admin/index.tt.text Thu Oct 28 11:06:03 2010 +0800
@@ -0,0 +1,97 @@
+;; -*- coding: utf-8 -*-
+
+.admin.title=Admin Tools
+
+.admin.capability.link=Capability Edit
+.admin.capability.text=For editing user capabilities.
+
+.admin.cluster.link=Cluster Status
+.admin.cluster.text=Get information on cluster availability.
+
+.admin.console.link=Console
+.admin.console.text=For general input; usable by all users to an extent.
+
+.admin.dbschema.link=Database Schema
+.admin.dbschema.text=Shows the database schema.
+
+.admin.dupkiller.link=Duplicate Entry Killer
+.admin.dupkiller.text=Checks for (and kills) duplicate entries.
+
+.admin.entryprops.link=Entry Properties
+.admin.entryprops.text=View the properties set on a particular entry.
+
+.admin.faq.link=FAQ Tools
+.admin.faq.text=Allows you to manipulate the FAQ.
+
+.admin.file_edit.link=File Edit
+.admin.file_edit.text=Allows you to edit various include files.
+
+.admin.invites.link=Invite Code Management
+.admin.invites.text=View and manage invite codes.
+
+.admin.logout_user.link=Logout User
+.admin.logout_user.text=Logs a user out of the site.
+
+.admin.memcache.link=Memcache Overview
+.admin.memcache.text=Shows current memcache conditions.
+
+.admin.memcache_view.link=Memcache View
+.admin.memcache_view.text=Shows current memcache details.
+
+.admin.mysql.link=MySQL Status
+.admin.mysql.text=Shows current MySQL status.
+
+.admin.navtag.link=Navtag Edit
+.admin.navtag.text=Allows you to tag pages for navigation.
+
+.admin.pay.link=Payment Managements
+.admin.pay.text=Review payment details.
+
+.admin.priv.link=Privilege Management
+.admin.priv.text=View privs by priv or by user. Some priv lists are private.
+
+.admin.propedit.link=User Property Edit
+.admin.propedit.text=Allows you to view and edit userprops.
+
+.admin.recent_comments.link=Recent Comments
+.admin.recent_comments.text=Allows you to view a user's recent comments.
+
+.admin.sitemessages_add.link=Site Messages - Add
+.admin.sitemessages_add.text=Add new site-wide messages.
+
+.admin.sitemessages_manage.link=Site Messages - Manage
+.admin.sitemessages_manage.text=View and manipulate site-wide messages.
+
+.admin.spamreports.link=Spam Reports
+.admin.spamreports.text=View and handle reports of spam.
+
+.admin.statushistory.link=Statushistory
+.admin.statushistory.text=Shows you a user's statushistory.
+
+.admin.styleinfo.link=Style Info
+.admin.styleinfo.text=Shows you a user's style information.
+
+.admin.sysban.link=Sysban Management
+.admin.sysban.text=Set and manage sysbans.
+
+.admin.theschwartz.link=TheSchwartz Queue/Error Viewer
+.admin.theschwartz.text=View the status of jobs in the TheSchwartz queue.
+
+.admin.translate.link=Translation & Site Copy
+.admin.translate.text=View and edit the site copy and translations.
+
+.admin.userlog.link=Userlog Viewer
+.admin.userlog.text=Shows you a user's logged actions.
+
+.anysupportpriv=any support priv
+.devserver=dev server
+
+.needspriv=needs
+.needs_one_of=needs one of
+
+
+
+
+
+
+
diff -r f4fcc06b2940 -r 61913b5952d1 views/admin/rename.tt
--- a/views/admin/rename.tt Thu Oct 28 10:15:22 2010 +0800
+++ b/views/admin/rename.tt Thu Oct 28 11:06:03 2010 +0800
@@ -9,8 +9,9 @@ the same terms as Perl itself. For a co
the same terms as Perl itself. For a copy of the license, please reference
'perldoc perlartistic' or 'perldoc perlgpl'.
%]
+[%- sections.title = '.title' | ml -%]
-[% sections.title = '.title' | ml %]
+<a href="[%site.root%]/admin/rename/new">[% '.new.link' | ml %]</a>
[% IF renames %]
[% IF renames.size == 0 %]
@@ -35,7 +36,7 @@ the same terms as Perl itself. For a co
[% IF user %]
<p>
-<a href="[%site.root%]/admin/rename">Return to renames lookup</a>
+<a href="[%site.root%]/admin/rename/">Return to renames lookup</a>
</p>
[% ELSE %]
<form method="GET">
diff -r f4fcc06b2940 -r 61913b5952d1 views/admin/rename.tt.text
--- a/views/admin/rename.tt.text Thu Oct 28 10:15:22 2010 +0800
+++ b/views/admin/rename.tt.text Thu Oct 28 11:06:03 2010 +0800
@@ -1,4 +1,9 @@
;; -*- coding: utf-8 -*-
+
+.admin.link=Renames
+.admin.text=Manage renames
+
+.new.link=Create Rename
.renames.list.empty=No renames involving "[[user]]".
diff -r f4fcc06b2940 -r 61913b5952d1 views/admin/stats.tt.text
--- a/views/admin/stats.tt.text Thu Oct 28 10:15:22 2010 +0800
+++ b/views/admin/stats.tt.text Thu Oct 28 11:06:03 2010 +0800
@@ -1,3 +1,7 @@
;; -*- coding: utf-8 -*-
+.admin.link=Business Statistics
+.admin.text=Detailed breakdown of business statistics
+
.title=Business Statistics
+
--------------------------------------------------------------------------------
