From 0e55ec42cd253ccb08c1b192155f56e5cd2ac8ce Mon Sep 17 00:00:00 2001 From: Doug Bell Date: Fri, 4 Jan 2008 06:23:38 +0000 Subject: [PATCH] Added migration utility for Gallery --- docs/changelog/7.x.x.txt | 1 + lib/WebGUI/Asset/Wobject/Gallery/Utility.pm | 195 ++++++++++++++++++++ sbin/migrateCollabToGallery.pl | 136 ++++++++++++++ t/Asset/Wobject/Gallery/Utility/addAlbum.t | 158 ++++++++++++++++ 4 files changed, 490 insertions(+) create mode 100644 lib/WebGUI/Asset/Wobject/Gallery/Utility.pm create mode 100644 sbin/migrateCollabToGallery.pl create mode 100644 t/Asset/Wobject/Gallery/Utility/addAlbum.t diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 690bd3041..bb9026bfb 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -15,6 +15,7 @@ - Fixed chdir problem in Storage -- more remain though - Added a new plugin handler system that is both faster and more secure. - Added switch for assets to determine whether they are exportable. + - Added migration utility for Gallery 7.4.20 - fix: Assets with no committed versions may be left as orphans when parent is purged diff --git a/lib/WebGUI/Asset/Wobject/Gallery/Utility.pm b/lib/WebGUI/Asset/Wobject/Gallery/Utility.pm new file mode 100644 index 000000000..81f251295 --- /dev/null +++ b/lib/WebGUI/Asset/Wobject/Gallery/Utility.pm @@ -0,0 +1,195 @@ +package WebGUI::Asset::Wobject::Gallery::Utility; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2005 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 Carp qw( carp croak ); +use File::Find; +use Scalar::Util qw( blessed ); +use WebGUI::Asset::Wobject::Collaboration; +use WebGUI::Asset::Wobject::Gallery; +use WebGUI::Asset::Post::Thread; +use WebGUI::Storage::Image; + + +=head1 NAME + +WebGUI::Asset::Wobject::Gallery::Utility -- Utility functions for working +with Gallery assets. + +=head1 DESCRIPTION + +This module provides utility functions to work with Gallery assets from +utility scripts. + +This module is B to be used by the Gallery asset itself! + +=head1 SYNOPSIS + + use WebGUI::Asset::Wobject::Gallery::Utility; + my $utility = "WebGUI::Asset::Wobject::Gallery::Utility" # <- not as cumbersome + + # Add albums from a collaboration system's threads + my $gallery = WebGUI::Asset::Wobject::Gallery->new( ... ); + my $collab = WebGUI::Asset::Wobject::Collaboration->new( ... ); + $utility->addAlbumFromCollaboration( $gallery, $collab ); + + # Add a single album from a collaboration system thread + my $thread = WebGUI::Asset::Post::Thread->new( ... ); + $utility->addAlbumFromThread( $gallery, $thread ); + + # Add a single album from a filesystem branch + $utility->addAlbumFromFilesystem( $gallery, "/Users/Doug/Photos" ); + + # Add a single album for every folder in a filesystem branch + $utility->addAlbumFromFilesystem( + $gallery, "/Users/Doug/Photos", + { + multiple => 1, + } + ); + +=head1 METHODS + +These methods are available from this class: + +=cut + +#---------------------------------------------------------------------------- + +=head2 addAlbumFromCollaboration ( gallery, collab ) + +Add an album or albums to the gallery from the given Collaboration System. +C is an instanciated Gallery asset. C is an instanciated +Collaboration System asset. + +Will add one album for every thread in the Collaboration System. Will call +C to do its dirty work. + +=cut + +sub addAlbumFromCollaboration { + my $class = shift; + my $gallery = shift; + my $collab = shift; + + croak "First argument must be Gallery asset" + unless blessed $gallery && $gallery->isa('WebGUI::Asset::Wobject::Gallery'); + croak "Second argument must be Collaboration System asset" + unless blessed $collab && $collab->isa('WebGUI::Asset::Wobject::Collaboration'); + + my $threads + = $collab->getLineage(['descendants'], { + returnObjects => 1, + includeOnlyClasses => ['WebGUI::Asset::Post::Thread'], + statesToInclude => ['published'], + statusToInclude => ['approved', 'archived', 'pending'], + }); + + for my $thread ( @$threads ) { + $class->addAlbumFromThread( $gallery, $thread ); + } + + return; +} + +#---------------------------------------------------------------------------- + +=head2 addAlbumFromFilesystem ( gallery, root [, options] ) + +Add an album to the gallery from the file system. C is an +instanciated Gallery asset. C is a location on the file system. + +C is a hash reference of options with the following keys: + + multiple - Create multiple albums, one for each folder. + +=cut + +sub addAlbumFromFilesystem { + my $class = shift; + my $gallery = shift; + my $root = shift; + my $options = shift; + + # TODO!!! + + return; +} + +#---------------------------------------------------------------------------- + +=head2 addAlbumFromThread ( gallery, thread ) + +Add an album to the gallery from the given Collaboration System thread. +C is an instanciated Gallery asset. C is an instanciated +Thread asset. + +=cut + +sub addAlbumFromThread { + my $class = shift; + my $gallery = shift; + my $thread = shift; + + croak "First argument must be Gallery asset" + unless blessed $gallery && $gallery->isa('WebGUI::Asset::Wobject::Gallery'); + croak "Second argument must be Thread asset" + unless blessed $thread && $thread->isa('WebGUI::Asset::Post::Thread'); + + my $session = $gallery->session; + my $addOptions = { skipAutoCommitWorkflows => 1 }; + + # Get all the storage locations + my @storageIds = (); + for my $post ( @{ $thread->getPosts } ) { + if ( $post->get('storageId') ) { + push @storageIds, $post->get('storageId'); + } + } + + # Create the new album + my $album = $gallery->addChild({ + className => 'WebGUI::Asset::Wobject::GalleryAlbum', + title => $thread->get('title'), + menuTitle => $thread->get('menuTitle'), + description => $thread->get('bodyText'), + synopsis => $thread->get('synopsis'), + }, undef, $thread->get('revisionDate'), $addOptions ); + + # Add a new Photo asset for each photo in the storage locations + for my $storageId ( @storageIds ) { + # Use WebGUI::Storage::Image to avoid thumbnails if there + my $storage = WebGUI::Storage::Image->get( $session, $storageId ); + + for my $filename ( @{$storage->getFiles} ) { + my $className = $gallery->getAssetClassForFile( $filename ); + if ( !$className ) { + warn "Skipping $filename because Gallery doesn't handle this file type"; + next; + } + + my $file = $album->addChild({ + className => $className, + }, undef, $thread->get('revisionDate'), $addOptions ); + + $file->setFile( $storage->getPath( $filename ) ); + } + } + + return; +} + +1; diff --git a/sbin/migrateCollabToGallery.pl b/sbin/migrateCollabToGallery.pl new file mode 100644 index 000000000..e850bd855 --- /dev/null +++ b/sbin/migrateCollabToGallery.pl @@ -0,0 +1,136 @@ + +use lib "../lib"; +use strict; +use Getopt::Long; +use Pod::Usage; +use WebGUI::Asset::Wobject::Gallery::Utility; +use WebGUI::Session; + +my $session = start(); + +my $collab = getCollaborationFromArgs(); +my $gallery = getGalleryFromArgs(); + +WebGUI::Asset::Wobject::Gallery::Utility->addAlbumFromCollaboration( $gallery, $collab ); + +finish($session); + +#---------------------------------------------------------------------------- +# getCollaborationFromArgs +# Gets the collaboration system from the arguments. The argument can be +# either an assetId or an absolute URL +sub getCollaborationFromArgs { + my $asset; + my $arg = $ARGV[0]; + if ( $arg =~ m{^/} ) { + $asset = WebGUI::Asset->newByUrl( $session, $arg ); + } + else { + $asset = WebGUI::Asset->newByDynamicClass( $session, $arg ); + } + + unless ( $asset && $asset->isa('WebGUI::Asset::Wobject::Collaboration') ) { + pod2usage("$0: First argument must be a Collaboration asset"); + } + + return $asset; +} + +#---------------------------------------------------------------------------- +# getGalleryFromArgs +# Gets the Gallery from the arguments. The argument can be either an assetId +# or an absolute URL +sub getGalleryFromArgs { + my $asset; + my $arg = $ARGV[1]; + if ( $arg =~ m{^/} ) { + $asset = WebGUI::Asset->newByUrl( $session, $arg ); + } + else { + $asset = WebGUI::Asset->newByDynamicClass( $session, $arg ); + } + + unless ( $asset && $asset->isa('WebGUI::Asset::Wobject::Gallery') ) { + pod2usage("$0: Second argument must be a Gallery asset"); + } + + return $asset; +} + +#---------------------------------------------------------------------------- +sub start { + $| = 1; #disable output buffering + my ($configFile, $help); + GetOptions( + 'configFile=s' => \$configFile, + 'help' => \$help, + ); + + # Show usage + if ($help) { + pod2usage(1); + } + + unless ($configFile) { + pod2usage("$0: Must specify a --configFile"); + } + + my $session = WebGUI::Session->open("..",$configFile); + $session->user({userId=>3}); + + my $versionTag = WebGUI::VersionTag->getWorking($session); + $versionTag->set({name => 'Migrate Collaboration to Gallery'}); + + return $session; +} + +#---------------------------------------------------------------------------- +sub finish { + my $session = shift; + + my $versionTag = WebGUI::VersionTag->getWorking($session); + $versionTag->commit; + + $session->var->end; + $session->close; +} + + +=head1 NAME + +migrateCollabToGallery.pl -- Migrate a collaboration system into a Gallery + +=head1 SYNOPSIS + +migrateCollabToGallery.pl --configFile= + +=head1 ARGUMENTS + +=over + +=item collab + +A collaboration system URL or asset ID. The URL must be an absolute URL, and +so must begin with a "/". + +=item gallery + +A Gallery URL or asset ID. The URL must be an absolute URL, and so much begin +with a "/". + +=back + +=head1 OPTIONS + +=over + +=item configFile + +The WebGUI config file to use. + +=back + +=head1 DESCRIPTION + +This script migrates a collaboration system's threads into gallery albums. It +uses C for its major features. diff --git a/t/Asset/Wobject/Gallery/Utility/addAlbum.t b/t/Asset/Wobject/Gallery/Utility/addAlbum.t new file mode 100644 index 000000000..816a21bba --- /dev/null +++ b/t/Asset/Wobject/Gallery/Utility/addAlbum.t @@ -0,0 +1,158 @@ +# $vim:syntax=perl +#------------------------------------------------------------------- +# WebGUI is Copyright 2001-2007 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 +#------------------------------------------------------------------ + +# Test the addAlbum* methods from the Gallery::Utility class +# +# + +use strict; +use FindBin; +use lib "$FindBin::Bin/../../../../../lib"; +use lib "$FindBin::Bin/../../../../lib"; +use Test::More; +use Test::Deep; +use WebGUI::Asset; +use WebGUI::Session; +use WebGUI::Test; + +#---------------------------------------------------------------------------- +# Init +my $session = WebGUI::Test->session; +my $node = WebGUI::Asset->getImportNode( $session ); + +# Add arguments to avoid autocommit workflows +my @addArgs = ( undef, undef, { skipAutoCommitWorkflows => 1 } ); + +my @versionTags; +push @versionTags, WebGUI::VersionTag->getWorking( $session ); + +# Generate a Gallery to import into +my $gallery; +my $album; + +# Generate a collaboration system to import +my $collab + = $node->addChild({ + className => 'WebGUI::Asset::Wobject::Collaboration', + }); + +my @threads; +for (1..3) { + push @threads, $collab->addChild({ + className => 'WebGUI::Asset::Post::Thread', + }, @addArgs); + $threads[-1]->getStorageLocation->addFileFromFilesystem( + WebGUI::Test->getTestCollateralPath('lamp.jpg') + ); +} + +# Add a post to one of the threads, with an image +my @posts; +push @{$posts[0]}, $threads[0]->addChild({ + className => 'WebGUI::Asset::Post', +}, @addArgs); +$posts[0][0]->getStorageLocation->addFileFromFilesystem( + WebGUI::Test->getTestCollateralPath('lamp.jpg') +); + +#---------------------------------------------------------------------------- +# Tests + +# addAlbumFromThread tests $thread[0] and @{$posts[0]} +my $threadTests = 4 * ( 1 + scalar @{ $posts[0] } ); + +plan tests => 9 + $threadTests; + +#---------------------------------------------------------------------------- +# Test use +my $utility = 'WebGUI::Asset::Wobject::Gallery::Utility'; +use_ok($utility); + +#---------------------------------------------------------------------------- +# Test addAlbumFromThread +$gallery = $node->addChild({ className => 'WebGUI::Asset::Wobject::Gallery' }); + +ok( + !eval{ $utility->addAlbumFromThread( "", $threads[0] ); 1}, + "addAlbumFromThread croaks if first argument is not a Gallery asset", +); + +ok( + !eval{ $utility->addAlbumFromThread( $gallery, "" ); 1}, + "addAlbumFromThread croaks if second argument is not a Thread asset", +); + +$utility->addAlbumFromThread( $gallery, $threads[0] ); + +is( + scalar @{ $gallery->getAlbumIds }, 1, + "addAlbumFromThread creates a new album", +); + +$album = WebGUI::Asset->newByDynamicClass( $session, $gallery->getAlbumIds->[0] ); + +is( + $album->get('revisionDate'), $threads[0]->get('revisionDate'), + "addAlbumFromThread creates album with same revisionDate as thread", +); + +is( + scalar @{ $album->getFileIds }, 2, + "addAlbumFromThread adds one file for each attachment to the thread or posts of the thread", +); + +# 4 tests for each post/file +for my $fileId ( @{$album->getFileIds} ) { + my $file = WebGUI::Asset->newByDynamicClass( $session, $fileId ); + is( + $file->get('revisionDate'), $threads[0]->get('revisionDate'), + "addAlbumFromThread adds files with same revisionDate as thread", + ); + isa_ok( $file->getStorageLocation, 'WebGUI::Storage', 'Storage location exists' ); + ok( $file->get('filename'), '"filename" property was set' ); + cmp_deeply( + $file->getStorageLocation->getFiles, superbagof($file->get('filename')), + "Storage location contains the filename" + ); +} + +#---------------------------------------------------------------------------- +# Test addAlbumFromCollaboration +$gallery = $node->addChild({ className => 'WebGUI::Asset::Wobject::Gallery' }); + +ok( + !eval{ $utility->addAlbumFromCollaboration( "", $collab ); 1}, + "addAlbumFromCollaboration croaks if first argument is not a Gallery asset", +); + +ok( + !eval{ $utility->addAlbumFromCollaboration( $gallery, "" ); 1}, + "addAlbumFromCollaboration croaks if second argument is not a Collaboration asset", +); + +$utility->addAlbumFromCollaboration( $gallery, $collab ); + +is( + scalar @{ $gallery->getAlbumIds }, scalar @threads, + "addAlbumFromCollaboration creates one album per thread", +); + +#---------------------------------------------------------------------------- +# Test addAlbumFromFilesystem +# TODO!!! + +#---------------------------------------------------------------------------- +# Cleanup +END { + for my $tag ( @versionTags ) { + $tag->rollback; + } +}