988 lines
33 KiB
Perl
988 lines
33 KiB
Perl
|
|
|
||
|
|
#!/usr/bin/perl
|
||
|
|
#
|
||
|
|
# DW::Controller::Customize::Advanced
|
||
|
|
#
|
||
|
|
# This controller is for /customize/options and the helper functions for that view.
|
||
|
|
#
|
||
|
|
# Authors:
|
||
|
|
# R Hatch <ruth.s.hatch@gmail.com>
|
||
|
|
#
|
||
|
|
# Copyright (c) 2016 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::Customize::Advanced;
|
||
|
|
|
||
|
|
use strict;
|
||
|
|
use warnings;
|
||
|
|
use Digest::MD5;
|
||
|
|
use DW::Controller;
|
||
|
|
use DW::Routing;
|
||
|
|
use DW::Template;
|
||
|
|
use DW::Logic::MenuNav;
|
||
|
|
|
||
|
|
DW::Routing->register_string( '/customize/advanced', \&advanced_handler, app => 1 );
|
||
|
|
DW::Routing->register_string( '/customize/advanced/layerbrowse', \&layerbrowse_handler, app => 1 );
|
||
|
|
DW::Routing->register_string( '/customize/advanced/layers', \&layers_handler, app => 1 );
|
||
|
|
DW::Routing->register_string( '/customize/advanced/styles', \&styles_handler, app => 1 );
|
||
|
|
DW::Routing->register_string( '/customize/advanced/layersource', \&layersource_handler, app => 1 );
|
||
|
|
DW::Routing->register_string( '/customize/advanced/layeredit', \&layeredit_handler, app => 1 );
|
||
|
|
|
||
|
|
sub advanced_handler {
|
||
|
|
my ( $ok, $rv ) = controller();
|
||
|
|
return $rv unless $ok;
|
||
|
|
|
||
|
|
my $r = $rv->{r};
|
||
|
|
my $POST = $r->post_args;
|
||
|
|
my $u = $rv->{u};
|
||
|
|
my $remote = $rv->{remote};
|
||
|
|
my $no_layer_edit = LJ::Hooks::run_hook( "no_theme_or_layer_edit", $u );
|
||
|
|
|
||
|
|
my $vars;
|
||
|
|
$vars->{u} = $u;
|
||
|
|
$vars->{remote} = $remote;
|
||
|
|
$vars->{no_layer_edit} = $no_layer_edit;
|
||
|
|
|
||
|
|
return DW::Template->render_template( 'customize/advanced/index.tt', $vars );
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
sub layerbrowse_handler {
|
||
|
|
my ( $ok, $rv ) = controller();
|
||
|
|
return $rv unless $ok;
|
||
|
|
|
||
|
|
my $r = $rv->{r};
|
||
|
|
my $POST = $r->post_args;
|
||
|
|
my $u = $rv->{u};
|
||
|
|
my $remote = $rv->{remote};
|
||
|
|
my $GET = $r->get_args;
|
||
|
|
|
||
|
|
my $vars;
|
||
|
|
$vars->{u} = $u;
|
||
|
|
$vars->{remote} = $remote;
|
||
|
|
$vars->{expand} = $GET->{'expand'};
|
||
|
|
|
||
|
|
my $pub = LJ::S2::get_public_layers();
|
||
|
|
|
||
|
|
my $id;
|
||
|
|
if ( $GET->{'id'} ) {
|
||
|
|
if ( $GET->{'id'} =~ /^\d+$/ ) { # numeric
|
||
|
|
$id = $GET->{'id'};
|
||
|
|
}
|
||
|
|
else { # redist_uniq
|
||
|
|
$id = $pub->{ $GET->{'id'} }->{'s2lid'};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
my $dbr = LJ::get_db_reader();
|
||
|
|
|
||
|
|
my %layerinfo;
|
||
|
|
my @to_load = grep { /^\d+$/ } keys %$pub;
|
||
|
|
LJ::S2::load_layer_info( \%layerinfo, \@to_load );
|
||
|
|
|
||
|
|
my @s2_keys =
|
||
|
|
grep { /^\d+$/ && exists $pub->{$_}->{'b2lid'} && $pub->{$_}->{'b2lid'} == 0 } keys %$pub;
|
||
|
|
|
||
|
|
$vars->{pub} = $pub;
|
||
|
|
$vars->{s2_keys} = \@s2_keys;
|
||
|
|
|
||
|
|
$vars->{childsort} = sub {
|
||
|
|
my $unsortedchildren = shift;
|
||
|
|
my @sortedchildren = sort {
|
||
|
|
( $layerinfo{$b}{type} cmp $layerinfo{$a}{type} )
|
||
|
|
|| ( $layerinfo{$a}{name} cmp $layerinfo{$b}{name} )
|
||
|
|
} @$unsortedchildren;
|
||
|
|
|
||
|
|
return \@sortedchildren;
|
||
|
|
};
|
||
|
|
|
||
|
|
my $xlink = sub {
|
||
|
|
my $r = shift;
|
||
|
|
$r =~ s/\[class\[(\w+)\]\]/<a href=\"\#class.$1\">$1<\/a>/g;
|
||
|
|
$r =~ s/\[method\[(.+?)\]\]/<a href=\"\#meth.$1\">$1<\/a>/g;
|
||
|
|
$r =~ s/\[function\[(.+?)\]\]/<a href=\"\#func.$1\">$1<\/a>/g;
|
||
|
|
$r =~ s/\[member\[(.+?)\]\]/<a href=\"\#member.$1\">$1<\/a>/g;
|
||
|
|
return $r;
|
||
|
|
};
|
||
|
|
|
||
|
|
my $class;
|
||
|
|
my $s2info;
|
||
|
|
if ($id) {
|
||
|
|
LJ::S2::load_layers($id);
|
||
|
|
$s2info = S2::get_layer_all($id);
|
||
|
|
$class = $s2info->{'class'} || {};
|
||
|
|
|
||
|
|
$vars->{s2info} = $s2info;
|
||
|
|
$vars->{id} = $id;
|
||
|
|
$vars->{class} = $class;
|
||
|
|
|
||
|
|
# load layer info
|
||
|
|
my $layer = defined $pub->{$id} ? $pub->{$id} : LJ::S2::load_layer($id);
|
||
|
|
|
||
|
|
my $layerinfo = {};
|
||
|
|
LJ::S2::load_layer_info( $layerinfo, [$id] );
|
||
|
|
my $srcview =
|
||
|
|
exists $layerinfo->{$id}->{'source_viewable'}
|
||
|
|
? $layerinfo->{$id}->{'source_viewable'}
|
||
|
|
: undef;
|
||
|
|
|
||
|
|
# do they have access?
|
||
|
|
my $isadmin =
|
||
|
|
!defined $pub->{$id} && $remote && $remote->has_priv( 'siteadmin', 'styleview' );
|
||
|
|
my $can_manage = $remote && $remote->can_manage( LJ::load_userid( $layer->{userid} ) );
|
||
|
|
|
||
|
|
$vars->{srcview} = $srcview;
|
||
|
|
$vars->{isadmin} = $isadmin;
|
||
|
|
$vars->{can_manage} = $can_manage;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
my $xlink_args = sub {
|
||
|
|
my $r = shift;
|
||
|
|
return
|
||
|
|
unless $r =~ /^(.+?\()(.*)\)$/;
|
||
|
|
my ( $new, @args ) = ( $1, split( /\s*\,\s*/, $2 ) );
|
||
|
|
foreach (@args) {
|
||
|
|
s/^(\w+)/defined $class->{$1} ? "[class[$1]]" : $1/eg;
|
||
|
|
}
|
||
|
|
$new .= join( ", ", @args ) . ")";
|
||
|
|
$r = $new;
|
||
|
|
$xlink->($r);
|
||
|
|
};
|
||
|
|
|
||
|
|
my $format_value;
|
||
|
|
$format_value = sub {
|
||
|
|
my $v = shift;
|
||
|
|
|
||
|
|
if ( ref $v eq "HASH" ) {
|
||
|
|
if ( $v->{'_type'}
|
||
|
|
&& $v->{'_type'} eq "Color"
|
||
|
|
&& $v->{'as_string'} =~ /^#\w\w\w\w\w\w$/ )
|
||
|
|
{
|
||
|
|
my $ecolor = LJ::ehtml( $v->{'as_string'} );
|
||
|
|
$v =
|
||
|
|
"<span style=\"border: 1px solid #000000; padding-left: 2em; background-color: $ecolor\"> </span> <tt>$ecolor</tt>";
|
||
|
|
}
|
||
|
|
elsif ( defined $v->{'_type'} ) {
|
||
|
|
$v = BML::ml( '.propformat.object', { 'type' => LJ::ehtml( $v->{'_type'} ) } );
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if ( scalar(%$v) ) {
|
||
|
|
$v =
|
||
|
|
"<code>{</code><ul style='list-style: none; margin: 0 0 0 1.5em; padding: 0;'>"
|
||
|
|
. join(
|
||
|
|
"\n",
|
||
|
|
map {
|
||
|
|
"<li><b>"
|
||
|
|
. LJ::ehtml($_)
|
||
|
|
. "</b> → "
|
||
|
|
. $format_value->( $v->{$_} )
|
||
|
|
. ",</li>"
|
||
|
|
} keys %$v
|
||
|
|
) . "</ul><code>}</code>";
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$v = "<code>{}</code>";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
elsif ( ref $v eq "ARRAY" ) {
|
||
|
|
if ( scalar(@$v) ) {
|
||
|
|
$v =
|
||
|
|
"<code>[</code><ul style='list-style: none; margin: 0 0 0 1.5em; padding: 0;'>"
|
||
|
|
. join( "\n", map { "<li>" . $format_value->($_) . ",</li>" } @$v )
|
||
|
|
. "</ul><code>]</code>";
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$v = "<code>[]</code>";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$v = $v ne '' ? LJ::ehtml($v) : "<i>" . LJ::Lang::ml('.propformat.empty') . "</i>";
|
||
|
|
}
|
||
|
|
|
||
|
|
return $v;
|
||
|
|
};
|
||
|
|
|
||
|
|
$vars->{xlink} = $xlink;
|
||
|
|
$vars->{xlink_args} = $xlink_args;
|
||
|
|
$vars->{layer_is_active} =
|
||
|
|
sub { my $x = shift; LJ::Hooks::run_hook( "layer_is_active", $pub->{$x}->{uniq} ); };
|
||
|
|
$vars->{ehtml} = \&LJ::ehtml;
|
||
|
|
$vars->{defined} = sub { return defined $_; };
|
||
|
|
$vars->{format_value} = $format_value;
|
||
|
|
$vars->{layerinfo} = \%layerinfo;
|
||
|
|
|
||
|
|
return DW::Template->render_template( 'customize/advanced/layerbrowse.tt', $vars );
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
sub layers_handler {
|
||
|
|
my ( $ok, $rv ) = controller( authas => 1, form_auth => 1 );
|
||
|
|
return $rv unless $ok;
|
||
|
|
|
||
|
|
my $r = $rv->{r};
|
||
|
|
my $POST = $r->post_args;
|
||
|
|
my $u = $rv->{u};
|
||
|
|
my $remote = $rv->{remote};
|
||
|
|
my $no_layer_edit = LJ::Hooks::run_hook( "no_theme_or_layer_edit", $remote );
|
||
|
|
my $GET = $r->get_args;
|
||
|
|
my $authas = $u->user ne $remote->user ? "?authas=" . $u->user : "";
|
||
|
|
|
||
|
|
# id is optional
|
||
|
|
my $id;
|
||
|
|
$id = $POST->{'id'} if $POST->{'id'} && $POST->{'id'} =~ /^\d+$/;
|
||
|
|
|
||
|
|
# this catches core_hidden if it's set
|
||
|
|
$POST->{'parid'} ||= $POST->{'parid_hidden'};
|
||
|
|
|
||
|
|
my $pub = LJ::S2::get_public_layers();
|
||
|
|
my $ulay = LJ::S2::get_layers_of_user($u);
|
||
|
|
|
||
|
|
my $vars;
|
||
|
|
$vars->{u} = $u;
|
||
|
|
$vars->{remote} = $remote;
|
||
|
|
$vars->{no_layer_edit} = $no_layer_edit;
|
||
|
|
$vars->{pub} = $pub;
|
||
|
|
$vars->{ulay} = $ulay;
|
||
|
|
$vars->{authas} = $authas;
|
||
|
|
$vars->{authas_html} = $rv->{authas_html};
|
||
|
|
|
||
|
|
return error_ml('/customize/advanced/index.tt.error.advanced.editing.denied')
|
||
|
|
if $no_layer_edit;
|
||
|
|
|
||
|
|
# if we don't have a u, maybe they're an admin and can view stuff anyway?
|
||
|
|
my $noactions = 0;
|
||
|
|
my $viewall = $remote && $remote->has_priv( 'siteadmin', 'styleview' );
|
||
|
|
|
||
|
|
if ( $GET->{user} && $viewall ) {
|
||
|
|
return error_ml('/customize/advanced/layers.tt.error.cantuseonsystem')
|
||
|
|
if $GET->{user} eq 'system';
|
||
|
|
$noactions = 1; # don't let admins change anything
|
||
|
|
}
|
||
|
|
return error_ml('.error.cantbeauthenticated')
|
||
|
|
unless $u;
|
||
|
|
|
||
|
|
return error_ml(
|
||
|
|
(
|
||
|
|
$remote->{user} eq $u->{user}
|
||
|
|
? '/customize/advanced/layers.tt.error.youcantuseadvanced'
|
||
|
|
: '/customize/advanced/layers.tt.error.usercantuseadvanced'
|
||
|
|
),
|
||
|
|
undef,
|
||
|
|
{ authas => $rv->{authas_html} }
|
||
|
|
) unless $u->can_create_s2_styles || $viewall;
|
||
|
|
|
||
|
|
if ( $POST->{'action:create'} && !$noactions ) {
|
||
|
|
|
||
|
|
return error_ml('/customize/advanced/layers.tt.error.maxlayers')
|
||
|
|
if keys %$ulay >= $u->count_s2layersmax;
|
||
|
|
|
||
|
|
my $type = $POST->{'type'}
|
||
|
|
or return error_ml('/customize/advanced/layers.tt.error.nolayertypeselected');
|
||
|
|
my $parid = $POST->{'parid'} + 0
|
||
|
|
or return error_ml('/customize/advanced/layers.tt.error.badparentid');
|
||
|
|
return error_ml('/customize/advanced/layers.tt.error.invalidlayertype')
|
||
|
|
unless $type =~ /^layout|theme|user|i18nc?$/;
|
||
|
|
my $parent_type =
|
||
|
|
( $type eq "theme" || $type eq "i18n" || $type eq "user" ) ? "layout" : "core";
|
||
|
|
|
||
|
|
# parent ID is public layer
|
||
|
|
if ( $pub->{$parid} ) {
|
||
|
|
|
||
|
|
# of the wrong type
|
||
|
|
return error_ml('/customize/advanced/layers.tt.error.badparentid')
|
||
|
|
if $pub->{$parid}->{'type'} ne $parent_type;
|
||
|
|
|
||
|
|
# parent ID is user layer, or completely invalid
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return error_ml('.error.badparentid')
|
||
|
|
if !$ulay->{$parid} || $ulay->{$parid}->{'type'} != $parent_type;
|
||
|
|
}
|
||
|
|
|
||
|
|
my $id = LJ::S2::create_layer( $u, $parid, $type );
|
||
|
|
return error_ml('/customize/advanced/layers.tt.error.cantcreatelayer') unless $id;
|
||
|
|
|
||
|
|
my $lay = {
|
||
|
|
'userid' => $u->userid,
|
||
|
|
'type' => $type,
|
||
|
|
'b2lid' => $parid,
|
||
|
|
's2lid' => $id,
|
||
|
|
};
|
||
|
|
|
||
|
|
# help user out a bit, creating the beginning of their layer.
|
||
|
|
my $s2 = "layerinfo \"type\" = \"$type\";\n";
|
||
|
|
$s2 .= "layerinfo \"name\" = \"\";\n\n";
|
||
|
|
my $error;
|
||
|
|
unless ( LJ::S2::layer_compile( $lay, \$error, { 's2ref' => \$s2 } ) ) {
|
||
|
|
return error_ml( '/customize/advanced/layers.tt.error.cantsetuplayer',
|
||
|
|
{ 'errormsg' => $error } );
|
||
|
|
}
|
||
|
|
|
||
|
|
# redirect so they can't refresh and create a new layer again
|
||
|
|
return $r->redirect("$LJ::SITEROOT/customize/advanced/layers$authas");
|
||
|
|
}
|
||
|
|
|
||
|
|
# delete
|
||
|
|
if ( $POST->{'action:del'} && !$noactions ) {
|
||
|
|
|
||
|
|
my $id = $POST->{'id'} + 0;
|
||
|
|
my $lay = LJ::S2::load_layer($id);
|
||
|
|
return error_ml('/customize/advanced/layers.tt.error.layerdoesntexist')
|
||
|
|
unless $lay;
|
||
|
|
|
||
|
|
return error_ml('/customize/advanced/layers.tt.error.notyourlayer')
|
||
|
|
unless $lay->{userid} == $u->userid;
|
||
|
|
|
||
|
|
LJ::S2::delete_layer( $u, $id );
|
||
|
|
return $r->redirect("$LJ::SITEROOT/customize/advanced/layers$authas");
|
||
|
|
}
|
||
|
|
|
||
|
|
my %active_style = LJ::S2::get_style($u);
|
||
|
|
|
||
|
|
# set up indices for the sort, because it's easier than the convoluted logic
|
||
|
|
# of doing all this within the sort itself
|
||
|
|
my @parentlayernames;
|
||
|
|
my @layernames;
|
||
|
|
my @weight;
|
||
|
|
my %specialnamelayers;
|
||
|
|
my @layerids = keys %$ulay;
|
||
|
|
foreach my $layerid (@layerids) {
|
||
|
|
my $parent = $ulay->{ $ulay->{$layerid}->{b2lid} } || $pub->{ $ulay->{$layerid}->{b2lid} };
|
||
|
|
push @parentlayernames, $parent->{name};
|
||
|
|
|
||
|
|
my $layername = $ulay->{$layerid}->{name};
|
||
|
|
push @layernames, $layername;
|
||
|
|
|
||
|
|
my $weight = {
|
||
|
|
"Auto-generated Customizations" => 1, # auto-generated
|
||
|
|
"" => 2 # empty
|
||
|
|
}->{$layername};
|
||
|
|
push @weight, $weight;
|
||
|
|
|
||
|
|
$specialnamelayers{$layerid} = 1 if $weight;
|
||
|
|
}
|
||
|
|
|
||
|
|
my @sortedlayers = @layerids[
|
||
|
|
sort {
|
||
|
|
# alphabetically by parent layer's name
|
||
|
|
$parentlayernames[$a] cmp $parentlayernames[$b]
|
||
|
|
|
||
|
|
# special case empty names and auto-generated customizations (push them to the bottom)
|
||
|
|
|| $weight[$a] cmp $weight[$b]
|
||
|
|
|
||
|
|
# alphabetically by layer name (for regular layer names)
|
||
|
|
|| $layernames[$a] cmp $layernames[$b]
|
||
|
|
|
||
|
|
# Auto-generated customizations then layers with no name sorted by layer id
|
||
|
|
|| $layerids[$a] <=> $layerids[$b]
|
||
|
|
|
||
|
|
} 0 .. $#layerids
|
||
|
|
];
|
||
|
|
|
||
|
|
my @corelayers = map { $_, $pub->{$_}->{'majorversion'} }
|
||
|
|
sort { $pub->{$b}->{'majorversion'} <=> $pub->{$a}->{'majorversion'} }
|
||
|
|
grep { $pub->{$_}->{'b2lid'} == 0 && $pub->{$_}->{'type'} eq 'core' && /^\d+$/ }
|
||
|
|
keys %$pub;
|
||
|
|
|
||
|
|
my @layouts = ( '', '' );
|
||
|
|
push @layouts, map { $_, $pub->{$_}->{'name'} }
|
||
|
|
sort { $pub->{$a}->{'name'} cmp $pub->{$b}->{'name'} || $a <=> $b }
|
||
|
|
grep { $pub->{$_}->{'type'} eq 'layout' && /^\d+$/ }
|
||
|
|
keys %$pub;
|
||
|
|
if (%$ulay) {
|
||
|
|
my @ulayouts = ();
|
||
|
|
push @ulayouts, map {
|
||
|
|
$_,
|
||
|
|
LJ::Lang::ml(
|
||
|
|
'/customize/advanced/layers.tt.createlayer.layoutspecific.select.userlayer',
|
||
|
|
{ 'name' => $ulay->{$_}->{'name'}, 'id' => $_ } )
|
||
|
|
}
|
||
|
|
sort { $ulay->{$a}->{'name'} cmp $ulay->{$b}->{'name'} || $a <=> $b }
|
||
|
|
grep { $ulay->{$_}->{'type'} eq 'layout' }
|
||
|
|
keys %$ulay;
|
||
|
|
push @layouts, ( '', '---', @ulayouts ) if @ulayouts;
|
||
|
|
}
|
||
|
|
|
||
|
|
$vars->{authas_html} = $rv->{authas_html};
|
||
|
|
$vars->{noactions} = $noactions;
|
||
|
|
$vars->{layouts} = \@layouts;
|
||
|
|
$vars->{corelayers} = \@corelayers;
|
||
|
|
$vars->{sortedlayers} = \@sortedlayers;
|
||
|
|
$vars->{active_style} = \%active_style;
|
||
|
|
$vars->{specialnamelayers} = \%specialnamelayers;
|
||
|
|
$vars->{ehtml} = \&LJ::ehtml;
|
||
|
|
$vars->{ejs} = \&LJ::ejs;
|
||
|
|
|
||
|
|
return DW::Template->render_template( 'customize/advanced/layers.tt', $vars );
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
sub styles_handler {
|
||
|
|
my ( $ok, $rv ) = controller( authas => 1, form_auth => 1 );
|
||
|
|
return $rv unless $ok;
|
||
|
|
|
||
|
|
my $r = $rv->{r};
|
||
|
|
my $POST = $r->post_args;
|
||
|
|
my $u = $rv->{u};
|
||
|
|
my $remote = $rv->{remote};
|
||
|
|
my $no_layer_edit = LJ::Hooks::run_hook( "no_theme_or_layer_edit", $remote );
|
||
|
|
my $GET = $r->get_args;
|
||
|
|
my $authas = $u->user ne $remote->user ? "?authas=" . $u->user : "";
|
||
|
|
|
||
|
|
my $vars;
|
||
|
|
$vars->{u} = $u;
|
||
|
|
$vars->{remote} = $remote;
|
||
|
|
$vars->{no_layer_edit} = $no_layer_edit;
|
||
|
|
$vars->{authas_html} = $rv->{authas_html};
|
||
|
|
$vars->{post} = $POST;
|
||
|
|
|
||
|
|
# if we don't have a u, maybe they're an admin and can view stuff anyway?
|
||
|
|
my $noactions = 0;
|
||
|
|
my $viewall = $remote && $remote->has_priv( 'siteadmin', 'styleview' );
|
||
|
|
|
||
|
|
if ( $GET->{user} && $viewall ) {
|
||
|
|
return error_ml('/customize/advanced/styles.tt.error.cantuseonsystem')
|
||
|
|
if $GET->{user} eq 'system';
|
||
|
|
$noactions = 1; # don't let admins change anything
|
||
|
|
}
|
||
|
|
|
||
|
|
return error_ml(
|
||
|
|
(
|
||
|
|
$remote->{user} eq $u->{user}
|
||
|
|
? '/customize/advanced/styles.tt.error.youcantuseadvanced'
|
||
|
|
: '/customize/advanced/styles.tt.error.usercantuseadvanced'
|
||
|
|
),
|
||
|
|
undef,
|
||
|
|
{ authas => $rv->{authas_html} }
|
||
|
|
) unless $u->can_create_s2_styles || $viewall;
|
||
|
|
|
||
|
|
return error_ml('/customize/advanced/index.tt.error.advanced.editing.denied')
|
||
|
|
if $no_layer_edit;
|
||
|
|
|
||
|
|
# extra arguments for get requests
|
||
|
|
my $getextra = $u->user ne $remote->user ? "?authas=" . $u->user : '';
|
||
|
|
my $getextra_amp = $getextra ? "&authas=" . $u->user : '';
|
||
|
|
if ($noactions) {
|
||
|
|
$getextra = "?user=" . $u->user;
|
||
|
|
$getextra_amp = "&user=" . $u->user;
|
||
|
|
}
|
||
|
|
|
||
|
|
$vars->{getextra} = $getextra;
|
||
|
|
$vars->{getextra_amp} = $getextra_amp;
|
||
|
|
|
||
|
|
# style id to edit, if we have one
|
||
|
|
# if we have this we're assumed to be in 'edit' mode
|
||
|
|
my $id = $GET->{'id'} + 0;
|
||
|
|
|
||
|
|
my $dbh = LJ::get_db_writer();
|
||
|
|
|
||
|
|
# variables declared here, but only filled in if $id
|
||
|
|
my ( $core, $layout ); # scalars
|
||
|
|
my ( $pub, $ulay, $style ); # hashrefs
|
||
|
|
|
||
|
|
if ($id) {
|
||
|
|
|
||
|
|
# load style
|
||
|
|
$style = LJ::S2::load_style($id);
|
||
|
|
return error_ml('/customize/advanced/styles.tt.error.stylenotfound') unless $style;
|
||
|
|
|
||
|
|
# check that they own the style
|
||
|
|
return error_ml('/customize/advanced/styles.tt.error.notyourstyle')
|
||
|
|
unless $style->{userid} == $u->userid;
|
||
|
|
|
||
|
|
# use selected style
|
||
|
|
if ( $POST->{'action:usestyle'} && !$noactions ) {
|
||
|
|
|
||
|
|
# save to db and update user object
|
||
|
|
$u->set_prop(
|
||
|
|
{
|
||
|
|
stylesys => '2',
|
||
|
|
s2_style => $id
|
||
|
|
}
|
||
|
|
);
|
||
|
|
LJ::Hooks::run_hooks( 'apply_theme', $u );
|
||
|
|
return $r->redirect("styles$getextra");
|
||
|
|
}
|
||
|
|
|
||
|
|
# get public layers
|
||
|
|
$pub = LJ::S2::get_public_layers();
|
||
|
|
$vars->{pub} = $pub;
|
||
|
|
|
||
|
|
# get user layers
|
||
|
|
$ulay = LJ::S2::get_layers_of_user($u);
|
||
|
|
$vars->{ulay} = $ulay;
|
||
|
|
|
||
|
|
# find effective layerids being used
|
||
|
|
my %eff_layer = ();
|
||
|
|
my @other_layers = ();
|
||
|
|
foreach (qw(i18nc layout theme i18n user)) {
|
||
|
|
my $lid = $POST->{$_} eq "_other" ? $POST->{"other_$_"} : $POST->{$_};
|
||
|
|
next unless $lid;
|
||
|
|
$eff_layer{$_} = $lid;
|
||
|
|
|
||
|
|
unless ( $ulay->{ $eff_layer{$_} } || $pub->{ $eff_layer{$_} } ) {
|
||
|
|
push @other_layers, $lid;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# core lid (can't use user core layer)
|
||
|
|
$POST->{core} ||= $POST->{core_hidden};
|
||
|
|
$core = defined $POST->{core} ? $POST->{core} : $style->{layer}->{core};
|
||
|
|
my $highest_core;
|
||
|
|
map {
|
||
|
|
$highest_core = $_
|
||
|
|
if $pub->{$_}->{type} eq 'core'
|
||
|
|
&& /^\d+$/
|
||
|
|
&& $pub->{$_}->{majorversion} > $pub->{$highest_core}->{majorversion}
|
||
|
|
} keys %$pub;
|
||
|
|
unless ($core) {
|
||
|
|
$core = $highest_core;
|
||
|
|
|
||
|
|
# update in POST to keep things in sync
|
||
|
|
$POST->{core} = $highest_core;
|
||
|
|
}
|
||
|
|
$style->{layer}->{core} = $highest_core unless $style->{layer}->{core};
|
||
|
|
|
||
|
|
$vars->{core} = $core;
|
||
|
|
|
||
|
|
# layout lid
|
||
|
|
$layout = $POST->{'action:change'} ? $eff_layer{'layout'} : $style->{'layer'}->{'layout'};
|
||
|
|
|
||
|
|
# if we're changing core, clear everything
|
||
|
|
if ( $POST->{'core'}
|
||
|
|
&& $style->{'layer'}->{'core'}
|
||
|
|
&& $POST->{'core'} != $style->{'layer'}->{'core'} )
|
||
|
|
{
|
||
|
|
foreach (qw(i18nc layout theme i18n user)) {
|
||
|
|
delete $eff_layer{$_};
|
||
|
|
}
|
||
|
|
undef $layout;
|
||
|
|
}
|
||
|
|
|
||
|
|
# if we're changing layout, clear everything below
|
||
|
|
if ( $eff_layer{'layout'}
|
||
|
|
&& $style->{'layer'}->{'layout'}
|
||
|
|
&& $eff_layer{'layout'} != $style->{'layer'}->{'layout'} )
|
||
|
|
{
|
||
|
|
foreach (qw(theme i18n user)) {
|
||
|
|
delete $eff_layer{$_};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
### process edit actions
|
||
|
|
|
||
|
|
# delete
|
||
|
|
if ( $POST->{'action:delete'} && !$noactions ) {
|
||
|
|
LJ::S2::delete_user_style( $u, $id );
|
||
|
|
undef $id; # don't show form below
|
||
|
|
return $r->redirect("styles$getextra");
|
||
|
|
}
|
||
|
|
|
||
|
|
# save changes
|
||
|
|
if ( ( $POST->{'action:change'} || $POST->{'action:savechanges'} ) && !$noactions ) {
|
||
|
|
$vars->{post_action} = 'change';
|
||
|
|
|
||
|
|
# are they renaming their style?
|
||
|
|
if ( $POST->{'stylename'}
|
||
|
|
&& $style->{'name'}
|
||
|
|
&& $POST->{'stylename'} ne $style->{'name'} )
|
||
|
|
{
|
||
|
|
|
||
|
|
# update db
|
||
|
|
my $styleid = $style->{'styleid'};
|
||
|
|
LJ::S2::rename_user_style( $u, $styleid, $POST->{stylename} );
|
||
|
|
|
||
|
|
# update style object
|
||
|
|
$style->{'name'} = $POST->{'stylename'};
|
||
|
|
}
|
||
|
|
|
||
|
|
# load layer info of any "other" layers
|
||
|
|
my %other_info = ();
|
||
|
|
if (@other_layers) {
|
||
|
|
LJ::S2::load_layer_info( \%other_info, \@other_layers );
|
||
|
|
foreach (@other_layers) {
|
||
|
|
return error_ml( '/customize/advanced/styles.tt.error.layernotfound',
|
||
|
|
{ 'layer' => $_ } )
|
||
|
|
unless exists $other_info{$_};
|
||
|
|
return error_ml( '/customize/advanced/styles.tt.error.layernotpublic',
|
||
|
|
{ 'layer' => $_ } )
|
||
|
|
unless $other_info{$_}->{'is_public'};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# error check layer modifications
|
||
|
|
my $get_layername = sub {
|
||
|
|
my $lid = shift;
|
||
|
|
|
||
|
|
my $name;
|
||
|
|
$name = $pub->{$lid}->{'name'} if $pub->{$lid};
|
||
|
|
$name ||= $ulay->{$lid}->{'name'} if $ulay->{$lid};
|
||
|
|
$name ||= ml( '.layerid', { 'id' => $lid } );
|
||
|
|
|
||
|
|
return $name;
|
||
|
|
};
|
||
|
|
|
||
|
|
# check layer hierarchy
|
||
|
|
my $error_check = sub {
|
||
|
|
my ( $type, $parentid ) = @_;
|
||
|
|
|
||
|
|
my $lid = $eff_layer{$type};
|
||
|
|
next if !$lid;
|
||
|
|
|
||
|
|
my $layer = $ulay->{$lid} || $pub->{$lid} || LJ::S2::load_layer($lid);
|
||
|
|
my $parentname = $get_layername->($parentid);
|
||
|
|
my $layername = $get_layername->($lid);
|
||
|
|
|
||
|
|
# is valid layer type?
|
||
|
|
return error_ml(
|
||
|
|
'/customize/advanced/styles.tt.error.invalidlayertype',
|
||
|
|
{ 'name' => "<i>$layername</i>", 'type' => $type }
|
||
|
|
) if $layer->{'type'} ne $type;
|
||
|
|
|
||
|
|
# is a child?
|
||
|
|
return error_ml(
|
||
|
|
'/customize/advanced/styles.tt.error.layerhierarchymismatch',
|
||
|
|
{
|
||
|
|
'layername' => "<i>$layername</i>",
|
||
|
|
'type' => $type,
|
||
|
|
'parentname' => "<i>$parentname</i>"
|
||
|
|
}
|
||
|
|
) unless $layer->{'b2lid'} == $parentid;
|
||
|
|
|
||
|
|
return undef;
|
||
|
|
};
|
||
|
|
|
||
|
|
# check child layers of core
|
||
|
|
foreach my $type (qw(i18nc layout)) {
|
||
|
|
my $errmsg = $error_check->( $type, $core );
|
||
|
|
return error_ml($errmsg) if $errmsg;
|
||
|
|
}
|
||
|
|
|
||
|
|
# don't check sub-layout layers if there's no layout
|
||
|
|
if ($layout) {
|
||
|
|
|
||
|
|
# check child layers of selected layout
|
||
|
|
foreach my $type (qw(theme i18n user)) {
|
||
|
|
my $errmsg = $error_check->( $type, $layout );
|
||
|
|
return error_ml($errmsg) if $errmsg;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# save in database
|
||
|
|
my @layers = ( 'core' => $core );
|
||
|
|
push @layers, map { $_, $eff_layer{$_} } qw(i18nc layout i18n theme user);
|
||
|
|
LJ::S2::set_style_layers( $u, $style->{'styleid'}, @layers );
|
||
|
|
|
||
|
|
# redirect if they clicked the bottom button
|
||
|
|
return return $r->redirect("styles$getextra") if $POST->{'action:savechanges'};
|
||
|
|
}
|
||
|
|
$vars->{id} = $id;
|
||
|
|
$vars->{layout} = $layout;
|
||
|
|
$vars->{style} = $style;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
# load user styles
|
||
|
|
my $ustyle = LJ::S2::load_user_styles($u);
|
||
|
|
my @sortedustyles = sort { $ustyle->{$a} cmp $ustyle->{$b} || $a <=> $b } keys %$ustyle;
|
||
|
|
|
||
|
|
$vars->{sortedustyles} = \@sortedustyles;
|
||
|
|
$vars->{ustyle} = $ustyle;
|
||
|
|
|
||
|
|
# process create action
|
||
|
|
if ( ( $POST->{'action:create'} && $POST->{'stylename'} ) && !$noactions ) {
|
||
|
|
|
||
|
|
return error_ml( '/customize/advanced/styles.tt.error.maxstyles2',
|
||
|
|
{ 'numstyles' => scalar( keys %$ustyle ), 'maxstyles' => $u->count_s2stylesmax } )
|
||
|
|
if scalar( keys %$ustyle ) >= $u->count_s2stylesmax;
|
||
|
|
|
||
|
|
my $styleid = LJ::S2::create_style( $u, $POST->{'stylename'} );
|
||
|
|
return error_ml('/customize/advanced/styles.tt.error.cantcreatestyle') unless $styleid;
|
||
|
|
|
||
|
|
return $r->redirect("styles?id=$styleid$getextra_amp");
|
||
|
|
}
|
||
|
|
|
||
|
|
# load style currently in use
|
||
|
|
$u->preload_props('s2_style');
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
my $layerselect_sub = sub {
|
||
|
|
my ( $type, $b2lid ) = @_;
|
||
|
|
|
||
|
|
my @opts = ();
|
||
|
|
|
||
|
|
my $lid = $POST->{'action:change'} ? $POST->{$type} : $style->{layer}->{$type};
|
||
|
|
$lid = $POST->{"other_$type"} if $lid eq "_other";
|
||
|
|
|
||
|
|
# greps, and sorts a list
|
||
|
|
my $greplist = sub {
|
||
|
|
my $ref = shift;
|
||
|
|
return sort { $ref->{$a}->{'name'} cmp $ref->{$b}->{'name'} || $a <=> $b }
|
||
|
|
grep {
|
||
|
|
my $is_active = LJ::Hooks::run_hook( "layer_is_active", $ref->{$_}->{uniq} );
|
||
|
|
$ref->{$_}->{'type'} eq $type
|
||
|
|
&& $ref->{$_}->{'b2lid'} == $b2lid
|
||
|
|
&& ( !defined $is_active || $is_active )
|
||
|
|
&& !( $pub->{$_} && $pub->{$_}->{is_internal} )
|
||
|
|
&& # checking this directly here, as I don't care if the parent layers are internal
|
||
|
|
/^\d+$/
|
||
|
|
} keys %$ref;
|
||
|
|
};
|
||
|
|
|
||
|
|
# public layers
|
||
|
|
my $name = $type eq 'core' ? 'majorversion' : 'name';
|
||
|
|
push @opts, map { $_, $pub->{$_}->{$name} } $greplist->($pub);
|
||
|
|
|
||
|
|
# no user core layers
|
||
|
|
return { 'lid' => $lid, 'opts' => \@opts } if $type eq 'core';
|
||
|
|
|
||
|
|
# user layers / using an internal layer %
|
||
|
|
push @opts, ( '', '---' );
|
||
|
|
my $startsize = scalar(@opts);
|
||
|
|
|
||
|
|
# add the current layer if it's internal and the user is using it.
|
||
|
|
push @opts,
|
||
|
|
(
|
||
|
|
$lid,
|
||
|
|
LJ::Lang::ml(
|
||
|
|
'/customize/advanced/styles.tt.stylelayers.select.layout.user',
|
||
|
|
{ 'layername' => $pub->{$lid}->{'name'}, 'id' => $lid }
|
||
|
|
)
|
||
|
|
) if $lid && $pub->{$lid} && $pub->{$lid}->{is_internal};
|
||
|
|
push @opts, map {
|
||
|
|
$_,
|
||
|
|
LJ::Lang::ml(
|
||
|
|
'/customize/advanced/styles.tt.stylelayers.select.layout.user',
|
||
|
|
{ 'layername' => $ulay->{$_}->{'name'}, 'id' => $_ }
|
||
|
|
)
|
||
|
|
} $greplist->($ulay);
|
||
|
|
|
||
|
|
# if we didn't push anything above, remove dividing line %
|
||
|
|
pop @opts, pop @opts unless scalar(@opts) > $startsize;
|
||
|
|
|
||
|
|
# add option for other layerids
|
||
|
|
push @opts,
|
||
|
|
(
|
||
|
|
'_other', LJ::Lang::ml('/customize/advanced/styles.tt.stylelayers.select.layout.other')
|
||
|
|
);
|
||
|
|
|
||
|
|
# add blank option to beginning of list
|
||
|
|
unshift @opts, ( '', @opts ? '' : ' ' );
|
||
|
|
return { 'lid' => $lid, 'opts' => \@opts };
|
||
|
|
};
|
||
|
|
|
||
|
|
$vars->{layerselect_sub} = $layerselect_sub;
|
||
|
|
$vars->{ehtml} = \&LJ::ehtml;
|
||
|
|
|
||
|
|
return DW::Template->render_template( 'customize/advanced/styles.tt', $vars );
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
sub layersource_handler {
|
||
|
|
my ( $ok, $rv ) = controller();
|
||
|
|
return $rv unless $ok;
|
||
|
|
|
||
|
|
my $r = $rv->{r};
|
||
|
|
my $POST = $r->post_args;
|
||
|
|
my $GET = $r->get_args;
|
||
|
|
my $u = $rv->{u};
|
||
|
|
my $remote = $rv->{remote};
|
||
|
|
my $no_layer_edit = LJ::Hooks::run_hook( "no_theme_or_layer_edit", $u );
|
||
|
|
|
||
|
|
my $pub = LJ::S2::get_public_layers();
|
||
|
|
|
||
|
|
my $dbr = LJ::get_db_reader();
|
||
|
|
|
||
|
|
my $id = $GET->{'id'};
|
||
|
|
return $r->redirect('layerbrowse') unless $id =~ /^\d+$/;
|
||
|
|
|
||
|
|
my $lay = defined $pub->{$id} ? $pub->{$id} : LJ::S2::load_layer($id);
|
||
|
|
return error_ml('/customize/advanced/layerbrowse.tt.error.layerdoesntexist')
|
||
|
|
unless $lay;
|
||
|
|
|
||
|
|
my $layerinfo = {};
|
||
|
|
LJ::S2::load_layer_info( $layerinfo, [$id] );
|
||
|
|
my $srcview =
|
||
|
|
exists $layerinfo->{$id}->{'source_viewable'}
|
||
|
|
? $layerinfo->{$id}->{'source_viewable'}
|
||
|
|
: undef;
|
||
|
|
|
||
|
|
# authorized to view this layer?
|
||
|
|
my $isadmin = !defined $pub->{$id} && $remote && $remote->has_priv( 'siteadmin', 'styleview' );
|
||
|
|
|
||
|
|
# public styles are pulled from the system account, so we don't
|
||
|
|
# want to check privileges in case they're private styles
|
||
|
|
return error_ml('/customize/advanced/layerbrowse.tt.error.cantviewlayer')
|
||
|
|
unless defined $pub->{$id} && ( !defined $srcview || $srcview != 0 )
|
||
|
|
|| $srcview == 1
|
||
|
|
|| $isadmin
|
||
|
|
|| $remote && $remote->can_manage( LJ::load_userid( $lay->{userid} ) );
|
||
|
|
|
||
|
|
my $s2code = LJ::S2::load_layer_source($id);
|
||
|
|
|
||
|
|
# get html version of the code?
|
||
|
|
if ( $GET->{'fmt'} eq "html" ) {
|
||
|
|
my $html;
|
||
|
|
my ( $md5, $save_cache );
|
||
|
|
if ( $pub->{$id} ) {
|
||
|
|
|
||
|
|
# let's see if we have it cached
|
||
|
|
$md5 = Digest::MD5::md5_hex($s2code);
|
||
|
|
my $cache =
|
||
|
|
$dbr->selectrow_array("SELECT value FROM blobcache WHERE bckey='s2html-$id'");
|
||
|
|
if ( $cache =~ s/^\[$md5\]// ) {
|
||
|
|
$html = $cache;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$save_cache = 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
unless ($html) {
|
||
|
|
my $cr = new S2::Compiler;
|
||
|
|
$cr->compile_source(
|
||
|
|
{
|
||
|
|
'source' => \$s2code,
|
||
|
|
'output' => \$html,
|
||
|
|
'format' => "html",
|
||
|
|
'type' => $pub->{$id}->{'type'},
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($save_cache) {
|
||
|
|
my $dbh = LJ::get_db_writer();
|
||
|
|
$dbh->do( "REPLACE INTO blobcache (bckey, dateupdate, value) VALUES (?,NOW(),?)",
|
||
|
|
undef, "s2html-$id", "[$md5]$html" );
|
||
|
|
}
|
||
|
|
$r->print($html);
|
||
|
|
return $r->OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
# return text version
|
||
|
|
$r->content_type("text/plain");
|
||
|
|
my $ua = $r->header_in("User-Agent");
|
||
|
|
if ( $ua && $ua =~ /\bMSIE\b/ ) {
|
||
|
|
my $filename = "s2source-$id.txt";
|
||
|
|
$r->header_out( 'Content-Disposition' => "attachment; filename=$filename" );
|
||
|
|
}
|
||
|
|
|
||
|
|
$r->print($s2code);
|
||
|
|
return $r->OK;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
sub layeredit_handler {
|
||
|
|
my ( $ok, $rv ) = controller();
|
||
|
|
return $rv unless $ok;
|
||
|
|
|
||
|
|
my $r = $rv->{r};
|
||
|
|
my $POST = $r->post_args;
|
||
|
|
my $GET = $r->get_args;
|
||
|
|
my $u = $rv->{u};
|
||
|
|
my $remote = $rv->{remote};
|
||
|
|
my $no_layer_edit = LJ::Hooks::run_hook( "no_theme_or_layer_edit", $u );
|
||
|
|
|
||
|
|
my $vars;
|
||
|
|
|
||
|
|
# we need a valid id
|
||
|
|
my $id;
|
||
|
|
$id = $GET->{'id'} if $GET->{'id'} =~ /^\d+$/;
|
||
|
|
return error_ml('/customize/advanced/layeredit.tt.error.nolayer')
|
||
|
|
unless $id;
|
||
|
|
|
||
|
|
return error_ml('/customize/advanced/index.tt.error.advanced.editing.denied')
|
||
|
|
if $no_layer_edit;
|
||
|
|
|
||
|
|
# load layer
|
||
|
|
my $lay = LJ::S2::load_layer($id);
|
||
|
|
return error_ml('/customize/advanced/layers.tt.error.layerdoesntexist')
|
||
|
|
unless $lay;
|
||
|
|
|
||
|
|
# if the b2lid of this layer has been remapped to a new layerid
|
||
|
|
# then update the b2lid mapping for this layer
|
||
|
|
my $b2lid = $lay->{b2lid};
|
||
|
|
if ( $b2lid && $LJ::S2LID_REMAP{$b2lid} ) {
|
||
|
|
LJ::S2::b2lid_remap( $remote, $id, $b2lid );
|
||
|
|
$lay->{b2lid} = $LJ::S2LID_REMAP{$b2lid};
|
||
|
|
}
|
||
|
|
|
||
|
|
# get u of user they are acting as
|
||
|
|
$u = LJ::load_userid( $lay->{userid} );
|
||
|
|
|
||
|
|
# is authorized admin for this layer?
|
||
|
|
return error_ml('/customize/advanced/layeredit.tt.error.layerunauthorized')
|
||
|
|
unless $u && $remote->can_manage($u);
|
||
|
|
|
||
|
|
# check priv and ownership
|
||
|
|
return error_ml('/customize/advanced/layeredit.tt.error.stylesunauthorized')
|
||
|
|
unless $u->can_create_s2_styles;
|
||
|
|
|
||
|
|
# at this point, they are authorized, allow viewing & editing
|
||
|
|
|
||
|
|
# get s2 code from db - use writer so we know it's up-to-date
|
||
|
|
my $dbh = LJ::get_db_writer();
|
||
|
|
my $s2code = LJ::S2::load_layer_source( $lay->{s2lid} );
|
||
|
|
|
||
|
|
# we tried to compile something
|
||
|
|
my $build;
|
||
|
|
if ( $POST->{'action'} eq "compile" ) {
|
||
|
|
return error_ml("error.invalidform") unless LJ::check_form_auth( $POST->{lj_form_auth} );
|
||
|
|
|
||
|
|
$build = "<b>S2 Compiler Output</b> <em>at " . scalar(localtime) . "</em><br />\n";
|
||
|
|
|
||
|
|
my $error;
|
||
|
|
$POST->{'s2code'} =~ tr/\r//d; # just in case
|
||
|
|
unless ( LJ::S2::layer_compile( $lay, \$error, { 's2ref' => \$POST->{'s2code'} } ) ) {
|
||
|
|
|
||
|
|
$error =~ s/LJ::S2,.+//s;
|
||
|
|
$error =~ s!, .+?(src/s2|cgi-bin)/!, !g;
|
||
|
|
|
||
|
|
$error =~
|
||
|
|
s/^Compile error: line (\d+), column (\d+)/Compile error: <a href="javascript:moveCursor($1-1,$2)">line $1, column $2<\/a>/;
|
||
|
|
|
||
|
|
$build .=
|
||
|
|
"Error compiling layer:\n<pre style=\"border-left: 1px red solid\">$error</pre>";
|
||
|
|
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
$build .= "Compiled with no errors.\n";
|
||
|
|
}
|
||
|
|
$r->print($build);
|
||
|
|
return $r->OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
# load layer info
|
||
|
|
my $layinf = {};
|
||
|
|
LJ::S2::load_layer_info( $layinf, [$id] );
|
||
|
|
|
||
|
|
# find a title to display on this page
|
||
|
|
my $type = $layinf->{$id}->{'type'};
|
||
|
|
my $name = $layinf->{$id}->{'name'};
|
||
|
|
|
||
|
|
# find name of parent layer if this is a child layer
|
||
|
|
if ( !$name && $type =~ /^(user|theme|i18n)$/ ) {
|
||
|
|
my $par = $lay->{'b2lid'} + 0;
|
||
|
|
LJ::S2::load_layer_info( $layinf, [$par] );
|
||
|
|
$name = $layinf->{$par}->{'name'};
|
||
|
|
}
|
||
|
|
|
||
|
|
# Only use the layer name if there is one and it's more than just whitespace
|
||
|
|
my $title = "[$type] ";
|
||
|
|
$title .= $name && $name =~ /[^\s]/ ? "$name [\#$id]" : "Layer \#$id";
|
||
|
|
$vars->{build} = "Loaded layer $id.";
|
||
|
|
$vars->{title} = $title;
|
||
|
|
$vars->{s2code} = $s2code;
|
||
|
|
|
||
|
|
return DW::Template->render_template( 'customize/advanced/layeredit.tt',
|
||
|
|
$vars, { no_sitescheme => 1 } );
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
1;
|