diff --git a/docs/upgrades/upgrade_6.2.9-6.3.0.pl b/docs/upgrades/upgrade_6.2.9-6.3.0.pl index 6237d5885..6164d832c 100644 --- a/docs/upgrades/upgrade_6.2.9-6.3.0.pl +++ b/docs/upgrades/upgrade_6.2.9-6.3.0.pl @@ -49,7 +49,97 @@ $sth->finish; WebGUI::SQL->write("delete from settings where name in ('siteicon','favicon')"); +#print "\tConverting Pages, Wobjects, and Forums to Assets\n" unless ($quiet); +#walkTree('0','theroot','000001','0'); WebGUI::Session::close(); +sub walkTree { + my $oldParentId = shift; + my $newParentId = shift; + my $parentLineage = shift; + my $myRank = shift; + WebGUI::SQL->write("alter table wobject add column assetId varchar(22) not null"); + my $sth = WebGUI::SQL->read("select distinct(namespace) from wobject"); + while (my ($namespace) = $sth->array) { + WebGUI::SQL->write("alter table ".$namespace." add column assetId varchar(22) not null"); + } + $sth->finish; + my $a = WebGUI::SQL->read("select * from page where subroutinePackage='WebGUI::Page' and parentId=".quote($oldParentId)); + while (my $page = $a->hashRef) { + my $pageId = WebGUI::Id::generate(); + my $pageLineage = $parentLineage.sprintf("%06d",$myRank); + my $pageUrl = $page->{urlizedTitle}; + my $className = 'WebGUI::Asset::Layout'; + if ($page->{redirectURL} ne "") { + $className = 'WebGUI::Asset::Redirect'; + } + WebGUI::SQL->write("insert into asset (assetId, parentId, lineage, className, state, title, menuTitle, url, startDate, + endDate, synopsis, newWindow, isHidden, ownerUserId, groupIdView, groupIdEdit) values (".quote($pageId).", + ".quote($newParentId).", ".quote($pageLineage).", ".quote($className).",'published',".quote($page->{title}).", + ".quote($page->{menuTitle}).", ".quote($pageUrl).", ".quote($page->startDate).", ".quote($page->{endDate}).", + ".quote($page->{synopsis}).", ".quote($page->{newWindow}).", ".quote($page->{hideFromNavigation}).", ".quote($page->{ownerId}).", + ".quote($page->{groupIdView}).", ".quote($page->{groupIdEdit}).")"); + if ($page->{redirectURL} ne "") { + WebGUI::SQL->write("insert into redirect (assetId, redirectUrl) values (".quote($pageId).",".quote($page->{redirectURL}).")"); + } else { + WebGUI::SQL->write("insert into layout (assetId, styleTemplateId, layoutTemplateId, printableStyleTemplateId) values ( + ".quote($pageId).", ".quote($page->{styleId}).", ".quote($page->{templateId}).", + ".quote($page->{printableStyleTemplateId}).")"); + } + my $rank = 0; + my $b = WebGUI::SQL->read("select * from wobject where pageId=".quote($page->{pageId})); + while (my $wobject = $b->hashRef) { + $rank++; + my $wobjectId = WebGUI::Id::generate(); + my $wobjectLineage = $pageLineage.sprintf("%06d",$rank); + my $wobjectUrl = $pageUrl."/".$wobject->{title}; + my $groupIdView = $page->{groupIdView}; + my $groupIdEdit = $page->{groupIdEdit}; + my $ownerId = $page->{ownerId}; + if ($page->{wobjectPrivileges}) { + $groupIdView = $wobject->{groupIdView}; + $groupIdEdit = $wobject->{groupIdEdit}; + $ownerId = $wobject->{ownerId}; + } + $className = 'WebGUI::Asset::Wobject::'.$wobject->{namespace}; + WebGUI::SQL->write("insert into asset (assetId, parentId, lineage, className, state, title, menuTitle, url, startDate, + endDate, synopsis, isHidden, ownerUserId, groupIdView, groupIdEdit) values (".quote($wobjectId).", + ".quote($pageId).", ".quote($wobjectLineage).", ".quote($className).",'published',".quote($page->{title}).", + ".quote($page->{title}).", ".quote($wobjectUrl).", ".quote($wobject->startDate).", ".quote($wobject->{endDate}).", + ".quote($page->{synopsis}).", 1, ".quote($ownerId).", ".quote($groupIdView).", ".quote($groupIdEdit).")"); + WebGUI::SQL->write("update wobject set assetId=".quote($wobjectId)); + my $c = WebGUI::SQL->read("select * from ".$wobject->{namespace}." where wobjectId=".quote($wobject->{wobjectId})); + while (my $namespace = $c->hashRef) { + } + $c->finish; + } + $b->finish; + walkTree($page->{pageId},$pageId,$pageLineage,$rank+1); + } + $a->finish; + my $sth = WebGUI::SQL->read("select distinct(namespace) from wobject"); + while (my ($namespace) = $sth->array) { + if (isIn($namespace, qw(Article DataForm EventsCalendar HttpProxy IndexedSearch MessageBoard Poll Product SQLReport Survey SyndicatedContent USS WobjectProxy WSClient))) { + WebGUI::SQL->write("alter table ".$namespace." drop column wobjectId"); + } else { + WebGUI::SQL->write("alter table ".$namespace." drop primary key"); + } + WebGUI::SQL->write("alter table ".$namespace." add primary key (assetId)"); + } + $sth->finish; + WebGUI::SQL->write("alter table wobject drop column wobjectId"); + WebGUI::SQL->write("alter table wobject add primary key (assetId)"); + WebGUI::SQL->write("alter table wobject drop column namespace"); + WebGUI::SQL->write("alter table wobject drop column title"); + WebGUI::SQL->write("alter table wobject drop column ownerId"); + WebGUI::SQL->write("alter table wobject drop column groupIdEdit"); + WebGUI::SQL->write("alter table wobject drop column groupIdView"); + WebGUI::SQL->write("drop table page"); +} + + + + + diff --git a/docs/upgrades/upgrade_6.2.9-6.3.0.sql b/docs/upgrades/upgrade_6.2.9-6.3.0.sql index 67117e48d..730bfa852 100644 --- a/docs/upgrades/upgrade_6.2.9-6.3.0.sql +++ b/docs/upgrades/upgrade_6.2.9-6.3.0.sql @@ -48,14 +48,18 @@ create table asset ( parentId varchar(22) not null, lineage varchar(255) not null, state varchar(35) not null, - namespace varchar(255) not null, + className varchar(255) not null, boundToId varchar(22), title varchar(255), menuTitle varchar(255), url varchar(255) not null, startDate bigint not null, endDate bigint not null, + ownerUserId varchar(22) not null, + groupIdView varchar(22) not null, + groupIdEdit varchar(22) not null, synopsis text, + newWindow int not null default 0, isHidden int not null default 0, isSystem int not null default 0, unique index (lineage asc), @@ -63,5 +67,5 @@ create table asset ( index (parentId) ); -insert into asset (assetId, parentId, lineage, state, namespace, title, menuTitle, url, startDate, endDate, isSystem) values ('theroot', 'infinity', '000001','published','Asset','Root','Root','root',997995720,9223372036854775807,1); +insert into asset (assetId, parentId, lineage, state, className, title, menuTitle, url, startDate, endDate, isSystem, ownerUserId, groupIdView, groupIdEdit) values ('theroot', 'infinity', '000001','published','WebGUI::Asset','Root','Root','root',997995720,9223372036854775807,1,'3','3','3'); diff --git a/lib/WebGUI/Asset.pm b/lib/WebGUI/Asset.pm index b1bda7898..988c9aad3 100644 --- a/lib/WebGUI/Asset.pm +++ b/lib/WebGUI/Asset.pm @@ -17,11 +17,19 @@ sub addChild { my $properties = shift; my $id = WebGUI::Id::generate(); my $lineage = $self->get("lineage").$self->getNextChildRank; - WebGUI::SQL->write("insert into asset (assetId, parentId, lineage, state, namespace, url, startDate, endDate) + WebGUI::SQL->beginTransaction; + WebGUI::SQL->write("insert into asset (assetId, parentId, lineage, state, className, url, startDate, endDate) values (".quote($id).",".quote($self->getId).", ".quote($lineage).", - 'published', ".quote($properties->{namespace}).", ".quote($id).", + 'published', ".quote($properties->{className}).", ".quote($id).", 997995720, 9223372036854775807)"); - my $newAsset = WebGUI::Asset->new($id); + foreach my $definition (@{$self->{definition}}) { + unless ($definition->{tableName} eq "asset") { + WebGUI::SQL->write("insert into ".$definition->{tableName}." (assetId) values (".quote($id).")"); + } + } + WebGUI::SQL->commit; + my $className = $properties->{className}; + my $newAsset = $className->new($id); $newAsset->set($properties); return $newAsset; } @@ -29,7 +37,7 @@ sub addChild { sub canEdit { my $self = shift; my $userId = shift || $session{user}{userId}; - if ($userId eq $self->get("ownerId")) { + if ($userId eq $self->get("ownerUserId")) { return 1; } return WebGUI::Grouping::isInGroup($self->get("groupIdEdit"),$userId); @@ -38,7 +46,7 @@ sub canEdit { sub canView { my $self = shift; my $userId = shift || $session{user}{userId}; - if ($userId eq $self->get("ownerId")) { + if ($userId eq $self->get("ownerUserId")) { return 1; } elsif ($self->get("startDate") < time() && $self->get("endDate") > time() && @@ -65,6 +73,55 @@ sub cut { $self->{_properties}{state} = "clipboard"; } +sub definition { + my $class = shift; + my $definition = shift; + push(@{$definition}, { + tableName=>'asset', + className=>'WebGUI::Asset', + properties=>{ + title=>{ + fieldType=>'text', + defaultValue=>$definition->[0]->{className} + }, + menuTitle=>{ + fieldType=>'text', + defaultValue=>undef + }, + synopsis=>{ + fieldType=>'textarea', + defaultValue=>undef + }, + url=>{ + fieldType=>'text', + defaultValue=>undef, + filter=>'fixUrl', + }, + groupIdEdit=>{ + fieldType=>'group', + defaultValue=>'4' + }, + groupIdView=>{ + fieldType=>'group', + defaultValue=>'7' + }, + ownerUserId=>{ + fieldType=>'selectList', + defaultValue=>'3' + }, + startDate=>{ + fieldType=>'dateTime', + defaultValue=>undef + }, + endDate=>{ + fieldType=>'dateTime', + defaultValue=>undef + }, + } + }); + return $definition; +} + sub delete { my $self = shift; WebGUI::SQL->beginTransaction; @@ -124,10 +181,23 @@ sub get { return $self->{_properties}; } + + + +#------------------------------------------------------------------- + +=head2 getAdminConsole () + +Returns a reference to a WebGUI::AdminConsole object. + +=cut + sub getAdminConsole { my $self = shift; - my $ac = WebGUI::AdminConsole->set("assets"); - return $ac; + unless (exists $self->{_adminConsole}) { + $self->{_adminConsole} = WebGUI::AdminConsole->new("assets"); + } + return $self->{_adminConsole}; } sub getEditForm { @@ -214,14 +284,14 @@ sub getEditForm { push (@$contentManagers, $session{user}{userId}); $clause = "userId in (".quoteAndJoin($contentManagers).")"; } else { - $clause = "userId=".quote($self->get("ownerId")); + $clause = "userId=".quote($self->get("ownerUserId")); } my $users = WebGUI::SQL->buildHashRef("select userId,username from users where $clause order by username"); $tabform->getTab("privileges")->select( - -name=>"ownerId", + -name=>"ownerUserId", -options=>$users, -label=>WebGUI::International::get(108), - -value=>[$self->get("ownerId")], + -value=>[$self->get("ownerUserId")], -subtext=>$subtext, -uiLevel=>6 ); @@ -307,16 +377,14 @@ sub getLineage { my $lineageLength = length($lineage); $whereDescendants .= "lineage like ".quote($lineage.'%')." and length(lineage)> ".$lineageLength; } - my $select = "*"; - $select = "assetId" if ($rules->{returnIds}); - my $sql = "select $select from asset where $whereSiblings $whereExact $whereDescendants order by lineage"; + my $sql = "select assetId from asset where $whereSiblings $whereExact $whereDescendants order by lineage"; my @lineage; my $sth = WebGUI::SQL->read($sql); - while (my $asset = $sth->hashRef) { - if ($rules->{returnIds}) { - push(@lineage,$asset->{assetId}); + while (my ($assetId) = $sth->array) { + if ($rules->{returnOjbects}) { + push(@lineage,WebGUI::Asset->new($assetId); } else { - push(@lineage,WebGUI::Asset->new($asset->{assetId},$asset)); + push(@lineage,$assetId); } } $sth->finish; @@ -352,7 +420,14 @@ sub getValue { my $self = shift; my $key = shift; if (defined $key) { - return $session{form}{$key} || $self->get($key); + unless (exists $self->{_propertyDefinitions}) { # check to see if the defintions have been merged and cached + my %properties; + foreach my $definition (@{$self->definition}) { + %properties = (%properties, %{$definition->{properties}}); + } + $self->{_propertyDefinitions} = \%properties; + } + return $session{form}{$key} || $self->get($key) || $self->{_propertiyDefinitions}{$key}{defaultValue}; } return undef; } @@ -360,17 +435,33 @@ sub getValue { sub new { my $class = shift; my $assetId = shift; - my $properties = shift; + my $overrideProperties = shift; + my $properties; + if ($assetId eq "new") { + $properties = $overrideProperties; + $properties->{assetId} = "new"; + $properties->{className} = $class; + } else { + my $definitions = $class->definition; + my @definitionsReversed = reverse(@{$definitions}); + shift(@definitionsReversed); + my $sql = "select * from asset"; + foreach my $definition (@definitionsReversed) { + $sql .= " left join ".$definition->{tableName}." on asset.assetId=".$definition->{tableName}.".assetId"; + } + $sql .= " where asset.assetId=".quote($assetId); + $properties = WebGUI::SQL->quickHashRef($sql); + return undef unless (exists $properties->{assetId}); + foreach my $property (keys %{$overrideProperties}) { + unless (isIn($property, qw(assetId className parentId lineage state))) { + $properties->{$property} = $overrideProperties->{$property}; + } + } + } if (defined $properties) { return bless { _properties=>$properties }, $class; - } else { - $properties = WebGUI::SQL->quickHashRef("select * from asset where assetId=".quote($assetId)); - if (exists $properties->{assetId}) { - return bless { _properties=>$properties}, $class; - } else { - return undef; - } } + return undef; } sub paste { @@ -396,21 +487,38 @@ sub promote { return 0; } +sub purge { + my $self = shift; + # NOTE to self, still need to delete all children too + WebGUI::SQL->beginTransaction; + foreach my $definition (@{$self->definition}) { + WebGUI::SQL->write("delete from ".$definition->{tableName}." where assetId=".quote($self->getId)); + } + WebGUI::SQL->commit; + $self = undef; +} + sub set { my $self = shift; my $properties = shift; - my %props = %{$properties}; # make a copy so we don't disturb the original as we make changes - my @setPairs; - foreach my $property (keys %props) { - if (isIn($property, qw(groupIdEdit groupIdView ownerId startDate endDate url title menuTitle synopsis))) { - if ($property eq "url") { - $props{url} = $self->fixUrl($props{url}); + WebGUI::SQL->beginTransaction; + foreach my $definition (@{$self->definition}) { + my @setPairs; + foreach my $property (keys %{$definition->{properties}}) { + my $value = $properties->{$property} || $definition->{properties}{$property}{defaultValue}; + if (defined $value) { + if (exists $definition->{properties}{$property}{filter}) { + $value = $self->$definition->{properties}{$property}{filter}($value); + } + $self->{_properties}{$property} = $value; + push(@setPairs, $property."=".quote($value)); } - $self->{_properties}{$property} = $props{$property}; - push(@setPairs ,$property."=".quote($props{$property})); + } + if (scalar(@setPairs) > 0) { + WebGUI::SQL->write("update ".$definition->{tableName}." set ".join(",",@setPairs)." where assetId=".quote($self->getId)); } } - WebGUI::SQL->write("update asset set ".join(",",@setPairs)." where assetId=".quote($self->getId)); + WebGUI::SQL->commit; return 1; } @@ -439,7 +547,7 @@ sub setRank { my $currentRank = $self->getRank; return 1 if ($newRank == $currentRank); # do nothing if we're moving to ourself my $parentLineage = $self->getParentLineage; - my $siblings = $self->getLineage(["siblings"]); + my $siblings = $self->getLineage(["siblings"],{returnObjects=>1}); my $temp = substr(WebGUI::Id::generate(),0,6); if ($newRank < $currentRank) { # have to do the ordering in reverse when the new rank is above the old rank @{$siblings} = reverse @{$siblings}; @@ -478,42 +586,64 @@ sub www_copy { return WebGUI::Privilege::insufficient() unless $self->canEdit; my $newAsset = $self->duplicate; $newAsset->cut; + return ""; } sub www_cut { my $self = shift; return WebGUI::Privilege::insufficient() unless $self->canEdit; $self->cut; + return ""; } sub www_delete { my $self = shift; return WebGUI::Privilege::insufficient() unless $self->canEdit; $self->delete; + return ""; } sub www_demote { my $self = shift; return WebGUI::Privilege::insufficient() unless $self->canEdit; $self->demote; + return ""; } sub www_edit { my $self = shift; return WebGUI::Privilege::insufficient() unless $self->canEdit; - return "No editor has been defined for this asset."; + return $self->getAdminConsole->render($self->getEditForm); +} + +sub www_editSave { + my $self = shift; + my %data; + foreach my $definition (@{$self->definition}) { + foreach my $property (keys %{$definition->{properties}}) { + my $data{$property} = WebGUI::FormProcessor::process( + $property, + $definition->{properties}{fieldType}, + $definition->{properties}{defaultValue} + ); + } + } + $self->set(\%data); + return ""; } sub www_paste { my $self = shift; return WebGUI::Privilege::insufficient() unless $self->canEdit; $self->paste($session{form}{newParentId}); + return ""; } sub www_promote { my $self = shift; return WebGUI::Privilege::insufficient() unless $self->canEdit; $self->promote; + return ""; } sub www_view { diff --git a/lib/WebGUI/Asset/Wobject.pm b/lib/WebGUI/Asset/Wobject.pm new file mode 100644 index 000000000..8f4143832 --- /dev/null +++ b/lib/WebGUI/Asset/Wobject.pm @@ -0,0 +1,350 @@ +package WebGUI::Asset::Wobject; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2004 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 CGI::Util qw(rearrange); +use DBI; +use strict qw(subs vars); +use Tie::IxHash; +use WebGUI::AdminConsole; +use WebGUI::DateTime; +use WebGUI::FormProcessor; +use WebGUI::Grouping; +use WebGUI::HTML; +use WebGUI::HTMLForm; +use WebGUI::Icon; +use WebGUI::Id; +use WebGUI::International; +use WebGUI::Macro; +use WebGUI::Node; +use WebGUI::Page; +use WebGUI::Privilege; +use WebGUI::Session; +use WebGUI::SQL; +use WebGUI::TabForm; +use WebGUI::Template; +use WebGUI::URL; +use WebGUI::Utility; +use WebGUI::MetaData; +use WebGUI::Wobject::WobjectProxy; + +=head1 NAME + +Package WebGUI::Wobject + +=head1 DESCRIPTION + +An abstract class for all other wobjects to extend. + +=head1 SYNOPSIS + + use WebGUI::Wobject; + our @ISA = qw(WebGUI::Wobject); + +See the subclasses in lib/WebGUI/Wobjects for details. + +=head1 METHODS + +These methods are available from this class: + +=cut + +sub definition { + my $class = shift; + my $definition = shift; + push(@{$definition}, { + tableName=>'wobject', + className=>'WebGUI::Asset::Wobject', + properties=>{ + description=>{ + fieldType=>'HTMLArea', + defaultValue=>undef + }, + displayTitle=>{ + fieldType=>'yesNo', + defaultValue=>1 + }, + cacheTimeout=>{ + fieldType=>'interval', + defaultValue=>60 + }, + cacheTimeoutVisitor=>{ + fieldType=>'interval', + defaultValue=>600 + } + } + }); + return $class->SUPER::definition($definition); +} + + + +#------------------------------------------------------------------- + +=head2 confirm ( message, yesURL, [ , noURL, vitalComparison ] ) + +=head3 message + +A string containing the message to prompt the user for this action. + +=head3 yesURL + +A URL to the web method to execute if the user confirms the action. + +=head3 noURL + +A URL to the web method to execute if the user denies the action. Defaults back to the current page. + +=head3 vitalComparison + +A comparison expression to be used when checking whether the action should be allowed to continue. Typically this is used when the action is a delete of some sort. + +=cut + +sub confirm { + return WebGUI::Privilege::vitalComponent() if ($_[4]); + my $noURL = $_[3] || WebGUI::URL::page(); + my $output = '
'; + $output .= '