diff --git a/docs/upgrades/packages-7.7.1/default_manage_adsku_template.wgpkg b/docs/upgrades/packages-7.7.1/default_manage_adsku_template.wgpkg new file mode 100644 index 000000000..67c8a4d19 Binary files /dev/null and b/docs/upgrades/packages-7.7.1/default_manage_adsku_template.wgpkg differ diff --git a/docs/upgrades/packages-7.7.1/default_purchase_adsku_template.wgpkg b/docs/upgrades/packages-7.7.1/default_purchase_adsku_template.wgpkg new file mode 100644 index 000000000..7d4589a06 Binary files /dev/null and b/docs/upgrades/packages-7.7.1/default_purchase_adsku_template.wgpkg differ diff --git a/docs/upgrades/upgrade_7.7.0-7.7.1.pl b/docs/upgrades/upgrade_7.7.0-7.7.1.pl index 9010edbc3..4aebadfd5 100644 --- a/docs/upgrades/upgrade_7.7.0-7.7.1.pl +++ b/docs/upgrades/upgrade_7.7.0-7.7.1.pl @@ -31,6 +31,7 @@ my $quiet; # this line required my $session = start(); # this line required # upgrade functions go here +adSkuInstall($session); addWelcomeMessageTemplateToSettings( $session ); addStatisticsCacheTimeoutToMatrix( $session ); @@ -80,6 +81,32 @@ sub addStatisticsCacheTimeoutToMatrix{ print "Done.\n" unless $quiet; } +#---------------------------------------------------------------------------- +# Describe what our function does +sub adSkuInstall { + my $session = shift; + print "\tCreate AdSku database table\n" unless $quiet; + $session->db->write("CREATE TABLE AdSku ( + assetId VARCHAR(22) BINARY NOT NULL, + revisionDate BIGINT NOT NULL, + purchaseTemplate VARCHAR(22) BINARY NOT NULL, + manageTemplate VARCHAR(22) BINARY NOT NULL, + adSpace VARCHAR(22) BINARY NOT NULL, + priority INTEGER DEFAULT '1', + pricePerClick Float DEFAULT '0', + pricePerImpression Float DEFAULT '0', + clickDiscounts VARCHAR(1024) default '', + impressionDiscounts VARCHAR(1024) default '', + PRIMARY KEY (assetId,revisionDate) + )"); + print "\tCreate Adsku crud table\n" unless $quiet; + use WebGUI::AssetCollateral::Sku::Ad::Ad; + WebGUI::AssetCollateral::Sku::Ad::Ad->crud_createTable($session); + print "\tinstall the AdSku Asset\n" unless $quiet; + $session->config->addToHash("assets", 'WebGUI::Asset::Sku::Ad' => { category => 'shop' } ); + print "DONE!\n" unless $quiet; +} + #---------------------------------------------------------------------------- # Describe what our function does #sub exampleFunction { diff --git a/lib/WebGUI/AdSpace/Ad.pm b/lib/WebGUI/AdSpace/Ad.pm index 9f97cf870..699fa7ad6 100644 --- a/lib/WebGUI/AdSpace/Ad.pm +++ b/lib/WebGUI/AdSpace/Ad.pm @@ -81,6 +81,12 @@ Deletes this ad. sub delete { my $self = shift; + my $iterator = WebGUI::AssetCollateral::Sku::Ad::Ad->getAllIterator($self->session,{ + constraints => [ { "adSkuPurchase.adId = ?" => $self->getId } ], + }); + while( my $object = $iterator->() ) { + $object->update({'isDeleted' => 1}); + } my $storage = WebGUI::Storage->get($self->session, $self->get("storageId")); $storage->delete if defined $storage; $self->session->db->deleteRow("advertisement","adId",$self->getId); diff --git a/lib/WebGUI/Asset/Sku/Ad.pm b/lib/WebGUI/Asset/Sku/Ad.pm new file mode 100644 index 000000000..7605916ed --- /dev/null +++ b/lib/WebGUI/Asset/Sku/Ad.pm @@ -0,0 +1,578 @@ +package WebGUI::Asset::Sku::Ad; + +=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 Tie::IxHash; +use base 'WebGUI::Asset::Sku'; +use WebGUI::Asset::Template; +use WebGUI::Form; +use WebGUI::Shop::Pay; +use WebGUI::AssetCollateral::Sku::Ad::Ad; +use WebGUI::AdSpace::Ad; + +=head1 NAME + +Package WebGUI::Asset::Sku::Ad + +=head1 DESCRIPTION + +This Asset allows ads to be purchased via WebGUI shopping + +=head1 SYNOPSIS + +use WebGUI::Asset::Sku::Ad; + +=head1 METHODS + +These methods are available from this class: + +=cut + +#------------------------------------------------------------------- + +=head2 definition + +Adds purchaseTemplate, manageTemplate, adSpace, priority, pricePerClick, pricePerImpression, clickDiscounts, impresisonDiscounts + +=cut + +sub definition { + my $class = shift; + my $session = shift; + my $definition = shift; + my %properties; + tie %properties, 'Tie::IxHash'; + my $i18n = WebGUI::International->new($session, "Asset_AdSku"); + %properties = ( + purchaseTemplate => { + tab => "display", + fieldType => "template", + namespace => "AdSku/Purchase", + defaultValue => 'R5zzB-ElsYbbiaS7aS3Uxw', + label => $i18n->get("property purchase template"), + hoverHelp => $i18n->get("property purchase template help"), + }, + manageTemplate => { + tab => "display", + fieldType => "template", + namespace => "AdSku/Manage", + defaultValue => 'xZyizWwkApUyvpHL9mI-FQ', + label => $i18n->get("property manage template"), + hoverHelp => $i18n->get("property manage template help"), + }, + adSpace => { + tab => "properties", + fieldType => "AdSpace", + namespace => "AdSku", + label => $i18n->get("property ad space"), + hoverHelp => $i18n->get("property ad Space help"), + }, + priority => { + tab => "properties", + defaultValue => '1', + fieldType => "integer", + label => $i18n->get("property priority"), + hoverHelp => $i18n->get("property priority help"), + }, + pricePerClick => { + tab => "properties", + defaultValue => '0.00', + fieldType => "float", + label => $i18n->get("property price per click"), + hoverHelp => $i18n->get("property price per click help"), + }, + pricePerImpression => { + tab => "properties", + defaultValue => '0.00', + fieldType => "float", + label => $i18n->get("property price per impression"), + hoverHelp => $i18n->get("property price per impression help"), + }, + clickDiscounts => { + fieldType => 'textarea', + label => $i18n->get('property click discounts'), + hoverHelp => $i18n->get('property click discounts help'), + defaultValue => '', + }, + impressionDiscounts => { + fieldType => 'textarea', + label => $i18n->get('property impression discounts'), + hoverHelp => $i18n->get('property impression discounts help'), + defaultValue => '', + }, + ); + + # Show the karma field only if karma is enabled + if ($session->setting->get("useKarma")) { + $properties{ karma } = { + type => 'integer', + label => $i18n->get('property adsku karma'), + hoverHelp => $i18n->get('property adsku karma description'), + defaultvalue => 0, + }; + } + + push(@{$definition}, { + assetName => $i18n->get('assetName'), + icon => 'adsku.gif', + autoGenerateForms => 1, + tableName => 'AdSku', + className => 'WebGUI::Asset::Sku::AdSku', + properties => \%properties, + }); + return $class->SUPER::definition($session, $definition); +} + +#------------------------------------------------------------------- + +=head2 getClickDiscountText + +returns the text to display the number of clicks purchasaed where discounts apply + +=cut + +sub getClickDiscountText { + my $self = shift; + return getDiscountText($self->i18n->get('click discount'), + $self->get('clickDiscounts')); +} + +#------------------------------------------------------------------- + +=head2 getConfiguredTitle + +combines the adSKu title with the customers ad title + +=cut + +sub getConfiguredTitle { + my $self = shift; + return $self->get('title') . ' (' . $self->getOptions->{'adtitle'} . ')'; +} + +#------------------------------------------------------------------- + +=head2 getDiscountAmount -- class level function + +returns the amount of discount to apply to this purchase + +=cut + +sub getDiscountAmount { + my($discounts,$count) = @_; + my @discounts = parseDiscountText( $discounts ); + my $previousDiscount = 0; + foreach my $discountSet ( @discounts ) { + last if $count < $discountSet->[1]; + $previousDiscount = $discountSet->[0]; + } + return $previousDiscount; +} + +#------------------------------------------------------------------- + +=head2 getDiscountText -- class level function + +returns a string with a coma seperated list of counts from the discount text + +=cut + +sub getDiscountText { + my($format,$discounts) = @_; + return sprintf( $format, join( ',', (map { $_->[1] } ( parseDiscountText( $discounts ) ) ) ) ); +} + +#------------------------------------------------------------------- + +=head2 getImpressionDiscountText + +returns the text to display the number of impressions purchased where discounts apply + +=cut + +sub getImpressionDiscountText { + my $self = shift; + return getDiscountText($self->i18n->get('impression discount'), + $self->get('impressionDiscounts')); +} + +#------------------------------------------------------------------- + +=head2 getPrice + +get the price for this purchase + +=cut + +sub getPrice { + my $self = shift; + my $options = $self->getOptions; + my $impressionCount = $options->{impressions} || $self->{formImpressions}; + my $clickCount = $options->{clicks}; + my $impressionDiscount = getDiscountAmount($self->get('impressionDiscounts'),$impressionCount ); + my $clickDiscount = getDiscountAmount($self->get('clickDiscounts'),$clickCount ); + my $impressionPrice = $self->get('pricePerImpression') * ( 100 - $impressionDiscount ) / 100 ; + my $clickPrice = $self->get('pricePerClick') * ( 100 - $clickDiscount ) / 100 ; + return sprintf "%.2f", $impressionPrice * $impressionCount + $clickPrice * $clickCount; +} + +#------------------------------------------------------------------- + +=head2 i18n + +returns an internationalization object for this class + +=cut + +sub i18n { + my $self = shift; + return WebGUI::International->new($self->session, "Asset_AdSku"); +} + +#------------------------------------------------------------------- + +=head2 manage + +generate template vars for manage page + +=cut + +sub manage { + my ($self) = @_; + my $session = $self->session; + + my $i18n = WebGUI::International->new($session, "Asset_AdSku"); + my %var; + $var{purchaseLink} = $self->getUrl; + my $iterator = WebGUI::AssetCollateral::Sku::Ad::Ad->getAllIterator($session,{ + constraints => [ { "adSkuPurchase.userId = ?" => $self->session->user->userId } ], + orderBy => 'dateOfPurchase', + }); + my %ads; + while( my $object = $iterator->() ) { + next if $object->get('isDeleted'); + next if exists $ads{$object->get('adId')}; + my $ad = $ads{$object->get('adId')} = WebGUI::AdSpace::Ad->new($session,$object->get('adId')); + push @{$var{myAds}}, { + rowTitle => $ad->get('title'), + rowClicks => $ad->get('clicks') . '/' . $ad->get('clicksBought'), + rowImpressions => $ad->get('impressions') . '/' . $ad->get('impressionsBought'), + rowRenewLink => $self->getUrl('func=renew;Id=' . $object->get('adSkuPurchaseId') ), + }; + } + return $self->processTemplate(\%var,undef,$self->{_viewTemplate}); +} + +#------------------------------------------------------------------- + +=head2 onCompletePurchase + +inserts the ad into the adspace... + +=cut + +sub onCompletePurchase { + my $self = shift; + my $item = shift; + my $options = $self->getOptions; + my $ad; + +# LATER: if we use Temp Storage for the image we need to move it to perm storage + + if( $options->{adId} ne '' ) { + $ad = WebGUI::AdSpace::Ad->new($self->session,$options->{adId}); + my $clicks = $options->{clicks} + $ad->get('clicksBought'); + my $impressions = $options->{impressions} + $ad->get('impressionsBought'); + $ad->set({ + title => $options->{'adtitle'}, + clicksBought => $clicks, + impressionsBought => $impressions, + url => $options->{'link'}, + storageId => $options->{'image'}, + }); + } else { + $ad = WebGUI::AdSpace::Ad->create($self->session,$self->get('adSpace'),{ + title => $options->{'adtitle'}, + clicksBought => $options->{'clicks'}, + impressionsBought => $options->{'impressions'}, + url => $options->{'link'}, + storageId => $options->{'image'}, + ownerUserId => $self->session->user->userId, + isActive => 1, + type => 'image', + priority => $self->get('priority'), + adSpace => $self->get('adSpace'), + }); + } + + WebGUI::AssetCollateral::Sku::Ad::Ad->create($self->session,{ + userId => $item->transaction->get('userId'), + transactionItemId => $item->getId, + adId => $ad->getId, + clicksPurchased => $options->{'clicks'}, + impressionsPurchased => $options->{'impressions'}, + dateOfPurchase => $item->transaction->get('dateOfPurchase'), + storedImage => $options->{'image'}, + isDeleted => 0, + }); + +} + +#------------------------------------------------------------------- + +=head2 onRemoveFromCart + +deletes the image if it gets removed from the cart + +LATER: if we switch to using Temp Storage we do not need to do this. + +=cut + +sub onRemoveFromCart { + my $self = shift; + my $item = shift; + my $options = $self->getOptions; + WebGUI::Storage->new($self->session,$options->{'image'})->delete; +} + +#------------------------------------------------------------------- + +=head2 onRefund + +delete the add if it gets refunded + +=cut + +sub onRefund { + my $self = shift; + my $item = shift; + my $ad; + + my $iterator = WebGUI::AssetCollateral::Sku::Ad::Ad->getAllIterator($self->session,{ + constraints => [ { "transactionItemId = ?" => $item->getId } ], + }); + my $crud = $iterator->(); + + my $ad = WebGUI::AdSpace::Ad->new($self->session,$crud->get('adId')); + $ad = WebGUI::AdSpace::Ad->new($self->session,$crud->get('adId')); + my $clicks = $ad->get('clicksBought') - $crud->get('clicksPurchased'); + my $impressions = $ad->get('impressionsBought') - $crud->get('impressionsPurchased') ; + $ad->set({ + clicksBought => $clicks, + impressionsBought => $impressions, + }); + + $crud->delete; +} + +#------------------------------------------------------------------- + +=head2 parseDiscountText -- class level function + +returns an array of array ref's that are extracted from the discount description text + +=cut + +sub parseDiscountText { + my $discountDescription = shift; + my @lines = split "\n", $discountDescription; + my @discounts; + foreach my $line ( @lines ) { + if( $line =~ /^(\d+)\@(\d+)/ ) { + push @discounts, [ $1, $2 ]; + } + } + return sort { $a->[1] <=> $b->[1] } @discounts; +} + +#------------------------------------------------------------------- + +=head2 prepareManage + +Prepares the template. + +=cut + +sub prepareManage { + my $self = shift; + $self->SUPER::prepareView(); + my $templateId = $self->get("manageTemplate"); + my $template = WebGUI::Asset::Template->new($self->session, $templateId); + $template->prepare($self->getMetaDataAsTemplateVariables); + $self->{_viewTemplate} = $template; +} + +#------------------------------------------------------------------- + +=head2 prepareView + +Prepares the template. + +=cut + +sub prepareView { + my $self = shift; + $self->SUPER::prepareView(); + my $templateId = $self->get("purchaseTemplate"); + my $template = WebGUI::Asset::Template->new($self->session, $templateId); + $template->prepare($self->getMetaDataAsTemplateVariables); + $self->{_viewTemplate} = $template; +} + +#------------------------------------------------------------------- + +=head2 view + +Displays the purchase adspace form + +=cut + +sub view { + my ($self) = @_; + my $session = $self->session; + my $options = $self->getOptions(); + + my $i18n = WebGUI::International->new($session, "Asset_AdSku"); + my %var = ( + formHeader => WebGUI::Form::formHeader($session, { action=>$self->getUrl }) + . WebGUI::Form::hidden( $session, { name=>"func", value=>"addToCart" }), + formFooter => WebGUI::Form::formFooter($session), + formSubmit => WebGUI::Form::submit( $session, { value => $i18n->get("form purchase button") }), + hasAddedToCart => $self->{_hasAddedToCart}, + continueShoppingUrl => $self->getUrl, + manageLink => $self->getUrl("func=manage"), + adSkuTitle => $self->get('title'), + adSkuDescription => $self->get('description'), + formTitle => WebGUI::Form::text($session, { + -name=>"formTitle", + -value=>$options->{adtitle}, + -size=>40 + -default=>'untitled', + }), + formLink => WebGUI::Form::Url($session, { + -name=>"formLink", + -value=>$options->{link}, + -size=>40 + -required=>1, + }), + formImage => WebGUI::Form::File($session, { + -name=>"formImage", + -value=>$options->{image}, + -size=>40 + -forceImageOnly=>1, + }), + formClicks => WebGUI::Form::Integer($session, { + -name=>"formClicks", + -value=>$options->{clicks}, + -size=>40 + -required=>1, + }), + formImpressions => WebGUI::Form::Integer($session, { + -name=>"formImpressions", + -value=>$options->{impressions}, + -size=>40 + -required=>1, + }), + formAdId => WebGUI::Form::Hidden($session, { + -name=>"formAdId", + -value=>$options->{adId} || '', + }), + clickPrice => $self->get('pricePerClick'), + impressionPrice => $self->get('pricePerImpression'), + clickDiscount => $self->getClickDiscountText, + impressionDiscount => $self->getImpressionDiscountText, + ); + return $self->processTemplate(\%var,undef,$self->{_viewTemplate}); +} + +#------------------------------------------------------------------- + +=head2 www_addToCart + +Add this subscription to the cart. + +=cut + +sub www_addToCart { + my $self = shift; + if ($self->canView) { + $self->{_hasAddedToCart} = 1; + my $form = $self->session->form; + my $imageStorage = $self->getOptions->{image} || WebGUI::Storage->create($self->session); # LATER should be createTemp + my $imageStorageId = $form->process('formImage', 'image', $imageStorage->getId); + my $cartInfo = { + adtitle => $form->process('formTitle'), + link => $form->process('formLink','url'), + clicks => $form->process('formClicks','integer'), + impressions => $form->process('formImpressions','integer'), + adId => $form->process('formAdId'), + image => $imageStorageId, + }; + $self->addToCart($cartInfo); + } + return $self->www_view; +} + +#------------------------------------------------------------------- + +=head2 www_manage + +manage previously purchased ads + +=cut + +sub www_manage { + my $self = shift; + my $check = $self->checkView; + return $check if (defined $check); + $self->session->http->setLastModified($self->getContentLastModified); + $self->session->http->sendHeader; + $self->prepareManage; + my $style = $self->processStyle($self->getSeparator); + my ($head, $foot) = split($self->getSeparator,$style); + $self->session->output->print($head, 1); + $self->session->output->print($self->manage); + $self->session->output->print($foot, 1); + return "chunked"; +} + +#------------------------------------------------------------------- + +=head2 www_renew + +renew an ad + +=cut + +sub www_renew { + my $self = shift; + my $session = $self->session; + my $id = $session->form->get('Id'); + my $crud = WebGUI::AssetCollateral::Sku::Ad::Ad->new($session,$id); + my $ad = WebGUI::AdSpace::Ad->new($session,$crud->get('adId')); + $self->applyOptions({ + adtitle => $ad->get('title'), + clicks => $crud->get('clicksPurchased'), + impressions => $crud->get('impressionsPurchased'), + link => $ad->get('url'), + image => $ad->get('storageId'), + adId => $crud->get('adId'), + }); + return $self->www_view; +} + +1; + diff --git a/lib/WebGUI/AssetCollateral/Sku/Ad/Ad.pm b/lib/WebGUI/AssetCollateral/Sku/Ad/Ad.pm new file mode 100644 index 000000000..a2edeffa8 --- /dev/null +++ b/lib/WebGUI/AssetCollateral/Sku/Ad/Ad.pm @@ -0,0 +1,81 @@ +package WebGUI::AssetCollateral::Sku::Ad::Ad; + +=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::Crud'; + +#------------------------------------------------ + +=head crud_definition + +defines the field this crud will contain + +userID = the id of the user that purchased the ad +transactionItemid = the id if the transaction item that completes this purchase +adId = th id if the ad purchased +clicksPurchased = the number of clicks the user purchased +impressionsPurchased = the number of impressions the user purchased +dateOfPurchase = the date of purchase +storedImage = storage for the image +isDeleted = boolean that indicates whether the ad has been deleted from the system + +=cut + +sub crud_definition { + my ($class, $session) = @_; + my $definition = $class->SUPER::crud_definition($session); + $definition->{tableName} = 'adSkuPurchase'; + $definition->{tableKey} = 'adSkuPurchaseId'; + $definition->{properties} = { + userId => { + fieldType => 'user', + defaultValue => undef, + }, + transactionItemId => { + fieldType => 'guid', + defaultValue => undef, + }, + adId => { + fieldType => 'guid', + defaultValue => undef, + }, + clicksPurchased => { + fieldType => 'integer', + defaultValue => undef, + }, + impressionsPurchased => { + fieldType => 'integer', + defaultValue => undef, + }, + dateOfPurchase => { + fieldType => 'date', + defaultValue => undef, + }, + storedImage => { + fieldType => 'guid', + defaultValue => undef, + }, + isDeleted => { + fieldType => 'yesNo', + defaultValue => 0, + }, + }; + return $definition; +} + +1; + diff --git a/lib/WebGUI/Form/AdSpace.pm b/lib/WebGUI/Form/AdSpace.pm new file mode 100644 index 000000000..22fd10431 --- /dev/null +++ b/lib/WebGUI/Form/AdSpace.pm @@ -0,0 +1,190 @@ +package WebGUI::Form::AdSpace; + +=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::SelectList'; +use WebGUI::International; +use WebGUI::SQL; + +=head1 NAME + +Package WebGUI::Form::AdSpace + +=head1 DESCRIPTION + +Creates a group chooser field for AdSpace values. + +=head1 SEE ALSO + +This is a subclass of WebGUI::Form::SelectList. + +=head1 METHODS + +The following methods are specifically available from this class. Check the superclass for additional methods. + +=cut + +#------------------------------------------------------------------- + +=head2 areOptionsSettable ( ) + +Returns 0. + +=cut + +sub areOptionsSettable { + return 0; +} + +#------------------------------------------------------------------- + +=head2 definition ( [ additionalTerms ] ) + +See the super class for additional details. + +=head3 additionalTerms + +The following additional parameters have been added via this sub class. + +=head4 size + +How many rows should be displayed at once? Defaults to 1. + +=head4 defaultValue + +This will be used if no value is specified. Should be passed as an array reference. Defaults to 1. + +=cut + +sub definition { + my $class = shift; + my $session = shift; + my $definition = shift || []; + push(@{$definition}, { + size=>{ + defaultValue=>1 + }, + }); + return $class->SUPER::definition($session, $definition); +} + +#------------------------------------------------------------------- + +=head2 getDatabaseFieldType ( ) + +Returns "CHAR(22) BINARY". + +=cut + +sub getDatabaseFieldType { + return "CHAR(22) BINARY"; +} + +#------------------------------------------------------------------- + +=head2 getName ( session ) + +Returns the human readable name of this control. + +=cut + +sub getName { + my ($self, $session) = @_; + return WebGUI::International->new($session, 'WebGUI')->get('Ad Space control name'); +} + +#------------------------------------------------------------------- + +=head2 getValueAsHtml ( ) + +Formats as a name. + +=cut + +sub getValueAsHtml { + my $self = shift; + my $item = WebGUI::AdSpace->new($self->session, $self->getOriginalValue); + if (defined $item) { + return $item->name; + } + return undef; +} + + +#------------------------------------------------------------------- + +=head2 isDynamicCompatible ( ) + +A class method that returns a boolean indicating whether this control is compatible with the DynamicField control. + +=cut + +sub isDynamicCompatible { + return 1; +} + +#------------------------------------------------------------------- + +=head2 toHtml ( ) + +Returns a group pull-down field. A group pull down provides a select list that provides name value pairs for all the groups in the WebGUI system. + +=cut + +sub toHtml { + my $self = shift; + my $options = { map { $_->getId => $_->get('name') } ( @{ WebGUI::AdSpace->getAdSpaces($self->session) } ) }; + $self->set('defaultValue', ( keys %{$options} )[0] ); + $self->set('options', $options ); + return $self->SUPER::toHtml(); +} + +#------------------------------------------------------------------- + +=head2 toHtmlAsHidden ( ) + +Creates a series of hidden fields representing the data in the list. + +=cut + +sub toHtmlAsHidden { + my $self = shift; + my $options = { map { $_->getId => $_->get('name') } ( @{ WebGUI::AdSpace->getAdSpaces($self->session) } ) }; + $self->set('defaultValue', ( keys %{$options} )[0] ); + $self->set('options', $options ); + return $self->SUPER::toHtmlAsHidden(); +} + +#------------------------------------------------------------------- + +=head2 toHtmlWithWrapper ( ) + +Renders the form field to HTML as a table row complete with labels, subtext, hoverhelp, etc. Also adds a manage icon next to the field if the current user is in the admins group. + +=cut + +sub toHtmlWithWrapper { + my $self = shift; + if ($self->session->user->isAdmin) { + my $subtext = $self->session->icon->manage("op=manageAdSpaces"); + $self->set("subtext",$subtext . $self->get("subtext")); + } + return $self->SUPER::toHtmlWithWrapper; +} + + +1; + diff --git a/lib/WebGUI/i18n/English/Asset_AdSku.pm b/lib/WebGUI/i18n/English/Asset_AdSku.pm new file mode 100644 index 000000000..f292e2149 --- /dev/null +++ b/lib/WebGUI/i18n/English/Asset_AdSku.pm @@ -0,0 +1,230 @@ +package WebGUI::i18n::English::Asset_AdSku; +use strict; + +our $I18N = { + 'assetName' => { + message => q|Ad Sales|, + lastUpdated => 0, + context => q|The name of the Ad Sales asset|, + }, + + + 'property purchase template' => { + message => q|purchase template|, + lastUpdated => 0, + context => q|the name of the template to use for purchasing ad space| + }, + + 'property purchase template help' => { + message => q|select a template to use for purchasing ad space|, + lastUpdated => 0, + context => q|select a template to use for purchasing ad space| + }, + + 'property manage template' => { + message => q|manage template|, + lastUpdated => 0, + context => q|the name of the template to use for managing ad space| + }, + + 'property manage template help' => { + message => q|select a template to use for managing ad space|, + lastUpdated => 0, + context => q|select a template to use for managing ad space| + }, + + 'property ad space' => { + message => q|ad space|, + lastUpdated => 0, + context => q|the ad space being sold here| + }, + + 'property ad Space help' => { + message => q|select the ad space being sold by this SKU|, + lastUpdated => 0, + context => q|select the ad space being sold by this SKU| + }, + + 'property priority' => { + message => q|priority|, + lastUpdated => 0, + context => q|the priority of the ads sold by this SKU| + }, + + 'property priority help' => { + message => q|indicate the priority of ads sold by this SKU. you can use multiple SKU's to sell the same ad space at different rates by setting different priorities for each SKU|, + lastUpdated => 0, + context => q|help text for the priority field on the AdSku Edit page| + }, + + 'property price per click' => { + message => q|price per click|, + lastUpdated => 0, + context => q|the price charged per click| + }, + + 'property price per click help' => { + message => q|indicate how much to charge for each click purchased|, + lastUpdated => 1165511641, + context => q|help for the price per click field| + }, + + 'property price per impression' => { + message => q|price per impression|, + lastUpdated => 0, + context => q|the price charged for each impression of this ad| + }, + + 'property price per impression help' => { + message => q|indicate how much to purchase for each impression purchased|, + lastUpdated => 0, + context => q|help text fot the price per impression field| + }, + + 'property click discounts' => { + message => q|click discounts|, + lastUpdated => 0, + context => q|the discounts offered based on number of clicks| + }, + + 'property click discounts help' => { + message => q|enter discounts one per line at the start of the line. extra text is ignored so you can put comments. each discount consists of two numbers seperated by '@' with no spaces. the first number is the percent(no decimal point) the second number is the number of items purchased|, + lastUpdated => 0, + context => q|help text for the click discounts field| + }, + + 'property impression discounts' => { + message => q|impression discounts|, + lastUpdated => 0, + context => q|the discounts offered based on number of impressions purchased| + }, + + 'property impression discounts help' => { + message => q|enter discounts one per line at the start of the line. extra text is ignored so you can put comments. each discount consists of two numbers seperated by '@' with no spaces. the first number is the percent(no decimal point) the second number is the number of items purchased|, + lastUpdated => 0, + context => q|help text for the impresison discounts field| + }, + + 'property adsku karma' => { + message => q|karma|, + lastUpdated => 0, + context => q|the karm field name| + }, + + 'property adsku karma description' => { + message => q|how much karm dos this offer|, + lastUpdated => 0, + context => q|description for the karma field| + }, + + 'form purchase per click' => { + message => q|@ %f per click|, + lastUpdated => 0, + context => q|%f is the price charged for each click on the ad| + }, + + 'form purchase per impression' => { + message => q|@ %f per impression|, + lastUpdated => 0, + context => q|%f is the price charged for each impression of the ad| + }, + + 'form manage title' => { + message => q|Manage My Ads|, + lastUpdated => 0, + context => q|text for the title of the form where the user can manage previously purchased advertisements| + }, + + 'form manage link' => { + message => q|Manage My Ads|, + lastUpdated => 0, + context => q|text for a link to the form where the user can manage previously purchased advertisements| + }, + + 'form purchase link' => { + message => q|Purchase Ads|, + lastUpdated => 0, + context => q|text for a link to the form where the user can purchase advertisements| + }, + + 'form manage table header title' => { + message => q|Title|, + lastUpdated => 0, + context => q|header for the adspace manage form: the title field| + }, + + 'form manage table header clicks' => { + message => q|Clicks|, + lastUpdated => 0, + context => q|header for the adspace manage form: the clicks field| + }, + + 'form manage table header impressions' => { + message => q|Impressions|, + lastUpdated => 0, + context => q|header for the adspace manage form: the impressions field| + }, + + 'form manage table header renew' => { + message => q|Renew|, + lastUpdated => 0, + context => q|header for the adspace manage form: the renew field| + }, + + 'form manage table value deleted' => { + message => q|Deleted|, + lastUpdated => 0, + context => q|contents for the renew field on the manage ads table: indicates a deleted item| + }, + + 'form manage table value renew' => { + message => q|Renew|, + lastUpdated => 0, + context => q|contents for the renew field on the manage ads table: indicates a renewable item| + }, + + 'form purchase button' => { + message => q|Add To Cart|, + lastUpdated => 0, + context => q|add the described item to the shopping cart| + }, + + 'form purchase ad title' => { + message => q|Ad Title|, + lastUpdated => 0, + context => q|the title chosen by the buyer for the advertisement| + }, + + 'form purchase ad link' => { + message => q|Ad Link|, + lastUpdated => 0, + context => q|the link the advertisement leads to| + }, + + 'form purchase ad image' => { + message => q|Image|, + lastUpdated => 0, + context => q|the image to be displayed in the ad| + }, + + 'form purchase number of clicks' => { + message => q|Number of Clicks|, + lastUpdated => 0, + context => q|the number of clicks the buyer wishes to purchase| + }, + + 'form purchase number of impressions' => { + message => q|Number of Impressions|, + lastUpdated => 0, + context => q|the number of impressions the user wishes to purchase| + }, + +# 'TODO' => { +# message => q|TODO|, +# lastUpdated => 0, +# context => q|TODO| +# }, + +}; + +1; diff --git a/lib/WebGUI/i18n/English/WebGUI.pm b/lib/WebGUI/i18n/English/WebGUI.pm index 8b0ae8570..d03c5185c 100644 --- a/lib/WebGUI/i18n/English/WebGUI.pm +++ b/lib/WebGUI/i18n/English/WebGUI.pm @@ -4338,6 +4338,12 @@ Users may override this setting in their profile. 'recaptcha public key' => { message => 'reCAPTCHA Public Key' }, + 'Ad Space control name' => { + message => q|Ad Space|, + lastUpdated => 0, + context => q|name for the Ad Space control| + }, + }; 1; diff --git a/t/Asset/Sku/Ad.t b/t/Asset/Sku/Ad.t new file mode 100644 index 000000000..5055c8e35 --- /dev/null +++ b/t/Asset/Sku/Ad.t @@ -0,0 +1,116 @@ +# vim:syntax=perl +#------------------------------------------------------------------- +# 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 +#------------------------------------------------------------------ + +# Write a little about what this script tests. +# +# This tests WebGUI::Asset::Sku::Ad + +use FindBin; +use strict; +use lib "$FindBin::Bin/../../lib"; + +use Test::More; +use Test::Deep; + +use WebGUI::Test; # Must use this before any other WebGUI modules +use WebGUI::Session; +use WebGUI::Asset; +use WebGUI::Asset::Sku::Ad; +use WebGUI::AdSpace; +use WebGUI::Storage; + +#---------------------------------------------------------------------------- +# Init +my $session = WebGUI::Test->session; + + +#---------------------------------------------------------------------------- +# Tests + +plan tests => 8; # Increment this number for each test you create + +#---------------------------------------------------------------------------- +# put your tests here + +my $discounts = <<'EOT'; +5@500 +10@1000 +EOT + +my $discountsWithJunk = <<'EOT'; +comment +5@500 nuthr cmnt + +10@1000heresatuf1 +last coment +EOT + +# print $discounts, $discountsWithJunk; + +cmp_deeply([WebGUI::Asset::Sku::Ad::parseDiscountText($discounts)], + [ [ 5,500 ],[10,1000] ], + 'parseDiscounttext parses correctly'); + +cmp_deeply([WebGUI::Asset::Sku::Ad::parseDiscountText($discountsWithJunk)], + [ [ 5,500 ],[10,1000] ], + 'parseDiscounttext ignores comments and blank space'); + +is( WebGUI::Asset::Sku::Ad::getDiscountText('Discount at %s',$discounts), + 'Discount at 500,1000', + 'getDiscountText formats the text correctly'); + +is( WebGUI::Asset::Sku::Ad::getDiscountAmount($discounts,100),0,'no discount'); +is( WebGUI::Asset::Sku::Ad::getDiscountAmount($discounts,550),5,'5% discount'); +is( WebGUI::Asset::Sku::Ad::getDiscountAmount($discounts,1050),10,'10% discount'); + +# make an AdSku object + +my $root = WebGUI::Asset->getRoot($session); + + +my $sku = $root->addChild({ + className => "WebGUI::Asset::Sku::Ad", + title => "Ad Space For Sale", + adSpace => 'qwert', + priority => 1, + pricePerClick => 0.01, + pricePerImpression => 0.0001, + clickDiscounts => <<'EOCD', +5@500 +10@50000 +EOCD + impressionDiscounts => <<'EOID', +5@10000 +15@500000 +EOID +}); + +$sku->applyOptions({ + adtitle => 'Sold!', + link => 'http://localhost/', + clicks => 1000, + impressions => 100000, + image => 'asdfgh', # don't need this unless I test onCompletePurchse... +}); + +is($sku->getConfiguredTitle, 'Ad Space For Sale (Sold!)', 'configured title'); +is($sku->getPrice, '19.00', 'get Price'); +# $sku->onCompletePurchase($item); --> not really sure how to test the rest... +# $sku->onRefund + +#---------------------------------------------------------------------------- +# Cleanup +END { + $sku->purge; +} + +1; +