template attachments (scripts and stylesheets)

This commit is contained in:
Paul Driver 2009-05-01 23:03:36 +00:00
parent 676b124697
commit f4df3b1280
6 changed files with 664 additions and 36 deletions

View file

@ -19,9 +19,17 @@ use base 'WebGUI::Asset';
use WebGUI::International;
use WebGUI::Asset::Template::HTMLTemplate;
use WebGUI::Utility;
use WebGUI::Form;
use Tie::IxHash;
use Clone qw/clone/;
use HTML::Packer;
tie my %attachmentTypeNames, 'Tie::IxHash' => (
stylesheet => 'CSS Stylesheet',
headScript => 'Javascript (head)',
bodyScript => 'Javascript (body)',
);
=head1 NAME
Package WebGUI::Asset::Template
@ -43,6 +51,52 @@ These methods are available from this class:
#-------------------------------------------------------------------
=head2 addAttachments ( attachments )
Adds attachments to this template. Attachments is an arrayref of hashrefs,
where each hashref should have at least url, type, and sequence as keys.
=cut
sub addAttachments {
my ($self, $attachments) = @_;
my $db = $self->session->db;
my $sql = q{
INSERT INTO template_attachments
(templateId, revisionDate, url, type, sequence)
VALUES
(?, ?, ?, ?, ?)
};
foreach my $a (@$attachments) {
my @params = (
$self->getId,
$self->get('revisionDate'),
@{$a}{qw(url type sequence)}
);
$db->write($sql, \@params);
}
}
#-------------------------------------------------------------------
=head2 addRevision ( )
Override the master addRevision to copy attachments
=cut
sub addRevision {
my $self = shift;
my $object = $self->SUPER::addRevision(@_);
$object->addAttachments($self->getAttachments);
return $object;
}
#-------------------------------------------------------------------
=head2 definition ( session, definition )
Defines the properties of this asset.
@ -146,6 +200,39 @@ sub duplicate {
#-------------------------------------------------------------------
=head2 removeAttachments ( urls )
Removes the specified attachments (specified by their urls, NOT by hashrefs,
since urls are unique to a particular revision) from this template. urls
should be an arrayref of strings.
=cut
sub removeAttachments {
my ($self, $urls) = @_;
return unless @$urls;
my $db = $self->session->db;
my $dbh = $db->dbh;
my $in = join(',', map { $dbh->quote($_) } @$urls);
my $rmsql = qq{
DELETE FROM
template_attachments
WHERE
templateId = ?
AND revisionDate = ?
AND url IN ($in)
};
my @params = (
$self->getId,
$self->get('revisionDate'),
);
$db->write($rmsql, \@params);
}
#-------------------------------------------------------------------
=head2 packTemplate ( template )
Pack the template into a minified version for faster downloads.
@ -185,11 +272,76 @@ sub processPropertiesFromFormPost {
$needsUpdate = 1;
$data{extraHeadTags} = '';
}
my $f = $self->session->form;
my $p = $f->paramsHashRef;
my @nums = grep {$_} map { my ($i) = /^attachmentUrl(\d+)$/; $i } keys %$p;
my @add;
foreach my $n (@nums) {
my ($index, $type, $url) =
map { $f->process('attachment' . $_ . $n) }
qw(Index Type Url);
push(
@add, {
sequence => $index,
url => $url,
type => $type,
}
);
}
my @remove = $f->process('removeAttachment', 'list');
$data{removeAttachments} = \@remove;
$data{attachments} = \@add;
$needsUpdate = 1 if @remove || @add;
$self->update(\%data) if $needsUpdate;
}
#-------------------------------------------------------------------
=head2 getAttachments ( [type] )
Returns an arrayref of hashrefs representing all attachments for this template
of the specified type (link, bodyScript, headScript).
=head3 type
If defined, will limit the attachments to this type; e.g., passing
'stylesheet' will return only stylesheets.
=cut
sub getAttachments {
my ( $self, $type ) = @_;
my @params = ($self->getId, $self->get('revisionDate'));
my $typeString;
if ($type) {
$typeString = 'AND type = ?';
push(@params, $type);
}
my $sql = qq{
SELECT
*
FROM
template_attachments
WHERE
templateId = ?
AND revisionDate = ?
$typeString
ORDER BY
type, sequence ASC
};
return $self->session->db->buildArrayRefOfHashRefs($sql, \@params);
}
#-------------------------------------------------------------------
=head2 getEditForm ( )
Returns the TabForm object that will be used in generating the edit page for this asset.
@ -230,11 +382,11 @@ sub getEditForm {
-label=>$i18n->get('show in forms'),
-hoverHelp=>$i18n->get('show in forms description'),
);
$tabform->getTab("properties")->codearea(
$tabform->getTab("properties")->codearea(
-name=>"template",
-label=>$i18n->get('assetName'),
-hoverHelp=>$i18n->get('template description'),
-syntax => "html",
-syntax => "html",
-value=>$self->getValue("template")
);
$tabform->getTab('properties')->yesNo(
@ -257,8 +409,67 @@ sub getEditForm {
-value=>$value,
-label=>$i18n->get('parser'),
-hoverHelp=>$i18n->get('parser description'),
);
);
}
my $session = $self->session;
my @headers = map { '<th>' . $i18n->get("attachment header $_") . '</th>' }
qw(index type url remove);
my $table = '<table id="attachmentDisplay">';
$table .= "<thead><tr>@headers</tr></thead><tbody id='addAnchor'>";
foreach my $a ( @{ $self->getAttachments } ) {
my ($seq, $type, $url) = @{$a}{qw(sequence type url)};
# escape macros in the url so they don't get processed
$url =~ s/\^/&#94;/g;
my $del = WebGUI::Form::checkbox(
$session, {
name => 'removeAttachment',
value => $url,
extras => 'class="id"',
}
);
my @data = (
"<td class='index'>$seq</td>",
"<td class='type'>$type</td>",
"<td class='url'>$url</td>",
"<td>$del</td>",
);
$table .= "<tr class='existingAttachment'>@data</tr>";
}
$table .= '</tbody></table>';
my $properties = $tabform->getTab('properties');
my $label = $i18n->get('attachment display label');
$properties->raw("<tr><td>$label</td><td>$table</td></tr>");
my @data = map { "<td>$_</td>" } (
WebGUI::Form::integer(
$session, { size => '2', id => 'addBoxIndex' }
),
WebGUI::Form::selectBox(
$session, { options => \%attachmentTypeNames, id => 'addBoxType' }
),
WebGUI::Form::text($session, { id => 'addBoxUrl', size => 40 }),
WebGUI::Form::button(
$session, {
value => $i18n->get('attachment add button'),
extras => 'onclick="addClick()"'
}
),
);
my ($style, $url) = $self->session->quick(qw(style url));
$style->setScript($url->extras('yui/build/yahoo/yahoo-min.js'));
$style->setScript($url->extras('yui/build/json/json-min.js'));
$style->setScript($url->extras('yui/build/dom/dom-min.js'));
pop(@headers);
my $scriptUrl = $url->extras('templateAttachments.js');
$table = "<table id='addBox'><tr>@headers</tr><tr>@data</tr></table>";
$table .= qq(<script type="text/javascript" src="$scriptUrl"></script>);
$label = $i18n->get('attachment add field label');
$properties->raw("<tr><td>$label</td><td>$table</td></tr>");
return $tabform;
}
@ -370,15 +581,42 @@ A hash reference containing template variables to be processed for the head bloc
sub prepare {
my $self = shift;
my $vars = shift;
my $vars = shift;
$self->{_prepared} = 1;
my $templateHeadersSent = $self->session->stow->get("templateHeadersSent") || [];
my @sent = @{$templateHeadersSent};
unless (isIn($self->getId, @sent)) { # don't send head block if we've already sent it for this template
$self->session->style->setRawHeadTags($self->getParser($self->session, $self->get('parser'))->process($self->getExtraHeadTags, $vars));
}
push(@sent, $self->getId);
$self->session->stow->set("templateHeadersSent", \@sent);
my $sent = $self->session->stow->get('templateHeadersSent');
unless ($sent) {
$self->session->stow->set('templateHeadersSent', $sent = []);
}
my $id = $self->getId;
# don't send head block if we've already sent it for this template
return if isIn($id, @$sent);
my $session = $self->session;
my ($db, $style) = $session->quick(qw(db style));
my $parser = $self->getParser($session, $self->get('parser'));
my $headBlock = $parser->process($self->getExtraHeadTags, $vars);
$style->setRawHeadTags($headBlock);
foreach my $sheet ( @{ $self->getAttachments('stylesheet') } ) {
my %props = ( type => 'text/css', rel => 'stylesheet' );
$style->setLink($sheet->{url}, \%props);
}
my $doScripts = sub {
my ($type, $body) = @_;
foreach my $script ( @{ $self->getAttachments($type) } ) {
my %props = ( type => 'text/javascript' );
$style->setScript($script->{url}, \%props, $body);
}
};
$doScripts->('headScript');
$doScripts->('bodyScript', 1);
push(@$sent, $id);
}
@ -445,6 +683,27 @@ sub processRaw {
return $class->getParser($session,$parser)->process($template, $vars);
}
#-------------------------------------------------------------------
=head2 purgeRevision ( )
Override the master purgeRevision to purge attachments
=cut
sub purgeRevision {
my $self = shift;
my $db = $self->session->db;
my $sql = q{
DELETE FROM
template_attachments
WHERE
templateId = ?
AND revisionDate = ?
};
$db->write($sql, [$self->getId, $self->get('revisionDate')]);
return $self->SUPER::purgeRevision(@_);
}
#-------------------------------------------------------------------
@ -456,16 +715,27 @@ packages that contain headBlocks.
This method is deprecated and will be removed in the future. Don't plan
on this being here.
Note, we are also using this now to update template attachments. So maybe it
will stay.
=cut
sub update {
my $self = shift;
my $requestedProperties = shift;
my $properties = clone($requestedProperties);
my $attachments = delete $properties->{attachments} || [];
my $removeAttachments = delete $properties->{removeAttachments} || [];
$self->removeAttachments($removeAttachments);
$self->addAttachments($attachments);
if (exists $properties->{headBlock}) {
$properties->{extraHeadTags} .= $properties->{headBlock};
delete $properties->{headBlock};
}
$self->SUPER::update($properties);
}