[livejournal] r20303: LJSUP-10082: layeredit.bml moved to use ...
Committer: vtroitsky
LJSUP-10082: layeredit.bml moved to use Templates and WidgetsA trunk/cgi-bin/LJ/Widget/LayerEditor.pm U trunk/htdocs/customize/advanced/layeredit.bml
Added: trunk/cgi-bin/LJ/Widget/LayerEditor.pm
===================================================================
--- trunk/cgi-bin/LJ/Widget/LayerEditor.pm (rev 0)
+++ trunk/cgi-bin/LJ/Widget/LayerEditor.pm 2011-10-13 08:03:15 UTC (rev 20303)
@@ -0,0 +1,230 @@
+package LJ::Widget::LayerEditor;
+
+use strict;
+use base qw(LJ::Widget);
+use Carp qw(croak);
+sub ajax { 1 }
+sub authas { 1 }
+sub need_res { qw( stc/widgets/layereditor.css js/s2edit/xlib.js js/s2edit/s2edit.js js/s2edit/s2gui.js js/s2edit/s2parser.js js/s2edit/s2sense.js js/s2edit/s2library.js stc/s2edit.css) }
+
+=head2 template_filename
+# path to template file,
+# subclass may skip overriding this method
+=cut
+sub template_filename {
+ my $class = shift;
+ my $lc_class = lc $class->subclass;
+ $lc_class =~ s|::|/|g;
+ return "$ENV{'LJHOME'}/templates/Widgets/${lc_class}.tmpl";
+}
+
+=head2 render_body
+=cut
+# fully ready 'render_body' method, subclass have no need to override this method
+sub render_body {
+ my $class = shift;
+ my %opts = @_;
+
+ # opts: GET parameters, and from_post - from previous post, parameters
+
+ my $filename = $class->template_filename();
+ my $template = LJ::HTML::Template->new(
+ { use_expr => 1 }, # force HTML::Template::Pro with Expr support
+ filename => $filename,
+ die_on_bad_params => 0,
+ strict => 0,
+ ) or die "Can't open template '$filename': $!";
+
+ # template object already contains 'lj_siteroot' and several same parameters, look LJ/HTML/Template.pm
+ # also it contains 'ml', 'ljuser', ... functions
+
+ my %params = ( );
+ $class->prepare_template_params(\%params, %opts);
+
+ if($opts{parameters}) {
+ $opts{parameters}->{$_} = $params{$_} foreach keys %params;
+ }
+ $template->param(%params);
+
+ return if LJ::Request->redirected;
+
+ return $template->output;
+}
+
+=head2 prepare_template_params
+
+=cut
+sub prepare_template_params {
+ my ($class, $params, %opts) = @_;
+
+ use Data::Dumper;
+ warn "OPTS:".Dumper(\%opts);
+
+ # we need a valid id
+ my $id = $opts{'id'} if $opts{'id'} =~ /^\d+$/;
+ die("You have not specified a layer to edit.")
+ unless $id;
+
+ # authenticate user;
+ my $remote = LJ::get_remote();
+ die("You must be logged in to edit layers.")
+ unless $remote;
+
+ my $no_layer_edit = LJ::run_hook("no_theme_or_layer_edit", $remote);
+ die(BML::ml('/customize/advanced/index.bml.error.advanced.editing.denied'))
+ if $no_layer_edit;
+
+ # load layer
+ my $lay = LJ::S2::load_layer($id);
+ die("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?
+ die('You are not authorized to edit this layer.')
+ unless $remote && $remote->can_manage($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
+ croak("You are not authorized to edit styles.")
+ unless LJ::get_cap($u, "s2styles");
+
+ # 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 = $opts{'s2code'} || LJ::S2::load_layer_source($lay->{s2lid});
+
+ # 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";
+
+ # add template variables
+ $params->{prefix} = $class->input_prefix,
+ $params->{id} = $id;
+ $params->{type} = $type;
+ $params->{name} = $name;
+ $params->{title} = $title;
+ $params->{s2code} = LJ::ehtml($s2code);
+ $params->{s2doc} = "$LJ::SITEROOT/doc/s2",
+ $params->{build} = (exists $opts{build} ? $opts{build} : "Loaded layer $id.");
+
+ $params->{is_remote_sup} = LJ::SUP->is_remote_sup ? 1 : 0;
+ $params->{errors} = [ $class->error_list ];
+ $params->{form_auth} = LJ::form_auth();
+
+ return 1;
+}
+=head2 handle_post
+ Check parameters passed.
+ Compile layer, return compile status
+=cut
+sub handle_post {
+ my ($class, $post, %opts) = @_;
+ my $u = $class->get_effective_remote();
+ my $build;
+ if ($post->{'action'} eq "compile") {
+ # we need a valid id
+ my $id = $post->{'id'} if $post->{'id'} =~ /^\d+$/;
+
+ die("You have not specified a layer to edit.") unless $id;
+
+ # load layer
+ my $lay = LJ::S2::load_layer($id);
+ die("The specified layer does not exist.") unless $lay;
+
+ $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;
+
+ $build .= "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 = $post->{'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;
+
+ $build .= "<b>Context</b><br /><pre>$snippet</pre>\n";
+ }
+
+ } else {
+ $build .= "Compiled with no errors.\n";
+ }
+ }
+ return ( build => $build, s2code => $post->{'s2code'} );
+}
+
+sub js {
+ q [
+ initWidget: function () {
+ var self = this;
+
+ var form = DOM.getElement("s2");
+ DOM.addEventListener(form, "submit", function (evt) { self.warnWord(evt, form) });
+ },
+ warnWord: function (evt, form) {
+ var given_text = form["Widget[LayerEditor]_s2code"].value + "";
+
+
+ this.doPostAndUpdateContent({
+ s2code: given_text,
+ action: 'compile',
+ id: form["Widget[LayerEditor]_id"].value,
+ });
+
+ Event.stop(evt);
+ },
+ onRefresh: function (data) {
+ this.initWidget();
+ }
+ ];
+
+
+}
+1;
Modified: trunk/htdocs/customize/advanced/layeredit.bml
===================================================================
--- trunk/htdocs/customize/advanced/layeredit.bml 2011-10-13 07:59:53 UTC (rev 20302)
+++ trunk/htdocs/customize/advanced/layeredit.bml 2011-10-13 08:03:15 UTC (rev 20303)
@@ -1,288 +1,30 @@
-<?_code # -*-bml-*-
+<?_code
{
use strict;
- our (%GET, %POST);
+ use vars qw(%POST %GET );
+ use LJ::Widget::LayerEditor;
+ my %from_post = LJ::Widget->handle_post(\%POST, qw ( LayerEditor ));
- # for error reporting
- my $err = sub {
- return "<title>Error</title>\n<h2>Error</h2>" . shift;
- };
+ my $widget = LJ::Widget::LayerEditor->new;
- # 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;
+ my %template_params;
+ $widget->prepare_template_params(\%template_params, %GET, %from_post);
- # authenticate user;
- my $remote = LJ::get_remote();
- return $err->("You must be logged in to edit layers.")
- unless $remote;
-
- my $no_layer_edit = LJ::run_hook("no_theme_or_layer_edit", $remote);
- return $err->($ML{'/customize/advanced/index.bml.error.advanced.editing.denied'})
- if $no_layer_edit;
+ my $filename = "$ENV{'LJHOME'}/templates/LayerEditor/layeredit.tmpl";
+ my $template = LJ::HTML::Template->new(
+ { use_expr => 1 }, # force HTML::Template::Pro with Expr support
+ filename => $filename,
+ die_on_bad_params => 0,
+ strict => 0,
+ ) or die "Can't open template '$filename': $!";
- # load layer
- my $lay = LJ::S2::load_layer($id);
- return $err->("The specified layer does not exist.")
- unless $lay;
+ $template->param(%template_params);
- # 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};
- }
+ LJ::need_res($widget->need_res);
+ my $headextra = LJ::res_includes();
+ $headextra .= $widget->wrapped_js(page_js_object => "LayerEditor");
+ $template->param( headextra => $headextra);
- # is authorized admin for this layer?
- return $err->('You are not authorized to edit this layer.')
- unless $remote && $remote->can_manage($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
-
- # 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'} || LJ::S2::load_layer_source($lay->{s2lid});
-
- # we tried to compile something
- my $build;
- if ($POST{'action'} eq "compile") {
- return "<b>$ML{'Error'}</b> $ML{'error.invalidform'}" unless LJ::check_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;
-
- $build .= "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;
-
- $build .= "<b>Context</b><br /><pre>$snippet</pre>\n";
- }
-
- } else {
- $build .= "Compiled with no errors.\n";
- }
- } else {
- $build = "Loaded layer $id.";
- }
-
- # 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";
-
- LJ::need_res( 'js/s2edit/xlib.js',
- 'js/s2edit/s2edit.js',
- 'js/s2edit/s2gui.js',
- 'js/s2edit/s2parser.js',
- 'js/s2edit/s2sense.js',
- 'js/s2edit/s2library.js',
- 'stc/s2edit.css');
-
- my $includes = LJ::res_includes();
- my $formauth = LJ::form_auth();
-
- # -------------------------------------------------------------------------
- # S2 Editor HTML follows
- # -------------------------------------------------------------------------
-
- return <<HERE;
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>$title - S2 Designer</title>
-
-<script type="text/javascript"><!--
- var s2docBaseURL = "$LJ::SITEROOT/doc/s2";
-// -->
-</script>
-
-$includes
-
-<!--[if IE]>
-<style type="text/css">
- html {
- overflow: hidden;
- }
-
- div.reference {
- height: expression(xGetElementById('statusbar').offsetTop - (42 + 9 + 10) + "px");
- }
-
- div.output {
- width: expression(xGetElementById('statusbar').clientWidth - (18 + xGetElementById('out').offsetLeft) + "px");
- bottom: 45px;
- }
-
- div.divider {
- font-size: 2px;
- }
-
- #outputdivider {
- width: expression(xGetElementById('statusbar').clientWidth - (18 + xGetElementById('out').offsetLeft) + "px");
- bottom: 145px;
- height: 7px;
- }
-
- #refdivider {
- height: expression(xGetElementById('statusbar').offsetTop - (42 + 9 + 10) + "px");
- }
-
- div.main {
- width: expression(xGetElementById('statusbar').clientWidth - (18 + 6 + xGetElementById('out').offsetLeft) + "px");
- height: expression(xGetElementById('statusbar').offsetTop - (42 - 16 + xGetElementById('out').clientHeight + 57) + "px");
- }
-
- textarea.maintext {
- width: 100%;
- height: expression(xGetElementById('statusbar').offsetTop - (42 - 16 + xGetElementById('out').clientHeight + 57) + "px");
- }
-
- #outputtabs {
- width: expression(xGetElementById('statusbar').clientWidth - (18 + 4 + xGetElementById('out').offsetLeft) + "px");
- }
-</style>
-<![endif]-->
-
-</head>
-<body onMouseMove="s2processDrag(event)" onMouseUp="s2endDrag(event)">
- <form method="post" name="s2" action="" onsubmit="return s2submit()">
- $formauth
- <input type="hidden" name="action" value="compile" />
-
- <div class="header">
- <h1>$title</h1>
-
- <div class="tools">
- <a href="$LJ::SITEROOT/doc/s2" target="_blank">Documentation</a>
- </div>
-
- <input type="submit" value="Save & Compile" class="compilelink" />
- </div>
-
- <div class="main" id="maindiv">
- <div class="maincontainer">
- <textarea id="main" class="maintext" name="s2code" onKeyPress="s2keyPressed(event)" wrap="off"
- onKeyDown="s2IETabKeyPressedHandler(event)">@{[ LJ::ehtml($s2code) ]}</textarea>
- </div>
- </div>
- <div class="divider" id="outputdivider" onMouseDown="s2startDrag(event)"
- onMouseUp="s2endDrag(event)"
- onMouseMove="s2processDrag(event)"> </div>
- <div class="tabs" id="outputtabs">
- <h2>Build</h2>
- </div>
- <div id="out" class="output">
- $build
- </div>
-
- <div class="tabs" id="reftabs">
- <span id="navtabs" class="refvisible">
- <h2>Nav.</h2>
- <a href="javascript:s2switchRefTab(0)">Classes</a>
- <a href="javascript:s2switchRefTab(1)">Funcs.</a>
- <a href="javascript:s2switchRefTab(2)">Props.</a>
- </span>
- <span id="classtabs" class="refinvisible">
- <a href="javascript:s2switchRefTab(-1)">Nav.</a>
- <h2>Classes</h2>
- <a href="javascript:s2switchRefTab(1)">Funcs.</a>
- <a href="javascript:s2switchRefTab(2)">Props.</a>
- </span>
- <span id="functabs" class="refinvisible">
- <a href="javascript:s2switchRefTab(-1)">Nav.</a>
- <a href="javascript:s2switchRefTab(0)">Classes</a>
- <h2>Funcs.</h2>
- <a href="javascript:s2switchRefTab(2)">Props.</a>
- </span>
- <span id="proptabs" class="refinvisible">
- <a href="javascript:s2switchRefTab(-1)">Nav.</a>
- <a href="javascript:s2switchRefTab(0)">Classes</a>
- <a href="javascript:s2switchRefTab(1)">Funcs.</a>
- <h2>Props.</h2>
- </span>
- </div>
- <div id="ref" class="reference">
- <div id="nav" class="refvisible">
-
- </div>
- <div id="classref" class="refinvisible">
- (Classes)
- </div>
- <div id="funcref" class="refinvisible">
- (Functions)
- </div>
- <div id="propref" class="refinvisible">
- (Properties)
- </div>
- </div>
-
- <div class="divider" id="refdivider" onMouseDown="s2startDragRef(event)"
- onMouseUp="s2endDrag(event)"
- onMouseMove="s2processDrag(event)"> </div>
-
- <div class="statusbar" id="statusbar">
- <div class="gutter"> </div>
- <div id="status">Ready.</div>
- </div>
-
- </form>
-
-
-</body>
-</html>
-
-
-
-HERE
+ return $template->output;
}
_code?>
