Adding new cached pagetree stuff.
This commit is contained in:
parent
019c28e63e
commit
97dfbcbb01
2 changed files with 439 additions and 115 deletions
|
|
@ -45,38 +45,36 @@ sub _changeWobjectPrivileges {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _recursivelyChangePrivileges {
|
||||
my ($sth, $pageId);
|
||||
$sth = WebGUI::SQL->read("select pageId from page where parentId=$_[0]");
|
||||
_changeWobjectPrivileges($_[0]) unless $session{form}{wobjectPrivileges};
|
||||
while (($pageId) = $sth->array) {
|
||||
if (WebGUI::Privilege::canEditPage($pageId)) {
|
||||
WebGUI::SQL->write("update page set startDate=".WebGUI::FormProcessor::dateTime("startDate").",
|
||||
endDate=".WebGUI::FormProcessor::dateTime("endDate").",
|
||||
ownerId=$session{form}{ownerId}, groupIdView=$session{form}{groupIdView},
|
||||
groupIdEdit=$session{form}{groupIdEdit}, wobjectPrivileges=$session{form}{wobjectPrivileges} where pageId=$pageId");
|
||||
_recursivelyChangePrivileges($pageId);
|
||||
}
|
||||
}
|
||||
$sth->finish;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _recursivelyChangeStyle {
|
||||
my ($sth, $pageId);
|
||||
$sth = WebGUI::SQL->read("select pageId from page where parentId=$_[0]");
|
||||
while (($pageId) = $sth->array) {
|
||||
if (WebGUI::Privilege::canEditPage($pageId)) {
|
||||
WebGUI::SQL->write("update page set styleId=$session{form}{styleId}, printableStyleId=$session{form}{printableStyleId} where pageId=$pageId");
|
||||
_recursivelyChangeStyle($pageId);
|
||||
# This combines _recusivelyChangePrivileges and _recusivelyChangeStyle, since there's no use in walking down a tree twice.
|
||||
sub _recursivelyChangeProperties {
|
||||
my $page = shift;
|
||||
|
||||
_changeWobjectPrivileges($page->get("pageId")) unless $session{form}{wobjectPrivileges};
|
||||
|
||||
$page->walk_down({
|
||||
callback => sub {
|
||||
if (WebGUI::Privilege::canEditPage($_[0]->get('pageId'))) {
|
||||
$_[0]->setWithoutRecache({
|
||||
startDate => WebGUI::FormProcessor::dateTime("startDate"),
|
||||
endDate => WebGUI::FormProcessor::dateTime("endDate"),
|
||||
ownerId => $session{form}{ownerId},
|
||||
groupIdView => $session{form}{groupIdView},
|
||||
groupIdEdit => $session{form}{groupIdEdit}
|
||||
}) if ($session{form}{recursePrivs});
|
||||
$_[0]->setWithoutRecache({
|
||||
styleId => $session{form}{styleId}
|
||||
}) if ($session{form}{recurseStyle});
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
$sth->finish;
|
||||
});
|
||||
|
||||
WebGUI::Page->recachePageTree;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
sub _reorderPages {
|
||||
my ($sth, $i, $pid);
|
||||
$sth = WebGUI::SQL->read("select pageId from page where parentId=$_[0] order by sequenceNumber");
|
||||
|
|
@ -192,16 +190,13 @@ sub _traversePageTree {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_cutPage {
|
||||
my ($page);
|
||||
if ($session{page}{pageId} < 26 && $session{page}{pageId} >= 0) {
|
||||
return WebGUI::Privilege::vitalComponent();
|
||||
|
||||
} elsif (WebGUI::Privilege::canEditPage()) {
|
||||
WebGUI::SQL->write("update page set parentId=2, "
|
||||
."bufferUserId=".$session{user}{userId}.", "
|
||||
."bufferDate=".time().", "
|
||||
."bufferPrevId=".$session{page}{parentId}." "
|
||||
."where pageId=".$session{page}{pageId});
|
||||
_reorderPages($session{page}{parentId});
|
||||
WebGUI::Session::refreshPageInfo($session{page}{parentId});
|
||||
$page = WebGUI::Page->getPage($session{page}{pageId});
|
||||
$page->cut;
|
||||
return "";
|
||||
} else {
|
||||
return WebGUI::Privilege::insufficient();
|
||||
|
|
@ -484,51 +479,54 @@ sub www_editPage {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_editPageSave {
|
||||
my ($nextSeq, $pageId);
|
||||
my ($pageId, $currentPage, $page);
|
||||
|
||||
if ($session{form}{pageId} eq "new") {
|
||||
$pageId = $session{form}{parentId};
|
||||
} else {
|
||||
$page = WebGUI::Page->getPage($session{form}{pageId});
|
||||
$pageId = $session{form}{pageId};
|
||||
}
|
||||
return WebGUI::Privilege::insufficient() unless (WebGUI::Privilege::canEditPage($pageId));
|
||||
|
||||
return WebGUI::Privilege::insufficient() unless (WebGUI::Privilege::canEditPage($pageId));
|
||||
|
||||
if ($session{form}{pageId} eq "new") {
|
||||
($nextSeq) = WebGUI::SQL->quickArray("select max(sequenceNumber) from page where parentId=$session{form}{parentId}");
|
||||
$nextSeq++;
|
||||
$session{form}{pageId} = getNextId("pageId");
|
||||
WebGUI::SQL->write("insert into page (pageId,sequenceNumber,parentId)
|
||||
values ($session{form}{pageId},$nextSeq,$session{form}{parentId})");
|
||||
$currentPage = WebGUI::Page->getPage($session{page}{pageId});
|
||||
$page = $currentPage->add;
|
||||
}
|
||||
|
||||
$session{form}{title} = "no title" if ($session{form}{title} eq "");
|
||||
$session{form}{menuTitle} = $session{form}{title} if ($session{form}{menuTitle} eq "");
|
||||
$session{form}{urlizedTitle} = $session{form}{menuTitle} if ($session{form}{urlizedTitle} eq "");
|
||||
$session{form}{urlizedTitle} = WebGUI::Page::makeUnique(WebGUI::URL::urlize($session{form}{urlizedTitle}),$session{form}{pageId});
|
||||
WebGUI::SQL->write("update page set
|
||||
title=".quote($session{form}{title}).",
|
||||
styleId=$session{form}{styleId},
|
||||
printableStyleId=$session{form}{printableStyleId},
|
||||
ownerId=$session{form}{ownerId},
|
||||
groupIdView=$session{form}{groupIdView},
|
||||
groupIdEdit=$session{form}{groupIdEdit},
|
||||
newWindow=$session{form}{newWindow},
|
||||
wobjectPrivileges=$session{form}{wobjectPrivileges},
|
||||
hideFromNavigation=$session{form}{hideFromNavigation},
|
||||
startDate=".WebGUI::FormProcessor::dateTime("startDate").",
|
||||
endDate=".WebGUI::FormProcessor::dateTime("endDate").",
|
||||
cacheTimeout=".WebGUI::FormProcessor::interval("cacheTimeout").",
|
||||
cacheTimeoutVisitor=".WebGUI::FormProcessor::interval("cacheTimeoutVisitor").",
|
||||
metaTags=".quote($session{form}{metaTags}).",
|
||||
urlizedTitle='$session{form}{urlizedTitle}',
|
||||
redirectURL='$session{form}{redirectURL}',
|
||||
languageId='$session{form}{languageId}',
|
||||
defaultMetaTags='$session{form}{defaultMetaTags}',
|
||||
templateId='$session{form}{templateId}',
|
||||
menuTitle=".quote($session{form}{menuTitle}).",
|
||||
synopsis=".quote($session{form}{synopsis})."
|
||||
where pageId=$session{form}{pageId}");
|
||||
WebGUI::SQL->write("update wobject set templatePosition=1 where pageId=$session{form}{pageId}
|
||||
and templatePosition>".WebGUI::Page::countTemplatePositions($session{form}{templateId}));
|
||||
_recursivelyChangeStyle($session{form}{pageId}) if ($session{form}{recurseStyle});
|
||||
_recursivelyChangePrivileges($session{form}{pageId}) if ($session{form}{recursePrivs});
|
||||
$page->set({
|
||||
title => $session{form}{title},
|
||||
styleId => $session{form}{styleId},
|
||||
printableStyleId => $session{form}{printableStyleId},
|
||||
ownerId => $session{form}{ownerId},
|
||||
groupIdView => $session{form}{groupIdView},
|
||||
groupIdEdit => $session{form}{groupIdEdit},
|
||||
newWindow => $session{form}{newWindow},
|
||||
wobjectPrivileges => $session{form}{wobjectPrivileges},
|
||||
hideFromNavigation => $session{form}{hideFromNavigation},
|
||||
startDate => WebGUI::FormProcessor::dateTime("startDate"),
|
||||
endDate => WebGUI::FormProcessor::dateTime("endDate"),
|
||||
cacheTimeout => WebGUI::FormProcessor::interval("cacheTimeout"),
|
||||
cacheTimeoutVisitor => WebGUI::FormProcessor::interval("cacheTimeoutVisitor"),
|
||||
metaTags => $session{form}{metaTags},
|
||||
urlizedTitle => $session{form}{urlizedTitle},
|
||||
redirectURL => $session{form}{redirectURL},
|
||||
languageId => $session{form}{languageId},
|
||||
defaultMetaTags => $session{form}{defaultMetaTags},
|
||||
templateId => $session{form}{templateId},
|
||||
menuTitle => $session{form}{menuTitle},
|
||||
synopsis => $session{form}{synopsis}
|
||||
});
|
||||
unless ($session{form}{pageId} == 'new') {
|
||||
WebGUI::SQL->write("update wobject set templatePosition=1 where pageId=$session{form}{pageId}
|
||||
and templatePosition>".WebGUI::Page::countTemplatePositions($session{form}{templateId}));
|
||||
}
|
||||
_recursivelyChangeProperties($page) if ($session{form}{recursePrivs} || $session{form}{recurseStyle});
|
||||
if ($session{form}{proceed} eq "gotoNewPage") {
|
||||
WebGUI::Session::refreshPageInfo($session{form}{pageId});
|
||||
} elsif ($session{form}{pageId} == $session{page}{pageId}) {
|
||||
|
|
@ -599,15 +597,11 @@ sub www_moveTreePageRight {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_pastePage {
|
||||
return "" if ($session{page}{pageId} == $session{form}{pageId}); # don't let it paste to itself
|
||||
my ($output, $nextSeq);
|
||||
($nextSeq) = WebGUI::SQL->quickArray("select max(sequenceNumber) from page where parentId=$session{page}{pageId}");
|
||||
$nextSeq += 1;
|
||||
my ($currentPage, $pageToPaste);
|
||||
if (WebGUI::Privilege::canEditPage()) {
|
||||
WebGUI::SQL->write("update page set parentId=$session{page}{pageId}, sequenceNumber='$nextSeq', "
|
||||
."bufferUserId=NULL, bufferDate=NULL, bufferPrevId=NULL "
|
||||
."where pageId=$session{form}{pageId}");
|
||||
_reorderPages($session{page}{pageId});
|
||||
$currentPage = WebGUI::Page->getPage($session{page}{pageId});
|
||||
$pageToPaste = WebGUI::Page->getPage($session{form}{pageId});
|
||||
$pageToPaste->paste($currentPage);
|
||||
return "";
|
||||
} else {
|
||||
return WebGUI::Privilege::insufficient();
|
||||
|
|
@ -624,4 +618,3 @@ sub www_viewPageTree {
|
|||
}
|
||||
|
||||
1;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ use WebGUI::Session;
|
|||
use WebGUI::SQL;
|
||||
use WebGUI::Template;
|
||||
use WebGUI::Utility;
|
||||
use WebGUI::DateTime;
|
||||
use Data::Serializer;
|
||||
|
||||
our @ISA = qw(WebGUI::Persistent::Tree);
|
||||
|
||||
|
|
@ -35,10 +37,15 @@ Package WebGUI::Page
|
|||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This package provides utility functions for WebGUI's page system.
|
||||
This package provides utility functions for WebGUI's page system. Some of these work in a
|
||||
non-object oriented fashion. These are utility functions, not affecting the page tree hiearchy.
|
||||
|
||||
The methods that do affect this hiearchy should be called in a object oriented context.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Non OO functions
|
||||
|
||||
use WebGUI::Page;
|
||||
$integer = WebGUI::Page::countTemplatePositions($templateId);
|
||||
$html = WebGUI::Page::drawTemplate($templateId);
|
||||
|
|
@ -48,6 +55,20 @@ This package provides utility functions for WebGUI's page system.
|
|||
$hashRef = WebGUI::Page::getTemplatePositions($templateId);
|
||||
$url = WebGUI::Page::makeUnique($url,$pageId);
|
||||
|
||||
|
||||
OO style methods
|
||||
|
||||
use WebGUI::Page;
|
||||
$page = WebGUI::Page->getPage($pageId);
|
||||
$newMother = WebGUI::Page->getPage($anotherPageId);
|
||||
$page->cut;
|
||||
$page->paste($newMother);
|
||||
|
||||
$page->set; # this automatically recaches the pagetree
|
||||
|
||||
$page->setWithoutRecache;
|
||||
WebGUI::Page->recachePageTree # here we've got to recache manually
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These functions are available from this package:
|
||||
|
|
@ -57,36 +78,82 @@ These functions are available from this package:
|
|||
#-------------------------------------------------------------------
|
||||
|
||||
sub classSettings {
|
||||
return {
|
||||
properties => {
|
||||
pageId => { key => 1 },
|
||||
parentId => { defaultValue => 0 },
|
||||
title => { quote => 1 },
|
||||
styleId => { defaultValue => 0 },
|
||||
ownerId => { defaultValue => 0 },
|
||||
sequenceNumber => { defaultValue => 1 },
|
||||
metaTags => { quote => 1 },
|
||||
urlizedTitle => { quote => 1 },
|
||||
defaultMetaTags => { defaultValue => 0 },
|
||||
menuTitle => { quote => 1 },
|
||||
synopsis => { quote => 1 },
|
||||
templateId => { defaultValue => 1 },
|
||||
startDate => { defaultValue => 946710000 },
|
||||
endDate => { defaultValue => 2082783600 },
|
||||
redirectURL => { quote => 1 },
|
||||
userDefined1 => { quote => 1 },
|
||||
userDefined2 => { quote => 1 },
|
||||
userDefined3 => { quote => 1 },
|
||||
userDefined4 => { quote => 1 },
|
||||
userDefined5 => { quote => 1 },
|
||||
languageId => { defaultValue => 1 },
|
||||
groupIdView => { defaultValue => 3 },
|
||||
groupIdEdit => { defaultValue => 3 },
|
||||
hideFromNavigation => { defaultValue => 0 },
|
||||
},
|
||||
useDummyRoot => 1,
|
||||
table => 'page'
|
||||
}
|
||||
return {
|
||||
properties => {
|
||||
# These fields define the place in the pagetree of a page
|
||||
pageId => { key => 1 },
|
||||
parentId => { defaultValue => 0 },
|
||||
sequenceNumber => { defaultValue => 1 },
|
||||
|
||||
# These are the entries that define the privileges and behaviour of a page.
|
||||
# They're in the same order as they apear in the set-statement in the www_editPageSave method
|
||||
# of WebGUI::Operation::Page. Please keep them in this order. You will find it to be more
|
||||
# convient when debugging.
|
||||
title => { quote => 1 },
|
||||
styleId => { defaultValue => 0 },
|
||||
printableStyleId => { defaultValue => 0 },
|
||||
ownerId => { defaultValue => 0 },
|
||||
groupIdView => { defaultValue => 3 },
|
||||
groupIdEdit => { defaultValue => 3 },
|
||||
newWindow => { defaultValue => 0 },
|
||||
wobjectPrivileges => { defaultValue => 0 },
|
||||
hideFromNavigation => { defaultValue => 0 },
|
||||
startDate => { defaultValue => 946710000 },
|
||||
endDate => { defaultValue => 2082783600 },
|
||||
cacheTimeout => { defaultValue => 60},
|
||||
cacheTimeoutVisitor => { defaultValue => 600},
|
||||
metaTags => { quote => 1 },
|
||||
urlizedTitle => { quote => 1 },
|
||||
redirectURL => { quote => 1 },
|
||||
languageId => { defaultValue => 1 },
|
||||
defaultMetaTags => { defaultValue => 0 },
|
||||
templateId => { defaultValue => 1 },
|
||||
menuTitle => { quote => 1 },
|
||||
synopsis => { quote => 1 },
|
||||
|
||||
# The userdefined database entries.
|
||||
userDefined1 => { quote => 1 },
|
||||
userDefined2 => { quote => 1 },
|
||||
userDefined3 => { quote => 1 },
|
||||
userDefined4 => { quote => 1 },
|
||||
userDefined5 => { quote => 1 }
|
||||
},
|
||||
useDummyRoot => 1,
|
||||
table => 'page'
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
=head2 add ( page )
|
||||
|
||||
Adds page to the children of the object this method is invoked on.
|
||||
|
||||
=over
|
||||
|
||||
=item page
|
||||
|
||||
A WebGUI::Page instance to be added to the children of the current object.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub add {
|
||||
my ($self, $page, @daughters, $newSequenceNumber);
|
||||
($self) = @_;
|
||||
|
||||
@daughters = $self->daughters;
|
||||
$newSequenceNumber = 1;
|
||||
$newSequenceNumber = (pop(@daughters))[0]->get('sequenceNumber') + 1 if (@daughters);
|
||||
|
||||
$page = WebGUI::Page->new(-properties => {
|
||||
parentId => $self->get("pageId"),
|
||||
sequenceNumber => $newSequenceNumber
|
||||
});
|
||||
$self->add_daughter($page);
|
||||
$page->set;
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -116,10 +183,38 @@ sub countTemplatePositions {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
=head2 cut
|
||||
|
||||
Cuts the this Page object and places it on the clipboard.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
sub cut {
|
||||
my ($self, $clipboard, $parentId);
|
||||
$self = shift;
|
||||
$parentId = $self->get("parentId");
|
||||
|
||||
# Place page in clipboard (pageId 2)
|
||||
$clipboard = WebGUI::Page->getPage(2);
|
||||
$self->get("pageId");
|
||||
|
||||
if ($self->move($clipboard)) {
|
||||
$self->set({
|
||||
bufferUserId => $session{user}{userId},
|
||||
bufferDate => time,
|
||||
bufferPrevId => $parentId,
|
||||
});
|
||||
}
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
=head2 deCache ( [ pageId ] )
|
||||
|
||||
Deletes the cached version of a specified page.
|
||||
Deletes the cached version of a specified page. Note that this is something else than the
|
||||
cached page tree. This funtion should be invoked in a non-OO context;
|
||||
|
||||
=over
|
||||
|
||||
|
|
@ -138,7 +233,6 @@ sub deCache {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 drawTemplate ( templateId )
|
||||
|
||||
Returns an HTML string containing a small representation of the page template.
|
||||
|
|
@ -243,7 +337,6 @@ sub generate {
|
|||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getTemplateList
|
||||
|
||||
Returns a hash reference containing template ids and template titles for all the page templates available in the system.
|
||||
|
|
@ -255,7 +348,6 @@ sub getTemplateList {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getTemplate ( [ templateId ] )
|
||||
|
||||
Returns an HTML template.
|
||||
|
|
@ -276,7 +368,6 @@ sub getTemplate {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getTemplatePositions ( templateId )
|
||||
|
||||
Returns a hash reference containing the positions available in the specified page template.
|
||||
|
|
@ -301,7 +392,6 @@ sub getTemplatePositions {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 makeUnique ( pageURL, pageId )
|
||||
|
||||
Returns a unique page URL.
|
||||
|
|
@ -334,5 +424,246 @@ sub makeUnique {
|
|||
return $url;
|
||||
}
|
||||
|
||||
1;
|
||||
#-------------------------------------------------------------------
|
||||
=head2 getPage ( [pageId] )
|
||||
|
||||
This method fetches a WebGUI::Page object. If no pageId is given the current page will be used.
|
||||
|
||||
=over
|
||||
|
||||
=item pageId
|
||||
|
||||
The id of the page requested.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
sub getPage {
|
||||
my ($serializer, $cache, $pageLookup, $node, $self, $class, $pageId, $tree);
|
||||
($class, $pageId) = @_;
|
||||
$pageId ||= $session{page}{pageId};
|
||||
|
||||
WebGUI::ErrorHandler::fatalError("Illegal pageId: '$pageId'") unless ($pageId =~ /^-?\d+$/);
|
||||
|
||||
# Only fetch from cache if cache is enabled in the config file
|
||||
if ($session{config}{usePageCache}) {
|
||||
# Fetch the correct pagetree from cache
|
||||
$cache = WebGUI::Cache->new('pageLookup', 'PageTree-'.$session{config}{configFile});
|
||||
$pageLookup = $cache->getDataStructure;
|
||||
$cache = WebGUI::Cache->new('root-'.$pageLookup->{$pageId},'PageTree-'.$session{config}{configFile});
|
||||
$tree = $cache->getDataStructure;
|
||||
|
||||
unless (defined $tree) {
|
||||
#Handle cache miss. The way it's done here costs twice the amount of time that's needed to build
|
||||
#a tree. This shouldn't matter that much, though, since cache-misses should occur almost never.
|
||||
WebGUI::Page->recachePageTree;
|
||||
$tree = WebGUI::Page->getTree()->{0};
|
||||
}
|
||||
# No caching
|
||||
} else {
|
||||
# Do it the diehard way. Just build a complete tree from the database. This will most definately work, but
|
||||
# not too fast. A more elegant aproach would be overlaoding every Tree::DAG_Node method WebGUI::Page inherits
|
||||
# and dynamically load the data from the db.
|
||||
$tree = WebGUI::Page->getTree()->{0};
|
||||
|
||||
# Caching the tree in the session hash might be a good idea, to reduce tree building to only once per session.
|
||||
# $session{page}{tree} = $tree;
|
||||
}
|
||||
|
||||
# Select the correct node from the tree
|
||||
$tree->walk_down({
|
||||
callback => sub {
|
||||
if ($_[0]->get('pageId') == $pageId) {
|
||||
$node = $_[0];
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}});
|
||||
return $node;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
=head2 move( newMother )
|
||||
|
||||
Moves a page to another page (ie. makes the page you execute this method on a child of newMother).
|
||||
Returns 1 if the move was succesfull, 0 otherwise.
|
||||
|
||||
=over
|
||||
|
||||
=item newMother
|
||||
|
||||
The page under which the current page should be moved. This should be an WebGUI::Page object.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
sub move{
|
||||
my ($self, $clipboard, $parentId, $newSequenceNumber, @newSisters, $newMother);
|
||||
$self = shift;
|
||||
$newMother = shift;
|
||||
|
||||
# Avoid cyclic pages. Not doing this will allow people to freeze your computer, by generating infinite loops.
|
||||
return 0 if (isIn($self->get("pageId"), map {$_->get("pageId")} $newMother->ancestors));
|
||||
|
||||
# Make sure a page is not moved to itself.
|
||||
return 0 if ($self->get("pageId") == $newMother->get("pageId"));
|
||||
|
||||
$parentId = $self->get("parentId");
|
||||
|
||||
# Lower the sequence numbers of the following sisters
|
||||
foreach ($self->right_sisters) {
|
||||
$_->setWithoutRecache({
|
||||
sequenceNumber => $_->get('sequenceNumber') - 1
|
||||
});
|
||||
}
|
||||
|
||||
# Derive new sequenceNumber
|
||||
@newSisters = $newMother->daughters;
|
||||
$newSequenceNumber = 1;
|
||||
$newSequenceNumber = $newSisters[scalar(@newSisters)-1]->get('sequenceNumber') +1 if (@newSisters);
|
||||
|
||||
# Do the move
|
||||
$self->unlink_from_mother;
|
||||
$newMother->add_daughter($self);
|
||||
$self->set({
|
||||
parentId => $newMother->get("pageId"),
|
||||
sequenceNumber => $newSequenceNumber,
|
||||
});
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
=head2 paste( newMother )
|
||||
|
||||
Pastes a page under newMother.
|
||||
|
||||
=over
|
||||
|
||||
=item newMother
|
||||
|
||||
The page under which the current page should be pasted. This should be an WebGUI::Page object.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
sub paste{
|
||||
my ($self, $newMother);
|
||||
$self = shift;
|
||||
$newMother = shift;
|
||||
return $self if ($self->get("pageId") == $newMother->get("pageId"));
|
||||
return WebGUI::ErrorHandler::fatalError("You cannot paste a page that's not on the clipboard.") unless ($self->get("parentId") == 2);
|
||||
|
||||
# Place page in clipboard (pageId 2)
|
||||
if ($self->move($newMother)) {
|
||||
$self->set({
|
||||
bufferUserId => 'NULL',
|
||||
bufferDate => 'NULL',
|
||||
bufferPrevId => 'NULL'
|
||||
});
|
||||
}
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
=head2 recachePageTree
|
||||
|
||||
This method fetches all pageroots from the database, builds their underlying trees and caches them. Additionally
|
||||
this method creates a lookup table that connects a node to a root. This is done to avoid searching through all
|
||||
page tree to find a specific node.
|
||||
|
||||
It should only be nescesarry to call this method when setWithoutRecache is used.
|
||||
|
||||
=cut
|
||||
sub recachePageTree {
|
||||
my ($forrest, @pageRoots, $currentTree, $serializer, $node, $serialized, $cache, %pageLookup);
|
||||
|
||||
# Purge the cached page trees.
|
||||
$cache = WebGUI::Cache->new("", "PageTree-".$session{config}{configFile});
|
||||
$cache->deleteByRegex(".*");
|
||||
|
||||
# Fetch the complete forrest, which is actually all the pagetrees connected by a dummy root.
|
||||
$forrest = WebGUI::Page->getTree();
|
||||
|
||||
@pageRoots = $forrest->{0}->daughters;
|
||||
$serializer = Data::Serializer->new(serializer => 'Storable');
|
||||
|
||||
foreach $currentTree (@pageRoots) {
|
||||
# Disconnect the tree from the dummy root.
|
||||
$currentTree->unlink_from_mother;
|
||||
|
||||
# Cache forrest per tree.
|
||||
$cache = WebGUI::Cache->new('root-'.$currentTree->get('pageId'),'PageTree-'.$session{config}{configFile});
|
||||
$cache->setDataStructure($currentTree);
|
||||
|
||||
# Create URL lookup table.
|
||||
$currentTree->walk_down({
|
||||
callback => sub {
|
||||
$_[1]->{_pageLookup}->{$_[0]->get('pageId')} = $_[1]->{_root};
|
||||
return 1;
|
||||
},
|
||||
_root => $currentTree->get('pageId'),
|
||||
_pageLookup => \%pageLookup
|
||||
});
|
||||
}
|
||||
|
||||
# Put the lookup table into cache
|
||||
$cache = WebGUI::Cache->new('pageLookup','PageTree-'.$session{config}{configFile});
|
||||
$cache->setDataStructure(\%pageLookup);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
=head2 set ( [ data ] )
|
||||
|
||||
If data is given, invoking this method will set the object to the state given in data. If called without any arguments
|
||||
the state of the tree is saved to the database.
|
||||
|
||||
A thing to note here is that the cached version of the pagetree is always refreshed after saving to the database. Refreshing
|
||||
the cache is pretty expensive, so if you have to do many sets in a row, like when recursively changing style of a (sub)tree,
|
||||
it would be best to use setWithoutRecache, and call recachePageTree afterwards.
|
||||
|
||||
=over
|
||||
|
||||
=item data
|
||||
|
||||
The properties you want to set. This parameter is optional and should be a hashref of the form {propertyA => valueA, propertyB => valueB, etc...}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
sub set {
|
||||
my $self = shift;
|
||||
my $output = $self->SUPER::set(@_);
|
||||
|
||||
# The very only reason we overload the set method is to make sure that the cache also gets
|
||||
# updated. So let's do just that ;). This might be overkill for some situations where only
|
||||
# one tree needs to be updated, but doing all of them, sure is a lot safer. (and easier!)
|
||||
recachePageTree();
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
=head2 setWithoutRecache ([data])
|
||||
|
||||
See set. The only difference with set is that the cached version of the pagetree is not updated. This means that you must
|
||||
update it manually by invoking recachePageTree afterwards.
|
||||
|
||||
=over
|
||||
|
||||
=item data
|
||||
|
||||
The properties you want to set. This parameter is optional and should be a hashref of the form {propertyA => valueA, propertyB => valueB, etc...}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
sub setWithoutRecache {
|
||||
my $self = shift;
|
||||
return $self->SUPER::set(@_);
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue