export cleanups and mobile style

This commit is contained in:
Graham Knop 2009-05-15 09:30:20 +00:00
parent 93819cda0c
commit 1f3ab6a419
20 changed files with 518 additions and 318 deletions

View file

@ -1,4 +1,9 @@
7.7.6 7.7.6
- Added mobile style template. If enabled in settings, will serve alternate style templates
and page layout templates to matching user agents. Also adds the 'mobileExportPath' config
variable where the mobile version of the site will be exported in addition to the normal
export process.
- Clean up the Asset export API to allow for easier re-use.
- New features in the UKplayer slidehow: you can hide the textblock, volume - New features in the UKplayer slidehow: you can hide the textblock, volume
slider and mute button, resize the textblock and thumbnails. A new demo slider and mute button, resize the textblock and thumbnails. A new demo
config is added. See: /extras/ukplayer/slideshow.html (Rogier Voogt, Arjan config is added. See: /extras/ukplayer/slideshow.html (Rogier Voogt, Arjan

View file

@ -14,6 +14,8 @@ save you many hours of grief.
* WebGUI now requires Crypt::SSLeay 0.57 or greater. * WebGUI now requires Crypt::SSLeay 0.57 or greater.
* WebGUI now requires Scope::Guard 0.03 or greater.
7.7.5 7.7.5
-------------------------------------------------------------------- --------------------------------------------------------------------
* Due to a long standing bug in the Profile system, if the type of a * Due to a long standing bug in the Profile system, if the type of a

View file

@ -32,6 +32,7 @@ my $session = start();
# upgrade functions go here # upgrade functions go here
addTemplateAttachmentsTable($session); addTemplateAttachmentsTable($session);
addMobileStyleTemplate( $session );
revertUsePacked( $session ); revertUsePacked( $session );
fixDefaultPostReceived($session); fixDefaultPostReceived($session);
addEuVatDbColumns( $session ); addEuVatDbColumns( $session );
@ -71,6 +72,50 @@ sub sendWebguiStats {
print "DONE!\n" unless $quiet; print "DONE!\n" unless $quiet;
} }
#----------------------------------------------------------------------------
sub addMobileStyleTemplate {
my $session = shift;
print "\tAdding mobile style template field... " unless $quiet;
$session->db->write(q{
ALTER TABLE wobject ADD COLUMN mobileStyleTemplateId CHAR(22) BINARY DEFAULT 'PBtmpl0000000000000060'
});
$session->db->write(q{
UPDATE wobject SET mobileStyleTemplateId = styleTemplateId
});
$session->db->write(q{
ALTER TABLE Layout ADD COLUMN mobileTemplateId CHAR(22) BINARY DEFAULT 'PBtmpl0000000000000054'
});
$session->setting->add('useMobileStyle', 0);
$session->config->set('mobileUserAgents', [
'AvantGo',
'DoCoMo',
'Vodafone',
'EudoraWeb',
'Minimo',
'UP\.Browser',
'PLink',
'Plucker',
'NetFront',
'^WM5 PIE$',
'Xiino',
'iPhone',
'Opera Mobi',
'BlackBerry',
'Opera Mini',
'HP iPAQ',
'IEMobile',
'Profile/MIDP',
'Smartphone',
'Symbian ?OS',
'J2ME/MIDP',
'PalmSource',
'PalmOS',
'Windows CE',
'Opera Mini',
]);
print "Done.\n" unless $quiet;
}
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
sub addListingsCacheTimeoutToMatrix{ sub addListingsCacheTimeoutToMatrix{
my $session = shift; my $session = shift;
@ -80,21 +125,22 @@ sub addListingsCacheTimeoutToMatrix{
} }
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
sub addTemplateAttachmentsTable { sub addTemplateAttachmentsTable {
my $session = shift; my $session = shift;
print "\tAdding template attachments table... " unless $quiet;
my $create = q{ my $create = q{
create table template_attachments ( CREATE TABLE template_attachments (
templateId varchar(22), templateId CHAR(22) BINARY,
revisionDate bigint(20), revisionDate bigint(20),
url varchar(256), url varchar(256),
type varchar(20), type varchar(20),
sequence int(11), sequence int(11),
primary key (templateId, revisionDate, url) PRIMARY KEY (templateId, revisionDate, url)
) )
}; };
$session->db->write($create); $session->db->write($create);
print "Done.\n" unless $quiet;
} }
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
@ -116,6 +162,7 @@ sub revertUsePacked {
# Describe what our function does # Describe what our function does
sub fixDefaultPostReceived { sub fixDefaultPostReceived {
my $session = shift; my $session = shift;
print "\tFixing post received template setting... " unless $quiet;
$session->db->write(<<EOSQL); $session->db->write(<<EOSQL);
UPDATE Collaboration SET postReceivedTemplateId='default_post_received1' WHERE postReceivedTemplateId='default-post-received' UPDATE Collaboration SET postReceivedTemplateId='default_post_received1' WHERE postReceivedTemplateId='default-post-received'
EOSQL EOSQL

View file

@ -2469,7 +2469,7 @@ ENDJS
### Show the processed template ### Show the processed template
$session->http->sendHeader; $session->http->sendHeader;
my $style = $session->style->process($self->getSeparator,$self->getParent->get("styleTemplateId")); my $style = $self->getParent->processStyle($self->getSeparator);
my ($head, $foot) = split($self->getSeparator,$style); my ($head, $foot) = split($self->getSeparator,$style);
$self->session->output->print($head, 1); $self->session->output->print($head, 1);
$self->session->output->print($self->processTemplate($var, undef, $template)); $self->session->output->print($self->processTemplate($var, undef, $template));

View file

@ -99,7 +99,16 @@ sub definition {
hoverHelp=>$i18n->get('1079 description'), hoverHelp=>$i18n->get('1079 description'),
filter=>'fixId', filter=>'fixId',
namespace=>'style' namespace=>'style'
} },
mobileStyleTemplateId => {
fieldType => ( $session->setting->get('useMobileStyle') ? 'template' : 'hidden' ),
defaultValue => 'PBtmpl0000000000000060',
tab => 'display',
label => $i18n->get('mobileStyleTemplateId label'),
hoverHelp => $i18n->get('mobileStyleTemplateId description'),
filter => 'fixId',
namespace => 'style',
},
); );
push(@{$definition}, { push(@{$definition}, {
tableName=>'wobject', tableName=>'wobject',
@ -390,7 +399,10 @@ sub processStyle {
content => $self->get('synopsis'), content => $self->get('synopsis'),
}); });
} }
return $style->process($output,$self->get("styleTemplateId")); if ($style->useMobileStyle) {
return $style->process($output,$self->get("mobileStyleTemplateId"));
}
return $style->process($output,$self->get("styleTemplateId"));
} }

View file

@ -72,6 +72,11 @@ sub definition {
namespace => "Layout", namespace => "Layout",
defaultValue =>'PBtmpl0000000000000054', defaultValue =>'PBtmpl0000000000000054',
}, },
mobileTemplateId => {
fieldType => ( $session->style->useMobileStyle ? 'template' : 'hidden' ),
namespace => 'Layout',
defaultValue => 'PBtmpl0000000000000054',
},
contentPositions => { contentPositions => {
noFormPost =>1, noFormPost =>1,
defaultValue =>undef, defaultValue =>undef,
@ -117,6 +122,22 @@ sub getEditForm {
-namespace=>"Layout" -namespace=>"Layout"
); );
if ( $self->session->setting->get('useMobileStyle') ) {
$tabform->getTab("display")->template(
name => 'mobileTemplateId',
value => $self->getValue('mobileTemplateId'),
label => $i18n->get('mobileTemplateId label'),
hoverHelp => $i18n->get('mobileTemplateId description'),
namespace => 'Layout',
);
}
else {
$tabform->getTab("display")->hidden(
name => 'mobileTemplateId',
value => $self->getValue('mobileTemplateId'),
);
}
tie my %assetOrder, "Tie::IxHash"; tie my %assetOrder, "Tie::IxHash";
%assetOrder = ( %assetOrder = (
"asc" =>$i18n->get("asset order asc"), "asc" =>$i18n->get("asset order asc"),
@ -163,7 +184,16 @@ sub prepareView {
my $self = shift; my $self = shift;
$self->SUPER::prepareView; $self->SUPER::prepareView;
my $session = $self->session; my $session = $self->session;
my $template = WebGUI::Asset->new($session,$self->get("templateId"),"WebGUI::Asset::Template"); my $templateId;
if ($session->style->useMobileStyle) {
$templateId = $self->get('templateId');
}
else {
$templateId = $self->get('mobileTemplateId');
}
my $template = WebGUI::Asset->new($session,$templateId,"WebGUI::Asset::Template");
$template->prepare( $self->getMetaDataAsTemplateVariables ); $template->prepare( $self->getMetaDataAsTemplateVariables );
$self->{_viewTemplate} = $template; $self->{_viewTemplate} = $template;
@ -325,29 +355,33 @@ sub getContentLastModified {
#------------------------------------------------------------------- #-------------------------------------------------------------------
sub www_view { sub www_view {
my $self = shift; my $self = shift;
my $session = $self->session;
# slashdot / burst protection hack # slashdot / burst protection hack
if ($self->session->var->get("userId") eq "1" && $self->session->form->param() == 0) { if ($session->var->get("userId") eq "1"
&& $session->form->param() == 0
&& !$session->scratch->get('isExporting')
) {
my $check = $self->checkView; my $check = $self->checkView;
return $check if (defined $check); return $check if (defined $check);
my $cache = WebGUI::Cache->new($self->session, "view_".$self->getId); my $cache = WebGUI::Cache->new($session, "view_".$self->getId);
my $out = $cache->get if defined $cache; my $out = $cache->get if defined $cache;
unless ($out) { unless ($out) {
$self->prepareView; $self->prepareView;
$self->session->stow->set("cacheFixOverride", 1); $session->stow->set("cacheFixOverride", 1);
$out = $self->processStyle($self->view); $out = $self->processStyle($self->view);
$cache->set($out, 60); $cache->set($out, 60);
$self->session->stow->delete("cacheFixOverride"); $session->stow->delete("cacheFixOverride");
} }
# keep those ads rotating # keep those ads rotating
while ($out =~ /(\[AD\:([^\]]+)\])/gs) { while ($out =~ /(\[AD\:([^\]]+)\])/gs) {
my $code = $1; my $code = $1;
my $adSpace = WebGUI::AdSpace->newByName($self->session, $2); my $adSpace = WebGUI::AdSpace->newByName($session, $2);
my $ad = $adSpace->displayImpression if (defined $adSpace); my $ad = $adSpace->displayImpression if (defined $adSpace);
$out =~ s/\Q$code/$ad/ges; $out =~ s/\Q$code/$ad/ges;
} }
$self->session->http->setLastModified($self->getContentLastModified); $session->http->setLastModified($self->getContentLastModified);
$self->session->http->sendHeader; $session->http->sendHeader;
$self->session->output->print($out, 1); $session->output->print($out, 1);
return "chunked"; return "chunked";
} }
$self->{_viewPrintOverride} = 1; # we do this to make it output each asset as it goes, rather than waiting until the end $self->{_viewPrintOverride} = 1; # we do this to make it output each asset as it goes, rather than waiting until the end

View file

@ -2011,7 +2011,7 @@ sub www_viewProject {
$var->{'task.back.label'} = $i18n->get("task back label"); $var->{'task.back.label'} = $i18n->get("task back label");
$var->{'task.back.url'} = $self->getUrl; $var->{'task.back.url'} = $self->getUrl;
return $style->process($self->processTemplate($var,$self->getValue("projectDisplayTemplateId")),$self->getValue("styleTemplateId")); return $style->processStyle($self->processTemplate($var,$self->getValue("projectDisplayTemplateId")));
} }

View file

@ -1408,7 +1408,7 @@ sub www_takeSurvey {
my $self = shift; my $self = shift;
my $out = $self->processTemplate( {}, $self->get('surveyTakeTemplateId') ); my $out = $self->processTemplate( {}, $self->get('surveyTakeTemplateId') );
return $self->session->style->process( $out, $self->get('styleTemplateId') ); return $self->processStyle($out);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -2071,7 +2071,7 @@ sub www_viewGradeBook {
$paginator->appendTemplateVars($var); $paginator->appendTemplateVars($var);
my $out = $self->processTemplate( $var, $self->get('gradebookTemplateId') ); my $out = $self->processTemplate( $var, $self->get('gradebookTemplateId') );
return $self->session->style->process( $out, $self->get('styleTemplateId') ); return $self->processStyle($out);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -2161,7 +2161,7 @@ sub www_viewStatisticalOverview {
$paginator->appendTemplateVars($var); $paginator->appendTemplateVars($var);
my $out = $self->processTemplate( $var, $self->get('overviewTemplateId') ); my $out = $self->processTemplate( $var, $self->get('overviewTemplateId') );
return $self->session->style->process( $out, $self->get('styleTemplateId') ); return $self->processStyle($out);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------

View file

@ -3468,8 +3468,9 @@ sub www_viewThingData {
$self->getViewThingVars($thingId,$thingDataId,$var); $self->getViewThingVars($thingId,$thingDataId,$var);
$self->appendThingsVars($var, $thingId); $self->appendThingsVars($var, $thingId);
return $self->session->style->process($self->processTemplate($var,$thingProperties->{viewTemplateId}),$self->get("styleTemplateId")); return $self->processStyle(
$self->processTemplate($var,$thingProperties->{viewTemplateId})
);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------

View file

@ -146,7 +146,6 @@ sub www_editBranch {
-value=>$self->getValue("styleTemplateId"), -value=>$self->getValue("styleTemplateId"),
-hoverHelp=>$i18n2->get('1073 description'), -hoverHelp=>$i18n2->get('1073 description'),
-namespace=>'style', -namespace=>'style',
-afterEdit=>'op=editPage;npp='.$self->session->form->process("npp"),
-subtext=>'<br />'.$i18n->get("change").' '.WebGUI::Form::yesNo($self->session,{name=>"change_styleTemplateId"}) -subtext=>'<br />'.$i18n->get("change").' '.WebGUI::Form::yesNo($self->session,{name=>"change_styleTemplateId"})
); );
$tabform->getTab("display")->template( $tabform->getTab("display")->template(
@ -155,9 +154,19 @@ sub www_editBranch {
-hoverHelp=>$i18n2->get('1079 description'), -hoverHelp=>$i18n2->get('1079 description'),
-value=>$self->getValue("printableStyleTemplateId"), -value=>$self->getValue("printableStyleTemplateId"),
-namespace=>'style', -namespace=>'style',
-afterEdit=>'op=editPage;npp='.$self->session->form->process("npp"),
-subtext=>'<br />'.$i18n->get("change").' '.WebGUI::Form::yesNo($self->session,{name=>"change_printableStyleTemplateId"}) -subtext=>'<br />'.$i18n->get("change").' '.WebGUI::Form::yesNo($self->session,{name=>"change_printableStyleTemplateId"})
); );
if ( $self->session->setting->get('useMobileStyle') ) {
$tabform->getTab("display")->template(
name => 'mobileStyleTemplateId',
label => $i18n2->get('mobileStyleTemplateId label'),
hoverHelp => $i18n2->get('mobileStyleTemplateId description'),
value => $self->getValue('mobileStyleTemplateId'),
namespace => 'style',
subtext => '<br />' . $i18n->get('change') . q{ }
. WebGUI::Form::yesNo($self->session,{name=>"change_mobileStyleTemplateId"}),
);
}
$tabform->addTab("security",$i18n->get(107),6); $tabform->addTab("security",$i18n->get(107),6);
if ($self->session->config->get("sslEnabled")) { if ($self->session->config->get("sslEnabled")) {
$tabform->getTab("security")->yesNo( $tabform->getTab("security")->yesNo(
@ -254,6 +263,8 @@ sub www_editBranchSave {
if ($self->session->form->yesNo("change_styleTemplateId")); if ($self->session->form->yesNo("change_styleTemplateId"));
$wobjectData{printableStyleTemplateId} = $self->session->form->template("printableStyleTemplateId") $wobjectData{printableStyleTemplateId} = $self->session->form->template("printableStyleTemplateId")
if ($self->session->form->yesNo("change_printableStyleTemplateId")); if ($self->session->form->yesNo("change_printableStyleTemplateId"));
$wobjectData{mobileStyleTemplateId} = $self->session->form->template("mobileStyleTemplateId")
if ($self->session->form->yesNo("change_mobileStyleTemplateId"));
my ($urlBaseBy, $urlBase, $endOfUrl); my ($urlBaseBy, $urlBase, $endOfUrl);
my $changeUrl = $self->session->form->yesNo("change_url"); my $changeUrl = $self->session->form->yesNo("change_url");
if ($changeUrl) { if ($changeUrl) {

View file

@ -15,14 +15,15 @@ package WebGUI::Asset;
=cut =cut
use strict; use strict;
use File::Basename ();
use File::Path (); use File::Path ();
use Path::Class; use Path::Class ();
use Scalar::Util 'looks_like_number'; use Scalar::Util qw(looks_like_number);
use WebGUI::International; use WebGUI::International;
use WebGUI::Exception; use WebGUI::Exception;
use WebGUI::Utility ();
use WebGUI::Session; use WebGUI::Session;
use URI::URL; use URI::URL;
use Scope::Guard;
=head1 NAME =head1 NAME
@ -46,18 +47,19 @@ These methods are available from this class:
#------------------------------------------------------------------- #-------------------------------------------------------------------
=head2 exportCheckPath ( session ) =head2 exportCheckPath ( [session] )
Class method. Tries very hard to ensure that exportPath is defined in the Class or object method. Tries very hard to ensure that exportPath is defined in the
configuration file, that it exists on the filesystem (creating any directories configuration file, that it exists on the filesystem (creating any directories
necessary), and that the OS user running WebGUI can write to it. Throws an necessary), and that the OS user running WebGUI can write to it. Throws an
appropriate exception on failure and returns a true value on success. appropriate exception on failure and returns a the export path as a L<Path::Class::Dir>
object on success.
Takes the following parameters: Takes the following parameters:
=head3 session =head3 session
A reference to a L<WebGUI::Session> object. A reference to a L<WebGUI::Session> object. Should only be specified if called as a class method.
Throws the following exceptions: Throws the following exceptions:
@ -73,25 +75,31 @@ Encountered filesystem permission problems with the defined exportPath
sub exportCheckPath { sub exportCheckPath {
my $class = shift; my $class = shift;
my $session = shift; my $session;
if (ref $class && $class->can('session')) {
# make sure we were given the right parameters $session = $class->session;
if(ref $session ne 'WebGUI::Session') {
WebGUI::Error::InvalidObject->throw(error => "first param to exportCheckPath must be a WebGUI::Session");
} }
else {
my $exportPath = $session->config->get('exportPath'); $session = shift;
# make sure we were given the right parameters
if((!ref $session) || !$session->isa('WebGUI::Session')) {
WebGUI::Error::InvalidObject->throw(error => "first param to exportCheckPath as a class method must be a WebGUI::Session");
}
}
my $exportPath = $session->style->useMobileStyle ? $session->config->get('mobileExportPath')
: $session->config->get('exportPath');
# first check that the path is defined in the config file and that it's not # first check that the path is defined in the config file and that it's not
# an empty string # an empty string
if(!defined $exportPath || !$exportPath) { if (!defined $exportPath || !$exportPath) {
WebGUI::Error::InvalidObject->throw(error => 'exportPath must be defined and not ""'); WebGUI::Error::InvalidObject->throw(error => 'exportPath must be defined and not ""');
} }
$exportPath = Path::Class::Dir->new($exportPath);
# now that we know that it's defined and not an empty string, test if it exists. # now that we know that it's defined and not an empty string, test if it exists.
if(!-e $exportPath) { if (!-e $exportPath) {
# it doesn't exist; let's try making it # it doesn't exist; let's try making it
eval { File::Path::mkpath( [$exportPath] ) }; eval { $exportPath->mkpath };
if($@) { if($@) {
WebGUI::Error->throw(error => "can't create exportPath $exportPath"); WebGUI::Error->throw(error => "can't create exportPath $exportPath");
} }
@ -99,11 +107,11 @@ sub exportCheckPath {
# the path didn't exist, and we succeeded creating it. Therefore we # the path didn't exist, and we succeeded creating it. Therefore we
# know we can write to it and that it's an actual directory. Nothing # know we can write to it and that it's an actual directory. Nothing
# more left to do. indicate success to our caller. # more left to do. indicate success to our caller.
return 1; return $exportPath;
} }
# the path exists. make sure it's actually a directory. # the path exists. make sure it's actually a directory.
if(!-d $exportPath) { if (!-d $exportPath) {
WebGUI::Error->throw(error => "$exportPath isn't a directory"); WebGUI::Error->throw(error => "$exportPath isn't a directory");
} }
@ -113,12 +121,12 @@ sub exportCheckPath {
# directories beneath it, and we need to be able to 'execute' the directory # directories beneath it, and we need to be able to 'execute' the directory
# to list files in it. and of course we need to be able to read it too. # to list files in it. and of course we need to be able to read it too.
# check for all of these. # check for all of these.
if(! (-w $exportPath) || ! (-x _) || ! (-r _) ) { if (! (-w $exportPath && -x _ && -r _) ) {
WebGUI::Error->throw(error => "can't access $exportPath"); WebGUI::Error->throw(error => "can't access $exportPath");
} }
# everything checks out, return 1 # everything checks out, return path
return 1; return $exportPath;
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -189,9 +197,8 @@ false will do nothing.
sub exportAsHtml { sub exportAsHtml {
my $self = shift; my $self = shift;
my $args = shift;
my $session = $self->session; my $session = $self->session;
# set a scratch variable for Assets to know we're exporting
my ($returnCode, $message);
# get the i18n object # get the i18n object
my $i18n = WebGUI::International->new($self->session, 'Asset'); my $i18n = WebGUI::International->new($self->session, 'Asset');
@ -199,23 +206,10 @@ sub exportAsHtml {
# take down when we started to tell the user how long the process took. # take down when we started to tell the user how long the process took.
my $startTime = $session->datetime->time; my $startTime = $session->datetime->time;
# before even looking at the parameters, make sure the exportPath is valid. # get the export path and ensure it is valid.
eval { WebGUI::Asset->exportCheckPath($session) }; my $exportPath = $self->exportCheckPath;
# something went wrong. we don't really care what at this point. we did
# everything we could to try to make exporting possible and we failed. give
# up.
if($@) {
$returnCode = 0;
$message = $@;
return ($returnCode, $message);
}
# if we're still here, then the exportPath is valid.
my $exportPath = $session->config->get('exportPath');
# get parameters # get parameters
my $args = shift;
my $quiet = $args->{quiet}; my $quiet = $args->{quiet};
my $userId = $args->{userId}; my $userId = $args->{userId};
my $depth = $args->{depth}; my $depth = $args->{depth};
@ -224,186 +218,180 @@ sub exportAsHtml {
my $rootUrlAction = $args->{rootUrlAction}; my $rootUrlAction = $args->{rootUrlAction};
my $exportUrl = $args->{exportUrl}; my $exportUrl = $args->{exportUrl};
# if we're doing symlinking of the root URL, then the current default asset
# is the root of the tree. take down that asset ID so we can pass it to
# exportSymlinkRoot later.
my $defaultAssetId = $self->session->setting->get('defaultPage');
my $defaultAsset = WebGUI::Asset->newByDynamicClass($session, $defaultAssetId);
my @extraUploadActions = qw/ symlink none /; my @extraUploadActions = qw/ symlink none /;
my @rootUrlActions = qw/ symlink none /; my @rootUrlActions = qw/ symlink none /;
# verify them # verify them
if(!defined $userId) { if (!defined $userId) {
$returnCode = 0; WebGUI::Error->throw(error => $i18n->get('need a userId parameter'));
$message = $i18n->get('need a userId parameter');
return ($returnCode, $message);
} }
# we take either a numeric userId or a WebGUI::User object # we take either a numeric userId or a WebGUI::User object
if( ref $userId ne 'WebGUI::User' && ! (looks_like_number($userId) || $session->id->valid($userId))) { my $user;
$returnCode = 0; if ( ref $userId && $userId->isa('WebGUI::User') ) {
$message = "'$userId' ".$i18n->get('is not a valid userId'); $user = $userId;
return ($returnCode, $message);
} }
elsif ( looks_like_number($userId) || $session->id->valid($userId) ) {
$user = WebGUI::User->new($session, $userId);
}
if (! defined $user) {
WebGUI::Error->throw(error => "'$userId' ".$i18n->get('is not a valid userId'));
}
$userId = $user->userId;
# depth is required. # depth is required.
if(!defined $depth) { if(! defined $depth) {
$returnCode = 0; WebGUI::Error->throw(error => $i18n->get('need a depth'));
$message = $i18n->get('need a depth');
return ($returnCode, $message);
} }
# and it must be a number. # and it must be a number.
if( !looks_like_number($depth) ) { if( !looks_like_number($depth) ) {
$returnCode = 0; WebGUI::Error->throw(error => sprintf $i18n->get('%s is not a valid depth'), $depth);
$message = sprintf $i18n->get('%s is not a valid depth'), $depth;
return ($returnCode, $message);
} }
# extrasUploadAction and rootUrlAction must have values matching something # extrasUploadAction and rootUrlAction must have values matching something
# in the arrays defined above # in the arrays defined above
if( defined $extrasUploadAction && !isIn($extrasUploadAction, @extraUploadActions) ) { if( defined $extrasUploadAction && !WebGUI::Utility::isIn($extrasUploadAction, @extraUploadActions) ) {
$returnCode = 0; WebGUI::Error->throw(error => "'$extrasUploadAction' is not a valid extrasUploadAction");
$message = "'$extrasUploadAction' is not a valid extrasUploadAction";
return ($returnCode, $message);
} }
if( defined $rootUrlAction && !isIn($rootUrlAction, @rootUrlActions) ) { if( defined $rootUrlAction && !WebGUI::Utility::isIn($rootUrlAction, @rootUrlActions) ) {
$returnCode = 0; WebGUI::Error->throw(error => "'$rootUrlAction' is not a valid rootUrlAction");
$message = "'$rootUrlAction' is not a valid rootUrlAction";
return ($returnCode, $message);
} }
# the export path is valid. the params are good. let's get started. first,
# we need to get the assets that we'll be exporting. exportGetDescendants
# takes a WebGUI::User object, so give it one.
my $user;
if(ref $userId ne 'WebGUI::User') {
$user = WebGUI::User->new($session, $userId);
}
else {
$user = $userId;
}
my $assetIds = $self->exportGetDescendants($user, $depth);
# make sure this user can view the top level asset we're exporting. if not,
# don't do anything.
unless ( $self->canView($userId) ) { unless ( $self->canView($userId) ) {
$returnCode = 0; WebGUI::Error->throw(error => "can't view asset at URL " . $self->getUrl);
$message = "can't view asset at URL " . $self->getUrl;
return ($returnCode, $message);
} }
# now, create a new session as the user doing the exports. this is so that
# the exported assets are taken from that user's perspective.
my $exportSession = WebGUI::Session->open(
$session->config->getWebguiRoot,
$session->config->getFilename,
);
my $esGuard = Scope::Guard->new(sub {
$exportSession->var->end;
$exportSession->close;
});
$exportSession->user( { userId => $userId } );
# set a scratch variable for Assets and widgets to know we're exporting
$exportSession->scratch->set('isExporting', 1);
$exportSession->scratch->set('exportUrl', $exportUrl);
$exportSession->style->setMobileStyle(0);
my $asset = WebGUI::Asset->new(
$exportSession,
$self->getId,
$self->get('className'),
$self->get('revisionDate'),
);
# pass in reporting session unless we're in quiet mode
my $exportedCount = $asset->exportBranch( $args, $quiet ? () : $session );
if ($session->config->get('mobileExportPath')) {
$exportSession->style->setMobileStyle(1);
# pass in reporting session unless we're in quiet mode
$exportedCount += $asset->exportBranch( $args, $quiet ? () : $session );
}
# we're done. give the user a status report.
my $timeRequired = $session->datetime->time - $startTime;
my $message = sprintf $i18n->get('export information'), $exportedCount, $timeRequired;
return $message;
}
sub exportBranch {
my $self = shift;
my $options = shift;
my $reportSession = shift;
my $depth = $options->{depth};
my $indexFileName = $options->{indexFileName};
my $extrasUploadAction = $options->{extrasUploadAction};
my $rootUrlAction = $options->{rootUrlAction};
my $i18n;
if ( $reportSession ) {
$i18n = WebGUI::International->new($self->session, 'Asset');
}
my $exportedCount = 0; my $exportedCount = 0;
my $assetIds = $self->exportGetDescendants(undef, $depth);
foreach my $assetId ( @{$assetIds} ) { foreach my $assetId ( @{$assetIds} ) {
# now, create a new session as the user doing the exports. this is so that
# the exported assets are taken from that user's perspective.
# Must be created once for each asset, since session is supposed to only handle # Must be created once for each asset, since session is supposed to only handle
# one main asset # one main asset
my $exportSession = WebGUI::Session->open($self->session->config->getWebguiRoot, $self->session->config->getFilename); my $outputSession = $self->session->duplicate;
$exportSession->user( { userId => $userId } ); my $osGuard = Scope::Guard->new(sub {
$outputSession->close;
});
# set a scratch variable for Assets and widgets to know we're exporting my $asset = WebGUI::Asset->new($outputSession, $assetId);
$exportSession->scratch->set('isExporting', 1);
$exportSession->scratch->set('exportUrl', $exportUrl);
my $asset = WebGUI::Asset->newByDynamicClass($exportSession, $assetId);
my $fullPath = $asset->exportGetUrlAsPath; my $fullPath = $asset->exportGetUrlAsPath;
# skip this asset if we can't view it as this user. # skip this asset if we can't view it as this user.
unless( $asset->canView($userId) ) { unless( $asset->canView ) {
if( !$quiet ) { if( $reportSession ) {
my $message = sprintf( $i18n->get('bad user privileges') . "\n") . $asset->getUrl; my $message = sprintf( $i18n->get('bad user privileges') . "\n") . $asset->getUrl;
$self->session->output->print($message); $reportSession->output->print($message);
} }
$exportSession->var->end;
$exportSession->close;
next; next;
} }
# skip this asset if it's not exportable. # skip this asset if it's not exportable.
unless ( $asset->exportCheckExportable ) { unless ( $asset->exportCheckExportable ) {
if( !$quiet ) { if ( $reportSession ) {
$self->session->output->print("$fullPath skipped, not exportable<br />"); $reportSession->output->print("$fullPath skipped, not exportable<br />");
} }
$exportSession->var->end;
$exportSession->close;
next; next;
} }
# tell the user which asset we're exporting. # tell the user which asset we're exporting.
unless ($quiet) { if ( $reportSession ) {
my $message = sprintf $i18n->get('exporting page'), $fullPath; my $message = sprintf $i18n->get('exporting page'), $fullPath;
$self->session->output->print($message); $reportSession->output->print($message);
} }
# try to write the file # try to write the file
eval { $asset->exportWriteFile }; eval { $asset->exportWriteFile };
if($@) { if( $@ ) {
$returnCode = 0; WebGUI::Error->throw(error => "could not export asset with URL " . $asset->getUrl . ": $@");
$message = $@;
$self->session->output->print("could not export asset with URL " . $asset->getUrl . ": $@");
$exportSession->var->end;
$exportSession->close;
return ($returnCode, $message);
} }
# next, tell the asset that we're exporting, so that it can export any # next, tell the asset that we're exporting, so that it can export any
# of its collateral or other extra data. # of its collateral or other extra data.
eval { $asset->exportAssetCollateral($asset->exportGetUrlAsPath, $args, $session) }; eval { $asset->exportAssetCollateral($asset->exportGetUrlAsPath, $options, $reportSession) };
if($@) { if($@) {
$returnCode = 0; WebGUI::Error->throw(error => "failed to export asset collateral for URL " . $asset->getUrl . ": $@");
$message = $@;
$self->session->output->print("failed to export asset collateral for URL " . $asset->getUrl . ": $@");
$exportSession->var->end;
$exportSession->close;
return ($returnCode, $message);
} }
# we exported this one successfully, so count it # we exported this one successfully, so count it
$exportedCount++; $exportedCount++;
# track when this asset was last exported for external caching and the like # track when this asset was last exported for external caching and the like
$session->db->write( "UPDATE asset SET lastExportedAs = ? WHERE assetId = ?", $self->session->db->write( "UPDATE asset SET lastExportedAs = ? WHERE assetId = ?",
[ $fullPath, $asset->getId ] ); [ $fullPath, $asset->getId ] );
$self->updateHistory("exported"); $self->updateHistory("exported");
# tell the user we did this asset correctly # tell the user we did this asset correctly
unless( $quiet ) { if ( $reportSession ) {
$session->output->print($i18n->get('done')); $reportSession->output->print($i18n->get('done'));
} }
$exportSession->var->end;
$exportSession->close;
} }
# handle symlinking # handle symlinking
if($extrasUploadAction eq 'symlink') { if ($extrasUploadAction eq 'symlink') {
eval { WebGUI::Asset->exportSymlinkExtrasUploads($session) }; $self->exportSymlinkExtrasUploads;
if ($@) {
$returnCode = 0;
$message = $@;
return ($returnCode, $message);
}
} }
if($rootUrlAction eq 'symlink') { if ($rootUrlAction eq 'symlink') {
eval { WebGUI::Asset->exportSymlinkRoot($session, $defaultAsset, $indexFileName, $quiet) }; my $defaultAsset = WebGUI::Asset->getDefault($self->session);
if ($@) { $self->exportSymlinkRoot($defaultAsset, $indexFileName, $reportSession);
$returnCode = 0;
$message = $@;
return ($returnCode, $message);
}
} }
return $exportedCount;
# we're done. give the user a status report.
$returnCode = 1;
my $timeRequired = $session->datetime->time - $startTime;
$message = sprintf $i18n->get('export information'), $exportedCount, $timeRequired;
return ($returnCode, $message);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -472,9 +460,9 @@ sub exportCheckExportable {
Gets the descendants of this asset for exporting, walking the lineage as the Gets the descendants of this asset for exporting, walking the lineage as the
user specified. Takes the following parameters: user specified. Takes the following parameters:
=head3 userId =head3 user
The WebGUI user ID as which to do the export. The WebGUI user object as which to do the export. If not specified, uses the current user.
=head3 depth =head3 depth
@ -497,36 +485,52 @@ sub exportGetDescendants {
my $user = shift; my $user = shift;
my $depth = shift; my $depth = shift;
# check for parameter validity # use current session by default
if( (!defined $user) or (ref $user ne 'WebGUI::User') ) { my $session = $self->session;
WebGUI::Error::InvalidObject->throw( my $asset = $self;
expected => 'WebGUI::User', my $sGuard;
got => ref $user,
error => 'Need a WebGUI::User object',
param => $user
);
}
# check for parameter validity
if( (!defined $depth) or (!looks_like_number($depth)) ) { if( (!defined $depth) or (!looks_like_number($depth)) ) {
WebGUI::Error::InvalidParam->throw(error => 'Need a depth', param => $depth); WebGUI::Error::InvalidParam->throw(error => 'Need a depth', param => $depth);
} }
# open a temporary session as the user doing the exporting so we don't get if ( defined $user ) {
# assets that they can't see # open a temporary session as the user doing the exporting so we don't get
my $tempSession = WebGUI::Session->open($self->session->config->getWebguiRoot,$self->session->config->getFilename); # assets that they can't see
$tempSession->user( { userId => $user->userId } ); if ( ref $user && $user->isa('WebGUI::User') ) {
$session = WebGUI::Session->open(
$session->config->getWebguiRoot,
$session->config->getFilename,
);
$session->user( { userId => $user->userId } );
$sGuard = Scope::Guard->new(sub {
$session->var->end;
$session->close;
});
# clone self in the new session
$asset = WebGUI::Asset->new(
$session,
$self->getId,
$self->get('className'),
$self->get('revisionDate'),
);
}
else {
WebGUI::Error::InvalidObject->throw(
expected => 'WebGUI::User',
got => ref $user,
error => 'Need a WebGUI::User object',
param => $user,
);
}
}
# clone self in the new session and get its lineage as the new user my $assetIds = $asset->getLineage( [ "self", "descendants" ], {
my $cloneOfSelf = WebGUI::Asset->new($tempSession, $self->getId, $self->get('className'), $self->get('revisionDate')); endingLineageLength => $asset->getLineageLength + $depth,
my $assetIds = $cloneOfSelf->getLineage( [ "self", "descendants" ], { orderByClause => 'assetData.url DESC',
endingLineageLength => $cloneOfSelf->getLineageLength + $depth,
orderByClause => 'assetData.url DESC',
} ); } );
# properly close the temp session
$tempSession->var->end;
$tempSession->close;
return $assetIds; return $assetIds;
} }
@ -553,55 +557,58 @@ index filename passed from L</exportAsHtml>
sub exportGetUrlAsPath { sub exportGetUrlAsPath {
my $self = shift; my $self = shift;
my $index = shift || 'index.html'; my $index = shift || 'index.html';
my $options = shift || {};
my $config = $self->session->config; my $config = $self->session->config;
# make sure that the export path is valid # make sure that the export path is valid
WebGUI::Asset->exportCheckPath($self->session); my $exportPath = $self->exportCheckPath;
# if we're still here, it's valid. get it.
my $exportPath = $config->get('exportPath');
# get a list of file types to pass through as-is # get a list of file types to pass through as-is
my $fileTypes = $config->get('exportBinaryExtensions'); my $fileTypes = $config->get('exportBinaryExtensions');
# get the asset's URL as a URI::URL object for easy parsing of components # get the asset's URL as a URI::URL object for easy parsing of components
my $url = URI::URL->new($self->session->url->getSiteURL . $self->getUrl); my $url = $self->get('url');
# for either a sub page or extension, remove the existing extension
if ($options->{subPage} || $options->{extension}) {
$url =~ s/\.[^.]+$//;
}
if ($options->{extension}) {
my $ext = $options->{extension};
$ext =~ s/^\.//;
$url .= ".$ext";
}
if ($options->{subPage}) {
my $subPage = $options->{subPage};
$subPage =~ s{^/}{};
$url .= "/$subPage";
}
$url = URI::URL->new($self->session->url->gateway($url));
my @pathComponents = $url->path_components; my @pathComponents = $url->path_components;
shift @pathComponents; # first item is the empty string shift @pathComponents; # first item is the empty string
my $filename = pop @pathComponents; my $filename = pop @pathComponents;
# if there's no . (i.e., no file with an extension) in $filename, this is my ($extension) = $filename =~ /\.([^.]+)$/;
# simple. Slap on a directory separator, $index, and return it. if ($extension && WebGUI::Utility::isIn($extension, @{ $fileTypes }) ) {
if(!index $filename, '.') { # no need to regex match for a single character return Path::Class::File->new($exportPath, @pathComponents, $filename);
return Path::Class::File->new($exportPath, @pathComponents, $filename, $index);
} }
else { # got a dot else {
my $extension = (File::Basename::fileparse($filename, qr/[^.]*$/))[2]; # get just the extension return Path::Class::File->new($exportPath, @pathComponents, $filename, $index);
# check if the file type is recognised by apache. if it is, return it
# as-is. if not, slap on the directory separator, $index, and return
# it.
if( isIn($extension, @{ $fileTypes } ) ) {
return Path::Class::File->new($exportPath, @pathComponents, $filename);
}
else { # don't know what it is
return Path::Class::File->new($exportPath, @pathComponents, $filename, $index);
}
} }
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
=head2 exportSymlinkExtrasUploads ( session ) =head2 exportSymlinkExtrasUploads ( [ session ] )
Class method. Sets up the extras and uploads symlinks. Class or object method. Sets up the extras and uploads symlinks.
Takes the following parameters: Takes the following parameters:
=head3 session =head3 session
A reference to a L<WebGUI::Session> object. A reference to a L<WebGUI::Session> object. Should only be specified if caled as a class method.
Throws the following exceptions: Throws the following exceptions:
@ -617,11 +624,16 @@ The first parameter is not a L<WebGUI::Session>.
sub exportSymlinkExtrasUploads { sub exportSymlinkExtrasUploads {
my $class = shift; my $class = shift;
my $session = shift; my $session;
if (ref $class && $class->can('session')) {
# check that session is a valid WebGUI::Session object $session = $class->session;
if(!defined $session || ref $session ne 'WebGUI::Session') { }
WebGUI::Error::InvalidObject->throw(error => "first param to exportSymlinkExtrasUploads must be a WebGUI::Session"); else {
$session = shift;
# make sure we were given the right parameters
if((!ref $session) || !$session->isa('WebGUI::Session')) {
WebGUI::Error::InvalidObject->throw(error => "first param to exportSymlinkExtrasUploads as a class method must be a WebGUI::Session");
}
} }
my $config = $session->config; my $config = $session->config;
@ -631,14 +643,11 @@ sub exportSymlinkExtrasUploads {
my $uploadsUrl = $config->get('uploadsURL'); my $uploadsUrl = $config->get('uploadsURL');
# we have no assurance whether the exportPath is valid or not, so check it. # we have no assurance whether the exportPath is valid or not, so check it.
WebGUI::Asset->exportCheckPath($session); my $exportPath = WebGUI::Asset->exportCheckPath($session);
# if we're still here, it's valid
my $exportPath = $config->get('exportPath');
# chop off leading / so we don't accidentally get absolute paths # chop off leading / so we don't accidentally get absolute paths
for my $url ($extrasUrl, $uploadsUrl) { for my $url ($extrasUrl, $uploadsUrl) {
s#^/*##; $url =~ s{^/*}{};
} }
# construct the destination paths # construct the destination paths
@ -667,7 +676,7 @@ sub exportSymlinkExtrasUploads {
#------------------------------------------------------------------- #-------------------------------------------------------------------
=head2 exportSymlinkRoot ( session, defaultAsset, [indexFile], [quiet] ) =head2 exportSymlinkRoot ( [session,] defaultAsset, [indexFile], [reportSession] )
Class method. Places a symlink in the exportPath linking to the index file of Class method. Places a symlink in the exportPath linking to the index file of
the default asset. the default asset.
@ -676,7 +685,7 @@ Takes the following parameters:
=head3 session =head3 session
A reference to a L<WebGUI::Session> object. A reference to a L<WebGUI::Session> object. Should only be specified if called as a class method.
Throws the following exceptions: Throws the following exceptions:
@ -689,9 +698,9 @@ symlink for the root URL.
Optional. Specifies a file name for the index URL. Defaults to C<index.html>. Optional. Specifies a file name for the index URL. Defaults to C<index.html>.
=head3 quiet =head3 reportSession
Optional. Whether to be quiet with our output. Optional. If included, status information will be printed to this session.
=head3 WebGUI::Error =head3 WebGUI::Error
@ -705,16 +714,21 @@ The first parameter is not a L<WebGUI::Session>.
sub exportSymlinkRoot { sub exportSymlinkRoot {
my $class = shift; my $class = shift;
my $session;
if (ref $class && $class->can('session')) {
$session = $class->session;
}
else {
$session = shift;
# make sure we were given the right parameters
if((!ref $session) || !$session->isa('WebGUI::Session')) {
WebGUI::Error::InvalidObject->throw(error => "first param to exportSymlinkRoot as a class method must be a WebGUI::Session");
}
}
my $session = shift;
my $defaultAsset = shift; my $defaultAsset = shift;
my $index = shift || 'index.html'; my $index = shift || 'index.html';
my $quiet = shift; my $reportSession = shift;
# check that $session is valid
if(!defined $session || ref $session ne 'WebGUI::Session') {
WebGUI::Error::InvalidObject->throw(error => 'first param to exportSymlinkRoot must be a WebGUI::Session');
}
# check that $defaultAsset is valid # check that $defaultAsset is valid
if( !defined $defaultAsset || !$defaultAsset->isa('WebGUI::Asset') ) { if( !defined $defaultAsset || !$defaultAsset->isa('WebGUI::Asset') ) {
@ -722,10 +736,7 @@ sub exportSymlinkRoot {
} }
# can't be sure if the export path exists, so check it. # can't be sure if the export path exists, so check it.
WebGUI::Asset->exportCheckPath($session); my $exportPath = WebGUI::Asset->exportCheckPath($session);
# if we're still here, it's valid, so get it
my $exportPath = $session->config->get('exportPath');
# get the source and the destination # get the source and the destination
my $source = $defaultAsset->exportGetUrlAsPath->absolute->stringify; my $source = $defaultAsset->exportGetUrlAsPath->absolute->stringify;
@ -734,9 +745,9 @@ sub exportSymlinkRoot {
my $i18n = WebGUI::International->new($session, 'Asset'); my $i18n = WebGUI::International->new($session, 'Asset');
# tell the user what's happening # tell the user what's happening
if( !$quiet ) { if ( $reportSession ) {
my $message = $i18n->get('rootUrl symlinking default') . "\n"; my $message = $i18n->get('rootUrl symlinking default') . "\n";
$session->output->print($message); $reportSession->output->print($message);
} }
# if the link exists, check if it's set up properly. if it's not, remove it. # if the link exists, check if it's set up properly. if it's not, remove it.
@ -767,7 +778,7 @@ sub exportWriteFile {
my $self = shift; my $self = shift;
# we have no assurance whether the exportPath is valid or not, so check it. # we have no assurance whether the exportPath is valid or not, so check it.
WebGUI::Asset->exportCheckPath($self->session); $self->exportCheckPath;
# if we're still here, everything is well with the export path. let's make # if we're still here, everything is well with the export path. let's make
# sure that this user can view the asset that we want to export. # sure that this user can view the asset that we want to export.
@ -775,14 +786,12 @@ sub exportWriteFile {
WebGUI::Error->throw(error => "user can't view asset at " . $self->getUrl . " to export it"); WebGUI::Error->throw(error => "user can't view asset at " . $self->getUrl . " to export it");
} }
# if we're still here, everything is well with the export path. let's get # if we're still here, everything is well with the export path. let's get
# our destination FS path and then make any required directories. # our destination FS path and then make any required directories.
my $dest = $self->exportGetUrlAsPath; my $dest = $self->exportGetUrlAsPath;
my $parent = $dest->parent; my $parent = $dest->parent;
eval { File::Path::mkpath($parent->absolute->stringify) }; eval { $parent->absolute->mkpath };
if($@) { if($@) {
WebGUI::Error->throw(error => "could not make directory " . $parent->absolute->stringify); WebGUI::Error->throw(error => "could not make directory " . $parent->absolute->stringify);
} }
@ -792,8 +801,6 @@ sub exportWriteFile {
if($@) { if($@) {
WebGUI::Error->throw(error => "can't open " . $dest->absolute->stringify . " for writing: $!"); WebGUI::Error->throw(error => "can't open " . $dest->absolute->stringify . " for writing: $!");
} }
my $previousHandle = $self->session->{_handle};
my $previousDefaultAsset = $self->session->asset;
$self->session->asset($self); $self->session->asset($self);
$self->session->output->setHandle($fh); $self->session->output->setHandle($fh);
my $contents = $self->exportHtml_view; my $contents = $self->exportHtml_view;
@ -802,8 +809,6 @@ sub exportWriteFile {
unless($contents eq 'chunked') { unless($contents eq 'chunked') {
$self->session->output->print($contents); $self->session->output->print($contents);
} }
$self->session->output->setHandle($previousHandle);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -886,7 +891,7 @@ sub www_export {
); );
$f->submit; $f->submit;
my $message; my $message;
eval { WebGUI::Asset->exportCheckPath($self->session) }; eval { $self->exportCheckPath };
if($@) { if($@) {
$message = $@; $message = $@;
} }
@ -911,7 +916,7 @@ sub www_exportStatus {
$iframeUrl = $self->session->url->append($iframeUrl, $formVar . '=' . $self->session->form->process($formVar)); $iframeUrl = $self->session->url->append($iframeUrl, $formVar . '=' . $self->session->form->process($formVar));
} }
my $output = '<iframe src="' . $iframeUrl . '" title="' . $i18n->get('Page Export Status') . '" width="700" height="500"></iframe>'; my $output = '<iframe src="' . $iframeUrl . '" title="' . $i18n->get('Page Export Status') . '" width="100%" height="500"></iframe>';
$self->getAdminConsole->render($output, $i18n->get('Page Export Status'), "Asset"); $self->getAdminConsole->render($output, $i18n->get('Page Export Status'), "Asset");
} }
@ -927,30 +932,40 @@ Executes the export process and displays real time status. This operation is dis
sub www_exportGenerate { sub www_exportGenerate {
my $self = shift; my $self = shift;
return $self->session->privilege->insufficient() unless ($self->session->user->isInGroup(13)); my $session = $self->session;
return $session->privilege->insufficient
unless $session->user->isInGroup(13);
# Unbuffered data output # Unbuffered data output
$|++; $|++;
$self->session->style->useEmptyStyle(1); $session->style->useEmptyStyle(1);
$self->session->http->sendHeader; $session->http->sendHeader;
my $splitter = $self->getSeparator;
my $style = $session->style->process($splitter);
my ($head, $foot) = split /\Q$splitter/, $style;
$session->output->print($head, 1);
my $i18n = WebGUI::International->new($self->session, 'Asset'); my $i18n = WebGUI::International->new($session, 'Asset');
my ($success, $description) = $self->exportAsHtml( { my $args = {
quiet => 0, quiet => 0,
userId => $self->session->form->process('userId'), userId => $session->form->process('userId'),
indexFileName => $self->session->form->process('index'), indexFileName => $session->form->process('index'),
extrasUploadAction => $self->session->form->process('extrasUploadsAction'), extrasUploadAction => $session->form->process('extrasUploadsAction'),
rootUrlAction => $self->session->form->process('rootUrlAction'), rootUrlAction => $session->form->process('rootUrlAction'),
depth => $self->session->form->process('depth'), depth => $session->form->process('depth'),
exportUrl => $self->session->form->process('exportUrl'), exportUrl => $session->form->process('exportUrl'),
}); };
if (!$success) { eval {
$self->session->output->print($description, 1); my $message = $self->exportAsHtml( $args );
return "chunked"; $self->session->output->print($message, 1);
$self->session->output->print(
'<a target="_parent" href="' . $self->getUrl . '">' . $i18n->get(493, 'WebGUI') . '</a>'
);
};
if ($@) {
$self->session->output->print("$@", 1);
} }
$session->output->print($foot, 1);
$self->session->output->print($description, 1);
$self->session->output->print('<a target="_parent" href="' . $self->getUrl . '">' . $i18n->get(493, 'WebGUI') . '</a>');
return "chunked"; return "chunked";
} }

View file

@ -269,6 +269,14 @@ sub definition {
label => $i18n->get('global head tags label'), label => $i18n->get('global head tags label'),
hoverHelp => $i18n->get('global head tags description'), hoverHelp => $i18n->get('global head tags description'),
defaultValue => $setting->get('globalHeadTags'), defaultValue => $setting->get('globalHeadTags'),
};
push @fields, {
tab => 'ui',
fieldType => 'yesNo',
name => 'useMobileStyle',
label => $i18n->get('mobile style label'),
hoverHelp => $i18n->get('mobile style description'),
defaultValue => $setting->get('useMobileStyle'),
}; };
# messaging settings # messaging settings
push(@fields, { push(@fields, {

View file

@ -239,6 +239,26 @@ sub DESTROY {
$self->close; $self->close;
} }
#-------------------------------------------------------------------
=head2 duplicate ( )
Creates a new session using the same WebGUI root, config file, and user.
=cut
sub duplicate {
my $self = shift;
my $newSession = WebGUI::Session->open(
$self->config->getWebguiRoot,
$self->config->getFilename,
undef,
undef,
$self->getId,
);
return $newSession;
}
#------------------------------------------------------------------- #-------------------------------------------------------------------

View file

@ -120,6 +120,51 @@ sub makePrintable {
$self->{_makePrintable} = shift; $self->{_makePrintable} = shift;
} }
#-------------------------------------------------------------------
=head2 useMobileStyle
Returns a true value if we are on a mobile display.
=cut
sub useMobileStyle {
my $self = shift;
my $session = $self->session;
my $scratchCheck = $session->scratch->get('useMobileStyle');
if (defined $scratchCheck) {
return $scratchCheck;
}
if (exists $self->{_useMobileStyle}) {
return $self->{_useMobileStyle};
}
if (! $session->setting->get('useMobileStyle')) {
return $self->{_useMobileStyle} = 0;
}
my $ua = $session->env->get('HTTP_USER_AGENT');
for my $mobileUA (@{ $self->session->config->get('mobileUserAgents') }) {
if ($ua =~ m/$mobileUA/) {
return $self->{_useMobileStyle} = 1;
}
}
return $self->{_useMobileStyle} = 0;
}
#-------------------------------------------------------------------
=head2 setMobileStyle
Sets whether the mobile style should be used for this session.
=cut
sub setMobileStyle {
my $self = shift;
my $enableMobile = shift;
$self->session->scratch->set('useMobileStyle', $enableMobile);
return $enableMobile;
}
#------------------------------------------------------------------- #-------------------------------------------------------------------

View file

@ -139,6 +139,13 @@ be useful, others may not.|,
lastUpdated => 1210967539 lastUpdated => 1210967539
}, },
'mobileTemplateId label' => {
message => 'Mobile Template',
},
'mobileTemplateId description' => {
message => 'Choose the template to use if viewing this Page Layout in a mobile browser.',
},
}; };
1; 1;

View file

@ -115,6 +115,13 @@ is displayed as part of a Layout Asset, the Layout Asset's <b>Style Template</b>
lastUpdated => 1167374430, lastUpdated => 1167374430,
}, },
'mobileStyleTemplateId label' => {
message => 'Mobile Style Template'
},
'mobileStyleTemplateId description' => {
message => q|Select a style template from the list to enclose your asset if it is viewed on a mobile browser|,
},
}; };
1; 1;

View file

@ -4402,6 +4402,13 @@ Users may override this setting in their profile.
lastUpdated => 1239057119, lastUpdated => 1239057119,
}, },
'mobile style label' => {
message => 'Use Mobile Style',
},
'mobile style description' => {
message => q{Enables displaying using a mobile style template and mobile page layout template. When enabled, the alternate templates are used when the browser's user agent string matches the list set in the config file.},
},
}; };
1; 1;

View file

@ -128,6 +128,7 @@ checkModule('JavaScript::Packer', '0.02' );
checkModule('CSS::Packer', '0.2' ); checkModule('CSS::Packer', '0.2' );
checkModule('Business::Tax::VAT::Validation', '0.20' ); checkModule('Business::Tax::VAT::Validation', '0.20' );
checkModule('Crypt::SSLeay', '0.57' ); checkModule('Crypt::SSLeay', '0.57' );
checkModule('Scope::Guard', '0.03' );
failAndExit("Required modules are missing, running no more checks.") if $missingModule; failAndExit("Required modules are missing, running no more checks.") if $missingModule;

View file

@ -56,7 +56,7 @@ isa_ok($e, 'WebGUI::Error::InvalidObject', 'exportCheckPath tests that its argum
cmp_deeply( cmp_deeply(
$e, $e,
methods( methods(
error => "first param to exportCheckPath must be a WebGUI::Session", error => 'first param to exportCheckPath as a class method must be a WebGUI::Session',
), ),
"exportCheckPath tests that its argument is a WebGUI::Session" "exportCheckPath tests that its argument is a WebGUI::Session"
); );
@ -150,7 +150,7 @@ $config->set('exportPath', $tempDirectory);
eval { $returnCode = WebGUI::Asset->exportCheckPath($session) }; eval { $returnCode = WebGUI::Asset->exportCheckPath($session) };
is($@, '', "exportCheckPath with valid path lives"); is($@, '', "exportCheckPath with valid path lives");
is($returnCode, 1, "exportCheckPath returns true value"); ok($returnCode, "exportCheckPath returns true value");
# now, let's try a directory to which we know we have access, but a path within # now, let's try a directory to which we know we have access, but a path within
# it that doesn't exist. # it that doesn't exist.
@ -159,7 +159,7 @@ $config->set('exportPath', $accessibleDirectory->stringify); # now accessible!
eval { $returnCode = WebGUI::Asset->exportCheckPath($session) }; eval { $returnCode = WebGUI::Asset->exportCheckPath($session) };
is($@, '', "exportCheckPath creating subdirectory lives"); is($@, '', "exportCheckPath creating subdirectory lives");
is($returnCode, 1, "exportCheckPath creating subdirectory returns true value"); ok($returnCode, "exportCheckPath creating subdirectory returns true value");
is(-d $accessibleDirectory, 1, "exportCheckPath creating subdirectory actually creates said subdirectory"); is(-d $accessibleDirectory, 1, "exportCheckPath creating subdirectory actually creates said subdirectory");
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
@ -492,7 +492,7 @@ isa_ok($e, 'WebGUI::Error::InvalidObject', 'exportSymlinkExtrasUploads without s
cmp_deeply( cmp_deeply(
$e, $e,
methods( methods(
error => 'first param to exportSymlinkExtrasUploads must be a WebGUI::Session', error => 'first param to exportSymlinkExtrasUploads as a class method must be a WebGUI::Session',
), ),
'exportSymlinkExtrasUploads without session object throws', 'exportSymlinkExtrasUploads without session object throws',
); );
@ -504,7 +504,7 @@ isa_ok($e, 'WebGUI::Error::InvalidObject', 'exportSymlinkExtrasUploads called wi
cmp_deeply( cmp_deeply(
$e, $e,
methods( methods(
error => 'first param to exportSymlinkExtrasUploads must be a WebGUI::Session', error => 'first param to exportSymlinkExtrasUploads as a class method must be a WebGUI::Session',
), ),
'exportSymlinkExtrasUploads called with memetic parameter throws', 'exportSymlinkExtrasUploads called with memetic parameter throws',
); );
@ -541,7 +541,7 @@ $e = Exception::Class->caught;
isa_ok($e, 'WebGUI::Error::InvalidObject', 'exportSymlinkRoot without session object throws'); isa_ok($e, 'WebGUI::Error::InvalidObject', 'exportSymlinkRoot without session object throws');
cmp_deeply($e, cmp_deeply($e,
methods( methods(
error => 'first param to exportSymlinkRoot must be a WebGUI::Session' error => 'first param to exportSymlinkRoot as a class method must be a WebGUI::Session'
), ),
'exportSymlinkRoot without session object throws', 'exportSymlinkRoot without session object throws',
); );
@ -553,7 +553,7 @@ $e = Exception::Class->caught;
isa_ok($e, 'WebGUI::Error::InvalidObject', 'exportSymlinkRoot called with memetic parameter throws'); isa_ok($e, 'WebGUI::Error::InvalidObject', 'exportSymlinkRoot called with memetic parameter throws');
cmp_deeply($e, cmp_deeply($e,
methods( methods(
error => 'first param to exportSymlinkRoot must be a WebGUI::Session' error => 'first param to exportSymlinkRoot as a class method must be a WebGUI::Session'
), ),
'exportSymlinkRoot called with memetic parameter throws', 'exportSymlinkRoot called with memetic parameter throws',
); );
@ -590,18 +590,18 @@ cmp_deeply(
$home->exportWriteFile; $home->exportWriteFile;
my $symlinkedRoot = Path::Class::File->new($exportPath, 'index.html'); my $symlinkedRoot = Path::Class::File->new($exportPath, 'index.html');
my $homePath = $home->exportGetUrlAsPath; my $homePath = $home->exportGetUrlAsPath;
eval { WebGUI::Asset->exportSymlinkRoot($session, $home, '', 1) }; eval { WebGUI::Asset->exportSymlinkRoot($session, $home, '') };
is($@, '', 'exportSymlinkRoot works when it should'); is($@, '', 'exportSymlinkRoot works when it should');
ok(-e $symlinkedRoot->stringify, 'exportSymlinkRoot sets up link correctly and supplies default index'); ok(-e $symlinkedRoot->stringify, 'exportSymlinkRoot sets up link correctly and supplies default index');
is($homePath, readlink $symlinkedRoot->stringify, 'exportSymlinkRoot sets up link correctly and supplies default index'); is(readlink $symlinkedRoot->stringify, $homePath, 'exportSymlinkRoot sets up link correctly and supplies default index');
unlink $symlinkedRoot->stringify; unlink $symlinkedRoot->stringify;
# give it an index and ensure it works # give it an index and ensure it works
eval { WebGUI::Asset->exportSymlinkRoot($session, $home, 'index.html', 1) }; eval { WebGUI::Asset->exportSymlinkRoot($session, $home, 'index.html') };
is($@, '', 'exportSymlinkRoot works when it should'); is($@, '', 'exportSymlinkRoot works when it should');
ok(-e $symlinkedRoot->stringify, 'exportSymlinkRoot sets up link correctly and supplies default index'); ok(-e $symlinkedRoot->stringify, 'exportSymlinkRoot sets up link correctly and supplies default index');
is($homePath, readlink $symlinkedRoot->stringify, 'exportSymlinkRoot sets up link correctly and supplies default index'); is(readlink $symlinkedRoot->stringify, $homePath, 'exportSymlinkRoot sets up link correctly and supplies default index');
unlink $symlinkedRoot->stringify; unlink $symlinkedRoot->stringify;
@ -644,26 +644,7 @@ $descendants = $grandChild->exportGetDescendants( WebGUI::User->new($session, 1)
cmp_deeply($descendants, $gcDescendants, "exportGetDescendants returns correct data for getting-started"); cmp_deeply($descendants, $gcDescendants, "exportGetDescendants returns correct data for getting-started");
# finally, ensure that calling exportGetDescendants without a userID throws an exception.
eval { $home->exportGetDescendants }; eval { $home->exportGetDescendants };
$e = Exception::Class->caught;
isa_ok($e, 'WebGUI::Error::InvalidObject', 'exportGetDescendants called without a user object throws');
cmp_deeply(
$e,
methods(
expected => 'WebGUI::User',
got => '',
error => 'Need a WebGUI::User object',
param => undef,
),
"exportGetDescendants called without a user object throws",
);
# make sure calling exportGetDescendants without a depth throws an exception.
eval { $home->exportGetDescendants( WebGUI::User->new($session, 1) ) };
$e = Exception::Class->caught; $e = Exception::Class->caught;
isa_ok($e, 'WebGUI::Error::InvalidParam', 'exportGetDescendants called without a depth throws'); isa_ok($e, 'WebGUI::Error::InvalidParam', 'exportGetDescendants called without a depth throws');
cmp_deeply( cmp_deeply(
@ -699,26 +680,23 @@ my $exportPath = Path::Class::Dir->new($session->config->get('exportPath'));
# default. exportAsHtml is supposed to catch exceptions, not throw them, so # default. exportAsHtml is supposed to catch exceptions, not throw them, so
# we'll be testing the return values rather than for an exception. # we'll be testing the return values rather than for an exception.
($success, $message) = $home->exportAsHtml; eval { $message = $home->exportAsHtml };
is($success, 0, "exportAsHtml returns 0 when not given a userId"); is($@, "need a userId parameter", "exportAsHtml returns correct error when not given a userId");
is($message, "need a userId parameter", "exportAsHtml returns correct message when not given a userId");
# omitting the userId works, so let's give it a bogus userId # omitting the userId works, so let's give it a bogus userId
($success, $message) = $home->exportAsHtml( { userId => '<rizen> perlDreamer is a 500 lb test mandating gorilla' } ); eval { $message = $home->exportAsHtml( { userId => '<rizen> perlDreamer is a 500 lb test mandating gorilla' } ) };
is($success, 0, "exportAsHtml returns 0 when given a bogus (but nonetheless funny) userId"); is($@, "'<rizen> perlDreamer is a 500 lb test mandating gorilla' is not a valid userId", "exportAsHtml throws correct error when given a bogus (but nonetheless funny) userId");
is($message, "'<rizen> perlDreamer is a 500 lb test mandating gorilla' is not a valid userId", "exportAsHtml returns correct message when given a bogus (but nonetheless funny) userId");
# checking an autogenerated userId # checking an autogenerated userId
my $randomUser = WebGUI::User->new($session, 'new'); my $randomUser = WebGUI::User->new($session, 'new');
($success, $message) = $home->exportAsHtml( { userId => $randomUser->userId, depth => 99} ); eval { $message = $home->exportAsHtml( { userId => $randomUser->userId, depth => 99} ) };
is($success, 1, "exportAsHtml returns 1 when given a valid userId"); is($@, '', "exportAsHtml doesn't throw error when given a valid userId");
$randomUser->delete; $randomUser->delete;
undef $randomUser; undef $randomUser;
# checking userId works, so check extrasUploadAction next. # checking userId works, so check extrasUploadAction next.
($success, $message) = $home->exportAsHtml( { userId => 3, depth => 99, extrasUploadAction => 'o hai' } ); eval { $message = $home->exportAsHtml( { userId => 3, depth => 99, extrasUploadAction => 'o hai' } ) };
is($success, 0, "exportAsHtml returns 0 when given bogus, memetic extrasUploadAction parameter"); is($@, "'o hai' is not a valid extrasUploadAction", "exportAsHtml throws correct error when given bogus, memetic extrasUploadAction parameter");
is($message, "'o hai' is not a valid extrasUploadAction", "exportAsHtml returns 0 when given bogus, memetic extrasUploadAction parameter");
# rootUrlAction # rootUrlAction
($success, $message) = $home->exportAsHtml( { userId => 3, depth => 99, rootUrlAction => 'NO U' } ); ($success, $message) = $home->exportAsHtml( { userId => 3, depth => 99, rootUrlAction => 'NO U' } );

View file

@ -48,7 +48,7 @@ is_deeply($wf->getCrons, [], 'workflow has no crons');
isa_ok(WebGUI::Workflow->getList($session), 'HASH', 'getList returns a hashref'); isa_ok(WebGUI::Workflow->getList($session), 'HASH', 'getList returns a hashref');
ok(!isIn($wfId, keys %{WebGUI::Workflow->getList($session)}), 'workflow not in enabled list'); ok(!isIn($wfId, keys %{WebGUI::Workflow->getList($session)}), 'workflow not in enabled list');
is(scalar keys %{WebGUI::Workflow->getList($session)}, 11, 'There are eleven default workflows, of all types, shipped with WebGUI'); is(scalar keys %{WebGUI::Workflow->getList($session)}, 12, 'There are twelve default workflows, of all types, shipped with WebGUI');
$wf->set({enabled => 1}); $wf->set({enabled => 1});
ok($wf->get('enabled'), 'workflow is enabled'); ok($wf->get('enabled'), 'workflow is enabled');