webgui/lib/WebGUI/AssetPackage.pm

275 lines
9.4 KiB
Perl

package WebGUI::Asset;
=head1 LEGAL
-------------------------------------------------------------------
WebGUI is Copyright 2001-2006 Plain Black Corporation.
-------------------------------------------------------------------
Please read the legal notices (docs/legal.txt) and the license
(docs/license.txt) that came with this distribution before using
this software.
-------------------------------------------------------------------
http://www.plainblack.com info@plainblack.com
-------------------------------------------------------------------
=cut
use strict;
use JSON;
use WebGUI::Storage;
=head1 NAME
Package WebGUI::Asset
=head1 DESCRIPTION
This is a mixin package for WebGUI::Asset that contains all package related functions.
=head1 SYNOPSIS
use WebGUI::Asset;
=head1 METHODS
These methods are available from this class:
=cut
#-------------------------------------------------------------------
=head2 exportAssetData ( )
Converts all the properties of this asset into a hash reference and then returns the hash reference. This method should be expanded upon by sub classes that have more data than just asset property data. Two nodes will be created: "properties" and "storage". Properties is a hash reference of the asset properties. Storage is an array reference of storage location ids. Storage will initially be empty, but if you have storage locations you want to include in this, then please push their ids onto this list when you override this method.
=cut
sub exportAssetData {
my $self = shift;
my %data = %{$self->get};
my %hash = ( properties => \%data, storage=>[] );
return \%hash;
}
#-------------------------------------------------------------------
=head2 exportPackage ( )
Turns this package into a package file and returns the storage location object of the package file.
=cut
sub exportPackage {
my $self = shift;
my $storage = WebGUI::Storage->createTemp($self->session);
foreach my $asset (@{$self->getLineage(["self","descendants"],{returnObjects=>1})}) {
my $data = $asset->exportAssetData;
$storage->addFileFromScalar($data->{properties}{lineage}.".json", JSON::objToJson($data,{pretty => 1, indent => 4, autoconv=>0, skipinvalid=>1}));
foreach my $storageId (@{$data->{storage}}) {
my $assetStorage = WebGUI::Storage->get($self->session, $storageId);
$assetStorage->tar($storageId.".storage", $storage);
}
}
my $filename = $self->get("url").".wgpkg";
$filename =~ s/\//_/g;
return $storage->tar($filename);
}
#-------------------------------------------------------------------
=head2 getPackageList ( )
Returns an array of hashes containing title, assetId, and className for all assets defined as packages.
=cut
sub getPackageList {
my $self = shift;
my @assets;
my $sql = "
select
asset.assetId,
assetData.revisionDate,
asset.className
from
asset
left join
assetData on asset.assetId=assetData.assetId
where
assetData.isPackage=1
and assetData.revisionDate=(SELECT max(revisionDate) from assetData where assetData.assetId=asset.assetId and
(assetData.status='approved'";
$sql .= " or assetData.tagId=".$self->session->db->quote($self->session->scratch->get("versionTag")) if ($self->session->scratch->get("versionTag"));
$sql .= ")) and asset.state='published' group by assetData.assetId order by assetData.title desc";
my $sth = $self->session->db->read($sql);
while (my ($id, $date, $class) = $sth->array) {
my $asset = WebGUI::Asset->new($self->session, $id,$class);
push(@assets, $asset) if ($asset->get("isPackage"));
}
$sth->finish;
return \@assets;
}
#-------------------------------------------------------------------
=head2 importAssetData ( hashRef )
Imports the data exported by the exportAssetData method. If the asset already exists, a new revision will be created with these properties. If it doesn't exist then a child will be added to the current asset. Returns a reference to the created asset.
=head3 hashRef
A hash reference containing the exported data.
=cut
sub importAssetData {
my $self = shift;
my $data = shift;
my $error = $self->session->errorHandler;
my $id = $data->{properties}{assetId};
my $class = $data->{properties}{className};
my $version = $data->{properties}{revisionDate};
my $asset = WebGUI::Asset->new($self->session, $id, $class, $version);
if (defined $asset) { # update an existing revision
$error->info("Updating an existing revision of asset $id");
$asset->update($data->{properties});
##Pending assets are assigned a new version tag
if ($data->{properties}->{status} eq 'pending') {
$self->session->db->write(
'update assetData set tagId=? where assetId=? and revisionDate='.$data->{properties}->{revisionDate},
[WebGUI::VersionTag->getWorking($self->session)->getId, $data->{properties}->{assetId}]
);
}
}
else {
$asset = WebGUI::Asset->new($self->session, $id, $class);
if (defined $asset) { # create a new revision of an existing asset
$error->info("Creating a new revision of asset $id");
$asset = $asset->addRevision($data->{properties}, $version, {skipAutoCommitWorkflows => 1});
}
else { # add an entirely new asset
$error->info("Adding $id that didn't previously exist.");
$asset = $self->addChild($data->{properties}, $id, $version, {skipAutoCommitWorkflows => 1});
}
}
return $asset;
}
#-------------------------------------------------------------------
=head2 importPackage ( storageLocation )
Imports the data from a webgui package file.
=head3 storageLocation
A reference to a WebGUI::Storage object that contains a webgui package file.
=cut
sub importPackage {
my $self = shift;
my $storage = shift;
my $decompressed = $storage->untar($storage->getFiles->[0]);
my %assets = ();
my $error = $self->session->errorHandler;
$error->info("Importing package.");
foreach my $file (sort(@{$decompressed->getFiles})) {
next unless ($decompressed->getFileExtension($file) eq "json");
$error->info("Found data file $file");
my $data = eval{JSON::jsonToObj($decompressed->getFileContentsAsScalar($file))};
if ($@ || $data->{properties}{assetId} eq "" || $data->{properties}{className} eq "" || $data->{properties}{revisionDate} eq "") {
$error->error("package corruption: ".$@) if ($@);
return "corrupt";
}
$error->info("Data file $file is valid and represents asset ".$data->{properties}{assetId});
foreach my $storageId (@{$data->{storage}}) {
my $assetStorage = WebGUI::Storage->get($self->session, $storageId);
$decompressed->untar($storageId.".storage", $assetStorage);
}
my $asset = $assets{$data->{properties}{parentId}} || $self;
my $newAsset = $asset->importAssetData($data);
$assets{$newAsset->getId} = $newAsset;
}
return undef;
}
#-------------------------------------------------------------------
=head2 www_deployPackage ( )
Deploys the package referenced by the query parameter 'assetId' as a
new child of the current asset. Requires edit privileges on the
current asset.
=cut
sub www_deployPackage {
my $self = shift;
# Must have edit rights to the asset deploying the package. Also, must be a Content Manager.
# This protects against non content managers deploying packages using a post or similar trickery.
return $self->session->privilege->insufficient() unless ($self->canEdit && $self->session->user->isInGroup(4));
my $packageMasterAssetId = $self->session->form->param("assetId");
if (defined $packageMasterAssetId) {
my $packageMasterAsset = WebGUI::Asset->newByDynamicClass($self->session, $packageMasterAssetId);
unless ($packageMasterAsset->getValue('isPackage')) { #only deploy packages
$self->session->errorHandler->security('deploy an asset as a package which was not set as a package.');
return;
}
my $masterLineage = $packageMasterAsset->get("lineage");
if (defined $packageMasterAsset && $packageMasterAsset->canView && $self->get("lineage") !~ /^$masterLineage/) {
my $deployedTreeMaster = $packageMasterAsset->duplicateBranch;
$deployedTreeMaster->setParent($self);
$deployedTreeMaster->update({isPackage=>0, styleTemplateId=>$self->get("styleTemplateId")});
}
}
return "";
}
#-------------------------------------------------------------------
=head2 www_exportPackage ( )
Returns a tarball file for the user to download containing the package data.
=cut
sub www_exportPackage {
my $self = shift;
return $self->session->privilege->insufficient() unless ($self->get("isPackage") && $self->canEdit && $self->session->user->isInGroup(4));
my $storage = $self->exportPackage;
my $filename = $storage->getFiles->[0];
$self->session->http->setRedirect($storage->getUrl($storage->getFiles->[0]));
return "redirect";
}
#-------------------------------------------------------------------
=head2 www_importPackage ( )
=cut
sub www_importPackage {
my $self = shift;
return $self->session->privilege->insufficient() unless ($self->canEdit && $self->session->user->isInGroup(4));
my $storage = WebGUI::Storage->createTemp($self->session);
##This is a hack. It should use the WebGUI::Form::File API to insulate
##us from future form name changes.
$storage->addFileFromFormPost("packageFile",1);
my $error = "";
if ($storage->getFileExtension($storage->getFiles->[0]) eq "wgpkg") {
$error = $self->importPackage($storage);
}
if ($error) {
my $i18n = WebGUI::International->new($self->session, "Asset");
return $self->session->style->userStyle($i18n->get("package corrupt"));
}
return $self->www_manageAssets();
}
1;