Merge commit 'v7.10.15' into 8
Conflicts: docs/gotcha.txt docs/previousVersion.sql docs/templates.txt lib/WebGUI.pm lib/WebGUI/Asset.pm lib/WebGUI/Asset/Event.pm lib/WebGUI/Asset/File.pm lib/WebGUI/Asset/MapPoint.pm lib/WebGUI/Asset/RichEdit.pm lib/WebGUI/Asset/Sku/Product.pm lib/WebGUI/Asset/Snippet.pm lib/WebGUI/Asset/Story.pm lib/WebGUI/Asset/Template.pm lib/WebGUI/Asset/Template/TemplateToolkit.pm lib/WebGUI/Asset/Wobject/Calendar.pm lib/WebGUI/Asset/Wobject/Carousel.pm lib/WebGUI/Asset/Wobject/Collaboration.pm lib/WebGUI/Asset/Wobject/Dashboard.pm lib/WebGUI/Asset/Wobject/DataForm.pm lib/WebGUI/Asset/Wobject/Folder.pm lib/WebGUI/Asset/Wobject/Map.pm lib/WebGUI/Asset/Wobject/Search.pm lib/WebGUI/Asset/Wobject/Shelf.pm lib/WebGUI/Asset/Wobject/StockData.pm lib/WebGUI/Asset/Wobject/StoryTopic.pm lib/WebGUI/Asset/Wobject/SyndicatedContent.pm lib/WebGUI/Asset/Wobject/Thingy.pm lib/WebGUI/Asset/Wobject/WeatherData.pm lib/WebGUI/AssetClipboard.pm lib/WebGUI/AssetCollateral/DataForm/Entry.pm lib/WebGUI/AssetExportHtml.pm lib/WebGUI/AssetLineage.pm lib/WebGUI/AssetMetaData.pm lib/WebGUI/AssetTrash.pm lib/WebGUI/AssetVersioning.pm lib/WebGUI/Auth.pm lib/WebGUI/Cache/CHI.pm lib/WebGUI/Content/AssetManager.pm lib/WebGUI/Fork/ProgressBar.pm lib/WebGUI/Form/JsonTable.pm lib/WebGUI/Form/TimeField.pm lib/WebGUI/Form/Zipcode.pm lib/WebGUI/Group.pm lib/WebGUI/International.pm lib/WebGUI/Macro/AssetProxy.pm lib/WebGUI/Macro/FileUrl.pm lib/WebGUI/Operation/SSO.pm lib/WebGUI/Operation/User.pm lib/WebGUI/Role/Asset/Subscribable.pm lib/WebGUI/Shop/Cart.pm lib/WebGUI/Shop/Transaction.pm lib/WebGUI/Shop/TransactionItem.pm lib/WebGUI/Test.pm lib/WebGUI/URL/Content.pm lib/WebGUI/URL/Uploads.pm lib/WebGUI/User.pm lib/WebGUI/Workflow/Activity/ExtendCalendarRecurrences.pm lib/WebGUI/Workflow/Activity/SendNewsletters.pm lib/WebGUI/i18n/English/Asset.pm lib/WebGUI/i18n/English/WebGUI.pm sbin/installClass.pl sbin/rebuildLineage.pl sbin/search.pl sbin/testEnvironment.pl t/Asset/Asset.t t/Asset/AssetClipboard.t t/Asset/AssetLineage.t t/Asset/AssetMetaData.t t/Asset/Event.t t/Asset/File.t t/Asset/File/Image.t t/Asset/Post/notification.t t/Asset/Sku.t t/Asset/Story.t t/Asset/Template.t t/Asset/Wobject/Collaboration/templateVariables.t t/Asset/Wobject/Collaboration/unarchiveAll.t t/Asset/Wobject/Shelf.t t/Auth.t t/Macro/EditableToggle.t t/Macro/FilePump.t t/Shop/Cart.t t/Shop/Transaction.t t/Storage.t t/User.t t/Workflow.t
This commit is contained in:
commit
277faae8a1
783 changed files with 32041 additions and 25495 deletions
|
|
@ -188,7 +188,7 @@ sub www_editFriends {
|
|||
my @manageableUsers = ();
|
||||
if ($groupName) { # Only adding users from a single group
|
||||
my $group = WebGUI::Group->find($session, $groupName);
|
||||
push @manageableUsers, @{ $group->getUsersNotIn($user->{_user}->{'friendsGroup'}, 'withoutExpired') };
|
||||
push @manageableUsers, @{ $group->getUsersNotIn($user->friends->getId, 'withoutExpired') };
|
||||
}
|
||||
else { # Defaults to groups selected in settings
|
||||
my $groupIds = $session->setting->get('groupsToManageFriends');
|
||||
|
|
@ -196,7 +196,7 @@ sub www_editFriends {
|
|||
foreach my $groupId (@groupIds) {
|
||||
my $group = WebGUI::Group->new($session, $groupId);
|
||||
next GROUP unless $group->getId || $group->getId eq 'new';
|
||||
push @manageableUsers, @{ $group->getUsersNotIn($user->{_user}->{'friendsGroup'}, 'withoutExpired') };
|
||||
push @manageableUsers, @{ $group->getUsersNotIn($user->friends->getId, 'withoutExpired') };
|
||||
}
|
||||
@manageableUsers = uniq @manageableUsers;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ property extraHeadTags => (
|
|||
around extraHeadTags => sub {
|
||||
my $orig = shift;
|
||||
my $self = shift;
|
||||
if (@_ > 1) {
|
||||
if (@_ > 0) {
|
||||
my $unpacked = $_[0];
|
||||
my $packed = $unpacked; ##Undo magic aliasing since a reference is passed below
|
||||
HTML::Packer::minify( \$packed, {
|
||||
|
|
@ -1709,6 +1709,19 @@ sub getViewCacheKey {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getContentLastModifiedBy ( )
|
||||
|
||||
Returns the userId that modified the content last.
|
||||
|
||||
=cut
|
||||
|
||||
sub getContentLastModifiedBy {
|
||||
my $self = shift;
|
||||
return $self->get("revisedBy");
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getWwwCacheKey ( )
|
||||
|
||||
Returns a cache object specific to this asset, and whether or not the request is in SSL mode.
|
||||
|
|
@ -2387,7 +2400,7 @@ sub publish {
|
|||
|
||||
$self->session->db->write("update asset set state='published', stateChangedBy=".$self->session->db->quote($self->session->user->userId).", stateChanged=".time()." where assetId in (".$idList.")");
|
||||
foreach my $id (@{$assetIds}) {
|
||||
my $asset = WebGUI::Asset->newById($self->session, $id);
|
||||
my $asset = WebGUI::Asset->newPending($self->session, $id);
|
||||
if (defined $asset) {
|
||||
$asset->purgeCache;
|
||||
}
|
||||
|
|
@ -2425,6 +2438,21 @@ sub purgeCache {
|
|||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 refused ( )
|
||||
|
||||
Returns an error message to the user, wrapped in the user's style. This is most useful for
|
||||
handling UI errors. Privilege errors should be still be sent to $session->privilege.
|
||||
|
||||
=cut
|
||||
|
||||
sub refused {
|
||||
my ($self) = @_;
|
||||
return $self->{_session};
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 session ( )
|
||||
|
|
@ -2683,10 +2711,10 @@ sub www_addSave {
|
|||
my ( $form ) = $session->quick(qw{ form });
|
||||
|
||||
return $session->privilege->insufficient() unless $self->canEdit;
|
||||
if ($self->session->config("maximumAssets")) {
|
||||
if ($self->session->config->get("maximumAssets")) {
|
||||
my ($count) = $self->session->db->quickArray("select count(*) from asset");
|
||||
my $i18n = WebGUI::International->new($self->session, "Asset");
|
||||
return $self->session->style->userStyle($i18n->get("over max assets")) if ($self->session->config("maximumAssets") <= $count);
|
||||
return $self->session->style->userStyle($i18n->get("over max assets")) if ($self->session->config->get("maximumAssets") <= $count);
|
||||
}
|
||||
|
||||
# Determine what version tag we should use
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ use WebGUI::Storage;
|
|||
use Test::Deep::NoTest qw(eq_deeply);
|
||||
use DateTime::Event::ICal;
|
||||
use DateTime::Set;
|
||||
use Data::ICal::Entry::Event;
|
||||
|
||||
use Moose;
|
||||
use WebGUI::Definition::Asset;
|
||||
|
|
@ -212,6 +213,54 @@ override addRevision => sub {
|
|||
return $newRev;
|
||||
};
|
||||
|
||||
####################################################################
|
||||
|
||||
=head2 add_to_calendar ($iCal)
|
||||
|
||||
Build a Data::ICal::Entry::Event object that contains the information for this
|
||||
event and add it to the Data::ICal calendar
|
||||
|
||||
=head3 $iCal
|
||||
|
||||
A Data::ICal object, representing the top-level calendar instance.
|
||||
|
||||
=cut
|
||||
|
||||
sub add_to_calendar {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $calendar = shift;
|
||||
my $event = Data::ICal::Entry::Event->new();
|
||||
$event->add_properties(
|
||||
'last-modified' => WebGUI::DateTime->new($session, $event->get("revisionDate"))->toIcal,
|
||||
created => WebGUI::DateTime->new($session, $event->get("creationDate"))->toIcal,
|
||||
sequence => $self->get('iCalSequenceNumber'),
|
||||
summary => $self->get('title'),
|
||||
description => $self->get('description'),
|
||||
location => $self->get('location'),
|
||||
uid => $self->get('feedUid')
|
||||
? $self->get('feedUid')
|
||||
: $self->get('assetId') . '@'. $session->config->get("sitename")->[0],
|
||||
);
|
||||
##WebGUI Specific fields
|
||||
foreach my $prop (qw/groupIdView groupIdEdit url menuTitle timeZone/) {
|
||||
$event->add_property( 'x-webgui-'.lc($prop) => $self->get($prop));
|
||||
}
|
||||
my $eventStart = $self->getIcalStart;
|
||||
my $start_parameters = {};
|
||||
if (! $eventStart =~ /T/) {
|
||||
$start_parameters->{VALUE} = 'DATE';
|
||||
}
|
||||
$event->add_property(dtstart => [ $eventStart, $start_parameters ]);
|
||||
my $eventEnd = $self->getIcalEnd;
|
||||
my $end_parameters = {};
|
||||
if (! $eventEnd =~ /T/) {
|
||||
$end_parameters->{VALUE} = 'DATE';
|
||||
}
|
||||
$event->add_property(dtend => [ $eventEnd, $end_parameters ]);
|
||||
$calendar->add_entry($event);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
my %dayNamesToICal = (
|
||||
|
|
@ -411,6 +460,14 @@ sub duplicate {
|
|||
my $newAsset = $self->SUPER::duplicate(@_);
|
||||
my $newStorage = $self->getStorageLocation->copy;
|
||||
$newAsset->update({storageId=>$newStorage->getId});
|
||||
my $links = $self->getRelatedLinks();
|
||||
my $id = $self->session->id;
|
||||
foreach my $link (@{ $links }) {
|
||||
$link->{new_event} = 1;
|
||||
$link->{eventlinkId} = $id->generate;
|
||||
$link->{linkurl} = $link->{linkURL};
|
||||
}
|
||||
$newAsset->setRelatedLinks($links);
|
||||
return $newAsset;
|
||||
}
|
||||
|
||||
|
|
@ -434,13 +491,12 @@ sub generateRecurrence {
|
|||
WHERE recurId = ? AND startDate = ?
|
||||
};
|
||||
my $db = $self->session->db;
|
||||
unless ($db->quickScalar($sql, [$self->recurId, $sdb])) {
|
||||
my $child = $self->get;
|
||||
$child->{startDate} = $sdb;
|
||||
$child->{endDate} = $edb;
|
||||
$self->getParent->addChild(
|
||||
$child, undef, undef, { skipAutoCommitWorkflows => 1 }
|
||||
);
|
||||
unless ($db->quickScalar($sql, [$self->get('recurId'), $sdb])) {
|
||||
my $child = $self->duplicate({skipAutoCommitWorkflows => 1});
|
||||
$child->update({
|
||||
startDate => $sdb,
|
||||
endDate => $edb,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1374,9 +1430,18 @@ override processEditForm => sub {
|
|||
|
||||
### Verify the form was filled out correctly...
|
||||
my @errors;
|
||||
# If the start date is after the end date
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Event');
|
||||
if ($self->startDate gt $self->endDate) {
|
||||
|
||||
# Verify we got valid dates
|
||||
if ( !eval{ $self->getDateTimeStart; 1 } ) {
|
||||
push @errors, $i18n->get('invalid start date');
|
||||
}
|
||||
if ( !eval{ $self->getDateTimeEnd; 1 } ) {
|
||||
push @errors, $i18n->get('invalid end date');
|
||||
}
|
||||
|
||||
# If the start date is after the end date
|
||||
if ($self->get("startDate") gt $self->get("endDate")) {
|
||||
push @errors, $i18n->get("The event end date must be after the event start date.");
|
||||
}
|
||||
|
||||
|
|
@ -1605,13 +1670,17 @@ Extent the method from the super class to delete all storage locations.
|
|||
|
||||
override purge => sub {
|
||||
my $self = shift;
|
||||
my $sth = $self->session->db->read("select storageId from Event where assetId=?",[$self->getId]);
|
||||
while (my ($storageId) = $sth->array) {
|
||||
my $storage = WebGUI::Storage->get($self->session,$storageId);
|
||||
my $id = $self->getId;
|
||||
my $session = $self->session;
|
||||
my @storageIds = $session->db->buildArray("select storageId from Event where assetId=?",[$id]);
|
||||
my $success = $self->SUPER::purge;
|
||||
return 0 unless $success;
|
||||
foreach my $storageId (@storageIds) {
|
||||
my $storage = WebGUI::Storage->get($session, $storageId);
|
||||
$storage->delete if defined $storage;
|
||||
}
|
||||
$sth->finish;
|
||||
return super();
|
||||
$session->db->write('delete from Event_relatedlink where assetId=?',[$id]);
|
||||
return 1;
|
||||
};
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -2235,20 +2304,24 @@ sub www_edit {
|
|||
# End
|
||||
$var->{"formRecurEnd"}
|
||||
= q|
|
||||
<div><input type="radio" name="recurEndType" id="recurEndType_none" value="none" |.(!$recur->{endDate} && !$recur->{endAfter} ? 'checked="checked"' : '').q|/>
|
||||
<label for="recurEndType_none">|. $i18n->get('No end'). q|</label><br />
|
||||
<div><input type="radio" name="recurEndType" id="recurEndType_none" value="none" |.(!$recur->{endDate} && !$recur->{endAfter} ? 'checked="checked"' : '').q| onclick="toggleRecurEnd()"/>
|
||||
<label for="recurEndType_none">|. $i18n->get('No end'). q|</label>
|
||||
|
||||
<input type="radio" name="recurEndType" id="recurEndType_date" value="date" |.($recur->{endDate} ? 'checked="checked"' : '' ).q| />
|
||||
<label for="recurEndType_date">|. $i18n->get('By date'). q| </label>|
|
||||
<input type="radio" name="recurEndType" id="recurEndType_date" value="date" |.($recur->{endDate} ? 'checked="checked"' : '' ).q| onclick="toggleRecurEnd()"/>
|
||||
<label for="recurEndType_date">|. $i18n->get('By date'). q| </label>
|
||||
<div id="recurEndPattern_date"> |
|
||||
. WebGUI::Form::date($session,{ name => "recurEndDate", value => $recur->{endDate}, defaultValue => $recur->{endDate} })
|
||||
. q|
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<input type="radio" name="recurEndType" id="recurEndType_after" value="after" |.($recur->{endAfter} ? 'checked="checked"' : '' ).q| />
|
||||
<input type="radio" name="recurEndType" id="recurEndType_after" value="after" |.($recur->{endAfter} ? 'checked="checked"' : '' ).q| onclick="toggleRecurEnd()"/>
|
||||
<label for="recurEndType_after">|. $i18n->get('After'). q| </label>
|
||||
<div id="recurEndPattern_after">
|
||||
<input type="text" size="3" name="recurEndAfter" value="|.$recur->{endAfter}.q|" />
|
||||
|. $i18n->get('occurences'). q|.
|
||||
</div>
|
||||
</div>
|
||||
|;
|
||||
|
||||
# Include
|
||||
|
|
@ -2310,7 +2383,19 @@ sub www_edit {
|
|||
document.getElementById("recurPattern_yearly").style.display = "block";
|
||||
}
|
||||
}
|
||||
YAHOO.util.Event.onAvailable("recurPattern",function(e) { toggleRecur(); });
|
||||
|
||||
function toggleRecurEnd() {
|
||||
document.getElementById("recurEndPattern_date").style.display = "none";
|
||||
document.getElementById("recurEndPattern_after").style.display = "none";
|
||||
|
||||
if (document.getElementById("recurEndType_date").checked) {
|
||||
document.getElementById("recurEndPattern_date").style.display = "block";
|
||||
}
|
||||
else if (document.getElementById("recurEndType_after").checked) {
|
||||
document.getElementById("recurEndPattern_after").style.display = "block";
|
||||
}
|
||||
}
|
||||
YAHOO.util.Event.onAvailable("recurPattern",function(e) { toggleRecur(); toggleRecurEnd(); });
|
||||
</script>
|
||||
ENDJS
|
||||
|
||||
|
|
|
|||
|
|
@ -133,6 +133,24 @@ sub setPrivileges {
|
|||
);
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 commit ( )
|
||||
|
||||
Override commit to remove all privileges for previous revisions' storage
|
||||
locations
|
||||
|
||||
=cut
|
||||
|
||||
sub commit {
|
||||
my ( $self, @args ) = @_;
|
||||
|
||||
for my $rev ( grep { $_->get("revisionDate") < $self->get("revisionDate") } @{$self->getRevisions} ) {
|
||||
$rev->getStorageLocation->trash;
|
||||
}
|
||||
|
||||
return $self->SUPER::commit( @args );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -401,7 +419,6 @@ override processEditForm => sub {
|
|||
return undef;
|
||||
};
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 purge
|
||||
|
|
@ -450,6 +467,20 @@ override purgeRevision => sub {
|
|||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 restore ( )
|
||||
|
||||
Override trash restore to restore storage location
|
||||
|
||||
=cut
|
||||
|
||||
sub restore {
|
||||
my ( $self, @args ) = @_;
|
||||
$self->setPrivileges;
|
||||
return $self->SUPER::restore( @args );
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 setFile ( [pathtofile] )
|
||||
|
||||
Tells the asset to do all the postprocessing on the file (setting privs, thubnails, or whatever).
|
||||
|
|
@ -535,6 +566,23 @@ sub setStorageLocation {
|
|||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 trash ( )
|
||||
|
||||
Override to put the attached file in the trash too
|
||||
|
||||
=cut
|
||||
|
||||
sub trash {
|
||||
my ( $self, @args ) = @_;
|
||||
my $return = $self->SUPER::trash( @args );
|
||||
|
||||
$self->getStorageLocation->trash;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 updatePropertiesFromStorage ( )
|
||||
|
||||
Updates the asset properties from the file tracked by this asset. Should be
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ package WebGUI::Asset::MapPoint;
|
|||
use strict;
|
||||
use Moose;
|
||||
use WebGUI::Definition::Asset;
|
||||
use Geo::Coder::Googlev3;
|
||||
|
||||
extends 'WebGUI::Asset';
|
||||
define assetName => ['assetName', 'Asset_MapPoint'];
|
||||
define icon => 'mappoint.png';
|
||||
|
|
@ -121,6 +123,12 @@ property userDefined5 => (
|
|||
fieldType => "hidden",
|
||||
noFormPost => 1,
|
||||
);
|
||||
property isGeocoded => (
|
||||
fieldType => "yesNo",
|
||||
tab => "properties",
|
||||
label => ["isGeocoded label",'Asset_MapPoint'],
|
||||
hoverHelp => ["isGeocoded description",'Asset_MapPoint'],
|
||||
);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -184,6 +192,7 @@ AT LEAST the following keys:
|
|||
title - The title of the point
|
||||
content - HTML content to show details about the point
|
||||
url - The URL of the point
|
||||
userDefined1-5 - The userDefined fields
|
||||
|
||||
The following keys are optional
|
||||
|
||||
|
|
@ -199,7 +208,7 @@ sub getMapInfo {
|
|||
# Get asset properties
|
||||
$var->{ url } = $self->getUrl;
|
||||
$var->{ assetId } = $self->getId;
|
||||
my @keys = qw( latitude longitude title );
|
||||
my @keys = qw( latitude longitude title userDefined1 userDefined2 userDefined3 userDefined4 userDefined5 isGeocoded );
|
||||
for my $key ( @keys ) {
|
||||
$var->{ $key } = $self->$key;
|
||||
}
|
||||
|
|
@ -246,6 +255,15 @@ sub getTemplateVarsEditForm {
|
|||
my $session = $self->session;
|
||||
my $var = $self->getTemplateVars;
|
||||
|
||||
my $parent = $self->getParent;
|
||||
#If it's a new point, we have to get the parent from the url
|
||||
unless ($parent) {
|
||||
my $url = $session->url->page;
|
||||
$parent = WebGUI::Asset->newByUrl($session,$url);
|
||||
}
|
||||
|
||||
$var->{'can_edit_map'} = $parent->canEdit;
|
||||
|
||||
$var->{ form_header }
|
||||
= WebGUI::Form::formHeader( $session )
|
||||
. WebGUI::Form::hidden( $session, {
|
||||
|
|
@ -293,8 +311,25 @@ sub getTemplateVarsEditForm {
|
|||
name => "synopsis",
|
||||
value => $self->synopsis,
|
||||
resizable => 0,
|
||||
} );
|
||||
} );
|
||||
|
||||
#Only allow people who can edit the parent to change isHidden
|
||||
if($var->{'can_edit_map'}) {
|
||||
my $isHidden = (defined $self->get("isHidden")) ? $self->get("isHidden") : 1;
|
||||
$var->{ "form_isHidden" }
|
||||
= WebGUI::Form::yesNo( $session, {
|
||||
name => "isHidden",
|
||||
value => $isHidden,
|
||||
} );
|
||||
}
|
||||
|
||||
my $isGeocoded = ( $self->getId ) ? $self->get("isGeocoded") : 1;
|
||||
$var->{"form_isGeocoded"}
|
||||
= WebGUI::Form::checkbox( $session, {
|
||||
name => "isGeocoded",
|
||||
value => 1,
|
||||
checked => $isGeocoded
|
||||
} );
|
||||
# Fix storageIdPhoto because scripts do not get executed in ajax requests
|
||||
$var->{ "form_storageIdPhoto" }
|
||||
= '<input type="file" name="storageIdPhoto" />';
|
||||
|
|
@ -309,6 +344,35 @@ sub getTemplateVarsEditForm {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 indexContent ( )
|
||||
|
||||
Indexing the content of attachments and user defined fields. See WebGUI::Asset::indexContent() for additonal details.
|
||||
|
||||
=cut
|
||||
|
||||
sub indexContent {
|
||||
my $self = shift;
|
||||
my $indexer = $self->SUPER::indexContent;
|
||||
$indexer->addKeywords($self->get("website"));
|
||||
$indexer->addKeywords($self->get("address1"));
|
||||
$indexer->addKeywords($self->get("address2"));
|
||||
$indexer->addKeywords($self->get("city"));
|
||||
$indexer->addKeywords($self->get("region"));
|
||||
$indexer->addKeywords($self->get("zipCode"));
|
||||
$indexer->addKeywords($self->get("country"));
|
||||
$indexer->addKeywords($self->get("phone"));
|
||||
$indexer->addKeywords($self->get("fax"));
|
||||
$indexer->addKeywords($self->get("email"));
|
||||
$indexer->addKeywords($self->get("userDefined1"));
|
||||
$indexer->addKeywords($self->get("userDefined2"));
|
||||
$indexer->addKeywords($self->get("userDefined3"));
|
||||
$indexer->addKeywords($self->get("userDefined4"));
|
||||
$indexer->addKeywords($self->get("userDefined5"));
|
||||
return $indexer;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 processAjaxEditForm ( )
|
||||
|
||||
Process the Ajax Edit Form from the Map. If any errors occur, return
|
||||
|
|
@ -336,6 +400,29 @@ sub processAjaxEditForm {
|
|||
$prop->{ synopsis } = $form->get('synopsis');
|
||||
$prop->{ url } = $session->url->urlize( $self->getParent->getUrl . '/' . $prop->{title} );
|
||||
$prop->{ ownerUserId } = $form->get('ownerUserId') || $session->user->userId;
|
||||
#Only users who can edit the map can set this property
|
||||
if($self->getParent->canEdit) {
|
||||
$prop->{ isHidden } = $form->get('isHidden');
|
||||
}
|
||||
$prop->{isGeocoded } = $form->get('isGeocoded') || 0;
|
||||
if($prop->{isGeocoded} &&
|
||||
(
|
||||
( $form->get("address1") ne $self->get("address1") )
|
||||
|| ( $form->get("address2") ne $self->get("address2") )
|
||||
|| ( $form->get("city") ne $self->get("city") )
|
||||
|| ( $form->get("region") ne $self->get("region") )
|
||||
|| ( $form->get("zipCode") ne $self->get("zipCode") )
|
||||
|| ( $form->get("country") ne $self->get("country") )
|
||||
)
|
||||
) {
|
||||
my $geocoder = Geo::Coder::Googlev3->new;
|
||||
my $address_str = $form->get("address1");
|
||||
$address_str .= " ".$form->get("address2") if($form->get("address2"));
|
||||
$address_str .= ", ".$form->get("city").", ".$form->get("region").", ".$form->get("zipCode").", ".$form->get("country");
|
||||
my $location = $geocoder->geocode( location => $address_str );
|
||||
$prop->{latitude } = $location->{geometry}->{location}->{lat};
|
||||
$prop->{longitude} = $location->{geometry}->{location}->{lng};
|
||||
}
|
||||
|
||||
$self->update( $prop );
|
||||
|
||||
|
|
|
|||
|
|
@ -235,12 +235,16 @@ Returns a boolean indicating whether the user can view the current post.
|
|||
|
||||
sub canView {
|
||||
my $self = shift;
|
||||
if (($self->status eq "approved" || $self->status eq "archived") && $self->getThread->getParent->canView) {
|
||||
my $userId = shift || $self->session->user->userId;
|
||||
$self->session->log->info( "$userId " . $self->status );
|
||||
if (($self->status eq "approved" || $self->status eq "archived") && $self->getThread->getParent->canView( $userId )) {
|
||||
$self->session->log->info( "CAN VIEW" );
|
||||
return 1;
|
||||
} elsif ($self->canEdit) {
|
||||
} elsif ($self->canEdit( $userId )) {
|
||||
$self->session->log->info( "CAN EDIT" );
|
||||
return 1;
|
||||
} else {
|
||||
$self->getThread->getParent->canEdit;
|
||||
return $self->getThread->getParent->canEdit( $userId );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -362,6 +366,26 @@ sub disqualifyAsLastPost {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 duplicate ( )
|
||||
|
||||
Extend the base method to handle duplicate storage locations and groups.
|
||||
|
||||
=cut
|
||||
|
||||
sub duplicate {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $copy = $self->SUPER::duplicate(@_);
|
||||
if ($self->get('storageId')) {
|
||||
my $storage = $self->getStorageLocation;
|
||||
my $copied_storage = $storage->copy;
|
||||
$copy->update({storageId => $copied_storage->getId});
|
||||
}
|
||||
return $copy;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 DESTROY
|
||||
|
||||
Extend the base method to delete the locally cached thread object.
|
||||
|
|
|
|||
|
|
@ -247,6 +247,27 @@ sub DEMOLISH {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 duplicate
|
||||
|
||||
Extends the base method to handle creating a new subscription group.
|
||||
|
||||
=cut
|
||||
|
||||
sub duplicate {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $copy = $self->SUPER::duplicate(@_);
|
||||
if ($self->get('subscriptionGroupId')) {
|
||||
my $group = WebGUI::Group->new($session, $self->get('subscriptionGroupId'));
|
||||
my $copied_group = WebGUI::Group->new($session, 'new');
|
||||
$copied_group->addUsers($group->getUsers('withoutExpired'));
|
||||
$copy->update({subscriptionGroupId => $copied_group->getId});
|
||||
}
|
||||
return $copy;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAdjacentThread ( )
|
||||
|
||||
Given a field and an order, returns the nearest thread when sorting by those.
|
||||
|
|
|
|||
|
|
@ -326,7 +326,140 @@ override getEditForm => sub {
|
|||
return $f;
|
||||
};
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getAllButtons ( )
|
||||
|
||||
Get a list of all the buttons in this MCE
|
||||
|
||||
=cut
|
||||
|
||||
sub getAllButtons {
|
||||
my ( $self ) = @_;
|
||||
my @toolbarRows = map{[split "\n", $self->get("toolbarRow$_")]} (1..3);
|
||||
my @toolbarButtons = map{ @{$_} } @toolbarRows;
|
||||
return @toolbarButtons;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getConfig ( )
|
||||
|
||||
Get a hashref of configuration to create this MCE. You must run the code
|
||||
from getLoadPlugins before you can successfully initialize an MCE. You
|
||||
must also specify the "elements" key so TinyMCE knows what textarea to
|
||||
replace.
|
||||
|
||||
=cut
|
||||
|
||||
sub getConfig {
|
||||
my ($self) = @_;
|
||||
my $i18n = WebGUI::International->new($self->session, 'Asset_RichEdit');
|
||||
my @plugins;
|
||||
push @plugins, "safari";
|
||||
push @plugins, "paste";
|
||||
push @plugins, "contextmenu"
|
||||
if $self->enableContextMenu;
|
||||
push @plugins, "inlinepopups"
|
||||
if $self->inlinePopups;
|
||||
push @plugins, "media"
|
||||
if $self->allowMedia;
|
||||
|
||||
my @toolbarRows = map{[split "\n", $self->get("toolbarRow$_")]} (1..3);
|
||||
my @toolbarButtons = map{ @{$_} } @toolbarRows;
|
||||
my %config = (
|
||||
mode => 'exact',
|
||||
theme => "advanced",
|
||||
relative_urls => JSON::false(),
|
||||
remove_script_host => JSON::true(),
|
||||
auto_reset_designmode => JSON::true(),
|
||||
cleanup_callback => "tinyMCE_WebGUI_Cleanup",
|
||||
urlconverter_callback => "tinyMCE_WebGUI_URLConvertor",
|
||||
theme_advanced_resizing => JSON::true(),
|
||||
( map { "theme_advanced_buttons" . ( $_ + 1 ) => ( join ',', @{ $toolbarRows[$_] } ) } ( 0 .. $#toolbarRows ) ),
|
||||
|
||||
ask => JSON::false(),
|
||||
preformatted => $self->preformatted ? JSON::true() : JSON::false(),
|
||||
force_br_newlines => $self->useBr ? JSON::true() : JSON::false(),
|
||||
force_p_newlines => $self->useBr ? JSON::false() : JSON::true(),
|
||||
$self->useBr ? ( forced_root_block => JSON::false() ) : (),
|
||||
remove_linebreaks => $self->removeLineBreaks ? JSON::true() : JSON::false(),
|
||||
nowrap => $self->nowrap ? JSON::true() : JSON::false(),
|
||||
directionality => $self->directionality,
|
||||
theme_advanced_toolbar_location => $self->toolbarLocation,
|
||||
theme_advanced_statusbar_location => "bottom",
|
||||
valid_elements => $self->validElements,
|
||||
wg_userIsVisitor => $self->session->user->isVisitor ? JSON::true() : JSON::false(),
|
||||
paste_postprocess => 'tinyMCE_WebGUI_paste_postprocess',
|
||||
);
|
||||
foreach my $button (@toolbarButtons) {
|
||||
if ( $button eq "spellchecker" && $self->session->config->get('availableDictionaries') ) {
|
||||
push( @plugins, "-wgspellchecker" );
|
||||
$config{spellchecker_rpc_url} = $self->session->url->gateway( '', "op=spellCheck" );
|
||||
$config{spellchecker_languages} = join( ',',
|
||||
map { ( $_->{default} ? '+' : '' ) . $_->{name} . '=' . $_->{id} }
|
||||
@{ $self->session->config->get('availableDictionaries') } );
|
||||
}
|
||||
push( @plugins, "table" ) if ( $button eq "tablecontrols" );
|
||||
push( @plugins, "save" ) if ( $button eq "save" );
|
||||
push( @plugins, "advhr" ) if ( $button eq "advhr" );
|
||||
push( @plugins, "fullscreen" ) if ( $button eq "fullscreen" );
|
||||
if ( $button eq "advimage" ) {
|
||||
push( @plugins, "advimage" );
|
||||
$config{external_link_list_url} = "";
|
||||
}
|
||||
if ( $button eq "advlink" ) {
|
||||
$config{external_image_list_url} = "";
|
||||
$config{file_browser_callback} = "mcFileManager.filebrowserCallBack";
|
||||
push( @plugins, "advlink" );
|
||||
}
|
||||
push( @plugins, "emotions" ) if ( $button eq "emotions" );
|
||||
push( @plugins, "iespell" ) if ( $button eq "iespell" );
|
||||
$config{gecko_spellcheck} = 'true' if ( $button eq "iespell" );
|
||||
if ( $button eq "paste" || $button eq "pastetext" || $button eq "pasteword" ) {
|
||||
push( @plugins, "paste" );
|
||||
}
|
||||
if ( $button eq "insertdate" || $button eq "inserttime" || $button eq "insertdatetime" ) {
|
||||
$config{plugin_insertdate_dateFormat} = "%Y-%m-%d";
|
||||
$config{plugin_insertdate_timeFormat} = "%H:%M:%S";
|
||||
push( @plugins, "insertdatetime" );
|
||||
}
|
||||
push( @plugins, "preview" ) if ( $button eq "preview" );
|
||||
if ( $button eq "media" ) {
|
||||
push( @plugins, "media" );
|
||||
}
|
||||
push( @plugins, "searchreplace" )
|
||||
if ( $button eq "search" || $button eq "replace" || $button eq "searchreplace" );
|
||||
push( @plugins, "print" ) if ( $button eq "print" );
|
||||
if ( $button eq "wginsertimage" ) {
|
||||
push @plugins, "-wginsertimage";
|
||||
}
|
||||
if ( $button eq "wgpagetree" ) {
|
||||
push @plugins, "-wgpagetree";
|
||||
}
|
||||
if ( $button eq "wgmacro" ) {
|
||||
push @plugins, "-wgmacro";
|
||||
}
|
||||
if ( $button eq "code" ) {
|
||||
$config{theme_advanced_source_editor_width} = $self->sourceEditorWidth
|
||||
if ( $self->sourceEditorWidth > 0 );
|
||||
$config{theme_advanced_source_editor_height} = $self->sourceEditorHeight
|
||||
if ( $self->sourceEditorHeight > 0 );
|
||||
}
|
||||
} ## end foreach my $button (@toolbarButtons)
|
||||
my $language = $i18n->getLanguage( '', "languageAbbreviation" );
|
||||
unless ($language) {
|
||||
$language = $i18n->getLanguage( "English", "languageAbbreviation" );
|
||||
}
|
||||
$config{language} = $language;
|
||||
$config{content_css} = $self->cssFile
|
||||
|| $self->session->url->extras('tinymce-webgui/defaultcontent.css');
|
||||
$config{width} = $self->editorWidth if ( $self->editorWidth > 0 );
|
||||
$config{height} = $self->editorHeight if ( $self->editorHeight > 0 );
|
||||
$config{plugins} = join( ",", @plugins );
|
||||
|
||||
return \%config;
|
||||
} ## end sub getConfig
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -354,6 +487,40 @@ my $sql = "select asset.assetId, assetData.revisionDate from RichEdit left join
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getLoadPlugins ( )
|
||||
|
||||
Get the JS code to load the plugins for this MCE. Needs to be called once
|
||||
on the page this MCE will be on
|
||||
|
||||
=cut
|
||||
|
||||
sub getLoadPlugins {
|
||||
my ( $self ) = @_;
|
||||
my %loadPlugins;
|
||||
for my $button ( $self->getAllButtons ) {
|
||||
if ( $button eq 'spellchecker' ) {
|
||||
$loadPlugins{wgspellchecker} = $self->session->url->extras("tinymce-webgui/plugins/wgspellchecker/editor_plugin.js");
|
||||
}
|
||||
if ( $button eq 'wginsertimage' ) {
|
||||
$loadPlugins{wginsertimage} = $self->session->url->extras("tinymce-webgui/plugins/wginsertimage/editor_plugin.js");
|
||||
}
|
||||
if ( $button eq 'wgpagetree' ) {
|
||||
$loadPlugins{wgpagetree} = $self->session->url->extras("tinymce-webgui/plugins/wgpagetree/editor_plugin.js");
|
||||
}
|
||||
if ( $button eq 'wgmacro' ) {
|
||||
$loadPlugins{wgmacro} = $self->session->url->extras("tinymce-webgui/plugins/wgmacro/editor_plugin.js");
|
||||
}
|
||||
}
|
||||
|
||||
my $out = '';
|
||||
while (my ($plugin, $path) = each %loadPlugins) {
|
||||
$out .= "tinymce.PluginManager.load('$plugin', '$path');\n";
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRichEditor ( $nameId )
|
||||
|
||||
Return the javascript needed to make the Rich Editor.
|
||||
|
|
@ -369,119 +536,16 @@ sub getRichEditor {
|
|||
my $self = shift;
|
||||
return '' if ($self->disableRichEditor);
|
||||
my $nameId = shift;
|
||||
my @plugins;
|
||||
my %loadPlugins;
|
||||
push @plugins, "safari";
|
||||
push @plugins, "contextmenu"
|
||||
if $self->enableContextMenu;
|
||||
push @plugins, "inlinepopups"
|
||||
if $self->inlinePopups;
|
||||
push @plugins, "media"
|
||||
if $self->allowMedia;
|
||||
|
||||
my @toolbarRows = map{[split "\n", $self->get("toolbarRow$_")]} (1..3);
|
||||
my @toolbarButtons = map{ @{$_} } @toolbarRows;
|
||||
my $i18n = WebGUI::International->new($self->session, 'Asset_RichEdit');
|
||||
my $ask = $self->askAboutRichEdit;
|
||||
my %config = (
|
||||
mode => $ask ? "none" : "exact",
|
||||
elements => $nameId,
|
||||
theme => "advanced",
|
||||
relative_urls => JSON::false(),
|
||||
remove_script_host => JSON::true(),
|
||||
auto_reset_designmode => JSON::true(),
|
||||
cleanup_callback => "tinyMCE_WebGUI_Cleanup",
|
||||
urlconverter_callback => "tinyMCE_WebGUI_URLConvertor",
|
||||
theme_advanced_resizing => JSON::true(),
|
||||
(map { "theme_advanced_buttons".($_+1) => (join ',', @{$toolbarRows[$_]}) }
|
||||
(0..$#toolbarRows)),
|
||||
#ask => $self->getValue("askAboutRichEdit") ? JSON::true() : JSON::false(),
|
||||
ask => JSON::false(),
|
||||
preformatted => $self->preformatted ? JSON::true() : JSON::false(),
|
||||
force_br_newlines => $self->useBr ? JSON::true() : JSON::false(),
|
||||
force_p_newlines => $self->useBr ? JSON::false() : JSON::true(),
|
||||
$self->useBr ? ( forced_root_block => JSON::false() ) : (),
|
||||
remove_linebreaks => $self->removeLineBreaks ? JSON::true() : JSON::false(),
|
||||
nowrap => $self->nowrap ? JSON::true() : JSON::false(),
|
||||
directionality => $self->directionality,
|
||||
theme_advanced_toolbar_location => $self->toolbarLocation,
|
||||
theme_advanced_statusbar_location => "bottom",
|
||||
valid_elements => $self->validElements,
|
||||
wg_userIsVisitor => $self->session->user->isVisitor ? JSON::true() : JSON::false(),
|
||||
);
|
||||
# if ($ask) {
|
||||
# $config{oninit} = 'turnOffTinyMCE_'.$nameId;
|
||||
# }
|
||||
foreach my $button (@toolbarButtons) {
|
||||
if ($button eq "spellchecker" && $self->session->config->get('availableDictionaries')) {
|
||||
push(@plugins,"-wgspellchecker");
|
||||
$loadPlugins{wgspellchecker} = $self->session->url->extras("tinymce-webgui/plugins/wgspellchecker/editor_plugin.js");
|
||||
$config{spellchecker_rpc_url} = $self->session->url->gateway('', "op=spellCheck");
|
||||
$config{spellchecker_languages} =
|
||||
join(',', map { ($_->{default} ? '+' : '').$_->{name}.'='.$_->{id} } @{$self->session->config->get('availableDictionaries')});
|
||||
}
|
||||
push(@plugins,"table") if ($button eq "tablecontrols");
|
||||
push(@plugins,"save") if ($button eq "save");
|
||||
push(@plugins,"advhr") if ($button eq "advhr");
|
||||
push(@plugins,"fullscreen") if ($button eq "fullscreen");
|
||||
if ($button eq "advimage") {
|
||||
push(@plugins,"advimage");
|
||||
$config{external_link_list_url} = "";
|
||||
}
|
||||
if ($button eq "advlink") {
|
||||
$config{external_image_list_url} = "";
|
||||
$config{file_browser_callback} = "mcFileManager.filebrowserCallBack";
|
||||
push(@plugins,"advlink");
|
||||
}
|
||||
push(@plugins,"emotions") if ($button eq "emotions");
|
||||
push(@plugins,"iespell") if ($button eq "iespell");
|
||||
$config{gecko_spellcheck} = 'true' if ($button eq "iespell");
|
||||
if ($button eq "paste" || $button eq "pastetext" || $button eq "pasteword") {
|
||||
push(@plugins,"paste");
|
||||
}
|
||||
if ($button eq "insertdate" || $button eq "inserttime" || $button eq "insertdatetime") {
|
||||
$config{plugin_insertdate_dateFormat} = "%Y-%m-%d";
|
||||
$config{plugin_insertdate_timeFormat} = "%H:%M:%S";
|
||||
push(@plugins,"insertdatetime");
|
||||
}
|
||||
push(@plugins,"preview") if ($button eq "preview");
|
||||
if ($button eq "media") {
|
||||
push(@plugins,"media");
|
||||
}
|
||||
push(@plugins,"searchreplace") if ($button eq "search" || $button eq "replace" || $button eq "searchreplace");
|
||||
push(@plugins,"print") if ($button eq "print");
|
||||
if ($button eq "wginsertimage") {
|
||||
push @plugins, "-wginsertimage";
|
||||
$loadPlugins{wginsertimage} = $self->session->url->extras("tinymce-webgui/plugins/wginsertimage/editor_plugin.js");
|
||||
}
|
||||
if ($button eq "wgpagetree") {
|
||||
push @plugins, "-wgpagetree";
|
||||
$loadPlugins{wgpagetree} = $self->session->url->extras("tinymce-webgui/plugins/wgpagetree/editor_plugin.js");
|
||||
}
|
||||
if ($button eq "wgmacro") {
|
||||
push @plugins, "-wgmacro";
|
||||
$loadPlugins{wgmacro} = $self->session->url->extras("tinymce-webgui/plugins/wgmacro/editor_plugin.js");
|
||||
}
|
||||
if ($button eq "code") {
|
||||
$config{theme_advanced_source_editor_width} = $self->sourceEditorWidth if ($self->sourceEditorWidth > 0);
|
||||
$config{theme_advanced_source_editor_height} = $self->sourceEditorHeight if ($self->sourceEditorHeight > 0);
|
||||
}
|
||||
}
|
||||
my $language = $i18n->getLanguage('' ,"languageAbbreviation");
|
||||
unless ($language) {
|
||||
$language = $i18n->getLanguage("English","languageAbbreviation");
|
||||
}
|
||||
$config{language} = $language;
|
||||
$config{content_css} = $self->cssFile || $self->session->url->extras('tinymce-webgui/defaultcontent.css');
|
||||
$config{width} = $self->editorWidth || "100%";
|
||||
$config{height} = $self->editorHeight || "100%";
|
||||
$config{plugins} = join(",",@plugins);
|
||||
|
||||
$self->richedit_headTags;
|
||||
my $out = '';
|
||||
if ($ask) {
|
||||
$out = q|<a style="display: block;" href="javascript:toggleEditor('|.$nameId.q|')">|.$i18n->get('Toggle editor').q|</a>|;
|
||||
}
|
||||
$self->richedit_headTags;
|
||||
$out .= qq|<script type="text/javascript">\n|;
|
||||
if ($ask) {
|
||||
$out .= <<"EOHTML1";
|
||||
|
|
@ -498,11 +562,16 @@ EOHTML1
|
|||
# }
|
||||
#}
|
||||
#YAHOO.util.Event.onDOMReady(turnOffTinyMCE_$nameId);
|
||||
}
|
||||
|
||||
my $config = $self->getConfig;
|
||||
$config->{ elements } = $nameId;
|
||||
if ( $ask ) {
|
||||
$config->{mode} = "none";
|
||||
}
|
||||
while (my ($plugin, $path) = each %loadPlugins) {
|
||||
$out .= "tinymce.PluginManager.load('$plugin', '$path');\n";
|
||||
}
|
||||
$out .= "\ttinyMCE.init(" . JSON->new->pretty->encode(\%config) . " );\n";
|
||||
|
||||
$out .= $self->getLoadPlugins;
|
||||
$out .= "\ttinyMCE.init(" . JSON->new->pretty->encode( $config ) . " );\n";
|
||||
$out .= "</script>";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -637,7 +637,8 @@ sub getShortcutByCriteria {
|
|||
|
||||
my $replacement = $expression; # We don't want to modify $expression.
|
||||
# We need it later.
|
||||
push(@joins," left join metaData_values ".$counter."_v on a.assetId=".$counter."_v.assetId ");
|
||||
my $alias = $counter . '_v';
|
||||
push(@joins," left join metaData_values $alias on a.assetId=$alias.assetId and d.revisionDate = $alias.revisionDate ");
|
||||
# Get the field (State) and the value (Wisconsin) from the $expression.
|
||||
$expression =~ /($attribute)\s*($operator)\s*($attribute)/gi;
|
||||
my $field = $1;
|
||||
|
|
@ -670,7 +671,12 @@ sub getShortcutByCriteria {
|
|||
}
|
||||
|
||||
my $sql = "select a.assetId from asset a
|
||||
".join("\n", @joins)."
|
||||
left join assetData d on a.assetId = d.assetId
|
||||
and d.revisionDate=(
|
||||
select max(revisionDate)
|
||||
from assetData d2
|
||||
where d2.assetId = a.assetId
|
||||
) ".join("\n", @joins)."
|
||||
where a.className = ".$db->quote($self->getShortcutDefault->get("className"));
|
||||
# Add constraint only if it has been modified.
|
||||
$sql .= " and ".$constraint if (($constraint ne $criteria) && $constraint ne "");
|
||||
|
|
|
|||
|
|
@ -528,7 +528,9 @@ The WebGUI::Shop::TransactionItem being refunded.
|
|||
|
||||
sub onRefund {
|
||||
my ($self, $item) = @_;
|
||||
$self->onCancelRecurring($item);
|
||||
if ($self->isRecurring) {
|
||||
$self->onCancelRecurring($item);
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1792,34 +1792,42 @@ sub view {
|
|||
$var{'addaccessory_url'} = $self->getUrl('func=addAccessory');
|
||||
$var{'addaccessory_label'} = $i18n->get(36);
|
||||
##Need an id for collateral operations, and an assetId for asset instantiation.
|
||||
foreach my $collateral ( @{ $self->getAllCollateral('accessoryJSON') } ) {
|
||||
ACCESSORY: foreach my $collateral ( @{ $self->getAllCollateral('accessoryJSON') } ) {
|
||||
my $id = $collateral->{accessoryAssetId};
|
||||
$segment = $self->session->icon->delete('func=deleteAccessoryConfirm&aid='.$id,$self->get('url'),$i18n->get(2))
|
||||
. $self->session->icon->moveUp('func=moveAccessoryUp&aid='.$id,$self->get('url'))
|
||||
. $self->session->icon->moveDown('func=moveAccessoryDown&aid='.$id,$self->get('url'));
|
||||
my $accessory_vars = {
|
||||
accessory_title => $i18n->get('Lost'),
|
||||
accessory_controls => $segment,
|
||||
};
|
||||
my $accessory = WebGUI::Asset->newById($session, $collateral->{accessoryAssetId});
|
||||
push(@accessoryloop,{
|
||||
'accessory_URL' => $accessory->getUrl,
|
||||
'accessory_title' => $accessory->getTitle,
|
||||
'accessory_controls' => $segment,
|
||||
});
|
||||
if ( $accessory ) {
|
||||
$accessory_vars->{ accessory_URL } = $accessory->getUrl;
|
||||
$accessory_vars->{ accessory_title } = $accessory->getTitle;
|
||||
}
|
||||
push(@accessoryloop, $accessory_vars);
|
||||
}
|
||||
$var{accessory_loop} = \@accessoryloop;
|
||||
|
||||
#---related
|
||||
$var{'addrelatedproduct_url'} = $self->getUrl('func=addRelated');
|
||||
$var{'addrelatedproduct_label'} = $i18n->get(37);
|
||||
foreach my $collateral ( @{ $self->getAllCollateral('relatedJSON')} ) {
|
||||
RELATED: foreach my $collateral ( @{ $self->getAllCollateral('relatedJSON')} ) {
|
||||
my $id = $collateral->{relatedAssetId};
|
||||
$segment = $self->session->icon->delete('func=deleteRelatedConfirm&rid='.$id, $self->get('url'),$i18n->get(4))
|
||||
. $self->session->icon->moveUp('func=moveRelatedUp&rid='.$id, $self->get('url'))
|
||||
. $self->session->icon->moveDown('func=moveRelatedDown&rid='.$id, $self->get('url'));
|
||||
my $related_vars = {
|
||||
relatedproduct_title => $i18n->get('Lost'),
|
||||
relatedproduct_controls => $segment,
|
||||
};
|
||||
my $related = WebGUI::Asset->newById($session, $collateral->{relatedAssetId});
|
||||
push(@relatedloop,{
|
||||
'relatedproduct_URL' => $related->getUrl,
|
||||
'relatedproduct_title' => $related->getTitle,
|
||||
'relatedproduct_controls' => $segment,
|
||||
});
|
||||
if ($related) {
|
||||
$related_vars->{ relatedproduct_URL } = $related->getUrl;
|
||||
$related_vars->{ relatedproduct_title } = $related->getTitle;
|
||||
}
|
||||
push(@relatedloop, $related_vars);
|
||||
}
|
||||
$var{relatedproduct_loop} = \@relatedloop;
|
||||
|
||||
|
|
|
|||
|
|
@ -91,13 +91,6 @@ property cacheTimeout => (
|
|||
label => ["cache timeout",'Asset_Snippet'],
|
||||
hoverHelp => ["cache timeout help",'Asset_Snippet'],
|
||||
);
|
||||
property processAsTemplate => (
|
||||
fieldType => 'yesNo',
|
||||
label => ['process as template','Asset_Snippet'],
|
||||
hoverHelp => ['process as template description','Asset_Snippet'],
|
||||
tab => "properties",
|
||||
default => 0,
|
||||
);
|
||||
property mimeType => (
|
||||
tab => "properties",
|
||||
hoverHelp => ['mimeType description','Asset_Snippet'],
|
||||
|
|
@ -105,6 +98,15 @@ property mimeType => (
|
|||
fieldType => 'mimeType',
|
||||
default => 'text/html',
|
||||
);
|
||||
property templateParser => (
|
||||
fieldType => 'templateParser',
|
||||
allowNone => 1,
|
||||
label => ['parser','Asset_Template'],
|
||||
hoverHelp => ['parser description','Asset_Template'],
|
||||
tab => 'properties',
|
||||
defaultValue => '',
|
||||
);
|
||||
|
||||
has '+uiLevel' => (
|
||||
default => 5,
|
||||
);
|
||||
|
|
@ -247,13 +249,15 @@ sub view {
|
|||
my $out = $session->cache->get( $cacheKey );
|
||||
return $out if $out;
|
||||
}
|
||||
my $output = $self->usePacked
|
||||
? $self->snippetPacked
|
||||
: $self->snippet
|
||||
;
|
||||
my $output = $self->get('usePacked')
|
||||
? $self->get("snippetPacked")
|
||||
: $self->get('snippet')
|
||||
;
|
||||
$output = $self->getToolbar.$output if ($session->isAdminOn && !$calledAsWebMethod);
|
||||
if ($self->processAsTemplate) {
|
||||
$output = WebGUI::Asset::Template->processRaw($session, $output, $self->get);
|
||||
if (my $parser = $self->templateParser) {
|
||||
$output = WebGUI::Asset::Template->processRaw(
|
||||
$session, $output, $self->get, $parser
|
||||
);
|
||||
}
|
||||
WebGUI::Macro::process($session,\$output);
|
||||
unless ($noCache) {
|
||||
|
|
|
|||
|
|
@ -207,6 +207,26 @@ sub exportAssetData {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 exportGetRelatedAssetIds
|
||||
|
||||
Overriden to include any topics in which this story would appear.
|
||||
|
||||
=cut
|
||||
|
||||
sub exportGetRelatedAssetIds {
|
||||
my $self = shift;
|
||||
my $rel = $self->SUPER::exportGetRelatedAssetIds(@_);
|
||||
push @$rel, @{
|
||||
WebGUI::Keyword->new($self->session)->getMatchingAssets({
|
||||
keywords => WebGUI::Keyword::string2list($self->get('keywords')),
|
||||
isa => 'WebGUI::Asset::Wobject::StoryTopic',
|
||||
})
|
||||
};
|
||||
return $rel;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 formatDuration ( $lastUpdated )
|
||||
|
||||
Format the time since this story was last updated. If it is longer than 1 week, then
|
||||
|
|
@ -396,6 +416,9 @@ sub getEditForm {
|
|||
value => $i18n->get('save and add another photo'),
|
||||
}),
|
||||
};
|
||||
if ($session->setting->get('metaDataEnabled')) {
|
||||
$var->{metadata} = $self->getMetaDataAsFormFields;
|
||||
}
|
||||
$var->{ photo_form_loop } = [];
|
||||
##Provide forms for the existing photos, if any
|
||||
##Existing photos get a delete Yes/No.
|
||||
|
|
@ -405,12 +428,16 @@ sub getEditForm {
|
|||
foreach my $photoIndex (1..$numberOfPhotos) {
|
||||
my $photo = $photoData->[$photoIndex-1];
|
||||
my $storage = WebGUI::Storage->get($session, $photo->{storageId});
|
||||
my $filename = $storage->getFiles->[0];
|
||||
my $filename = $storage && $storage->getFiles->[0];
|
||||
push @{ $var->{ photo_form_loop } }, {
|
||||
hasPhoto => $filename ? 1 : 0,
|
||||
imgThumb => $filename ? $storage->getThumbnailUrl($filename) : '',
|
||||
imgUrl => $filename ? $storage->getUrl($filename) : '',
|
||||
imgFilename => $filename ? $filename : '',
|
||||
imgRemoteUrlForm => WebGUI::Form::text($session, {
|
||||
name => 'imgRemoteUrl'.$photoIndex,
|
||||
value => $photo->{remoteUrl},
|
||||
}),
|
||||
newUploadForm => WebGUI::Form::file($session, {
|
||||
name => 'newPhoto' . $photoIndex,
|
||||
maxAttachments => 1,
|
||||
|
|
@ -442,6 +469,9 @@ sub getEditForm {
|
|||
};
|
||||
}
|
||||
push @{ $var->{ photo_form_loop } }, {
|
||||
imgRemoteUrlForm => WebGUI::Form::text($session, {
|
||||
name => 'imgRemoteUrl',
|
||||
}),
|
||||
newUploadForm => WebGUI::Form::image($session, {
|
||||
name => 'newPhoto',
|
||||
maxAttachments => 1,
|
||||
|
|
@ -580,16 +610,20 @@ sub processEditForm {
|
|||
PHOTO: foreach my $photoIndex (1..$numberOfPhotos) {
|
||||
##TODO: Deletion check and storage cleanup
|
||||
my $storageId = $photoData->[$photoIndex-1]->{storageId};
|
||||
my $storage = $storageId && WebGUI::Storage->get($session, $storageId);
|
||||
my $remote = $form->process("imgRemoteUrl$photoIndex");
|
||||
if ($form->process('deletePhoto'.$photoIndex, 'yesNo')) {
|
||||
my $storage = WebGUI::Storage->get($session, $storageId);
|
||||
$storage->delete if $storage;
|
||||
splice @{ $photoData }, $photoIndex-1, 1;
|
||||
next PHOTO;
|
||||
}
|
||||
##Process photos with urls that replace existing photos
|
||||
if ($remote) {
|
||||
$storage->delete() if $storage;
|
||||
}
|
||||
##Process uploads that replace existing photos
|
||||
if (my $uploadId = $form->process('newPhoto'.$photoIndex,'File')) {
|
||||
elsif (my $uploadId = $form->process('newPhoto'.$photoIndex,'File')) {
|
||||
my $upload = WebGUI::Storage->get($session, $uploadId);
|
||||
my $storage = WebGUI::Storage->get($session, $storageId);
|
||||
$storage->clear;
|
||||
my $filename = $upload->getFiles->[0];
|
||||
$storage->addFileFromFilesystem($upload->getPath($filename));
|
||||
|
|
@ -600,31 +634,43 @@ sub processEditForm {
|
|||
$upload->delete;
|
||||
}
|
||||
my $newPhoto = {
|
||||
storageId => $storageId,
|
||||
caption => $form->process('imgCaption'.$photoIndex, 'text'),
|
||||
alt => $form->process('imgAlt' .$photoIndex, 'text'),
|
||||
title => $form->process('imgTitle' .$photoIndex, 'text'),
|
||||
byLine => $form->process('imgByline' .$photoIndex, 'text'),
|
||||
url => $form->process('imgUrl' .$photoIndex, 'url' ),
|
||||
};
|
||||
if ($remote) {
|
||||
$newPhoto->{remoteUrl} = $remote;
|
||||
}
|
||||
else {
|
||||
$newPhoto->{storageId} = $storageId;
|
||||
}
|
||||
splice @{ $photoData }, $photoIndex-1, 1, $newPhoto;
|
||||
}
|
||||
my $newStorageId = $form->process('newPhoto', 'image');
|
||||
if ($newStorageId) {
|
||||
my $newStorage = WebGUI::Storage->get($session, $newStorageId);
|
||||
my $photoName = $newStorage->getFiles->[0];
|
||||
my ($width, $height) = $newStorage->getSizeInPixels($photoName);
|
||||
if ($width > $self->getArchive->photoWidth) {
|
||||
$newStorage->resize($photoName, $self->getArchive->photoWidth);
|
||||
}
|
||||
push @{ $photoData }, {
|
||||
my $newRemote = $form->process('imgRemoteUrl');
|
||||
if ($newStorageId || $newRemote) {
|
||||
my $newPhoto = {
|
||||
caption => $form->process('newImgCaption', 'text'),
|
||||
alt => $form->process('newImgAlt', 'text'),
|
||||
title => $form->process('newImgTitle', 'text'),
|
||||
byLine => $form->process('newImgByline', 'text'),
|
||||
url => $form->process('newImgUrl', 'url'),
|
||||
storageId => $newStorageId,
|
||||
};
|
||||
if ($newRemote) {
|
||||
$newPhoto->{remoteUrl} = $newRemote;
|
||||
}
|
||||
else {
|
||||
my $newStorage = WebGUI::Storage->get($session, $newStorageId);
|
||||
my $photoName = $newStorage->getFiles->[0];
|
||||
my ($width, $height) = $newStorage->getSizeInPixels($photoName);
|
||||
if ($width > $self->getArchive->get('photoWidth')) {
|
||||
$newStorage->resize($photoName, $self->getArchive->get('photoWidth'));
|
||||
}
|
||||
$newPhoto->{storageId} = $newStorageId;
|
||||
}
|
||||
push @{ $photoData }, $newPhoto;
|
||||
}
|
||||
$self->setPhotoData($photoData);
|
||||
$self->{_parent} = $archive; ##Restore archive, for URL and other calculations
|
||||
|
|
@ -666,8 +712,9 @@ Remove the storage locations for this revision of the Asset.
|
|||
override purgeRevision => sub {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
foreach my $photo ( @{ $self->getPhotoData} ) {
|
||||
my $storage = WebGUI::Storage->get($session, $self-$photo->{storageId});
|
||||
PHOTO: foreach my $photo ( @{ $self->getPhotoData} ) {
|
||||
my $id = $photo->{storageId} or next PHOTO;
|
||||
my $storage = WebGUI::Storage->get($session, $id);
|
||||
$storage->delete if $storage;
|
||||
}
|
||||
return super();
|
||||
|
|
@ -832,13 +879,23 @@ sub viewTemplateVariables {
|
|||
}
|
||||
}
|
||||
|
||||
my $key = WebGUI::Keyword->new($session);
|
||||
my $keywords = $key->getKeywordsForAsset( { asArrayRef => 1, asset => $self });
|
||||
my $isExporting = $session->scratch->get('isExporting');
|
||||
my $key = WebGUI::Keyword->new($session);
|
||||
my $keywords = $key->getKeywordsForAsset( { asArrayRef => 1, asset => $self });
|
||||
$var->{keyword_loop} = [];
|
||||
my $parent = $self->getParent;
|
||||
my $upwards = $parent->isa('WebGUI::Asset::Wobject::StoryArchive')
|
||||
? '' #In parallel with the Keywords files
|
||||
: '../' #Keywords files are one level up
|
||||
;
|
||||
foreach my $keyword (@{ $keywords }) {
|
||||
my $keyword_url = $isExporting
|
||||
? $upwards . $archive->getKeywordFilename($keyword)
|
||||
: $archive->getUrl("func=view;keyword=".$session->url->escape($keyword))
|
||||
;
|
||||
push @{ $var->{keyword_loop} }, {
|
||||
keyword => $keyword,
|
||||
url => $archive->getUrl("func=view;keyword=".$session->url->escape($keyword)),
|
||||
url => $keyword_url,
|
||||
};
|
||||
}
|
||||
$var->{updatedTime} = $self->formatDuration();
|
||||
|
|
@ -849,11 +906,19 @@ sub viewTemplateVariables {
|
|||
$var->{photo_loop} = [];
|
||||
my $photoCounter = 0;
|
||||
PHOTO: foreach my $photo (@{ $photoData }) {
|
||||
next PHOTO unless $photo->{storageId};
|
||||
my $storage = WebGUI::Storage->get($session, $photo->{storageId});
|
||||
my $file = $storage->getFiles->[0];
|
||||
next PHOTO unless $file;
|
||||
my $imageUrl = $storage->getUrl($file);
|
||||
my $imageUrl;
|
||||
if (my $remote = $photo->{remoteUrl}) {
|
||||
$imageUrl = $remote;
|
||||
}
|
||||
elsif (my $id = $photo->{storageId}) {
|
||||
my $storage = WebGUI::Storage->get($session, $photo->{storageId});
|
||||
my $file = $storage->getFiles->[0];
|
||||
next PHOTO unless $file;
|
||||
$imageUrl = $storage->getUrl($file);
|
||||
}
|
||||
else {
|
||||
next PHOTO;
|
||||
}
|
||||
push @{ $var->{photo_loop} }, {
|
||||
imageUrl => $imageUrl,
|
||||
imageCaption => $photo->{caption},
|
||||
|
|
|
|||
|
|
@ -115,7 +115,8 @@ use List::MoreUtils qw{ any };
|
|||
use Tie::IxHash;
|
||||
use Clone qw/clone/;
|
||||
use HTML::Packer;
|
||||
use JSON qw{ to_json };
|
||||
use JSON qw{ to_json from_json };
|
||||
use Try::Tiny;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -227,6 +228,8 @@ around cut => sub {
|
|||
return $returnValue;
|
||||
};
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addRevision ( )
|
||||
|
||||
Override the master addRevision to copy attachments
|
||||
|
|
@ -324,19 +327,22 @@ Returns the WebGUI::FormBuilder object that will be used in generating the edit
|
|||
override getEditForm => sub {
|
||||
my $self = shift;
|
||||
my $tabform = super();
|
||||
my $i18n = WebGUI::International->new($self->session, 'Asset_Template');
|
||||
my $session = $self->session;
|
||||
my ( $url, $style ) = $session->quick(qw( url style ));
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Template');
|
||||
my $returnUrl = $session->form->get("returnUrl");
|
||||
$tabform->addField( "hidden",
|
||||
name=>"returnUrl",
|
||||
value=>$self->session->form->get("returnUrl")
|
||||
value=>$returnUrl,
|
||||
);
|
||||
if ($self->namespace eq "") {
|
||||
my $namespaces = $self->session->dbSlave->buildHashRef("select distinct(namespace) from template order by namespace");
|
||||
my $namespaces = $session->dbSlave->buildHashRef("select distinct(namespace) from template order by namespace");
|
||||
$tabform->getTab("properties")->addField( "combo",
|
||||
name=>"namespace",
|
||||
options=>$namespaces,
|
||||
label=>$i18n->get('namespace'),
|
||||
hoverHelp=>$i18n->get('namespace description'),
|
||||
value=>[$self->session->form->get("namespace")]
|
||||
value=>[$session->form->get("namespace")]
|
||||
);
|
||||
} else {
|
||||
$tabform->getTab("meta")->addField( "ReadOnly",
|
||||
|
|
@ -346,14 +352,68 @@ override getEditForm => sub {
|
|||
value=>$self->namespace
|
||||
);
|
||||
}
|
||||
if($self->session->config->get("templateParsers")){
|
||||
my @temparray = @{$self->session->config->get("templateParsers")};
|
||||
|
||||
my $previewButtons
|
||||
= $tabform->getTab('properties')->addField( "ButtonGroup",
|
||||
name => 'previewButtons',
|
||||
label => $i18n->get('Preview'),
|
||||
);
|
||||
$previewButtons->addButton( 'Button' => { id => 'preview', value => $i18n->get('Preview') } );
|
||||
$previewButtons->addButton( 'Button' => { id => 'previewConfig', value => $i18n->get('Configure') } );
|
||||
my $cform = WebGUI::HTMLForm->new($session);
|
||||
$cform->yesNo(
|
||||
id => 'previewRaw',
|
||||
name => 'previewRaw',
|
||||
label => $i18n->get('Plain Text?'),
|
||||
hoverHelp => $i18n->get('Plain Text hoverHelp'),
|
||||
);
|
||||
$cform->text(
|
||||
id => 'previewFetchUrl',
|
||||
label => $i18n->get('URL'),
|
||||
hoverHelp => $i18n->get('URL hoverHelp'),
|
||||
defaultValue => $returnUrl,
|
||||
);
|
||||
$cform->button(
|
||||
id => 'previewFetch',
|
||||
label => $i18n->get('Fetch Variables'),
|
||||
hoverHelp => $i18n->get('Fetch Variables hoverHelp'),
|
||||
value => $i18n->get('Fetch'),
|
||||
);
|
||||
$cform->codearea(
|
||||
id => 'previewVars',
|
||||
label => $i18n->get('Variables'),
|
||||
hoverHelp => $i18n->get('Variables hoverHelp'),
|
||||
);
|
||||
|
||||
$cform->hidden(id => 'previewId', value => $self->getId);
|
||||
$cform->hidden(id => 'previewGateway', value => $url->gateway);
|
||||
$tabform->getTab('properties')->addField("ReadOnly",
|
||||
name => 'previewDialog',
|
||||
value => qq(
|
||||
<div id='previewConfigForm'>
|
||||
<div class='hd'>${\ $i18n->get('Configure Preview') }</div>
|
||||
<table class='bd'>${\ $cform->printRowsOnly }</table>
|
||||
<div class='ft' style='margin:0 auto; text-align: center'>
|
||||
<button id='previewConfigClose'>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
);
|
||||
|
||||
$style->setScript($url->extras($_)) for qw(
|
||||
yui/build/json/json-min.js
|
||||
yui/build/container/container-min.js
|
||||
templatePreview.js
|
||||
);
|
||||
|
||||
if($session->config->get("templateParsers")){
|
||||
my @temparray = @{$session->config->get("templateParsers")};
|
||||
tie my %parsers, 'Tie::IxHash';
|
||||
while(my $a = shift @temparray){
|
||||
$parsers{$a} = $self->getParser($self->session, $a)->getName();
|
||||
$parsers{$a} = $self->getParser($session, $a)->getName();
|
||||
}
|
||||
my $value = [$self->parser];
|
||||
$value = \[$self->session->config->get("defaultTemplateParser")] if(!$self->parser);
|
||||
$value = \[$session->config->get("defaultTemplateParser")] if(!$self->parser);
|
||||
$tabform->getTab("properties")->addField( "SelectBox",
|
||||
name=>"parser",
|
||||
options=>\%parsers,
|
||||
|
|
@ -501,6 +561,22 @@ sub getParser {
|
|||
return $parser->new($session);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
#
|
||||
# See the warning about using this on processVariableHeaders(). If no
|
||||
# variables were captured, we'll return the empty string.
|
||||
|
||||
sub getVariableJson {
|
||||
my ($class, $session) = @_;
|
||||
my ($show, $vars, $json);
|
||||
|
||||
return ($show = $session->stow->get('showTemplateVars'))
|
||||
&& ($vars = $show->{vars})
|
||||
&& ($json = eval { JSON::encode_json($vars) })
|
||||
&& ($show->{startDelimiter} . $json . $show->{endDelimiter})
|
||||
or '';
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 importAssetCollateralData ( data )
|
||||
|
|
@ -631,6 +707,15 @@ sub process {
|
|||
return to_json( $self->param );
|
||||
}
|
||||
|
||||
my $stow = $session->stow;
|
||||
my $show = $stow->get('showTemplateVars');
|
||||
if ( $show && $show->{assetId} eq $self->getId && $self->canEdit ) {
|
||||
# This will never be true again, cause we're getting rid of assetId
|
||||
delete $show->{assetId};
|
||||
$show->{vars} = $vars;
|
||||
$stow->set( showTemplateVars => $show );
|
||||
}
|
||||
|
||||
$self->prepare unless ($self->{_prepared});
|
||||
my $parser = $self->getParser($session, $self->parser);
|
||||
my $template = $self->usePacked
|
||||
|
|
@ -653,6 +738,59 @@ sub process {
|
|||
return $output;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
# Used for debugging and the template test renderer.
|
||||
|
||||
# WARNING: Please do not rely on this behavior. It's a bit of a hack, and
|
||||
# should not be considered part of the core API. Eventually, we will have
|
||||
# introspectable template objects so that you can more easily (and
|
||||
# efficiently) get this kind of information.
|
||||
|
||||
# If the first value for the 'X-Webgui-Template-Variables' header is our
|
||||
# assetId, then in addition to processing the template, append add a json
|
||||
# representation of our template variables to the response. The headers
|
||||
# "X-Webgui-Template-Variables-Start" and "X-Webgui-Template-Variables-End"
|
||||
# will contain the delimiters for the start and end of this content so that
|
||||
# the user agent (who had to have stuck the header in in the first place) can
|
||||
# parse it out. The delimiters will make the whole thing look like an xml
|
||||
# comment (<!-- ... -->) just in case.
|
||||
|
||||
# We would just send the vars in the header, but different webservers have
|
||||
# different limits on header field size and it's impossible to say whether our
|
||||
# data will fit inside them or not.
|
||||
|
||||
# This is intended to be called earlier in the request cycle (in the Content
|
||||
# URL handler) so that the headers get sent before any chunked content starts
|
||||
# being set up. We set the stow here and check it during process() to see
|
||||
# whether we need to include the delimited json. Later on, Content will call
|
||||
# call getVariableJson to get the results.
|
||||
|
||||
{
|
||||
my $head = 'X-Webgui-Template-Variables';
|
||||
my @chr = ('0'..'9', 'a'..'z', 'A'..'Z');
|
||||
|
||||
sub processVariableHeaders {
|
||||
my ($class, $session) = @_;
|
||||
my $r = $session->request;
|
||||
if (my $id = $r->headers->header($head)) {
|
||||
my $rnd = join('', map { $chr[int(rand($#chr))] } (1..32));
|
||||
my $out = {};
|
||||
my $st = "<!-- $rnd ";
|
||||
my $end = " $rnd -->";
|
||||
$out->{"$head-Start"} = $st;
|
||||
$out->{"$head-End"} = $end;
|
||||
$session->response->headers( $out );
|
||||
$session->stow->set(
|
||||
showTemplateVars => {
|
||||
assetId => $id,
|
||||
startDelimiter => $st,
|
||||
endDelimiter => $end,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -921,6 +1059,42 @@ sub www_manage {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_preview
|
||||
|
||||
Rendes this template with the given variables (posted as JSON)
|
||||
|
||||
=cut
|
||||
|
||||
sub www_preview {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient unless $self->canEdit;
|
||||
|
||||
my $form = $session->form;
|
||||
my $http = $session->http;
|
||||
|
||||
try {
|
||||
my $output = $self->processRaw(
|
||||
$session,
|
||||
$form->get('template'),
|
||||
from_json($form->get('variables')),
|
||||
$form->get('parser'),
|
||||
);
|
||||
if ($form->get('plainText')) {
|
||||
$http->setMimeType('text/plain');
|
||||
}
|
||||
elsif ($output !~ /<html>/) {
|
||||
$output = $session->style->userStyle($output);
|
||||
}
|
||||
return $output;
|
||||
} catch {
|
||||
$http->setMimeType('text/plain');
|
||||
$_[0];
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_view
|
||||
|
||||
Override the default behavior. When a template is viewed, it redirects you
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ package WebGUI::Asset::Template::TemplateToolkit;
|
|||
use strict;
|
||||
use base 'WebGUI::Asset::Template::Parser';
|
||||
use Template;
|
||||
use WebGUI::Template::Provider;
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _rewriteVars { # replace dots with underscrores in keys (except in keys that aren't usable as variables (URLs etc.))
|
||||
|
|
@ -81,12 +82,30 @@ sub process {
|
|||
my $vars = $self->addSessionVars(shift);
|
||||
my ($t,$output);
|
||||
eval {
|
||||
$t = Template->new({
|
||||
INTERPOLATE => 1, # expand "$var" in plain text
|
||||
POST_CHOMP => 1, # cleanup whitespace
|
||||
EVAL_PERL => 0, # evaluate Perl code blocks
|
||||
});
|
||||
$t->process( \$template, _rewriteVars($vars),\$output) || $self->session->log->error($t->error());
|
||||
my $config = $self->session->config->get( 'template' ) || {};
|
||||
$config->{INTERPOLATE} //= 1; # expand "$var" in plain text
|
||||
$config->{POST_CHOMP} //= 1; # cleanup whitespace
|
||||
$config->{EVAL_PERL} //= 0; # evaluate Perl code blocks
|
||||
# Add WebGUI::Template::Plugin to PLUGIN_BASE
|
||||
if ( defined $config->{PLUGIN_BASE} && !ref $config->{PLUGIN_BASE} ) {
|
||||
$config->{PLUGIN_BASE} = [ $config->{PLUGIN_BASE} ];
|
||||
}
|
||||
elsif ( !defined $config->{PLUGIN_BASE} ) {
|
||||
$config->{PLUGIN_BASE} = [];
|
||||
}
|
||||
push @{$config->{PLUGIN_BASE}}, 'WebGUI::Template::Plugin';
|
||||
|
||||
# Allow WebGUI assets to be included in templates
|
||||
$config->{LOAD_TEMPLATES} = [ WebGUI::Template::Provider->new( $self->session, $config ) ];
|
||||
|
||||
$t = Template->new( $config );
|
||||
$vars = _rewriteVars($vars);
|
||||
$vars->{_session} = $self->session;
|
||||
unless ($t->process( \$template, $vars, \$output)) {
|
||||
my $e = $t->error;
|
||||
$self->session->log->error($e);
|
||||
die $e;
|
||||
}
|
||||
};
|
||||
if ($@) {
|
||||
WebGUI::Error::Template->throw( error => $@ );
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use Moose;
|
|||
use Tie::IxHash;
|
||||
use WebGUI::Definition::Asset;
|
||||
extends 'WebGUI::Asset::Wobject';
|
||||
with 'WebGUI::Role::Asset::JSONCollateral';
|
||||
|
||||
define assetName => ['assetName', 'Asset_Calendar'];
|
||||
define icon => 'calendar.gif';
|
||||
|
|
@ -260,7 +261,7 @@ property icalFeeds => (
|
|||
label => ['Feed URL','Asset_Calendar'],
|
||||
},
|
||||
{
|
||||
name => 'status',
|
||||
name => 'lastResult',
|
||||
type => 'readonly',
|
||||
label => ['434','WebGUI'],
|
||||
},
|
||||
|
|
@ -303,6 +304,7 @@ use WebGUI::Search;
|
|||
use WebGUI::Form;
|
||||
use WebGUI::HTML;
|
||||
use WebGUI::DateTime;
|
||||
use WebGUI::ICal;
|
||||
|
||||
use DateTime;
|
||||
use JSON;
|
||||
|
|
@ -348,10 +350,6 @@ The date this feed was added, or edited last.
|
|||
|
||||
The results of what happened the last time this feed was accessed to pull iCal.
|
||||
|
||||
=head4 feedType
|
||||
|
||||
What kind of feed this is.
|
||||
|
||||
=cut
|
||||
|
||||
sub addFeed {
|
||||
|
|
@ -860,6 +858,17 @@ override processEditForm => sub {
|
|||
$self->createSubscriptionGroup();
|
||||
}
|
||||
|
||||
my @feeds = @{ $self->getFeeds };
|
||||
foreach my $feed (@feeds) {
|
||||
if ($feed->{lastUpdated} eq 'new') {
|
||||
$feed->{lastUpdated} = 'never';
|
||||
}
|
||||
if ($feed->{lastResult} eq 'new') {
|
||||
$feed->{lastResult} = '';
|
||||
}
|
||||
$self->setFeed($feed->{feedId}, $feed);
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -1706,97 +1715,20 @@ sub www_ical {
|
|||
$dt_end = $dt_start->clone->add( seconds => $self->icalInterval );
|
||||
}
|
||||
|
||||
my $ical = WebGUI::ICal->new();
|
||||
|
||||
# Get all the events we're going to display
|
||||
my @events = $self->getEventsIn($dt_start->toMysql,$dt_end->toMysql);
|
||||
|
||||
|
||||
my $ical = qq{BEGIN:VCALENDAR\r\n}
|
||||
. qq{PRODID:WebGUI }.$WebGUI::VERSION."-".$WebGUI::STATUS.qq{\r\n}
|
||||
. qq{VERSION:2.0\r\n};
|
||||
|
||||
# VEVENT:
|
||||
EVENT: for my $event (@events) {
|
||||
next EVENT unless $event->canView();
|
||||
$ical .= qq{BEGIN:VEVENT\r\n};
|
||||
|
||||
### UID
|
||||
# Use feed's UID to prevent over-propagation
|
||||
if ($event->feedUid) {
|
||||
$ical .= qq{UID:}.$event->feedUid."\r\n";
|
||||
}
|
||||
# Create a UID for feeds native to this calendar
|
||||
else {
|
||||
my $domain = $session->config->get("sitename")->[0];
|
||||
$ical .= qq{UID:}.$event->assetId.'@'.$domain."\r\n";
|
||||
}
|
||||
|
||||
# LAST-MODIFIED (revisionDate)
|
||||
$ical .= qq{LAST-MODIFIED:}
|
||||
. WebGUI::DateTime->new($self->session, $event->revisionDate)->toIcal
|
||||
. "\r\n";
|
||||
|
||||
# CREATED (creationDate)
|
||||
$ical .= qq{CREATED:}
|
||||
. WebGUI::DateTime->new($self->session, $event->creationDate)->toIcal
|
||||
. "\r\n";
|
||||
|
||||
# SEQUENCE
|
||||
my $sequenceNumber = $event->iCalSequenceNumber;
|
||||
if (defined $sequenceNumber) {
|
||||
$ical .= qq{SEQUENCE:}
|
||||
. $event->iCalSequenceNumber
|
||||
. "\r\n";
|
||||
}
|
||||
|
||||
# DTSTART
|
||||
my $eventStart = $event->getIcalStart;
|
||||
$ical .= 'DTSTART';
|
||||
if ($eventStart !~ /T/) {
|
||||
$ical .= ';VALUE=DATE';
|
||||
}
|
||||
$ical .= ":$eventStart\r\n";
|
||||
|
||||
# DTEND
|
||||
my $eventEnd = $event->getIcalEnd;
|
||||
$ical .= 'DTEND';
|
||||
if ($eventEnd !~ /T/) {
|
||||
$ical .= ';VALUE=DATE';
|
||||
}
|
||||
$ical .= ":$eventEnd\r\n";
|
||||
|
||||
# Summary (the title)
|
||||
# Wrapped at 75 columns
|
||||
$ical .= $self->wrapIcal("SUMMARY:".$event->title)."\r\n";
|
||||
|
||||
# Description (the text)
|
||||
# Wrapped at 75 columns
|
||||
$ical .= $self->wrapIcal("DESCRIPTION:".$event->description)."\r\n";
|
||||
|
||||
# Location (the text)
|
||||
# Wrapped at 75 columns
|
||||
$ical .= $self->wrapIcal("LOCATION:".$event->location)."\r\n";
|
||||
|
||||
# X-WEBGUI lines
|
||||
if ($event->groupIdView) {
|
||||
$ical .= "X-WEBGUI-GROUPIDVIEW:".$event->groupIdView."\r\n";
|
||||
}
|
||||
if ($event->get("groupIdEdit")) {
|
||||
$ical .= "X-WEBGUI-GROUPIDEDIT:".$event->groupIdEdit."\r\n";
|
||||
}
|
||||
$ical .= "X-WEBGUI-URL:".$event->get("url")."\r\n";
|
||||
$ical .= "X-WEBGUI-MENUTITLE:".$event->menuTitle."\r\n";
|
||||
|
||||
$ical .= qq{END:VEVENT\r\n};
|
||||
$event->add_to_calendar($ical);
|
||||
}
|
||||
# ENDVEVENT
|
||||
|
||||
$ical .= qq{END:VCALENDAR\r\n};
|
||||
|
||||
|
||||
# Set mime of text/icalendar
|
||||
$self->session->response->header( 'Content-Disposition' => qq{attachment; filename="feed.ics"});
|
||||
$self->session->response->content_type("text/calendar");
|
||||
return $ical;
|
||||
#$self->session->http->setMimeType("text/plain");
|
||||
$self->session->http->setFilename("feed.ics","text/calendar");
|
||||
return $ical->as_string;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -48,6 +48,20 @@ property items => (
|
|||
noFormPost => 1,
|
||||
fieldType => 'text',
|
||||
);
|
||||
property autoPlay => (
|
||||
fieldType => 'yesNo',
|
||||
defaultValue => 0,
|
||||
tab => "properties",
|
||||
hoverHelp => ['carousel autoPlay description', 'Asset_Carousel' ],
|
||||
label => ['carousel autoPlay label', 'Asset_Carousel' ],
|
||||
);
|
||||
property autoPlayInterval => (
|
||||
fieldType => 'Integer',
|
||||
defaultValue => 4,
|
||||
tab => 'properties',
|
||||
hoverHelp => ['carousel autoPlayInterval description', 'Asset_Carousel'],
|
||||
label => ['carousel autoPlayInterval label', 'Asset_Carousel'],
|
||||
);
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -63,16 +77,30 @@ override getEditForm => sub {
|
|||
my $tabform = super();
|
||||
my $i18n = WebGUI::International->new($self->session, "Asset_Carousel");
|
||||
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/editor/editor-min.js'));
|
||||
$self->session->style->setCss($self->session->url->extras('yui/build/editor/assets/skins/sam/editor.css'));
|
||||
$self->session->style->setScript($self->session->url->extras('wobject/Carousel/carousel.js'));
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'), {type =>
|
||||
'text/javascript'});
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/element/element-min.js'), {type =>
|
||||
'text/javascript'});
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/tabview/tabview-min.js'), {type =>
|
||||
'text/javascript'});
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/editor/editor-min.js'), {type =>
|
||||
'text/javascript'});
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/json/json-min.js'), {type =>
|
||||
'text/javascript'});
|
||||
$self->session->style->setLink($self->session->url->extras('yui/build/editor/assets/skins/sam/editor.css'), {type
|
||||
=>'text/css', rel=>'stylesheet'});
|
||||
$self->session->style->setLink($self->session->url->extras('yui/build/tabview/assets/skins/sam/tabview.css'), {type
|
||||
=>'text/css', rel=>'stylesheet'});
|
||||
$self->session->style->setScript($self->session->url->extras('wobject/Carousel/carousel.js'), {type =>
|
||||
'text/javascript'});
|
||||
|
||||
my $tableRowStart =
|
||||
'<tr id="items_row">'
|
||||
.' <td class="formDescription" valign="top" style="width: 180px;"><label for="item1">'
|
||||
.$i18n->get("items label").'</label><div class="wg-hoverhelp">'.$i18n->get("items description").'</div></td>'
|
||||
.' <td id="items_td" valign="top" class="tableData">'
|
||||
.' <input type="button" value="Add item" onClick="javascript:addItem()"></input><br />'
|
||||
.' <input type="hidden" id="items_formId" name="items" />'
|
||||
.' <input type="button" value="Add item" onclick="window.carouselEditor.addTab()"></input><br />'
|
||||
." <br />\n";
|
||||
|
||||
$tabform->getTab("properties")->addField('ReadOnly', value => $tableRowStart);
|
||||
|
|
@ -122,6 +150,27 @@ onClick='javascript:deleteItem(this.id)'></input>\n"
|
|||
."</script>\n";
|
||||
$tabform->getTab("properties")->addField('ReadOnly', value => $itemHTML);
|
||||
}
|
||||
|
||||
|
||||
$self->session->log->warn('richedit:' .$self->get('richEditor'));
|
||||
my $richEditId = $self->get('richEditor') || "PBrichedit000000000001";
|
||||
my $richedit = WebGUI::Asset->newById( $self->session, $richEditId );
|
||||
my $config = JSON->new->encode( $richedit->getConfig );
|
||||
my $loadMcePlugins = $richedit->getLoadPlugins;
|
||||
my $items = $self->get('items') ? JSON->new->decode($self->get('items'))->{items} : [];
|
||||
$items = JSON->new->encode( $items );
|
||||
my $i18nJson = JSON->new->encode( { "delete" => $i18n->get("delete") } );
|
||||
|
||||
$tabform->getTab('properties')->raw(<<"ENDHTML");
|
||||
<div id="carouselEditor"></div>
|
||||
<script type="text/javascript">
|
||||
$loadMcePlugins
|
||||
YAHOO.util.Event.onDOMReady( function() {
|
||||
window.carouselEditor = new WebGUI.Carousel.Editor( "carouselEditor", $config, $items, $i18nJson );
|
||||
} );
|
||||
</script>
|
||||
ENDHTML
|
||||
|
||||
my $tableRowEnd = qq|
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -165,32 +214,9 @@ Used to process properties from the form posted.
|
|||
override processEditForm => sub {
|
||||
my $self = shift;
|
||||
my $form = $self->session->form;
|
||||
my (@items,$items);
|
||||
super();
|
||||
|
||||
foreach my $param ($form->param) {
|
||||
if ($param =~ m/^item_/){
|
||||
my $sequenceNumber = $param;
|
||||
$sequenceNumber =~ s/^item_//;
|
||||
if($form->process('itemId_'.$sequenceNumber)){
|
||||
push(@items,{
|
||||
sequenceNumber => $sequenceNumber,
|
||||
text => $form->process($param),
|
||||
itemId => $form->process('itemId_'.$sequenceNumber),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my @sortedItems = sort { $a->{sequenceNumber} cmp $b->{sequenceNumber} } @items;
|
||||
@items = ();
|
||||
for (my $i=0; $i<scalar @sortedItems; $i++) {
|
||||
$sortedItems[$i]->{sequenceNumber} = $i + 1;
|
||||
push(@items,$sortedItems[$i]);
|
||||
}
|
||||
|
||||
$items = JSON->new->encode({items => \@items});
|
||||
$self->update({items => $items});
|
||||
my $items = JSON->new->decode( $form->get("items") );
|
||||
$self->update({ items => JSON->new->encode({ items => $items }) });
|
||||
return undef;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -879,19 +879,19 @@ override commit => sub {
|
|||
unless (defined $cron) {
|
||||
$cron = WebGUI::Workflow::Cron->create($self->session, {
|
||||
title=>$self->getTitle." ".$i18n->get("mail"),
|
||||
minuteOfHour=>"*/".($self->getMailInterval/60),
|
||||
className=>(ref $self),
|
||||
methodName=>"new",
|
||||
parameters=>$self->getId,
|
||||
workflowId=>"csworkflow000000000001"
|
||||
workflowId=>"csworkflow000000000001",
|
||||
$self->getCronIntervals,
|
||||
});
|
||||
$self->update({getMailCronId=>$cron->getId});
|
||||
}
|
||||
if ($self->getMail) {
|
||||
$cron->set({enabled=>1,title=>$self->getTitle." ".$i18n->get("mail"), minuteOfHour=>"*/".($self->getMailInterval/60)});
|
||||
} else {
|
||||
$cron->set({enabled=>0,title=>$self->getTitle." ".$i18n->get("mail"), minuteOfHour=>"*/".($self->getMailInterval/60)});
|
||||
}
|
||||
$cron->set({
|
||||
enabled => $self->get('getMail') ? 1 : 0,
|
||||
title => $self->getTitle." ".$i18n->get("mail"),
|
||||
$self->getCronIntervals(),
|
||||
});
|
||||
};
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -931,11 +931,11 @@ sub duplicate {
|
|||
my $i18n = WebGUI::International->new($self->session, "Asset_Collaboration");
|
||||
my $newCron = WebGUI::Workflow::Cron->create($self->session, {
|
||||
title=>$self->getTitle." ".$i18n->get("mail"),
|
||||
minuteOfHour=>"*/".($self->get("getMailInterval")/60),
|
||||
className=>(ref $self),
|
||||
methodName=>"new",
|
||||
parameters=>$self->getId,
|
||||
workflowId=>"csworkflow000000000001"
|
||||
workflowId=>"csworkflow000000000001",
|
||||
$self->getCronIntervals(),
|
||||
});
|
||||
$newAsset->update({getMailCronId=>$newCron->getId});
|
||||
$newAsset->incrementReplies('','');
|
||||
|
|
@ -959,6 +959,87 @@ sub duplicateBranch {
|
|||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getCronIntervals
|
||||
|
||||
Translate the settings for getCsMailInterval into options for Spectre's Cron,
|
||||
minuteOfHour, hourOfDay and so on.
|
||||
|
||||
Returns a hash of those options that can be folded into a hash of property settings for the
|
||||
Cron job.
|
||||
|
||||
=cut
|
||||
|
||||
sub getCronIntervals {
|
||||
my $self = shift;
|
||||
my $interval = $self->get('getMailInterval');
|
||||
##My kingdom for a switch statement!
|
||||
if ($interval eq 'every minute') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/1',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every other minute') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/2',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every 5 minutes') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/5',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every 10 minutes') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/10',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every 15 minutes') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/15',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every 20 minutes') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/20',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every 30 minutes') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '*/30',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every hour') {
|
||||
return(
|
||||
hourOfDay => '*',
|
||||
minuteOfHour => '0',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'every other hour') {
|
||||
return(
|
||||
hourOfDay => '*/2',
|
||||
minuteOfHour => '0',
|
||||
);
|
||||
}
|
||||
elsif ($interval eq 'once per day') {
|
||||
return(
|
||||
hourOfDay => '7',
|
||||
minuteOfHour => '0',
|
||||
);
|
||||
}
|
||||
return(
|
||||
minuteOfHour => '*/10',
|
||||
);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getHelpers ( )
|
||||
|
||||
Add the collaboration-specific asset helpers
|
||||
|
|
@ -1282,6 +1363,35 @@ sub getViewTemplateVars {
|
|||
return \%var;
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
=head2 groupIdView ( [newvalue] )
|
||||
|
||||
Override the existing accessor to update the subscription group if the value
|
||||
changes.
|
||||
|
||||
=cut
|
||||
|
||||
around groupIdView => sub {
|
||||
my $orig = shift;
|
||||
my $self = shift;
|
||||
my ( $newValue ) = @_;
|
||||
my $oldValue = $self->$orig;
|
||||
my $return = $self->$orig(@_);
|
||||
# Update the subscription group so if they can't see the collab, they don't get e-mailed
|
||||
if ( $newValue && $newValue != $oldValue ) {
|
||||
my $instance_data = {
|
||||
workflowId => 'xR-_GRRbjBojgLsFx3dEMA',
|
||||
className => 'WebGUI::Asset',
|
||||
methodName => 'newById',
|
||||
parameters => $self->getId,
|
||||
};
|
||||
my $instance = WebGUI::Workflow::Instance->create($self->session, $instance_data);
|
||||
$instance->start('skipRealtime');
|
||||
}
|
||||
return $return;
|
||||
};
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 incrementReplies ( lastPostDate, lastPostId )
|
||||
|
|
@ -1586,7 +1696,6 @@ sub unsubscribe {
|
|||
$group->deleteUsers([$user->userId]);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 view
|
||||
|
|
|
|||
|
|
@ -320,13 +320,17 @@ override purge => sub {
|
|||
|
||||
=head2 view
|
||||
|
||||
Render the dashboard.
|
||||
Render the dashboard. Of all the positions for content, position1 is reserved for hidden content
|
||||
or content to be placed. Deleting content causes it to go into position1.
|
||||
|
||||
=cut
|
||||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my %vars = %{$self->get()};
|
||||
$vars{canEdit} = $self->canEdit;
|
||||
$vars{fullUrl} = $self->getUrl;
|
||||
|
||||
$self->session->style->setScript( $self->session->url->extras('yui/build/utilities/utilities.js'));
|
||||
|
||||
|
|
@ -356,60 +360,85 @@ sub view {
|
|||
|
||||
my @found;
|
||||
my $newStuff;
|
||||
my $showPerformance = $self->session->log->performanceLogger();
|
||||
my $user = $self->session->user;
|
||||
foreach my $position (@positions) {
|
||||
my @assets = split(",",$position);
|
||||
foreach my $asset (@assets) {
|
||||
foreach my $child (@{$children}) {
|
||||
CHILD: foreach my $child (@{$children}) {
|
||||
if ($asset eq $child->getId) {
|
||||
unless ($asset ~~ @hidden || !$child->canView) {
|
||||
$self->session->style->setRawHeadTags($child->getExtraHeadTags);
|
||||
$child->{_properties}{title} = $child->getTitle;
|
||||
$child->{_properties}{title} = $child->getShortcut->getTitle if (ref $child eq 'WebGUI::Asset::Shortcut');
|
||||
if ($i == 1 || $i > $numPositions) {
|
||||
push(@{$vars{"position1_loop"}},{
|
||||
id=>$child->getId,
|
||||
content=>'', #so things in the New Content bar don't display.
|
||||
dashletTitle=>$child->{_properties}{title},
|
||||
shortcutUrl=>$child->getUrl,
|
||||
canPersonalize=>$self->canPersonalize,
|
||||
showReloadIcon=>$child->{_properties}{showReloadIcon},
|
||||
canEditUserPrefs=>(($self->session->user->isRegistered) && (ref $child eq 'WebGUI::Asset::Shortcut') && (scalar($child->getPrefFieldsToShow) > 0))
|
||||
});
|
||||
$newStuff .= 'available_dashlets["'.$child->getId.'"]=\''.$child->getUrl.'\';';
|
||||
|
||||
} else {
|
||||
$child->prepareView;
|
||||
push(@{$vars{"position".$i."_loop"}},{
|
||||
id=>$child->getId,
|
||||
content=>$child->view,
|
||||
dashletTitle=>$child->{_properties}{title},
|
||||
shortcutUrl=>$child->getUrl,
|
||||
canPersonalize=>$self->canPersonalize,
|
||||
showReloadIcon=>$child->{_properties}{showReloadIcon},
|
||||
canEditUserPrefs=>(($self->session->user->isRegistered) && (ref $child eq 'WebGUI::Asset::Shortcut') && (scalar($child->getPrefFieldsToShow) > 0))
|
||||
});
|
||||
$newStuff .= 'available_dashlets["'.$child->getId.'"]=\''.$child->getUrl.'\';';
|
||||
}
|
||||
}
|
||||
push(@found, $child->getId);
|
||||
}
|
||||
##Filter based on visibility
|
||||
next CHILD unless $child->canView;
|
||||
next CHILD if isIn($asset, @hidden);
|
||||
##Detect child types
|
||||
my $is_shortcut = $child->isa('WebGUI::Asset::Shortcut');
|
||||
my $is_dashlet = $child->can('getOverrideFormDefinition');
|
||||
$self->session->style->setRawHeadTags($child->getExtraHeadTags);
|
||||
##Override the title for shortcuts
|
||||
if ($is_shortcut) {
|
||||
$child->{_properties}{title} = $child->getShortcut->getTitle;
|
||||
}
|
||||
##Fetch dashlet options from the database
|
||||
my $options = $session->db->quickHashRef('select * from Dashboard_dashlets where dashboardAssetId=? and dashletAssetId=?', [$self->getId, $child->getId]);
|
||||
if (!($i == 1 || $i > $numPositions)) {
|
||||
$child->prepareView;
|
||||
}
|
||||
my $spot = $i > $numPositions ? 1 : $i;
|
||||
my $canMove = $self->canPersonalize && !$options->{isStatic};
|
||||
my $editFormUrl = ($is_shortcut && $child->getPrefsFieldToShow) ? $child->getUrl('func=getUserPrefsForm')
|
||||
: ($is_dashlet && $child->getOverrideFormDefinition) ? $self->getUrl('func=customizeDashlet;dashletAssetId='.$child->getId)
|
||||
: ''
|
||||
;
|
||||
my $canEditUserPrefs = $user->isRegistered && $editFormUrl;
|
||||
|
||||
push(@{$vars{"position".$spot."_loop"}},{
|
||||
id => $child->getId,
|
||||
content => $child->view,
|
||||
dashletTitle => $child->get('title'),
|
||||
shortcutUrl => ($is_shortcut ? $child->getUrl : ''),
|
||||
editFormUrl => $editFormUrl,
|
||||
dashletUrl => ($is_dashlet ? $child->getUrl : ''),
|
||||
canDelete => $self->canPersonalize && !$options->{isRequired},
|
||||
canMove => $canMove,
|
||||
canPersonalize => $self->canPersonalize,
|
||||
showReloadIcon => $is_shortcut && $child->get('showReloadIcon'),
|
||||
canEditUserPrefs => $canEditUserPrefs,
|
||||
});
|
||||
if ($canMove) {
|
||||
$newStuff .= 'available_dashlets["'.$child->getId.'"]=\''.$child->getUrl.'\';';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
# deal with unplaced children
|
||||
# deal with unplaced children, they go into position 1
|
||||
foreach my $child (@{$children}) {
|
||||
unless ($child->getId ~~ @found || $child->getId ~~ @hidden) {
|
||||
if ($child->canView) {
|
||||
$child->{_properties}{title} = $child->getShortcut->title if (ref $child eq 'WebGUI::Asset::Shortcut');
|
||||
my $is_shortcut = $child->isa('WebGUI::Asset::Shortcut');
|
||||
my $is_dashlet = $child->can('getOverrideFormDefinition');
|
||||
my $title = $child->{_properties}{title} = $is_shortcut ? $child->getShortcut->getTitle : $child->getTitle;
|
||||
my $options = $session->db->quickHashRef('select * from Dashboard_dashlets where dashboardAssetId=? and dashletAssetId=?', [$self->getId, $child->getId]);
|
||||
my $canMove = $self->canPersonalize && !$options->{isStatic};
|
||||
my $editFormUrl = ($is_shortcut && $child->getPrefFieldsToShow) ? $child->getUrl('func=getUserPrefsForm')
|
||||
: ($is_dashlet && $child->getOverrideFormDefinition) ? $self->getUrl('func=customizeDashlet;dashletAssetId='.$child->getId)
|
||||
: ''
|
||||
;
|
||||
my $canEditUserPrefs = $user->isRegistered && $editFormUrl;
|
||||
push(@{$vars{"position1_loop"}},{
|
||||
id=>$child->getId,
|
||||
content=>'',
|
||||
dashletTitle=>$child->getTitle,
|
||||
shortcutUrl=>$child->getUrl,
|
||||
showReloadIcon=>$child->{_properties}{showReloadIcon},
|
||||
canPersonalize=>$self->canPersonalize,
|
||||
canEditUserPrefs=>(($self->session->user->isRegistered) && (ref $child eq 'WebGUI::Asset::Shortcut') && (scalar($child->getPrefFieldsToShow) > 0))
|
||||
id => $child->getId,
|
||||
content => '',
|
||||
dashletTitle => $title,
|
||||
shortcutUrl => ($is_shortcut ? $child->getUrl : ''),
|
||||
editFormUrl => $editFormUrl,
|
||||
dashletUrl => ($is_dashlet ? $child->getUrl : ''),
|
||||
canDelete => $self->canPersonalize && !$options->{isRequired},
|
||||
canMove => $canMove,
|
||||
canPersonalize => $self->canPersonalize,
|
||||
showReloadIcon => $is_shortcut && $child->{_properties}{showReloadIcon},
|
||||
canEditUserPrefs => $canEditUserPrefs,
|
||||
});
|
||||
$newStuff .= 'available_dashlets["'.$child->getId.'"]=\''.$child->getUrl.'\';';
|
||||
}
|
||||
|
|
@ -418,9 +447,9 @@ sub view {
|
|||
$vars{showAdmin} = ($self->session->isAdminOn && $self->canEdit);
|
||||
$vars{"dragger.init"} = '
|
||||
<script type="text/javascript">
|
||||
dragable_init("'.$self->getUrl.'");
|
||||
var available_dashlets= new Array();
|
||||
'.$newStuff.'
|
||||
dragable_init("'.$self->getUrl.'");
|
||||
</script>
|
||||
';
|
||||
return $self->processTemplate(\%vars, $templateId);
|
||||
|
|
@ -428,6 +457,128 @@ sub view {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_customizeDashlet
|
||||
|
||||
Web facing method for saving per dashlet configuration, such as being required, or movable.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_customizeDashlet {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient() unless ($session->user->isRegistered);
|
||||
my $dashletAssetId = $session->form->get('dashletAssetId');
|
||||
my $dashlet = WebGUI::Asset->newById($session, $dashletAssetId);
|
||||
return $session->privilege->insufficient() unless ($dashlet && $dashlet->canView && $dashlet->can('getOverrideFormDefinition'));
|
||||
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Dashboard');
|
||||
|
||||
my $form = $session->form;
|
||||
my $html_form = WebGUI::HTMLForm->new($session, action => $self->getUrl, method => 'POST', );
|
||||
$html_form->hidden(name => 'func', value => 'customizeDashletSave', );
|
||||
$html_form->hidden(name => 'dashletAssetId', value => $dashletAssetId, );
|
||||
$html_form->readOnly(name => $i18n->get(), value => $dashlet->getTitle, );
|
||||
|
||||
my $overrides = $dashlet->fetchUserOverrides($self->getId);
|
||||
my @dashlet_properties = $dashlet->getOverrideFormDefinition;
|
||||
foreach my $property (@dashlet_properties) {
|
||||
my %properties = %{ $property };
|
||||
$properties{value} = $overrides->{$property->{name}} || $dashlet->get($property->{name});
|
||||
$html_form->dynamicField(%properties);
|
||||
}
|
||||
|
||||
$html_form->submit();
|
||||
return $html_form->print;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_customizeDashletSave
|
||||
|
||||
Web facing method for saving per dashlet configuration, such as being required, or movable.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_customizeDashletSave {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient() unless ($session->user->isRegistered);
|
||||
my $dashletAssetId = $session->form->get('dashletAssetId');
|
||||
my $dashlet = WebGUI::Asset->newById($session, $dashletAssetId);
|
||||
return $session->privilege->insufficient() unless ($dashlet && $dashlet->canView && $dashlet->can('getOverrideFormDefinition'));
|
||||
my $overrides = {};
|
||||
my @dashlet_properties = $dashlet->getOverrideFormDefinition;
|
||||
my $form = $session->form;
|
||||
foreach my $property (@dashlet_properties) {
|
||||
my $value = $form->process($property->{name}, $property->{fieldType}, $property->{value});
|
||||
$overrides->{$property->{name}} = $value;
|
||||
}
|
||||
$dashlet->storeUserOverrides($self->getId, $overrides);
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
##-------------------------------------------------------------------
|
||||
|
||||
=head2 www_editDashlet
|
||||
|
||||
Web facing method for saving per dashlet configuration, such as being required, or movable.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_editDashlet {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient() unless ($self->canEdit);
|
||||
my $dashletAssetId = $session->form->get('dashletAssetId');
|
||||
my $dashlet = WebGUI::Asset->newById($session, $dashletAssetId);
|
||||
return $session->privilege->insufficient() unless ($dashletAssetId);
|
||||
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Dashboard');
|
||||
|
||||
my $form = $session->form;
|
||||
my $html_form = WebGUI::HTMLForm->new($session, action => $self->getUrl, method => 'POST', );
|
||||
$html_form->hidden(name => 'func', value => 'editDashletSave', );
|
||||
$html_form->hidden(name => 'dashletAssetId', value => $dashletAssetId, );
|
||||
$html_form->readOnly(name => $i18n->get(), value => $dashlet->getTitle, );
|
||||
my $options = $session->db->quickHashRef('select * from Dashboard_dashlets where dashboardAssetId=? and dashletAssetId=?', [$self->getId, $dashletAssetId]);
|
||||
$html_form->yesNo(
|
||||
name => 'isStatic',
|
||||
label => $i18n->get('Is static'),
|
||||
hoverHelp => $i18n->get('Is static help'),
|
||||
value => $form->get('isStatic') || $options->{isStatic},
|
||||
);
|
||||
$html_form->yesNo(
|
||||
name => 'isRequired',
|
||||
label => $i18n->get('Is required'),
|
||||
hoverHelp => $i18n->get('Is required help'),
|
||||
value => $form->get('isRequired') || $options->{isRequired},
|
||||
);
|
||||
$html_form->submit();
|
||||
return $html_form->print;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_editDashletSave
|
||||
|
||||
Web facing method for saving per dashlet configuration, such as being required, or movable.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_editDashletSave {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient() unless ($self->canEdit);
|
||||
my $dashletAssetId = $session->form->get('dashletAssetId');
|
||||
my $isStatic = $session->form->get('isStatic', 'yesNo');
|
||||
my $isRequired = $session->form->get('isRequired', 'yesNo');
|
||||
$session->db->write('DELETE FROM Dashboard_dashlets where dashboardAssetId=? and dashletAssetId=?',[$self->getId, $dashletAssetId, ]);
|
||||
$session->db->write('INSERT INTO Dashboard_dashlets (dashboardAssetId, dashletAssetId, isStatic, isRequired) VALUES (?,?,?,?)', [$self->getId, $dashletAssetId, $isStatic, $isRequired, ]);
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_setContentPositions
|
||||
|
||||
Web method for saving the positions of dashlets in the dashboard.
|
||||
|
|
|
|||
|
|
@ -320,12 +320,13 @@ sub _fieldAdminIcons {
|
|||
my $self = shift;
|
||||
my $fieldName = shift;
|
||||
my $i18n = WebGUI::International->new($self->session,"Asset_DataForm");
|
||||
my $mode = ";mode=" . $self->currentView;
|
||||
my $output;
|
||||
$output = $self->session->icon->delete('func=deleteFieldConfirm;fieldName='.$fieldName,$self->url,$i18n->get(19))
|
||||
$output = $self->session->icon->delete('func=deleteFieldConfirm;fieldName='.$fieldName.$mode,$self->get("url"),$i18n->get(19))
|
||||
unless $self->getFieldConfig($fieldName)->{isMailField};
|
||||
$output .= $self->session->icon->edit('func=editField;fieldName='.$fieldName,$self->url)
|
||||
. $self->session->icon->moveUp('func=moveFieldUp;fieldName='.$fieldName,$self->url)
|
||||
. $self->session->icon->moveDown('func=moveFieldDown;fieldName='.$fieldName,$self->url);
|
||||
$output .= $self->session->icon->edit('func=editField;fieldName='.$fieldName.$mode,$self->get("url"))
|
||||
. $self->session->icon->moveUp('func=moveFieldUp;fieldName='.$fieldName.$mode,$self->get("url"))
|
||||
. $self->session->icon->moveDown('func=moveFieldDown;fieldName='.$fieldName.$mode,$self->get("url"));
|
||||
return $output;
|
||||
}
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -784,6 +785,7 @@ sub getListTemplateVars {
|
|||
'field.label' => $fieldConfig->{$_}{label},
|
||||
'field.isMailField' => $fieldConfig->{$_}{isMailField},
|
||||
'field.type' => $fieldConfig->{$_}{type},
|
||||
"field.controls" => $self->_fieldAdminIcons($fieldConfig->{$_}{name}),
|
||||
}
|
||||
} @{ $self->getFieldOrder };
|
||||
$var->{field_loop} = \@fieldLoop;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ Overridden to check the revision dates of children as well
|
|||
|
||||
sub getContentLastModified {
|
||||
my $self = shift;
|
||||
my $mtime = $self->revisionDate;
|
||||
my $mtime = $self->get("lastModified");
|
||||
my $childIter = $self->getLineageIterator(["children"]);
|
||||
while ( 1 ) {
|
||||
my $child;
|
||||
|
|
@ -119,6 +119,60 @@ sub getContentLastModified {
|
|||
return $mtime;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getContentLastModifiedBy
|
||||
|
||||
Overridden to check the updated dates of children as well
|
||||
|
||||
=cut
|
||||
|
||||
sub getContentLastModifiedBy {
|
||||
my $self = shift;
|
||||
my $mtime = $self->SUPER::getContentLastModified;
|
||||
my $userId = $self->get('revisedBy');
|
||||
my $childIter = $self->getLineageIterator(["children"]);
|
||||
while ( 1 ) {
|
||||
my $child;
|
||||
eval { $child = $childIter->() };
|
||||
if ( my $x = WebGUI::Error->caught('WebGUI::Error::ObjectNotFound') ) {
|
||||
$self->session->log->error($x->full_message);
|
||||
next;
|
||||
}
|
||||
last unless $child;
|
||||
my $child_mtime = $child->getContentLastModified;
|
||||
if ($child_mtime > $mtime) {
|
||||
$mtime = $child_mtime;
|
||||
$userId = $child->get("revisedBy");
|
||||
}
|
||||
}
|
||||
return $userId;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=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_Folder");
|
||||
if ($self->get("assetId") eq "new") {
|
||||
$tabform->getTab("properties")->whatNext(
|
||||
-options=>{
|
||||
view=>$i18n->get(823),
|
||||
"viewParent"=>$i18n->get(847)
|
||||
},
|
||||
-value=>"view"
|
||||
);
|
||||
}
|
||||
return $tabform;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getTemplateVars ( )
|
||||
|
|
|
|||
|
|
@ -363,6 +363,36 @@ override getContentLastModified => sub {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getContentLastModifiedBy
|
||||
|
||||
Extend the base class to include the userid of the person that made last modification.
|
||||
|
||||
=cut
|
||||
|
||||
sub getContentLastModifiedBy {
|
||||
my $self = shift;
|
||||
my $mtime = $self->SUPER::getContentLastModified;
|
||||
my $userId = $self->get('revisedBy');
|
||||
my $childIter = $self->getLineageIterator(["children"],{excludeClasses=>['WebGUI::Asset::Wobject::Layout']});
|
||||
while ( 1 ) {
|
||||
my $child;
|
||||
eval { $child = $childIter->() };
|
||||
if ( my $x = WebGUI::Error->caught('WebGUI::Error::ObjectNotFound') ) {
|
||||
$self->session->log->error($x->full_message);
|
||||
next;
|
||||
}
|
||||
last unless $child;
|
||||
my $child_mtime = $child->getContentLastModified;
|
||||
if ($child_mtime > $mtime) {
|
||||
$mtime = $child_mtime;
|
||||
$userId = $child->get("revisedBy");
|
||||
}
|
||||
}
|
||||
return $userId;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_view
|
||||
|
||||
Extend the base method to handle caching and ad rotation.
|
||||
|
|
|
|||
|
|
@ -371,7 +371,9 @@ sub view {
|
|||
google.setOnLoadCallback( function() {
|
||||
var mapId = "%s";
|
||||
var mapUrl = "%s";
|
||||
var map = new GMap2( document.getElementById("map_" + mapId) );
|
||||
var element = document.getElementById("map_" + mapId);
|
||||
var map = new GMap2( element );
|
||||
element.mapObject = map;
|
||||
map.url = mapUrl;
|
||||
map.assetId = mapId;
|
||||
map.setCenter(new GLatLng(%s, %s), %s);
|
||||
|
|
@ -379,6 +381,10 @@ sub view {
|
|||
map.extrasUrl = "%s";
|
||||
|
||||
var markermanager = new MarkerManager(map, {trackMarkers: true});
|
||||
map.markermanager = markermanager;
|
||||
map.fancyClickHandler = null;
|
||||
map.panOnClick = true;
|
||||
map.clickToEdit = false;
|
||||
ENDHTML
|
||||
|
||||
|
||||
|
|
@ -392,9 +398,9 @@ ENDHTML
|
|||
for my $pointId ( @{$pointIds} ) {
|
||||
my $point = WebGUI::Asset->newById( $session, $pointId );
|
||||
next unless $point;
|
||||
$mapHtml .= sprintf ' points.push(%s);'."\n",
|
||||
JSON->new->encode($point->getMapInfo),
|
||||
;
|
||||
my $buffer = JSON->new->encode( $point->getMapInfo );
|
||||
|
||||
$mapHtml .= sprintf ' points.push(%s);'."\n", $buffer;
|
||||
|
||||
push @{$var->{ mapPoints }}, $point->getTemplateVars;
|
||||
}
|
||||
|
|
@ -416,11 +422,11 @@ ENDHTML
|
|||
}
|
||||
|
||||
# Script to control addPoint and setPoint buttons
|
||||
$mapHtml .= <<'ENDHTML';
|
||||
$mapHtml .= sprintf <<'ENDHTML', $self->getUrl;
|
||||
if ( document.getElementById( "setCenter_" + mapId ) ) {
|
||||
var button = document.getElementById( "setCenter_" + mapId );
|
||||
GEvent.addDomListener( button, "click", function () {
|
||||
WebGUI.Map.setCenter( map );
|
||||
WebGUI.Map.setCenter( map, '%s' );
|
||||
} );
|
||||
}
|
||||
if ( document.getElementById( "addPoint_" + mapId ) ) {
|
||||
|
|
|
|||
|
|
@ -175,30 +175,31 @@ sub view {
|
|||
);
|
||||
|
||||
my @results = ();
|
||||
foreach my $data (@{$p->getPageData}) {
|
||||
next unless (
|
||||
ENTRY: foreach my $data (@{$p->getPageData}) {
|
||||
next ENTRY unless (
|
||||
$user->userId eq $data->{ownerUserId}
|
||||
|| $user->isInGroup($data->{groupIdView})
|
||||
|| $user->isInGroup($data->{groupIdEdit})
|
||||
);
|
||||
|
||||
my $asset = WebGUI::Asset->newById($session, $data->{assetId});
|
||||
if (defined $asset) {
|
||||
my $properties = $asset->get;
|
||||
if ($self->useContainers) {
|
||||
$properties->{url} = $asset->isa('WebGUI::Asset::Post::Thread') ? $asset->getCSLinkUrl()
|
||||
: $asset->getContainer->url;
|
||||
}
|
||||
#Add highlighting
|
||||
$properties->{'title' } = $hl->highlight($properties->{title} || '');
|
||||
$properties->{'title_nohighlight' } = $properties->{title};
|
||||
my $synopsis = $data->{'synopsis'} || '';
|
||||
WebGUI::Macro::process($self->session, \$synopsis);
|
||||
$properties->{'synopsis' } = $hl->highlight($synopsis);
|
||||
$properties->{'synopsis_nohighlight'} = $synopsis;
|
||||
push(@results, $properties);
|
||||
$var{results_found} = 1;
|
||||
}
|
||||
next ENTRY unless defined $asset;
|
||||
my $properties = $asset->get;
|
||||
##Overlay the asset properties with the original data to handle sub-entries for assets
|
||||
$properties = { %{ $properties }, %{ $data} };
|
||||
if ( $self->get("useContainers") && $asset->getContainer->canView ) {
|
||||
$properties->{url} = $asset->isa('WebGUI::Asset::Post::Thread') ? $asset->getCSLinkUrl()
|
||||
: $asset->getContainer->get("url");
|
||||
}
|
||||
#Add highlighting
|
||||
$properties->{'title' } = $hl->highlight($properties->{title} || '');
|
||||
$properties->{'title_nohighlight' } = $properties->{title};
|
||||
my $synopsis = $properties->{'synopsis'} || '';
|
||||
WebGUI::Macro::process($self->session, \$synopsis);
|
||||
$properties->{'synopsis' } = $hl->highlight($synopsis);
|
||||
$properties->{'synopsis_nohighlight'} = $synopsis;
|
||||
push(@results, $properties);
|
||||
$var{results_found} = 1;
|
||||
}
|
||||
|
||||
$var{result_set} = \@results;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use Number::Format ();
|
|||
use Moose;
|
||||
use WebGUI::Definition::Asset;
|
||||
extends 'WebGUI::Asset::Wobject';
|
||||
with 'WebGUI::Role::Asset::Dashlet';
|
||||
define tableName => 'StockData';
|
||||
define icon => 'stockData.gif';
|
||||
define assetName => ["assetName", 'Asset_StockData'];
|
||||
|
|
@ -45,6 +46,7 @@ property defaultStocks => (
|
|||
tab => 'properties',
|
||||
label => ["default_stock_label", 'Asset_StockData'],
|
||||
hoverHelp => ["default_stock_label_description", 'Asset_StockData'],
|
||||
dashletOverridable => 1,
|
||||
);
|
||||
property source => (
|
||||
fieldType => "selectList",
|
||||
|
|
@ -208,9 +210,12 @@ sub _convertToEpoch {
|
|||
if($time =~ m/pm/i) {
|
||||
$hour += 12;
|
||||
}
|
||||
$hour ||= 0;
|
||||
$hour = $self->_appendZero($hour);
|
||||
$minute ||= 0;
|
||||
$minute = $self->_appendZero($minute);
|
||||
return $self->session->datetime->humanToEpoch("$year-$month-$day $hour:$minute:00");
|
||||
my $epoch = eval {$self->session->datetime->humanToEpoch("$year-$month-$day $hour:$minute:00")};
|
||||
return $epoch;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -226,21 +231,45 @@ List of stock symbols to find passed in as an array reference. Stock symbols sh
|
|||
=cut
|
||||
|
||||
sub _getStocks {
|
||||
my $self = shift;
|
||||
my $stocks = $_[0];
|
||||
my $self = shift;
|
||||
my $stocks = $_[0];
|
||||
my $session = $self->session;
|
||||
|
||||
# Create a new Finance::Quote object
|
||||
my $q = Finance::Quote->new;
|
||||
# Disable failover if specified
|
||||
unless ($self->failover) {
|
||||
$q->failover(0);
|
||||
}
|
||||
# Create a new Finance::Quote object
|
||||
my $q = Finance::Quote->new;
|
||||
# Disable failover if specified
|
||||
unless ($self->failover) {
|
||||
$q->failover(0);
|
||||
}
|
||||
# Hardcoded timeout for now.
|
||||
$q->timeout(15);
|
||||
|
||||
# Hardcoded timeout for now.
|
||||
$q->timeout(15);
|
||||
my $source = $self->source;
|
||||
my %stocks = ();
|
||||
my @stocks_to_fetch = ();
|
||||
STOCK: foreach my $stock (@{$stocks}) {
|
||||
$stock = uc $stock;
|
||||
my $value = $session->cache->get( join "", $self->getId, $source, $stock );
|
||||
if ($value) {
|
||||
%stocks = (%stocks, %{ $value });
|
||||
}
|
||||
else {
|
||||
push @stocks_to_fetch, $stock;
|
||||
}
|
||||
}
|
||||
|
||||
# Fetch the stock information and return the results
|
||||
return $q->fetch($self->source,@{$stocks});
|
||||
# Fetch the information for uncached stocks, cache them individually, and build the composite data.
|
||||
my %new_stocks = $q->fetch($source, @stocks_to_fetch);
|
||||
foreach my $stock (@stocks_to_fetch) {
|
||||
$stock = uc $stock;
|
||||
my @stock_keys = grep { /$stock\b/ } keys %new_stocks;
|
||||
my %slice;
|
||||
@slice{ @stock_keys } = @new_stocks{ @stock_keys };
|
||||
$slice{$stock,'last_fetch'} = time();
|
||||
$session->cache->set( join( "", $self->getId, $source, $stock ), \%slice, $self->get('cacheTimeout') );
|
||||
%stocks = (%stocks, %slice);
|
||||
}
|
||||
return \%stocks;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -330,7 +359,8 @@ sub view {
|
|||
$var->{'stock.display.url'} = $self->getUrl("func=displayStock;symbol=");
|
||||
|
||||
#Build list of stocks as an array
|
||||
my $defaults = $self->defaultStocks;
|
||||
my $overrides = $self->fetchUserOverrides($self->getParent->getId);
|
||||
my $defaults = $overrides->{defaultStocks} || $self->defaultStocks;
|
||||
#replace any windows newlines
|
||||
$defaults =~ s/\r//;
|
||||
my @array = split("\n",$defaults);
|
||||
|
|
|
|||
|
|
@ -171,38 +171,48 @@ sub viewTemplateVariables {
|
|||
rowsPerPage => $numberOfStories,
|
||||
});
|
||||
my $storyIds = $p->getPageData();
|
||||
$var->{story_loop} = [];
|
||||
|
||||
my $icon = $session->icon;
|
||||
my $userUiLevel = $session->user->get("uiLevel");
|
||||
my $uiLevels = $session->config->get('assetToolbarUiLevel');
|
||||
my $i18n = WebGUI::International->new($session);
|
||||
my $url = $session->url;
|
||||
|
||||
##Only build objects for the assets that we need
|
||||
STORY: foreach my $storyId (@{ $storyIds }) {
|
||||
my $story = WebGUI::Asset->newById($session, $storyId->{assetId}, $storyId->{revisionDate});
|
||||
next STORY unless $story;
|
||||
my $storyVars = {
|
||||
url => ( $exporting
|
||||
? $story->getUrl
|
||||
: $session->url->append($self->getUrl, 'func=viewStory;assetId='.$storyId->{assetId}) ),
|
||||
title => $story->getTitle,
|
||||
creationDate => $story->creationDate,
|
||||
};
|
||||
if ($story->canEdit && $userUiLevel >= $uiLevels->{delete} && !$exporting) {
|
||||
$storyVars->{deleteIcon} = $icon->delete('func=delete', $story->url, $i18n->get(43));
|
||||
$var->{story_loop} = [
|
||||
map {
|
||||
my $v = $_->viewTemplateVariables;
|
||||
if ($exporting) {
|
||||
$v->{url} = $_->getUrl;
|
||||
}
|
||||
else {
|
||||
my $params = "func=viewStory;assetId=$v->{assetId}";
|
||||
my $rawUrl = $v->{url};
|
||||
$v->{url} = $url->append($self->getUrl, $params);
|
||||
if ($v->{canEdit}) {
|
||||
if ($userUiLevel >= $uiLevels->{delete}) {
|
||||
$v->{deleteIcon} = $icon->delete('func=delete', $rawUrl, $i18n->get(43));
|
||||
}
|
||||
if ($userUiLevel >= $uiLevels->{edit}) {
|
||||
$v->{editIcon} = $icon->edit('func=edit', $rawUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
$v;
|
||||
}
|
||||
if ($story->canEdit && $userUiLevel >= $uiLevels->{edit} && !$exporting) {
|
||||
$storyVars->{editIcon} = $icon->edit('func=edit', $story->url);
|
||||
grep { $_ }
|
||||
map {
|
||||
WebGUI::Asset->newById( $session, $_->{assetId} )
|
||||
}
|
||||
push @{$var->{story_loop}}, $storyVars;
|
||||
}
|
||||
@{ $storyIds }
|
||||
];
|
||||
|
||||
if (@{ $storyIds }) {
|
||||
my $topStoryData = $storyIds->[0];
|
||||
my $topStoryVars = shift @{ $var->{story_loop} };
|
||||
##Note, this could have saved from the loop above, but this looks more clean and encapsulated to me.
|
||||
my $topStory = WebGUI::Asset->newById($session, $topStoryData->{assetId}, $topStoryData->{revisionDate});
|
||||
$var->{topStory} = $topStoryVars;
|
||||
$var->{topStoryTitle} = $topStory->getTitle;
|
||||
$var->{topStorySubtitle} = $topStory->subtitle;
|
||||
$var->{topStoryUrl} = $session->url->append($self->getUrl, 'func=viewStory;assetId='.$topStoryData->{assetId}),
|
||||
|
|
|
|||
|
|
@ -2336,12 +2336,12 @@ sub www_viewStatisticalOverview {
|
|||
}
|
||||
}
|
||||
else{
|
||||
my $responses = $db->read('select value,answerComment from Survey_tempReport'
|
||||
my $responses = $db->read('select answerValue,answerComment from Survey_tempReport'
|
||||
. ' where sectionNumber=? and questionNumber=?',
|
||||
[$sectionIndex,$questionIndex]);
|
||||
while (my $response = $responses->hashRef) {
|
||||
push @answerloop,{
|
||||
'answer_value' =>$response->{value},
|
||||
'answer_value' =>$response->{answerValue},
|
||||
'answer_comment' =>$response->{answerComment}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ has '+uiLevel' => (
|
|||
with 'WebGUI::Role::Asset::RssFeed';
|
||||
use WebGUI::Macro;
|
||||
use XML::FeedPP;
|
||||
use XML::FeedPP::MediaRSS;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -252,6 +253,7 @@ A reference to an XML::FeedPP object.
|
|||
|
||||
sub getTemplateVariables {
|
||||
my ($self, $feed) = @_;
|
||||
my $media = XML::FeedPP::MediaRSS->new($feed);
|
||||
my @items = $feed->get_item;
|
||||
my %var;
|
||||
$var{channel_title} = WebGUI::HTML::filter(scalar $feed->title, 'javascript');
|
||||
|
|
@ -268,6 +270,7 @@ sub getTemplateVariables {
|
|||
$var{channel_image_height} = WebGUI::HTML::filter($image[5], 'javascript');
|
||||
foreach my $object (@items) {
|
||||
my %item;
|
||||
$item{media} = [ map { { %$_ } } $media->for_item($object) ];
|
||||
$item{title} = WebGUI::HTML::filter(scalar $object->title, 'javascript');
|
||||
$item{date} = WebGUI::HTML::filter(scalar $object->get_pubDate_epoch, 'javascript');
|
||||
$item{category} = WebGUI::HTML::filter(scalar $object->category, 'javascript');
|
||||
|
|
|
|||
|
|
@ -260,6 +260,24 @@ sub badOtherThing {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 deleteThingIndex ( $thingId )
|
||||
|
||||
Remove the entry about this Thing from the database, and for any rows for it that are indexed as well.
|
||||
|
||||
=head3 $thingId
|
||||
|
||||
The GUID of the Thing, used to pick out this record in the database.
|
||||
|
||||
=cut
|
||||
|
||||
sub deleteThingIndex {
|
||||
my $self = shift;
|
||||
my $thingId = shift;
|
||||
$self->session->db->write(q|delete from assetIndex where assetId=? and subId like CONCAT(?,'%')|,[$self->getId, $thingId]);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 duplicate ( )
|
||||
|
||||
Duplicates a Thingy, including the definitions of the Things in this Thingy and their fields.
|
||||
|
|
@ -346,6 +364,8 @@ sub duplicateThing {
|
|||
$self->addField($field,0);
|
||||
}
|
||||
|
||||
$thingProperties->{thingId} = $newThingId;
|
||||
$self->indexThing($thingProperties);
|
||||
return $newThingId;
|
||||
|
||||
}
|
||||
|
|
@ -397,6 +417,7 @@ sub deleteField {
|
|||
$db->write("ALTER TABLE ".$db->quote_identifier("Thingy_".$thingId)." DROP "
|
||||
.$db->quote_identifier("field_".$fieldId));
|
||||
}
|
||||
$self->reindexThings;
|
||||
$log->info("Deleted field: $fieldId in thing: $thingId.");
|
||||
return undef;
|
||||
}
|
||||
|
|
@ -433,7 +454,7 @@ sub copyThingData {
|
|||
my @storage_field_ids = ();
|
||||
##Check to see if any of them are File or Image
|
||||
foreach my $field (@{ $fields }) {
|
||||
if ($field->{fieldType} eq 'File' or $field->{fieldType} eq 'Image') {
|
||||
if ($self->field_isa($field->{fieldType}, 'WebGUI::Form::File')) {
|
||||
push @storage_field_ids, $field->{fieldId};
|
||||
}
|
||||
}
|
||||
|
|
@ -447,6 +468,7 @@ sub copyThingData {
|
|||
}
|
||||
##Update the copy
|
||||
$self->setCollateral("Thingy_".$thingId, "thingDataId", $origCollateral, 0, 0);
|
||||
$self->indexThingData($thingId, $origCollateral);
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
|
@ -491,7 +513,7 @@ sub deleteThingData {
|
|||
my @storage_field_ids = ();
|
||||
##Check to see if any of them are File or Image
|
||||
foreach my $field (@{ $fields }) {
|
||||
if ($field->{fieldType} eq 'File' or $field->{fieldType} eq 'Image') {
|
||||
if ($self->field_isa($field->{fieldType}, 'WebGUI::Form::File')) {
|
||||
push @storage_field_ids, $field->{fieldId};
|
||||
}
|
||||
}
|
||||
|
|
@ -501,11 +523,30 @@ sub deleteThingData {
|
|||
$storage->delete;
|
||||
}
|
||||
|
||||
$self->deleteThingDataIndex($thingDataId);
|
||||
return undef;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 deleteThingDataIndex ( $thingDataId )
|
||||
|
||||
Remove the entry about this Thing from the database, and for any rows for it that are indexed as well.
|
||||
|
||||
=head3 $thingDataId
|
||||
|
||||
The GUID of the thingData to remove, used to pick out this record in the database.
|
||||
|
||||
=cut
|
||||
|
||||
sub deleteThingDataIndex {
|
||||
my $self = shift;
|
||||
my $thingDataId = shift;
|
||||
$self->session->db->write(q|delete from assetIndex where assetId=? and subId like CONCAT('%-',?)|,[$self->getId, $thingDataId]);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 deleteThing ( thingId )
|
||||
|
||||
Deletes a Thing and its fields from Collateral and drops the things table.
|
||||
|
|
@ -528,6 +569,7 @@ sub deleteThing {
|
|||
$session->db->write("drop table if exists ".$session->db->quote_identifier("Thingy_".$thingId));
|
||||
|
||||
$log->info("Deleted thing: $thingId.");
|
||||
$self->deleteThingIndex($thingId);
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
|
@ -535,7 +577,9 @@ sub deleteThing {
|
|||
|
||||
=head2 editThingDataSave ( )
|
||||
|
||||
Saves a row of thing data and triggers the appropriate workflow triggers.
|
||||
Saves a row of thing data and triggers the appropriate workflow triggers. Returns the id of the row created in
|
||||
the database, and an array reference of errors from required fields and other sources. In there are errors, no data
|
||||
is saved in the database, and the id returned in the empty string.
|
||||
|
||||
=head3 thingId
|
||||
|
||||
|
|
@ -579,8 +623,7 @@ sub editThingDataSave {
|
|||
lastUpDated=>time(),
|
||||
);
|
||||
|
||||
$fields = $session->db->read('select * from Thingy_fields where assetId = ? and thingId = ? order by sequenceNumber',
|
||||
[$self->getId,$thingId]);
|
||||
$fields = $self->getFields($thingId);
|
||||
while (my $field = $fields->hashRef) {
|
||||
my $fieldName = 'field_'.$field->{fieldId};
|
||||
my $fieldValue;
|
||||
|
|
@ -589,7 +632,7 @@ sub editThingDataSave {
|
|||
$fieldType = "" if ($fieldType =~ m/^otherThing/x);
|
||||
# Modify the defaultValue for certain field types. For most types we want to use
|
||||
# the default in the database, for these we want the last known value for this thingData
|
||||
if ( $fieldType eq "File" || $fieldType eq "Image" ) {
|
||||
if ($self->field_isa($fieldType, 'WebGUI::Form::File')) {
|
||||
$field->{ defaultValue } = $thingData{ "field_" . $field->{ fieldId } };
|
||||
}
|
||||
$fieldValue = $thingData->{$fieldName} || $session->form->process($fieldName,$fieldType,$field->{defaultValue},$field);
|
||||
|
|
@ -598,7 +641,6 @@ sub editThingDataSave {
|
|||
push (@errors,{
|
||||
"error_message"=>$field->{label}." ".$i18n->get('is required error').".",
|
||||
});
|
||||
#$hadErrors = 1;
|
||||
}
|
||||
if ($field->{status} eq "hidden") {
|
||||
$fieldValue = $field->{defaultValue};
|
||||
|
|
@ -611,7 +653,11 @@ sub editThingDataSave {
|
|||
$thingData{$fieldName} = $fieldValue;
|
||||
}
|
||||
|
||||
if (@errors) {
|
||||
return ('', \@errors);
|
||||
}
|
||||
$newThingDataId = $self->setCollateral("Thingy_".$thingId,"thingDataId",\%thingData,0,0);
|
||||
$self->indexThingData($thingId, \%thingData);
|
||||
|
||||
# trigger workflow
|
||||
if($thingDataId eq "new"){
|
||||
|
|
@ -653,6 +699,33 @@ override exportAssetData => sub {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 field_isa ( $fieldType, $isa )
|
||||
|
||||
Builds a form field and does an isa check on it.
|
||||
|
||||
=head2 $fieldType
|
||||
|
||||
This is the type of a field to build. It will have 'WebGUI::Form' prepended to it to form
|
||||
a complete classname.
|
||||
|
||||
=head2 $isa
|
||||
|
||||
This is the class name to check against.
|
||||
|
||||
=cut
|
||||
|
||||
sub field_isa {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $fieldType = shift;
|
||||
my $isa = shift;
|
||||
$fieldType = ucfirst $fieldType;
|
||||
my $control = eval { WebGUI::Pluggable::instanciate("WebGUI::Form::".$fieldType, "new", [ $session, () ]) };
|
||||
return ($control && $control->isa($isa));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 _getDbDataType ( fieldType )
|
||||
|
||||
returns the database data type for a field based on the fieldType.
|
||||
|
|
@ -905,6 +978,23 @@ sub getEditFieldForm {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getFields ( $thingId )
|
||||
|
||||
Returns a result set with all the fields in a thing in this Thingy.
|
||||
|
||||
=head3 $thingId
|
||||
|
||||
The GUID for a thing
|
||||
|
||||
=cut
|
||||
|
||||
sub getFields {
|
||||
my ($self, $thingId) = @_;
|
||||
return $self->session->db->read("select * from Thingy_fields where assetId=? and thingId=? order by sequenceNumber",[$self->getId, $thingId]);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getFieldValue ( value, field )
|
||||
|
||||
Processes the field value for date(Time) fields and Other Thing fields.
|
||||
|
|
@ -1153,6 +1243,29 @@ sub getThing {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getThingUrl ( thingData )
|
||||
|
||||
Returns a the URL to view a Thing in this Thingy
|
||||
|
||||
=head3 thingData
|
||||
|
||||
A hashref of properties for the Thing, as returned by getThing. This is needed to extract the defaultView,
|
||||
to get the right func, and the thingId.
|
||||
|
||||
=cut
|
||||
|
||||
sub getThingUrl {
|
||||
my ($self, $thing) = @_;
|
||||
if ($thing->{defaultView} eq "addThing") {
|
||||
return 'func=editThingData;thingId='.$thing->{thingId}.';thingDataId=new';
|
||||
}
|
||||
else{
|
||||
return 'func=search;thingId='.$thing->{thingId};
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getViewThingVars ( )
|
||||
|
||||
Returns the field values of a thing instance and the title for its view screen in a tmpl var hashref.
|
||||
|
|
@ -1171,8 +1284,7 @@ sub getViewThingVars {
|
|||
." where thingDataId = ?",[$thingDataId]);
|
||||
|
||||
if (%thingData) {
|
||||
my $fields = $db->read('select * from Thingy_fields where assetId = ? and thingId = ? order by sequenceNumber',
|
||||
[$self->getId,$thingId]);
|
||||
my $fields = $self->getFields($thingId);
|
||||
while (my %field = $fields->hash) {
|
||||
next unless ($field{display} eq '1');
|
||||
my $hidden = ($field{status} eq "hidden" && !$self->session->isAdminOn);
|
||||
|
|
@ -1207,6 +1319,7 @@ sub getViewThingVars {
|
|||
);
|
||||
push(@viewScreenTitleFields,$value) if ($field{viewScreenTitle});
|
||||
push(@field_loop, { map {("field_".$_ => $fieldProperties{$_})} keys(%fieldProperties) });
|
||||
$var->{ $field{label} } = $value;
|
||||
}
|
||||
$var->{viewScreenTitle} = join(" ",@viewScreenTitleFields);
|
||||
$var->{field_loop} = \@field_loop;
|
||||
|
|
@ -1314,7 +1427,7 @@ sub importAssetCollateralData {
|
|||
push(@importThings,$thing->{thingId});
|
||||
my ($thingIdExists) = $session->db->quickArray("select thingId from Thingy_things where thingId = ?",
|
||||
[$thing->{thingId}]);
|
||||
if ($assetExists && $thingIdExists){
|
||||
if ($thingIdExists){
|
||||
# update existing thing
|
||||
$log->info("Updating Thing, label: ".$thing->{label}.", id: ".$thing->{thingId});
|
||||
$self->setCollateral("Thingy_things","thingId",$thing,0,0);
|
||||
|
|
@ -1323,6 +1436,7 @@ sub importAssetCollateralData {
|
|||
# add new thing
|
||||
$self->addThing($thing,1);
|
||||
}
|
||||
$self->indexThing($thing);
|
||||
}
|
||||
# delete deleted things
|
||||
my $thingsInDatabase = $self->getThings;
|
||||
|
|
@ -1338,7 +1452,7 @@ sub importAssetCollateralData {
|
|||
push(@importFields,$field->{fieldId});
|
||||
my $dbDataType = $self->_getDbDataType($field->{fieldType});
|
||||
my ($fieldIdExists) = $session->db->quickArray("select fieldId from Thingy_fields where fieldId = ? and thingId = ? ",[$field->{fieldId},$field->{thingId}]);
|
||||
if ($assetExists && $fieldIdExists){
|
||||
if ($fieldIdExists){
|
||||
# update existing field
|
||||
$log->info("Updating Field, label: ".$field->{label}.", id: ".$field->{fieldId}.",seq :"
|
||||
.$field->{sequenceNumber});
|
||||
|
|
@ -1364,6 +1478,126 @@ sub importAssetCollateralData {
|
|||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 indexContent ( )
|
||||
|
||||
Extend the base class to handle reindexing every Thing, and every row in every Thing. We have
|
||||
to do a complete rework because the URL may have changed, and that affects everything that has
|
||||
been inserted into the AssetIndex.
|
||||
|
||||
=cut
|
||||
|
||||
sub indexContent {
|
||||
my ($self) = @_;
|
||||
my $session = $self->session;
|
||||
$self->SUPER::indexContent();
|
||||
$self->reindexThings;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 indexThing ( $thing )
|
||||
|
||||
Add an entry about this Thing into the AssetIndex so it can be found for searches.
|
||||
|
||||
=head3 $thing
|
||||
|
||||
A hashref of Thing properties, as returned by getThing
|
||||
|
||||
=cut
|
||||
|
||||
sub indexThing {
|
||||
my ($self, $thing) = @_;
|
||||
return unless $thing;
|
||||
my $index = WebGUI::Search::Index->new($self);
|
||||
$index->addRecord(
|
||||
url => $self->getUrl($self->getThingUrl($thing)),
|
||||
groupIdView => $thing->{groupIdView},
|
||||
title => $thing->{label},
|
||||
subId => $thing->{thingId},
|
||||
keywords => join(' ', @{$thing}{qw/label editScreenTitle editInstructions searchScreenTitle searchDescription/}),
|
||||
);
|
||||
##Easy update of all thingData fields for this thing. This is in lieu of deleting all records
|
||||
##And rebuilding them all.
|
||||
$self->session->db->write(q|update assetIndex set title=?, groupIdView=? where assetId=? and subId like CONCAT(?, '%')|, [$thing->{label}, $thing->{groupIdView}, $self->getId, $thing->{thingId}]);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 indexThingData ( $thingId, $thingData )
|
||||
|
||||
Add an entry about a row from this Thing into the AssetIndex so it can be found for searches.
|
||||
|
||||
=head3 $thingId
|
||||
|
||||
The GUID for a Thing.
|
||||
|
||||
=head3 $thingData
|
||||
|
||||
A hashref of ThingData properties
|
||||
|
||||
=cut
|
||||
|
||||
sub indexThingData {
|
||||
my ($self, $thingId, $thingData) = @_;
|
||||
my $session = $self->session;
|
||||
return unless $thingId;
|
||||
my $thing = $self->getThing($thingId);
|
||||
my $index = WebGUI::Search::Index->new($self);
|
||||
my $keywords;
|
||||
##Get the Thingy's fields
|
||||
my $fields = $session->db->read('select * from Thingy_fields where assetId = ? and thingId = ?',
|
||||
[$self->getId, $thingId]);
|
||||
##Walk the fields
|
||||
my @viewScreenTitleFields = ();
|
||||
FIELD: while (my %field = $fields->hash) {
|
||||
my $fieldName = 'field_'.$field{fieldId};
|
||||
$field{value} = $thingData->{$fieldName} || $field{defaultValue};
|
||||
my $subkeywords = '';
|
||||
my $value = '';
|
||||
if ($self->field_isa($field{fieldType}, 'WebGUI::Form::File')) {
|
||||
my $storage = WebGUI::Storage->get($session, $field{value});
|
||||
if ($storage) {
|
||||
foreach my $file (@{$storage->getFiles()}) {
|
||||
$subkeywords = $index->getKeywordsForFile($storage->getPath($file));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$value = $self->getFieldValue($field{value}, \%field);
|
||||
##If it's a file type, then get keywords from the file.
|
||||
##Accumulate keywords
|
||||
$subkeywords = $value;
|
||||
}
|
||||
if ($value && $field{viewScreenTitle}) {
|
||||
push @viewScreenTitleFields, $value;
|
||||
}
|
||||
##We don't index date fields, since they're unix epochs and they'd be different for everyone based on timezone.
|
||||
next FIELD if $field{fieldType} eq 'date'
|
||||
|| $field{fieldType} eq 'datetime'
|
||||
|| $field{fieldType} eq 'time';
|
||||
##Don't show what shouldn't be shown
|
||||
next FIELD unless $field{displayInSearch};
|
||||
$keywords = join ' ', $keywords, $subkeywords;
|
||||
}
|
||||
return unless $keywords; ##No sense indexing nothing;
|
||||
my $title = join('', @viewScreenTitleFields)
|
||||
|| $thing->{label}
|
||||
|| $self->getTitle;
|
||||
$index->addRecord(
|
||||
assetId => $self->getId,
|
||||
url => $self->getUrl('func=viewThingData;thingId='. $thing->{thingId} . ';thingDataId='. $thingData->{thingDataId}),
|
||||
groupIdView => $thing->{groupIdView},
|
||||
title => $title,
|
||||
subId => $thing->{thingId} . '-' . $thingData->{thingDataId},
|
||||
keywords => $keywords,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 prepareView ( )
|
||||
|
|
@ -1412,6 +1646,30 @@ override purge => sub {
|
|||
return super();
|
||||
};
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 reindexThings ( )
|
||||
|
||||
Reindex every Thing, and every row in every Thing.
|
||||
|
||||
=cut
|
||||
|
||||
sub reindexThings {
|
||||
my ($self) = @_;
|
||||
my $session = $self->session;
|
||||
my $things = $self->getThings;
|
||||
THING: while (my $thing = $things->hashRef) {
|
||||
$self->deleteThingIndex($thing->{thingId});
|
||||
$self->indexThing($thing);
|
||||
my $sth = $session->db->read('select * from '. $session->db->dbh->quote_identifier('Thingy_'.$thing->{thingId}));
|
||||
while (my $thingData = $sth->hashRef) {
|
||||
$self->indexThingData($thing->{thingId}, $thingData);
|
||||
}
|
||||
$sth->finish;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 triggerWorkflow ( workflowId, thingId, thingDataId )
|
||||
|
|
@ -1734,7 +1992,7 @@ sub www_editThing {
|
|||
exportMetaData=>undef,
|
||||
maxEntriesPerUser=>undef,
|
||||
);
|
||||
$thingId = $self->addThing(\%properties,0);
|
||||
$thingId = "new";
|
||||
}
|
||||
else{
|
||||
%properties = %{$self->getThing($thingId)};
|
||||
|
|
@ -1834,15 +2092,15 @@ sub www_editThing {
|
|||
." <td class='formDescription'>".$i18n->get('sort by label')."</td>\n"
|
||||
."</tr>\n";
|
||||
|
||||
$fields = $self->session->db->read('select * from Thingy_fields where assetId = '.$self->session->db->quote($self->getId).' and thingId = '.$self->session->db->quote($thingId).' order by sequenceNumber');
|
||||
$fields = $self->getFields($thingId);
|
||||
while (my $field = $fields->hashRef) {
|
||||
my $formElement;
|
||||
if ($field->{fieldType} eq "File"){
|
||||
$formElement = "<input type='file' name='file'>";
|
||||
}
|
||||
if ($field->{fieldType} eq "Image"){
|
||||
if ($self->field_isa($field->{fieldType}, 'WebGUI::Form::Image')) {
|
||||
$formElement = "<input type='file' name='image'>";
|
||||
}
|
||||
elsif ($self->field_isa($field->{fieldType}, 'WebGUI::Form::File')) {
|
||||
$formElement = "<input type='file' name='file'>";
|
||||
}
|
||||
else{
|
||||
$formElement = $self->getFormElement($field);
|
||||
}
|
||||
|
|
@ -1857,11 +2115,12 @@ sub www_editThing {
|
|||
."\n<table>\n<tr>\n"
|
||||
." <td style='width:100px;' valign='top' class='formDescription'>".$field->{label}."</td>\n"
|
||||
." <td style='width:370px;'>".$formElement."</td>\n"
|
||||
." <td style='width:120px;' valign='top'> <input onClick=\"editListItem('".$self->session->url->page()
|
||||
."?func=editField;fieldId=".$field->{fieldId}.";thingId=".$thingId."','".$field->{fieldId}."')\" value='Edit' type='button'>"
|
||||
." <input onClick=\"editListItem('".$self->session->url->page()
|
||||
."?func=editField;copy=1;fieldId=".$field->{fieldId}.";thingId=".$thingId."','".$field->{fieldId}
|
||||
."','copy')\" value='Copy' type='button'>"
|
||||
." <td style='width:120px;' valign='top'> <input onClick=\"editListItem('"
|
||||
.$self->getUrl('func=editField;fieldId='.$field->{fieldId}.';thingId='.$thingId)
|
||||
."','".$field->{fieldId}."')\" value='".$i18n->get('Edit','Icon')."' type='button'>"
|
||||
." <input onClick=\"editListItem('"
|
||||
.$self->getUrl('func=editField;copy=1;fieldId='.$field->{fieldId}.';thingId='.$thingId)
|
||||
."','".$field->{fieldId}."','copy')\" value='".$i18n->get('Copy','Icon')."' type='button'>"
|
||||
."<input onClick=\"deleteListItem('".$self->session->url->page()."','".$field->{fieldId}."','".$thingId."')\" "
|
||||
."value='".$i18n->get('Delete','Icon')."' type='button'></td>\n</tr>\n</table>\n</li>\n";
|
||||
|
||||
|
|
@ -2138,50 +2397,47 @@ database immediately.
|
|||
=cut
|
||||
|
||||
sub www_editThingSave {
|
||||
|
||||
my $self = shift;
|
||||
return $self->session->privilege->insufficient() unless $self->canEdit;
|
||||
my $form = $self->session->form;
|
||||
my ($thingId, $fields);
|
||||
$thingId = $self->session->form->process("thingId");
|
||||
my $form = $self->session->form;
|
||||
my $thingId = $self->session->form->process("thingId");
|
||||
my $fields = $self->getFields($thingId);
|
||||
|
||||
$fields = $self->session->db->read('select * from Thingy_fields where assetId = '.$self->session->db->quote($self->getId).' and thingId = '.$self->session->db->quote($thingId).' order by sequenceNumber');
|
||||
|
||||
|
||||
$self->setCollateral("Thingy_things","thingId",{
|
||||
thingId=>$thingId,
|
||||
label=>$form->process("label"),
|
||||
editScreenTitle=>$form->process("editScreenTitle"),
|
||||
editInstructions=>$form->process("editInstructions"),
|
||||
groupIdAdd=>$form->process("groupIdAdd"),
|
||||
groupIdEdit=>$form->process("groupIdEdit"),
|
||||
saveButtonLabel=>$form->process("saveButtonLabel"),
|
||||
afterSave=>$form->process("afterSave"),
|
||||
editTemplateId=>$form->process("editTemplateId") || 1,
|
||||
onAddWorkflowId=>$form->process("onAddWorkflowId"),
|
||||
onEditWorkflowId=>$form->process("onEditWorkflowId"),
|
||||
onDeleteWorkflowId=>$form->process("onDeleteWorkflowId"),
|
||||
groupIdView=>$form->process("groupIdView"),
|
||||
viewTemplateId=>$form->process("viewTemplateId") || 1,
|
||||
defaultView=>$form->process("defaultView"),
|
||||
searchScreenTitle=>$form->process("searchScreenTitle"),
|
||||
searchDescription=>$form->process("searchDescription"),
|
||||
groupIdSearch=>$form->process("groupIdSearch"),
|
||||
groupIdImport=>$form->process("groupIdImport"),
|
||||
groupIdExport=>$form->process("groupIdExport"),
|
||||
searchTemplateId=>$form->process("searchTemplateId") || 1,
|
||||
thingsPerPage=>$form->process("thingsPerPage") || 25,
|
||||
sortBy=>$form->process("sortBy") || '',
|
||||
exportMetaData=>$form->process("exportMetaData") || '',
|
||||
maxEntriesPerUser=>$form->process("maxEntriesPerUser") || '',
|
||||
},0,1);
|
||||
my $thing = {
|
||||
thingId => $thingId,
|
||||
label => $form->process("label"),
|
||||
editScreenTitle => $form->process("editScreenTitle"),
|
||||
editInstructions => $form->process("editInstructions"),
|
||||
groupIdAdd => $form->process("groupIdAdd"),
|
||||
groupIdEdit => $form->process("groupIdEdit"),
|
||||
saveButtonLabel => $form->process("saveButtonLabel"),
|
||||
afterSave => $form->process("afterSave"),
|
||||
editTemplateId => $form->process("editTemplateId") || 1,
|
||||
onAddWorkflowId => $form->process("onAddWorkflowId"),
|
||||
onEditWorkflowId => $form->process("onEditWorkflowId"),
|
||||
onDeleteWorkflowId => $form->process("onDeleteWorkflowId"),
|
||||
groupIdView => $form->process("groupIdView"),
|
||||
viewTemplateId => $form->process("viewTemplateId") || 1,
|
||||
defaultView => $form->process("defaultView"),
|
||||
searchScreenTitle => $form->process("searchScreenTitle"),
|
||||
searchDescription => $form->process("searchDescription"),
|
||||
groupIdSearch => $form->process("groupIdSearch"),
|
||||
groupIdImport => $form->process("groupIdImport"),
|
||||
groupIdExport => $form->process("groupIdExport"),
|
||||
searchTemplateId => $form->process("searchTemplateId") || 1,
|
||||
thingsPerPage => $form->process("thingsPerPage") || 25,
|
||||
sortBy => $form->process("sortBy") || '',
|
||||
exportMetaData => $form->process("exportMetaData") || '',
|
||||
maxEntriesPerUser => $form->process("maxEntriesPerUser") || '',
|
||||
};
|
||||
$self->setCollateral("Thingy_things", "thingId", $thing, 0, 1);
|
||||
|
||||
if($fields->rows < 1){
|
||||
$self->session->log->warn("Thing failed to create because it had no fields");
|
||||
my $i18n = WebGUI::International->new($self->session, "Asset_Thingy");
|
||||
return $self->www_editThing($i18n->get("thing must have fields"));
|
||||
}
|
||||
|
||||
|
||||
while (my $field = $fields->hashRef) {
|
||||
my $display = $self->session->form->process("display_".$field->{fieldId}) || 0;
|
||||
my $viewScreenTitle = $self->session->form->process("viewScreenTitle_".$field->{fieldId}) || 0;
|
||||
|
|
@ -2190,6 +2446,7 @@ sub www_editThingSave {
|
|||
|
||||
$self->session->db->write("update Thingy_fields set display = ?, viewScreenTitle = ?, displayinSearch = ?, searchIn = ? where fieldId = ? and thingId = ?",[$display, $viewScreenTitle, $displayInSearch, $searchIn, $field->{fieldId}, $thingId]);
|
||||
}
|
||||
$self->indexThing($thing);
|
||||
return $self->www_manage;
|
||||
}
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -2208,6 +2465,7 @@ sub www_editField {
|
|||
return $session->privilege->insufficient() unless $self->canEdit;
|
||||
$fieldId = $session->form->process("fieldId");
|
||||
$thingId = $session->form->process("thingId");
|
||||
|
||||
%properties = $session->db->quickHash("select * from Thingy_fields where thingId=? and fieldId=? and assetId=?",
|
||||
[$thingId,$fieldId,$self->getId]);
|
||||
if($session->form->process("copy")){
|
||||
|
|
@ -2248,6 +2506,8 @@ sub www_editFieldSave {
|
|||
if ($fieldType =~ m/^otherThing/){
|
||||
$defaultValue = $session->form->process("defaultFieldInThing");
|
||||
}
|
||||
|
||||
$thingId = $self->addThing({ thingId => 'new' },0) if $thingId eq 'new';
|
||||
|
||||
$fieldId = $session->form->process("fieldId");
|
||||
%properties = (
|
||||
|
|
@ -2285,12 +2545,12 @@ sub www_editFieldSave {
|
|||
$newFieldId = $self->setCollateral("Thingy_fields","fieldId",\%properties,1,1,"thingId",$thingId);
|
||||
}
|
||||
|
||||
if ($properties{fieldType} eq "File"){
|
||||
$formElement = "<input type='file' name='file'>";
|
||||
}
|
||||
elsif ($properties{fieldType} eq "Image"){
|
||||
if ($self->field_isa($properties{fieldType}, 'WebGUI::Form::Image')) {
|
||||
$formElement = "<input type='file' name='image'>";
|
||||
}
|
||||
elsif ($self->field_isa($properties{fieldType}, 'WebGUI::Form::File')) {
|
||||
$formElement = "<input type='file' name='file'>";
|
||||
}
|
||||
else{
|
||||
$formElement = $self->getFormElement(\%properties);
|
||||
}
|
||||
|
|
@ -2303,15 +2563,16 @@ sub www_editFieldSave {
|
|||
|
||||
$listItemHTML = "<table>\n<tr>\n<td style='width:100px;' valign='top' class='formDescription'>".$label."</td>\n"
|
||||
."<td style='width:370px;'>".$formElement."</td>\n"
|
||||
."<td style='width:120px;' valign='top'> <input onClick=\"editListItem('".$session->url->page()
|
||||
."?func=editField;fieldId=".$newFieldId.";thingId=".$properties{thingId}."','".$newFieldId."')\" value='".$i18n->get('Edit','Icon')."' type='button'>"
|
||||
."<td style='width:120px;' valign='top'> <input onClick=\"editListItem('"
|
||||
.$self->getUrl('func=editField;fieldId='.$newFieldId.';thingId='.$properties{thingId})
|
||||
."','".$newFieldId."')\" value='".$i18n->get('Edit','Icon')."' type='button'>"
|
||||
."<input onClick=\"deleteListItem('".$session->url->page()."','".$newFieldId
|
||||
."','".$properties{thingId}."')\" value='".$i18n->get('Delete','Icon')."' type='button'></td>\n</tr>\n</table>";
|
||||
|
||||
# Make sure we send debug information along with the field.
|
||||
$log->preventDebugOutput;
|
||||
|
||||
$session->output->print($newFieldId.$listItemHTML);
|
||||
$session->output->print($thingId.$newFieldId.$listItemHTML);
|
||||
return "chunked";
|
||||
}
|
||||
|
||||
|
|
@ -2493,8 +2754,7 @@ sub editThingData {
|
|||
." where thingDataId = ?",[$thingDataId]);
|
||||
}
|
||||
|
||||
$fields = $session->db->read('select * from Thingy_fields where assetId = ? and thingId = ? order by sequenceNumber'
|
||||
,[$self->getId,$thingId]);
|
||||
$fields = $self->getFields($thingId);
|
||||
while (my %field = $fields->hash) {
|
||||
my $fieldName = 'field_'.$field{fieldId};
|
||||
$fieldValue = undef;
|
||||
|
|
@ -2656,13 +2916,13 @@ sub www_editThingDataSaveViaAjax {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_export ( )
|
||||
=head2 www_exportThing ( )
|
||||
|
||||
Exports search results as csv.
|
||||
Exports one entire Thing as CSV.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_export {
|
||||
sub www_exportThing {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my ($query,$sth,$out,$fields,@fields,$fileName,@fieldLabels);
|
||||
|
|
@ -2676,30 +2936,29 @@ sub www_export {
|
|||
$pb->start($i18n->get('export label').' '.$thingProperties->{label}, $session->url->extras('assets/thingy.gif'));
|
||||
$pb->update($i18n->get('Creating column headers'));
|
||||
my $tempStorage = WebGUI::Storage->createTemp($session);
|
||||
$fields = $session->db->read('select * from Thingy_fields where assetId =? and thingId = ? order by sequenceNumber',
|
||||
[$self->getId,$thingId]);
|
||||
$fields = $self->getFields($thingId);
|
||||
while (my $field = $fields->hashRef) {
|
||||
if ($field->{displayInSearch}){
|
||||
push(@fields, {
|
||||
fieldId => $field->{fieldId},
|
||||
properties => $field,
|
||||
});
|
||||
push(@fieldLabels,$field->{label});
|
||||
}
|
||||
push(@fields, {
|
||||
fieldId => $field->{fieldId},
|
||||
properties => $field,
|
||||
});
|
||||
push(@fieldLabels,$field->{label});
|
||||
}
|
||||
|
||||
my @metaDataFields = ('thingDataId','dateCreated','createdById','updatedById','updatedByName','lastUpdated','ipAddress');
|
||||
if ($thingProperties->{exportMetaData}){
|
||||
push(@fieldLabels,@metaDataFields)
|
||||
}
|
||||
|
||||
$query = $session->cache->get("query_".$thingId);
|
||||
$query = 'select * from '.$session->db->dbh->quote_identifier("Thingy_".$thingId);
|
||||
$sth = $session->db->read($query);
|
||||
|
||||
### Loop through the returned structure and put it through Text::CSV
|
||||
# Column heads
|
||||
$self->session->log->warn("field labels: ". join ' ', @fieldLabels);
|
||||
my $csv_filename = 'export_'.$thingProperties->{label}.'.csv';
|
||||
$tempStorage->addFileFromScalar($csv_filename, WebGUI::Text::joinCSV(@fieldLabels));
|
||||
open my $CSV, '>', $tempStorage->getPath($csv_filename);
|
||||
print $CSV WebGUI::Text::joinCSV( @fieldLabels );
|
||||
|
||||
# Data lines
|
||||
$pb->update($i18n->get('Writing data'));
|
||||
|
|
@ -2712,11 +2971,11 @@ sub www_export {
|
|||
my $value = $self->getFieldValue($data->{"field_".$fieldId},$field->{properties},"%y-%m-%d","%y-%m-%d %j:%n:%s");
|
||||
push(@fieldValues, $value);
|
||||
}
|
||||
if ($thingProperties->{exportMetaData}) {
|
||||
foreach my $metaDataField (@metaDataFields){
|
||||
push(@fieldValues,$data->{$metaDataField});
|
||||
}
|
||||
}
|
||||
|
||||
if ($thingProperties->{exportMetaData}) {
|
||||
push(@fieldValues, @{$data}{@metaDataFields});
|
||||
}
|
||||
|
||||
print $CSV "\n".WebGUI::Text::joinCSV( @fieldValues );
|
||||
#if (! ++$rowCounter % 25) {
|
||||
$pb->update($i18n->get('Writing data'));
|
||||
|
|
@ -2724,7 +2983,7 @@ sub www_export {
|
|||
}
|
||||
close $CSV;
|
||||
|
||||
$pb->update(sprintf q|<a href="%s">%s</a>|, $self->getUrl, sprintf($i18n->get('Return to %s'), $thingProperties->{label}));
|
||||
$pb->update(sprintf q|<a href="%s">%s</a>|, $self->getUrl($self->getThingUrl($thingProperties)), sprintf($i18n->get('Return to %s'), $thingProperties->{label}));
|
||||
return $pb->finish($tempStorage->getUrl($csv_filename));
|
||||
}
|
||||
|
||||
|
|
@ -2758,8 +3017,7 @@ sub www_getThingViaAjax {
|
|||
$thingProperties->{groupIdView});
|
||||
|
||||
my @field_loop;
|
||||
my $fields = $session->db->read('select * from Thingy_fields where assetId=? and thingId=? order by sequenceNumber'
|
||||
,[$self->getId,$thingId]);
|
||||
my $fields = $self->getFields($thingId);
|
||||
while (my $field = $fields->hashRef) {
|
||||
$field->{formElement} = $self->getFormElement($field);
|
||||
push(@field_loop,$field);
|
||||
|
|
@ -2992,8 +3250,7 @@ sub www_importForm {
|
|||
." <td>".$i18n->get("check duplicates label")."</td>"
|
||||
."</tr>";
|
||||
|
||||
$fields = $db->read('select label, fieldId from Thingy_fields where assetId =? and thingId = ? order by sequenceNumber',
|
||||
[$self->getId,$thingId]);
|
||||
$fields = $self->getFields($thingId);
|
||||
while (my $field = $fields->hashRef) {
|
||||
$fieldOptions .= "<tr><td>".$field->{label}."</td><td>";
|
||||
$fieldOptions .= WebGUI::Form::Checkbox->new($self->session, {
|
||||
|
|
@ -3059,13 +3316,7 @@ sub www_manage {
|
|||
'thing_searchUrl' => $session->url->append($url, 'func=search;thingId='.$thing->{thingId}),
|
||||
);
|
||||
# set the url for the view icon to the things default view
|
||||
my $viewParams;
|
||||
if ($thing->{defaultView} eq "addThing") {
|
||||
$viewParams = 'func=editThingData;thingId='.$thing->{thingId}.';thingDataId=new';
|
||||
}
|
||||
else{
|
||||
$viewParams = 'func=search;thingId='.$thing->{thingId};
|
||||
}
|
||||
my $viewParams = $self->getThingUrl($thing);
|
||||
$templateVars{'thing_viewIcon'} = $session->icon->view($viewParams);
|
||||
push (@things_loop, \%templateVars);
|
||||
}
|
||||
|
|
@ -3240,13 +3491,12 @@ sub getSearchTemplateVars {
|
|||
my $session = $self->session;
|
||||
my $dbh = $session->db->dbh;
|
||||
my $i18n = WebGUI::International->new($self->session,"Asset_Thingy");
|
||||
my ($var,$url,$orderBy);
|
||||
my ($fields,@searchFields_loop,@displayInSearchFields_loop,$query,@constraints);
|
||||
my (@searchResult_loop,$searchResults,@searchResults,@displayInSearchFields,$paginatePage,$currentUrl,$p);
|
||||
my (@searchResult_loop,$searchResults,@searchResults,@displayInSearchFields,$paginatePage,$p);
|
||||
|
||||
$orderBy = $session->form->process("orderBy") || $thingProperties->{sortBy};
|
||||
$var = $self->get;
|
||||
$url = $self->getUrl;
|
||||
my $orderBy = $session->form->process("orderBy") || $thingProperties->{sortBy};
|
||||
my $var = $self->get;
|
||||
my $url = $self->getUrl;
|
||||
|
||||
$var->{canEditThings} = $self->canEdit;
|
||||
$var->{"addThing_url"} = $session->url->append($url, 'func=editThing;thingId=new');
|
||||
|
|
@ -3254,7 +3504,7 @@ sub getSearchTemplateVars {
|
|||
$var->{"thing_label"} = $thingProperties->{label};
|
||||
|
||||
if ($self->hasPrivileges($thingProperties->{groupIdExport})){
|
||||
$var->{"export_url"} = $session->url->append($url, 'func=export;thingId='.$thingId);
|
||||
$var->{"export_url"} = $session->url->append($url, 'func=exportThing;thingId='.$thingId);
|
||||
}
|
||||
if ($self->hasPrivileges($thingProperties->{groupIdImport})){
|
||||
$var->{"import_url"} = $session->url->append($url, 'func=importForm;thingId='.$thingId);
|
||||
|
|
@ -3265,21 +3515,17 @@ sub getSearchTemplateVars {
|
|||
$var->{searchScreenTitle} = $thingProperties->{searchScreenTitle};
|
||||
$var->{searchDescription} = $thingProperties->{searchDescription};
|
||||
|
||||
$currentUrl = $self->getUrl();
|
||||
foreach ($self->session->form->param) {
|
||||
# if we just saved data from an edit, we do not want to keep any of the params
|
||||
last if $_ eq 'func' and $self->session->form->process($_) eq 'editThingDataSave';
|
||||
|
||||
unless ($_ eq "pn" || $_ eq "op" || $_ =~ /identifier/xi || $_ =~ /password/xi || $_ eq "orderBy" ||
|
||||
$self->session->form->process($_) eq "") {
|
||||
$currentUrl = $self->session->url->append($currentUrl,$self->session->url->escape($_)
|
||||
.'='.$self->session->url->escape($self->session->form->process($_)));
|
||||
}
|
||||
my $currentUrl;
|
||||
my $func = $session->form->process('func');
|
||||
$func = 'search' if $func eq 'editThingDataSave';
|
||||
$currentUrl = $self->getUrl('func='.$func.';thingId='.$thingId);
|
||||
##Instead of blacklisting query params, they are whitelisted. List is currently empty.
|
||||
FORM: foreach my $form (qw//) {
|
||||
my $param = $session->form->process($form);
|
||||
next FORM unless defined $param;
|
||||
$currentUrl = $session->url->append($currentUrl, $form.'='.$param);
|
||||
}
|
||||
|
||||
$fields = $session->db->read('select * from Thingy_fields where assetId =
|
||||
'.$session->db->quote($self->getId).' and thingId = '.$session->db->quote($thingId).' order by
|
||||
sequenceNumber');
|
||||
$fields = $self->getFields($thingId);
|
||||
while (my $field = $fields->hashRef) {
|
||||
if ($field->{searchIn}){
|
||||
my $searchForm = $self->getFormPlugin($field, 1);
|
||||
|
|
@ -3332,7 +3578,8 @@ sequenceNumber');
|
|||
}
|
||||
$query .= join(", ",map {$dbh->quote_identifier('field_'.$_->{fieldId})} @displayInSearchFields);
|
||||
$query .= " from ".$dbh->quote_identifier("Thingy_".$thingId);
|
||||
if($session->form->process('func') eq 'search'){
|
||||
my $func = $session->form->process('func');
|
||||
if( $func eq 'search' || $func eq 'searchViaAjax' ){
|
||||
# Don't add constraints when the search screen is displayed as an 'after save' option.
|
||||
$query .= " where ".join(" and ",@constraints) if (scalar(@constraints) > 0);
|
||||
}
|
||||
|
|
@ -3345,9 +3592,6 @@ sequenceNumber');
|
|||
$noFields = 1;
|
||||
}
|
||||
|
||||
# store query in cache for thirty minutes
|
||||
$self->session->cache->set("query_".$thingId, $query, 30*60);
|
||||
|
||||
$paginatePage = $self->session->form->param('pn') || 1;
|
||||
$currentUrl = $self->session->url->append($currentUrl, "orderBy=".$orderBy) if $orderBy;
|
||||
|
||||
|
|
@ -3355,7 +3599,7 @@ sequenceNumber');
|
|||
|
||||
my @visibleResults;
|
||||
if (! $noFields) {
|
||||
my $sth = $self->session->db->read($query) if ! $noFields;
|
||||
my $sth = $self->session->db->read($query);
|
||||
while (my $result = $sth->hashRef){
|
||||
if ($self->canViewThingData($thingId,$result->{thingDataId})){
|
||||
push(@visibleResults,$result);
|
||||
|
|
@ -3532,6 +3776,11 @@ The unique id of a thing.
|
|||
|
||||
The unique id of a row of thing data.
|
||||
|
||||
=head3 templateId
|
||||
|
||||
Optional. The unique id or url of the template to be used. When specified, the style template is not used.
|
||||
If omitted, the thing data view template and style will be used.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_viewThingData {
|
||||
|
|
@ -3540,7 +3789,7 @@ sub www_viewThingData {
|
|||
my $session = $self->session;
|
||||
my $thingId = shift || $session->form->process('thingId');
|
||||
my $thingDataId = shift || $session->form->process('thingDataId');
|
||||
|
||||
my $templateId = shift || $session->form->process('templateId');
|
||||
my $var = $self->get;
|
||||
my $url = $self->getUrl;
|
||||
my $i18n = WebGUI::International->new($self->session, "Asset_Thingy");
|
||||
|
|
@ -3570,9 +3819,19 @@ sub www_viewThingData {
|
|||
|
||||
$self->getViewThingVars($thingId,$thingDataId,$var);
|
||||
$self->appendThingsVars($var, $thingId);
|
||||
|
||||
my $template;
|
||||
if( $templateId )
|
||||
{
|
||||
$template = WebGUI::Asset::Template->newByUrl( $session, $templateId ) ||
|
||||
WebGUI::Asset::Template->newById( $session, $templateId );
|
||||
}
|
||||
|
||||
return $self->processStyle(
|
||||
$self->processTemplate($var,$thingProperties->{viewTemplateId})
|
||||
);
|
||||
$self->processTemplate($var,$thingProperties->{viewTemplateId})
|
||||
) if !$template;
|
||||
|
||||
return $self->processTemplate($var,$template->getId,$template);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use WebGUI::International;
|
|||
use Moose;
|
||||
use WebGUI::Definition::Asset;
|
||||
extends 'WebGUI::Asset::Wobject';
|
||||
with 'WebGUI::Role::Asset::Dashlet';
|
||||
define tableName => 'WeatherData';
|
||||
define assetName => ["assetName", 'Asset_WeatherData'];
|
||||
define icon => 'weatherData.gif';
|
||||
|
|
@ -57,6 +58,7 @@ property locations => (
|
|||
tab => "properties",
|
||||
hoverHelp => ["Your list of default weather locations", 'Asset_WeatherData'],
|
||||
label => ["Default Locations", 'Asset_WeatherData'],
|
||||
dashletOverridable => 1,
|
||||
);
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -93,49 +95,70 @@ to be displayed within the page style
|
|||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my %var;
|
||||
my $url = $self->session->url;
|
||||
|
||||
if ($self->partnerId ne "" && $self->licenseKey ne "") {
|
||||
foreach my $location (split("\n", $self->locations)) {
|
||||
my $weather = Weather::Com::Finder->new({
|
||||
'partner_id' => $self->partnerId,
|
||||
'license' => $self->licenseKey,
|
||||
'cache' => '/tmp',
|
||||
});
|
||||
next unless defined $weather;
|
||||
my $overrides = $self->fetchUserOverrides($self->getParent->getId);
|
||||
my $locations = $overrides->{locations} || $self->locations;
|
||||
foreach my $location (split("\n", $locations)) {
|
||||
my $loop_data;
|
||||
my $link_data = [];
|
||||
my $cached_data = $session->cache->get( join "", $self->getId, $location );
|
||||
if ($cached_data) {
|
||||
$loop_data = $cached_data->{locations};
|
||||
$link_data = $cached_data->{links} || [];
|
||||
}
|
||||
else {
|
||||
my $weather = Weather::Com::Finder->new({
|
||||
'partner_id' => $self->partnerId,
|
||||
'license' => $self->licenseKey,
|
||||
'cache' => '/tmp',
|
||||
});
|
||||
next unless defined $weather;
|
||||
|
||||
foreach my $foundLocation(@{$weather->find($location)}) {
|
||||
my $current_conditions = $foundLocation->current_conditions;
|
||||
my $conditions = $current_conditions->description;
|
||||
$conditions =~ s/\b(\w)/uc($1)/eg;
|
||||
my $tempC = $current_conditions->temperature;
|
||||
my $tempF;
|
||||
$tempF = sprintf("%.0f",(((9/5)*$tempC) + 32)) if($tempC);
|
||||
my $icon = $current_conditions->icon || "na";
|
||||
foreach my $foundLocation(@{$weather->find($location)}) {
|
||||
my $current_conditions = $foundLocation->current_conditions;
|
||||
my $conditions = $current_conditions->description;
|
||||
$conditions =~ s/\b(\w)/uc($1)/eg;
|
||||
my $tempC = $current_conditions->temperature;
|
||||
my $tempF;
|
||||
$tempF = sprintf("%.0f",(((9/5)*$tempC) + 32)) if($tempC);
|
||||
my $icon = $current_conditions->icon || "na";
|
||||
|
||||
push(@{$var{'ourLocations.loop'}}, {
|
||||
query => $location,
|
||||
cityState => $foundLocation->name || $location,
|
||||
sky => $conditions || 'N/A',
|
||||
tempF => (defined $tempF)?$tempF:'N/A',
|
||||
tempC => (defined $tempC)?$tempC:'N/A',
|
||||
smallIcon => $url->extras("wobject/WeatherData/small_icons/".$icon.".png"),
|
||||
mediumIcon => $url->extras("wobject/WeatherData/medium_icons/".$icon.".png"),
|
||||
largeIcon => $url->extras("wobject/WeatherData/large_icons/".$icon.".png"),
|
||||
iconUrl => $url->extras("wobject/WeatherData/medium_icons/".$icon.".png"),
|
||||
iconAlt => $conditions,
|
||||
});
|
||||
if (!$var{links_loop}) {
|
||||
$var{links_loop} = [];
|
||||
push @{$loop_data}, {
|
||||
query => $location,
|
||||
cityState => $foundLocation->name || $location,
|
||||
sky => $conditions || 'N/A',
|
||||
tempF => (defined $tempF)?$tempF:'N/A',
|
||||
tempC => (defined $tempC)?$tempC:'N/A',
|
||||
smallIcon => $url->extras("wobject/WeatherData/small_icons/".$icon.".png"),
|
||||
mediumIcon => $url->extras("wobject/WeatherData/medium_icons/".$icon.".png"),
|
||||
largeIcon => $url->extras("wobject/WeatherData/large_icons/".$icon.".png"),
|
||||
iconUrl => $url->extras("wobject/WeatherData/medium_icons/".$icon.".png"),
|
||||
iconAlt => $conditions,
|
||||
last_fetch => time(),
|
||||
};
|
||||
for my $lnk (@{$foundLocation->current_conditions->{WEATHER}{lnks}{link}} ) {
|
||||
push @{$var{links_loop}}, {
|
||||
link_url => $lnk->{l},
|
||||
link_title => $lnk->{t},
|
||||
};
|
||||
if (! $link_data) {
|
||||
push @{ $link_data }, {
|
||||
link_url => $lnk->{l},
|
||||
link_title => $lnk->{t},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
my $cached_data = {
|
||||
locations => $loop_data,
|
||||
links => $link_data,
|
||||
};
|
||||
$session->cache->set( join( "", $self->getId, $location ), $cached_data, $self->get('cacheTimeout'));
|
||||
}
|
||||
push @{$var{'ourLocations.loop'}}, @{ $loop_data };
|
||||
if (!$var{links_loop}) {
|
||||
$var{links_loop} = $link_data;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $self->processTemplate(\%var, undef, $self->{_viewTemplate});
|
||||
|
|
|
|||
|
|
@ -869,6 +869,8 @@ Return search results that match the keyword from the form variable C<keyword>.
|
|||
|
||||
sub www_byKeyword {
|
||||
my $self = shift;
|
||||
my $check = $self->checkView;
|
||||
return $self->session->privilege->noAccess() unless $self->canView;
|
||||
my $session = $self->session;
|
||||
my $keyword = $session->form->process("keyword");
|
||||
|
||||
|
|
@ -980,6 +982,8 @@ Render a search form and process the contents, returning the results.
|
|||
|
||||
sub www_search {
|
||||
my $self = shift;
|
||||
my $check = $self->checkView;
|
||||
return $self->session->privilege->noAccess() unless $self->canView;
|
||||
my $i18n = WebGUI::International->new($self->session, "Asset_WikiMaster");
|
||||
my $queryString = $self->session->form->process('query', 'text');
|
||||
my $var = {
|
||||
|
|
|
|||
129
lib/WebGUI/AssetAspect/Dashlet.pm
Normal file
129
lib/WebGUI/AssetAspect/Dashlet.pm
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
package WebGUI::AssetAspect::Dashlet;
|
||||
|
||||
use strict;
|
||||
use Class::C3;
|
||||
use JSON qw/to_json from_json/;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
WebGUI::AssetAspect::Dashlet - Implement features to turn Assets into Dashlets
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
This Aspect provides methods that allow a Dashboard to determine, store and retrieve
|
||||
customization options for Assets.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 fetchUserOverrides ($dashboardAssetId, [$userId])
|
||||
|
||||
Retrieve user preferences for a particular dashboard and user for this Asset from the database.
|
||||
|
||||
=head3 $dashboardId
|
||||
|
||||
The assetId of the dashboard to reference.
|
||||
|
||||
=head3 $userId
|
||||
|
||||
The userId to whose preferences should be returned. Uses the current session user if omitted.
|
||||
|
||||
=cut
|
||||
|
||||
sub fetchUserOverrides {
|
||||
my $self = shift;
|
||||
my $dashboardAssetId = shift;
|
||||
my $userId = shift || $self->session->user->userId;
|
||||
my $properties_json = $self->session->db->quickScalar('select properties from Dashboard_userPrefs where dashboardAssetId=? and userId=? and dashletAssetId=?',[$dashboardAssetId, $userId, $self->getId,]);
|
||||
$properties_json ||= '{}';
|
||||
my $properties = from_json($properties_json);
|
||||
return $properties;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getOverrideFormDefinition
|
||||
|
||||
Return an array ref of form properties. The form properties are those that the
|
||||
Asset has marked as being able to be overridden by a Dashboard asset by giving
|
||||
the property the dashletOverridable flag.
|
||||
|
||||
Assets that want to allow additional properties outside of their definition should
|
||||
override and extend this method.
|
||||
|
||||
=cut
|
||||
|
||||
sub getOverrideFormDefinition {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my @definitions = reverse @{ $self->definition($session) };
|
||||
my @properties = ();
|
||||
foreach my $definition (@definitions) {
|
||||
foreach my $property_name (keys %{ $definition->{properties} }) {
|
||||
my $property = $definition->{properties}->{$property_name};
|
||||
next unless $property->{dashletOverridable};
|
||||
$property->{name} = $property_name;
|
||||
push @properties, $property;
|
||||
}
|
||||
}
|
||||
return @properties;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getUserOverrides
|
||||
|
||||
Store user preferences for this Asset. This is direct reference from inside the object, so
|
||||
if you plan to modify the data, Clone it first.
|
||||
|
||||
=cut
|
||||
|
||||
sub getUserOverrides {
|
||||
return shift->{_userOverrides};
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 setUserOverrides
|
||||
|
||||
Store user preferences for this Asset.
|
||||
|
||||
=cut
|
||||
|
||||
sub setUserOverrides {
|
||||
shift->{_userOverrides} = shift;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 storeUserOverrides ($dashboardAssetId, $properties, [$userId])
|
||||
|
||||
Store user preferences for a particular dashboard and user for this Asset to the database.
|
||||
|
||||
=head3 $dashboardId
|
||||
|
||||
The assetId of the dashboard to reference.
|
||||
|
||||
=head3 $userId
|
||||
|
||||
The userId to whose preferences should be returned. Uses the current session user if omitted.
|
||||
|
||||
=cut
|
||||
|
||||
sub storeUserOverrides {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $dashboardAssetId = shift;
|
||||
my $properties = shift;
|
||||
my $userId = shift || $session->user->userId;
|
||||
my $properties_json = to_json($properties);
|
||||
$session->db->write('DELETE FROM Dashboard_userPrefs where dashboardAssetId=? and userId=? and dashletAssetId=?',[$dashboardAssetId, $userId, $self->getId]);
|
||||
$session->db->write('INSERT INTO Dashboard_userPrefs (dashboardAssetId, userId, dashletAssetId, properties) VALUES (?,?,?,?)', [$dashboardAssetId, $userId, $self->getId, $properties_json]);
|
||||
}
|
||||
|
||||
|
||||
1; # You can't handle the truth
|
||||
|
|
@ -99,6 +99,10 @@ A hash reference of options that can modify how this method works.
|
|||
|
||||
Assets that normally autocommit their workflows (like CS Posts, and Wiki Pages) won't if this is true.
|
||||
|
||||
=head4 skipNotification
|
||||
|
||||
Disable sending a notification that a new revision was added, for those assets that support it.
|
||||
|
||||
=head4 state
|
||||
|
||||
A state for the duplicated asset (defaults to 'published')
|
||||
|
|
@ -110,8 +114,15 @@ sub duplicate {
|
|||
my $session = $self->session;
|
||||
my $options = shift;
|
||||
my $parent = $self->getParent;
|
||||
##Remove state and pass all other options along to addChild
|
||||
my $asset_state = delete $options->{state};
|
||||
my $newAsset
|
||||
= $parent->addChild( $self->get, undef, $self->get("revisionDate"), { skipAutoCommitWorkflows => $options->{skipAutoCommitWorkflows} } );
|
||||
= $parent->addChild(
|
||||
$self->get,
|
||||
undef,
|
||||
$self->get("revisionDate"),
|
||||
$options,
|
||||
);
|
||||
|
||||
if (! $newAsset) {
|
||||
$self->session->log->error(
|
||||
|
|
@ -120,12 +131,13 @@ sub duplicate {
|
|||
return undef;
|
||||
}
|
||||
# Duplicate metadata fields
|
||||
my $sth = $session->db->read(
|
||||
"select * from metaData_values where assetId = ?",
|
||||
[$self->getId]
|
||||
my $sth = $self->session->db->read(
|
||||
"select * from metaData_values where assetId = ? and revisionDate = ?",
|
||||
[$self->getId, $self->get('revisionDate')]
|
||||
);
|
||||
while (my $h = $sth->hashRef) {
|
||||
$session->db->write("insert into metaData_values (fieldId, assetId, value) values (?, ?, ?)", [$h->{fieldId}, $newAsset->getId, $h->{value}]);
|
||||
$self->session->db->write("insert into metaData_values (fieldId,
|
||||
assetId, revisionDate, value) values (?, ?, ?, ?)", [$h->{fieldId}, $newAsset->getId, $newAsset->get('revisionDate'), $h->{value}]);
|
||||
}
|
||||
|
||||
# Duplicate keywords
|
||||
|
|
@ -139,8 +151,8 @@ sub duplicate {
|
|||
keywords => $keywords,
|
||||
} );
|
||||
|
||||
if (my $state = $options->{state}) {
|
||||
$newAsset->setState($state);
|
||||
if ($asset_state) {
|
||||
$newAsset->setState($asset_state);
|
||||
}
|
||||
|
||||
return $newAsset;
|
||||
|
|
@ -263,11 +275,12 @@ WebGUI::Fork method called by www_pasteList
|
|||
sub pasteInFork {
|
||||
my ( $process, $args ) = @_;
|
||||
my $session = $process->session;
|
||||
$session->log->info( "Trying " . $args->{assetId} );
|
||||
my $self = WebGUI::Asset->newById( $session, $args->{assetId} );
|
||||
$session->asset($self);
|
||||
|
||||
my @roots = grep { $_ && $_->canEdit }
|
||||
map { WebGUI::Asset->newPending( $session, $_ ) } @{ $args->{list} };
|
||||
map { $session->log->info( " Trying " . $_ ); WebGUI::Asset->newPending( $session, $_ ) } @{ $args->{list} };
|
||||
|
||||
my @ids = map {
|
||||
my $list
|
||||
|
|
|
|||
|
|
@ -39,10 +39,6 @@ use WebGUI::Exception;
|
|||
use WebGUI::DateTime;
|
||||
use WebGUI::Asset::Wobject::DataForm;
|
||||
|
||||
#readonly session => my %session;
|
||||
#readonly assetId => my %assetId;
|
||||
#readonly asset => my %asset;
|
||||
|
||||
has session => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
|
|
@ -101,13 +97,6 @@ has entryId => (
|
|||
writer => '_set_entryId',
|
||||
);
|
||||
|
||||
#private entryData => my %entryData;
|
||||
#private entryId => my %entryId;
|
||||
#private userId => my %userId;
|
||||
#readonly username => my %username;
|
||||
#public ipAddress => my %ipAddress;
|
||||
#public submissionDate => my %submissionDate;
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 delete
|
||||
|
|
|
|||
|
|
@ -379,8 +379,8 @@ sub exportBranch {
|
|||
|
||||
# try to write the file
|
||||
eval { $asset->exportWriteFile };
|
||||
if( $@ ) {
|
||||
WebGUI::Error->throw(error => "could not export asset with URL " . $asset->getUrl . ": $@");
|
||||
if( my $e = WebGUI::Error->caught() || $@ ) {
|
||||
WebGUI::Error->throw(error => "could not export asset with URL " . $asset->getUrl . ": $e");
|
||||
}
|
||||
|
||||
# next, tell the asset that we're exporting, so that it can export any
|
||||
|
|
@ -419,7 +419,7 @@ sub exportBranch {
|
|||
$asset->$report('done');
|
||||
};
|
||||
|
||||
my $assetIds = $self->exportGetDescendants(undef, $depth);
|
||||
my $assetIds = $self->exportGetAssetIds($options);
|
||||
foreach my $assetId ( @{$assetIds} ) {
|
||||
$exportAsset->( $assetId );
|
||||
}
|
||||
|
|
@ -507,6 +507,33 @@ sub exportCheckExportable {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 exportGetAssetIds ( options )
|
||||
|
||||
Gets the ids of all the assets to be exported in this run as an arrayref.
|
||||
Takes the same options spec as exportBranch.
|
||||
|
||||
=cut
|
||||
|
||||
sub exportGetAssetIds {
|
||||
my ($self, $options) = @_;
|
||||
my $session = $self->session;
|
||||
my $ids = $self->exportGetDescendants( undef, $options->{depth} );
|
||||
return $ids unless $options->{exportRelated};
|
||||
# We want the ids in a descendant order, but we don't want to repeat
|
||||
# assetIds, so we're using Tie::IxHash to get an ordered set.
|
||||
tie my %set, 'Tie::IxHash';
|
||||
while (my $id = shift @$ids) {
|
||||
my $asset = WebGUI::Asset->newById($session, $id);
|
||||
undef $set{$id};
|
||||
for my $id (@{ $asset->exportGetRelatedAssetIds }) {
|
||||
push(@$ids, $id) unless exists $set{$id};
|
||||
}
|
||||
}
|
||||
return [ keys %set ];
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 exportGetDescendants ( user, depth )
|
||||
|
||||
Gets the descendants of this asset for exporting, walking the lineage as the
|
||||
|
|
@ -587,6 +614,27 @@ sub exportGetDescendants {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 exportGetRelatedAssetIds
|
||||
|
||||
Normally all an asset's shorcuts, but override if exporting your asset would
|
||||
invalidate other exported assets. If exportRelated is checked, this will be
|
||||
called and any assetIds it returns will be exported when your asset is
|
||||
exported.
|
||||
|
||||
Note: You should NOT include parents as related assets simply because they're
|
||||
your parents. If the user wants to export your parent, he can do that. This is
|
||||
for assets that aren't necessarily in your ancestry. If parents were always
|
||||
related, exporting anything would export everything.
|
||||
|
||||
=cut
|
||||
|
||||
sub exportGetRelatedAssetIds {
|
||||
my $self = shift;
|
||||
WebGUI::Asset::Shortcut->getShortcutsForAssetId($self->session, $self->getId);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 exportGetUrlAsPath ( index )
|
||||
|
||||
Translates an asset's URL into an appropriate path and filename for exporting. For
|
||||
|
|
@ -663,7 +711,7 @@ sub exportInFork {
|
|||
my $session = $process->session;
|
||||
my $self = WebGUI::Asset->newById( $session, delete $args->{assetId} );
|
||||
$args->{indexFileName} = delete $args->{index};
|
||||
my $assetIds = $self->exportGetDescendants( undef, $args->{depth} );
|
||||
my $assetIds = $self->exportGetAssetIds($args);
|
||||
my $tree = WebGUI::ProgressTree->new( $session, $assetIds );
|
||||
$process->update( sub { $tree->json } );
|
||||
my %reports = (
|
||||
|
|
|
|||
|
|
@ -88,6 +88,12 @@ ENDHTML
|
|||
name => "depth",
|
||||
value => 99,
|
||||
);
|
||||
$f->addField( "YesNo",
|
||||
label => $i18n->get('Export Related Assets'),
|
||||
hoverHelp => $i18n->get('Export Related Assets description'),
|
||||
name => "exportRelated",
|
||||
value => '',
|
||||
);
|
||||
$f->addField( "selectBox",
|
||||
label => $i18n->get('Export as user'),
|
||||
hoverHelp => $i18n->get('Export as user description'),
|
||||
|
|
@ -157,7 +163,7 @@ sub www_exportStatus {
|
|||
unless $session->user->isInGroup(13);
|
||||
my $form = $session->form;
|
||||
my @vars = qw(
|
||||
index depth userId extrasUploadsAction rootUrlAction exportUrl
|
||||
index depth userId extrasUploadsAction rootUrlAction exportUrl exportRelated
|
||||
);
|
||||
$asset->forkWithStatusPage({
|
||||
plugin => 'ProgressTree',
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ sub importProducts {
|
|||
my %productRow;
|
||||
##Order the data according to the headers, in whatever order they exist.
|
||||
@productRow{ @headers } = @{ $productRow };
|
||||
$productRow{price} =~ tr/0-9.//cd;
|
||||
##Isolate just the collateral from the other product information
|
||||
my %productCollateral;
|
||||
@productCollateral{ @collateralFields } = @productRow{ @collateralFields };
|
||||
|
|
|
|||
|
|
@ -783,19 +783,25 @@ Returns a 6 digit number with leading zeros of the next rank a child will get.
|
|||
=cut
|
||||
|
||||
sub getNextChildRank {
|
||||
my $self = shift;
|
||||
my ($lineage) = $self->session->db->quickArray("select max(lineage) from asset where parentId=?",[$self->getId]);
|
||||
my $rank;
|
||||
if (defined $lineage) {
|
||||
$rank = $self->getRank($lineage);
|
||||
$self->session->log->fatal("Asset ".$self->getId." has too many children.") if ($rank >= 999998);
|
||||
$rank++;
|
||||
} else {
|
||||
$rank = 1;
|
||||
}
|
||||
return $self->formatRank($rank);
|
||||
}
|
||||
my $self = shift;
|
||||
|
||||
# Increment by steps for servers in multi-master DB setups
|
||||
my $inc_step = $self->session->config->get('db/increment_step') || 1;
|
||||
my $inc_offset = $self->session->config->get('db/increment_offset') || 0;
|
||||
|
||||
my ($lineage) = $self->session->db->quickArray("select max(lineage) from asset where parentId=?",[$self->getId]);
|
||||
my $rank;
|
||||
if (defined $lineage) {
|
||||
$rank = $self->getRank($lineage);
|
||||
# Increase rank to next step then add offset
|
||||
$rank += ( $inc_step - $rank % $inc_step ) + $inc_offset;
|
||||
$self->session->log->fatal("Asset ".$self->getId." has too many children.") if ($rank >= 999999); # Each lineage area is only 6 digits
|
||||
}
|
||||
else {
|
||||
$rank = 1;
|
||||
}
|
||||
return $self->formatRank($rank);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ These methods are available from this class:
|
|||
|
||||
=head2 addMetaDataField ( )
|
||||
|
||||
Adds a new field to the metadata system, or edit an existing one.
|
||||
Adds a new field to the metadata system, or edit an existing one. The id of
|
||||
the field is returned.
|
||||
|
||||
=head3 fieldId
|
||||
|
||||
|
|
@ -68,6 +69,10 @@ The form field type for metaData: selectBox, text, integer, or checkList, yesNo,
|
|||
For fields that provide options, the list of options. This is a string with
|
||||
newline separated values.
|
||||
|
||||
=head3 classes
|
||||
|
||||
An arrayref of classnames that this metadata field applies to
|
||||
|
||||
=cut
|
||||
|
||||
sub addMetaDataField {
|
||||
|
|
@ -79,18 +84,31 @@ sub addMetaDataField {
|
|||
my $description = shift || '';
|
||||
my $fieldType = shift;
|
||||
my $possibleValues = shift;
|
||||
my $classes = shift;
|
||||
my $db = $self->session->db;
|
||||
|
||||
if($fieldId eq 'new') {
|
||||
$fieldId = $self->session->id->generate();
|
||||
$self->session->db->write("insert into metaData_properties (fieldId, fieldName, defaultValue, description, fieldType, possibleValues) values (?,?,?,?,?,?)",
|
||||
$db->write("insert into metaData_properties (fieldId, fieldName, defaultValue, description, fieldType, possibleValues) values (?,?,?,?,?,?)",
|
||||
[ $fieldId, $fieldName, $defaultValue, $description, $fieldType, $possibleValues, ]
|
||||
);
|
||||
}
|
||||
else {
|
||||
$self->session->db->write("update metaData_properties set fieldName = ?, defaultValue = ?, description = ?, fieldType = ?, possibleValues = ? where fieldId = ?",
|
||||
$db->write("update metaData_properties set fieldName = ?, defaultValue = ?, description = ?, fieldType = ?, possibleValues = ? where fieldId = ?",
|
||||
[ $fieldName, $defaultValue, $description, $fieldType, $possibleValues, $fieldId, ]
|
||||
);
|
||||
$db->write('delete from metaData_classes where fieldId=?', [$fieldId]);
|
||||
}
|
||||
|
||||
if ($classes && @$classes) {
|
||||
my $qfid = $db->quote($fieldId);
|
||||
$db->write('insert into metaData_classes (fieldId, className) values '
|
||||
.join(', ',
|
||||
map { my $q = $db->quote($_); "($qfid, $q)" } @$classes
|
||||
));
|
||||
}
|
||||
|
||||
return $fieldId;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -109,12 +127,57 @@ The fieldId to be deleted.
|
|||
sub deleteMetaDataField {
|
||||
my $self = shift;
|
||||
my $fieldId = shift;
|
||||
$self->session->db->beginTransaction;
|
||||
$self->session->db->write("delete from metaData_properties where fieldId = ?",[$fieldId]);
|
||||
$self->session->db->write("delete from metaData_values where fieldId = ?",[$fieldId]);
|
||||
$self->session->db->commit;
|
||||
my $db = $self->session->db;
|
||||
$db->beginTransaction;
|
||||
for my $table (map { "metaData_$_" } qw(properties values classes)) {
|
||||
$db->write("delete from $table where fieldId = ?", [ $fieldId ]);
|
||||
}
|
||||
$db->commit;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getMetaDataAsFormFields
|
||||
|
||||
Returns a hashref of metadata field names WebGUI::Form objects appropriate
|
||||
for use on edit forms.
|
||||
|
||||
=cut
|
||||
|
||||
sub getMetaDataAsFormFields {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset');
|
||||
my $fields = $self->getMetaDataFields;
|
||||
my %hash;
|
||||
for my $fid (keys %$fields) {
|
||||
my $info = $fields->{$fid};
|
||||
my $type = lcfirst ($info->{fieldType} || 'text');
|
||||
my $name = $info->{fieldName};
|
||||
my $options = $info->{possibleValues};
|
||||
if($type eq 'selectBox') {
|
||||
my $label = $i18n->get('Select');
|
||||
$options = "|$label\n$options";
|
||||
}
|
||||
my $formClass = ucfirst $type;
|
||||
$hash{$name} = WebGUI::Pluggable::instanciate(
|
||||
"WebGUI::Form::$formClass",
|
||||
'new',
|
||||
[
|
||||
$session, {
|
||||
name => "metadata_$fid",
|
||||
label => $name,
|
||||
value => $info->{value},
|
||||
extras => qq'title="$info->{description}"',
|
||||
defaultValue => $info->{defaultValue},
|
||||
fieldType => $type,
|
||||
options => $options,
|
||||
}
|
||||
]
|
||||
)->toHtml;
|
||||
};
|
||||
\%hash;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -140,21 +203,11 @@ sub getMetaDataAsTemplateVariables {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getMetaDataFields ( [fieldId] )
|
||||
|
||||
Returns a hash reference containing all metadata field properties for this Asset.
|
||||
You can limit the output to a certain field by specifying a fieldId.
|
||||
|
||||
=head3 fieldId
|
||||
|
||||
If specified, the hashRef will contain only this field.
|
||||
|
||||
=cut
|
||||
|
||||
sub getMetaDataFields {
|
||||
sub _getMetaDataFieldsHelper {
|
||||
my $self = shift;
|
||||
my $fieldId = shift;
|
||||
my $session = $self->session;
|
||||
my $listAll = shift || $fieldId;
|
||||
my $db = $self->session->db;
|
||||
my $sql = "select
|
||||
f.fieldId,
|
||||
f.fieldName,
|
||||
|
|
@ -164,19 +217,76 @@ sub getMetaDataFields {
|
|||
f.possibleValues,
|
||||
d.value
|
||||
from metaData_properties f
|
||||
left join metaData_values d on f.fieldId=d.fieldId and d.assetId=".$session->db->quote($self->getId);
|
||||
$sql .= " where f.fieldId = ".$session->db->quote($fieldId) if ($fieldId);
|
||||
$sql .= " order by f.fieldName";
|
||||
if ($fieldId) {
|
||||
return $session->db->quickHashRef($sql);
|
||||
}
|
||||
else {
|
||||
tie my %hash, 'Tie::IxHash';
|
||||
%hash = %{ $session->db->buildHashRefOfHashRefs($sql, [], 'fieldId') };
|
||||
return \%hash;
|
||||
}
|
||||
left join metaData_values d
|
||||
on f.fieldId=d.fieldId
|
||||
and d.assetId=?
|
||||
and d.revisionDate = ?
|
||||
";
|
||||
|
||||
my @where;
|
||||
my @place = ($self->getId, $self->get('revisionDate'));
|
||||
unless ($listAll) {
|
||||
# Either there's no class info stored for this field or this class is
|
||||
# one of them.
|
||||
push @where, q{
|
||||
not exists (
|
||||
select * from metaData_classes where fieldId = f.fieldId
|
||||
)
|
||||
or exists (
|
||||
select *
|
||||
from metaData_classes
|
||||
where className = ?
|
||||
and fieldId = f.fieldId
|
||||
)
|
||||
};
|
||||
push @place, ref $self;
|
||||
}
|
||||
|
||||
if ($fieldId) {
|
||||
push @where, 'f.fieldId = ?';
|
||||
push @place, $fieldId;
|
||||
}
|
||||
|
||||
if (@where) {
|
||||
$sql .= 'where ' . join(' AND ', map { "($_)" } @where);
|
||||
}
|
||||
|
||||
my $hash = $db->buildHashRefOfHashRefs( $sql, \@place, 'fieldId' );
|
||||
|
||||
return $fieldId ? $hash->{$fieldId} : $hash;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAllMetaDataFields
|
||||
|
||||
getMetaDataFields without bothering about whether they apply to this class.
|
||||
|
||||
=cut
|
||||
|
||||
sub getAllMetaDataFields {
|
||||
my $self = shift;
|
||||
return $self->_getMetaDataFieldsHelper(undef, 1);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getMetaDataFields ( [fieldId] )
|
||||
|
||||
Returns a hash reference containing all metadata field properties for this Asset.
|
||||
You can limit the output to a certain field by specifying a fieldId.
|
||||
|
||||
=head3 fieldId
|
||||
|
||||
If specified, the hashRef will contain only this field. In this case, you will
|
||||
get that metadata field if it exists whether it applies to this asset or not.
|
||||
|
||||
=cut
|
||||
|
||||
sub getMetaDataFields {
|
||||
my ($self, $fieldId) = @_;
|
||||
return $self->_getMetaDataFieldsHelper($fieldId);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -198,17 +308,10 @@ sub updateMetaData {
|
|||
my $self = shift;
|
||||
my $fieldId = shift;
|
||||
my $value = shift;
|
||||
my $db = $self->session->db;
|
||||
my ($exists) = $db->quickArray("select count(*) from metaData_values where assetId = ? and fieldId = ?",[$self->getId, $fieldId]);
|
||||
if (!$exists && $value ne "") {
|
||||
$db->write("insert into metaData_values (fieldId, assetId) values (?,?)",[$fieldId, $self->getId]);
|
||||
}
|
||||
if ($value eq "") { # Keep it clean
|
||||
$db->write("delete from metaData_values where assetId = ? and fieldId = ?",[$self->getId, $fieldId]);
|
||||
}
|
||||
else {
|
||||
$db->write("update metaData_values set value = ? where assetId = ? and fieldId=?", [$value, $self->getId, $fieldId]);
|
||||
}
|
||||
$self->session->db->write(
|
||||
'replace into metaData_values (fieldId, assetId, revisionDate, value) values (?, ?, ?, ?)',
|
||||
[$fieldId, $self->getId, $self->get('revisionDate'), $value]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -279,7 +382,49 @@ sub www_editMetaDataField {
|
|||
value=>$fieldInfo->{fieldType} || "text",
|
||||
types=> [ qw /text integer yesNo selectBox radioList checkList/ ]
|
||||
);
|
||||
$f->addField( "textarea",
|
||||
|
||||
my $default = ref WebGUI::Asset->assetName eq 'ARRAY'
|
||||
? WebGUI::International->new( $self->session )->get( @{WebGUI::Asset->assetName} )
|
||||
: WebGUI::Asset->assetName;
|
||||
my %classOptions;
|
||||
# usedNames maps a name to a class. If a name exists there, it has been
|
||||
# used. If it maps to a classname, that classname needs to be renamed.
|
||||
my %usedNames;
|
||||
for my $class (WebGUI::Pluggable::findAndLoad('WebGUI::Asset')) {
|
||||
next unless $class->isa('WebGUI::Asset');
|
||||
my $name = ref $class->assetName eq 'ARRAY'
|
||||
? WebGUI::International->new( $self->session )->get( @{$class->assetName} )
|
||||
: $class->assetName;
|
||||
next unless $name; # abstract classes (e.g. wobject) don't have names
|
||||
|
||||
# We don't want things named "Asset".
|
||||
if ($name eq $default) {
|
||||
$name = $class;
|
||||
}
|
||||
elsif (exists $usedNames{$name}) {
|
||||
if (my $rename = $usedNames{$name}) {
|
||||
$classOptions{$rename} = "$name ($rename)";
|
||||
undef $usedNames{$name};
|
||||
}
|
||||
$name = "$name ($class)";
|
||||
}
|
||||
$usedNames{$name} = $class;
|
||||
$classOptions{$class} = $name;
|
||||
}
|
||||
|
||||
$f->addField( "selectList",
|
||||
name => 'classes',
|
||||
label => $i18n->get('Allowed Classes'),
|
||||
hoverHelp => $i18n->get('Allowed Classes hoverHelp'),
|
||||
options => \%classOptions,
|
||||
defaultValue => $fid ne 'new' && $self->session->db->buildArrayRef(
|
||||
'select className from metaData_classes where fieldId = ?',
|
||||
[ $fid ]
|
||||
),
|
||||
sortByValue => 1,
|
||||
);
|
||||
|
||||
$f->addField( "textarea",
|
||||
name=>"possibleValues",
|
||||
label=>$i18n->get(487),
|
||||
hoverHelp=>$i18n->get('Possible Values description'),
|
||||
|
|
@ -332,6 +477,7 @@ sub www_editMetaDataFieldSave {
|
|||
$self->session->form->process("description") || '',
|
||||
$self->session->form->process("fieldType"),
|
||||
$self->session->form->process("possibleValues"),
|
||||
[ $self->session->form->process("classes") ],
|
||||
);
|
||||
|
||||
return $self->www_manageMetaData;
|
||||
|
|
@ -353,7 +499,7 @@ sub www_manageMetaData {
|
|||
my $i18n = WebGUI::International->new($self->session,"Asset");
|
||||
$ac->addSubmenuItem($self->getUrl('func=editMetaDataField'), $i18n->get("Add new field"));
|
||||
my $output;
|
||||
my $fields = $self->getMetaDataFields();
|
||||
my $fields = $self->getAllMetaDataFields;
|
||||
foreach my $fieldId (keys %{$fields}) {
|
||||
$output .= $self->session->icon->delete("func=deleteMetaDataField;fid=".$fieldId,$self->get("url"),$i18n->get('deleteConfirm'));
|
||||
$output .= $self->session->icon->edit("func=editMetaDataField;fid=".$fieldId,$self->get("url"));
|
||||
|
|
|
|||
|
|
@ -363,6 +363,8 @@ sub trash {
|
|||
return 1;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
require WebGUI::Workflow::Activity::DeleteExportedFiles;
|
||||
sub _invokeWorkflowOnExportedFiles {
|
||||
my $self = shift;
|
||||
|
|
|
|||
|
|
@ -89,13 +89,33 @@ sub addRevision {
|
|||
foreach my $table ($self->meta->get_tables) {
|
||||
$session->db->write( "insert into ".$table." (assetId,revisionDate) values (?,?)", [$self->getId, $now]);
|
||||
}
|
||||
|
||||
# Copy metadata values
|
||||
my $db = $self->session->db;
|
||||
my $id = $self->getId;
|
||||
my $then = $self->get('revisionDate');
|
||||
my $mdget = q{
|
||||
select fieldId, value from metaData_values
|
||||
where assetId = ? and revisionDate = ?
|
||||
};
|
||||
my $mdset = q{
|
||||
insert into metaData_values (fieldId, value, assetId, revisionDate)
|
||||
values (?, ?, ?, ?)
|
||||
};
|
||||
for my $row (@{ $db->buildArrayRefOfHashRefs($mdget, [ $id, $then ]) }) {
|
||||
$db->write($mdset, [ $row->{fieldId}, $row->{value}, $id, $now ]);
|
||||
}
|
||||
|
||||
$session->db->commit;
|
||||
|
||||
# current values, and the user set properties
|
||||
my %mergedProperties = (%{$self->get}, %{$properties}, );
|
||||
|
||||
# Set some defaults
|
||||
$mergedProperties{ revisedBy } ||= $session->user->userId;
|
||||
$mergedProperties{ revisedBy } = $properties->{ revisedBy } || $session->user->userId;
|
||||
|
||||
# Force the packed head block to be regenerated
|
||||
delete $mergedProperties{extraHeadTagsPacked};
|
||||
|
||||
#Instantiate new revision and fill with real data
|
||||
my $newVersion = WebGUI::Asset->newById($session, $self->getId, $now);
|
||||
|
|
@ -330,6 +350,10 @@ sub purgeRevision {
|
|||
if ($count < 1) {
|
||||
$db->write("update asset set isLockedBy=null where assetId=?",[$self->getId]);
|
||||
}
|
||||
$db->write(
|
||||
'delete from metaData_values where assetId=? and revisionDate=?',
|
||||
[ $self->getId, $self->get('revisionDate') ]
|
||||
);
|
||||
$db->commit;
|
||||
$self->purgeCache;
|
||||
$self->updateHistory("purged revision ".$self->get("revisionDate"));
|
||||
|
|
|
|||
|
|
@ -900,7 +900,7 @@ sub www_createAccountSave {
|
|||
my $username = $_[0];
|
||||
my $properties = $_[1];
|
||||
my $password = $_[2];
|
||||
my $profile = $_[3];
|
||||
my $profile = $_[3] || {};
|
||||
|
||||
my $i18n = WebGUI::International->new($self->session);
|
||||
|
||||
|
|
@ -910,6 +910,13 @@ sub www_createAccountSave {
|
|||
my $userId = $u->userId;
|
||||
$u->username($username);
|
||||
$u->authMethod($self->authMethod);
|
||||
$self->session->log->info( " override: " . $self->session->scratch->getLanguageOverride );
|
||||
use Data::Dumper;
|
||||
$self->session->log->info( Dumper $profile );
|
||||
|
||||
if (!$profile->{'language'} && $self->session->scratch->getLanguageOverride) {
|
||||
$profile->{'language'} = $self->session->scratch->getLanguageOverride;
|
||||
}
|
||||
$u->karma($self->session->setting->get("karmaPerLogin"),"Login","Just for logging in.") if ($self->session->setting->get("useKarma"));
|
||||
$u->updateProfileFields($profile) if ($profile);
|
||||
$self->update($properties);
|
||||
|
|
|
|||
|
|
@ -1127,7 +1127,13 @@ sub www_emailRecoverPasswordFinish {
|
|||
my $mail = WebGUI::Mail::Send->create($session, { to=>$email, subject=>$i18n->get('WebGUI password recovery')});
|
||||
my $vars = { };
|
||||
$vars->{recoverPasswordUrl} = $session->url->append($session->url->getSiteURL,'op=auth;method=emailResetPassword;token='.$recoveryGuid);
|
||||
my $template = WebGUI::Asset->newByDynamicClass($session, $session->setting->get('webguiPasswordRecoveryEmailTemplate'));
|
||||
my $templateId = $session->setting->get('webguiPasswordRecoveryEmailTemplate');
|
||||
my $template = WebGUI::Asset->newById($session, $templateId);
|
||||
if (!$template) {
|
||||
$session->errorHandler->error("Can't instantiate template $templateId for template email recovery");
|
||||
my $i18n = WebGUI::International->new($self->session, 'Asset');
|
||||
return $i18n->get('Error: Cannot instantiate template').' '.$templateId;
|
||||
}
|
||||
my $emailText = $template->process($vars);
|
||||
WebGUI::Macro::process($session, \$emailText);
|
||||
$mail->addText($emailText);
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ sub handler {
|
|||
return undef unless ($form->get("op") eq "account");
|
||||
|
||||
#Visitor cannot access the acccount system
|
||||
return $session->privilege->insufficient if($session->user->isVisitor);
|
||||
return $session->privilege->noAccess if($session->user->isVisitor);
|
||||
|
||||
my $module = $form->get("module");
|
||||
my $method = $form->get("do");
|
||||
|
|
|
|||
|
|
@ -452,7 +452,7 @@ sub init {
|
|||
$class->daemonize( $request, sub { $class->runCmd } );
|
||||
};
|
||||
}
|
||||
exit 0;
|
||||
CORE::exit(0);
|
||||
} ## end sub init
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ sub renderBar {
|
|||
my ( $process, $template, $extras ) = @_;
|
||||
my $session = $process->session;
|
||||
my $url = $session->url;
|
||||
my $style = $session->style;
|
||||
my $f = $session->form->paramsHashRef;
|
||||
my $tt = Template->new;
|
||||
my $dialog = delete $f->{dialog};
|
||||
|
|
@ -211,13 +212,18 @@ sub renderBar {
|
|||
return $styled;
|
||||
}
|
||||
else {
|
||||
my $console = WebGUI::AdminConsole->new( $session, $f->{icon} );
|
||||
my $style = $session->style;
|
||||
$link->query_form($f);
|
||||
$console->addSubmenuItem( $link->as_string, $label );
|
||||
$style->setLink($_, { rel => 'stylesheet' }) for @sheets;
|
||||
$style->setScript($_) for @scripts;
|
||||
return $console->render( $content, $title );
|
||||
if ( $session->var->isAdminOn ) {
|
||||
my $console = WebGUI::AdminConsole->new( $session, $f->{icon} );
|
||||
my $style = $session->style;
|
||||
$link->query_form($f);
|
||||
$console->addSubmenuItem( $link->as_string, $label );
|
||||
return $console->render( $content, $title );
|
||||
}
|
||||
else {
|
||||
return $session->style->userStyle( $content );
|
||||
}
|
||||
}
|
||||
} ## end sub renderBar
|
||||
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ my $template = <<'TEMPLATE';
|
|||
}
|
||||
tree = document.getElementById('tree');
|
||||
tree.innerHTML = '';
|
||||
_.each(JSON.parse(data.status), function (root) {
|
||||
_.each(YAHOO.lang.JSON.parse(data.status), function (root) {
|
||||
recurse(root, tree);
|
||||
});
|
||||
bar.update(finished, total);
|
||||
|
|
|
|||
|
|
@ -100,4 +100,37 @@ sub getName {
|
|||
return WebGUI::International->new($session, 'WebGUI')->get('codearea');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 headTags
|
||||
|
||||
Includes script files for the code area
|
||||
|
||||
=cut
|
||||
|
||||
sub headTags {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
$self->SUPER::headTags(@_);
|
||||
$session->style->setScript(
|
||||
$session->url->extras('yui-webgui/build/codeArea/codeArea-min.js')
|
||||
);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 toHtml
|
||||
|
||||
Add some javascript to fix hitting the tab key.
|
||||
|
||||
=cut
|
||||
|
||||
sub toHtml {
|
||||
my $self = shift;
|
||||
$self->headTags;
|
||||
my $id = $self->get('id');
|
||||
return $self->SUPER::toHtml(@_)
|
||||
. qq{<script>new YAHOO.WebGUI.CodeArea('$id').render()</script>};
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -245,7 +245,10 @@ sub toHtml {
|
|||
my $originalValue = $self->getOriginalValue;
|
||||
my $dt = eval { WebGUI::DateTime->new($session, $originalValue); };
|
||||
$dt = WebGUI::DateTime->new($session,0) if ! (blessed $dt && $dt->isa('DateTime')); ##Parsing error
|
||||
$dt->set_time_zone($session->datetime->getTimeZone);
|
||||
if ($originalValue =~ $isaEpoch) {
|
||||
##Epoch date, correct for time zone;
|
||||
$dt->set_time_zone($session->datetime->getTimeZone);
|
||||
}
|
||||
$value = $dt->toMysqlDate;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,6 +141,37 @@ sub getValueAsHtml {
|
|||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 headTags ( )
|
||||
|
||||
Set the head tags for this form plugin
|
||||
|
||||
=cut
|
||||
|
||||
sub headTags {
|
||||
my $self = shift;
|
||||
my $style = $self->session->style;
|
||||
my $url = $self->session->url;
|
||||
$style->setScript($url->extras('yui/build/yahoo/yahoo-min.js'), { type=>'text/javascript' });
|
||||
$style->setScript($url->extras('yui/build/dom/dom-min.js'), { type=>'text/javascript' });
|
||||
$style->setScript($url->extras('yui/build/event/event-min.js'), { type=>'text/javascript' });
|
||||
$style->setScript($url->extras("yui/build/datasource/datasource-min.js"), {type=>"text/javascript"});
|
||||
$style->setScript($url->extras('yui/build/connection/connection-min.js'), { type=>'text/javascript' });
|
||||
$style->setScript($url->extras('yui/build/element/element-min.js'), { type=>'text/javascript' });
|
||||
$style->setScript($url->extras('yui/build/button/button-min.js'), { type=>'text/javascript' });
|
||||
$style->setScript($url->extras('yui/build/container/container-min.js'), { type=>'text/javascript' });
|
||||
$style->setScript($url->extras("yui/build/autocomplete/autocomplete-min.js"), {type=>"text/javascript"});
|
||||
$style->setScript($url->extras('yui-webgui/build/form/form.js'), { type=>'text/javascript' });
|
||||
$style->setScript($url->extras('yui/build/json/json-min.js'), {type => 'text/javascript'});
|
||||
$style->setScript($url->extras('yui-webgui/build/i18n/i18n.js'), {type => 'text/javascript'} );
|
||||
$style->setScript($url->extras('yui-webgui/build/form/groupManager.js'), { type=>'text/javascript' });
|
||||
$style->setLink($url->extras('yui/build/autocomplete/assets/skins/sam/autocomplete.css'), { rel => 'stylesheet', type => 'text/css' });
|
||||
$style->setLink($url->extras('yui/build/container/assets/skins/sam/container.css'), { rel => 'stylesheet', type => 'text/css' });
|
||||
$style->setLink($url->extras('yui/build/button/assets/skins/sam/button.css'), { rel => 'stylesheet', type => 'text/css' });
|
||||
$style->setLink($url->extras('yui-webgui/build/form/groupManager.css'), { rel => 'stylesheet', type => 'text/css' });
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 isDynamicCompatible ( )
|
||||
|
|
@ -180,9 +211,9 @@ Creates a series of hidden fields representing the data in the list.
|
|||
=cut
|
||||
|
||||
sub toHtmlAsHidden {
|
||||
my $self = shift;
|
||||
$self->set("options", $self->session->db->buildHashRef("select groupId,groupName from groups"));
|
||||
return $self->SUPER::toHtmlAsHidden();
|
||||
my $self = shift;
|
||||
$self->set("options", $self->session->db->buildHashRef("select groupId,groupName from groups"));
|
||||
return $self->SUPER::toHtmlAsHidden();
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -194,14 +225,187 @@ Renders the form field to HTML as a table row complete with labels, subtext, hov
|
|||
=cut
|
||||
|
||||
sub toHtmlWithWrapper {
|
||||
my $self = shift;
|
||||
if ($self->session->user->isAdmin) {
|
||||
my $subtext = $self->session->icon->manage("op=listGroups");
|
||||
$self->set("subtext",$subtext . $self->get("subtext"));
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $user = $session->user;
|
||||
if ($user->isAdmin) {
|
||||
my $subtext = $session->icon->manage("op=listGroups");
|
||||
$self->set("subtext", $subtext . $self->get("subtext"));
|
||||
}
|
||||
my $dialog = $self->get('name') . '_groupDialog';
|
||||
my $group_manager = $user->isInGroup($session->setting->get('groupIdAdminGroup'));
|
||||
my $form;
|
||||
if ($group_manager) {
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $name = $self->get('name');
|
||||
my $groupId = $self->getOriginalValue;
|
||||
my $extra_subtext = qq!<span class="toolbarIcon" style="vertical-align:middle;"><a href="#" onClick="WebGUI.Form.GroupManager.show_dialog('$name'); return false;"><img src="!. $session->icon->getBaseURL().qq!edit.gif" alt="!. $i18n->get('Edit') .qq!"style="vertical-align:middle;border: 0px;" /></a></span>!;
|
||||
$extra_subtext .= qq!<span class="toolbarIcon" style="vertical-align:middle;"><a href="#" onClick="WebGUI.Form.GroupManager.show_dialog('$name', 'new'); return false;"><img src="!. $session->icon->getBaseURL().qq!add.gif" alt="!. $i18n->get('Add') .qq!" style="vertical-align:middle;border: 0px;" /></a></span>!;
|
||||
$self->set("subtext", $self->get('subtext').$extra_subtext);
|
||||
}
|
||||
$self->headTags;
|
||||
$form .= $self->SUPER::toHtmlWithWrapper;
|
||||
return $form;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_groupMembers ($session)
|
||||
|
||||
Returns a list of users that are in the sub-group specified by the form variable
|
||||
variable C<groupId>. Data returned is in JSON format.
|
||||
|
||||
This is a class method.
|
||||
|
||||
=head3 $session
|
||||
|
||||
A WebGUI::Session object.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_groupMembers {
|
||||
my $session = shift;
|
||||
return '{}' unless $session->user->isInGroup($session->setting->get('groupIdAdminGroup'));
|
||||
my $groupId = $session->form->param('groupId');
|
||||
return '{}' unless $groupId;
|
||||
|
||||
my $group = WebGUI::Group->new($session, $groupId);
|
||||
return '{}' unless $group;
|
||||
|
||||
my $results = {
|
||||
groupName => $group->name,
|
||||
users => [],
|
||||
groups => [],
|
||||
};
|
||||
my $userIds = $group->getUsers('withoutExpired');
|
||||
USER: foreach my $userId (@{ $userIds }) {
|
||||
my $user = WebGUI::User->new($session, $userId);
|
||||
next USER unless $user;
|
||||
push @{$results->{users}},
|
||||
{
|
||||
username => $user->username,
|
||||
userId => $userId,
|
||||
};
|
||||
}
|
||||
my $groupIds = $group->getGroupsIn(0); ##Without recursion
|
||||
GROUP: foreach my $groupId (@{ $groupIds }) {
|
||||
my $group = WebGUI::Group->new($session, $groupId);
|
||||
next GROUP unless $group;
|
||||
push @{$results->{groups}},
|
||||
{
|
||||
groupName => $group->name,
|
||||
groupId => $groupId,
|
||||
};
|
||||
}
|
||||
|
||||
return JSON::to_json($results);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_saveGroup ($session)
|
||||
|
||||
Save new information about the membership of a group, which users have
|
||||
been added and deleted, and which groups have been added and deleted.
|
||||
|
||||
This is a subroutine, not a class method, not an object method.
|
||||
|
||||
=head3 $session
|
||||
|
||||
A WebGUI::Session object.
|
||||
|
||||
=head3 Expected form variables
|
||||
|
||||
=head4 groupId
|
||||
|
||||
The GUID for the group to modify.
|
||||
|
||||
=head4 groupName
|
||||
|
||||
The name of the group. This is always set, so it should always be included.
|
||||
|
||||
=head4 usersAdded
|
||||
|
||||
A list of userId's for users who were added.
|
||||
|
||||
=head4 usersDeleted
|
||||
|
||||
A list of userId's for users who were deleted. Deleting happens after adding.
|
||||
|
||||
=head4 groupsAdded
|
||||
|
||||
A list of groupId's for groups who were added.
|
||||
|
||||
=head4 groupsDeleted
|
||||
|
||||
A list of groupId's for groups who were deleted. Deleting happens after adding.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_saveGroup {
|
||||
my $session = shift;
|
||||
$session->log->warn("hit the group plugin");
|
||||
return '{}' unless $session->user->isInGroup($session->setting->get('groupIdAdminGroup'));
|
||||
my $form = $session->form;
|
||||
my $groupId = $form->get('groupId');
|
||||
my $group = WebGUI::Group->new($session, $groupId);
|
||||
$session->log->warn("got groupId: $groupId");
|
||||
return '{}' unless $group;
|
||||
|
||||
$session->log->warn("updating group data, name = ".$form->get('groupName'));
|
||||
$group->name($form->get('groupName'));
|
||||
my @usersAdded = $form->get('usersAdded');
|
||||
use Data::Dumper;
|
||||
$session->log->warn("users added ".Dumper(\@usersAdded));
|
||||
$group->addUsers(\@usersAdded);
|
||||
my @usersDeleted = $form->get('usersDeleted');
|
||||
$group->deleteUsers(\@usersDeleted);
|
||||
my @groupsAdded = $form->get('groupsAdded');
|
||||
$session->log->warn("groups added ".Dumper(\@groupsAdded));
|
||||
$group->addGroups(\@groupsAdded);
|
||||
my @groupsDeleted = $form->get('groupsDeleted');
|
||||
$group->deleteGroups(\@groupsDeleted);
|
||||
|
||||
return JSON::to_json({ groupId => $group->getId, groupName => $group->name, originalGroupId => $groupId });
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_searchGroups ($session)
|
||||
|
||||
Returns groups that match the supplied group name. Group name is specified via the form
|
||||
variable C<search>. A list of groups will be returned of up to 15 names and groupIds.
|
||||
|
||||
This is a subroutine, not a class method, not an object method.
|
||||
|
||||
=head3 $session
|
||||
|
||||
A WebGUI::Session object.
|
||||
|
||||
=head3 Sample JSON
|
||||
|
||||
{
|
||||
'results' : [
|
||||
{
|
||||
'groupId': 'someGroupId',
|
||||
'groupName' : 'Great Group'
|
||||
}
|
||||
return $self->SUPER::toHtmlWithWrapper;
|
||||
//Other hashes may be in the list, or it could be completely empty
|
||||
]
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub www_searchGroups {
|
||||
my $session = shift;
|
||||
return '{"results":[]}' unless $session->user->isInGroup($session->setting->get('groupIdAdminGroup'));
|
||||
my $search = $session->form->param('query');
|
||||
|
||||
my $results = $session->db->buildArrayRefOfHashRefs(q|select groupId, groupName from groups where groupName like CONCAT(?, '%') and showInForms=1 LIMIT 15|, [ $search ]);
|
||||
|
||||
return JSON::to_json({ results => $results });
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
|
|
|
|||
|
|
@ -139,6 +139,8 @@ sub headTags {
|
|||
my ( $url, $style ) = $self->session->quick(qw( url style ));
|
||||
$style->setScript( $url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'));
|
||||
$style->setScript( $url->extras('yui/build/json/json-min.js'));
|
||||
$style->setScript( $url->extras('yui/build/connect/connect-min.js') );
|
||||
$style->setScript( $url->extras('yui-webgui/build/i18n/i18n.js') );
|
||||
$style->setScript( $url->extras('yui-webgui/build/form/jsontable.js'));
|
||||
}
|
||||
|
||||
|
|
@ -153,6 +155,7 @@ Renders an input tag of type text.
|
|||
sub toHtml {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new($session, 'WebGUI');
|
||||
my ( $url, $style ) = $session->quick(qw( url style ));
|
||||
my $value = $self->fixMacros($self->fixQuotes($self->fixSpecialCharacters($self->getOriginalValue)));
|
||||
my $output = '';
|
||||
|
|
@ -167,7 +170,7 @@ sub toHtml {
|
|||
# Buttons to add rows in the table footer
|
||||
my $cols = scalar @{ $self->get('fields') } + 1; # Extra column for buttons
|
||||
$output .= '</thead><tfoot><tr><td colspan="' . $cols . '">'
|
||||
. '<button id="' . $self->get('id') . '_add">' . "Add" . '</button>'
|
||||
. '<button id="' . $self->get('id') . '_add">' . $i18n->get('Add') . '</button>'
|
||||
. '</td></tr></tfoot>'
|
||||
;
|
||||
|
||||
|
|
@ -194,7 +197,10 @@ sub toHtml {
|
|||
elsif ( $field->{type} eq "id" ) {
|
||||
$fieldHtml .= '<input type="hidden" class="jsontable_id" name="' . $fieldName . '" value="new" />';
|
||||
}
|
||||
else { # Readonly or unknown
|
||||
elsif ( $field->{type} eq "hidden" || $field->{type} eq "readonly" ) {
|
||||
$fieldHtml .= '<input type="hidden" name="' . $fieldName . '" value="new" />';
|
||||
}
|
||||
else { # Unknown
|
||||
$fieldHtml = ' ';
|
||||
}
|
||||
|
||||
|
|
|
|||
122
lib/WebGUI/Form/TemplateParser.pm
Normal file
122
lib/WebGUI/Form/TemplateParser.pm
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
package WebGUI::Form::TemplateParser;
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 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::Form::SelectBox';
|
||||
use WebGUI::International;
|
||||
use Tie::IxHash;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Form::TemplateParser
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A dropdown list for selecting a template parser.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
This is a subclass of WebGUI::Form::SelectBox.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
The following methods are specifically available from this class. Check the superclass for additional methods.
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 areOptionsSettable
|
||||
|
||||
No, they aren't.
|
||||
|
||||
=cut
|
||||
|
||||
sub areOptionsSettable { 0 }
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( [ additionalTerms ] )
|
||||
|
||||
See the super class for additional details.
|
||||
|
||||
=head3 additionalTerms
|
||||
|
||||
The following additional parameters have been added via this sub class.
|
||||
|
||||
=head3 allowNone
|
||||
|
||||
Set to true if "None" is an acceptable option for this dropdown. Defaults to
|
||||
false.
|
||||
|
||||
=head4 defaultValue
|
||||
|
||||
Defaults to the default parser selected in the config file
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my ($class, $session, $definition) = @_;
|
||||
push @{$definition ||= []}, {
|
||||
allowNone => {
|
||||
defaultValue => 0,
|
||||
},
|
||||
defaultValue => {
|
||||
defaultValue => $session->config->get('defaultTemplateParser')
|
||||
}
|
||||
};
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getName ( session )
|
||||
|
||||
Returns the human readable name of this control.
|
||||
|
||||
=cut
|
||||
|
||||
sub getName {
|
||||
my ($self, $session) = @_;
|
||||
return WebGUI::International->new($session, 'WebGUI')->get('Template Parser');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getOptions
|
||||
|
||||
Called by the superclass to determine which options are presented.
|
||||
|
||||
=cut
|
||||
|
||||
sub getOptions {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
tie my %o, 'Tie::IxHash';
|
||||
if ($self->get('allowNone')) {
|
||||
$o{''} = WebGUI::International->new($session, 'WebGUI')->get('881');
|
||||
}
|
||||
return \%o unless my $parsers = $session->config->get('templateParsers');
|
||||
|
||||
for my $class (@$parsers) {
|
||||
my $parser = WebGUI::Asset::Template->getParser($session, $class);
|
||||
$o{$class} = $parser->getName;
|
||||
}
|
||||
|
||||
return \%o;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -157,6 +157,32 @@ sub getValue {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getValueAsHtml ( )
|
||||
|
||||
Return the Form's value as a formatted time.
|
||||
|
||||
=cut
|
||||
|
||||
sub getValueAsHtml {
|
||||
my $self = shift;
|
||||
my $value = $self->getOriginalValue();
|
||||
my $mysqlTime = ($value =~ $mysqlFormattedDate);
|
||||
my $digits = ($value =~ /^\d+$/);
|
||||
##Format is fine
|
||||
if ( $mysqlTime ) {
|
||||
return $value;
|
||||
}
|
||||
##Convert to mysql format
|
||||
elsif ($digits) {
|
||||
return $self->session->datetime->secondsToTime($value);
|
||||
}
|
||||
else { ##Bad stuff, maynard
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 headTags ( )
|
||||
|
||||
Set the head tags for this form plugin
|
||||
|
|
@ -164,8 +190,15 @@ Set the head tags for this form plugin
|
|||
=cut
|
||||
|
||||
sub headTags {
|
||||
my $self = shift;
|
||||
$self->session->style->setScript($self->session->url->extras('inputCheck.js'));
|
||||
my $self = shift;
|
||||
my $style = $self->session->style;
|
||||
my $url = $self->session->url;
|
||||
$style->setScript($url->extras('inputCheck.js'), { type => 'text/javascript' });
|
||||
$style->setScript($url->extras('yui/build/connection/connection-min.js'), { type => 'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/event/event-min.js'), { type => 'text/javascript' });
|
||||
$style->setScript($url->extras('yui/build/json/json-min.js'), { type => 'text/javascript' });
|
||||
$style->setScript($url->extras('yui-webgui/build/i18n/i18n.js' ), { type => 'text/javascript' });
|
||||
$style->setScript($url->extras('form/timefield.js'), { type => 'text/javascript' });
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -190,15 +223,11 @@ Renders a time field.
|
|||
|
||||
sub toHtml {
|
||||
my $self = shift;
|
||||
my $value = $self->getOriginalValue;
|
||||
my $i18n = WebGUI::International->new($self->session);
|
||||
$self->set("extras", $self->get('extras') . ' onkeyup="doInputCheck(document.getElementById(\''.$self->get("id").'\'),\'0123456789:\')"');
|
||||
return $self->SUPER::toHtml
|
||||
.WebGUI::Form::Button->new($self->session,
|
||||
id=>$self->get('id'),
|
||||
extras=>'style="font-size: 8pt;" onclick="window.timeField = this.form.'.$self->get("name").';clockSet = window.open(\''.$self->session->url->extras('timeChooser.html').'\',\'timeChooser\',\'WIDTH=230,HEIGHT=100\');return false"',
|
||||
value=>$i18n->get(970)
|
||||
)->toHtml;
|
||||
##JS expects formatted time
|
||||
$self->set('value', $self->getValueAsHtml);
|
||||
#my $i18n = WebGUI::International->new($self->session);
|
||||
$self->set("extras", $self->get('extras') . ' onblur="WebGUI.TimeField.munge(document.getElementById(\''.$self->get("id").'\'))" onkeyup="WebGUI.TimeField.check(document.getElementById(\''.$self->get("id").'\'));"');
|
||||
return $self->SUPER::toHtml;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -170,5 +170,25 @@ sub toHtml {
|
|||
)->toHtml).$manage;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_searchUsers
|
||||
|
||||
Returns users that match the supplied username. Username is specified via the form
|
||||
variable C<search>. A list of usernames will be returned of up to 15 names and userIds.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_searchUsers {
|
||||
my $session = shift;
|
||||
return '{"results":[]}' unless $session->user->isInGroup($session->setting->get('groupIdAdminUser'));
|
||||
my $search = $session->form->param('query');
|
||||
|
||||
my $results = $session->db->buildArrayRefOfHashRefs(q|select userId, username from users where username like CONCAT(?, '%') LIMIT 15|, [ $search ]);
|
||||
|
||||
return JSON::to_json({ results => $results });
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
|
|
|
|||
|
|
@ -92,9 +92,8 @@ An optional value to use instead of POST input.
|
|||
|
||||
sub getValue {
|
||||
my $self = shift;
|
||||
my $value = $self->SUPER::getValue(@_);
|
||||
my $value = uc $self->SUPER::getValue(@_);
|
||||
$value =~ tr/\r\n//d;
|
||||
$value =~ tr/a-z/A-Z/;
|
||||
if ($value =~ /^[A-Z\d\s\-]+$/) {
|
||||
return $value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ sub addGroups {
|
|||
my $group = WebGUI::Group->new($self->session, $gid);
|
||||
my $recursive = $self->getId ~~ $group->getGroupsIn(1);
|
||||
next GROUP if $recursive;
|
||||
$self->session->db->write("insert into groupGroupings (groupId,inGroup) values (?,?)",[$gid, $self->getId]);
|
||||
$self->session->db->write("REPLACE into groupGroupings (groupId,inGroup) values (?,?)",[$gid, $self->getId]);
|
||||
}
|
||||
$self->clearCaches();
|
||||
return 1;
|
||||
|
|
@ -212,7 +212,7 @@ sub addUsers {
|
|||
foreach my $uid (@{$users}) {
|
||||
my ($isIn) = $self->session->db->quickArray("select count(*) from groupings where groupId=? and userId=?", [$self->getId, $uid]);
|
||||
unless ($isIn) {
|
||||
$self->session->db->write("insert into groupings (groupId,userId,expireDate) values (?,?,?)", [$self->getId, $uid, (time()+$expireOffset)]);
|
||||
$self->session->db->write("REPLACE into groupings (groupId,userId,expireDate) values (?,?,?)", [$self->getId, $uid, (time()+$expireOffset)]);
|
||||
$self->session->stow->delete("gotGroupsForUser");
|
||||
} else {
|
||||
$self->userGroupExpireDate($uid,(time()+$expireOffset));
|
||||
|
|
@ -1007,24 +1007,33 @@ sub getUsersNotIn {
|
|||
if($groupId eq "") {
|
||||
return $self->getUsers($withoutExpired);
|
||||
}
|
||||
my $selfWhere;
|
||||
if ( $self->getId ne '2' ) {
|
||||
$selfWhere = "and groupId=" . $self->session->db->dbh->quote( $self->getId );
|
||||
}
|
||||
else {
|
||||
$selfWhere = 'and userId != ' . $self->session->db->dbh->quote( "1" );
|
||||
}
|
||||
|
||||
my $expireTime = 0;
|
||||
if ($withoutExpired) {
|
||||
$expireTime = time();
|
||||
}
|
||||
|
||||
my $sql = q{
|
||||
my $sql = qq{
|
||||
select
|
||||
userId
|
||||
from
|
||||
groupings
|
||||
users
|
||||
left join
|
||||
groupings using (userId)
|
||||
where
|
||||
expireDate > ?
|
||||
and groupId=?
|
||||
$selfWhere
|
||||
and userId not in (select userId from groupings where expireDate > ? and groupId=?)
|
||||
};
|
||||
|
||||
my @users = $self->session->db->buildArray($sql, [$expireTime,$self->getId,$expireTime,$groupId]);
|
||||
my @users = $self->session->db->buildArray($sql, [$expireTime,$expireTime,$groupId]);
|
||||
return \@users;
|
||||
|
||||
}
|
||||
|
|
|
|||
60
lib/WebGUI/Help/Asset_Dashboard.pm
Normal file
60
lib/WebGUI/Help/Asset_Dashboard.pm
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
package WebGUI::Help::Asset_Dashboard;
|
||||
use strict;
|
||||
|
||||
our $HELP = {
|
||||
|
||||
'dashboard template' => {
|
||||
title => 'Dashboard Template Variables',
|
||||
isa => [
|
||||
{ namespace => "Asset_Dashboard",
|
||||
tag => "dashboard asset template variables"
|
||||
},
|
||||
{ namespace => "Asset",
|
||||
tag => "asset template"
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
{ name => 'dragger.init' },
|
||||
{ name => 'fullUrl' },
|
||||
{ name => 'canEdit' },
|
||||
{ name => 'positionN_loop',
|
||||
variables => [
|
||||
{ 'name' => 'id' },
|
||||
{ 'name' => 'content' },
|
||||
{ 'name' => 'dashletTitle' },
|
||||
{ 'name' => 'shortcutUrl' },
|
||||
{ 'name' => 'dashletUrl' },
|
||||
{ 'name' => 'canDelete' },
|
||||
{ 'name' => 'canMove' },
|
||||
{ 'name' => 'canPersonalize' },
|
||||
{ 'name' => 'showReloadIcon' },
|
||||
{ 'name' => 'canEditUserPrefs' },
|
||||
{ 'name' => 'editFormUrl' },
|
||||
]
|
||||
},
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
'dashboard asset template variables' => {
|
||||
private => 1,
|
||||
title => 'dashboard asset template variables title',
|
||||
isa => [
|
||||
{ namespace => "Asset_Wobject",
|
||||
tag => "wobject template variables"
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
{ name => 'templateId' },
|
||||
{ name => 'adminsGroupId' },
|
||||
{ name => 'usersGroupId' },
|
||||
{ name => 'isInitialized' },
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
59
lib/WebGUI/Help/Asset_Map.pm
Normal file
59
lib/WebGUI/Help/Asset_Map.pm
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
package WebGUI::Help::Asset_Map;
|
||||
use strict;
|
||||
|
||||
our $HELP = {
|
||||
|
||||
'view template' => {
|
||||
title => 'view template',
|
||||
body => '',
|
||||
isa => [
|
||||
{ namespace => 'Asset_Template',
|
||||
tag => 'template variables'
|
||||
},
|
||||
{ namespace => 'Asset_Map',
|
||||
tag => 'map asset template variables'
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
{ name => 'canAddPoint', },
|
||||
{ name => 'canEdit', },
|
||||
{ name => 'mapPoints', required => 1, },
|
||||
{ name => 'button_addPoint', required => 1, },
|
||||
{ name => 'button_setCenter', required => 1, },
|
||||
{ name => 'button_setCenter', selectPoint => 1, },
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
'map asset template variables' => {
|
||||
private => 1,
|
||||
title => 'map asset template variables',
|
||||
body => '',
|
||||
isa => [
|
||||
{ namespace => 'Asset',
|
||||
tag => 'asset template asset variables'
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
{ name => 'groupIdAddPoint', },
|
||||
{ name => 'mapApiKey', },
|
||||
{ name => 'mapHeight', },
|
||||
{ name => 'mapWidth', },
|
||||
{ name => 'startLatitude', },
|
||||
{ name => 'startLongitude', },
|
||||
{ name => 'startZoom', },
|
||||
{ name => 'templateIdEditPoint', },
|
||||
{ name => 'templateIdView', },
|
||||
{ name => 'templateIdViewPoint', },
|
||||
{ name => 'workflowIdPoint', },
|
||||
{ name => 'canAddPoint', },
|
||||
{ name => 'canEdit', },
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
@ -10,6 +10,9 @@ our $HELP = {
|
|||
{ namespace => 'Asset_Template',
|
||||
tag => 'template variables'
|
||||
},
|
||||
{ namespace => 'Asset_MapPoint',
|
||||
tag => 'map point asset template variables'
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
|
|
@ -31,6 +34,9 @@ our $HELP = {
|
|||
{ name => 'form_phone', },
|
||||
{ name => 'form_fax', },
|
||||
{ name => 'form_email', },
|
||||
{ name => 'user defined variables', },
|
||||
{ name => 'form_isHidden', },
|
||||
{ name => 'form_isGeocoded', },
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
|
@ -60,6 +66,11 @@ our $HELP = {
|
|||
{ name => 'phone', },
|
||||
{ name => 'fax', },
|
||||
{ name => 'email', },
|
||||
{ name => 'userDefined1', },
|
||||
{ name => 'userDefined2', },
|
||||
{ name => 'userDefined3', },
|
||||
{ name => 'userDefined4', },
|
||||
{ name => 'userDefined5', },
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ our $HELP = {
|
|||
{ name => 'imgUrl', },
|
||||
{ name => 'imgFilename', },
|
||||
{ name => 'newUploadForm', },
|
||||
{ name => 'imgRemoteUrlForm', },
|
||||
{ name => 'imgCaptionForm', },
|
||||
{ name => 'imgBylineForm', },
|
||||
{ name => 'imgAltForm', },
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ our $HELP = {
|
|||
{ name => 'editIcon' },
|
||||
],
|
||||
},
|
||||
{ name => 'topStory' },
|
||||
{ name => 'topStoryDeleteIcon',
|
||||
description => 'deleteIcon', },
|
||||
{ name => 'topStoryEditIcon',
|
||||
|
|
@ -46,7 +47,12 @@ our $HELP = {
|
|||
{ name => 'rssUrl' },
|
||||
{ name => 'atomUrl' },
|
||||
],
|
||||
related => []
|
||||
related => [
|
||||
{
|
||||
namespace => 'Asset_Story',
|
||||
tag => 'view template',
|
||||
}
|
||||
],
|
||||
},
|
||||
|
||||
'storytopic asset template variables' => {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ our $HELP = {
|
|||
{ 'name' => 'category' },
|
||||
{ 'name' => 'author' },
|
||||
{ 'name' => 'guid' },
|
||||
{ 'name' => 'media' },
|
||||
{ 'name' => 'description' },
|
||||
{ 'name' => 'descriptionFirst100words' },
|
||||
{ 'name' => 'descriptionFirst75words' },
|
||||
|
|
|
|||
|
|
@ -152,6 +152,9 @@ our $HELP = {
|
|||
{ 'name' => 'field_pretext' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'name' => 'variables by label',
|
||||
},
|
||||
],
|
||||
related => [
|
||||
{ tag => 'edit thing template',
|
||||
|
|
|
|||
|
|
@ -740,6 +740,9 @@ our $HELP = {
|
|||
{
|
||||
name => 'viewItemUrl',
|
||||
},
|
||||
{
|
||||
name => 'hasSku',
|
||||
},
|
||||
{
|
||||
name => 'price',
|
||||
description => 'price help',
|
||||
|
|
|
|||
43
lib/WebGUI/ICal.pm
Normal file
43
lib/WebGUI/ICal.pm
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
package WebGUI::ICal;
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 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
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::ICal
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This package wraps Data::ICal so the PRODUCT_ID parameter in the generated iCal feeds are set appropriately.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use WebGUI::ICal;
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
use WebGUI;
|
||||
use base 'Data::ICal';
|
||||
|
||||
=head2 product_id
|
||||
|
||||
Override the method from Data::ICal to set it to be the WebGUI version and status.
|
||||
|
||||
=cut
|
||||
|
||||
sub product_id {
|
||||
return 'WebGUI '. $WebGUI::VERSION . '-' . $WebGUI::STATUS;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -35,8 +35,6 @@ This package provides an interface to the internationalization system.
|
|||
$string = $i->get($internationalId);
|
||||
$string = $i->get($internationalId, $otherNamespace);
|
||||
|
||||
$url = $i->makeUrlCompliant($url);
|
||||
|
||||
$hashRef = $i->getLanguage($lang);
|
||||
|
||||
$hashRef = $i->getLanguages();
|
||||
|
|
@ -206,6 +204,7 @@ sub getLanguages {
|
|||
my ($self) = @_;
|
||||
my $hashRef;
|
||||
for my $lang ( findsubmod 'WebGUI::i18n' ) {
|
||||
$self->session->log->info( "Found language $lang" );
|
||||
$lang =~ s/^WebGUI::i18n:://;
|
||||
$hashRef->{$lang} = $self->getLanguage($lang, "label");
|
||||
}
|
||||
|
|
@ -217,6 +216,8 @@ sub getLanguages {
|
|||
|
||||
=head2 makeUrlCompliant ( url [ , language ] )
|
||||
|
||||
THIS METHOD IS DEPRECATED AND WILL BE REMOVED FROM WEBGUI.
|
||||
|
||||
Manipulates a URL to make sure it will work on the internet. It removes things like non-latin characters, etc.
|
||||
|
||||
=head3 url
|
||||
|
|
@ -231,11 +232,7 @@ Specify a default language. Defaults to user preference or "English".
|
|||
|
||||
sub makeUrlCompliant {
|
||||
my ($self, $url, $language) = @_;
|
||||
$language = $language || $self->{_language} || $self->session->user->get("language") || "English";
|
||||
my $cmd = "WebGUI::i18n::".$language;
|
||||
WebGUI::Pluggable::load($cmd);
|
||||
my $output = WebGUI::Pluggable::run($cmd, 'makeUrlCompliant', [$url]);
|
||||
return $output;
|
||||
return $url;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -228,11 +228,20 @@ sub generateCloud {
|
|||
[ $options->{startAsset}->get("lineage").'%', @extraPlaceholders, $maxKeywords ]);
|
||||
my $cloud = HTML::TagCloud->new(levels=>$options->{cloudLevels} || 24);
|
||||
while (my ($count, $keyword) = $sth->array) {
|
||||
my $url
|
||||
= $urlCallback ? $display->$urlCallback($keyword)
|
||||
: $options->{displayFunc} ? $display->getUrl("func=".$options->{displayFunc}.";keyword=".$keyword)
|
||||
: $display->getUrl("keyword=".$keyword)
|
||||
;
|
||||
my $url;
|
||||
if ($urlCallback) {
|
||||
$url = $display->$urlCallback($keyword);
|
||||
}
|
||||
else {
|
||||
my @q = ( [ 'keyword', $keyword, ] );
|
||||
my $e = $self->session->url;
|
||||
if (my $func = $options->{displayFunc}) {
|
||||
unshift @q, [ 'func', $func ];
|
||||
}
|
||||
$url = $display->getUrl(
|
||||
join(';', map { join '=', $_->[0], $e->escape($_->[1]) } @q)
|
||||
);
|
||||
}
|
||||
$cloud->add($keyword, $url, $count);
|
||||
}
|
||||
return $cloud->html_and_css($maxKeywords);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,15 @@ Defaults to 'url'. But if you want to use an assetId as the first parameter, the
|
|||
#-------------------------------------------------------------------
|
||||
sub process {
|
||||
my ($session, $identifier, $type) = @_;
|
||||
if (!$identifier) {
|
||||
$session->errorHandler->warn('AssetProxy macro called without an asset to proxy. '
|
||||
. 'The macro was called through this url: '.$session->asset->get('url'));
|
||||
if ($session->isAdminOn) {
|
||||
my $i18n = WebGUI::International->new($session, 'Macro_AssetProxy');
|
||||
return $i18n->get('invalid url');
|
||||
}
|
||||
return;
|
||||
}
|
||||
my $perfLog = $session->log->performanceLogger;
|
||||
my $t = $perfLog ? [Time::HiRes::gettimeofday()] : undef;
|
||||
my $asset;
|
||||
|
|
|
|||
|
|
@ -46,14 +46,17 @@ sub process {
|
|||
my $asset = eval { WebGUI::Asset->newByUrl($session,$url); };
|
||||
my $i18n = WebGUI::International->new($session, 'Macro_FileUrl');
|
||||
if (Exception::Class->caught()) {
|
||||
$session->log->warn("Invalid Asset URL for url: " . $url);
|
||||
return $i18n->get('invalid url');
|
||||
}
|
||||
my $storageId = $asset->can('storageId') ? $asset->storageId : undef;
|
||||
if (not defined $storageId) {
|
||||
$session->log->warn("No Storage Location for assetId: " . $asset->getId . " url: $url");
|
||||
return $i18n->get('no storage');
|
||||
}
|
||||
my $filename = $asset->can('filename') ? $asset->filename : undef;
|
||||
if (not defined $filename) {
|
||||
$session->log->warn("No Filename for assetId: " . $asset->getId . " url: $url");
|
||||
return $i18n->get('no filename');
|
||||
}
|
||||
my $storage = WebGUI::Storage->get($session,$storageId);
|
||||
|
|
|
|||
48
lib/WebGUI/Macro/LastUpdatedBy.pm
Normal file
48
lib/WebGUI/Macro/LastUpdatedBy.pm
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package WebGUI::Macro::LastUpdatedBy;
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# WebGUI is Copyright 2001-2009 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
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
use strict;
|
||||
use WebGUI::Asset;
|
||||
use WebGUI::User;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Macro::LastUpdatedBy
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Macro for displaying the username of the user that made the most recent revision of current Asset.
|
||||
|
||||
=head2 process ( )
|
||||
|
||||
Display the username, if the user still exists in the system. If not, of if the user does not
|
||||
have a username, then display an internationalized label for "Unknown".
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub process {
|
||||
my $session = shift;
|
||||
return '' unless $session->asset;
|
||||
|
||||
my $userId = $session->asset->getContentLastModifiedBy();
|
||||
my $user = WebGUI::User->new($session, $userId);
|
||||
if ($user && $user->username) {
|
||||
return $user->username;
|
||||
}
|
||||
|
||||
my $i18n = WebGUI::International->new($session,'Macro_LastModified');
|
||||
return $i18n->get('Unknown');
|
||||
}
|
||||
|
||||
1;
|
||||
66
lib/WebGUI/Macro/RenderThingData.pm
Normal file
66
lib/WebGUI/Macro/RenderThingData.pm
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
package WebGUI::Macro::RenderThingData;
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# WebGUI is Copyright 2001-2011 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
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
use strict;
|
||||
use WebGUI::Group;
|
||||
use WebGUI::Asset::Template;
|
||||
use WebGUI::Asset::Wobject::Thingy;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Macro::RenderThingData
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Macro that allows users to render thing data.
|
||||
|
||||
=head2 process ( thingURL, templateHint )
|
||||
|
||||
=head3 thingHint
|
||||
|
||||
The URL from which to pull the thingId and thingDataId
|
||||
|
||||
=head3 templateHint
|
||||
|
||||
Optional. Specifies the templateId or template url to use. If omitted, the default thingy view template will be used.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub process {
|
||||
my ($session, $thingDataUrl, $templateHint ) = @_;
|
||||
|
||||
my $uri = URI->new( $thingDataUrl );
|
||||
|
||||
my $urlHash = { $uri->query_form };
|
||||
my $thingId = $urlHash->{'thingId'};
|
||||
my $thingDataId = $urlHash->{'thingDataId'};
|
||||
|
||||
my $thing = WebGUI::Asset::Wobject::Thingy->newByUrl( $session, $uri->path );
|
||||
|
||||
# TODO: i18n
|
||||
return ( "Bad URL: " . $thingDataUrl ) if !$thing || !$thingId || !$thingDataId;
|
||||
|
||||
# Render
|
||||
my $output = $thing->www_viewThingData( $thingId, $thingDataId, $templateHint );
|
||||
|
||||
# FIX: Temporary solution (broken map due to template rendering <script> tags)
|
||||
return "RenderThingData: Please specify a template." if !$templateHint;
|
||||
return "RenderThingData: Contained bad tags!" if $output =~ /script>/;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
|
|
@ -60,6 +60,9 @@ sub call {
|
|||
$privs = JSON->new->utf8->decode($contents);
|
||||
}
|
||||
|
||||
return @$r = (403, [ 'Content-Type' => 'text/plain' ], [ 'Forbidden' ])
|
||||
if $privs->{state} eq 'trash';
|
||||
|
||||
require WebGUI::Asset;
|
||||
my $userId = $session->get('userId');
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,8 @@ sub getOperations {
|
|||
'listGroups' => 'Group',
|
||||
'manageGroupsInGroup' => 'Group',
|
||||
'manageUsersInGroup' => 'Group',
|
||||
'manageGroups' => 'Group',
|
||||
'updateGroupUsers' => 'Group',
|
||||
|
||||
'viewHelp' => 'Help',
|
||||
'viewHelpIndex' => 'Help',
|
||||
|
|
|
|||
|
|
@ -826,6 +826,11 @@ sub www_emailGroup {
|
|||
-label=>$i18n->get(229),
|
||||
-hoverHelp=>$i18n->get('229 description'),
|
||||
);
|
||||
$f->yesNo(
|
||||
-name=>'override',
|
||||
-label=>$i18n->get('override user email preference'),
|
||||
-hoverHelp=>$i18n->get('override user email preference description'),
|
||||
);
|
||||
$f->HTMLArea(
|
||||
-name=>"message",
|
||||
-label=>$i18n->get(230),
|
||||
|
|
@ -851,11 +856,21 @@ A WebGUI::Session object
|
|||
|
||||
sub www_emailGroupSend {
|
||||
my $session = shift;
|
||||
return $session->privilege->adminOnly() unless (canEditGroup($session,$session->form->process("gid")) && $session->form->validToken);
|
||||
my $mail = WebGUI::Mail::Send->create($session, {toGroup=>$session->form->process("gid"),subject=>$session->form->process("subject"),from=>$session->form->process("from")});
|
||||
$mail->addHtml($session->form->process("message","HTMLArea"));
|
||||
$mail->addFooter;
|
||||
$mail->queue;
|
||||
my $f = $session->form;
|
||||
return $session->privilege->adminOnly()
|
||||
unless (canEditGroup($session,$f->get('gid')) && $f->validToken);
|
||||
|
||||
WebGUI::Inbox::Message->create(
|
||||
$session, {
|
||||
groupId => $f->get('gid'),
|
||||
subject => $f->get('subject'),
|
||||
status => 'unread',
|
||||
message => $f->process('message', 'HTMLArea'),
|
||||
sentBy => $session->user->userId,
|
||||
overridePerUserDelivery => $f->get('override'),
|
||||
extraHeaders => { from => $f->get('from') }
|
||||
}
|
||||
);
|
||||
my $i18n = WebGUI::International->new($session);
|
||||
return _submenu($session,$i18n->get(812));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,12 +26,15 @@ TODO
|
|||
|
||||
=head2 www_ssoViaSessionId
|
||||
|
||||
TODO: DOCUMENT ME
|
||||
Allows a user to login as another user, by referencing that user's sessionId. Requires that
|
||||
sessionId is passed as a form or URL parameter. It does NOT duplicate the original user's session,
|
||||
it just switches you to that user.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_ssoViaSessionId {
|
||||
my $session = shift;
|
||||
return undef unless $session->config->get('enableSimpleSSO');
|
||||
my $sessionId = $session->form->get("sessionId");
|
||||
if (defined $sessionId && $sessionId ne "") {
|
||||
if ($sessionId eq $session->getId) {
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ sub formProperties {
|
|||
$properties{ options } = $orderedValues;
|
||||
$properties{ forceImageOnly } = $self->get("forceImageOnly");
|
||||
$properties{ dataDefault } = $self->get("dataDefault");
|
||||
$properties{ extras } = $self->get("extras");
|
||||
return \%properties;
|
||||
}
|
||||
|
||||
|
|
@ -335,6 +336,11 @@ sub formField {
|
|||
if(!defined $properties->{value}) {
|
||||
$properties->{value} = WebGUI::Operation::Shared::secureEval($session,$properties->{dataDefault});
|
||||
}
|
||||
if ($self->getId eq "language") {
|
||||
if ($self->session->scratch->getLanguageOverride) {
|
||||
$properties->{value} = $self->session->scratch->getLanguageOverride;
|
||||
}
|
||||
}
|
||||
}
|
||||
my $form = WebGUI::Form::DynamicField->new($session,%{$properties});
|
||||
return $form if $returnObject;
|
||||
|
|
|
|||
124
lib/WebGUI/Role/Asset/Dashlet.pm
Normal file
124
lib/WebGUI/Role/Asset/Dashlet.pm
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
package WebGUI::Role::Asset::Dashlet;
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
WebGUI::AssetAspect::Dashlet - Implement features to turn Assets into Dashlets
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
This Aspect provides methods that allow a Dashboard to determine, store and retrieve
|
||||
customization options for Assets.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 fetchUserOverrides ($dashboardAssetId, [$userId])
|
||||
|
||||
Retrieve user preferences for a particular dashboard and user for this Asset from the database.
|
||||
|
||||
=head3 $dashboardId
|
||||
|
||||
The assetId of the dashboard to reference.
|
||||
|
||||
=head3 $userId
|
||||
|
||||
The userId to whose preferences should be returned. Uses the current session user if omitted.
|
||||
|
||||
=cut
|
||||
|
||||
sub fetchUserOverrides {
|
||||
my $self = shift;
|
||||
my $dashboardAssetId = shift;
|
||||
my $userId = shift || $self->session->user->userId;
|
||||
my $properties_json = $self->session->db->quickScalar('select properties from Dashboard_userPrefs where dashboardAssetId=? and userId=? and dashletAssetId=?',[$dashboardAssetId, $userId, $self->getId,]);
|
||||
$properties_json ||= '{}';
|
||||
my $properties = from_json($properties_json);
|
||||
return $properties;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getOverrideFormDefinition
|
||||
|
||||
Return an array ref of form properties. The form properties are those that the
|
||||
Asset has marked as being able to be overridden by a Dashboard asset by giving
|
||||
the property the dashletOverridable flag.
|
||||
|
||||
Assets that want to allow additional properties outside of their definition should
|
||||
override and extend this method.
|
||||
|
||||
=cut
|
||||
|
||||
sub getOverrideFormDefinition {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my @properties;
|
||||
foreach my $property ( $self->getProperties ) {
|
||||
my $fieldHash = $self->getFieldData( $property );
|
||||
next unless $fieldHash->{dashletOverridable};
|
||||
$fieldHash->{name} = $property;
|
||||
push @properties, $fieldHash;
|
||||
}
|
||||
return @properties;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getUserOverrides
|
||||
|
||||
Store user preferences for this Asset. This is direct reference from inside the object, so
|
||||
if you plan to modify the data, Clone it first.
|
||||
|
||||
=cut
|
||||
|
||||
sub getUserOverrides {
|
||||
return shift->{_userOverrides};
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 setUserOverrides
|
||||
|
||||
Store user preferences for this Asset.
|
||||
|
||||
=cut
|
||||
|
||||
sub setUserOverrides {
|
||||
shift->{_userOverrides} = shift;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 storeUserOverrides ($dashboardAssetId, $properties, [$userId])
|
||||
|
||||
Store user preferences for a particular dashboard and user for this Asset to the database.
|
||||
|
||||
=head3 $dashboardId
|
||||
|
||||
The assetId of the dashboard to reference.
|
||||
|
||||
=head3 $userId
|
||||
|
||||
The userId to whose preferences should be returned. Uses the current session user if omitted.
|
||||
|
||||
=cut
|
||||
|
||||
sub storeUserOverrides {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $dashboardAssetId = shift;
|
||||
my $properties = shift;
|
||||
my $userId = shift || $session->user->userId;
|
||||
my $properties_json = to_json($properties);
|
||||
$session->db->write('DELETE FROM Dashboard_userPrefs where dashboardAssetId=? and userId=? and dashletAssetId=?',[$dashboardAssetId, $userId, $self->getId]);
|
||||
$session->db->write('INSERT INTO Dashboard_userPrefs (dashboardAssetId, userId, dashletAssetId, properties) VALUES (?,?,?,?)', [$dashboardAssetId, $userId, $self->getId, $properties_json]);
|
||||
}
|
||||
|
||||
|
||||
1; # You can't handle the truth
|
||||
|
|
@ -76,14 +76,15 @@ override duplicate => sub {
|
|||
|
||||
=head2 addRevision ( properties [, revisionDate, options ] )
|
||||
|
||||
Extend addRevision to set skipNotification to 0 for each new revision.
|
||||
Override addRevision to set skipNotification to 0 for each new revision. This preserves whether or
|
||||
not a notification was sent for the previous revision.
|
||||
|
||||
=cut
|
||||
|
||||
around addRevision => sub {
|
||||
my $orig = shift;
|
||||
my $self = shift;
|
||||
my $properties = shift;
|
||||
my $properties = shift || {};
|
||||
|
||||
$properties->{ skipNotification } = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -285,6 +285,9 @@ A hash reference containing rules for a search. The rules will will be hash refe
|
|||
|
||||
{ keywords => "something to search for", lineage => [ "000001000005", "000001000074000003" ] };
|
||||
|
||||
All rules, except for assetIds, are logically AND'ed together to create a finer search. assetIds are OR'ed to the final
|
||||
query.
|
||||
|
||||
=head4 keywords
|
||||
|
||||
This rule limits the search results to assets that match keyword criteria.
|
||||
|
|
@ -303,6 +306,8 @@ This rule limits the search to a specific set of assetIds. An array reference of
|
|||
|
||||
assetIds => [ "PBasset000000000000001", ]
|
||||
|
||||
Unlike every other rule, this rule is logically OR'ed with the other rules.
|
||||
|
||||
=head4 classes
|
||||
|
||||
This rule limits the search to a specific set of asset classes. An array reference of class names.
|
||||
|
|
|
|||
|
|
@ -35,12 +35,12 @@ These methods are available from this package:
|
|||
|
||||
=cut
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addFile ( path )
|
||||
|
||||
Use an external filter defined in the config file as searchIndexerPlugins.
|
||||
Use an external filter defined in the config file as searchIndexerPlugins to pull keywords from a file and
|
||||
add them to the index.
|
||||
|
||||
=head3 path
|
||||
|
||||
|
|
@ -51,22 +51,11 @@ The path to the filename to index, including the filename.
|
|||
sub addFile {
|
||||
my $self = shift;
|
||||
my $path = shift;
|
||||
my $filters = $self->session->config->get("searchIndexerPlugins");
|
||||
my $content;
|
||||
if ($path =~ m/\.(\w+)$/) {
|
||||
my $type = lc($1);
|
||||
if ($filters->{$type}) {
|
||||
open my $fh, "$filters->{$type} $path |" or return undef; # open pipe to filter
|
||||
$content = do { local $/; <$fh> }; # slurp file
|
||||
close $fh;
|
||||
}
|
||||
}
|
||||
return $self->addKeywords($content)
|
||||
if $content =~ m/\S/; # only index if we fine non-whitespace
|
||||
return undef;
|
||||
my $keywords = $self->getKeywordsForFile($path);
|
||||
return unless $keywords =~ /\S/;
|
||||
return $self->addKeywords($keywords)
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addKeywords ( text )
|
||||
|
|
@ -84,8 +73,40 @@ sub addKeywords {
|
|||
my $text = join(" ", @_);
|
||||
|
||||
$text = $self->_filterKeywords($text);
|
||||
my ($keywords) = $self->session->db->quickArray("select keywords from assetIndex where assetId=?",[$self->getId]);
|
||||
$self->session->db->write("update assetIndex set keywords =? where assetId=?", [$keywords.' '.$text, $self->getId]);
|
||||
my ($keywords) = $self->session->db->quickArray("select keywords from assetIndex where assetId=? and url=?",[$self->getId, $self->asset->get('url')]);
|
||||
$self->session->db->write("update assetIndex set keywords =? where assetId=? and url=?", [$keywords.' '.$text, $self->getId, $self->asset->get('url')]);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addRecord ( %fields )
|
||||
|
||||
Adds a duplicate record for the current asset, along with fields that are overridden.
|
||||
|
||||
=head3 %fields
|
||||
|
||||
A hash of fields to override in the record. Entries for url and keywords are mandatory, and
|
||||
no record will be added unless they exist in the hash.
|
||||
|
||||
The lineage entry cannot be overridden.
|
||||
|
||||
=cut
|
||||
|
||||
sub addRecord {
|
||||
my $self = shift;
|
||||
my %fields = @_;
|
||||
return unless $fields{url} and $fields{keywords};
|
||||
my $asset = $self->asset;
|
||||
##Get the asset's record from the database.
|
||||
my %defaults = $self->session->db->quickHash('select * from assetIndex where assetId=? and url=?', [$asset->get('assetId'), $asset->get('url')]);
|
||||
$fields{keywords} = $self->_filterKeywords($fields{keywords});
|
||||
%fields = (%defaults, %fields);
|
||||
$fields{assetId} = $asset->getId;
|
||||
$fields{lineage} = $defaults{lineage};
|
||||
my $add = $self->session->db->prepare("replace into assetIndex (assetId, url, title, creationDate, revisionDate,
|
||||
ownerUserId, groupIdView, groupIdEdit, lineage, className, synopsis, keywords, subId) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )");
|
||||
$add->execute([@fields{qw/assetId url title creationDate revisionDate ownerUserId groupIdView groupIdEdit lineage className synopsis keywords subId/}]);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -201,6 +222,36 @@ sub getId {
|
|||
return $self->{_id};
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getKeywordsForFile ( path )
|
||||
|
||||
Use an external filter defined in the config file as searchIndexerPlugins to get keywords
|
||||
from a file.
|
||||
|
||||
=head3 path
|
||||
|
||||
The path to the filename to index, including the filename.
|
||||
|
||||
=cut
|
||||
|
||||
sub getKeywordsForFile {
|
||||
my $self = shift;
|
||||
my $path = shift;
|
||||
my $filters = $self->session->config->get("searchIndexerPlugins");
|
||||
my $content;
|
||||
if ($path =~ m/\.(\w+)$/) {
|
||||
my $type = lc($1);
|
||||
if ($filters->{$type}) {
|
||||
open my $fh, "$filters->{$type} $path |" or return undef; # open pipe to filter
|
||||
$content = do { local $/; <$fh> }; # slurp file
|
||||
close $fh;
|
||||
}
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 setIsPublic ( boolean )
|
||||
|
|
|
|||
|
|
@ -183,10 +183,7 @@ the one in this user's current session.
|
|||
sub validToken {
|
||||
my ($self) = @_;
|
||||
my $session = $self->session;
|
||||
$session->log->info('HTTP method: '. $session->request->method);
|
||||
$session->log->info('CSRF token: '. $session->scratch->get('webguiCsrfToken'));
|
||||
return 0 unless $session->request->method eq 'POST';
|
||||
$session->log->info('Web token: '. $self->param('webguiCsrfToken'));
|
||||
return 0 unless $self->param('webguiCsrfToken') eq $session->scratch->get('webguiCsrfToken');
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,8 +97,8 @@ sub copy {
|
|||
my $urlParams = shift;
|
||||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'copy.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Copy').'" title="'.$i18n->get('Copy').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'copy.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Copy').'" title="'.$i18n->get('Copy').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -124,8 +124,8 @@ sub cut {
|
|||
my $urlParams = shift;
|
||||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'cut.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Cut').'" title="'.$i18n->get('Cut').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'cut.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Cut').'" title="'.$i18n->get('Cut').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -160,8 +160,8 @@ sub delete {
|
|||
$confirmText = qq| onclick="return confirm('$confirmText');" |;
|
||||
}
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'" '.$confirmText.'>';
|
||||
$output .= '<img src="'.$self->getBaseURL().'delete.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Delete').'" title="'.$i18n->get('Delete').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'" '.$confirmText.'>';
|
||||
$output .= '<img src="'.$self->getBaseURL().'delete.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Delete').'" title="'.$i18n->get('Delete').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +181,7 @@ sub drag {
|
|||
my $self = shift;
|
||||
my $extras = shift;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
return '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><img '.$extras.' src="'.$self->getBaseURL().'drag.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Drag').'" title="'.$i18n->get('Drag').'" /></p>';
|
||||
return '<span class="toolbarIcon" style="vertical-align:middle;"><img '.$extras.' src="'.$self->getBaseURL().'drag.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Drag').'" title="'.$i18n->get('Drag').'" /></span>';
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -206,8 +206,8 @@ sub edit {
|
|||
my $urlParams = shift;
|
||||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'edit.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Edit').'" title="'.$i18n->get('Edit').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'edit.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Edit').'" title="'.$i18n->get('Edit').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -234,8 +234,8 @@ sub export {
|
|||
my $urlParams = shift;
|
||||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'export.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Export').'" title="'.$i18n->get('Export').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'export.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Export').'" title="'.$i18n->get('Export').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -287,8 +287,8 @@ sub locked {
|
|||
my $urlParams = shift;
|
||||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'locked.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('locked').'" title="'.$i18n->get('locked').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'locked.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('locked').'" title="'.$i18n->get('locked').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -315,8 +315,8 @@ sub manage {
|
|||
my $urlParams = shift;
|
||||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'manage.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Manage').'" title="'.$i18n->get('Manage').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'manage.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Manage').'" title="'.$i18n->get('Manage').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -343,8 +343,8 @@ sub moveBottom {
|
|||
my $urlParams = shift;
|
||||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'moveBottom.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Move To Bottom').'" title="'.$i18n->get('Move To Bottom').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'moveBottom.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Move To Bottom').'" title="'.$i18n->get('Move To Bottom').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -376,11 +376,11 @@ sub moveDown {
|
|||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $disabled = shift;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;">';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;">';
|
||||
$output .= '<a href="'.$self->session->url->gateway($pageURL,$urlParams).'">' unless $disabled;
|
||||
$output .= '<img src="'.$self->getBaseURL().'moveDown.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Move Down').'" title="'.$i18n->get('Move Down').'" />';
|
||||
$output .= '</a>' unless $disabled;
|
||||
$output .= '</p>';
|
||||
$output .= '</span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -407,8 +407,8 @@ sub moveLeft {
|
|||
my $urlParams = shift;
|
||||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'moveLeft.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Move Left').'" title="'.$i18n->get('Move Left').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'moveLeft.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Move Left').'" title="'.$i18n->get('Move Left').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -435,8 +435,8 @@ sub moveRight {
|
|||
my $urlParams = shift;
|
||||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'moveRight.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Move Right').'" title="'.$i18n->get('Move Right').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'moveRight.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Move Right').'" title="'.$i18n->get('Move Right').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -463,8 +463,8 @@ sub moveTop {
|
|||
my $urlParams = shift;
|
||||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'moveTop.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Move To Top').'" title="'.$i18n->get('Move To Top').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'moveTop.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Move To Top').'" title="'.$i18n->get('Move To Top').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -496,11 +496,11 @@ sub moveUp {
|
|||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $disabled = shift;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;">';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;">';
|
||||
$output .= '<a href="'.$self->session->url->gateway($pageURL,$urlParams).'">' unless $disabled;
|
||||
$output .= '<img src="'.$self->getBaseURL().'moveUp.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Move Up').'" title="'.$i18n->get('Move Up').'" />';
|
||||
$output .= '</a>' unless $disabled;
|
||||
$output .= '</p>';
|
||||
$output .= '</span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -563,8 +563,8 @@ sub shortcut {
|
|||
my $urlParams = shift;
|
||||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'shortcut.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Create Shortcut').'" title="'.$i18n->get('Create Shortcut').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'shortcut.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('Create Shortcut').'" title="'.$i18n->get('Create Shortcut').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
@ -591,8 +591,8 @@ sub view {
|
|||
my $urlParams = shift;
|
||||
my $pageURL = shift || $self->session->url->getRequestedUrl;
|
||||
my $i18n = WebGUI::International->new($self->session,'Icon');
|
||||
my $output = '<p class="toolbarIcon" style="display:inline;vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'view.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('View').'" title="'.$i18n->get('View').'" /></a></p>';
|
||||
my $output = '<span class="toolbarIcon" style="vertical-align:middle;"><a href="'.$self->session->url->gateway($pageURL,$urlParams).'">';
|
||||
$output .= '<img src="'.$self->getBaseURL().'view.gif" style="vertical-align:middle;border: 0px;" alt="'.$i18n->get('View').'" title="'.$i18n->get('View').'" /></a></span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ sub audit {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 canShowPerformanceIndicators ( )
|
||||
=head2 performanceLogger ( )
|
||||
|
||||
Returns true if the user meets the conditions to see performance indicators and performance indicators are enabled.
|
||||
|
||||
|
|
|
|||
|
|
@ -389,7 +389,7 @@ sub makeAbsolute {
|
|||
|
||||
=head2 makeCompliant ( string )
|
||||
|
||||
Returns a string that has made into a WebGUI compliant URL based upon the language being submitted.
|
||||
Returns a string that has been made into a WebGUI compliant URL.
|
||||
|
||||
=head3 string
|
||||
|
||||
|
|
|
|||
|
|
@ -936,8 +936,10 @@ sub www_ajaxPrices {
|
|||
} || 0,
|
||||
|
||||
shipping => eval {
|
||||
die unless $shipping;
|
||||
$self->update({ shippingAddressId => $shipping });
|
||||
#die unless $shipping;
|
||||
if ( $shipping ) {
|
||||
$self->update({ shippingAddressId => $shipping });
|
||||
}
|
||||
my $ship = WebGUI::Shop::Ship->new($self->session);
|
||||
$ship->getOptions($self);
|
||||
} || [],
|
||||
|
|
@ -1234,7 +1236,13 @@ sub www_view {
|
|||
|
||||
my $billingAddressId = $self->billingAddressId;
|
||||
if ($billingAddressId) {
|
||||
$billingAddressOptions{'update_address'} = sprintf $i18n->get('Update %s'), $self->getBillingAddress->get('label');
|
||||
my $billingAddress = eval { $self->getBillingAddress };
|
||||
if ( defined $billingAddress ) {
|
||||
$billingAddressOptions{'update_address'} = sprintf $i18n->get('Update %s'), $billingAddress->get('label');
|
||||
}
|
||||
elsif (my $e = WebGUI::Error->caught("WebGUI::Error::ObjectNotFound") && $self->get('billingAddressId')) {
|
||||
$self->update({billingAddressId=>''});
|
||||
}
|
||||
}
|
||||
|
||||
%billingAddressOptions = (%billingAddressOptions, %addressOptions);
|
||||
|
|
@ -1250,7 +1258,10 @@ sub www_view {
|
|||
|
||||
my $shippingAddressId = $self->shippingAddressId;
|
||||
if ($shippingAddressId) {
|
||||
$shippingAddressOptions{'update_address'} = sprintf $i18n->get('Update %s'), $self->getShippingAddress->get('label');
|
||||
my $shippingAddress = eval { $self->getShippingAddress };
|
||||
if ( defined $shippingAddress ) {
|
||||
$shippingAddressOptions{'update_address'} = sprintf $i18n->get('Update %s'), $shippingAddress->get('label');
|
||||
}
|
||||
}
|
||||
%shippingAddressOptions = (%shippingAddressOptions, %addressOptions);
|
||||
|
||||
|
|
|
|||
|
|
@ -271,8 +271,9 @@ sub processPayment {
|
|||
at => $self->identityToken,
|
||||
);
|
||||
my $response = LWP::UserAgent->new->post($self->payPalUrl, \%form);
|
||||
my ($status, @lines) = split("\n", uri_unescape($response->content));
|
||||
my %params = map { split /=/ } @lines;
|
||||
my ($status, @lines) = split("\n", $response->content);
|
||||
my %params = map { split /=/ }
|
||||
map { uri_unescape($_) } @lines;
|
||||
|
||||
if ($status =~ /FAIL/) {
|
||||
my $message = '<table><tr><th>Field</th><th>Value</th></tr>';
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ Base class for all modules which do tax calculations in the Shop.
|
|||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use base WebGUI::Shop::TaxDriver;
|
||||
use base 'WebGUI::Shop::TaxDriver';
|
||||
|
||||
my $driver = WebGUI::Shop::TaxDriver->new($session);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@ property shippingAddressName => (
|
|||
noFormPost => 1,
|
||||
default => '',
|
||||
);
|
||||
property shippingOrganization => (
|
||||
is => 'rw',
|
||||
noFormPost => 1,
|
||||
default => '',
|
||||
);
|
||||
property shippingAddress1 => (
|
||||
is => 'rw',
|
||||
noFormPost => 1,
|
||||
|
|
@ -122,6 +127,11 @@ property isRecurring => (
|
|||
noFormPost => 1,
|
||||
default => '',
|
||||
);
|
||||
property paymentOrganization => (
|
||||
is => 'rw',
|
||||
noFormPost => 1,
|
||||
default => '',
|
||||
);
|
||||
property paymentAddress1 => (
|
||||
is => 'rw',
|
||||
noFormPost => 1,
|
||||
|
|
@ -663,7 +673,9 @@ A hash reference with the address properties.
|
|||
|
||||
sub formatAddress {
|
||||
my ($self, $address) = @_;
|
||||
my $formatted = $address->{name} . "<br />" . $address->{address1} . "<br />";
|
||||
my $formatted = $address->{name} . "<br />";
|
||||
$formatted .= $address->{organization} . "<br />" if ($address->{organization} ne "");
|
||||
$formatted .= $address->{address1} . "<br />";
|
||||
$formatted .= $address->{address2} . "<br />" if ($address->{address2} ne "");
|
||||
$formatted .= $address->{address3} . "<br />" if ($address->{address3} ne "");
|
||||
$formatted .= $address->{city} . ", ";
|
||||
|
|
@ -797,6 +809,7 @@ sub getTransactionVars {
|
|||
shippingPrice => sprintf( "%.2f", $self->shippingPrice ),
|
||||
shippingAddress => $self->formatAddress( {
|
||||
name => $self->shippingAddressName,
|
||||
organization => $self->shippingOrganization,
|
||||
address1 => $self->shippingAddress1,
|
||||
address2 => $self->shippingAddress2,
|
||||
address3 => $self->shippingAddress3,
|
||||
|
|
@ -808,6 +821,7 @@ sub getTransactionVars {
|
|||
} ),
|
||||
paymentAddress => $self->formatAddress({
|
||||
name => $self->paymentAddressName,
|
||||
organization => $self->paymentOrganization,
|
||||
address1 => $self->paymentAddress1,
|
||||
address2 => $self->paymentAddress2,
|
||||
address3 => $self->paymentAddress3,
|
||||
|
|
@ -825,25 +839,31 @@ sub getTransactionVars {
|
|||
my $address = '';
|
||||
if ($self->shippingAddressId ne $item->get('shippingAddressId')) {
|
||||
$address = $self->formatAddress({
|
||||
name => $item->get('shippingAddressName'),
|
||||
address1 => $item->get('shippingAddress1'),
|
||||
address2 => $item->get('shippingAddress2'),
|
||||
address3 => $item->get('shippingAddress3'),
|
||||
city => $item->get('shippingCity'),
|
||||
state => $item->get('shippingState'),
|
||||
code => $item->get('shippingCode'),
|
||||
country => $item->get('shippingCountry'),
|
||||
phoneNumber => $item->get('shippingPhoneNumber'),
|
||||
name => $item->get('shippingAddressName'),
|
||||
organization => $self->get('shippingOrganization'),
|
||||
address1 => $item->get('shippingAddress1'),
|
||||
address2 => $item->get('shippingAddress2'),
|
||||
address3 => $item->get('shippingAddress3'),
|
||||
city => $item->get('shippingCity'),
|
||||
state => $item->get('shippingState'),
|
||||
code => $item->get('shippingCode'),
|
||||
country => $item->get('shippingCountry'),
|
||||
phoneNumber => $item->get('shippingPhoneNumber'),
|
||||
});
|
||||
}
|
||||
|
||||
# Post purchase actions
|
||||
my $actionsLoop = [];
|
||||
my $actions = $item->getSku->getPostPurchaseActions( $item );
|
||||
for my $label ( keys %{$actions} ) {
|
||||
push @{$actionsLoop}, {
|
||||
label => $label,
|
||||
url => $actions->{$label},
|
||||
my $sku = eval { $item->getSku };
|
||||
my $has_sku = 0;
|
||||
if (! WebGUI::Error->caught) {
|
||||
my $actions = $sku->getPostPurchaseActions( $item );
|
||||
$has_sku = 1;
|
||||
for my $label ( keys %{$actions} ) {
|
||||
push @{$actionsLoop}, {
|
||||
label => $label,
|
||||
url => $actions->{$label},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -861,7 +881,8 @@ sub getTransactionVars {
|
|||
%{$item->get},
|
||||
%taxVars,
|
||||
viewItemUrl => $url->page('shop=transaction;method=viewItem;transactionId='.$self->getId.';itemId='.$item->getId, 1),
|
||||
price => sprintf("%.2f", $item->get('price')),
|
||||
hasSku => $has_sku,
|
||||
price => sprintf( "%.2f", $item->get('price') ),
|
||||
pricePlusTax => sprintf( "%.2f", $price + $taxAmount ),
|
||||
extendedPrice => sprintf( "%.2f", $quantity * $price ),
|
||||
extendedPricePlusTax => sprintf( "%.2f", $quantity * ( $price + $taxAmount ) ),
|
||||
|
|
@ -1222,8 +1243,8 @@ Refunds a specific item from a transaction and then issues shop credit.
|
|||
sub www_refundItem {
|
||||
my ($class, $session) = @_;
|
||||
return $session->privilege->insufficient unless (WebGUI::Shop::Admin->new($session)->canManage);
|
||||
my $self = $class->new($session, $session->form->get("transactionId"));
|
||||
my $form = $session->form;
|
||||
my $self = $class->new($session, $form->get("transactionId"));
|
||||
my $item = eval { $self->getItem($form->get("itemId")) };
|
||||
if (WebGUI::Error->caught()) {
|
||||
$session->log->error("Can't get item ".$form->get("itemId"));
|
||||
|
|
@ -1327,15 +1348,16 @@ sub www_view {
|
|||
</tr>
|
||||
<tr>
|
||||
<th>}. $i18n->get("shipping address") .q{</th><td>}. $transaction->formatAddress({
|
||||
name => $transaction->get('shippingAddressName'),
|
||||
address1 => $transaction->get('shippingAddress1'),
|
||||
address2 => $transaction->get('shippingAddress2'),
|
||||
address3 => $transaction->get('shippingAddress3'),
|
||||
city => $transaction->get('shippingCity'),
|
||||
state => $transaction->get('shippingState'),
|
||||
code => $transaction->get('shippingCode'),
|
||||
country => $transaction->get('shippingCountry'),
|
||||
phoneNumber => $transaction->get('shippingPhoneNumber'),
|
||||
name => $transaction->get('shippingAddressName'),
|
||||
organization => $transaction->get('shippingOrganization'),
|
||||
address1 => $transaction->get('shippingAddress1'),
|
||||
address2 => $transaction->get('shippingAddress2'),
|
||||
address3 => $transaction->get('shippingAddress3'),
|
||||
city => $transaction->get('shippingCity'),
|
||||
state => $transaction->get('shippingState'),
|
||||
code => $transaction->get('shippingCode'),
|
||||
country => $transaction->get('shippingCountry'),
|
||||
phoneNumber => $transaction->get('shippingPhoneNumber'),
|
||||
}) .q{</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
@ -1346,15 +1368,16 @@ sub www_view {
|
|||
</tr>
|
||||
<tr>
|
||||
<th>}. $i18n->get("payment address") .q{</th><td>}. $transaction->formatAddress({
|
||||
name => $transaction->get('paymentAddressName'),
|
||||
address1 => $transaction->get('paymentAddress1'),
|
||||
address2 => $transaction->get('paymentAddress2'),
|
||||
address3 => $transaction->get('paymentAddress3'),
|
||||
city => $transaction->get('paymentCity'),
|
||||
state => $transaction->get('paymentState'),
|
||||
code => $transaction->get('paymentCode'),
|
||||
country => $transaction->get('paymentCountry'),
|
||||
phoneNumber => $transaction->get('paymentPhoneNumber'),
|
||||
name => $transaction->get('paymentAddressName'),
|
||||
organization => $transaction->get('paymentOrganization'),
|
||||
address1 => $transaction->get('paymentAddress1'),
|
||||
address2 => $transaction->get('paymentAddress2'),
|
||||
address3 => $transaction->get('paymentAddress3'),
|
||||
city => $transaction->get('paymentCity'),
|
||||
state => $transaction->get('paymentState'),
|
||||
code => $transaction->get('paymentCode'),
|
||||
country => $transaction->get('paymentCountry'),
|
||||
phoneNumber => $transaction->get('paymentPhoneNumber'),
|
||||
}) .q{</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
@ -1379,6 +1402,8 @@ sub www_view {
|
|||
<tbody>
|
||||
};
|
||||
foreach my $item (@{$transaction->getItems}) {
|
||||
eval { $item->getSku; };
|
||||
my $sku_exists = !WebGUI::Error->caught;
|
||||
$output .= WebGUI::Form::formHeader($session)
|
||||
.WebGUI::Form::hidden($session, {name=>"shop",value=>"transaction"})
|
||||
.WebGUI::Form::hidden($session, {name=>"method",value=>"updateItem"})
|
||||
|
|
@ -1386,9 +1411,15 @@ sub www_view {
|
|||
.WebGUI::Form::hidden($session, {name=>"itemId",value=>$item->getId})
|
||||
.q{
|
||||
<tr>
|
||||
<td>}.$item->get('lastUpdated').q{</td>
|
||||
<td><a href="}.$url->page('shop=transaction;method=viewItem;transactionId='.$transaction->getId.';itemId='.$item->getId).q{">}.$item->get('configuredTitle').q{</a></td>
|
||||
<td>}.$transaction->formatCurrency($item->get('price')).q{</td>
|
||||
<td>}.$item->get('lastUpdated').qq{</td>\n}.
|
||||
(
|
||||
$sku_exists
|
||||
? q{<td><a href="}.$url->page('shop=transaction;method=viewItem;transactionId='.$transaction->getId
|
||||
. ';itemId='.$item->getId).q{">}.$item->get('configuredTitle').qq{</a></td>\n}
|
||||
: q{<td>}.$item->get('configuredTitle').q{<br />}.$i18n->get('item sku deleted').qq{</td>\n}
|
||||
|
||||
)
|
||||
. q{<td>}.$transaction->formatCurrency($item->get('price')).q{</td>
|
||||
<td>}.$item->get('quantity').q{</td>
|
||||
};
|
||||
if ($item->get('shippingAddressId') eq $transaction->get('shippingAddressId')) {
|
||||
|
|
@ -1397,15 +1428,16 @@ sub www_view {
|
|||
else {
|
||||
$output .= q{
|
||||
<td class="smallAddress">}. $transaction->formatAddress({
|
||||
name => $item->get('shippingAddressName'),
|
||||
address1 => $item->get('shippingAddress1'),
|
||||
address2 => $item->get('shippingAddress2'),
|
||||
address3 => $item->get('shippingAddress3'),
|
||||
city => $item->get('shippingCity'),
|
||||
state => $item->get('shippingState'),
|
||||
code => $item->get('shippingCode'),
|
||||
country => $item->get('shippingCountry'),
|
||||
phoneNumber => $item->get('shippingPhoneNumber'),
|
||||
name => $item->get('shippingAddressName'),
|
||||
organization => $item->get('shippingOrganization'),
|
||||
address1 => $item->get('shippingAddress1'),
|
||||
address2 => $item->get('shippingAddress2'),
|
||||
address3 => $item->get('shippingAddress3'),
|
||||
city => $item->get('shippingCity'),
|
||||
state => $item->get('shippingState'),
|
||||
code => $item->get('shippingCode'),
|
||||
country => $item->get('shippingCountry'),
|
||||
phoneNumber => $item->get('shippingPhoneNumber'),
|
||||
}) .q{</td>
|
||||
};
|
||||
}
|
||||
|
|
@ -1464,7 +1496,12 @@ sub www_viewItem {
|
|||
$session->log->error("Can't get item ".$session->form->get("itemId"));
|
||||
return $class->www_view($session);
|
||||
}
|
||||
return $item->getSku->www_view;
|
||||
my $sku = eval { $item->getSku };
|
||||
if (WebGUI::Error->caught()) {
|
||||
$session->errorHandler->error("Can't get sku for ".$session->form->get("itemId"));
|
||||
return $class->www_view($session);
|
||||
}
|
||||
return $sku->www_view;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -72,6 +72,11 @@ property shippingName => (
|
|||
noFormPost => 1,
|
||||
default => '',
|
||||
);
|
||||
property shippingOrganization => (
|
||||
is => 'rw',
|
||||
noFormPost => 1,
|
||||
default => '',
|
||||
);
|
||||
property shippingAddress1 => (
|
||||
is => 'rw',
|
||||
noFormPost => 1,
|
||||
|
|
@ -356,15 +361,20 @@ sub getSku {
|
|||
|
||||
=head2 issueCredit ( )
|
||||
|
||||
Returns the money from this item to the user in the form of in-store credit.
|
||||
Returns the money from this item to the user in the form of in-store credit. Items marked
|
||||
cancelled cannot be refunded.
|
||||
|
||||
=cut
|
||||
|
||||
sub issueCredit {
|
||||
my $self = shift;
|
||||
return if $self->orderStatus eq 'Cancelled';
|
||||
return unless $self->transaction->isSuccessful;
|
||||
my $credit = WebGUI::Shop::Credit->new($self->transaction->session, $self->transaction->userId);
|
||||
$credit->adjust(($self->price * $self->quantity), "Issued credit on sku ".$self->assetId." for transaction item ".$self->getId." on transaction ".$self->transaction->getId);
|
||||
$self->getSku->onRefund($self);
|
||||
if (my $sku = eval {$self->getSku}) {
|
||||
$sku->onRefund($self);
|
||||
}
|
||||
$self->update({orderStatus=>'Cancelled'});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ This package provides a mechanism for storing and retrieving files that are not
|
|||
$store = WebGUI::Storage->createTemp($self->session);
|
||||
$store = WebGUI::Storage->get($self->session,$id);
|
||||
|
||||
$exists = WebGUI::Storage->storageExists($session, $id);
|
||||
|
||||
$filename = $store->addFileFromFilesystem($pathToFile);
|
||||
$filename = $store->addFileFromFormPost($formVarName,$attachmentLimit);
|
||||
$filename = $store->addFileFromHashref($filename,$hashref);
|
||||
|
|
@ -304,7 +306,10 @@ sub addFileFromFilesystem {
|
|||
if (! defined $pathToFile) {
|
||||
return undef;
|
||||
}
|
||||
##Handle UTF-8 filenames.
|
||||
$pathToFile = Encode::encode_utf8($pathToFile);
|
||||
$pathToFile = Cwd::realpath($pathToFile); # trace any symbolic links
|
||||
$pathToFile = Encode::decode_utf8($pathToFile);
|
||||
if (-d $pathToFile) {
|
||||
$self->session->log->error($pathToFile." is a directory, not a file.");
|
||||
return undef;
|
||||
|
|
@ -370,6 +375,7 @@ sub addFileFromFormPost {
|
|||
return $filename;
|
||||
}
|
||||
my $clientFilename = $upload->filename;
|
||||
$clientFilename = Encode::decode_utf8($clientFilename);
|
||||
next
|
||||
unless $clientFilename;
|
||||
next
|
||||
|
|
@ -1078,7 +1084,7 @@ sub getFiles {
|
|||
callback => sub {
|
||||
my $obj = shift;
|
||||
my $rel = $obj->relative($dir);
|
||||
my $str = $rel->stringify;
|
||||
my $str = Encode::decode_utf8($rel->stringify);
|
||||
if (! $showAll ) {
|
||||
return if $str =~ /^thumb-/;
|
||||
return if $str =~ /^\./;
|
||||
|
|
@ -1704,36 +1710,34 @@ sub setPrivileges {
|
|||
}
|
||||
}
|
||||
|
||||
my $public;
|
||||
for my $user (@{ $privs{users} }) {
|
||||
if ($user eq '1') {
|
||||
$public = 1;
|
||||
}
|
||||
}
|
||||
for my $group (@{ $privs{groups} }) {
|
||||
if ($group eq '1' || $group eq '7') {
|
||||
$public = 1;
|
||||
}
|
||||
}
|
||||
my $accessFile = JSON->new->encode( \%privs );
|
||||
return $self->writeAccess( %privs );
|
||||
}
|
||||
|
||||
my $dirObj = $self->getPathClassDir();
|
||||
return undef if ! defined $dirObj;
|
||||
$dirObj->recurse(
|
||||
callback => sub {
|
||||
my $obj = shift;
|
||||
return unless $obj->is_dir;
|
||||
my $rel = $obj->relative($dirObj);
|
||||
|
||||
if ($public) {
|
||||
$self->deleteFile($rel->file('.wgaccess')->stringify);
|
||||
}
|
||||
else {
|
||||
$self->addFileFromScalar($rel->file('.wgaccess')->stringify, $accessFile);
|
||||
}
|
||||
}
|
||||
);
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 storageExists ( $session, $storageId )
|
||||
|
||||
Class method to determine if a storage location exists. This can't be done
|
||||
with C<get> since it will create it if it doesn't exist. Returns true if the
|
||||
storage directory exists.
|
||||
|
||||
=head3 $session
|
||||
|
||||
A session object, used to find the uploadsPath location
|
||||
|
||||
=head3 $storageId
|
||||
|
||||
A WebGUI::Storage GUID.
|
||||
|
||||
=cut
|
||||
|
||||
sub storageExists {
|
||||
my ($class, $session, $storageId) = @_;
|
||||
my $hexId = $session->id->toHex($storageId);
|
||||
my @parts = ($hexId =~ m/^((.{2})(.{2}).+)/)[1,2,0];
|
||||
my $dir = Path::Class::Dir->new($session->config->get('uploadsPath'), @parts);
|
||||
return (-e $dir->stringify && -d _ ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1808,6 +1812,19 @@ sub tar {
|
|||
return $temp;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 trash ( )
|
||||
|
||||
Set this storage location as trashed
|
||||
|
||||
=cut
|
||||
|
||||
sub trash {
|
||||
my ( $self ) = @_;
|
||||
return $self->writeAccess( state => "trash" );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 untar ( filename [, storage ] )
|
||||
|
|
@ -1867,5 +1884,64 @@ sub getDirectoryId {
|
|||
return $self->{_pathParts}[2];
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 writeAccess( pairs )
|
||||
|
||||
Write the given pairs to the wgaccess files in this storage location.
|
||||
|
||||
If the storage location should be public, will remove all wgaccess files.
|
||||
|
||||
Possible keys:
|
||||
|
||||
users - an arrayref of userIds to allow access to
|
||||
groups - an arrayref of groupIds to allow access to
|
||||
assets - an arrayref of assetIds to validate permissions against
|
||||
state - a string describing a special state.
|
||||
valid values: "trash" - storage location is trashed
|
||||
|
||||
|
||||
=cut
|
||||
|
||||
sub writeAccess {
|
||||
my ( $self, %privs ) = @_;
|
||||
|
||||
my $public;
|
||||
if ( $privs{users} ) {
|
||||
for my $user (@{ $privs{users} }) {
|
||||
if ($user eq '1') {
|
||||
$public = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( $privs{groups} ) {
|
||||
for my $group (@{ $privs{groups} }) {
|
||||
if ($group eq '1' || $group eq '7') {
|
||||
$public = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
my $accessFile = JSON->new->encode( \%privs );
|
||||
|
||||
my $dirObj = $self->getPathClassDir();
|
||||
return undef if ! defined $dirObj;
|
||||
$dirObj->recurse(
|
||||
callback => sub {
|
||||
my $obj = shift;
|
||||
return unless $obj->is_dir;
|
||||
my $rel = $obj->relative($dirObj);
|
||||
|
||||
if ($public) {
|
||||
$self->deleteFile($rel->file('.wgaccess')->stringify);
|
||||
}
|
||||
else {
|
||||
$self->addFileFromScalar($rel->file('.wgaccess')->stringify, $accessFile);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ sub _initSession {
|
|||
'Payment Drivers' => 'paymentGateway',
|
||||
'Database Links' => 'databaseLink',
|
||||
'LDAP Links' => 'ldapLink',
|
||||
'Profile Fields' => 'userProfileField',
|
||||
);
|
||||
my %initCounts;
|
||||
for ( my $i = 0; $i < @checkCount; $i += 2) {
|
||||
|
|
@ -640,6 +641,7 @@ were passed in. Currently able to destroy:
|
|||
WebGUI::LDAPLink
|
||||
WebGUI::Inbox::Message
|
||||
WebGUI::Fork
|
||||
WebGUI::ProfileField
|
||||
|
||||
Example call:
|
||||
|
||||
|
|
@ -723,6 +725,7 @@ Example call:
|
|||
pbworkflow000000000006
|
||||
pbworkflow000000000007
|
||||
send_webgui_statistics
|
||||
xR-_GRRbjBojgLsFx3dEMA
|
||||
};
|
||||
},
|
||||
);
|
||||
|
|
@ -743,6 +746,7 @@ Example call:
|
|||
'WebGUI::Inbox::Message' => 'purge',
|
||||
'WebGUI::AdSpace' => 'delete',
|
||||
'WebGUI::FilePump::Bundle' => 'delete',
|
||||
'WebGUI::ProfileField' => 'delete',
|
||||
'WebGUI::Shop::Cart' => sub {
|
||||
my $cart = shift;
|
||||
my $addressBook = eval { $cart->getAddressBook(); };
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ use JSON ();
|
|||
use WebGUI::Exception;
|
||||
use WebGUI::ProfileField;
|
||||
use WebGUI::Inbox;
|
||||
use List::MoreUtils qw( any );
|
||||
use Scalar::Util qw( weaken );
|
||||
use Net::CIDR::Lite;
|
||||
use WebGUI::Friends;
|
||||
|
|
@ -395,7 +396,6 @@ sub delete {
|
|||
my $userId = $self->userId;
|
||||
my $session = $self->session;
|
||||
my $db = $session->db;
|
||||
$self->uncache;
|
||||
|
||||
foreach my $groupId ( @{ $self->getGroups } ) {
|
||||
my $group = WebGUI::Group->new($session, $groupId);
|
||||
|
|
@ -446,6 +446,7 @@ sub delete {
|
|||
$credit->purge;
|
||||
|
||||
# remove user itself
|
||||
$self->uncache;
|
||||
$db->write("DELETE FROM userProfileData WHERE userId=?",[$userId]);
|
||||
$db->write("DELETE FROM users WHERE userId=?",[$userId]);
|
||||
}
|
||||
|
|
@ -806,7 +807,7 @@ Field to get privacy setting for.
|
|||
sub getProfileFieldPrivacySetting {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $field = shift;
|
||||
my $fieldId = shift;
|
||||
|
||||
unless ($self->{_privacySettings}) {
|
||||
#Look it up manually because we want to cache this separately.
|
||||
|
|
@ -818,12 +819,16 @@ sub getProfileFieldPrivacySetting {
|
|||
$self->{_privacySettings} = JSON->new->decode($privacySettings);
|
||||
}
|
||||
|
||||
return $self->{_privacySettings} unless ($field);
|
||||
return $self->{_privacySettings} unless ($fieldId);
|
||||
|
||||
#No privacy settings returned the privacy setting field
|
||||
return "none" if($field eq "privacyFields");
|
||||
return "none" if($fieldId eq "privacyFields");
|
||||
|
||||
return $self->{_privacySettings}->{$field};
|
||||
if (exists $self->{_privacySettings}->{$fieldId}) {
|
||||
return $self->{_privacySettings}->{$fieldId};
|
||||
}
|
||||
my $field = WebGUI::ProfileField->new($session, $fieldId);
|
||||
return $field && $field->get('defaultPrivacySetting');
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -919,6 +924,25 @@ sub isAdmin {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 isDuplicateEmail( email )
|
||||
|
||||
Returns true if the email passed is also being used by any other user
|
||||
|
||||
=cut
|
||||
|
||||
sub isDuplicateEmail {
|
||||
my ( $self, $email ) = @_;
|
||||
|
||||
my @userIds = $self->session->db->quickArray(
|
||||
"SELECT userId FROM users WHERE email = ?",
|
||||
[ $email ],
|
||||
);
|
||||
|
||||
return any { $_ ne $self->userId } @userIds;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 isEnabled ()
|
||||
|
||||
Returns 1 if the user is enabled.
|
||||
|
|
@ -1593,7 +1617,7 @@ sub validateProfileDataFromForm {
|
|||
push(@{$errorFields},$fieldId);
|
||||
}
|
||||
#Duplicate emails throw warnings
|
||||
elsif($fieldId eq "email" && $field->isDuplicate($fieldValue,$self->userId)) {
|
||||
elsif($fieldId eq "email" && $self->isDuplicateEmail($fieldValue)) {
|
||||
$errorCat = $field->get("profileCategoryId") unless (defined $errorCat);
|
||||
push (@{$warnings},$i18n->get(1072));
|
||||
push(@{$warnFields},$fieldId);
|
||||
|
|
|
|||
|
|
@ -193,9 +193,11 @@ sub commit {
|
|||
my $now = time;
|
||||
my $finished = 1;
|
||||
foreach my $asset (@{$self->getAssets({"byLineage"=>1, onlyPending=>1})}) {
|
||||
$self->session->log->info( "Committing " . $asset->getId );
|
||||
$asset->commit;
|
||||
if ($now + $timeout < time) {
|
||||
$finished = 0;
|
||||
$self->session->log->info( "NOES!" );
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -551,6 +551,14 @@ sub set {
|
|||
$self->session->db->setRow("Workflow","workflowId",$self->{_data});
|
||||
}
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<WebGUI::Workflow::Instance>
|
||||
|
||||
After creating a workflow, you need to create an instance of that workflow to kick off activities in it.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
1;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ use WebGUI::Asset::Event;
|
|||
use WebGUI::DateTime;
|
||||
use DateTime::TimeZone;
|
||||
use Data::Dumper;
|
||||
use Data::ICal;
|
||||
|
||||
use LWP::UserAgent;
|
||||
use JSON ();
|
||||
|
|
@ -124,10 +125,6 @@ sub execute {
|
|||
$session->db->write("REPLACE INTO userSessionScratch (sessionId,name,value) VALUES (?,?,?)",
|
||||
[$session->getId,$calendar->getId,"SPECTRE"]);
|
||||
}
|
||||
#/KLUDGE
|
||||
|
||||
## Somebody point me to a DECENT iCalendar parser...
|
||||
# Text::vFile perhaps?
|
||||
|
||||
# Get the feed
|
||||
$session->log->info( "Trying Calendar feed ".$feed->{url}." for $calendarTitle" );
|
||||
|
|
@ -142,88 +139,52 @@ sub execute {
|
|||
next FEED;
|
||||
}
|
||||
|
||||
my $data = $response->content;
|
||||
# If doesn't start with BEGIN:VCALENDAR then error
|
||||
unless ($data =~ /^BEGIN:VCALENDAR/i) {
|
||||
my $data = $response->content;
|
||||
my $cal = Data::ICal->new( data => $data );
|
||||
if (!$cal) {
|
||||
# Update the result and last updated fields
|
||||
$feed->{lastResult} = "Not an iCalendar feed";
|
||||
$feed->{lastResult} = "Error parsing iCal feed";
|
||||
$feed->{lastUpdated} = $dt;
|
||||
$calendar->setFeed($feed->{feedId}, $feed);
|
||||
next FEED;
|
||||
#next FEED;
|
||||
}
|
||||
|
||||
my $active = 0; # Parser on/off
|
||||
my %current_event = ();
|
||||
my %events;
|
||||
my $line_number = 0;
|
||||
$data =~ s/[ \t]?[\r\n]+[ \t]+/ /msg; #Process line continuations
|
||||
LINE: for my $line (split /[\r\n]+/,$data) {
|
||||
chomp $line;
|
||||
$line_number++;
|
||||
next unless $line =~ /\w/;
|
||||
|
||||
#warn "LINE $line_number: $line\n";
|
||||
|
||||
if ($line =~ /^BEGIN:VEVENT$/i) {
|
||||
$active = 1;
|
||||
next LINE;
|
||||
}
|
||||
elsif ($line =~ /^END:VEVENT$/i) {
|
||||
$active = 0;
|
||||
# Flush event
|
||||
my $uid = lc $current_event{uid}[1];
|
||||
delete $current_event{uid};
|
||||
$events{$uid} = {%current_event};
|
||||
$session->log->info( "Found event $uid from feed " . $feed->{feedId} );
|
||||
%current_event = ();
|
||||
next LINE;
|
||||
}
|
||||
else {
|
||||
# Flush old entry
|
||||
# KEY;ATTRIBUTE=VALUE;ATTRIBUTE=VALUE:KEYVALUE
|
||||
my ($key_attrs,$value) = split /:/,$line,2;
|
||||
my @attrs = $key_attrs ? (split /;/, $key_attrs) : ();
|
||||
my $key = shift @attrs;
|
||||
my %attrs;
|
||||
while (my $attribute = shift @attrs) {
|
||||
my ($attr_key, $attr_value) = split /=/, $attribute, 2;
|
||||
$attrs{lc $attr_key} = $attr_value;
|
||||
}
|
||||
|
||||
$current_event{lc $key} = [\%attrs,$value];
|
||||
}
|
||||
}
|
||||
|
||||
my $feedData = $feedList->{$feed->{feedId}} = {
|
||||
added => 0,
|
||||
updated => 0,
|
||||
errored => 0,
|
||||
assetId => $calendar->getId,
|
||||
};
|
||||
EVENT: for my $id (keys %events) {
|
||||
EVENT: foreach my $entry (@{ $cal->entries }) {
|
||||
next EVENT unless $entry->ical_entry_type eq 'VEVENT';
|
||||
#use Data::Dumper;
|
||||
#warn "EVENT: $id; ".Dumper $events{$id};
|
||||
my $event_properties = $entry->properties;
|
||||
|
||||
# Prepare event data
|
||||
my $properties = {
|
||||
feedUid => $id,
|
||||
feedId => $feed->{feedId},
|
||||
description => _unwrapIcalText($events{$id}->{description}->[1]),
|
||||
title => _unwrapIcalText($events{$id}->{summary}->[1]),
|
||||
location => _unwrapIcalText($events{$id}->{location}->[1]),
|
||||
menuTitle => substr($events{$id}->{summary}->[1],0,15),
|
||||
className => 'WebGUI::Asset::Event',
|
||||
isHidden => 1,
|
||||
};
|
||||
PROPERTY: foreach my $property (qw/uid description summary location/) {
|
||||
next PROPERTY unless exists $event_properties->{$property};
|
||||
$properties->{$property} = $event_properties->{$property}->[0]->value;
|
||||
}
|
||||
##Fixup
|
||||
$properties->{title} = delete $properties->{summary};
|
||||
$properties->{feedUid} = delete $properties->{uid};
|
||||
|
||||
# Prepare the date
|
||||
my $dtstart = $events{$id}->{dtstart}->[1];
|
||||
my $dtstart = $event_properties->{dtstart}->[0]->value;
|
||||
if ($dtstart =~ /T/) {
|
||||
my ($date, $time) = split /T/, $dtstart;
|
||||
|
||||
my ($year, $month, $day) = $date =~ /(\d{4})(\d{2})(\d{2})/;
|
||||
my ($hour, $minute, $second) = $time =~ /(\d{2})(\d{2})(\d{2})/;
|
||||
my $tz = $events{$id}->{dtstart}->[0]->{tzid};
|
||||
my $tz = '';
|
||||
if ($event_properties->{dtstart}->[0]->{tzid}) {
|
||||
$tz = $event_properties->{dtstart}->[0]->{tzid};
|
||||
}
|
||||
if (!$tz || !DateTime::TimeZone->is_valid_name($tz)) {
|
||||
$tz = "UTC";
|
||||
}
|
||||
|
|
@ -253,14 +214,14 @@ sub execute {
|
|||
next EVENT;
|
||||
}
|
||||
|
||||
my $dtend = $events{$id}->{dtend}->[1];
|
||||
my $duration = $events{$id}->{duration}->[1];
|
||||
my $dtend = exists $event_properties->{dtend} ? $event_properties->{dtend}->[0]->value : undef;
|
||||
my $duration = exists $event_properties->{duration} ? $event_properties->{duration}->[0]->value : undef;
|
||||
if ($dtend =~ /T/) {
|
||||
my ($date, $time) = split /T/, $dtend;
|
||||
|
||||
my ($year, $month, $day) = $date =~ /(\d{4})(\d{2})(\d{2})/;
|
||||
my ($hour, $minute, $second) = $time =~ /(\d{2})(\d{2})(\d{2})/;
|
||||
my $tz = $events{$id}->{dtend}->[0]->{tzid};
|
||||
my $tz = '';
|
||||
if (!$tz || !DateTime::TimeZone->is_valid_name($tz)) {
|
||||
$tz = "UTC";
|
||||
}
|
||||
|
|
@ -330,28 +291,15 @@ sub execute {
|
|||
}
|
||||
|
||||
# If there are X-WebGUI-* fields
|
||||
for my $key (grep /^x-webgui-/, keys %{$events{$id}}) {
|
||||
my $property_name = $key;
|
||||
$property_name =~ s/^x-webgui-//;
|
||||
$property_name = lc $property_name;
|
||||
|
||||
if ($property_name eq "groupidedit") {
|
||||
$properties->{groupIdEdit} = $events{$id}->{$key}->[1];
|
||||
}
|
||||
elsif ($property_name eq "groupidview") {
|
||||
$properties->{groupIdView} = $events{$id}->{$key}->[1];
|
||||
}
|
||||
elsif ($property_name eq "url") {
|
||||
$properties->{url} = $events{$id}->{$key}->[1];
|
||||
}
|
||||
elsif ($property_name eq "menutitle") {
|
||||
$properties->{menuTitle} = $events{$id}->{$key}->[1];
|
||||
}
|
||||
PROPERTY: foreach my $key (qw/groupIdEdit groupIdView url menuTitle timeZone/) {
|
||||
my $property_name = 'x-webgui-'.lc $key;
|
||||
next PROPERTY unless exists $event_properties->{$property_name};
|
||||
$properties->{$key} = $event_properties->{$property_name}->[0]->value;
|
||||
}
|
||||
|
||||
my $recur;
|
||||
if ($events{$id}->{rrule}) {
|
||||
$recur = _icalToRecur($session, $properties->{startDate}, $events{$id}->{rrule}->[1]);
|
||||
if (exists $event_properties->{rrule}) {
|
||||
$recur = _icalToRecur($session, $properties->{startDate}, $event_properties->{rrule}->[0]->value);
|
||||
}
|
||||
|
||||
# save events for later
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use strict;
|
|||
use base 'WebGUI::Workflow::Activity';
|
||||
use WebGUI::International;
|
||||
use WebGUI::Asset;
|
||||
use WebGUI::VersionTag;
|
||||
use DateTime;
|
||||
|
||||
=head1 NAME
|
||||
|
|
@ -74,8 +75,8 @@ sub execute {
|
|||
return $self->COMPLETE unless $piped;
|
||||
my ( $recurId, $rest ) = split /\|/, $piped, 2;
|
||||
|
||||
$self->processRecurrence( $recurId, $timeLimit )
|
||||
and $piped = $rest;
|
||||
$self->processRecurrence( $recurId, $timeLimit );
|
||||
$piped = $rest;
|
||||
}
|
||||
|
||||
$instance->setScratch( recurrences => $piped );
|
||||
|
|
@ -165,20 +166,36 @@ sub processRecurrence {
|
|||
my ( $self, $recurId, $timeLimit ) = @_;
|
||||
my $eventId = $self->findLastEventId($recurId);
|
||||
my $event = WebGUI::Asset::Event->newById( $self->session, $eventId );
|
||||
if (! $event) {
|
||||
$self->session->log->warn("Unable to instanciate event with assetId $eventId");
|
||||
return 0;
|
||||
}
|
||||
##Ignore assets in the trash. Same with assets in the clipboard since they would not be
|
||||
##put into the clipboard.
|
||||
if ($event->state ne 'published') {
|
||||
return 0;
|
||||
}
|
||||
my $recur = $event->getRecurrence;
|
||||
|
||||
my $versionTag = WebGUI::VersionTag->create($self->session, {name => 'Extend Calendar Recurrence for assetId '.$event->getId, });
|
||||
$versionTag->setWorking();
|
||||
my $start = $event->getDateTimeStart->truncate(to => 'day');
|
||||
my $limit = DateTime->today->add( years => 2 );
|
||||
my $end = $event->limitedEndDate($limit);
|
||||
my $set = $event->dateSet( $recur, $start, $end );
|
||||
my $i = $set->iterator;
|
||||
|
||||
while ( my $d = $i->next ) {
|
||||
return if ( time > $timeLimit );
|
||||
my $time_limit = 0;
|
||||
DATE: while ( my $d = $i->next ) {
|
||||
if ( time > $timeLimit ) {
|
||||
$time_limit = 1;
|
||||
last DATE;
|
||||
}
|
||||
$event->generateRecurrence($d);
|
||||
}
|
||||
|
||||
return 1;
|
||||
$versionTag->commit;
|
||||
return $time_limit ? 1 : 0;
|
||||
} ## end sub processRecurrence
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ sub execute {
|
|||
comments => $versionTag->get('comments'),
|
||||
url => $urlOfSingleAsset,
|
||||
};
|
||||
my $template = WebGUI::Asset->newByDynamicClass($self->session, $self->get('templateId'));
|
||||
my $template = WebGUI::Asset->newById($self->session, $self->get('templateId'));
|
||||
my $message = $template->process($var);
|
||||
my $properties = {
|
||||
status=>"completed",
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ sub sendMessage {
|
|||
comments => $versionTag->get('comments'),
|
||||
url => $approvalUrl,
|
||||
};
|
||||
my $template = WebGUI::Asset->newByDynamicClass($self->session, $self->get('templateId'));
|
||||
my $template = WebGUI::Asset->newById($self->session, $self->get('templateId'));
|
||||
my $messageText = $template->process($var);
|
||||
for my $groupId ( @{ $self->getGroupToApprove } ) {
|
||||
my $message
|
||||
|
|
|
|||
|
|
@ -99,9 +99,20 @@ sub execute {
|
|||
$log->info("Found subscription $subscription");
|
||||
my ($fieldId, $value) = split("~", $subscription);
|
||||
$log->info("Searching for threads that match $subscription");
|
||||
my $matchingThreads = $db->read("select metaData_values.assetId from metaData_values
|
||||
left join asset using (assetId) where fieldId=? and value like ? and creationDate > ?
|
||||
and className like ? and lineage like ? and state = ?",
|
||||
my $matchingThreads = $db->read("
|
||||
select mv.assetId
|
||||
from metaData_values mv
|
||||
left join asset a using (assetId)
|
||||
left join assetData d on
|
||||
mv.assetId = d.assetId
|
||||
and mv.revisionDate = d.revisionDate
|
||||
and d.revisionDate = (
|
||||
select max(revisionDate)
|
||||
from assetData d2
|
||||
where d2.assetId = d.assetId
|
||||
)
|
||||
where mv.fieldId=? and mv.value like ? and a.creationDate > ?
|
||||
and a.className like ? and a.lineage like ? and a.state = ?",
|
||||
[$fieldId, '%'.$value.'%', $lastTimeSent, 'WebGUI::Asset::Post::Thread%', $newsletter->get("lineage").'%', 'published']);
|
||||
while (my ($threadId) = $matchingThreads->array) {
|
||||
next
|
||||
|
|
|
|||
100
lib/WebGUI/Workflow/Activity/UpdateAssetSubscribers.pm
Normal file
100
lib/WebGUI/Workflow/Activity/UpdateAssetSubscribers.pm
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
package WebGUI::Workflow::Activity::UpdateAssetSubscribers;
|
||||
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 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::Workflow::Activity';
|
||||
use WebGUI::User;
|
||||
use WebGUI::Group;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Workflow::Activity::UpdateCollaborationSubscribers
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This workflow activity should be called whenever permissions to view a Collaboration System
|
||||
are changed. It will remove users who are no longer able to view the CS.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
See WebGUI::Workflow::Activity for details on how to use any activity.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, definition )
|
||||
|
||||
See WebGUI::Workflow::Activity::definition() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, "Workflow_Activity_UpdateAssetSubscribers");
|
||||
push(@{$definition}, {
|
||||
name => $i18n->get("name"),
|
||||
properties => { }
|
||||
});
|
||||
return $class->SUPER::definition($session,$definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 execute ( )
|
||||
|
||||
See WebGUI::Workflow::Activity::execute() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub execute {
|
||||
my $self = shift;
|
||||
my $asset = shift;
|
||||
|
||||
return unless $asset->get('subscriptionGroupId');
|
||||
|
||||
my $expireTime = time() + $self->getTTL();
|
||||
my $subscriptionGroup = WebGUI::Group->new($self->session, $asset->get('subscriptionGroupId'));
|
||||
|
||||
##Deserialize from scratch
|
||||
my @users = @{ $subscriptionGroup->getUsers }; ##Cache
|
||||
my @usersToDelete = (); ##Cache
|
||||
##Note, we could use grep here, but we can't interrupt if the workflow runs too long
|
||||
USER: foreach my $userId (@users) {
|
||||
if (time() > $expireTime) {
|
||||
#return $self->WAITING(1);
|
||||
}
|
||||
next USER if $asset->canView($userId);
|
||||
push @usersToDelete, $userId;
|
||||
}
|
||||
if (@usersToDelete) {
|
||||
$subscriptionGroup->deleteUsers(\@usersToDelete);
|
||||
}
|
||||
#Clear scratch
|
||||
return $self->COMPLETE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
1;
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue