package WebGUI::Asset::File; =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 base 'WebGUI::Asset'; use WebGUI::Cache; use WebGUI::Storage; use WebGUI::SQL; use WebGUI::Utility; use FileHandle; =head1 NAME Package WebGUI::Asset::File =head1 DESCRIPTION Provides a mechanism to upload files to WebGUI. =head1 SYNOPSIS use WebGUI::Asset::File; =head1 METHODS These methods are available from this class: =cut #------------------------------------------------------------------- =head2 addRevision Override the default method in order to deal with attachments. =cut sub addRevision { my $self = shift; my $properties = shift; if ($self->get("storageId") ne "") { my $newStorage = WebGUI::Storage->get($self->session,$self->get("storageId"))->copy; $properties->{storageId} = $newStorage->getId; } my $newSelf = $self->SUPER::addRevision($properties); return $newSelf; } #------------------------------------------------------------------- =head2 definition ( definition ) Defines the properties of this asset. =head3 definition A hash reference passed in from a subclass definition. =cut sub definition { my $class = shift; my $session = shift; my $definition = shift; my $i18n = WebGUI::International->new($session,"Asset_File"); push(@{$definition}, { assetName=>$i18n->get('assetName'), tableName=>'FileAsset', className=>'WebGUI::Asset::File', properties=>{ cacheTimeout => { tab => "display", fieldType => "interval", defaultValue => 3600, uiLevel => 8, label => $i18n->get("cache timeout"), hoverHelp => $i18n->get("cache timeout help") }, filename=>{ noFormPost=>1, fieldType=>'hidden', defaultValue=>undef }, storageId=>{ noFormPost=>1, fieldType=>'hidden', defaultValue=>undef }, templateId=>{ fieldType=>'template', defaultValue=>'PBtmpl0000000000000024' } } }); return $class->SUPER::definition($session, $definition); } #------------------------------------------------------------------- sub duplicate { my $self = shift; my $newAsset = $self->SUPER::duplicate(@_); my $newStorage = $self->getStorageLocation->copy; $newAsset->update({storageId=>$newStorage->getId}); return $newAsset; } #------------------------------------------------------------------- =head2 exportAssetData ( ) See WebGUI::AssetPackage::exportAssetData() for details. =cut sub exportAssetData { my $self = shift; my $data = $self->SUPER::exportAssetData; push(@{$data->{storage}}, $self->get("storageId")) if ($self->get("storageId") ne ""); return $data; } #------------------------------------------------------------------- =head2 getEditForm ( ) Returns the TabForm object that will be used in generating the edit page for this asset. =cut sub getEditForm { my $self = shift; my $tabform = $self->SUPER::getEditForm(); my $i18n = WebGUI::International->new($self->session, 'Asset_File'); if ($self->get("filename") ne "") { $tabform->getTab("properties")->readOnly( -label=>$i18n->get('current file'), -hoverHelp=>$i18n->get('current file description', 'Asset_File'), -value=>'

'.$self->get( '.$self->get("filename").'

' ); } $tabform->getTab("properties")->file( -name => 'newFile', -label => $i18n->get('new file'), -hoverHelp => $i18n->get('new file description'), ); return $tabform; } #------------------------------------------------------------------- sub getFileUrl { my $self = shift; #return $self->get("url"); return $self->getStorageLocation->getUrl($self->get("filename")); } #------------------------------------------------------------------- sub getFileIconUrl { my $self = shift; return $self->getStorageLocation->getFileIconUrl($self->get("filename")); } #------------------------------------------------------------------- sub getIcon { my $self = shift; my $small = shift; if ($small && $self->get("dummy")) { return $self->session->url->extras('assets/small/file.gif'); } elsif ($small) { return $self->getFileIconUrl; } return $self->session->url->extras('assets/file.gif'); } #------------------------------------------------------------------- sub getStorageLocation { my $self = shift; unless (exists $self->{_storageLocation}) { $self->setStorageLocation; } return $self->{_storageLocation}; } #------------------------------------------------------------------- =head2 indexContent ( ) Indexing the content of the attachment. See WebGUI::Asset::indexContent() for additonal details. =cut sub indexContent { my $self = shift; my $indexer = $self->SUPER::indexContent; $indexer->addFile($self->getStorageLocation->getPath($self->get("filename"))); } #------------------------------------------------------------------- =head2 prepareView ( ) See WebGUI::Asset::prepareView() for details. =cut sub prepareView { my $self = shift; $self->SUPER::prepareView(); my $template = WebGUI::Asset::Template->new($self->session, $self->get("templateId")); $template->prepare; $self->{_viewTemplate} = $template; } #------------------------------------------------------------------- sub processPropertiesFromFormPost { my $self = shift; my $session = $self->session; $self->SUPER::processPropertiesFromFormPost; #Get the storage location out of memory. If you call getStorageLocation you risk creating another one. my $storageLocation = $self->{_storageLocation}; my $storageId = undef; $storageId = $storageLocation->getId if(defined $storageLocation); #Now remove the storage location to prevent wierd caching stuff. delete $self->{_storageLocation}; #Clear the storage location if a file was uploaded. if($session->form->get("newFile_file") ne "") { $storageLocation->clear(); } #Pass in the storage Id to prevent another one from being created. my $fileStorageId = WebGUI::Form::File->new($session, {name => 'newFile', value=>$storageId })->getValueFromPost; my $storage = WebGUI::Storage->get($session, $fileStorageId); if (defined $storage) { $storage->setPrivileges($self->get('ownerUserId'), $self->get('groupIdView'), $self->get('groupIdEdit')); my $filename = $storage->getFiles()->[0]; if (defined $filename) { my %data; $data{filename} = $filename; $data{storageId} = $storage->getId; $data{title} = $filename unless ($session->form->process("title")); $data{menuTitle} = $filename unless ($session->form->process("menuTitle")); $data{url} = $self->getParent->get('url').'/'.$filename unless ($session->form->process("url")); $self->setStorageLocation($storage); $self->update(\%data); } } } #------------------------------------------------------------------- sub purge { my $self = shift; my $sth = $self->session->db->read("select storageId from FileAsset where assetId=".$self->session->db->quote($self->getId)); while (my ($storageId) = $sth->array) { WebGUI::Storage->get($self->session,$storageId)->delete; } $sth->finish; return $self->SUPER::purge; } #------------------------------------------------------------------- =head2 purgeCache ( ) See WebGUI::Asset::purgeCache() for details. =cut sub purgeCache { my $self = shift; WebGUI::Cache->new($self->session,"view_".$self->getId)->delete; $self->SUPER::purgeCache; } #------------------------------------------------------------------- sub purgeRevision { my $self = shift; $self->getStorageLocation->delete; return $self->SUPER::purgeRevision; } #------------------------------------------------------------------- sub setSize { my $self = shift; my $fileSize = shift || 0; my $storage = $self->getStorageLocation; if (defined $storage) { foreach my $file (@{$storage->getFiles}) { $fileSize += $storage->getFileSize($file); } } return $self->SUPER::setSize($fileSize); } #------------------------------------------------------------------- sub setStorageLocation { my $self = shift; my $storage = shift; if (defined $storage) { $self->{_storageLocation} = $storage; } elsif ($self->get("storageId") eq "") { $self->{_storageLocation} = WebGUI::Storage->create($self->session); $self->update({storageId=>$self->{_storageLocation}->getId}); } else { $self->{_storageLocation} = WebGUI::Storage->get($self->session,$self->get("storageId")); } } #------------------------------------------------------------------- =head2 update We override the update method from WebGUI::Asset in order to handle file system privileges. =cut sub update { my $self = shift; my %before = ( owner => $self->get("ownerUserId"), view => $self->get("groupIdView"), edit => $self->get("groupIdEdit"), storageId => $self->get('storageId'), ); ##update may have entered a new storageId. Reset the cached one just in case. if ($self->get("storageId") ne $before{storageId}) { $self->setStorageLocation; } if ($self->get("ownerUserId") ne $before{owner} || $self->get("groupIdEdit") ne $before{edit} || $self->get("groupIdView") ne $before{view}) { $self->getStorageLocation->setPrivileges($self->get("ownerUserId"),$self->get("groupIdView"),$self->get("groupIdEdit")); } $self->SUPER::update(@_); } #------------------------------------------------------------------- sub view { my $self = shift; if (!$self->session->var->isAdminOn && $self->get("cacheTimeout") > 10) { my $out = WebGUI::Cache->new($self->session,"view_".$self->getId)->get; return $out if $out; } my %var = %{$self->get}; $var{controls} = $self->getToolbar; $var{fileUrl} = $self->getFileUrl; $var{fileIcon} = $self->getFileIconUrl; $var{fileSize} = formatBytes($self->get("assetSize")); my $out = $self->processTemplate(\%var,undef,$self->{_viewTemplate}); if (!$self->session->var->isAdminOn && $self->get("cacheTimeout") > 10) { WebGUI::Cache->new($self->session,"view_".$self->getId)->set($out,$self->get("cacheTimeout")); } return $out; } #------------------------------------------------------------------- sub www_edit { my $self = shift; return $self->session->privilege->insufficient() unless $self->canEdit; return $self->session->privilege->locked() unless $self->canEditIfLocked; my $i18n = WebGUI::International->new($self->session); my $tabform = $self->getEditForm; $tabform->getTab("display")->template( -value=>$self->getValue("templateId"), -hoverHelp=>$i18n->get('file template description','Asset_File'), -namespace=>"FileAsset" ); $self->getAdminConsole->setHelp("file add/edit", "Asset_File"); my $addEdit = ($self->session->form->process("func") eq 'add') ? $i18n->get('add','Asset_Wobject') : $i18n->get('edit','Asset_Wobject'); return $self->getAdminConsole->render($tabform->print,$addEdit.' '.$self->getName); } #------------------------------------------------------------------- # setStreamedFile and setRedirect do not interact well with the # exporter. We have a separate method for this now. sub exportHtml_view { my $self = shift; my $path = $self->getStorageLocation->getPath($self->get('filename')); my $fh = eval { FileHandle->new($path) }; defined($fh) or return ""; binmode $fh or ($fh->close, return ""); my $block; while (read($fh, $block, 16384) > 0) { $self->session->output->print($block, 1); } $fh->close; return 'chunked'; } #-------------------------------------------------------------------- sub www_view { my $self = shift; return $self->session->privilege->noAccess() unless $self->canView; # Check to make sure it's not in the trash or some other weird place my $state = $self->get("state"); if ($state ne "published" && $state ne "archived") { my $i18n = WebGUI::International->new($self->session,'Asset_File'); $self->session->http->setStatus("404"); return sprintf($i18n->get("file not found"), $self->getUrl()); } $self->session->http->setRedirect($self->getFileUrl); $self->session->http->setStreamedFile($self->getStorageLocation->getPath($self->get("filename"))); return 'chunked'; } 1;