init
This commit is contained in:
29
livejournal/htdocs/customize/advanced/index.bml
Executable file
29
livejournal/htdocs/customize/advanced/index.bml
Executable file
@@ -0,0 +1,29 @@
|
||||
<?page
|
||||
title=>Advanced Customization
|
||||
body<=
|
||||
<?_code
|
||||
LJ::set_active_crumb('advcustomize');
|
||||
return;
|
||||
_code?>
|
||||
|
||||
<?h1 Disclaimer h1?>
|
||||
<?p
|
||||
Unless you're a programmer or web designer, most users should stay away from this area and use
|
||||
the <a href="/customize/">main customization area</a>, which is designed for anybody to use.
|
||||
p?>
|
||||
|
||||
<?h1 Documentation h1?>
|
||||
<?p Before you jump into tweaking/programming S2, you should understand how it works. p?>
|
||||
<ul>
|
||||
<li><a href="/doc/s2/">S2 Documentation</a> -- under construction, but some good content</li>
|
||||
<li><a href="layerbrowse.bml">Public Layers</a> -- system layers (good reference & place to learn)</li>
|
||||
</ul>
|
||||
|
||||
<?h1 Advanced Options h1?>
|
||||
<ul>
|
||||
<li><a href="layers.bml">Your Layers</a> -- create/manage your layers</li>
|
||||
<li><a href="styles.bml">Your Styles</a> -- create/manage your styles</li>
|
||||
</ul>
|
||||
|
||||
<=body
|
||||
page?>
|
||||
308
livejournal/htdocs/customize/advanced/layerbrowse.bml
Executable file
308
livejournal/htdocs/customize/advanced/layerbrowse.bml
Executable file
@@ -0,0 +1,308 @@
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST $title $body);
|
||||
|
||||
LJ::set_active_crumb('layerbrowse');
|
||||
|
||||
# start of content
|
||||
$body = BML::ml("Backlink", {
|
||||
'link' => './',
|
||||
'text' => 'Advanced Customization',
|
||||
});
|
||||
|
||||
my $err = sub {
|
||||
$title = "Error";
|
||||
$body = shift;
|
||||
return;
|
||||
};
|
||||
|
||||
my $pub = LJ::S2::get_public_layers();
|
||||
|
||||
my $id;
|
||||
if ($GET{'id'} =~ /^\d+$/) { # numeric
|
||||
$id = $GET{'id'};
|
||||
} elsif ($GET{'id'}) { # redist_uniq
|
||||
$id = $pub->{$GET{'id'}}->{'s2lid'};
|
||||
}
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
# show the public layers
|
||||
unless ($id) {
|
||||
$title = "Public Layers";
|
||||
my %layerinfo;
|
||||
my @to_load = grep { /^\d+$/ } keys %$pub;
|
||||
LJ::S2::load_layer_info(\%layerinfo, \@to_load);
|
||||
|
||||
my $recurse = sub {
|
||||
my $self = shift;
|
||||
my $lid = shift; # layer id
|
||||
my $lay = $pub->{$lid};
|
||||
return unless $lay;
|
||||
|
||||
# set to true if the layer is not core and is not a layout
|
||||
my $is_child = $lay->{'type'} ne 'core' && $lay->{'type'} ne 'layout';
|
||||
|
||||
my $typedes = " ($lay->{'type'}" . (! $is_child ? ": <b>$lid</b>" : '') . ")";
|
||||
|
||||
# show link to detailed view
|
||||
$body .= "<li><a href='layerbrowse.bml?id=$lay->{'uniq'}'>" . LJ::ehtml($layerinfo{$lid}->{'name'});
|
||||
$body .= "</a>$typedes</li>";
|
||||
|
||||
# done unless there are children to recurse through
|
||||
return unless ! $is_child && $lay->{'children'};
|
||||
|
||||
# if we're not expanding these children, stop and show a link
|
||||
if ($lay->{'type'} eq 'layout' && $GET{'expand'} != $lid) {
|
||||
$body .= "<ul><li>[<a href='layerbrowse.bml?expand=$lid'>";
|
||||
$body .= scalar(@{$lay->{'children'}}) . " children...</a>]</li></ul>";
|
||||
return;
|
||||
}
|
||||
|
||||
# expand children
|
||||
$body .= "<ul>";
|
||||
foreach (@{$lay->{'children'}}) {
|
||||
$self->($self, $_);
|
||||
}
|
||||
$body .= "</ul>";
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
# iterate through core layers
|
||||
$body .= "<ul>";
|
||||
foreach (grep { $pub->{$_}->{'b2lid'} == 0 } grep { /^\d+$/ } keys %$pub) {
|
||||
$recurse->($recurse, $_); # start from the top
|
||||
}
|
||||
$body .= "</ul>";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
### details on a specific layer ###
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
# load layer info
|
||||
my $layer = defined $pub->{$id} ? $pub->{$id} : LJ::S2::load_layer($id);
|
||||
return $err->("The specified layer does not exist.")
|
||||
unless $layer;
|
||||
|
||||
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} && # public styles are pulled from the system
|
||||
(LJ::check_priv($remote, 'canview', 'styles') || # account, so we don't want to check privileges
|
||||
LJ::check_priv($remote, 'canview', '*')); # in case they're private styles
|
||||
return $err->("You are not authorized to view this layer.")
|
||||
unless defined $pub->{$id} || $srcview == 1 ||
|
||||
LJ::can_manage($remote, $layer->{'userid'}) ||
|
||||
$isadmin;
|
||||
|
||||
LJ::S2::load_layers($id);
|
||||
my $s2info = S2::get_layer_all($id);
|
||||
my $class = $s2info->{'class'} || {};
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
$body .= "<br />";
|
||||
# link to layer list if this is a public layer, otherwise user's layer list
|
||||
if (defined $pub->{$id}) {
|
||||
$body .= BML::ml('backlink', { 'link' => 'layerbrowse.bml', 'text' => 'Public Layers' }) . "\n";
|
||||
} else {
|
||||
$body .= BML::ml('backlink', { 'link' => "layers.bml", 'text' => 'Your Layers' }) . "\n";
|
||||
$body .= BML::ml('actionlink', { 'link' => "<a href='layeredit.bml?id=$id'>Edit Layer</a>" }) . "\n";
|
||||
}
|
||||
|
||||
if ($layer->{'b2lid'}) {
|
||||
$body .= "[<a href=\"layerbrowse.bml?id=$layer->{'b2lid'}\">Parent Layer</a>]\n";
|
||||
}
|
||||
if (defined $pub->{$id} && (! defined $srcview || $srcview != 0) ||
|
||||
$srcview == 1 ||
|
||||
LJ::can_manage($remote, $layer->{'userid'}) ||
|
||||
$isadmin) {
|
||||
|
||||
$body .= "[<a href=\"layersource.bml?id=$id\">Download</a>]\n";
|
||||
$body .= "[<a href=\"layersource.bml?id=$id&fmt=html\">View as HTML</a>]\n";
|
||||
}
|
||||
|
||||
# layerinfo
|
||||
if (my $info = $s2info->{'info'}) {
|
||||
$body .= "<?h1 Layer Info h1?>";
|
||||
$body .= "<table style='margin-bottom: 10px' border='1' cellpadding='2'>";
|
||||
foreach my $k (sort keys %$info) {
|
||||
my ($ek, $ev) = map { LJ::ehtml($_) } ($k, $info->{$k});
|
||||
$title = $ev if $k eq "name";
|
||||
$body .= "<tr><td><b>$ek</b></td><td>$ev</td></tr>\n";
|
||||
}
|
||||
$body .= "</table>";
|
||||
}
|
||||
|
||||
# sets
|
||||
if (my $set = $s2info->{'set'}) {
|
||||
$body .= "<?h1 Properties Set h1?>";
|
||||
$body .= "<table style='margin-bottom: 10px' border='1' cellpadding='2'>";
|
||||
foreach my $k (sort keys %$set) {
|
||||
my $v = $set->{$k};
|
||||
if (ref $v eq "HASH") {
|
||||
if ($v->{'_type'} eq "Color") {
|
||||
$v = "<span style=\"border: 1px solid #000000; padding-left: 2em; background-color: $v->{'as_string'}\"> </span> <tt>$v->{'as_string'}</tt>";
|
||||
} else {
|
||||
$v = "[unknown object type]";
|
||||
}
|
||||
} elsif (ref $v eq "ARRAY") {
|
||||
$v = "<i>List:</i> (" . join(", ", map { LJ::ehtml($_) } @$v) . ")";
|
||||
} else {
|
||||
$v = LJ::ehtml($v);
|
||||
}
|
||||
$body .= "<tr><td><b>$k</b></td><td>$v</td></tr>\n";
|
||||
}
|
||||
$body .= "</table>";
|
||||
}
|
||||
|
||||
# global functions
|
||||
my $gb = $s2info->{'global'};
|
||||
if (ref $gb eq "HASH" && %$gb) {
|
||||
$body .= "<?h1 Global Functions h1?>";
|
||||
$body .= "<table style='margin-bottom: 10px' border='1' cellpadding='2'>";
|
||||
foreach my $fname (sort keys %$gb) {
|
||||
my $rt = $gb->{$fname}->{'returntype'};
|
||||
if (defined $class->{$rt}) {
|
||||
$rt = "[class[$rt]]";
|
||||
}
|
||||
$xlink->(\$rt);
|
||||
my $ds = LJ::ehtml($gb->{$fname}->{'docstring'});
|
||||
$xlink->(\$ds);
|
||||
|
||||
my $args = $gb->{$fname}->{'args'};
|
||||
$xlink_args->(\$args);
|
||||
|
||||
$body .= "<tr><td><nobr><a name='func.$fname'><tt>$args : $rt</tt></a></nobr></td><td>$ds</td></tr>";
|
||||
}
|
||||
$body .= "</table>";
|
||||
}
|
||||
|
||||
|
||||
if (%$class)
|
||||
{
|
||||
# class index
|
||||
$body .= "<?h1 Classes h1?>";
|
||||
$body .= "<table style='margin-bottom: 10px'><tr valign='top' align='left'>";
|
||||
$body .= "<td width='50%'>Alphabetical";
|
||||
$body .= "<ul>";
|
||||
foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) {
|
||||
$body .= "<li><a href='#class.$cname'><b>$cname</b></a></li>\n";
|
||||
}
|
||||
$body .= "</ul>";
|
||||
$body .= "</td>";
|
||||
$body .= "<td width='50%'>Hierarchical";
|
||||
my $dumpsub = sub {
|
||||
my $self = shift;
|
||||
my $parent = shift;
|
||||
$body .= "<li><a href='#class.$parent'><b>$parent</b></a></li>\n"
|
||||
if $parent;
|
||||
my $didul = 0;
|
||||
foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) {
|
||||
next unless $class->{$cname}->{'parent'} eq $parent;
|
||||
unless ($didul++) { $body .= "<ul>"; }
|
||||
$self->($self, $cname);
|
||||
}
|
||||
if ($didul) { $body .= "</ul>"; }
|
||||
};
|
||||
$dumpsub->($dumpsub, "");
|
||||
$body .= "</td></tr></table>";
|
||||
|
||||
# classes
|
||||
foreach my $cname (sort { lc($a) cmp lc($b) } keys %$class) {
|
||||
$body .= "<a name='class.$cname'><?h1 $cname Class h1?></a>";
|
||||
my $ds = LJ::ehtml($class->{$cname}->{'docstring'});
|
||||
if ($class->{$cname}->{'parent'}) {
|
||||
$ds = "Child class of [class[$class->{$cname}->{'parent'}]]. $ds";
|
||||
}
|
||||
if ($ds) {
|
||||
$xlink->(\$ds);
|
||||
$body .= "<?p $ds p?>";
|
||||
}
|
||||
|
||||
# build functions & methods
|
||||
my (%func, %var);
|
||||
my $add = sub {
|
||||
my ($self, $aname) = @_;
|
||||
foreach (keys %{$class->{$aname}->{'funcs'}}) {
|
||||
$func{$_} = $class->{$aname}->{'funcs'}->{$_};
|
||||
$func{$_}->{'_declclass'} = $aname;
|
||||
}
|
||||
foreach (keys %{$class->{$aname}->{'vars'}}) {
|
||||
$var{$_} = $class->{$aname}->{'vars'}->{$_};
|
||||
$var{$_}->{'_declclass'} = $aname;
|
||||
}
|
||||
|
||||
my $parent = $class->{$aname}->{'parent'};
|
||||
$self->($self, $parent) if $parent;
|
||||
};
|
||||
$add->($add, $cname);
|
||||
|
||||
$body .= "<table style='margin-bottom: 10px' border='1' cellpadding='2'><?h2 Members h2?>" if %var;
|
||||
foreach (sort keys %var) {
|
||||
my $type = $var{$_}->{'type'};
|
||||
$type =~ s/(\w+)/defined $class->{$1} ? "[class[$1]]" : $1/eg;
|
||||
$xlink->(\$type);
|
||||
|
||||
my $ds = LJ::ehtml($var{$_}->{'docstring'});
|
||||
$xlink->(\$ds);
|
||||
|
||||
if ($var{$_}->{'readonly'}) {
|
||||
$ds = "<i>(Read-only)</i> $ds";
|
||||
}
|
||||
|
||||
$body .= "<tr><td><nobr><a name='member.${cname}.$_'><tt>$type $_</tt></a></nobr></td><td>$ds</td></tr>";
|
||||
}
|
||||
$body .= "</table>" if %var;
|
||||
|
||||
$body .= "<table style='margin-bottom: 10px' border='1' cellpadding='2'><?h2 Methods h2?>" if %func;
|
||||
foreach (sort keys %func) {
|
||||
my $rt = $func{$_}->{'returntype'};
|
||||
if (defined $class->{$rt}) {
|
||||
$rt = "[class[$rt]]";
|
||||
}
|
||||
$xlink->(\$rt);
|
||||
my $ds = LJ::ehtml($func{$_}->{'docstring'});
|
||||
$xlink->(\$ds);
|
||||
|
||||
my $args = $_;
|
||||
$xlink_args->(\$args);
|
||||
|
||||
$body .= "<tr><td><nobr><a name='meth.${cname}::$_'><tt>$args : $rt</tt></a></nobr></td><td>$ds</td></tr>";
|
||||
}
|
||||
$body .= "</table>" if %func;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
_code?><?page title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?>
|
||||
|
||||
139
livejournal/htdocs/customize/advanced/layeredit.bml
Executable file
139
livejournal/htdocs/customize/advanced/layeredit.bml
Executable file
@@ -0,0 +1,139 @@
|
||||
<style>
|
||||
em.error { font-weight: bold; color: red; font-style: normal; }
|
||||
textarea.s2code { width: 100%; display: block; clear: both; padding: 2px; }
|
||||
</style>
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
# for error reporting
|
||||
my $err = sub {
|
||||
return "<title>Error</title>\n<h2>Error</h2>" . shift;
|
||||
};
|
||||
|
||||
# we need a valid id
|
||||
my $id = $GET{'id'} if $GET{'id'} =~ /^\d+$/;
|
||||
return $err->("You have not specified a layer to edit.")
|
||||
unless $id;
|
||||
|
||||
# authenticate user;
|
||||
my $remote = LJ::get_remote();
|
||||
return $err->("You must be logged in to edit layers.")
|
||||
unless $remote;
|
||||
|
||||
# load layer
|
||||
my $lay = LJ::S2::load_layer($id);
|
||||
return $err->("The specified layer does not exist.")
|
||||
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};
|
||||
}
|
||||
|
||||
# is authorized admin for this layer?
|
||||
return $err->('You are not authorized to edit this layer.')
|
||||
unless LJ::can_manage($remote, $lay->{'userid'});
|
||||
|
||||
# get u of user they are acting as
|
||||
my $u = $lay->{'userid'} == $remote->{'userid'} ? $remote : LJ::load_userid($lay->{'userid'});
|
||||
|
||||
# check priv and ownership
|
||||
return $err->("You are not authorized to edit styles.")
|
||||
unless LJ::get_cap($u, "s2styles");
|
||||
|
||||
# at this point, they are authorized, allow viewing & editing
|
||||
my $ret;
|
||||
$ret .= "<form method='post' action='layeredit.bml?id=$id'>\n";
|
||||
$ret .= BML::ml('backlink', { 'text' => 'Your Layers', 'link' => "layers.bml?authas=$u->{'user'}" }) . "\n";
|
||||
|
||||
# get s2 code from db - use writer so we know it's up-to-date
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $s2code = $POST{'s2code'};
|
||||
$s2code = $dbh->selectrow_array("SELECT s2code FROM s2source WHERE s2lid=?",
|
||||
undef, $lay->{'s2lid'}) unless $s2code;
|
||||
|
||||
# we tried to compile something
|
||||
if ($POST{'action'} eq "compile") {
|
||||
$ret .= "<div style='margin: 20px 0 20px 40px'>\n";
|
||||
$ret .= "<b>S2 Compiler Output</b> <em>at " . scalar(localtime) . "</em><br />\n";
|
||||
|
||||
my $error;
|
||||
$POST{'s2code'} =~ s/\r//g; # 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;
|
||||
|
||||
$ret .= "Error compiling layer:\n<pre style=\"border-left: 1px red solid\">$error</pre>";
|
||||
|
||||
# display error with helpful context
|
||||
if ($error =~ /^compile error: line (\d+)/i) {
|
||||
my $errline = $1;
|
||||
my $kill = $errline - 5 < 0 ? 0 : $errline - 5;
|
||||
my $prehilite = $errline - 1 > 4 ? 4: $errline - 1;
|
||||
my $snippet = $s2code;
|
||||
|
||||
# make sure there's a newlilne at the end
|
||||
chomp $snippet;
|
||||
$snippet .= "\n";
|
||||
|
||||
# and now, fun with regular expressions
|
||||
my $ct = 0;
|
||||
$snippet =~ s!(.*?)\n!sprintf("%3d", ++$ct) . ": " .
|
||||
$1 . "\n"!ge; # add line breaks and numbering
|
||||
$snippet = LJ::ehtml($snippet);
|
||||
$snippet =~ s!^((?:.*?\n){$kill,$kill}) # kill before relevant lines
|
||||
((?:.*?\n){$prehilite,$prehilite}) # capture context before error
|
||||
(.*?\n){0,1} # capture error
|
||||
((?:.*?\n){0,4}) # capture context after error
|
||||
.* # kill after relevant lines
|
||||
!$2<em class='error'>$3</em>$4!sx;
|
||||
|
||||
$ret .= "<b>Context</b><br /><pre>$snippet</pre>\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
$ret .= "No errors\n";
|
||||
}
|
||||
$ret .= "</div>\n\n";
|
||||
}
|
||||
|
||||
$ret .= LJ::html_hidden("action", "compile") . "\n";
|
||||
$ret .= "<p>" . LJ::html_submit('submit', 'Compile', {
|
||||
'style' => 'float: right; margin-bottom: 2px',
|
||||
'accesskey' => 'c',
|
||||
'title' => 'alt-C: compile',
|
||||
} ) . "\n";
|
||||
$ret .= "<b>Edit layer source</b>\n";
|
||||
$ret .= LJ::html_textarea({ 'name' => 's2code', 'class' => 's2code', 'wrap' => 'off',
|
||||
'cols' => '50', 'rows' => '40', 'value' => $s2code }) . "\n";
|
||||
$ret .= LJ::html_submit('submit', 'Compile') . "\n";
|
||||
$ret .= "</p></form>\n";
|
||||
|
||||
# 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";
|
||||
|
||||
return "<title>" . LJ::ehtml($title) . " - Edit</title>\n" . $ret;
|
||||
}
|
||||
_code?>
|
||||
260
livejournal/htdocs/customize/advanced/layers.bml
Executable file
260
livejournal/htdocs/customize/advanced/layers.bml
Executable file
@@ -0,0 +1,260 @@
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST $title $body);
|
||||
|
||||
LJ::set_active_crumb('yourlayers');
|
||||
|
||||
my $remote;
|
||||
|
||||
# authas switcher form
|
||||
my $authasform = sub {
|
||||
$body .= "<form method='get' action='styles.bml'>\n";
|
||||
$body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n";
|
||||
$body .= "</form>\n\n";
|
||||
};
|
||||
|
||||
# used for error messages
|
||||
my $err = sub {
|
||||
$title = "Error";
|
||||
$body = '';
|
||||
$authasform->() if $remote;
|
||||
$body .= "<?p $_[0] p?>";
|
||||
return;
|
||||
};
|
||||
|
||||
# id is optional
|
||||
my $id = $POST{'id'} if $POST{'id'} =~ /^\d+$/;
|
||||
|
||||
# this catches core_hidden if it's set
|
||||
$POST{'parid'} ||= $POST{'parid_hidden'};
|
||||
|
||||
# authenticate user
|
||||
$remote = LJ::get_remote();
|
||||
return $err->('You must be logged in to view your layers.')
|
||||
unless $remote;
|
||||
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
|
||||
# if we don't have a u, maybe they're an admin and can view stuff anyway?
|
||||
my $noactions = 0;
|
||||
if ($GET{user} && (LJ::check_priv($remote, 'canview', 'styles') ||
|
||||
LJ::check_priv($remote, 'canview', '*'))) {
|
||||
return $err->('This privilege cannot be used on the system account.')
|
||||
if $GET{user} eq 'system';
|
||||
$u = LJ::load_user($GET{user});
|
||||
$noactions = 1; # don't let admins change anything
|
||||
}
|
||||
return $err->('You could not be authenticated as the specified user.')
|
||||
unless $u;
|
||||
|
||||
# load user and public layers
|
||||
my $pub = LJ::S2::get_public_layers();
|
||||
my $ulay = LJ::S2::get_layers_of_user($u);
|
||||
|
||||
my $has_priv = LJ::get_cap($u, 's2styles');
|
||||
return $err->($remote->{user} eq $u->{user} ?
|
||||
'Your account type does not allow advanced customization.' :
|
||||
'The selected user\'s account type does not allow advanced customization.' )
|
||||
unless $has_priv;
|
||||
|
||||
# start of output
|
||||
$title = "Your Layers";
|
||||
$body .= BML::ml("backlink", {
|
||||
'link' => './',
|
||||
'text' => 'Advanced Customization',
|
||||
}) . "\n";
|
||||
$body .= BML::ml("actionlink", {
|
||||
'link' => "<a href='styles.bml?authas=$authas'>Your Styles</a>",
|
||||
}) . "\n";
|
||||
|
||||
|
||||
### perform actions ###
|
||||
|
||||
# create
|
||||
if ($POST{'action:create'} && !$noactions) {
|
||||
return $err->("You have reached your maximum number of allowed layers")
|
||||
if keys %$ulay >= LJ::get_cap($u, 's2layersmax');
|
||||
|
||||
my $err_badparid = "No/bogus parent layer ID given (for layouts and core languages, use core parent ID; for themes and layout languages, use layout ID)";
|
||||
my $type = $POST{'type'} or return $err->("No layer type selected.");
|
||||
my $parid = $POST{'parid'}+0 or return $err->($err_badparid);
|
||||
return $err->("Invalid layer type") 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 $err->($err_badparid) if $pub->{$parid}->{'type'} ne $parent_type;
|
||||
|
||||
# parent ID is user layer, or completely invalid
|
||||
} else {
|
||||
return $err->($err_badparid) if
|
||||
! $ulay->{$parid} || $ulay->{$parid}->{'type'} != $parent_type;
|
||||
}
|
||||
|
||||
my $id = LJ::S2::create_layer($u, $parid, $type);
|
||||
return $err->("Error creating layer") 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 $err->("Error setting up & compiling layer: $error");
|
||||
}
|
||||
|
||||
# redirect so they can't refresh and create a new layer again
|
||||
return BML::redirect("layers.bml?authas=$authas");
|
||||
}
|
||||
|
||||
# delete
|
||||
if ($POST{'action:del'} && !$noactions) {
|
||||
my $id = $POST{'id'}+0;
|
||||
my $lay = LJ::S2::load_layer($id);
|
||||
return $err->("The specified layer does not exist")
|
||||
unless $lay;
|
||||
|
||||
return $err->("You do not own the specified layer")
|
||||
unless $lay->{'userid'} == $u->{'userid'};
|
||||
|
||||
unless ($POST{'confirm'}) {
|
||||
my $layerinfo = {};
|
||||
LJ::S2::load_layer_info($layerinfo, [ $id ]);
|
||||
my $name = $layerinfo->{$id}->{'name'} ? "'$layerinfo->{$id}->{'name'}'" : "#$id";
|
||||
$name = LJ::ehtml($name);
|
||||
|
||||
$title = "Deleting layer $name";
|
||||
$body .= "<br /> ";
|
||||
$body .= BML::ml("backlink", {
|
||||
'link' => "layers.bml?authas=$authas",
|
||||
'text' => 'Your Layers',
|
||||
}) . "\n";
|
||||
$body .= "<form method='post' action='layers.bml?authas=$authas'>";
|
||||
$body .= LJ::html_hidden('action:del', '1', 'id', $id);
|
||||
|
||||
$body .= "Are you sure you want to delete $lay->{'type'} layer $name?";
|
||||
$body .= "<p>" . LJ::html_submit('confirm', 'Delete') . "</p>\n";;
|
||||
$body .= "</form>\n";
|
||||
return;
|
||||
}
|
||||
|
||||
LJ::S2::delete_layer($u, $id);
|
||||
return BML::redirect("layers.bml?authas=$authas");
|
||||
}
|
||||
|
||||
# authas switcher form
|
||||
unless ($noactions) {
|
||||
$authasform->();
|
||||
}
|
||||
|
||||
# show list of layers
|
||||
$body .= "<?h1 Your Layers h1?>\n";
|
||||
if (%$ulay) {
|
||||
$body .= "<table style='margin-bottom: 10px' cellpadding='3' border='1'>\n";
|
||||
$body .= "<tr><td><b>LayerID</b></td><td><b>Type</b></td><td><b>Name</b></td><td><b>Actions</b></td></tr>\n";
|
||||
my $lastbase = 0;
|
||||
foreach my $lid (sort { $ulay->{$a}->{'b2lid'} <=> $ulay->{$b}->{'b2lid'} || $a <=> $b }
|
||||
keys %$ulay)
|
||||
{
|
||||
my $bid = $ulay->{$lid}->{'b2lid'};
|
||||
if ($bid != $lastbase) {
|
||||
$lastbase = $bid;
|
||||
my $parlay = $ulay->{$bid} || $pub->{$bid};
|
||||
my $pname = LJ::ehtml($parlay->{'name'});
|
||||
$body .= "<tr><td colspan='4'><small>Child of <a href='layerbrowse.bml?id=$bid'>layer $bid</a>: $pname</small></td></tr>\n";
|
||||
}
|
||||
my $lay = $ulay->{$lid};
|
||||
my $name = LJ::ehtml($lay->{'name'}) || "<i>(none)</i>";
|
||||
$body .= "<tr><td><a href='layerbrowse.bml?id=$lid'>$lid</a></td><td>$lay->{'type'}</td><td>$name</td><td>";
|
||||
$body .= "<form method='post' style='display:inline' action='layeredit.bml?id=$lid'>";
|
||||
$body .= LJ::html_submit('action:edit', 'Edit...', { disabled => $noactions });
|
||||
$body .= "</form>";
|
||||
|
||||
$body .= "<form method='post' style='display:inline' action='layers.bml?authas=$authas'>";
|
||||
$body .= LJ::html_hidden('id', $lid);
|
||||
$body .= LJ::html_submit('action:del', 'Delete...', { disabled => $noactions });
|
||||
$body .= "</form>";
|
||||
$body .= "</td></tr>\n"
|
||||
}
|
||||
$body .= "</table>\n\n";
|
||||
} else {
|
||||
$body .= "<?p <i>None</i> p?>\n\n";
|
||||
}
|
||||
|
||||
# jump out if we're just viewing
|
||||
return if $noactions;
|
||||
|
||||
# create layer
|
||||
$body .= "<?h1 Create Layer h1?>\n";
|
||||
|
||||
$body .= "<div style='margin-top: 10px;'>\n";
|
||||
$body .= "<?h2 Create top-level layer h2?>\n";
|
||||
$body .= "<form method='post' action='layers.bml?authas=$authas'>\n";
|
||||
|
||||
$body .= "Type: " . LJ::html_select({ 'name' => 'type' },
|
||||
"" => "",
|
||||
"layout" => "Layout",
|
||||
"i18nc" => "Language",
|
||||
) . "\n";
|
||||
|
||||
my @corelayers = map { $_, $pub->{$_}->{'majorversion'} }
|
||||
sort { $pub->{$b}->{'majorversion'} <=> $pub->{$a}->{'majorversion'} }
|
||||
grep { $pub->{$_}->{'b2lid'} == 0 && $pub->{$_}->{'type'} eq 'core' && /^\d+$/}
|
||||
keys %$pub;
|
||||
$body .= " Core Version: " . LJ::html_select({ 'name' => 'parid',
|
||||
'selected' => $corelayers[0],
|
||||
'disabled' => @corelayers > 2 ? 0: 1 },
|
||||
@corelayers ) . "\n";
|
||||
|
||||
# store value in hidden to later be copied to 'parid' if necessary
|
||||
# defaults to $corelayers[0] which should be the highest numbered core
|
||||
$body .= LJ::html_hidden("parid_hidden", $POST{'parid'} || $corelayers[0]) . "\n";
|
||||
$body .= LJ::html_submit("action:create", "Create") . "\n";
|
||||
$body .= "</form>\n";
|
||||
$body .= "</div>\n\n";
|
||||
|
||||
$body .= "<?h2 Create layout-specific layer h2?>\n";
|
||||
$body .= "<form method='post' action='layers.bml?authas=$authas'>\n";
|
||||
|
||||
$body .= "Type: " . LJ::html_select({ 'name' => 'type' },
|
||||
"" => "",
|
||||
"theme" => "Theme",
|
||||
"i18n" => "Language",
|
||||
"user" => "User"
|
||||
) . "\n";
|
||||
|
||||
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 { $_, "$ulay->{$_}->{'name'} (#$_)" }
|
||||
sort { $ulay->{$a}->{'name'} cmp $ulay->{$b}->{'name'} || $a <=> $b}
|
||||
grep { $ulay->{$_}->{'type'} eq 'layout' }
|
||||
keys %$ulay;
|
||||
push @layouts, ('', '---', @ulayouts) if @ulayouts;
|
||||
}
|
||||
|
||||
$body .= "Layout: " . LJ::html_select({ 'name' => 'parid' }, @layouts) . "\n";
|
||||
|
||||
$body .= LJ::html_submit("action:create", "Create") . "\n";
|
||||
$body .= "</form>\n\n";
|
||||
|
||||
return;
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?>
|
||||
|
||||
78
livejournal/htdocs/customize/advanced/layersource.bml
Executable file
78
livejournal/htdocs/customize/advanced/layersource.bml
Executable file
@@ -0,0 +1,78 @@
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET);
|
||||
|
||||
my $pub = LJ::S2::get_public_layers();
|
||||
|
||||
# for error reporting
|
||||
my $err = sub {
|
||||
return "<h2>Error</h2>" . shift;
|
||||
};
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
my $id = $GET{'id'};
|
||||
return BML::redirect('layerbrowse.bml') unless $id =~ /^\d+$/;
|
||||
|
||||
my $lay = defined $pub->{$id} ? $pub->{$id} : LJ::S2::load_layer($id);
|
||||
return $err->("The specified layer does not exist.")
|
||||
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} && # public styles are pulled from the system
|
||||
(LJ::check_priv($remote, 'canview', 'styles') || # account, so we don't want to check privileges
|
||||
LJ::check_priv($remote, 'canview', '*')); # in case they're private styles
|
||||
return $err->("You are not authorized to view this layer.")
|
||||
unless defined $pub->{$id} && (! defined $srcview || $srcview != 0) ||
|
||||
$srcview == 1 ||
|
||||
LJ::can_manage($remote, $lay->{'userid'}) ||
|
||||
$isadmin;
|
||||
|
||||
my $s2code = $dbr->selectrow_array("SELECT s2code FROM s2source WHERE s2lid=?", undef, $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");
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
# return text version
|
||||
BML::set_content_type("text/plain");
|
||||
BML::noparse();
|
||||
return $s2code;
|
||||
}
|
||||
_code?>
|
||||
465
livejournal/htdocs/customize/advanced/styles.bml
Executable file
465
livejournal/htdocs/customize/advanced/styles.bml
Executable file
@@ -0,0 +1,465 @@
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST $title $body);
|
||||
|
||||
LJ::set_active_crumb('yourstyles');
|
||||
|
||||
my $remote;
|
||||
|
||||
# authas switcher form
|
||||
my $authasform = sub {
|
||||
$body .= "<form method='get' action='styles.bml'>\n";
|
||||
$body .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} }) . "\n";
|
||||
$body .= "</form>\n\n";
|
||||
};
|
||||
|
||||
# used for error messages
|
||||
my $err = sub {
|
||||
$title = "Error";
|
||||
$body = '';
|
||||
$authasform->() if $remote;
|
||||
$body .= "<?p $_[0] p?>";
|
||||
return;
|
||||
};
|
||||
|
||||
# authenticate user
|
||||
$remote = LJ::get_remote();
|
||||
return $err->('You must be logged in to view your styles.')
|
||||
unless $remote;
|
||||
|
||||
my $authas = $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
return $err->('You could not be authenticated as the specified user.')
|
||||
unless $u;
|
||||
|
||||
return $err->($remote->{user} eq $u->{user} ?
|
||||
'Your account type does not allow advanced customization.' :
|
||||
'The selected user\'s account type does not allow advanced customization.' )
|
||||
unless LJ::get_cap($u, 's2styles');
|
||||
|
||||
# extra arguments for get requests
|
||||
my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : '';
|
||||
my $getextra_amp = "&authas=$authas" if $getextra;
|
||||
|
||||
# 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
|
||||
|
||||
# start of output
|
||||
$title = "Styles";
|
||||
$body = BML::ml("backlink", {
|
||||
'link' => './',
|
||||
'text' => 'Advanced Customization',
|
||||
}) . "\n";
|
||||
$body .= BML::ml("actionlink", {
|
||||
'link' => "<a href='layers.bml$getextra'>Your Layers</a>",
|
||||
}) . "\n";
|
||||
|
||||
# edit mode
|
||||
if ($id) {
|
||||
|
||||
# load style
|
||||
$style = LJ::S2::load_style($id);
|
||||
return $err->('Style not found') unless $style;
|
||||
|
||||
# check that they own the style
|
||||
return $err->("You do not own this style.")
|
||||
unless $style->{'userid'} == $u->{'userid'};
|
||||
|
||||
# use selected style
|
||||
if ($POST{'action:usestyle'}) {
|
||||
|
||||
# save to db and update user object
|
||||
LJ::set_userprop($u, "stylesys", '2');
|
||||
LJ::set_userprop($u, "s2_style", $id);
|
||||
return BML::redirect("styles.bml$getextra");
|
||||
}
|
||||
|
||||
# get public layers
|
||||
$pub = LJ::S2::get_public_layers();
|
||||
|
||||
# get user layers
|
||||
$ulay = LJ::S2::get_layers_of_user($u);
|
||||
|
||||
# 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'};
|
||||
unless ($core) { # default to highest numbered core
|
||||
map { $core = $_ if $pub->{$_}->{'type'} eq 'core' && /^\d+$/ &&
|
||||
$pub->{$_}->{'majorversion'} > $pub->{$core}->{'majorversion'} } keys %$pub;
|
||||
|
||||
# update in POST to keep things in sync
|
||||
$POST{'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{$_};
|
||||
}
|
||||
}
|
||||
|
||||
# set up start of output
|
||||
$title = "Edit Style";
|
||||
$body .= "<br />" . BML::ml('backlink', { 'text' => 'Your Styles', 'link' => "styles.bml$getextra" }) . "\n";
|
||||
|
||||
### process edit actions
|
||||
|
||||
# delete
|
||||
if ($POST{'action:delete'}) {
|
||||
LJ::S2::delete_user_style($u, $id);
|
||||
undef $id; # don't show form below
|
||||
return BML::redirect("styles.bml$getextra");
|
||||
}
|
||||
|
||||
# save changes
|
||||
if ($POST{'action:change'} || $POST{'action:savechanges'}) {
|
||||
|
||||
# are they renaming their style?
|
||||
if ($POST{'stylename'} && $style->{'name'} &&
|
||||
$POST{'stylename'} ne $style->{'name'}) {
|
||||
|
||||
# update db
|
||||
my $styleid = $style->{'styleid'};
|
||||
$dbh->do("UPDATE s2styles SET name=? WHERE styleid=? AND userid=?",
|
||||
undef, $POST{'stylename'}, $styleid, $u->{'userid'});
|
||||
LJ::MemCache::delete([$styleid, "s2s:$styleid"]);
|
||||
|
||||
# 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 $err->("Layer not found: $_") unless exists $other_info{$_};
|
||||
return $err->("Layer not public: $_") 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 ||= "#$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 "Invalid layer type: <i>$layername</i> is not a $type layer"
|
||||
if $layer->{'type'} ne $type;
|
||||
|
||||
# is a child?
|
||||
return "Layer hierarchy mismatch: <i>$layername</i> is not a child $type layer of <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 $err->($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 $err->($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 BML::redirect("styles.bml$getextra") if $POST{'action:savechanges'};
|
||||
}
|
||||
|
||||
# no style id, process actions for non-edit mode
|
||||
# and load in data necessary for style list
|
||||
} else {
|
||||
|
||||
# load user styles
|
||||
my $ustyle = LJ::S2::load_user_styles($u);
|
||||
|
||||
# process create action
|
||||
if ($POST{'action:create'} && $POST{'stylename'}) {
|
||||
|
||||
return $err->('You have reached your maximum number of styles.')
|
||||
if scalar(keys %$ustyle) >= LJ::get_cap($u, 's2stylesmax');
|
||||
|
||||
my $styleid = LJ::S2::create_style($u, $POST{'stylename'});
|
||||
return $err->('Style not created: Database error') unless $styleid;
|
||||
|
||||
return BML::redirect("styles.bml?id=$styleid$getextra_amp");
|
||||
}
|
||||
|
||||
# load style currently in use
|
||||
LJ::load_user_props($u, 's2_style');
|
||||
|
||||
# set up page header
|
||||
$title = "Your Styles";
|
||||
|
||||
$authasform->();
|
||||
|
||||
$body .= "<div><?h1 Your Styles h1?></div>\n";
|
||||
|
||||
# show style listing
|
||||
$body .= "<table style='margin-left: 40px'>\n";
|
||||
if (%$ustyle) {
|
||||
my $journalbase = LJ::journal_base($u);
|
||||
foreach my $styleid (sort { $ustyle->{$a} cmp $ustyle->{$b} || $a <=> $b} keys %$ustyle) {
|
||||
$body .= "<tr><td><form style='display:inline' method='post' action='styles.bml?id=$styleid$getextra_amp'>";
|
||||
my @b = $styleid == $u->{'s2_style'} ? "<b>" : "</b>";
|
||||
$body .= $b[0] . LJ::ehtml($ustyle->{$styleid});
|
||||
$body .= " (<a href='$journalbase/?s2id=$styleid'>\#$styleid</a>)$b[1] ";
|
||||
$body .= "</td><td>";
|
||||
$body .= LJ::html_submit('action:edit', 'Edit') . " ";
|
||||
$body .= LJ::html_submit('action:delete', 'Delete',
|
||||
{ 'onclick' => "return confirm('Are you sure you want to delete style \#$styleid?')" }) . " ";
|
||||
$body .= LJ::html_submit('action:usestyle', 'Use', { 'disabled' => $styleid == $u->{'s2_style'} }),
|
||||
$body .= "</form></td></tr>\n";
|
||||
}
|
||||
} else {
|
||||
$body .= "<tr><td><i>none</i></td></tr>\n";
|
||||
}
|
||||
$body .= "</table>\n";
|
||||
}
|
||||
|
||||
|
||||
### show create / edit form
|
||||
|
||||
my $extra = $id ? "?id=$id" : '';
|
||||
$extra .= $extra ? $getextra_amp : $getextra;
|
||||
$body .= "<form name='styleForm' method='post' action='styles.bml$extra'>";
|
||||
|
||||
# create a new style, or change the name of the style currently being edited
|
||||
# note: this little bit of code appears whether there is an id passed or not.
|
||||
# the textbox just has a different purpose depending on the context.
|
||||
$body .= "<?h1 " . ($id ? "Style Options" : "Create Style") . " h1?>\n";
|
||||
$body .= "<table style='margin-bottom: 10px'>\n";
|
||||
$body .= "<tr><td>Name: </td><td>";
|
||||
$body .= LJ::html_text({ 'name' => 'stylename', 'size' => '30', 'maxlength' => '255',
|
||||
'value' => defined $POST{'stylename'} ? $POST{'stylename'} : $style->{'name'} });
|
||||
$body .= " " . LJ::html_submit('action:create', 'Create') unless $id;
|
||||
$body .= "</td></tr>\n";
|
||||
$body .= "</table>\n";
|
||||
|
||||
# if no id to edit, we're finished
|
||||
$body .= "</form>\n", return unless $id;
|
||||
|
||||
# from here on we have $pub, $ulay, and $style filled in
|
||||
|
||||
# sub to take a layer type, core, and parent layout
|
||||
# and return a list of options to feed to LJ::html_select()
|
||||
my $layerselect = sub {
|
||||
my ($type, $b2lid) = @_;
|
||||
|
||||
my @opts = ();
|
||||
|
||||
# returns html_select to caller
|
||||
my $html_select = sub {
|
||||
my $dis = scalar(@opts) > 2 ? 0 : 1;
|
||||
|
||||
my $lid = $POST{'action:change'} ? $POST{$type} : $style->{'layer'}->{$type};
|
||||
$lid = $POST{"other_$type"} if $lid eq "_other";
|
||||
my $sel = ($lid && ! $pub->{$lid} && ! $ulay->{$lid}) ? "_other" : $lid;
|
||||
return [ LJ::html_select({ 'name' => $type, 'id' => "select_$type",
|
||||
'onChange' => "showOther('$type')",
|
||||
'selected' => $sel,
|
||||
'disabled' => $dis }, @opts), { 'disabled' => $dis, } ];
|
||||
};
|
||||
|
||||
# greps, and sorts a list
|
||||
my $greplist = sub {
|
||||
my $ref = shift;
|
||||
return sort { $ref->{$a}->{'name'} cmp $ref->{$b}->{'name'} || $a <=> $b}
|
||||
grep { $ref->{$_}->{'type'} eq $type && $ref->{$_}->{'b2lid'} == $b2lid && /^\d+$/}
|
||||
keys %$ref;
|
||||
};
|
||||
|
||||
# public layers
|
||||
my $name = $type eq 'core' ? 'majorversion' : 'name';
|
||||
push @opts, map { $_, $pub->{$_}->{$name} } $greplist->($pub);
|
||||
|
||||
# no user core layers
|
||||
return $html_select->() if $type eq 'core';
|
||||
|
||||
# user layers
|
||||
push @opts, ('', '---');
|
||||
my $startsize = scalar(@opts);
|
||||
push @opts, map { $_, "$ulay->{$_}->{'name'} (\#$_)" } $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', 'Other ...');
|
||||
|
||||
# add blank option to beginning of list
|
||||
unshift @opts, ('', @opts ? '' : ' ');
|
||||
|
||||
return $html_select->();
|
||||
};
|
||||
|
||||
my $layerother = sub {
|
||||
my $name = shift;
|
||||
|
||||
my $olid = $POST{'action:change'} ? $POST{"other_$name"} : $style->{'layer'}->{$name};
|
||||
my $disp = 'none';
|
||||
my $val;
|
||||
if ($olid && ! $pub->{$olid} && ! $ulay->{$olid}) {
|
||||
$disp = 'inline';
|
||||
$val = $olid;
|
||||
}
|
||||
|
||||
return "<div id='layer_$name' style='margin-left: 5px; display: $disp;'>Layerid: " .
|
||||
LJ::html_text({ 'name' => "other_$name", 'id' => "other_$name",
|
||||
'size' => 6, 'value' => $val }) .
|
||||
"</div>";
|
||||
};
|
||||
|
||||
### core version
|
||||
|
||||
$body .= "<?h1 Style Layers h1?>\n";
|
||||
$body .= "<table>\n";
|
||||
$body .= "<tr><td>Core Version: </td><td>";
|
||||
my $coresel = $layerselect->('core', 0);
|
||||
$body .= $coresel->[0];
|
||||
$body .= LJ::html_hidden('core_hidden', $core);
|
||||
my $dis = $coresel->[1]->{'disabled'} ? { 'disabled' => 'disabled' } : undef;
|
||||
$body .= " " . LJ::html_submit('action:change', 'Change', $dis) . "</td></tr>\n";
|
||||
$body .= "</table>\n";
|
||||
|
||||
### i18nc / layout
|
||||
|
||||
$body .= "<table style='margin: 10px 0 0 40px'>\n";
|
||||
|
||||
# i18nc
|
||||
$body .= "<tr><td>Language (i18nc): </td><td>";
|
||||
$body .= $layerselect->('i18nc', $core)->[0];
|
||||
$body .= $layerother->('i18nc');
|
||||
$body .= "</td></tr>\n";
|
||||
|
||||
# layout
|
||||
$body .= "<tr><td>Layout: </td><td>";
|
||||
my $layoutsel = $layerselect->('layout', $core);
|
||||
$body .= $layoutsel->[0];
|
||||
$body .= $layerother->('layout');
|
||||
my $dis = $layoutsel->[1]->{'disabled'} ? { 'disabled' => 'disabled' } : undef;
|
||||
$body .= " " . LJ::html_submit("action:change", "Change", $dis) . " </td></tr>\n";
|
||||
$body .= "</table>\n";
|
||||
|
||||
# do we need to show the rest of the form?
|
||||
$body .= "</form>\n", return unless $layout;
|
||||
|
||||
### theme / i18n / user
|
||||
|
||||
# theme
|
||||
$body .= "<table style='margin: 10px 0 0 80px'>\n";
|
||||
$body .= "<tr><td>Language (i18n): </td><td>";
|
||||
$body .= $layerselect->('i18n', $layout)->[0];
|
||||
$body .= $layerother->('i18n') . "</td></tr>\n";
|
||||
$body .= "<tr><td>Theme: </td><td>";
|
||||
$body .= $layerselect->('theme', $layout)->[0];
|
||||
$body .= $layerother->('theme') . "</td></tr>\n";
|
||||
$body .= "<tr><td>User: </td><td>";
|
||||
$body .= $layerselect->('user', $layout)->[0];
|
||||
$body .= $layerother->('user') . "</td></tr>\n";
|
||||
$body .= "<tr><td> </td><td>";
|
||||
$body .= LJ::html_submit('action:savechanges', 'Save Changes') . "</td></tr>\n";
|
||||
$body .= "</table>\n";
|
||||
|
||||
# end edit form
|
||||
$body .= "</form>\n";
|
||||
|
||||
return;
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
head<=
|
||||
<script language="JavaScript">
|
||||
function showOther (name) {
|
||||
if (! document.getElementById) return false;
|
||||
var box = document.getElementById("other_" + name);
|
||||
var list = document.getElementById("select_" + name);
|
||||
var div = document.getElementById("layer_" + name);
|
||||
if (div && box) {
|
||||
div.style.display =
|
||||
(list.value == "_other" && box.value != '' || list.value == "_other")
|
||||
? "inline" : "none";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function pageload () {
|
||||
if (!document.getElementById) return false;
|
||||
|
||||
var layers = new Array('i18nc', 'layout', 'i18n', 'theme', 'user');
|
||||
for (var i=0; i<layers.length; i++) {
|
||||
showOther(layers[i]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
<=head
|
||||
body=><?_code return $body; _code?>
|
||||
bodyopts=>onLoad="pageload();"
|
||||
page?>
|
||||
|
||||
361
livejournal/htdocs/customize/index.bml
Executable file
361
livejournal/htdocs/customize/index.bml
Executable file
@@ -0,0 +1,361 @@
|
||||
<?page
|
||||
title=><?_ml .title _ml?>
|
||||
head<=
|
||||
<style>
|
||||
option.disabled { color: GrayText; }
|
||||
</style>
|
||||
<=head
|
||||
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST %FORM);
|
||||
|
||||
LJ::set_active_crumb('customize');
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return LJ::bad_input($ML{'error.noremote'})
|
||||
unless $remote;
|
||||
|
||||
my $authas = $GET{'journal'} || $GET{'authas'} || $remote->{'user'};
|
||||
my $u = LJ::get_authas_user($authas);
|
||||
return LJ::bad_input($ML{'error.invalidauth'})
|
||||
unless $u;
|
||||
|
||||
my $userid = $u->{'userid'};
|
||||
my $has_cap = LJ::get_cap($u, "s2styles");
|
||||
|
||||
return $LJ::MSG_READONLY_USER if LJ::get_cap($u, "readonly");
|
||||
|
||||
my $ret;
|
||||
|
||||
# authas switcher form
|
||||
$ret .= "<form method='get' action='index.bml'>\n";
|
||||
$ret .= LJ::make_authas_select($remote, { 'authas' => $GET{'authas'} || $GET{'journal'} }) . "\n";
|
||||
$ret .= "</form>\n\n";
|
||||
|
||||
LJ::load_user_props($u, "stylesys", "s2_style");
|
||||
$u->{'stylesys'} ||= 1;
|
||||
|
||||
my $pub = LJ::S2::get_public_layers();
|
||||
my $userlay = LJ::S2::get_layers_of_user($u);
|
||||
my %style = LJ::S2::get_style($u, "verify");
|
||||
|
||||
my $get_lang = sub {
|
||||
my $styleid = shift;
|
||||
foreach ($userlay, $pub) {
|
||||
return $_->{$styleid}->{'langcode'} if
|
||||
$_->{$styleid} && $_->{$styleid}->{'langcode'};
|
||||
}
|
||||
return undef;
|
||||
};
|
||||
my $langcode = $get_lang->($style{'i18n'}) || $get_lang->($style{'i18nc'});
|
||||
|
||||
if ($POST{'save:stylesys'}) {
|
||||
my $num = $POST{'stylesys'} == 2 ? 2 : 1;
|
||||
LJ::set_userprop($u, "stylesys", $num);
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}");
|
||||
}
|
||||
|
||||
my $implicit_style_create = sub {
|
||||
|
||||
# create new style if necessary
|
||||
unless ($u->{'s2_style'}) {
|
||||
my $layid = $style{'layout'};
|
||||
my $lay = $pub->{$layid} || $userlay->{$layid};
|
||||
my $uniq = (split("/", $lay->{'uniq'}))[0] || $lay->{'s2lid'};
|
||||
|
||||
unless ($u->{'s2_style'} = LJ::S2::create_style($u, "wizard-$uniq")) {
|
||||
die "<?h1 $ML{'Error'} h1?><?p $ML{'.error.fail_create_style'} p?>";
|
||||
}
|
||||
LJ::set_userprop($u, "s2_style", $u->{'s2_style'});
|
||||
}
|
||||
|
||||
# save values in %style to db
|
||||
LJ::S2::set_style_layers($u, $u->{'s2_style'}, %style);
|
||||
};
|
||||
|
||||
if ($POST{'save:layout'}) {
|
||||
my $layid = $POST{'layoutid'}+0;
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}")
|
||||
if $layid == $style{'layout'};
|
||||
|
||||
my $lay = $pub->{$layid};
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.disallowed_user_layer'} p?>"
|
||||
if ! $lay and $lay ||= $userlay->{$layid} and ! $has_cap;
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.not_your_layout'} p?>"
|
||||
unless $lay && LJ::S2::can_use_layer($u, $lay->{'uniq'});
|
||||
|
||||
my $coreid = $lay->{'b2lid'};
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.no_core_parent'} p?>"
|
||||
unless $coreid;
|
||||
|
||||
# delete s2_style and replace it with a new
|
||||
# or existing style for this layout
|
||||
delete $u->{'s2_style'};
|
||||
|
||||
my $uniq = (split("/", $lay->{'uniq'}))[0] || $lay->{'s2lid'};
|
||||
my $usersty = LJ::S2::load_user_styles($u);
|
||||
foreach (keys %$usersty) {
|
||||
next unless $usersty->{$_} eq "wizard-$uniq";
|
||||
|
||||
$u->{'s2_style'} = $_;
|
||||
LJ::set_userprop($u, "s2_style", $u->{'s2_style'});
|
||||
|
||||
# now we have to populate %style from this style, but not core and layout,
|
||||
# as those are reset below
|
||||
my $stylay = LJ::S2::get_style_layers($u, $u->{'s2_style'});
|
||||
foreach my $layer (qw(user theme i18nc i18n)) {
|
||||
$style{$layer} = exists $stylay->{$layer} ? $stylay->{$layer} : 0;
|
||||
}
|
||||
|
||||
last;
|
||||
}
|
||||
|
||||
# no existing style found, create a new one
|
||||
unless ($u->{'s2_style'}) {
|
||||
$style{'user'} = $style{'theme'} = $style{'i18nc'} = $style{'i18n'} = 0;
|
||||
}
|
||||
|
||||
# even if we're using an existing style that we found by name (uniq), we need to
|
||||
# set layout and core layers to make sure the style still has the proper layout
|
||||
$style{'layout'} = $layid;
|
||||
$style{'core'} = $coreid;
|
||||
|
||||
$implicit_style_create->();
|
||||
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}");
|
||||
}
|
||||
|
||||
if ($POST{'action:deluser'}) {
|
||||
LJ::S2::delete_layer($style{'user'});
|
||||
LJ::S2::set_style_layers($u, $u->{'s2_style'}, "user", 0) if $style{'user'};
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}");
|
||||
}
|
||||
|
||||
if ($POST{'action:edituser'}) {
|
||||
|
||||
unless ($style{'user'}) {
|
||||
$style{'user'} = LJ::S2::create_layer($u, $style{'layout'}, "user");
|
||||
return "<?h1 $ML{'Error'} h1?> <?p $ML{'.error.cant_generate_user_layer'} p?>"
|
||||
unless $style{'user'};
|
||||
}
|
||||
|
||||
$implicit_style_create->();
|
||||
|
||||
return BML::redirect("/customize/layer.bml?w=user&journal=$authas");
|
||||
}
|
||||
|
||||
if ($POST{'save:theme'}) {
|
||||
my $themeid = $POST{'themeid'}+0;
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}")
|
||||
if $themeid == $style{'theme'};
|
||||
|
||||
my $lay = $pub->{$themeid};
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.disallowed_theme_layer'} p?>"
|
||||
if ! $lay and $lay ||= $userlay->{$themeid} and ! $has_cap;
|
||||
return "<?h1 $ML{'Error'} h1?><?p $ML{'.error.not_your_theme'} p?>" if $themeid && ! $lay;
|
||||
$style{'theme'} = $themeid;
|
||||
|
||||
$implicit_style_create->();
|
||||
|
||||
# TODO: conflict resolution. check if there
|
||||
# exists a user layer, and ask user if they want to
|
||||
# override it using the theme exclusively.
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}");
|
||||
}
|
||||
|
||||
if ($POST{'save:langcode'}) {
|
||||
my $langcode = $POST{'langcode'};
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}")
|
||||
if $langcode eq 'custom';
|
||||
|
||||
my @langs = LJ::S2::get_layout_langs($pub, $style{'layout'});
|
||||
my ($i18n, $i18nc);
|
||||
|
||||
# scan for an i18n user layer
|
||||
foreach (values %$userlay) {
|
||||
last if
|
||||
$_->{'b2lid'} == $style{'layout'} &&
|
||||
$_->{'type'} eq 'i18n' &&
|
||||
$_->{'langcode'} eq $langcode &&
|
||||
($i18n = $_->{'s2lid'});
|
||||
}
|
||||
|
||||
# scan for i18nc public layer and i18n layer if necessary
|
||||
foreach (values %$pub) {
|
||||
last if $i18nc && $i18n;
|
||||
|
||||
next if
|
||||
! $i18nc &&
|
||||
$_->{'type'} eq 'i18nc' &&
|
||||
$_->{'langcode'} eq $langcode &&
|
||||
($i18nc = $_->{'s2lid'});
|
||||
|
||||
next if
|
||||
! $i18n &&
|
||||
$_->{'b2lid'} == $style{'layout'} &&
|
||||
$_->{'type'} eq 'i18n' &&
|
||||
$_->{'langcode'} eq $langcode &&
|
||||
($i18n = $_->{'s2lid'});
|
||||
}
|
||||
|
||||
$style{'i18nc'} = $i18nc;
|
||||
$style{'i18n'} = $i18n;
|
||||
|
||||
$implicit_style_create->();
|
||||
|
||||
# TODO: conflict resolution. check if there
|
||||
# exists a user layer, and ask user if they want to
|
||||
# override it using the theme exclusively.
|
||||
return BML::redirect("/customize/?journal=$u->{'user'}");
|
||||
}
|
||||
|
||||
# choose style system
|
||||
$ret .= "<form method='post' action='./?journal=$u->{'user'}'>";
|
||||
$ret .= "<?h1 $ML{'.choose.header'} h1?><?p $ML{'.choose'} p?>";
|
||||
$ret .= "<blockquote>";
|
||||
$ret .= LJ::html_select({ 'name' => 'stylesys', 'selected' => $u->{'stylesys'} },
|
||||
1, "$ML{'.choose.s1'}",
|
||||
2, "$ML{'.choose.s2'}");
|
||||
$ret .= " <input type='submit' name='save:stylesys' value='$ML{'.change'}'>";
|
||||
$ret .= "</blockquote>";
|
||||
|
||||
# no more options if they're using S1.
|
||||
if ($u->{'stylesys'} == 1) {
|
||||
$ret .= "<?h1 $ML{'.s1.header'} h1?><?p ";
|
||||
$ret .= BML::ml('.s1.2', { aopts => "href='$LJ::SITEROOT/modify.bml?authas=$authas'" });
|
||||
$ret .= " p?></form>";
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# choose layout
|
||||
my @layouts = map { $_, $pub->{$_}->{'name'} }
|
||||
sort { $pub->{$a}->{'name'} cmp $pub->{$b}->{'name'} }
|
||||
grep { my $tmp = $_;
|
||||
$tmp =~ /^\d+$/ &&
|
||||
$pub->{$tmp}->{'type'} eq "layout" &&
|
||||
LJ::S2::can_use_layer($u, $pub->{$tmp}->{'uniq'}) &&
|
||||
($_ = $tmp)
|
||||
} keys %$pub;
|
||||
|
||||
# custom layers can will be shown in the "Custom Layers" and "Disabled Layers" groups
|
||||
# depending on the user's account status. if they don't have the s2styles cap, then
|
||||
# they will have all layers disabled, except for the one they are currently using.
|
||||
my $custom_layer_list = sub {
|
||||
my ($type, $ptype) = @_;
|
||||
my @layers = ();
|
||||
|
||||
my @user = map { $_, $userlay->{$_}->{'name'} ? $userlay->{$_}->{'name'} : "\#$_" }
|
||||
sort { $userlay->{$a}->{'name'} cmp $userlay->{$b}->{'name'} || $a <=> $b }
|
||||
grep { /^\d+$/ && $userlay->{$_}->{'b2lid'} == $style{$ptype} &&
|
||||
$userlay->{$_}->{'type'} eq $type &&
|
||||
($has_cap || $_ == $style{$type}) }
|
||||
keys %$userlay;
|
||||
if (@user) {
|
||||
push @layers, { value => "",
|
||||
text => "--- Custom Layers: ---",
|
||||
disabled => 1 }, @user;
|
||||
}
|
||||
|
||||
unless ($has_cap) {
|
||||
my @disabled =
|
||||
map { { value => $_,
|
||||
text => $userlay->{$_}->{'name'} ? $userlay->{$_}->{'name'} : "\#$_",
|
||||
disabled => 1 } }
|
||||
sort { $userlay->{$a}->{'name'} cmp $userlay->{$b}->{'name'} ||
|
||||
$userlay->{$a}->{'s2lid'} <=> $userlay->{$b}->{'s2lid'} }
|
||||
grep { /^\d+$/ && $userlay->{$_}->{'b2lid'} == $style{$ptype} &&
|
||||
$userlay->{$_}->{'type'} eq $type && $_ != $style{$type} }
|
||||
keys %$userlay;
|
||||
if (@disabled) {
|
||||
push @layers, { value => "",
|
||||
text => "--- Disabled Layers: ---",
|
||||
disabled => 1 }, @disabled;
|
||||
}
|
||||
}
|
||||
|
||||
return @layers;
|
||||
};
|
||||
|
||||
# add user/disabled ones
|
||||
push @layouts, $custom_layer_list->('layout', 'core');
|
||||
|
||||
$ret .= "<?h1 $ML{'.s2.layout.header'} h1?><?p $ML{'.s2.layout'} p?>";
|
||||
$ret .= "<blockquote>";
|
||||
$ret .= LJ::html_select({ 'name' => 'layoutid',
|
||||
'selected' => $style{'layout'}, },
|
||||
@layouts);
|
||||
$ret .= " <input type='submit' name='save:layout' value='$ML{'.change'}'> <a href=\"preview.bml?journal=$u->{'user'}\">$ML{'.previews'}</a>";
|
||||
$ret .= "</blockquote>";
|
||||
|
||||
# pick other stuff
|
||||
$ret .= "<?h1 $ML{'.s2.customize.header'} h1?>";
|
||||
$ret .= "<?p $ML{'.s2.customize'} p?>";
|
||||
|
||||
# langauge
|
||||
my @langs = LJ::S2::get_layout_langs($pub, $style{'layout'});
|
||||
|
||||
# they have set a custom i18n layer
|
||||
if ($style{'i18n'} &&
|
||||
($style{'i18nc'} != $style{'i18n'} || ! defined $pub->{$style{'i18n'}})) {
|
||||
push @langs, 'custom', $ML{'.s2.customize.language.custom'};
|
||||
$langcode = 'custom';
|
||||
}
|
||||
|
||||
$ret .= "<?h2 $ML{'.s2.customize.language.header'} h2?><?p $ML{'.s2.customize.language'} p?>";
|
||||
$ret .= "<blockquote>";
|
||||
$ret .= LJ::html_select({ 'name' => 'langcode',
|
||||
'selected' => $langcode, },
|
||||
0 => $ML{'.s2.customize.language.default'},
|
||||
@langs);
|
||||
$ret .= " <input type='submit' name='save:langcode' value='$ML{'.change'}'>";
|
||||
$ret .= "</blockquote>";
|
||||
|
||||
# theme
|
||||
my @themes = LJ::S2::get_layout_themes_select([$pub], $style{'layout'});
|
||||
|
||||
# add user/disabled ones
|
||||
push @themes, $custom_layer_list->('theme', 'layout');
|
||||
|
||||
$ret .= "<?h2 $ML{'.s2.customize.themes.header'} h2?><?p p?>";
|
||||
$ret .= "<blockquote>";
|
||||
$ret .= LJ::html_select({ 'name' => 'themeid',
|
||||
'selected' => $style{'theme'}, },
|
||||
'0' => $ML{'.s2.customize.themes.default'},
|
||||
@themes);
|
||||
$ret .= " <input type='submit' name='save:theme' value='$ML{'.change'}'> <a href=\"themes.bml?journal=$u->{'user'}\">$ML{'.previews'}</a>";
|
||||
$ret .= "</blockquote>";
|
||||
|
||||
# customize
|
||||
$ret .= "<?h2 $ML{'.s2.customize.settings.header'} h2?><?p $ML{'.s2.customize.settings'} p?>";
|
||||
$ret .= "<blockquote>";
|
||||
if ($style{'user'}) {
|
||||
$ret .= LJ::html_submit('action:edituser', $ML{'.s2.customize.settings.edit'});
|
||||
$ret .= LJ::html_submit('action:deluser', $ML{'.s2.customize.settings.delete'},
|
||||
{ 'onclick' => "return confirm('" . LJ::ejs($ML{'.s2.customize.settings.delete.confirm'}) . "')" });
|
||||
} else {
|
||||
$ret .= "<input type='submit' name='action:edituser' value='$ML{'.s2.customize.settings.new'}'>\n";
|
||||
}
|
||||
$ret .= "</blockquote>";
|
||||
|
||||
$ret .= "</form>";
|
||||
|
||||
$ret .= "<?h1 $ML{'.s2.related.header'} h1?>";
|
||||
$ret .= "<dl><dt>$ML{'.s2.advanced.header'}</dt><dd>";
|
||||
$ret .= $has_cap ? $ML{'.s2.advanced.permitted'} : $ML{'.s2.advanced.denied'};
|
||||
$ret .= "</dd><dt><a href='/manage/links.bml?authas=$authas'>$ML{'/manage/links.bml.title'}</a></dt><dd>$ML{'.s2.related.links.about'}</dd>";
|
||||
$ret .= "<dt><a href='/modify.bml?authas=$authas'>$ML{'/modify.bml.title'}</a></dt><dd>$ML{'.s2.related.modify.about'}</dd>";
|
||||
$ret .= "<dt><a href='/editinfo.bml?authas=$authas'>$ML{'/editinfo.bml.title'}</a></dt><dd>$ML{'.s2.related.editinfo.about'}</dd></dl>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
head<=
|
||||
<style type='text/css'>
|
||||
dt { font-weight: bold }
|
||||
</style>
|
||||
<=head
|
||||
page?>
|
||||
438
livejournal/htdocs/customize/layer.bml
Executable file
438
livejournal/htdocs/customize/layer.bml
Executable file
@@ -0,0 +1,438 @@
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%POST %GET $title $body $js);
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?h1 Login Required h1?><?p Before you customize your journal, you must first <a href='/login.bml'>login</a>. p?>"
|
||||
unless $remote;
|
||||
|
||||
my @journals = ($remote->{'user'});
|
||||
push @journals, LJ::get_shared_journals($remote);
|
||||
my $journal = $GET{'journal'} || $remote->{'user'};
|
||||
unless (grep { $_ eq $journal } @journals) { return BML::redirect("/customize/"); }
|
||||
|
||||
my $u = $remote;
|
||||
$u = LJ::load_user($journal) unless $journal eq $remote->{'user'};
|
||||
my $userid = $u->{'userid'};
|
||||
|
||||
LJ::load_user_props($u, "stylesys", "s2_style");
|
||||
|
||||
$body = "";
|
||||
$title = "Customize";
|
||||
$js = "";
|
||||
|
||||
my $err = sub {
|
||||
$title = "Error";
|
||||
$body = shift;
|
||||
return;
|
||||
};
|
||||
|
||||
my ($style, $layer);
|
||||
my $save_arg;
|
||||
my $save_redir;
|
||||
|
||||
# when given 'w' argument, load user's current style, and edit the user layer.
|
||||
# this is the mode redirected to from /customize/ (the simple customization UI)
|
||||
if ($GET{'w'} eq "user" && $u->{'stylesys'} == 2)
|
||||
{
|
||||
$style = LJ::S2::load_style($u->{'s2_style'});
|
||||
return $err->("Style not found.") unless $style && $style->{'userid'} == $u->{'userid'};
|
||||
$layer = LJ::S2::load_layer($dbh, $style->{'layer'}->{'user'});
|
||||
|
||||
# if the b2lid of this layer has been remapped to a new layerid
|
||||
# then update the b2lid mapping for this layer
|
||||
my $b2lid = $layer->{b2lid};
|
||||
if ($b2lid && $LJ::S2LID_REMAP{$b2lid}) {
|
||||
LJ::S2::b2lid_remap($u, $style->{'layer'}->{'user'}, $b2lid);
|
||||
$layer->{b2lid} = $LJ::S2LID_REMAP{$b2lid};
|
||||
}
|
||||
|
||||
$save_arg = "w=user&journal=$journal";
|
||||
$save_redir = "/customize/?journal=$journal";
|
||||
}
|
||||
|
||||
return BML::redirect("/customize/") unless $layer;
|
||||
return $err->("Layer belongs to another user.") unless $layer->{'userid'} == $u->{'userid'};
|
||||
return $err->("Layer isn't of type user or theme.")
|
||||
unless $layer->{'type'} eq "user" || $layer->{'type'} eq "theme";
|
||||
|
||||
my $lyr_layout = LJ::S2::load_layer($dbh, $layer->{'b2lid'});
|
||||
return $err->("Layout layer for this $layer->{'type'} layer not found.")
|
||||
unless $lyr_layout;
|
||||
my $lyr_core = LJ::S2::load_layer($dbh, $lyr_layout->{'b2lid'});
|
||||
return $err->("Core layer for layout not found.")
|
||||
unless $lyr_core;
|
||||
|
||||
$lyr_layout->{'uniq'} = $dbh->selectrow_array("SELECT value FROM s2info WHERE s2lid=? AND infokey=?",
|
||||
undef, $lyr_layout->{'s2lid'}, "redist_uniq");
|
||||
|
||||
my ($lid_i18nc, $lid_theme, $lid_i18n);
|
||||
$lid_i18nc = $style->{'layer'}->{'i18nc'};
|
||||
$lid_theme = $style->{'layer'}->{'theme'};
|
||||
$lid_i18n = $style->{'layer'}->{'i18n'};
|
||||
|
||||
my $layerid = $layer->{'s2lid'};
|
||||
|
||||
my @layers;
|
||||
push @layers, ([ 'core' => $lyr_core->{'s2lid'} ],
|
||||
[ 'i18nc' => $lid_i18nc ],
|
||||
[ 'layout' => $lyr_layout->{'s2lid'} ],
|
||||
[ 'i18n' => $lid_i18n ]);
|
||||
if ($layer->{'type'} eq "user" && $lid_theme) {
|
||||
push @layers, [ 'theme' => $lid_theme ];
|
||||
}
|
||||
push @layers, [ $layer->{'type'} => $layer->{'s2lid'} ];
|
||||
|
||||
my @layerids = grep { $_ } map { $_->[1] } @layers;
|
||||
LJ::S2::load_layers(@layerids);
|
||||
|
||||
my %layerinfo;
|
||||
|
||||
# load the language and layout choices for core.
|
||||
LJ::S2::load_layer_info(\%layerinfo, \@layerids);
|
||||
|
||||
# action path
|
||||
if (LJ::did_post()) {
|
||||
# prevent spoofing:
|
||||
return BML::redirect("/customize")
|
||||
unless $POST{'userid'} == $u->{'userid'};
|
||||
|
||||
my %override;
|
||||
foreach my $prop (S2::get_properties($lyr_layout->{'s2lid'}))
|
||||
{
|
||||
$prop = S2::get_property($lyr_core->{'s2lid'}, $prop)
|
||||
unless ref $prop;
|
||||
next unless ref $prop;
|
||||
next if $prop->{'noui'};
|
||||
my $name = $prop->{'name'};
|
||||
next unless $POST{"$name:override"};
|
||||
next unless LJ::S2::can_use_prop($u, $lyr_layout->{'uniq'}, $name);
|
||||
$override{$name} = [ $prop, $POST{"${name}_value"} ];
|
||||
}
|
||||
|
||||
if (LJ::S2::layer_compile_user($layer, \%override)) {
|
||||
return BML::redirect($save_redir) if $save_redir;
|
||||
$body = "Saved.";
|
||||
return;
|
||||
} else {
|
||||
my $error = LJ::last_error();
|
||||
$body = "Error saving layer:<pre>$error</pre>";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$body .= "<form method='post' action='layer.bml?$save_arg'>";
|
||||
$body .= LJ::html_hidden("userid", $u->{'userid'});
|
||||
|
||||
my %prop; # name -> hashref, deleted when added to a category
|
||||
my @propnames;
|
||||
foreach my $prop (S2::get_properties($lyr_layout->{'s2lid'})) {
|
||||
unless (ref $prop) {
|
||||
$prop = S2::get_property($lyr_core->{'s2lid'}, $prop);
|
||||
next unless ref $prop;
|
||||
}
|
||||
$prop{$prop->{'name'}} = $prop;
|
||||
push @propnames, $prop->{'name'};
|
||||
}
|
||||
|
||||
my @groups = S2::get_property_groups($lyr_layout->{'s2lid'});
|
||||
my $misc_group;
|
||||
my %groupprops; # gname -> [ propname ]
|
||||
my %propgroup; # pname -> gname;
|
||||
|
||||
foreach my $gname (@groups) {
|
||||
if ($gname eq "misc" || $gname eq "other") { $misc_group = $gname; }
|
||||
foreach my $pname (S2::get_property_group_props($lyr_layout->{'s2lid'}, $gname)) {
|
||||
my $prop = $prop{$pname};
|
||||
next if ! $prop || $propgroup{$pname};
|
||||
$propgroup{$pname} = $gname;
|
||||
push @{$groupprops{$gname}}, $pname;
|
||||
}
|
||||
}
|
||||
# put unsorted props into an existing or new unsorted/misc group
|
||||
if (@groups) {
|
||||
my @unsorted;
|
||||
foreach my $pname (@propnames) {
|
||||
my $prop = $prop{$pname};
|
||||
next if ! $prop || $propgroup{$pname};
|
||||
push @unsorted, $pname;
|
||||
}
|
||||
if (@unsorted) {
|
||||
unless ($misc_group) {
|
||||
$misc_group = "misc";
|
||||
push @groups, "misc";
|
||||
}
|
||||
push @{$groupprops{$misc_group}}, @unsorted;
|
||||
}
|
||||
}
|
||||
|
||||
my $group_name = sub {
|
||||
my $gname = shift;
|
||||
foreach my $lid ($lid_i18n, $lyr_layout->{'s2lid'}, $lid_i18nc, $lyr_core->{'s2lid'}) {
|
||||
next unless $lid;
|
||||
my $name = S2::get_property_group_name($lid, $gname);
|
||||
return LJ::ehtml($name) if $name;
|
||||
}
|
||||
return "Misc" if $gname eq "misc";
|
||||
return $gname;
|
||||
};
|
||||
|
||||
my $prop_js = "";
|
||||
my $output_prop = sub {
|
||||
my $name = shift;
|
||||
my $prop = $prop{$name};
|
||||
return if ! $prop || $prop->{'noui'};
|
||||
|
||||
my $name = $prop->{'name'};
|
||||
my $type = $prop->{'type'};
|
||||
|
||||
my $can_use = LJ::S2::can_use_prop($u, $lyr_layout->{'uniq'}, $name);
|
||||
|
||||
# figure out existing value (if there was no user/theme layer)
|
||||
my $existing;
|
||||
foreach my $lid (reverse @layerids) {
|
||||
next if $lid == $layerid;
|
||||
$existing = S2::get_set($lid, $name);
|
||||
last if defined $existing;
|
||||
}
|
||||
|
||||
if (ref $existing eq "HASH") { $existing = $existing->{'as_string'}; }
|
||||
|
||||
if ($type eq "bool") {
|
||||
$prop->{'values'} ||= "1|Yes|0|No";
|
||||
}
|
||||
|
||||
my %values = split(/\|/, $prop->{'values'});
|
||||
my $existing_display = defined $values{$existing} ?
|
||||
$values{$existing} : $existing;
|
||||
|
||||
$existing_display = LJ::eall($existing_display);
|
||||
|
||||
my $override = S2::get_set($layerid, $name);
|
||||
my $had_override = defined $override;
|
||||
$override = $existing unless defined $override;
|
||||
|
||||
if (ref $override eq "HASH") { $override = $override->{'as_string'}; }
|
||||
|
||||
$body .= "<?h1 " . LJ::eall($prop->{'des'}) . " h1?>";
|
||||
{
|
||||
my $t = "";
|
||||
$t .= LJ::eall($prop->{'note'}) if $prop->{'note'};
|
||||
$t .= "<?help " . $LJ::HELPPURL{"s2opt_$name"} . " help?>" if $LJ::HELPURL{"s2opt_$name"};
|
||||
$body .= "<?p $t p?>" if $t;
|
||||
}
|
||||
$body .= "<div class='inset'>\n";
|
||||
$body .= LJ::html_check({ 'name' => "$name:override", 'id' => "$name:override",
|
||||
'selected' => $had_override, 'disabled' => ! $can_use,
|
||||
'onchange' => "toggleOverride('$name');" });
|
||||
my $offhelp = ! $can_use ? LJ::help_icon('s2propoff', ' ') : "";
|
||||
$body .= "<label for='$name:override'> Override default</label>$offhelp<br />\n";
|
||||
$body .= "<dl class='hidedt'>\n<dt>Default:</dt>\n<dd id='$name:default_value' style='font-family: monospace'>\n";
|
||||
if ($type eq "int" || $type eq "string") {
|
||||
if ($existing_display ne "") {
|
||||
$body .= $existing_display;
|
||||
} else {
|
||||
$body .= "<i>(nothing)</i>";
|
||||
}
|
||||
} elsif ($type eq "Color") {
|
||||
$body .= "<span style=\"border: 1px solid #000000; padding-left: 2em; ".
|
||||
"background-color: $existing;\"> </span> <tt>$existing_display</tt>";
|
||||
} elsif ($type eq "bool") {
|
||||
$body .= $existing_display;
|
||||
}
|
||||
$body .= "</dd>\n<dt>Override:</dt>\n<dd id='$name:user_value'>\n";
|
||||
if ($prop->{'values'}) {
|
||||
$body .= LJ::html_select({ 'name' => "${name}_value",
|
||||
'disabled' => ! $can_use,
|
||||
'selected' => $override },
|
||||
split(/\|/, $prop->{'values'}));
|
||||
} elsif ($type eq "int") {
|
||||
$body .= LJ::html_text({ 'name' => "${name}_value",
|
||||
'disabled' => ! $can_use,
|
||||
'value' => $override,
|
||||
'maxlength' => 5,
|
||||
'size' => 7 });
|
||||
} elsif ($type eq "string") {
|
||||
my ($rows, $cols) = ($prop->{'rows'} + 0,
|
||||
$prop->{'cols'} + 0);
|
||||
if ($rows > 0 && $cols > 0) {
|
||||
$body .= LJ::html_textarea({ 'name' => "${name}_value",
|
||||
'disabled' => ! $can_use,
|
||||
'value' => $override,
|
||||
'onfocus' => "toggleOverride('$name');",
|
||||
'rows' => $rows,
|
||||
'cols' => $cols });
|
||||
} else {
|
||||
my ($size, $maxlength) = ($prop->{'size'} || 30,
|
||||
$prop->{'maxlength'} || 255);
|
||||
$body .= LJ::html_text({ 'name' => "${name}_value",
|
||||
'disabled' => ! $can_use,
|
||||
'value' => $override,
|
||||
'maxlength' => $maxlength,
|
||||
'size' => $size });
|
||||
}
|
||||
} elsif ($type eq "Color") {
|
||||
$body .= LJ::html_color({ 'name' => "${name}_value",
|
||||
'disabled' => ! $can_use,
|
||||
'default' => $override,
|
||||
'des' => $prop->{'des'} });
|
||||
}
|
||||
$body .= "</dd></dl>\n</div>\n";
|
||||
$prop_js .= "toggleOverride('$name');\n";
|
||||
};
|
||||
|
||||
if (@groups) {
|
||||
$body .= "<div id='propgroupstab'>";
|
||||
my $num = 0;
|
||||
foreach my $gname (@groups) {
|
||||
my $name = $group_name->($gname);
|
||||
$num++;
|
||||
my $class = $num == 1 ? "propgrouptabsel" : "propgrouptab";
|
||||
$js .= " propgroups[$num] = \"$gname\";\n";
|
||||
$body .= "<span class='$class' id='pgroup_tab_$gname'><a href='#pgroup$gname' onclick=\"return showPropGroup('$gname')\">$name</a></span>\n";
|
||||
}
|
||||
$body .= "</div>";
|
||||
$body .= "<div id='propgroupsbody'>";
|
||||
|
||||
|
||||
foreach my $gname (@groups) {
|
||||
$body .= "<a name='pgroup$gname'></a>\n";
|
||||
$body .= "<div id='pgroup_body_$gname'>\n";
|
||||
foreach my $pname (@{$groupprops{$gname}}) {
|
||||
$output_prop->($pname);
|
||||
}
|
||||
$body .= "</div>";
|
||||
}
|
||||
$body .= "</div>\n";
|
||||
|
||||
$body .= "<script language='JavaScript'>showPropGroup('$groups[0]');</script>\n";
|
||||
|
||||
} else {
|
||||
foreach my $pname (@propnames) {
|
||||
$output_prop->($pname);
|
||||
}
|
||||
}
|
||||
|
||||
$body .= "<script type='text/javascript' language='JavaScript'><!--\n$prop_js// --></script>";
|
||||
|
||||
$body .= "<?h1 Finished? h1?><?p When done, click the save button below. p?><center>";
|
||||
$body .= LJ::html_submit('action:save', "Save");
|
||||
$body .= "</center>";
|
||||
|
||||
$body .= "</form>";
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
head<=
|
||||
<script language="JavaScript" src="<?_code return $LJ::JSPREFIX; _code?>/colorpicker.js"></script>
|
||||
<script language="JavaScript">
|
||||
colPic_set_imgprefix("<?_code return $LJ::IMGPREFIX; _code?>");
|
||||
|
||||
var propgroups = new Array();
|
||||
function showPropGroup (name) {
|
||||
if (! document.getElementById) { return true; }
|
||||
for (var i=0; i<propgroups.length; i++) {
|
||||
var gname = propgroups[i];
|
||||
var tab = document.getElementById("pgroup_tab_" + gname);
|
||||
if (tab && tab.setAttribute) {
|
||||
tab.setAttribute("class", (gname == name) ? "propgrouptabsel" : "propgrouptab");
|
||||
}
|
||||
var div = document.getElementById("pgroup_body_" + gname);
|
||||
if (div) {
|
||||
div.style.display = (gname == name) ? "block" : "none";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function toggleOverride (name) {
|
||||
if (!name) return true;
|
||||
if (!document.getElementById) return true;
|
||||
var ocheck = document.getElementById(name + ':override');
|
||||
if (!ocheck) return true;
|
||||
|
||||
var def_vals = document.getElementById(name + ':default_value');
|
||||
if (!def_vals) return true;
|
||||
var usr_vals = document.getElementById(name + ':user_value');
|
||||
if (!usr_vals) return true;
|
||||
|
||||
var disp_def = ocheck.checked ? 'none' : 'block';
|
||||
var disp_usr = ocheck.checked ? 'block' : 'none';
|
||||
|
||||
def_vals.style.display = disp_def;
|
||||
usr_vals.style.display = disp_usr;
|
||||
}
|
||||
<?_code return $js; _code?>
|
||||
</script>
|
||||
|
||||
|
||||
<style type='text/css'>
|
||||
#propgroupstab {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
font-decoration: none;
|
||||
border-bottom: 2px solid black;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
#propgroupsbody {
|
||||
border-left: 2px solid black;
|
||||
border-right: 2px solid black;
|
||||
border-bottom: 2px solid black;
|
||||
margin: 0; padding: 0.5em;
|
||||
}
|
||||
|
||||
span.propgrouptabsel, span.propgrouptab {
|
||||
margin: 0 0.2em 0 0.8em;
|
||||
padding: 0.25em;
|
||||
border-top: 2px solid black;
|
||||
border-left: 2px solid black;
|
||||
border-right: 2px solid black;
|
||||
}
|
||||
|
||||
span.propgrouptab {
|
||||
background: #ddd;
|
||||
color: black;
|
||||
}
|
||||
span.propgrouptab a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
span.propgrouptabsel {
|
||||
color: #ddd;
|
||||
background: black;
|
||||
}
|
||||
span.propgrouptabsel a {
|
||||
text-decoration: none;
|
||||
color: #ddd;
|
||||
}
|
||||
div.inset {
|
||||
margin-left: 2em;
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
dl.hidedt {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
dl.hidedt dt { font-weight: bold; }
|
||||
noscript { display: inline; }
|
||||
</style>
|
||||
<script type='text/javascript' language='JavaScript'>
|
||||
// Only hide if we do the JS-switchy thing
|
||||
if (document.getElementById)
|
||||
document.write("<style type='text/css'>" +
|
||||
"dl.hidedt dd { margin: 0; padding: 0; }" +
|
||||
"dl.hidedt dt { display: none; }" +
|
||||
"noscript { display: none; }" +
|
||||
"</style>");
|
||||
</script>
|
||||
|
||||
<=head
|
||||
page?>
|
||||
39
livejournal/htdocs/customize/preview.bml
Executable file
39
livejournal/htdocs/customize/preview.bml
Executable file
@@ -0,0 +1,39 @@
|
||||
<?page
|
||||
title=>Layout Previews
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
LJ::set_active_crumb('preview');
|
||||
|
||||
my $ret;
|
||||
my $remote = LJ::get_remote();
|
||||
my $journal = LJ::canonical_username($GET{'journal'});
|
||||
|
||||
$ret .= "<p>[<< <a href='/customize/?journal=$journal'>Back</a>]</p>";
|
||||
|
||||
my $pub = LJ::S2::get_public_layers();
|
||||
|
||||
my @layouts =
|
||||
sort { $a->{'name'} cmp $b->{'name'} }
|
||||
map { $pub->{$_} } grep { /^\d+$/ && $pub->{$_}->{'type'} eq "layout" } keys %$pub;
|
||||
|
||||
foreach my $l (@layouts) {
|
||||
$ret .= "<?h1 " . LJ::eall($l->{'name'}) . " h1?>";
|
||||
unless ($l->{'_previews'}) {
|
||||
$ret .= "<?p <i>No preview available.</i> p?>";
|
||||
next;
|
||||
}
|
||||
foreach (split(/\,/, $l->{'_previews'})) {
|
||||
my ($img, $w, $h) = split(/\|/, $_);
|
||||
$ret .= "<p style='margin-left: 20px'><img src=\"$LJ::IMGPREFIX/s2preview/$img\" width=\"$w\" height=\"$h\"></p>";
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
79
livejournal/htdocs/customize/themes.bml
Executable file
79
livejournal/htdocs/customize/themes.bml
Executable file
@@ -0,0 +1,79 @@
|
||||
<?page
|
||||
title=>Theme Previews
|
||||
body<=
|
||||
<?_code
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%GET %POST);
|
||||
|
||||
LJ::set_active_crumb('themes');
|
||||
|
||||
my $ret;
|
||||
my $dbr = LJ::get_db_reader();
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
|
||||
return "<?h1 Login Required h1?><?p Before you customize your journal, you must first <a href='/login.bml?ret=1'>login</a>. p?>"
|
||||
unless $remote;
|
||||
|
||||
my @journals = ($remote->{'user'});
|
||||
push @journals, LJ::get_shared_journals($remote);
|
||||
my $journal = $GET{'journal'} || $remote->{'user'};
|
||||
unless (grep { $_ eq $journal } @journals) { return BML::redirect("/customize/"); }
|
||||
|
||||
$ret .= "<p>[<< <a href='/customize/?journal=$journal'>Back</a>]</p>";
|
||||
|
||||
my $u = $remote;
|
||||
$u = LJ::load_user($journal) unless $journal eq $remote->{'user'};
|
||||
my $userid = $u->{'userid'};
|
||||
|
||||
LJ::load_user_props($u, "stylesys", "s2_style");
|
||||
$u->{'stylesys'} ||= 1;
|
||||
my $pub = LJ::S2::get_public_layers();
|
||||
my $userlay = {}; # TODO: add API call to fetch these
|
||||
my %style = LJ::S2::get_style($u->{'s2_style'});
|
||||
|
||||
return "S2 required" unless $u->{'stylesys'} == 2 && $style{'layout'};
|
||||
|
||||
# get themes for this layer
|
||||
my @themes = LJ::S2::get_layout_themes([$pub, $userlay], $style{'layout'});
|
||||
|
||||
# make the context, without the theme
|
||||
my @layers;
|
||||
foreach (qw(core i18nc layout i18n)) {
|
||||
push @layers, $style{$_} if $style{$_};
|
||||
}
|
||||
LJ::S2::load_layers(@layers, map { $_->{'s2lid'} } @themes);
|
||||
|
||||
my $cleaner = new HTMLCleaner ('output' => sub { $ret .= $_[0]; });
|
||||
my $out_straight = sub { $ret .= $_[0]; };
|
||||
my $out_clean = sub { $cleaner->parse($_[0]); };
|
||||
|
||||
$LJ::S2::CURR_PAGE = undef;
|
||||
|
||||
foreach my $t (0, @themes) {
|
||||
my $id = ref $t ? $t->{'s2lid'} : 0;
|
||||
my $name = ref $t ? LJ::eall($t->{'name'}) : "Layout Default";
|
||||
my $ctx = S2::make_context(@layers, $id);
|
||||
LJ::S2::escape_context_props($ctx);
|
||||
LJ::S2::populate_system_props($ctx);
|
||||
|
||||
S2::set_output(sub {}); # printing suppressed
|
||||
S2::set_output_safe(sub {});
|
||||
eval { S2::run_code($ctx, "prop_init()"); };
|
||||
S2::set_output($out_straight);
|
||||
S2::set_output_safe($out_straight);
|
||||
$ret .= "<?h1 $name h1?>";
|
||||
$ret .= "<div>";
|
||||
eval { S2::run_code($ctx, "print_theme_preview()"); };
|
||||
$ret .= "</div>";
|
||||
|
||||
}
|
||||
$cleaner->eof if $cleaner; # flush any remaining text/tag not yet spit out
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
_code?>
|
||||
<=body
|
||||
page?>
|
||||
159
livejournal/htdocs/customize/viewuser.bml
Executable file
159
livejournal/htdocs/customize/viewuser.bml
Executable file
@@ -0,0 +1,159 @@
|
||||
<?_code # -*-bml-*-
|
||||
{
|
||||
use strict;
|
||||
use vars qw(%POST %GET $title $body);
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $remote = LJ::get_remote();
|
||||
return "<?h1 Login Required h1?><?p You must first <a href='/login.bml?ret=1'>login</a>. p?>"
|
||||
unless $remote;
|
||||
|
||||
my @journals = ($remote->{'user'});
|
||||
push @journals, LJ::get_shared_journals($remote);
|
||||
my $journal = $GET{'journal'} || $remote->{'user'};
|
||||
unless (grep { $_ eq $journal } @journals) { return BML::redirect("/customize/"); }
|
||||
|
||||
my $u = $remote;
|
||||
$u = LJ::load_user($journal) unless $journal eq $remote->{'user'};
|
||||
my $userid = $u->{'userid'};
|
||||
|
||||
LJ::load_user_props($u, "stylesys", "s2_style");
|
||||
|
||||
$body = "";
|
||||
$title = "User Layer";
|
||||
|
||||
if (@journals > 1) {
|
||||
$body .= "<form method='get' action='viewuser.bml'>";
|
||||
$body .= "Work with journal: ";
|
||||
$body .= LJ::html_select({
|
||||
'name' => 'journal',
|
||||
'selected' => $journal,
|
||||
}, map { $_, $_ } @journals);
|
||||
$body .= " <input type='submit' value='Switch'> </form>";
|
||||
}
|
||||
|
||||
$body .= "<< <a href='/customize/?journal=$journal'>customize</a><p>";
|
||||
|
||||
my $err = sub {
|
||||
$title = "Error";
|
||||
$body = shift;
|
||||
return;
|
||||
};
|
||||
|
||||
my ($style, $layer);
|
||||
my $save_arg;
|
||||
my $save_redir;
|
||||
|
||||
# when given 'w' argument, load user's current style, and edit the user layer.
|
||||
# this is the mode redirected to from /customize/ (the simple customization UI)
|
||||
if ($u->{'stylesys'} == 2)
|
||||
{
|
||||
$style = LJ::S2::load_style($u->{'s2_style'});
|
||||
return $err->("Style not found.") unless $style && $style->{'userid'} == $u->{'userid'};
|
||||
$layer = LJ::S2::load_layer($dbh, $style->{'layer'}->{'user'});
|
||||
}
|
||||
|
||||
unless ($layer) {
|
||||
$body .= "No user layer";
|
||||
return;
|
||||
}
|
||||
|
||||
return $err->("Layer belongs to another user.") unless $layer->{'userid'} == $u->{'userid'};
|
||||
return $err->("Layer isn't of type user or theme.")
|
||||
unless $layer->{'type'} eq "user";
|
||||
|
||||
my $lyr_layout = LJ::S2::load_layer($dbh, $layer->{'b2lid'});
|
||||
return $err->("Layout layer for this $layer->{'type'} layer not found.")
|
||||
unless $lyr_layout;
|
||||
my $lyr_core = LJ::S2::load_layer($dbh, $lyr_layout->{'b2lid'});
|
||||
return $err->("Core layer for layout not found.")
|
||||
unless $lyr_core;
|
||||
|
||||
$lyr_layout->{'uniq'} = $dbh->selectrow_array("SELECT value FROM s2info WHERE s2lid=? AND infokey=?",
|
||||
undef, $lyr_layout->{'s2lid'}, "redist_uniq");
|
||||
|
||||
my ($lid_i18nc, $lid_theme, $lid_i18n);
|
||||
$lid_i18nc = $style->{'layer'}->{'i18nc'};
|
||||
$lid_theme = $style->{'layer'}->{'theme'};
|
||||
$lid_i18n = $style->{'layer'}->{'i18n'};
|
||||
|
||||
my $layerid = $layer->{'s2lid'};
|
||||
|
||||
my @layers;
|
||||
push @layers, ([ 'core' => $lyr_core->{'s2lid'} ],
|
||||
[ 'i18nc' => $lid_i18nc ],
|
||||
[ 'layout' => $lyr_layout->{'s2lid'} ],
|
||||
[ 'i18n' => $lid_i18n ]);
|
||||
if ($layer->{'type'} eq "user" && $lid_theme) {
|
||||
push @layers, [ 'theme' => $lid_theme ];
|
||||
}
|
||||
push @layers, [ $layer->{'type'} => $layer->{'s2lid'} ];
|
||||
|
||||
my @layerids = grep { $_ } map { $_->[1] } @layers;
|
||||
LJ::S2::load_layers(@layerids);
|
||||
|
||||
my %layerinfo;
|
||||
|
||||
# load the language and layout choices for core.
|
||||
LJ::S2::load_layer_info(\%layerinfo, \@layerids);
|
||||
|
||||
$body .= "<a href='viewuser.bml?journal=$journal'>Raw</a> | ";
|
||||
$body .= "<a href='viewuser.bml?journal=$journal&as=theme'>As Theme</a>\n";
|
||||
|
||||
$body .= "<p><textarea rows='40' cols='60' wrap='off'>";
|
||||
|
||||
$body .= "# for layout: $lyr_layout->{'s2lid'} ($lyr_layout->{'uniq'})\n";
|
||||
|
||||
if ($GET{'as'} eq "") {
|
||||
$body .= "layerinfo type = user;\n\n";
|
||||
} elsif ($GET{'as'} eq "theme") {
|
||||
$body .= "layerinfo type = theme;\nlayerinfo name = \"\";\n\n";
|
||||
}
|
||||
|
||||
foreach my $prop (S2::get_properties($lyr_layout->{'s2lid'}))
|
||||
{
|
||||
$prop = S2::get_property($lyr_core->{'s2lid'}, $prop)
|
||||
unless ref $prop;
|
||||
next unless ref $prop;
|
||||
next if $prop->{'noui'};
|
||||
|
||||
my $name = $prop->{'name'};
|
||||
my $type = $prop->{'type'};
|
||||
|
||||
# figure out existing value (if there was no user/theme layer)
|
||||
my $existing;
|
||||
foreach my $lid (reverse @layerids) {
|
||||
next if $lid == $layerid;
|
||||
$existing = S2::get_set($lid, $name);
|
||||
last if defined $existing;
|
||||
}
|
||||
|
||||
if (ref $existing eq "HASH") { $existing = $existing->{'as_string'}; }
|
||||
my $val = S2::get_set($layerid, $name);
|
||||
my $had_override = defined $val;
|
||||
$val = $existing unless $had_override;
|
||||
if (ref $val eq "HASH") { $val = $val->{'as_string'}; }
|
||||
|
||||
next if $GET{'as'} eq "" && ! $had_override;
|
||||
next if $GET{'as'} eq "theme" && $type ne "Color";
|
||||
|
||||
if ($prop->{'type'} eq "int") {
|
||||
$val = int($val);
|
||||
} elsif ($prop->{'type'} eq "bool") {
|
||||
$val = $val ? "true" : "false";
|
||||
} else {
|
||||
$val =~ s/[\\\$\"]/\\$&/g;
|
||||
$val = "\"$val\"";
|
||||
}
|
||||
$body .= "set $name = $val;\n";
|
||||
}
|
||||
$body .= "</textarea>";
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
_code?><?page
|
||||
title=><?_code return $title; _code?>
|
||||
body=><?_code return $body; _code?>
|
||||
page?>
|
||||
Reference in New Issue
Block a user