#!/usr/bin/perl
use strict;
my $bFound = 0;
my $sDir;
foreach $sDir (@INC)
{
if ($sDir eq ".")
{
$bFound = 1;
last;
}
}
if (!$bFound)
{
push (@INC, ".");
}
push (@INC, "cgi-bin");
require sl000001;
require ao000001;
require sm000001;
use HTML::Entities;
use strict;
$::prog_name = "SearchScript";
$::prog_name = $::prog_name;
$::prog_ver = '$Revision: 50724 $ ';
$::prog_ver = substr($::prog_ver, 11);
$::prog_ver =~ s/ \$//;
my $nFILEVERSION = 1;
my $gbFilterDefaultInputs = $::FALSE;
my $gbMissingFilterDefaultInputs = $::FALSE;
my $gbFilterPageUpdate = $::FALSE;
my $gbExcludeOutOfStockItems = $::TRUE;
my $sPath = Init();
my ($status, $sError);
my $TRUE_RESULT  =  1;
my $FALSE_RESULT =  0;
my $SKIP_RESULT  = -1;
my $VIEW_ALL_RESULTS_PAGE = -1;
my $nSearchNumber = '';
my $nProductCategoryNumber = '';
my $sSearchFile = $sPath;
my $sCustomSearch = "customsearch";
my $sProductCategorySearch = "productcategory";
if (defined $::g_InputHash{PAGE} &&
($::g_InputHash{PAGE} eq 'DynamicFilter'))
{
$gbExcludeOutOfStockItems = $::FALSE;
}
if (defined $::g_InputHash{PAGE} &&
($::g_InputHash{PAGE} eq 'DynamicFilter') &&
defined $::g_InputHash{DPR})
{
my @arrProductRefs = split ('_', $::g_InputHash{DPR});
my $rFile = \*PRODUCTINDEX;
my $sFilename = ACTINIC::GetPath() . "oldprod.fil";
my ($status, $sError) = ACTINIC::InitIndex($sFilename, $rFile, $::g_nSearchIndexVersion);
if ($status == $::SUCCESS)
{
my $sProductRef;
my %Product;
my @arrProductInfo;
foreach $sProductRef (@arrProductRefs)
{
($status, $sError) = ACTINIC::ProductSearch($sProductRef, $rFile, $sFilename, \%Product);
if ($status == $::SUCCESS)
{
my @arrProductFields;
my $sTemp;
push @arrProductFields, $sProductRef;
push @arrProductFields, $Product{SID};
($status, $sTemp) = ACTINIC::ProcessEscapableText($Product{NAME});
if ($status != $::SUCCESS)
{
$sTemp = '';
}
push @arrProductFields, $sTemp;
($status, $sTemp) = ACTINIC::ProcessEscapableText($Product{DESCRIPTION});
if ($status != $::SUCCESS)
{
$sTemp = '';
}
push @arrProductFields, $sTemp;
push @arrProductFields, ACTINIC::EncodeText2($Product{SECTION});
push @arrProductFields, ACTINIC::EncodeText2($Product{IMAGE});
push @arrProductFields, ACTINIC::EncodeText2($Product{ANCHOR});
push @arrProductFields, $Product{PRICE};
push @arrProductFields, $Product{SIMPLIFIED_PERMUTATIONS};
my $sPermutations = $Product{PERMUTATIONS};
my $delimiter = quotemeta("|");
my $sCommaDelimiter = quotemeta(",");
my @arrComponentPerms = split($sCommaDelimiter, $sPermutations);
my $sComponentPerm;
my @arrChildProducts;
foreach $sComponentPerm (@arrComponentPerms)
{
my @arrPermutations = split /$delimiter/, $sComponentPerm;
my $sPermutation;
foreach $sPermutation (@arrPermutations)
{
my($sChildProductDetails) = $sPermutation =~ /.*:.*:([^:]*)$/;
my @arrChildProdRefs = split('!', $sChildProductDetails);
push @arrChildProducts, $arrChildProdRefs[0];
}
}
@arrChildProducts = grep /\S/, @arrChildProducts;
my $sChildProducts = join ('|', @arrChildProducts);
push @arrProductFields, $sChildProducts;				
push @arrProductFields, $Product{PROPERTIES};
push @arrProductFields, $Product{UPLOADUDPS};
push @arrProductFields, $Product{STOCKCONTROLLED};
push @arrProductFields, $Product{INSTOCK};
push @arrProductFields, $Product{STOCKLEVEL};
my $nResultCount = scalar (@arrProductFields);
for (@arrProductFields) 
{
s/"/\\"/g;
}
my $sResults = join ('","', @arrProductFields);
$sResults = '{"ProductInfo": ["' . $sResults . '"]}';				
push @arrProductInfo, $sResults;
}
}
my $nProductInfoCount = scalar (@arrProductInfo);
my $sProductDetails = join (',', @arrProductInfo);
$sProductDetails = '[' . $sProductDetails . ']';
my $sSectionResult = '';
if (defined $::g_InputHash{SIDS})
{
my @arrSectionIDs = split ('_', $::g_InputHash{SIDS});
my $sSectionID;
my $nNonEmptySubSectionCount = 0;
my @arrSubSectionDetails;
foreach $sSectionID (@arrSectionIDs)
{
my @arrResponse = ACTINIC::GetSectionBlobName($sSectionID);
my $sSectionBlobName = $arrResponse[2];
if ($arrResponse[0] == $::SUCCESS)
{
my @arrSubSecResponse = ACTINIC::GetSubSections($sSectionBlobName);
if ($arrSubSecResponse[0] == $::SUCCESS && $arrSubSecResponse[1] != '')
{
my $sSubSections = '';
my @arrSubSectionIDs = split ('-', $arrSubSecResponse[1]);
my $sSubSectionIDs = '';
my $sSubSectionID;
foreach $sSubSectionID (@arrSubSectionIDs)
{
$sSubSectionIDs .= $sSubSectionID;
$sSubSectionIDs = join ('","', @arrSubSectionIDs);
}
$sSubSections .= '{"SectionID":' . '"' . $sSectionID . '"' . ',"SubSectionIDs": ["' . $sSubSectionIDs . '"]}';
push @arrSubSectionDetails, $sSubSections;
$nNonEmptySubSectionCount++;
}
}
}
my $sSubSectionDetails = join (',', @arrSubSectionDetails);
$sSectionResult = '"SectionDetails":{"SectionInfoCount":'. $nNonEmptySubSectionCount . ',"SectionInfoSet":[' . $sSubSectionDetails .']}';
}
my $sFinalResult = '{"ProductDetails": { "ProductInfoCount": ' . $nProductInfoCount . ',"ProductInfoSet": ' .$sProductDetails. ' }';
if ($sSectionResult ne '')
{
$sFinalResult .= ',' . $sSectionResult;
}
$sFinalResult .= '}';
PrintPage($sFinalResult, "application/json");
if (!$ACTINIC::B2B->Get('UserDigest') &&
$$::g_pSetupBlob{FILTERING_CACHE_ENABLED} &&
defined $$::g_pSetupBlob{UPLOAD_REFERENCE_NUMBER} &&
defined $::g_InputHash{SID})
{
my $sAjaxProductDetailsFile = ACTINIC::GetPath() . 'AjaxProductDetails_'.$$::g_pSetupBlob{UPLOAD_REFERENCE_NUMBER}.'_'.$::g_InputHash{SID}.'.js';
if (open(PROD_DETAILS_FILE, "+>".$sAjaxProductDetailsFile))
{
print PROD_DETAILS_FILE $sFinalResult;
close(PROD_DETAILS_FILE);
chmod(0666, $sAjaxProductDetailsFile);
}
}
ACTINIC::CleanupIndex($rFile);
exit;
}
PrintPage('{"ProductDetails": { "ProductInfoCount": 0, "ProductInfoSet": []} }', "application/json");
ACTINIC::CleanupIndex($rFile);
exit;
}
elsif ($::g_InputHash{ACTION} eq "MATCH")
{
my $sText = "";
if (exists $::g_InputHash{TEXT})
{
$sText = $::g_InputHash{TEXT};
}
$sText =~ s/^\s*//o;
$sText =~ s/\s*$//o;
ACTINIC::LogData("Match words; text ='$sText'", $::DC_SEARCH);
my $phashWordHits = {};
my $sMatchSearchValue = $sText;
($status, $sError) = Search::MatchText($sPath, \$sMatchSearchValue, $phashWordHits);
if ($status != $::SUCCESS)
{
ACTINIC::LogData("Match words failure: error was '$sError'", $::DC_SEARCH);
PrintPage('{"result":0, "words":[]}', "application/json");
exit;
}
ACTINIC::LogData("Match search has finished - sorting", $::DC_SEARCH);
my @WordResults = sort {
$phashWordHits->{$b} <=> $phashWordHits->{$a} ||
$a cmp $b
} keys %$phashWordHits;
ACTINIC::LogData("Word match sorting has finished", $::DC_SEARCH);
my $nResults = scalar (@WordResults);
ACTINIC::LogData("Word match search yielded $nResults hits.", $::DC_SEARCH);
my $nMaxResultCount = ACTINIC::DecodeText($::g_InputHash{MAXRESULTCOUNT}, $ACTINIC::FORM_URL_ENCODED);
if ($nMaxResultCount == "")
{
$nMaxResultCount = 10;
}
$nResults = ($nResults > $nMaxResultCount) ? $nMaxResultCount : $nResults;
my $nIncludeRelevance = ACTINIC::DecodeText($::g_InputHash{INCLUDERELEVANCE}, $ACTINIC::FORM_URL_ENCODED);
my $sResults = "";
if ($nIncludeRelevance == "1")
{
$sResults = join (',', map {"\"$_\",$phashWordHits->{$_}"} @WordResults[0 .. $nResults-1]);
$sResults = '[' . $sResults . ']';
}
else
{
$sResults = join ('","', @WordResults[0 .. $nResults-1]);
$sResults = '["' . $sResults . '"]';
}
ACTINIC::LogData("Words: $sResults", $::DC_SEARCH);
PrintPage('{"result":1, "matched":"' . $sMatchSearchValue . '", "count":' . $nResults . ', "words":' . $sResults . '}', "application/json");
exit;
}
elsif ($::g_InputHash{ACTION} eq "FULLPERMLIST")
{
if (exists $::g_InputHash{PRODREF})
{
my $sProdRef = $::g_InputHash{PRODREF};
my @arrProductRefs = split('_', $sProdRef);
my $rFile = \*PRODUCTINDEX;
my $sFilename = ACTINIC::GetPath() . "oldprod.fil";
my ($status, $sError) = ACTINIC::InitIndex($sFilename, $rFile, $::g_nSearchIndexVersion);
my @arrPermutations;		 
if ($status == $::SUCCESS)
{
my $sProductRef;
my %Product;			
my $sTemp;	
foreach $sProductRef (@arrProductRefs)
{
($status, $sError) = ACTINIC::ProductSearch($sProductRef, $rFile, $sFilename, \%Product);
if ($status == $::SUCCESS)
{				
$sTemp = $Product{PERMUTATIONS};					
push @arrPermutations, '{"'.$sProductRef.'":"'.$sTemp.'"}';			
}
}			 
}		 
my $sResults = join (',', @arrPermutations);
$sResults = '{"FullPermutationList": [' . $sResults . ']}';	
PrintPage($sResults, "application/json");
ACTINIC::CleanupIndex($rFile);
exit;
}
else
{		 
my $sResults = '{"FullPermutationList": []}';	
PrintPage($sResults, "application/json");
exit;
}
}
if (exists $::g_InputHash{PRODREF})
{
my $sHTML = DirectLinkToProduct($sPath, $::g_InputHash{PRODREF});
ACTINIC::SaveSessionAndPrintPage($sHTML, "");
exit;
}
elsif (exists $::g_InputHash{SECTIONID})
{
my $sSection = ACTINIC::DecodeText($::g_InputHash{SECTIONID}, $ACTINIC::FORM_URL_ENCODED);
my $sHTML = DisplayDirectLinkPage($sSection, $::TRUE );
$::g_bLoginPage = $::TRUE;
ACTINIC::SaveSessionAndPrintPage($sHTML, "");
exit;
}
elsif ($::g_InputHash{ACTION} eq "LOGIN")
{
my $sURL = $::Session->GetLastShopPage();
my $sPage = $sURL;
$sPage =~ s!.*?/([^/]*)$!$1!img;
my $sStorePath = ACTINIC::GetStoreFolderName() . '/' .  $sPage;
if ($sURL !~ m!.*$sStorePath$!i)
{
$sPage = $$::g_pSetupBlob{BROCHURE_MAIN_PAGE};
}
my $sSection = ACTINIC::DecodeText($sPage, $ACTINIC::FORM_URL_ENCODED);
my $sHTML = DisplayDirectLinkPage($sSection, $::TRUE );
$::g_bLoginPage = $::TRUE;
ACTINIC::SaveSessionAndPrintPage($sHTML, "");
exit;
}	
if (exists $::g_InputHash{SN})
{
$nSearchNumber = $::g_InputHash{SN};
unless ($nSearchNumber =~ /^\d*$/)
{
my $filelog = ACTINIC::GetPhrase(-1, 325, $nSearchNumber);
SearchError($filelog);
exit;
}
ACTINIC::LogData("Using custom search $nSearchNumber", $::DC_SEARCH);
}
elsif (exists $::g_InputHash{PC})
{
$nProductCategoryNumber = $::g_InputHash{PC};
unless ($nProductCategoryNumber =~ /^\d*$/)
{
my $filelog = ACTINIC::GetPhrase(-1, 3009, $nProductCategoryNumber);
SearchError($filelog);
exit;
}
ACTINIC::LogData("Using custom search $nProductCategoryNumber", $::DC_SEARCH);
}
else
{
ACTINIC::LogData("Using standard search", $::DC_SEARCH);
}
if (exists $::g_InputHash{PC})
{
$sSearchFile .= $sProductCategorySearch."_$nProductCategoryNumber.fil";
}
else
{
$sSearchFile .= $sCustomSearch. "$nSearchNumber.fil";
}
my @SearchCmd = ();
my @PropertyTypes = ("Text Property", "Date", "Integer");
my $Item;
if ($::g_InputHash{FT} eq "GF")
{
@SearchCmd = ();
foreach $Item (keys %::g_InputHash)
{
if ($Item eq "PC")
{
push @SearchCmd, "ProductCategory!".$Item."\n";
push @SearchCmd, "And\n";
}
elsif (($Item eq "SX") ||
($Item eq "SX_ID"))
{
push @SearchCmd, "Section!".$Item."\n";
push @SearchCmd, "And\n";
}
if ($Item eq "PR")
{
push @SearchCmd, "Price!PR\n";
push @SearchCmd, "And\n";
}
elsif(($Item =~ /^S_(\d+)_(\d+)_(\d+)/) ||
($Item =~ /^SX_(\d+)_(\d+)_(\d+)/))			
{
push @SearchCmd, $PropertyTypes[$3]."!".$Item."\n";
push @SearchCmd, "And\n";
}
elsif (($Item =~ /^hf_(.*)/) &&
(!exists $::g_InputHash{$1}))
{
$Item = $1;
if ($Item =~ /^S_(\d+)_(\d+)_(\d+)/)
{
push @SearchCmd, $PropertyTypes[$3]."!".$Item."\n";
push @SearchCmd, "And\n";
}
}
}
}
else
{
unless (open SFILE, "<$sSearchFile")
{
my $filelog = ACTINIC::GetPhrase(-1, 21, $sSearchFile, $!);
SearchError($filelog);
exit;
}
@SearchCmd = <SFILE>;
close SFILE;
my $nFileVersion = shift (@SearchCmd);
unless ($nFileVersion == $nFILEVERSION)
{
my $filelog = ACTINIC::GetPhrase(-1, 326, $nFILEVERSION, $nFileVersion);
SearchError($filelog);
exit;
}
ACTINIC::LogData("Search command file version = $nFileVersion", $::DC_SEARCH);
if ($::g_InputHash{FT} eq "CF")
{
foreach $Item (keys %::g_InputHash)
{
if ($Item eq "SX_ID")
{
push @SearchCmd, "Section!SX_ID\n";
push @SearchCmd, "And\n";
}
elsif($Item =~ /^SX_(\d+)_(\d+)_(\d+)/)			
{
push @SearchCmd, $PropertyTypes[$3]."!".$Item."\n";
push @SearchCmd, "And\n";
}
}
}			
}
push @SearchCmd, "PriceSchedule\n";
push @SearchCmd, "And\n";
if (($gbExcludeOutOfStockItems == $::TRUE) &&
$$::g_pSearchSetup{SEARCH_EXCLUDE_OUTOFSTOCK_ITEMS})
{
push @SearchCmd, "InStockItem!IS\n";
push @SearchCmd, "And\n";
}
if ($::g_InputHash{GROUPONLY})
{
@SearchCmd = ();
push @SearchCmd, "ProductGroup!PG\n";
}
my %MatchWords;
my %UsedValues;
my $rProductReferenceToMatchingProperties = {};
my @ResultsStack;
my $bValidSearch = 0;
my $bPriceSearch = $::FALSE;
SearchMain(\@SearchCmd, \$bValidSearch, \$bPriceSearch, \%MatchWords, \@ResultsStack, $rProductReferenceToMatchingProperties);
my %NullSet;
my $rhashResults = \%NullSet;
if ($#ResultsStack == -1)
{
ACTINIC::LogData("Null (not empty) results stack!", $::DC_SEARCH);
}
elsif ($#ResultsStack == 0)
{
my $rArray = pop @ResultsStack;
if ($rArray->[0] == $TRUE_RESULT)
{
$rhashResults = $rArray->[1];
ACTINIC::LogData("Search resulted in a single result list (everything worked as expected).", $::DC_SEARCH);
}
else
{
ACTINIC::LogData("Search resulted in an empty result list (everything worked as expected).", $::DC_SEARCH);
}
}
else
{
ACTINIC::LogData("Search resulted in a set of result lists.  They should have been combined into a single list by now.  We will combine them at this point.", $::DC_SEARCH);
my $pLine;
my @ResultHashes;
foreach $pLine (@ResultsStack)
{
my ($nStatus, $rhashtemp) = @{$pLine};
ACTINIC::LogData("Result status was $nStatus", $::DC_SEARCH);
if (($nStatus == $FALSE_RESULT) and
($::g_InputHash{GB} eq 'A'))
{
@ResultHashes = ();
ACTINIC::LogData("Exiting loop - one of the lists to be combined is empty and the join is an INTERSECTION.  Using an empty set.", $::DC_SEARCH);
last;
}
elsif ($nStatus != $TRUE_RESULT)
{
ACTINIC::LogData("Skipping set of irrelevant results (SKIP set).", $::DC_SEARCH);
next;
}
else
{
push @ResultHashes, $rhashtemp;
ACTINIC::LogData("Found a result set.", $::DC_SEARCH);
}
}
if ($#ResultHashes == -1)
{
$rhashResults = \%NullSet;
ACTINIC::LogData("No populated results were found.  Using a null set.", $::DC_SEARCH);
}
else
{
ACTINIC::LogData("Found multiple results sets.  Combining results with global join operation ($::g_InputHash{GB}).", $::DC_SEARCH);
$rhashResults = shift @ResultHashes;
my $bJoin = ($::g_InputHash{GB} eq 'A') ? $::INTERSECT : $::UNION;
while (@ResultHashes)
{
my $rPrevious = $rhashResults;
my $rCurrent = shift @ResultHashes;
Search::JoinSearchResults($rPrevious, $rCurrent, $bJoin, $rhashResults);
}
}
}
if (defined $::g_InputHash{PAGE} &&
($::g_InputHash{PAGE} eq 'DynamicFilter'))
{
my $sFinalResult = GetFilterProductListJSON(%$rhashResults);
PrintPage($sFinalResult, "application/json");
if (!$ACTINIC::B2B->Get('UserDigest') &&
$$::g_pSetupBlob{FILTERING_CACHE_ENABLED} &&
defined $$::g_pSetupBlob{UPLOAD_REFERENCE_NUMBER} &&
defined $::g_InputHash{SID})
{
my $sAjaxProductListFile = ACTINIC::GetPath() . 'AjaxProductList_'.$$::g_pSetupBlob{UPLOAD_REFERENCE_NUMBER} .'_'.$::g_InputHash{SID}.'.js';
if (open(PROD_LIST_FILE, "+>".$sAjaxProductListFile))
{
print PROD_LIST_FILE $sFinalResult;
close(PROD_LIST_FILE);
chmod(0666, $sAjaxProductListFile);
}
}
exit;
}
if (!$bValidSearch)
{
my $sError;
my $sStart = ACTINIC::EncodeText2(ACTINIC::GetPhrase(-1, 113), $::FALSE);
if ($bPriceSearch &&
$::g_InputHash{ACTION})
{
$sError = ACTINIC::GetPhrase(-1, 245);
}
else
{
$sError = ACTINIC::GetPhrase(-1, 2085);
}
SearchError($sError, $::FALSE);
exit;
}
my $nPageNumber = $::g_InputHash{PN};
my @StringTemp = keys %MatchWords;
my $sWords = join (' ', @StringTemp);
($status, $sError) = DisplayResults($sPath, $rhashResults, $nPageNumber, $sWords, $rProductReferenceToMatchingProperties);
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
ACTINIC::LogData("Search calling exit", $::DC_SEARCH);
exit;
sub Init
{
my ($status, $sError, $unused);
($status, $sError, $::g_OriginalInputData, $unused, %::g_InputHash) = ACTINIC::ReadAndParseInput();
if ($::SUCCESS != $status)
{
ACTINIC::TerminalError($sError);
}
ACTINIC::LogData("      Validating input", $::DC_SEARCH);
my $sPath = ACTINIC::GetPath();
ACTINIC::SecurePath($sPath);
if (!$sPath)
{
ACTINIC::TerminalError("Path not found.");
}
if (!-e $sPath ||
!-d $sPath)
{
ACTINIC::TerminalError("Invalid path.");
}
my $nParamCount = keys %::g_InputHash;
if ($nParamCount <= 2 &&
((defined $::g_InputHash{FILTERPAGE}) || ((defined $::g_InputHash{FILTERPAGE}) && (defined $::g_InputHash{PN})))
)
{
my $sFilename;
my $sPageNumber = '';
my $sFilterPageName = '';
if (defined $::g_InputHash{FILTERPAGE})
{
$sFilterPageName = $::g_InputHash{FILTERPAGE};
my $sFilterPage = $::g_InputHash{FILTERPAGE};
if ($sFilterPageName =~ /(.*)\.Filter$/)
{			
$gbFilterPageUpdate = $::TRUE;
$gbExcludeOutOfStockItems = $::FALSE;
}
$sFilename = $sPath . $::g_InputHash{FILTERPAGE};
}
if (defined $::g_InputHash{PN})
{
$sPageNumber = $::g_InputHash{PN};
}
($status, $sError, $::g_OriginalInputData, $unused, %::g_InputHash) = ParseFilterDefaultInputs($sFilename);
if ($::SUCCESS == $status)
{
if ($sFilterPageName ne '')
{
$::g_InputHash{FILTERPAGE} = $sFilterPageName;
}
$gbFilterDefaultInputs = $::TRUE;
}
else
{
$gbMissingFilterDefaultInputs = $::TRUE;
}
if ($sPageNumber ne '')
{
$::g_InputHash{PN} = $sPageNumber;
}
}
ACTINIC::LogData("----- Search input parsed", $::DC_SEARCH);
if ((defined $::g_InputHash{NOLOGIN}) &&
($::g_InputHash{NOLOGIN} ne "0"))
{
$::g_InputHash{NOLOGIN} = "1";
}
ACTINIC::LogData("      Reading prompt blob", $::DC_SEARCH);
($status, $sError) = ACTINIC::ReadPromptFile($sPath);
if ($status != $::SUCCESS)
{
ACTINIC::ReportError($sError, $sPath);
}
ACTINIC::LogData("      Reading setup blob", $::DC_SEARCH);
($status, $sError) = ACTINIC::ReadSetupFile($sPath);
if ($status != $::SUCCESS)
{
ACTINIC::ReportError($sError, $sPath);
}
if ($::g_InputHash{ACTION} eq "MATCH")
{
ACTINIC::LogData("----- End Search Init early due to MATCH", $::DC_SEARCH);
return ($sPath);
}
ACTINIC::LogData("      Reading search setup blob", $::DC_SEARCH);
($status, $sError) = ACTINIC::ReadSearchSetupFile($sPath);
if ($status != $::SUCCESS)
{
ACTINIC::ReportError($sError, $sPath);
}
ACTINIC::LogData("      Reading catalog blob", $::DC_SEARCH);
($status, $sError) = ACTINIC::ReadCatalogFile($sPath);
if ($status != $::SUCCESS)
{
ACTINIC::ReportError($sError, $sPath);
}
if (defined $::g_InputHash{PAGE} &&
($::g_InputHash{PAGE} eq 'DynamicFilter'))
{
ACTINIC::LogData("      Checking B2B mode", $::DC_SEARCH);
my ($sUserDigest, $sBaseFile);
$sUserDigest = $ACTINIC::B2B->Get('UserDigest');
if (!$sUserDigest)
{
($sUserDigest, $sBaseFile) = ACTINIC::CaccGetCookies();
$ACTINIC::B2B->Set('UserDigest',$sUserDigest);
$ACTINIC::B2B->Set('BaseFile',  $sBaseFile);
}
if (!$sUserDigest)
{
ACTINIC::LogData("----- End Search Init early due to Dynamic Filtering", $::DC_SEARCH);
return ($sPath);
}			
}
($status, $sError) = ACTINIC::ReadTaxSetupFile($sPath);
if ($status != $::SUCCESS)
{
ACTINIC::ReportError($sError, $sPath);
}
($status, $sError) = ACTINIC::ReadLocationsFile($sPath);
if ($status != $::SUCCESS)
{
ACTINIC::ReportError($sError, $sPath);
}
ACTINIC::LogData("      Initialising session - GetCookies", $::DC_SEARCH);
my ($sCartID, $sContactDetails) = ACTINIC::GetCookies();
ACTINIC::LogData("      Initialising session - new Session", $::DC_SEARCH);
$::Session = new Session($sCartID, $sContactDetails, ACTINIC::GetPath(), $::TRUE);
my @Response = $::Session->RestoreCheckoutInfo();
if ($Response[0] != $::SUCCESS)
{
return (@Response);
}
no strict 'refs';
my ($Status, $Message, $pBillContact, $pShipContact, $pShipInfo, $pTaxInfo, $pGeneralInfo, $pPaymentInfo, $pLocationInfo) = @Response;
%::g_BillContact	= %$pBillContact;
%::g_ShipContact 	= %$pShipContact;
%::g_ShipInfo	 	= %$pShipInfo;
%::g_TaxInfo		= %$pTaxInfo;
%::g_GeneralInfo 	= %$pGeneralInfo;
%::g_PaymentInfo  = %$pPaymentInfo;
%::g_LocationInfo = %$pLocationInfo;
$::g_sWebSiteUrl = $::Session->GetBaseUrl();
$::g_sContentUrl = $::g_sWebSiteUrl;
ACTINIC::LogData("      Checking B2B mode", $::DC_SEARCH);
my ($sUserDigest, $sBaseFile);
$sUserDigest = $ACTINIC::B2B->Get('UserDigest');
if (!$sUserDigest)
{
($sUserDigest, $sBaseFile) = ACTINIC::CaccGetCookies();
$ACTINIC::B2B->Set('UserDigest',$sUserDigest);
$ACTINIC::B2B->Set('BaseFile',  $sBaseFile);
}
if ($sUserDigest)
{
$sBaseFile   = $ACTINIC::B2B->Get('BaseFile');
($::g_sWebSiteUrl, $::g_sContentUrl) = ($sBaseFile, $sBaseFile);
}
elsif( $::g_InputHash{BASE} )
{
($::g_sWebSiteUrl, $::g_sContentUrl) = ($::g_InputHash{BASE}, $::g_InputHash{BASE});
}
ACTINIC::LogData("----- End Search Init", $::DC_SEARCH);
return ($sPath);
}
sub ParseSearchInput
{
my ($rhashResults) = @_;
my @EncodedInput = split (/[&=]/, $::g_OriginalInputData);
if ($#EncodedInput % 2 != 1)
{
return ($::FAILURE, "Bad input string \"" . ACTINIC::HTMLEncode($::g_OriginalInputData) . "\".  Argument count " . $#EncodedInput . ".\n", '', '', 0, 0);
}
my ($key, $value);
my @hiddenInputs;
while (@EncodedInput)
{
$key = ACTINIC::DecodeText(shift @EncodedInput, $ACTINIC::FORM_URL_ENCODED);
$value = ACTINIC::DecodeText(shift @EncodedInput, $ACTINIC::FORM_URL_ENCODED);
if (exists $$rhashResults{$key})
{
push @{$$rhashResults{$key}}, $value;
}
else
{
$$rhashResults{$key} = [$value];
}
if ($key =~ /^hf_/)
{
push @hiddenInputs, $key;
}
}
foreach $key (@hiddenInputs)
{
$key =~ /^hf_(.*)$/;
if (!exists $$rhashResults{$1})
{
$$rhashResults{$1} = $$rhashResults{$key};
}
delete $$rhashResults{$key};
}
return ($::SUCCESS, '');
}
sub SearchMain
{
my ($plistSearchCommands, $pbValidSearch, $pbPriceSearch, $pmapKeywordsFound, $pResultsStack, $pmapProductReferenceToMatchingProperties) = @_;
my $sPath = ACTINIC::GetPath();
if ($gbMissingFilterDefaultInputs == $::TRUE)
{
SearchError("No filter default input defined. \
Please check if the variable 'FilterDefaultInput' is included in the section layout");
exit;
}
ACTINIC::LogData("Search command: \n" . join("", @$plistSearchCommands), $::DC_SEARCH);
my ($sLine, %mapInputKeyToValueArray);
foreach $sLine (@$plistSearchCommands)
{
chomp $sLine;
ACTINIC::LogData("++++ Processing command: $sLine", $::DC_SEARCH);
my ($sCmd, $sSearchControlName, $sKeywordBooleanControlName) = split ('!', $sLine);
ACTINIC::LogData("Command parsed: Command='$sCmd', Search Control Name='$sSearchControlName', Keyword Join Control Name='$sKeywordBooleanControlName'", $::DC_SEARCH);
my $sSearchValue = '';
if ($sSearchControlName)
{
if (exists $::g_InputHash{$sSearchControlName})
{
$sSearchValue = $::g_InputHash{$sSearchControlName};
}
ACTINIC::LogData("Search parameter value ='$sSearchValue'", $::DC_SEARCH);
}
$sSearchValue =~ s/^\s*//o;
$sSearchValue =~ s/\s*$//o;
my $sKeywordBooleanOperation = '';
if ($sKeywordBooleanControlName)
{
if (exists $::g_InputHash{$sKeywordBooleanControlName})
{
$sKeywordBooleanOperation = $::g_InputHash{$sKeywordBooleanControlName};
}
ACTINIC::LogData("Keyword join value ='$sKeywordBooleanOperation'", $::DC_SEARCH);
}
if ($sCmd eq 'Text')
{
ACTINIC::LogData("Doing a keyword search.", $::DC_SEARCH);
my $bText = $::UNION;
ACTINIC::LogData("Defaulting to joining keywords with UNION.", $::DC_SEARCH);
if ($sKeywordBooleanOperation eq 'A')
{
$bText = $::INTERSECT;
ACTINIC::LogData("Overriding join method with INTERSECTION.", $::DC_SEARCH);
}
elsif ($sKeywordBooleanOperation ne 'O')
{
my $sError = ACTINIC::GetPhrase(-1, 244);
SearchError($sError);
exit;
}
if ($sSearchValue eq '')
{
ACTINIC::LogData("Searcher doesn't care about keywords.", $::DC_SEARCH);
next;
}
$$pbValidSearch = 1;
my $pTextHits = {};
($status, $sError) = Search::SearchText($sPath, \$sSearchValue, $bText, $pTextHits);
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
if (scalar (keys %$pTextHits))
{
push @$pResultsStack, [$TRUE_RESULT, $pTextHits];
my @matches = split (' ', $sSearchValue);
my $word;
foreach $word (@matches)
{
$$pmapKeywordsFound{$word} = 1;
}
if ($::DEBUG_CLASS_FILTER & $::DC_SEARCH)
{
my @Results = keys %$pTextHits;
my $nResults = scalar (@Results);
my $sResults = "";
map {$sResults .= $_ . "=" . $pTextHits->{$_} . ";"} @Results;
ACTINIC::LogData("The keyword search yielded $nResults hits: $sResults", $::DC_SEARCH);
}
}
else
{
push @$pResultsStack, [$FALSE_RESULT];
ACTINIC::LogData("The keyword search yielded no hits.", $::DC_SEARCH);
}
}
elsif ($sCmd eq 'Price')
{
ACTINIC::LogData("Doing a price range search.", $::DC_SEARCH);
$$pbPriceSearch = $::TRUE;
my $pmapAllPriceMatchedProducts = {};
my $nPriceBand;
unless (scalar (keys %mapInputKeyToValueArray))
{
($status, $sError) = ParseSearchInput(\%mapInputKeyToValueArray);
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
}
my $sCurrentValueOfMultiple = '';
my @listAllValuesForPrice = ();
if ($mapInputKeyToValueArray{$sSearchControlName})
{
@listAllValuesForPrice = @{$mapInputKeyToValueArray{$sSearchControlName}};
}
my $bAnyPrice = 0;
while (@listAllValuesForPrice)
{
my $nCurrentPRValue = shift @listAllValuesForPrice;
$nPriceBand = $nCurrentPRValue;
if (defined $nPriceBand && ($nPriceBand == $::ANY_PRICE_BAND))
{
$bAnyPrice = 1;
}
if (defined $nPriceBand &&
($nPriceBand != $::ANY_PRICE_BAND) && (!$bAnyPrice))
{
my %mapFoundProductsPriceRelevence;
ACTINIC::LogData("Searching price band $nPriceBand.", $::DC_SEARCH);
$$pbValidSearch = 1;
($status, $sError) = Search::SearchPrice($sPath, $nPriceBand, \%mapFoundProductsPriceRelevence);
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
map {$pmapAllPriceMatchedProducts->{$_} = $pmapAllPriceMatchedProducts->{$_} + $mapFoundProductsPriceRelevence{$_}} keys %mapFoundProductsPriceRelevence;
}
elsif($nPriceBand == $::ANY_PRICE_BAND)
{
ACTINIC::LogData("Searcher doesn't care about price range.", $::DC_SEARCH);
push @$pResultsStack, [$SKIP_RESULT];
}                            
}
if ((!$bAnyPrice) && ($nPriceBand != $::ANY_PRICE_BAND) && (scalar (keys %$pmapAllPriceMatchedProducts)))
{
push @$pResultsStack, [$TRUE_RESULT, $pmapAllPriceMatchedProducts];
if ($::DEBUG_CLASS_FILTER & $::DC_SEARCH)
{
my @Results = keys %$pmapAllPriceMatchedProducts;
my $nResults = scalar (@Results);
my $sResults = join (';', @Results);
ACTINIC::LogData("The price range search yielded $nResults hits: $sResults", $::DC_SEARCH);
}
}
elsif (!$bAnyPrice)
{
ACTINIC::LogData("Price band search yielded no hits.", $::DC_SEARCH);
push @$pResultsStack, [$FALSE_RESULT];
}
}
elsif (($sCmd eq 'Text Property') ||
($sCmd eq 'Integer') ||
($sCmd eq 'Date'))
{
ACTINIC::LogData("Doing arbitrary property search.  Property type='$sCmd'.", $::DC_SEARCH);
unless (exists $$::g_pSearchSetup{$sSearchControlName})
{
my $sError = ACTINIC::GetPhrase(-1, 327, $sSearchControlName);
SearchError($sError);
exit;
}
my $pBlobParam = $$::g_pSearchSetup{$sSearchControlName};
ACTINIC::LogData("Control Optional = $pBlobParam->{Optional}.", $::DC_SEARCH);
ACTINIC::LogData("Control Label = $pBlobParam->{Label}.", $::DC_SEARCH);
unless (scalar (keys %mapInputKeyToValueArray))
{
($status, $sError) = ParseSearchInput(\%mapInputKeyToValueArray);
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
}
my $pmapAllFoundProducts = {};
my $sCurrentValueOfMultiple = '';
my @listAllValuesForControl = ();
if ($mapInputKeyToValueArray{$sSearchControlName})
{
@listAllValuesForControl = @{$mapInputKeyToValueArray{$sSearchControlName}};
}
while (@listAllValuesForControl)
{
$sCurrentValueOfMultiple = shift @listAllValuesForControl;
ACTINIC::LogData("Searching for property value '$sCurrentValueOfMultiple'.", $::DC_SEARCH);
if (($sCurrentValueOfMultiple eq '') &&
(!$$pBlobParam{Optional}))
{
my $sError = ACTINIC::GetPhrase(-1, 328, $$pBlobParam{Label});
SearchError($sError);
exit;
}
$UsedValues{$sSearchControlName} = $sCurrentValueOfMultiple;
if (($sCmd eq 'Integer') &&
($sCurrentValueOfMultiple ne '')) # and the value is not blank (i.e. not ignored)
{
unless ($sCurrentValueOfMultiple =~ /^[-+]?\d+$/o)
{
my $sError = ACTINIC::GetPhrase(-1, 330, $sCurrentValueOfMultiple, $$pBlobParam{Label});
SearchError($sError);
exit;
}
}
elsif (($sCmd eq 'Date') &&
$sCurrentValueOfMultiple)
{
unless ($sCurrentValueOfMultiple =~ /\d{8}/o) # must be of the format YYYYMMDD (i.e. 8 digits)
{
my $sError = ACTINIC::GetPhrase(-1, 331, $sCurrentValueOfMultiple, $$pBlobParam{Label});
SearchError($sError);
exit;
}
}
else
{
}
if ($sCurrentValueOfMultiple ne '')
{
my %mapFoundProductsToRelevance;
$$pbValidSearch = 1;
($status, $sError) = Search::SearchProperty($sPath, $sSearchControlName, $sCurrentValueOfMultiple, \%mapFoundProductsToRelevance);
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
ACTINIC::LogData("Property search '$sSearchControlName' = '$sCurrentValueOfMultiple'.", $::DC_SEARCH);
if ($$::g_pSearchSetup{SEARCH_SHOW_PROPERTY})
{
my $sProductReference;
my $sLabel = ACTINIC::EncodeText2($pBlobParam->{Label}) . ": " . ACTINIC::EncodeText2($sCurrentValueOfMultiple) . "<BR>";
foreach $sProductReference (keys %mapFoundProductsToRelevance)
{
unless (exists $pmapProductReferenceToMatchingProperties->{$sProductReference})
{
$pmapProductReferenceToMatchingProperties->{$sProductReference} = [];
}
push @{$pmapProductReferenceToMatchingProperties->{$sProductReference}}, $sLabel;
}
}
map {$pmapAllFoundProducts->{$_} = $pmapAllFoundProducts->{$_} + $mapFoundProductsToRelevance{$_}} keys %mapFoundProductsToRelevance;				
if ($::DEBUG_CLASS_FILTER & $::DC_SEARCH)
{
my @Results = keys %mapFoundProductsToRelevance;
my $nResults = scalar (@Results);
my $sResults = join (';', @Results);
ACTINIC::LogData("The property search yielded $nResults hits for '$sSearchControlName' = '$sCurrentValueOfMultiple': $sResults", $::DC_SEARCH);
}
}
else
{
@listAllValuesForControl = ();
ACTINIC::LogData("Property search for '$sSearchControlName' being ignored (searcher doesn't care about value).", $::DC_SEARCH);
}
}
if ($sCurrentValueOfMultiple eq '')
{
ACTINIC::LogData("Property search for '$sSearchControlName' being ignored (searcher doesn't care about value).", $::DC_SEARCH);
push @$pResultsStack, [$SKIP_RESULT];
}
elsif (scalar (keys %$pmapAllFoundProducts))
{
if ($::DEBUG_CLASS_FILTER & $::DC_SEARCH)
{
my @Results = keys %$pmapAllFoundProducts;
my $nResults = scalar (@Results);
my $sResults = join (';', @Results);
ACTINIC::LogData("The property search yielded $nResults total hits: $sResults", $::DC_SEARCH);
}
push @$pResultsStack, [$TRUE_RESULT, $pmapAllFoundProducts];
}
else
{
ACTINIC::LogData("Property search for '$sSearchControlName' resulted in no hits.", $::DC_SEARCH);
push @$pResultsStack, [$FALSE_RESULT];
}
}
elsif ($sCmd eq 'Section')	      
{
my $pAllSectionHits = {};
my $nSectionID;
unless (scalar (keys %mapInputKeyToValueArray))
{
($status, $sError) = ParseSearchInput(\%mapInputKeyToValueArray);
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
}
my $sCurrentValueOfMultiple = '';
my @listAllValuesForSection = ();
if ($mapInputKeyToValueArray{$sSearchControlName})
{
@listAllValuesForSection = @{$mapInputKeyToValueArray{$sSearchControlName}};
}
my $bIgnoreSearch = scalar(@listAllValuesForSection) == 0 ? $::TRUE : $::FALSE;
while (!$bIgnoreSearch &&
@listAllValuesForSection)
{
$nSectionID = shift @listAllValuesForSection;
if (($nSectionID != -1) &&
(($sSearchControlName eq "SX_ID") || 
$nSectionID))
{
my $pSectionHits = {};
ACTINIC::LogData("Doing section search.", $::DC_SEARCH);
$$pbValidSearch = 1;
my $bIncludeSubSections = $::TRUE;
if (($sSearchControlName eq "SX_ID") &&
exists $::g_InputHash{SX_IN})
{
$bIncludeSubSections = $::g_InputHash{SX_IN};
}
($status, $sError) = Search::SearchSection($sPath, $nSectionID, $bIncludeSubSections, $pSectionHits);
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
%$pAllSectionHits = (%$pAllSectionHits, %$pSectionHits);
}
else
{
$bIgnoreSearch = $::TRUE;
}
}
if ($bIgnoreSearch)
{
ACTINIC::LogData("Section search for '$sSearchControlName' being ignored (searcher doesn't care about value).", $::DC_SEARCH);
push @$pResultsStack, [$SKIP_RESULT];
}
elsif (scalar (keys %$pAllSectionHits))
{
if ($::DEBUG_CLASS_FILTER & $::DC_SEARCH)
{
my @Results = keys %$pAllSectionHits;
my $nResults = scalar (@Results);
my $sResults = join (';', @Results);
ACTINIC::LogData("The section search for '$sSearchValue' yielded $nResults total hits: $sResults", $::DC_SEARCH);
}
push @$pResultsStack, [$TRUE_RESULT, $pAllSectionHits];
}
else
{
ACTINIC::LogData("Section search for '$nSectionID' resulted in no hits.", $::DC_SEARCH);
push @$pResultsStack, [$FALSE_RESULT];
}
}
elsif ($sCmd eq 'ProductCategory')
{
ACTINIC::LogData("Doing product category search.", $::DC_SEARCH);
my $pProductCategoryHits = {};
if ($sSearchValue)
{
$$pbValidSearch = 1;
($status, $sError) = Search::SearchContentCategory($sPath, $sSearchValue, $pProductCategoryHits);
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
if (scalar (keys %$pProductCategoryHits))
{
if ($::DEBUG_CLASS_FILTER & $::DC_SEARCH)
{
my @Results = keys %$pProductCategoryHits;
my $nResults = scalar (@Results);
my $sResults = join (';', @Results);
ACTINIC::LogData("The product category search for '$sSearchValue' yielded $nResults total hits: $sResults", $::DC_SEARCH);
}
push @$pResultsStack, [$TRUE_RESULT, $pProductCategoryHits];
}
else
{
ACTINIC::LogData("Product category search for '$sSearchValue' resulted in no hits.", $::DC_SEARCH);
push @$pResultsStack, [$FALSE_RESULT];
}
}
else
{
ACTINIC::LogData("Product category search being ignored (searcher doesn't care about value).", $::DC_SEARCH);
push @$pResultsStack, [$SKIP_RESULT];
}
}			
elsif ($sCmd eq 'ProductGroup')
{
ACTINIC::LogData("Doing product group search.", $::DC_SEARCH);
my $pGroupHits = {};
if ($sSearchValue)
{
$$pbValidSearch = 1;
($status, $sError) = Search::SearchProductGroup($sPath, $sSearchValue, $pGroupHits);
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
if (scalar (keys %$pGroupHits))
{
if ($::DEBUG_CLASS_FILTER & $::DC_SEARCH)
{
my @Results = keys %$pGroupHits;
my $nResults = scalar (@Results);
my $sResults = join (';', @Results);
ACTINIC::LogData("The product group search for '$sSearchValue' yielded $nResults total hits: $sResults", $::DC_SEARCH);
}
push @$pResultsStack, [$TRUE_RESULT, $pGroupHits];
}
else
{
ACTINIC::LogData("Product Group search for '$sSearchValue' resulted in no hits.", $::DC_SEARCH);
push @$pResultsStack, [$FALSE_RESULT];
}
}
else
{
ACTINIC::LogData("Product group search being ignored (searcher doesn't care about value).", $::DC_SEARCH);
push @$pResultsStack, [$SKIP_RESULT];
}
}
elsif ($sCmd eq 'PriceSchedule')
{
ACTINIC::LogData("Doing price schedule search.", $::DC_SEARCH);
my $nScheduleID;
($status, $sError, $nScheduleID) = ACTINIC::GetCurrentScheduleID();
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
ACTINIC::LogData("Searching for products hidden for price schedule $nScheduleID.", $::DC_SEARCH);
if (ACTINIC::IsPriceScheduleConstrained($nScheduleID))
{
my $pPriceScheduleHits = {};
($status, $sError) = Search::SearchPriceSchedule($sPath, $nScheduleID, $pPriceScheduleHits);
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
push @$pResultsStack, [$TRUE_RESULT, $pPriceScheduleHits];
if ($::DEBUG_CLASS_FILTER & $::DC_SEARCH)
{
my @Results = keys %$pPriceScheduleHits;
my $nResults = scalar (@Results);
my $sResults = join (';', @Results);
ACTINIC::LogData("The price schedule search for '$nScheduleID' yielded $nResults hits: $sResults", $::DC_SEARCH);
}
}
else
{
ACTINIC::LogData("There are no price schedule based restraints on the product set.", $::DC_SEARCH);
push @$pResultsStack, [$SKIP_RESULT];
}
}
elsif ($sCmd eq 'InStockItem')
{
ACTINIC::LogData("Doing product in stock search.", $::DC_SEARCH);
my $pProductInStockHits = {};
($status, $sError) = Search::SearchInStock($sPath, 1, $pProductInStockHits);
if ($status != $::SUCCESS)
{
SearchError($sError);
exit;
}
if (scalar (keys %$pProductInStockHits))
{
if ($::DEBUG_CLASS_FILTER & $::DC_SEARCH)
{
my @Results = keys %$pProductInStockHits;
my $nResults = scalar (@Results);
my $sResults = join (';', @Results);
ACTINIC::LogData("The product in stock search yielded $nResults total hits: $sResults", $::DC_SEARCH);
}
push @$pResultsStack, [$TRUE_RESULT, $pProductInStockHits];
}
else
{
ACTINIC::LogData("Products in stock search resulted in no hits.", $::DC_SEARCH);
push @$pResultsStack, [$FALSE_RESULT];
}			
}
elsif ($sCmd eq 'And')
{
ACTINIC::LogData("Doing an intersection combine of search results (and).", $::DC_SEARCH);
if ($#$pResultsStack < 1)
{
ACTINIC::LogData("There are no sets to combine.", $::DC_SEARCH);
}
else
{
my $pArray1 = pop @$pResultsStack;
my $pArray2 = pop @$pResultsStack;
if ($pArray1->[0] == $SKIP_RESULT)
{
ACTINIC::LogData("List 1 contains the results of a search that was ignored by the searcher.  Using list 2.", $::DC_SEARCH);
push @$pResultsStack, $pArray2;
}
elsif ($pArray2->[0] == $SKIP_RESULT)
{
ACTINIC::LogData("List 2 contains the results of a search that was ignored by the searcher.  Using list 1.", $::DC_SEARCH);
push @$pResultsStack, $pArray1;
}
elsif ( ( $pArray1->[0] == $FALSE_RESULT) ||
( $pArray2->[0] == $FALSE_RESULT))
{
ACTINIC::LogData("Both lists are empty sets.  The combined list is an empty set", $::DC_SEARCH);
push @$pResultsStack, [$FALSE_RESULT];
}
else
{
ACTINIC::LogData("Both lists are populated with results.  Combining the list.  Length of list 1 = "
. (scalar keys %{$pArray1->[1]}) . ".  Length of list 2 = " . (scalar keys %{$pArray2->[1]}) . ".", $::DC_SEARCH);
my $pJoins = {};
Search::JoinSearchResults( $pArray1->[1], $pArray2->[1], $::INTERSECT, $pJoins);
if (scalar (keys %$pJoins))
{
if ($::DEBUG_CLASS_FILTER & $::DC_SEARCH)
{
my @Results = keys %$pJoins;
my $nResults = scalar (@Results);
my $sResults = join (';', @Results);
ACTINIC::LogData("The combined list yielded $nResults hits: $sResults", $::DC_SEARCH);
}
push @$pResultsStack, [$TRUE_RESULT, $pJoins];
}
else
{
ACTINIC::LogData("The combined list is empty.", $::DC_SEARCH);
push @$pResultsStack, [$FALSE_RESULT];
}
}
}
}
elsif ($sCmd eq 'Or')
{
ACTINIC::LogData("Doing a union combine of search results (or).", $::DC_SEARCH);
if ($#$pResultsStack < 1)
{
ACTINIC::LogData("There are no sets to combine.", $::DC_SEARCH);
}
else
{
my $pArray1 = pop @$pResultsStack;
my $pArray2 = pop @$pResultsStack;
if ($pArray1->[0] == $FALSE_RESULT)
{
ACTINIC::LogData("List 1 is empty.  Using list 2.", $::DC_SEARCH);
push @$pResultsStack, $pArray2;
}
elsif ($pArray2->[0] == $FALSE_RESULT)
{
ACTINIC::LogData("List 2 is empty.  Using list 1.", $::DC_SEARCH);
push @$pResultsStack, $pArray1;
}
elsif ($pArray1->[0] == $SKIP_RESULT) # the first result set in ignored (no search criteria selected by the customer)
{
if ($pArray2->[0] == $SKIP_RESULT)
{
ACTINIC::LogData("Both list 1 and list 2 contain results of a search that is being ignored by the searcher.  The combined list is ignored as well.", $::DC_SEARCH);
push @$pResultsStack, [$SKIP_RESULT];
}
else
{
ACTINIC::LogData("List 1 contains results of a search that is being ignored by the searcher.  Using list 2.", $::DC_SEARCH);
push @$pResultsStack, $pArray2;
}
}
elsif ($pArray2->[0] == $SKIP_RESULT) # the second set is ignored (but if we are here, the first set is meaningful)
{
ACTINIC::LogData("List 2 contains results of a search that is being ignored by the searcher.  Using list 1.", $::DC_SEARCH);
push @$pResultsStack, $pArray1;
}
else
{
ACTINIC::LogData("Both lists are populated with results.  Combining the list.  Length of list 1 = "
. (scalar keys %{$pArray1->[1]}) . ".  Length of list 2 = " . (scalar keys %{$pArray2->[1]}) . ".", $::DC_SEARCH);
my $pJoins = {};
Search::JoinSearchResults($pArray1->[1], $pArray2->[1], $::UNION, $pJoins);
if (scalar (keys %$pJoins))
{
if ($::DEBUG_CLASS_FILTER & $::DC_SEARCH)
{
my @Results = keys %$pJoins;
my $nResults = scalar (@Results);
my $sResults = join (';', @Results);
ACTINIC::LogData("The combined list yielded $nResults hits: $sResults", $::DC_SEARCH);
}
push @$pResultsStack, [$TRUE_RESULT, $pJoins];
}
else
{
ACTINIC::LogData("The combined list is empty.", $::DC_SEARCH);
push @$pResultsStack, [$FALSE_RESULT];
}
}
}
}
else
{
ACTINIC::LogData("Unknown search command.", $::DC_SEARCH);
my $sError = ACTINIC::GetPhrase(-1, 332, $sCmd, $sSearchFile);
SearchError($sError);
exit;
}
}
}
sub SearchError
{
my ($sMessage, $bWriteIntoLog) = @_;
if (!defined($bWriteIntoLog))
{
$bWriteIntoLog = $::TRUE;
}
my ($status, $sError, $sHTML) = ACTINIC::BounceToPageEnhanced(5, ACTINIC::GetPhrase(-1, 1962) . $sMessage . ACTINIC::GetPhrase(-1, 1970) . ACTINIC::GetPhrase(-1, 2047),
'',
$::g_sWebSiteUrl,
$::g_sContentUrl, $::g_pSetupBlob, $::Session->GetLastShopPage(), \%::g_InputHash,
$::FALSE);
if ($bWriteIntoLog)
{
ACTINIC::RecordErrors($sMessage, ACTINIC::GetPath());
}
else
{
ACTINIC::LogData($sMessage, $::DC_SEARCH);
}
ACTINIC::UpdateDisplay($sHTML, $::g_OriginalInputData);
}
sub DisplayResults
{
my ($sPath, $rhashResults, $nPageNumber, $sSearchStrings, $rhashRefToProps) = @_;
ACTINIC::LogData("Sorting search results - extracting sort orders", $::DC_SEARCH);
my $sSort = $$::g_pSearchSetup{DEFAULT_SORT};
if ((exists $::g_InputHash{SO}) &&
($::g_InputHash{SO} ne ''))
{
$sSort = $::g_InputHash{SO};
}
else
{
$::g_OriginalInputData .= "&SO=" . $sSort;
}
my @aSort = split('_', $sSort);
push(@aSort, (0, 0, 0, 0));
my @SortOrders = split(/,/, $$::g_pSearchSetup{SORT_ORDERS});
my %SortAsc =
(
0 =>  1,
1 =>  0,
2 =>  1,
3 =>  0,
4 =>  1,
5 =>  0,
6 =>  1,
7 =>  0,
8 =>  0,
9 =>  0,
10 => 1,
11 => 0,
12 => 1,
13 => 0,
14 => 1,
15 => 0
);
my %SortBaseOrder =
(
0 =>  0,
1 =>  1,
2 =>  2,
3 =>  2,
4 =>  4,
5 =>  4,
6 =>  6,
7 =>  7,
8 =>  8,
9 =>  9,
10 => 10,
11 => 10,
12 => 12,
13 => 12,
14 => 14,
15 => 14
);
my $nOCount = @SortOrders;
my %mapProdRefToSortOrders;
my %mapProdRefToAlternateParentRefs;
map
{
my ($sProductRef, $refMatches) = ACTINIC::SplitDecoratedProductRef($_);
my @aMatches = @$refMatches;
my @aProductRefs = split(':', $sProductRef);
if (@aProductRefs == 2)
{
$mapProdRefToAlternateParentRefs{$aProductRefs[0]} = $aProductRefs[1];
}		
push(@aMatches, sprintf('%8.8x', $rhashResults->{$_}));
$mapProdRefToSortOrders{$aProductRefs[0]} = [@aMatches];
} keys %$rhashResults;
ACTINIC::LogData("Sorting search results - sorting", $::DC_SEARCH);
my $sAltProductRef;
foreach $sAltProductRef (keys %mapProdRefToAlternateParentRefs)
{
my $sAltParentProductRef = $mapProdRefToAlternateParentRefs{$sAltProductRef};
if(exists $mapProdRefToSortOrders{$sAltParentProductRef})
{
delete $mapProdRefToSortOrders{$sAltProductRef};
}
}
my $nOrderIndex = 0;
my %SortOrderIndex;
while ($nOrderIndex < $nOCount)
{
$SortOrderIndex{$SortOrders[$nOrderIndex]} = $nOrderIndex;
$nOrderIndex++;
}
$SortOrderIndex{0} = $nOCount;
$SortOrderIndex{1} = $nOCount + 1;
my $asc0 = $SortAsc{$aSort[0]};
my $asc1 = $SortAsc{$aSort[1]};
my $asc2 = $SortAsc{$aSort[2]};
my $asc3 = $SortAsc{$aSort[3]};
my $OrderIndex0 = $SortOrderIndex{$SortBaseOrder{$aSort[0]}};
my $OrderIndex1 = $SortOrderIndex{$SortBaseOrder{$aSort[1]}};
my $OrderIndex2 = $SortOrderIndex{$SortBaseOrder{$aSort[2]}};
my $OrderIndex3 = $SortOrderIndex{$SortBaseOrder{$aSort[3]}};
my @Results = sort
{
$mapProdRefToSortOrders{$asc0 ? $a : $b}->[$OrderIndex0] cmp $mapProdRefToSortOrders{$asc0 ? $b : $a}->[$OrderIndex0] ||
$mapProdRefToSortOrders{$asc1 ? $a : $b}->[$OrderIndex1] cmp $mapProdRefToSortOrders{$asc1 ? $b : $a}->[$OrderIndex1] ||
$mapProdRefToSortOrders{$asc2 ? $a : $b}->[$OrderIndex2] cmp $mapProdRefToSortOrders{$asc2 ? $b : $a}->[$OrderIndex2] ||
$mapProdRefToSortOrders{$asc3 ? $a : $b}->[$OrderIndex3] cmp $mapProdRefToSortOrders{$asc3 ? $b : $a}->[$OrderIndex3]
}
keys %mapProdRefToSortOrders;
my $sSearchProductList = GetFilterProductListJSON(%$rhashResults);
%$rhashResults = {};
ACTINIC::LogData("Cleaning up property list", $::DC_SEARCH);
my %rhashCleanRefToProps =
map
{
my ($sProductRef, $refMatches) = ACTINIC::SplitDecoratedProductRef($_);
my @aProductRefs = split(':', $sProductRef);
$aProductRefs[0] => $rhashRefToProps->{$_}} keys %$rhashRefToProps;
ACTINIC::LogData("Read search template", $::DC_SEARCH);
my $sFilename = $sPath . "results.html";
if (defined $::g_InputHash{FILTERPAGE})
{
$sFilename = $sPath . $::g_InputHash{FILTERPAGE};
my $sFilterPage = $::g_InputHash{FILTERPAGE};
if ($sFilterPage =~ /(.*)\.Filter$/)
{
$::g_InputHash{FILTERPAGE} = $1;
}
}
unless (open (TFFILE, "<$sFilename"))
{
return ($::FAILURE, ACTINIC::GetPhrase(-1, 21, $sFilename, $!));
}
my ($sHTML);
{
local $/;
$sHTML = <TFFILE>;
}
close (TFFILE);
my $sUrl = $::Session->GetBaseUrl();
if( $sUrl )
{
$sUrl =~ s/\/[^\/]*$/\//;
my $sStart = ACTINIC::EncodeText2(ACTINIC::GetPhrase(-1, 113), $::FALSE);
$sHTML =~ s/\?ACTION\=$sStart/\?ACTION\=$sStart\&BASE\=$sUrl/g;
}
my $sResultsTemplate = '';
if ($sHTML =~ /<ACTINIC:SEARCH_RESULT_TEMPLATE>(.*?)<\/ACTINIC:SEARCH_RESULT_TEMPLATE>/si)
{
$sResultsTemplate = $1;
}
my %mapTableProperties =
(
'ColumnCount'	=> '<div id="S_LISTCOLCOUNT".*?>(.*?)<\/div>',
'StartOfList' 	=> '<div id="S_LISTSTART".*?>(.*?)<\/div>',
'EndOfList' 	=> '<div id="S_LISTEND".*?>(.*?)<\/div>',
'StartOfRow' 	=> '<div id="S_LISTROWSTART".*?>(.*?)<\/div>',
'EndOfRow'		=> '<div id="S_LISTROWEND".*?>(.*?)<\/div>',
'StartOfCell'	=> '<div id="S_LISTCELLSTART".*?>(.*?)<\/div>',
'EndOfCell'		=> '<div id="S_LISTCELLEND".*?>(.*?)<\/div>'
);
if ($sHTML =~ /<ACTINIC:TAB_SEARCH_RESULTS>(.*?)<\/ACTINIC:TAB_SEARCH_RESULTS>/si)
{
my $sTableAttributeName;
foreach $sTableAttributeName (keys %mapTableProperties)
{
my $sMatchingPattern =  $mapTableProperties{$sTableAttributeName};
if ($sHTML =~ /$sMatchingPattern/si)
{
$mapTableProperties{$sTableAttributeName} =  decode_entities($1);
$sHTML =~ s/$sMatchingPattern//si;
}
else
{
return ($::FAILURE, ACTINIC::GetPhrase(-1, 262));
}
}
}
else
{
my $sTableAttributeName;
foreach $sTableAttributeName (keys %mapTableProperties)
{
$mapTableProperties{$sTableAttributeName} = '';
}
}
unless ($sHTML =~ /<ACTINIC:SEARCH_RESULTS>(.*?)<\/ACTINIC:SEARCH_RESULTS>/si)
{
return ($::FAILURE, ACTINIC::GetPhrase(-1, 262));
}
my $sRepeatXML = $1;
$sRepeatXML =~ s/(<script(\s*)type=\"text\/template\">([^`]*?)<\/script>)/$3/gi;
$sRepeatXML =~ s/(<sd_script)/<script/gi;
$sRepeatXML =~ s/(<\/sd_script)/<\/script/gi;
my ($nMin, $nMax);
my $nResultsLimit = $$::g_pSearchSetup{SEARCH_RESULTS_PER_PAGE};
my $bIncludeViewAllPage = $::FALSE;
my $nMaxVisibleLinks = 0;
my %mapPaginationDesignAttributes;		
my $bPaginationLinksTemplateDefined = $::FALSE;	
if ($sHTML =~ /<div id="PaginationLinksTemplate".*?>(.*?)<\/div>/si)
{	
$bPaginationLinksTemplateDefined = $::TRUE;
%mapPaginationDesignAttributes =
(
'nResultsLimit'			=> '<Actinic:PAGINATION_PRODUCTSPERPAGE>(.*?)<\/Actinic:PAGINATION_PRODUCTSPERPAGE>',
'bIncludeViewAllPage' 	=> '<Actinic:PAGINATION_INCLUDEFULLPAGE>(.*?)<\/Actinic:PAGINATION_INCLUDEFULLPAGE>',
'nMaxVisibleLinks' 		=> '<Actinic:PAGINATION_VISIBLELINKS>(.*?)<\/Actinic:PAGINATION_VISIBLELINKS>',
'sHeader' 					=> '<Actinic:PAGINATION_HEADER>(.*?)<\/Actinic:PAGINATION_HEADER>',		
'sShowFirstLink'			=> '<Actinic:PAGINATION_SHOWFIRSTURL>(.*?)<\/Actinic:PAGINATION_SHOWFIRSTURL>',
'sFirstPageURL' 			=> '<Actinic:PAGINATION_FIRSTPAGEURL>(.*?)<\/Actinic:PAGINATION_FIRSTPAGEURL>',
'sPrevPageURL' 			=> '<Actinic:PAGINATION_PREVPAGEURL>(.*?)<\/Actinic:PAGINATION_PREVPAGEURL>',
'sLinksPageURL'			=> '<Actinic:PAGINATION_LINKSPAGEURL>(.*?)<\/Actinic:PAGINATION_LINKSPAGEURL>',
'sNextPageURL'				=> '<Actinic:PAGINATION_NEXTPAGEURL>(.*?)<\/Actinic:PAGINATION_NEXTPAGEURL>',
'sLastPageURL'				=> '<Actinic:PAGINATION_LASTPAGEURL>(.*?)<\/Actinic:PAGINATION_LASTPAGEURL>',
'sFullPageURL'				=> '<Actinic:PAGINATION_FULLPAGEURL>(.*?)<\/Actinic:PAGINATION_FULLPAGEURL>'
);
my $sLinksDesignAttribute;
foreach $sLinksDesignAttribute (keys %mapPaginationDesignAttributes)
{
my $sMatchingPattern =  $mapPaginationDesignAttributes{$sLinksDesignAttribute};
if ($sHTML =~ /$sMatchingPattern/si)
{
$mapPaginationDesignAttributes{$sLinksDesignAttribute} =  decode_entities($1);
}
else
{
$mapPaginationDesignAttributes{$sLinksDesignAttribute} = '';
}
}
$nResultsLimit = $mapPaginationDesignAttributes{'nResultsLimit'};
$nMaxVisibleLinks = $mapPaginationDesignAttributes{'nMaxVisibleLinks'};
if($gbFilterPageUpdate)
{
$nResultsLimit = 0;
$nMaxVisibleLinks = 0;
}
if ($nMaxVisibleLinks == 0 &&
($nResultsLimit > 0))
{
$nMaxVisibleLinks = ActinicOrder::RoundTax(($#Results + 1) / $nResultsLimit, $ActinicOrder::CEILING);
}
$bIncludeViewAllPage = $mapPaginationDesignAttributes{'bIncludeViewAllPage'};			
}
my $bResultsLimited = $::FALSE;
if (($nResultsLimit > 0) && 
($nResultsLimit < $#Results + 1))
{
$bResultsLimited = $::TRUE;
}
if (!$bResultsLimited ||
(($bIncludeViewAllPage != 0) &&
(defined $::g_InputHash{PN}  &&
($::g_InputHash{PN} == $VIEW_ALL_RESULTS_PAGE))))		
{
$nMin = 0;
$nMax = $#Results + 1;
}
else
{
$nMin = $nPageNumber * $nResultsLimit;
$nMax = ($nPageNumber + 1) * $nResultsLimit;
}
if ($nMax > $#Results + 1)
{
$nMax = $#Results + 1;
}
my $sSummary = ACTINIC::GetPhrase(-1, 264, $nMin + 1, $nMax, ($#Results + 1));
ACTINIC::LogData("Create product HTML", $::DC_SEARCH);
my $sResults;
if ($#Results == -1)
{
$sResults = ACTINIC::GetPhrase(-1, 267);
undef $sSummary;
}
else
{
my ($status, $sError);
($status, $sError, $sResults) = SearchResultsParser($sPath, $sRepeatXML, \@Results, $nMin, $nMax, $sSearchStrings, \%mapTableProperties, \%rhashCleanRefToProps);
if ($status != $::SUCCESS)
{
return ($status, $sError);
}
}
my ($status, $sError, %mapInputKeyToValueArray);
if (defined $::g_InputHash{FILTERPAGE} ||
(defined $::g_InputHash{PAGE} &&
(lc($::g_InputHash{PAGE}) eq 'search')))
{
$sHTML =~ s/<Actinic:CONTENT_PAGE.*?<\/Actinic:CONTENT_PAGE>//si;
$sHTML =~ s/<div id=\"filter_results_area\"(.*?)>/<div id=\"filter_results_area\">/si;
$sHTML =~ s/<div id=\"search_results_list\"(.*?)>/<div id=\"search_results_list\">/si;
$sHTML =~ s/<div class=\"sort_by\"(.*?)>/<div class=\"sort_by\" id=\"SortBy\">/si;
unless (scalar (keys %mapInputKeyToValueArray))
{
($status, $sError) = ParseSearchInput(\%mapInputKeyToValueArray);
if ($status != $::SUCCESS)
{
return ($status, $sError);
}
}
my $sSearhHiddenFields;
my ($sCgiParam, $plistValues, $sHiddenField);
while (($sCgiParam, $plistValues) = each %mapInputKeyToValueArray)
{
my $sValue;
if ($sCgiParam =~ /[^(SO|PN)]/)
{
foreach $sValue (@$plistValues)
{
$sSearhHiddenFields .= sprintf("<INPUT TYPE=\"HIDDEN\" NAME=\"%s\" VALUE=\"%s\"/>", $sCgiParam, $sValue);
}
}
}
$sHTML =~ s/<Actinic:SEARCHFILTER_FIELDS>(.*?)<\/Actinic:SEARCHFILTER_FIELDS>/$sSearhHiddenFields/si;
my $sSearchSortOrderField = sprintf("<INPUT TYPE=\"HIDDEN\" NAME=\"SO\" VALUE=\"%s\"/>", $sSort);
$sHTML =~ s/<Actinic:SEARCH_SORTORDER>(.*?)<\/Actinic:SEARCH_SORTORDER>/$sSearchSortOrderField/si;
$sHTML =~ s/\"filter_sortorder\"/\"filter_sortorder_static\"/si;
undef $sSummary;
}
my $sSearchProductListScript = sprintf("<script type=\"text/javascript\"> var pg_aSearchProductList = %s;</script>", $sSearchProductList);
$sHTML =~ s/<Actinic:SEARCH_PRODUCTLIST><\/Actinic:SEARCH_PRODUCTLIST>/$sSearchProductListScript/si;	
$sHTML =~ s/<Actinic:SEARCH_RESULTS>.*?<\/Actinic:SEARCH_RESULTS>/$sResults/si;
ACTINIC::LogData("Building continuation links", $::DC_SEARCH);
my $sContinue;
if ($bResultsLimited)
{
my $sCustomNumber = '';
if (exists $::g_InputHash{SN})
{
$sCustomNumber = "&SN=$::g_InputHash{SN}";
}
my $sCustomSection = '';
if (exists $::g_InputHash{SX})
{
$sCustomSection = "&SX=$::g_InputHash{SX}";
}
my $sScript = sprintf('%s?SO=%s', $::g_sSearchScript, $sSort);
if (defined $::g_InputHash{TB})
{
$sScript .= sprintf('&TB=%s',  $::g_InputHash{TB});
}
if (defined  $::g_InputHash{GB})
{			
$sScript .= sprintf('&GB=%s',  $::g_InputHash{GB});				
}
if (defined $::g_InputHash{SS})
{
$sScript .= sprintf('&SS=%s%s%s',  
ACTINIC::EncodeText2($::g_InputHash{SS}, $::FALSE),
$sCustomNumber,
$sCustomSection);
}
if (defined  $::g_InputHash{PR})
{
$sScript .= sprintf('&PR=%s',  $::g_InputHash{PR});
}
if (defined  $::g_InputHash{PG})
{
$sScript .= sprintf('&PG=%s',  $::g_InputHash{PG});
}
if (defined $::g_InputHash{PC})
{
$sScript .= sprintf('&PC=%s',  $::g_InputHash{PC});
}
if (defined $::g_InputHash{FILTERPAGE})
{
$sScript .= sprintf('&FILTERPAGE=%s',  $::g_InputHash{FILTERPAGE});
if (defined $::g_InputHash{FT})
{
$sScript .= sprintf('&FT=%s',  $::g_InputHash{FT});
}
}
if (defined $::g_InputHash{GROUPONLY})
{
$sScript .= "&GROUPONLY=1";
}
my ($sCgiParam, $plistValues);
unless (scalar (keys %mapInputKeyToValueArray))
{
($status, $sError) = ParseSearchInput(\%mapInputKeyToValueArray);
if ($status != $::SUCCESS)
{
return ($status, $sError);
}
}
while (($sCgiParam, $plistValues) = each %mapInputKeyToValueArray)
{
if ($sCgiParam =~ /[S_|SX_].*/)
{
my $sValue;
foreach $sValue (@$plistValues)
{
$sValue =~ s/ /+/g;
$sValue =~ s/([^A-Za-z0-9\+-])/sprintf('%%%2.2x', ord($1))/eg;
$sScript .= "&" . ACTINIC::EncodeText2($sCgiParam, $::FALSE) . "=" . $sValue;
}
}
}
my $sPathAndHistory = ($::g_InputHash{SHOP} ? "&SHOP=" . ACTINIC::EncodeText2($::g_InputHash{SHOP}, $::FALSE) : "");
if (($gbFilterDefaultInputs == $::TRUE) && (defined $::g_InputHash{FILTERPAGE}))
{
$sScript = $::g_sSearchScript . '?FILTERPAGE=' . $::g_InputHash{FILTERPAGE};
}
else
{
$sScript .= $sPathAndHistory;	
}
my $sLinkFormat = '<A HREF="%s">';		
my $sLink;		
my $sPageLabel;
my $bShowPaginationLinks = $::TRUE;
if ($bPaginationLinksTemplateDefined &&
($bIncludeViewAllPage != 0) &&
(defined $::g_InputHash{PN} &&
($::g_InputHash{PN} == $VIEW_ALL_RESULTS_PAGE)))			
{
$sPageLabel = $mapPaginationDesignAttributes{'sShowFirstLink'};
$sLink = $sScript . "&PN=0";
$sPageLabel =~ s/<ACTINIC:PAGINATION_URLLINK><\/ACTINIC:PAGINATION_URLLINK>/$sLink/si;
$sContinue .= $sPageLabel;
$bShowPaginationLinks = $::FALSE;
}
my $nMaxPageCount = ActinicOrder::RoundTax(($#Results + 1) / $nResultsLimit, $ActinicOrder::CEILING);
my $nCurrentPageNo = 0;
if (defined $::g_InputHash{PN})
{
$nCurrentPageNo = $::g_InputHash{PN};
}
if ($bShowPaginationLinks)
{
if ($bPaginationLinksTemplateDefined)
{			
$sContinue .= $mapPaginationDesignAttributes{'sHeader'};
}
if (0 != $nPageNumber)
{			
if ($bPaginationLinksTemplateDefined)
{
$sPageLabel = $mapPaginationDesignAttributes{'sFirstPageURL'};
$sLink = $sScript . "&PN=0";
$sPageLabel =~ s/<ACTINIC:PAGINATION_URLLINK><\/ACTINIC:PAGINATION_URLLINK>/$sLink/si;
$sContinue .= $sPageLabel;
$sPageLabel = $mapPaginationDesignAttributes{'sPrevPageURL'};
$sLink = $sScript . "&PN=" . ($nPageNumber - 1);
$sPageLabel =~ s/<ACTINIC:PAGINATION_URLLINK><\/ACTINIC:PAGINATION_URLLINK>/$sLink/si;
$sContinue .= $sPageLabel;
}
else
{
$sLink = $sScript . "&PN=" . ($nPageNumber - 1);
$sLink = sprintf($sLinkFormat, $sLink);
$sContinue .= $sLink . ACTINIC::GetPhrase(-1, 265, $nResultsLimit) . "</A>"; # add the "Last 20" link
}
}
my $nPage;
my $nPageOffset = 0;
my $nCurrentPage = 0;
if($nMaxVisibleLinks == 0)
{
$nMaxVisibleLinks = $nMaxPageCount;
}
if (defined $::g_InputHash{PN} &&
($::g_InputHash{PN} > $VIEW_ALL_RESULTS_PAGE))
{
$nPageOffset = int ($::g_InputHash{PN} / $nMaxVisibleLinks);				
}
if (defined $::g_InputHash{PN} &&
($::g_InputHash{PN} ge 0))
{
$nCurrentPage = $::g_InputHash{PN};
}
my $nStartPage = 0;
my $nMaxPage = $nMaxPageCount - 1;
if ($bPaginationLinksTemplateDefined)
{
$nStartPage = $nPageOffset * $nMaxVisibleLinks;
$nMaxPage = $nStartPage + $nMaxVisibleLinks;
}
if($nMaxPage > $nMaxPageCount)
{
$nMaxPage = $nMaxPageCount;
}
for ($nPage = $nStartPage; $nPage <= $nMaxPage; $nPage++)
{
$sLink = $sScript . "&PN=" . $nPage;
if (defined $mapPaginationDesignAttributes{'sLinksPageURL'})
{				
$sPageLabel = $mapPaginationDesignAttributes{'sLinksPageURL'};
my $nPageIndex = $nPage + 1;
if ($nPage < $nMaxPage)
{
if ($nPage == $nCurrentPage)
{
$sPageLabel =~ s/<A(.*)<\/A>/ <b>$nPageIndex<\/b> /si;
}
else
{
$sPageLabel =~ s/<ACTINIC:PAGINATION_INDEX><\/ACTINIC:PAGINATION_INDEX>/$nPageIndex/si;						
$sPageLabel =~ s/<ACTINIC:PAGINATION_URLLINK><\/ACTINIC:PAGINATION_URLLINK>/$sLink/si;
}
$sContinue .= $sPageLabel;	
}
elsif ($nPage < $nMaxPageCount)
{
my $sExtraLinks = '...';
$sPageLabel =~ s/<ACTINIC:PAGINATION_INDEX><\/ACTINIC:PAGINATION_INDEX>/$sExtraLinks/si;
$sPageLabel =~ s/<ACTINIC:PAGINATION_URLLINK><\/ACTINIC:PAGINATION_URLLINK>/$sLink/si;
$sContinue .= $sPageLabel;	
}
}
else
{
$sPageLabel = ($nPage * $nResultsLimit + 1) . '-' . ((($nPage + 1) * $nResultsLimit) > ($#Results + 1) ? $#Results + 1 : ($nPage + 1) * $nResultsLimit);
$sLink = sprintf($sLinkFormat, $sLink);
if ($nPage == $nPageNumber)
{
$sContinue .= " " . $sPageLabel;
}
else
{
$sContinue .= " " . $sLink . $sPageLabel . "</A>";
}
}
}
if ($nMaxPageCount != $nPageNumber + 1)
{
$sLink = $sScript . "&PN=" . ($nPageNumber + 1);
if ($bPaginationLinksTemplateDefined)
{
$sPageLabel = $mapPaginationDesignAttributes{'sNextPageURL'};
$sPageLabel =~ s/<ACTINIC:PAGINATION_URLLINK><\/ACTINIC:PAGINATION_URLLINK>/$sLink/si;
$sContinue .= $sPageLabel;
$sLink = $sScript . "&PN=" . ($nMaxPageCount - 1);
$sPageLabel = $mapPaginationDesignAttributes{'sLastPageURL'};
$sPageLabel =~ s/<ACTINIC:PAGINATION_URLLINK><\/ACTINIC:PAGINATION_URLLINK>/$sLink/si;
$sContinue .= $sPageLabel;
}
else
{
my $nNextNoOfProds;
if (($nMaxPageCount - 1) == ($nPageNumber + 1))
{
$nNextNoOfProds = ($#Results + 1) - (($nPageNumber + 1) * $nResultsLimit);
}
else
{
$nNextNoOfProds = $nResultsLimit;
}				
$sLink = sprintf($sLinkFormat, $sLink);
$sContinue .= " " . $sLink . ACTINIC::GetPhrase(-1, 266, $nNextNoOfProds) . "</A>"; # add the "Next 20" link
}
}
if ($bPaginationLinksTemplateDefined &&
($bIncludeViewAllPage != 0))
{
$sPageLabel = $mapPaginationDesignAttributes{'sFullPageURL'};
$sLink = $sScript . "&PN=-1";
my $nTotalProducts = ($#Results + 1);
$sPageLabel =~ s/<ACTINIC:PAGINATION_URLLINK><\/ACTINIC:PAGINATION_URLLINK>/$sLink/si;
$sPageLabel =~ s/<ACTINIC:PAGINATION_PRODUCTCOUNT><\/ACTINIC:PAGINATION_PRODUCTCOUNT>/$nTotalProducts/si;
$sContinue .= $sPageLabel;
}
if (!defined $::g_InputHash{FILTERPAGE} &&
(1 >= $nMaxPageCount))
{
undef $sContinue;
}
}
}
$ACTINIC::B2B->ClearXML();
$ACTINIC::B2B->SetXML('S_SUMMARY',$sSummary);
$ACTINIC::B2B->SetXML('S_CONTINUE',$sContinue);
ACTINIC::LogData("Search call to ACTINIC::ParseXML", $::DC_SEARCH);
if($gbFilterPageUpdate)
{
eval
{
require ax000001;
};
if ($@)
{
ACTINIC::ReportError($@, ACTINIC::GetPath());
}
my $pXML = new ACTINIC_PXML();
my $pTree;
if (defined $pXML->{_Tags}->{COOKIECHECK})
{
delete $pXML->{_Tags}->{COOKIECHECK};
}
if (defined $pXML->{_Tags}->{NOTINB2B})
{
delete $pXML->{_Tags}->{NOTINB2B};
}
($sHTML, $pTree) = $pXML->Parse($sHTML);
}
else
{
$sHTML = ACTINIC::ParseXML($sHTML);
if( !$ACTINIC::B2B->Get('UserDigest') )
{
($status, $sError, $sHTML) = ACTINIC::MakeLinksAbsolute($sHTML, $::g_sWebSiteUrl, $::g_sContentUrl);
}
else
{
my $sBaseFile = $ACTINIC::B2B->Get('BaseFile');
my $smPath = ($sBaseFile) ? $sBaseFile : $::g_sContentUrl;
my $sCgiUrl = $::g_sAccountScript;
$sCgiUrl   .= ($::g_InputHash{SHOP} ? '?SHOP=' . ACTINIC::EncodeText2($::g_InputHash{SHOP}, $::FALSE) . '&' : '?');
$sCgiUrl   .= 'PRODUCTPAGE=';
($status, $sError, $sHTML) = ACTINIC::MakeLinksAbsolute($sHTML, $sCgiUrl, $smPath);
}
}
if ($status != $::SUCCESS)
{
return ($status, $sError);
}
$sHTML =~ s/<ACTINIC:STATIC_RESULTS>(.*?)<\/ACTINIC:STATIC_RESULTS>//si;
$sHTML =~ s/<ACTINIC:SEARCH_RESULT_TEMPLATE>(.*?)<\/ACTINIC:SEARCH_RESULT_TEMPLATE>/<ACTINIC:SEARCH_RESULT_TEMPLATE>$sResultsTemplate<\/ACTINIC:SEARCH_RESULT_TEMPLATE><ACTINIC:STATIC_RESULTS><div id=\"StaticResults\">$1<\/div><\/ACTINIC:STATIC_RESULTS>/si;
if($gbFilterPageUpdate)
{
ACTINIC::LogData("Write .html page from filter", $::DC_SEARCH);
my $sFilterPage = ACTINIC::GetPath().$::g_InputHash{FILTERPAGE};
if (open(FILTER_HTML_PAGE, "+>".$sFilterPage))
{
print FILTER_HTML_PAGE $sHTML;
close(FILTER_HTML_PAGE);
chmod(0666, $sFilterPage);
my $sFilterPageTemp = $sFilterPage.'.Filter';
ACTINIC::LogData("Delete .html.Filter file", $::DC_SEARCH);
ACTINIC::DeleteFile($sFilterPageTemp);
PrintPage("200 OK", "text");
}
else
{
PrintPage("540 Failed to overwrite .html file", "text");
}
return ($::SUCCESS);
}
ACTINIC::LogData("Search call to ACTINIC::SaveSessionAndPrintPage", $::DC_SEARCH);
ACTINIC::SaveSessionAndPrintPage($sHTML, undef, $::FALSE, undef, $::TRUE);
return ($::SUCCESS);
}
sub SearchResultsParser
{
my ($sPath, $sResultMarkup, $rarrResults, $nMin, $nMax, $sSearchStrings, $mapTableProperties, $pmapResultProdRefToMatchingProperties) = @_;
my $rFile = \*PRODUCTINDEX;
my $sFilename = $sPath . "oldprod.fil";
my ($status, $sError) = ACTINIC::InitIndex($sFilename, $rFile, $::g_nSearchIndexVersion);
if ($status != $::SUCCESS)
{
return($status, $sError);
}
my $sScript;
if ($$::g_pSearchSetup{SEARCH_SHOW_HIGHLIGHT})
{
if ($ACTINIC::B2B->Get('UserDigest'))
{
$sScript = sprintf('%s?WD=%s%s&PRODUCTPAGE=',
$::g_sAccountScript,
ACTINIC::EncodeText2($sSearchStrings, $::FALSE),
($::g_InputHash{SHOP} ? "&SHOP=" . ACTINIC::EncodeText2($::g_InputHash{SHOP}, $::FALSE) : ""));
}
else
{
$sScript = sprintf('%s?WD=%s%s&PN=',
$::g_sSearchHighLightScript,
ACTINIC::EncodeText2($sSearchStrings, $::FALSE),
($::g_InputHash{SHOP} ? "&SHOP=" . ACTINIC::EncodeText2($::g_InputHash{SHOP}, $::FALSE) : ""));
}
}
else
{
if ($ACTINIC::B2B->Get('UserDigest'))
{
$sScript = sprintf('%s?WD=%s%s&PRODUCTPAGE=',
$::g_sAccountScript,
ACTINIC::EncodeText2($sSearchStrings, $::FALSE),
($::g_InputHash{SHOP} ? "&SHOP=" . ACTINIC::EncodeText2($::g_InputHash{SHOP}, $::FALSE) : ""));
}
}
$sResultMarkup =~ s/<ACTINIC:S_PRODREF><\/ACTINIC:S_PRODREF>/<Actinic:S_PRODREFUPPER><\/Actinic:S_PRODREFUPPER>/gs; # note! case sensitive match
my ($sDummy, $pTree) = ACTINIC::PreProcessXMLTemplateString($sResultMarkup);
my $pXML = new Element({"_CONTENT" => $pTree});
my $sImageLineHTML 	= ACTINIC_PXML::GetTemplateFragment($pXML, "ImageLine");
my $sFeefoLogoHTML = ACTINIC_PXML::GetTemplateFragment($pXML, "FeefoLogo");
my $nCount;
my $sHTML;
my $sTemp;
my %Product;
my $nListColumnCount = $$mapTableProperties{'ColumnCount'};
my $nListIndex = 0;
$sHTML.= $$mapTableProperties{'StartOfList'};
for ($nCount = $nMin; $nCount < $nMax; $nCount++)
{
if ($nListIndex == 0)
{
$sHTML.= $$mapTableProperties{'StartOfRow'};
}
$nListIndex++;
($status, $sError) = ACTINIC::ProductSearch($$rarrResults[$nCount], $rFile, $sFilename, \%Product);
if ($status == $::FAILURE)
{
ACTINIC::CleanupIndex($rFile);
return($status, $sError);
}
if ($status == $::NOTFOUND)
{
ACTINIC::CleanupIndex($rFile);
return($status, ACTINIC::GetPhrase(-1, 263));
}
$ACTINIC::B2B->SetXML('S_ITEM', ($nCount + 1));
my $sImage;
my $sImageFileName = "";
if (length $Product{IMAGE} > 0)
{
$sImageFileName = $Product{IMAGE};
}
else
{
$sImageFileName = ACTINIC::IsCustomVarDefined( 'DefaultProductImage' );
}
if ($$::g_pSearchSetup{SEARCH_DISPLAYS_IMAGE} && 
$sImageFileName ne '')
{
my %hVarTable;
$hVarTable{"NETQUOTEVAR:THUMBNAIL"} = $sImageFileName;
if ($$::g_pSetupBlob{SEARCH_USE_THUMBNAIL})
{
my $sWidth  = $$::g_pSetupBlob{SEARCH_THUMBNAIL_WIDTH}  == 0 ? "" : sprintf("width=%d ",  $$::g_pSetupBlob{SEARCH_THUMBNAIL_WIDTH});
my $sHeight = $$::g_pSetupBlob{SEARCH_THUMBNAIL_HEIGHT} == 0 ? "" : sprintf("height=%d ", $$::g_pSetupBlob{SEARCH_THUMBNAIL_HEIGHT});
$hVarTable{"NETQUOTEVAR:THUMBNAILSIZE"} = $sWidth . $sHeight;
}
($status, $sError, $sImage) = ACTINIC::TemplateString($sImageLineHTML, \%hVarTable);
if ($status != $::SUCCESS)
{
ACTINIC::CleanupIndex($rFile);
return($status, $sTemp);
}
}
$ACTINIC::B2B->SetXML('ImageLine', $sImage);
$ACTINIC::B2B->SetXML('S_PRODREF', $$rarrResults[$nCount]);
$ACTINIC::B2B->SetXML('FeefoLogo',decode_entities($sFeefoLogoHTML));
$ACTINIC::B2B->SetXML('S_PRODREFUPPER', uc($$rarrResults[$nCount]));
if ($$::g_pSearchSetup{SEARCH_SHOW_HIGHLIGHT} &&
$sSearchStrings)
{
my ($sFileName, $sAnchor) = split('#', $Product{ANCHOR});
if ($sAnchor)
{
$sAnchor = '#' . $sAnchor;
}
$ACTINIC::B2B->SetXML('S_LINK', sprintf('<a href="%s">', $sScript . ACTINIC::EncodeText2($sFileName, $::FALSE) . $sAnchor));
}
else
{
$ACTINIC::B2B->SetXML('S_LINK', sprintf('<a href="%s">', $Product{ANCHOR}));
}
$sTemp = "";
if ($$::g_pSearchSetup{SEARCH_SHOW_NAME})
{
($status, $sTemp) = ACTINIC::ProcessEscapableText($Product{NAME});
if ($status != $::SUCCESS)
{
ACTINIC::CleanupIndex($rFile);
return($status, $sTemp);
}
}
else
{
$sTemp = ACTINIC::GetPhrase(-1, 278);
}
$ACTINIC::B2B->SetXML('S_PNAME', $sTemp);
$sTemp = "";
if ($$::g_pSearchSetup{SEARCH_SHOW_SECTION})
{
($status, $sTemp) = ACTINIC::ProcessEscapableText($Product{SECTION});
if ($status != $::SUCCESS)
{
ACTINIC::CleanupIndex($rFile);
return($status, $sTemp);
}
$sTemp = "($sTemp)";
}
$ACTINIC::B2B->SetXML('S_SNAME', $sTemp);
$sTemp = "";
$sTemp = $Product{SID};
$ACTINIC::B2B->SetXML('S_SID', $sTemp);
$sTemp = "";
if ($$::g_pSearchSetup{SEARCH_SHOW_DESCRIPTION})
{
($status, $sTemp) = ACTINIC::ProcessEscapableText($Product{DESCRIPTION});
if ($status != $::SUCCESS)
{
ACTINIC::CleanupIndex($rFile);
return($status, $sTemp);
}
}
$ACTINIC::B2B->SetXML('S_DESCR', $sTemp);
$sTemp = "";
if ($$::g_pSearchSetup{SEARCH_SHOW_PRICE} &&
$$::g_pSetupBlob{PRICES_DISPLAYED} &&
$Product{PRICE} != 0)
{
($status, $sError, $sTemp) = ActinicOrder::FormatPrice($Product{PRICE}, $::TRUE, $::g_pCatalogBlob);
if ($status != $::SUCCESS)
{
ACTINIC::CleanupIndex($rFile);
return($status, $sError);
}
}
$ACTINIC::B2B->SetXML('S_PRICE', $sTemp);
$ACTINIC::B2B->SetXML('S_PRAWPRICE', $Product{PRICE});
$ACTINIC::B2B->SetXML('S_STOCK', $Product{STOCKLEVEL});
$sTemp = "";
if ($$::g_pSearchSetup{SEARCH_SHOW_PROPERTY} && # does the user want it? and
exists $$pmapResultProdRefToMatchingProperties{$rarrResults->[$nCount]})
{
my $sLine;
foreach $sLine (@{$$pmapResultProdRefToMatchingProperties{$rarrResults->[$nCount]}})
{
$sTemp .= $sLine;
}
}
$ACTINIC::B2B->SetXML('S_PROP', $sTemp);
my $sProductInfo = ACTINIC::ParseXML($sResultMarkup);
$sProductInfo = UpdateUDPVariableTemplates($sProductInfo, %Product);
$sHTML .= $$mapTableProperties{'StartOfCell'}.$sProductInfo.$$mapTableProperties{'EndOfCell'};
if ($nListIndex == $nListColumnCount)
{
$sHTML.= $$mapTableProperties{'EndOfRow'};
$nListIndex = 0;
}
}
if (($nListIndex > 0) &&
($nListIndex < $nListColumnCount))
{
$sHTML.= $$mapTableProperties{'EndOfRow'};
}
$sHTML.= $$mapTableProperties{'EndOfList'};
ACTINIC::CleanupIndex($rFile);
return ($::SUCCESS, undef, $sHTML);
}
sub DirectLinkToProduct
{
my ($sPath, $sProdRef) = @_;
if ($::g_InputHash{SID})
{
my @arrResponse = ACTINIC::GetSectionBlobName($::g_InputHash{SID});
if ($arrResponse[0] == $::SUCCESS)
{
my $sSectionBlobName = $arrResponse[2];
@arrResponse = ACTINIC::GetSectionHash($sSectionBlobName);
if ($arrResponse[0] == $::SUCCESS)
{
my $rhSection = $arrResponse[2];
@arrResponse = ACTINIC::GetProduct($sProdRef, $sSectionBlobName, ACTINIC::GetPath());
my $rhProduct = $arrResponse[2];
if ($arrResponse[0] == $::SUCCESS)
{
return (DisplayDirectLinkPage($rhSection->{'PAGE'}, $::FALSE, $sProdRef));
}
}
}
SearchError($arrResponse[1]);
exit;
}
my %Product;
my $rFile = \*PRODUCTINDEX;
my $sFilename = $sPath . "oldprod.fil";
my ($status, $sError) = ACTINIC::InitIndex($sFilename, $rFile, $::g_nSearchIndexVersion);
if ($status != $::SUCCESS)
{
ACTINIC::TerminalError($sError);
}
($status, $sError) = ACTINIC::ProductSearch($sProdRef, $rFile, $sFilename, \%Product);
if ($status == $::FAILURE)
{
ACTINIC::CleanupIndex($rFile);
SearchError($sError);
exit;
}
if ($status == $::NOTFOUND)
{
ACTINIC::CleanupIndex($rFile);
my ($status, $sError, $sHTML) = ACTINIC::BounceToPageEnhanced(5, ACTINIC::GetPhrase(-1, 1962) . ACTINIC::GetPhrase(-1, 1965, ACTINIC::HTMLEncode($sProdRef)) . ACTINIC::GetPhrase(-1, 1970) . ACTINIC::GetPhrase(-1, 2048),
'', $::g_sWebSiteUrl, $::g_sContentUrl,
$::g_pSetupBlob, ACTINIC::GetReferrer(), \%::g_InputHash, $::FALSE);
return($sHTML);
}
my $sLink = $Product{ANCHOR};
ACTINIC::CleanupIndex($rFile);
return(DisplayDirectLinkPage($sLink, $::FALSE, $sProdRef));
}
sub DisplayDirectLinkPage
{
my $sLink		= shift;
my $bClearFrames = shift;
my $sProdRef	= shift;
my $sBaseFile = $ACTINIC::B2B->Get('BaseFile');
my $sReferrer = ACTINIC::GetReferrer();
my $sCgiUrl = $::g_sAccountScript;
$sCgiUrl   .= ($::g_InputHash{SHOP} ? '?SHOP=' . ACTINIC::EncodeText2($::g_InputHash{SHOP}, $::FALSE) . '&' : '?');
$sReferrer = $::Session->GetBaseUrl();
if ($ACTINIC::B2B->Get('UserDigest'))
{
$sLink =~ /([^\#]*)(.*)/;
my $sAnchor = $2;
$sLink = !$bClearFrames || $::g_InputHash{NOCLEARFRAMES} ||
!$$::g_pSetupBlob{USE_FRAMES} ?
$sCgiUrl . "PRODUCTPAGE=" . ACTINIC::EncodeText2($sLink, $::FALSE) :
$sCgiUrl . "MAINFRAMEURL=" . ACTINIC::EncodeText2($sLink, $::FALSE);
if ($sProdRef)
{
$sLink .= "&PRODUCTREF=" . $sProdRef;
}
if ($sAnchor)
{
$sLink .= $sAnchor;
}
}
else
{
if ($$::g_pSetupBlob{B2B_MODE} &&
!$::g_InputHash{NOLOGIN})
{
my @Response = ACTINIC::TemplateFile(ACTINIC::GetPath() . $$::g_pSetupBlob{B2B_LOGONPAGE});
if ($Response[0] != $::SUCCESS)
{
ACTINIC::TerminalError($Response[1]);
}
$sLink =~ /([^\#]*)(.*)/;
my $sAnchor = $2;
my $sReplace = $$::g_pSetupBlob{USE_FRAMES} ? "<INPUT TYPE=HIDDEN NAME=MAINFRAMEURL VALUE=\"".  $sLink . "\">" :
"<INPUT TYPE=HIDDEN NAME=PRODUCTPAGE VALUE=\"". $sLink . "\">";
if ($::g_InputHash{TARGET} eq "BROCHURE")
{
$sReplace = "<INPUT TYPE=HIDDEN NAME=BROCHUREMAINFRAMEURL VALUE=\"".  $sLink . "\">";
}
if ($sProdRef)
{
$sReplace .= "<INPUT TYPE=HIDDEN NAME=PRODUCTREF VALUE=\"". $sProdRef . "\">";
}
$sReplace .= "<INPUT TYPE=HIDDEN NAME=\"ACTINIC_REFERRER\" VALUE=\"$sReferrer\">";
$Response[2] =~ s/<FORM([^>]+ACTION\s*?=\s*?["'])\s*?(.*?$::g_sAccountScriptName)\s*?(["'][^>]*?>)/<FORM$1$2$sAnchor$3$sReplace/gi; #'
if ($sProdRef)
{
if (ACTINIC::IsPriceScheduleConstrained($ActinicOrder::RETAILID) &&
!ACTINIC::IsProductVisible($sProdRef, $ActinicOrder::RETAILID))
{
$ACTINIC::B2B->SetXML('PRODUCTNOTAVAILABLE', ACTINIC::GetPhrase(-1, 2176));# add the 'Product is not available for retail' warning to the page
}
}
my $sSearch = $$::g_pSetupBlob{USE_FRAMES} ? $$::g_pSetupBlob{FRAMESET_PAGE} : $$::g_pSetupBlob{CATALOG_PAGE};
$sReplace = !$$::g_pSetupBlob{USE_FRAMES} || $::g_InputHash{TARGET} eq "BROCHURE" ? $sLink :
$sCgiUrl . "ACTION=DIRECTLINK&MAINFRAMEURL=" . ACTINIC::EncodeText2($::g_sContentUrl . $sLink, $::FALSE) .
"&ACTINIC_REFERRER=" . ACTINIC::EncodeText2($sReferrer , $::FALSE);
$Response[2] =~ s/(<A[^>]*?HREF\s?=\s?["'][^"']*?SECTIONID=)$sSearch([^"']*?["']\s?>)/$1$sReplace$2/gi; #'
if ($$::g_pSetupBlob{USE_SSL} &&
($$::g_pSetupBlob{SSL_USEAGE} == 1))
{
my $sParams = sprintf("&SESSIONID=%s&DIGEST=%s",
ACTINIC::EncodeText2($::Session->GetSessionID(), $::FALSE),
ACTINIC::CAccBusinessCookie());
if ($sProdRef)
{
$sReplace = sprintf("%s?PRODREF=%s%s", $::g_sSSLSearchScript, $sProdRef, $sParams);
}
else
{
$sReplace = sprintf("%s?SECTIONID=%s%s", $::g_sSSLSearchScript, $sLink, $sParams);
}
$Response[2] =~ s/NETQUOTEVAR:SSLREDIRECT/$sReplace/;
}
return($Response[2]);
}
else
{
if (($sLink eq $$::g_pSetupBlob{CATALOG_PAGE}) &&
($$::g_pSetupBlob{USE_FRAMES}))
{
$sLink = $$::g_pSetupBlob{FRAMESET_PAGE};
}
$sLink = $::g_sContentUrl . $sLink;
}
}
my @Response = ACTINIC::BounceToPagePlain(0, undef, undef, $::g_sWebSiteUrl,
$::g_sContentUrl, $::g_pSetupBlob, $sLink, \%::g_InputHash);
if ($Response[0] != $::SUCCESS)
{
ACTINIC::ReportError($Response[1], ACTINIC::GetPath());
}
return($Response[2]);
}
sub PrintPage
{
my ($sHTML, $sType) = @_;
binmode STDOUT;
my $nLength = length $sHTML;
if($ENV{'PerlXS'} eq 'PerlIS')
{
print "HTTP/1.0 200 OK\n";
}
print "Content-type: $sType\r\n";
print "Content-length: $nLength\r\n";
print "\r\n";
print $sHTML;
}
sub UpdateUDPVariableTemplates
{
my ($sResultTemplate, %Product) = @_;
my $sUDPVarValues;
if ($Product{UPLOADUDPS})
{
my @arrUDPs = split (',', $Product{UPLOADUDPS});
foreach $sUDPVarValues (@arrUDPs)
{
my ($sUDPVar, $sUDPValue) = $sUDPVarValues =~ /(.*)\|(.*)/;
my $sVariableTemplate = '<actinic:template name=\"' . $sUDPVar . '\"><\/actinic:template>';
$sResultTemplate =~ s/$sVariableTemplate/$sUDPValue/gi;
}
}
return ($sResultTemplate);
}
sub ParseFilterDefaultInputs
{
my ($sFilename) = @_;
my %hFilterInput;
my $sOriginalData;
unless (open (TFFILE, "<$sFilename"))
{
return ($::FAILURE, ACTINIC::GetPhrase(-1, 21, $sFilename, $!));
}
my ($sHTML);
{
local $/;
$sHTML = <TFFILE>;
}
close (TFFILE);
my $sParamValues;
my ($sFilterInputs) = $sHTML =~ /<Actinic:FILTER_INPUT style=\"display:none;\">(.*)<\/Actinic:FILTER_INPUT>/;
if ($sFilterInputs eq '')
{
return ($::FAILURE, "No filter default input defined.");
}
my @arrParams = split(',', $sFilterInputs);
my $nCount = 0;
foreach $sParamValues (@arrParams)
{
my ($sParam, $sValue) = $sParamValues =~ /(.*)\!(.*)/;
$hFilterInput{$sParam} = $sValue;
if ($nCount != 0)
{
$sOriginalData .= '&';
}
$sOriginalData .= $sParam . '=' . $sValue;
$nCount++;
}
return ($::SUCCESS, '', $sOriginalData, '', %hFilterInput)
}
sub GetFilterProductListJSON
{
my (%rhashResults) = @_;
my $nResultCount = scalar (keys %$rhashResults);
ACTINIC::LogData("Dynamic Search Result Count : $nResultCount", $::DC_SEARCH);
my $sResults = "[]";
if ($nResultCount > 0)
{	
my $sProductRef;
my @arraySearchResults;
foreach $sProductRef (keys %$rhashResults)
{
push @arraySearchResults, (int($rhashResults->{$sProductRef} + 0.5) . ':' . $sProductRef);
}
$sResults = join ('","', @arraySearchResults);
$sResults = '["' . $sResults . '"]';
ACTINIC::LogData("Dynamic Search Results : $sResults", $::DC_SEARCH);
}
my $sFinalResult = '{"ProductSearchResults": { "ResultCount":' . $nResultCount .', "ResultSet": '.$sResults .' } }';
return ($sFinalResult);
}