Sample Search Spring Data Feed
<mvt:comment>
GLOBAL Setup
| 1) File Settings
| 2) Initial File Handling
| - Set Offset / Per Page Variables
| - Delete Existing File (if EXISTS)
| 3) Special Character Reference Variables
========================================
</mvt:comment>
<mvt:comment> =1 File Settings </mvt:comment>
<mvt:assign name="g.File_Path" value="'/searchspring/'" />
<mvt:assign name="g.File_Name" value="'custom.txt'" />
<mvt:comment> =2 Initial File Handling </mvt:comment>
<mvt:if expr="ISNULL g.Per_Page">
<mvt:assign name="g.Per_Page" value="100" />
</mvt:if>
<mvt:if expr="ISNULL g.AllOffset OR g.AllOffset EQ '@offset'">
<mvt:assign name="g.AllOffset" value="0" />
</mvt:if>
<mvt:if expr="g.AllOffset LT g.Per_Page AND g.debug NE 1">
<mvt:assign name="l.empty" value="''" />
<mvt:assign name="l.file_exists" value="sexists( g.File_Path $ g.File_Name )" />
<mvt:if expr="l.file_exists EQ 1">
<mvt:assign name="l.file_deleted" value="sdelete( g.File_Path $ g.File_Name )" />
<mvt:if expr="l.file_deleted EQ 1">
<mvt:assign name="l.file_created" value="file_create( g.File_Path $ g.File_Name, 'script', l.empty )" />
</mvt:if>
<mvt:else>
<mvt:assign name="l.file_created" value="file_create( g.File_Path $ g.File_Name, 'script', l.empty )" />
</mvt:if>
</mvt:if>
<mvt:comment> =3 Special Character Reference Variables </mvt:comment>
<mvt:assign name="l.delimiter" value="asciichar( 9 )" />
<mvt:assign name="l.break" value="asciichar( 10 )" />
<mvt:assign name="l.double_quote" value="asciichar( 34 )" />
<mvt:assign name="l.comma" value="asciichar( 44 )" />
<mvt:comment>================================================================================</mvt:comment>
<mvt:comment>
Header Row
| 1) Define the CSV Header Fields
| - Loop through Custom Fields to Dynamically Generate Header Row
| 2) Write Header Row to File
| - Check if First Offset ... Write Header Row
========================================
</mvt:comment>
<mvt:comment> =1 Define the CSV Header Fields </mvt:comment>
<mvt:assign name="g.Header_Row" value="
'product_id' $ l.delimiter $
'code' $ l.delimiter $
'productsku' $ l.delimiter $
'name' $ l.delimiter $
'product_url' $ l.delimiter $
'add_url' $ l.delimiter $
'catcodes' $ l.delimiter $
'categories' $ l.delimiter $
'parent_catcodes' $ l.delimiter $
'price' $ l.delimiter $
'description' $ l.delimiter $
'salesrank' $ l.delimiter $
'reviews' $ l.delimiter $
'rating'
" />
<mvt:foreach iterator="field_custom" array="all_products:fields_custom">
<mvt:assign name="g.Header_Row" value="g.Header_Row $ l.delimiter $ l.settings:field_custom:code" />
</mvt:foreach>
<mvt:assign name="g.Header_Row" value="g.Header_Row $ l.break" />
<mvt:comment> =2 Write `g.Header_Row` to File </mvt:comment>
<mvt:if expr="g.AllOffset LT g.Per_Page AND g.debug NE 1">
<mvt:assign name="l.write_line" value="file_append( g.File_Path $ g.File_Name, 'script', g.Header_Row )" />
</mvt:if>
<mvt:comment>================================================================================</mvt:comment>
<mvt:comment>
All Products
========================================
</mvt:comment>
<mvt:foreach iterator="product" array="all_products:products">
<mvt:comment>Start if Search Spring Omit </mvt:comment>
<mvt:item name="customfields" param="Read_Product_Code( l.settings:product:code, 'omit_from_ss', l.settings:omit_ss )" />
<mvt:if expr="'Yes' CIN l.settings:omit_ss">
<mvt:comment>Omit Product from Search Spring Feed</mvt:comment>
<mvt:else>
<mvt:comment>
Reset Key Variables
| Null-out variables for the next Iteration
========================================
</mvt:comment>
<mvt:assign name="l.parts" value="NULL" />
<mvt:assign name="l.settings:category" value="NULL" />
<mvt:assign name="l.settings:assigned_categories" value="NULL" />
<mvt:assign name="l.settings:master_product" value="NULL" />
<mvt:assign name="l.settings:has_variants" value="NULL" />
<mvt:assign name="g.master_customfield_value" value="NULL" />
<mvt:assign name="l.value" value="NULL" />
<mvt:assign name="g.sql" value="NULL" />
<mvt:assign name="g.Row" value="NULL" />
<mvt:assign name="g.Line" value="NULL" />
<mvt:assign name="l.settings:variant_product_ids" value="NULL" />
<mvt:assign name="l.settings:variant_product_id" value="NULL" />
<mvt:assign name="l.settings:gd_ratings" value="NULL" />
<mvt:assign name="l.imagetypes" value="NULL" />
<mvt:comment> Set Fallback Image </mvt:comment>
<mvt:assign name="l.settings:product:fallback_image" value="'../images/img_no_thumb.png'" />
<mvt:comment> Check if Product is a Variant </mvt:comment>
<mvt:do file="g.Module_Library_DB" name="l.success" value="ProductVariantPartList_Load_Part( l.settings:product:id, l.parts )" />
<mvt:if expr="miva_array_elements( l.parts ) GT 0">
<mvt:comment> Load Variant's Master Product </mvt:comment>
<mvt:do file="g.Module_Library_DB" name="l.success" value="Product_Load_ID( l.parts[1]:product_id, l.settings:master_product )" />
<mvt:comment> ==== Check if Master Product is Inactive ==== </mvt:comment>
<mvt:if expr="l.settings:master_product:active EQ 0">
<mvt:foreachcontinue />
</mvt:if>
<mvt:comment>
Master Product Variable Modifications
| 1) Generate Master Product's URL w/ Variant ID
| 2) Generate Master Product's "Add to Cart" URL
| 3) Read Master Product's Category Codes
| - Remove Trailing Comma
| 4) Read Master Product's Custom Fields
| 5) Read Master Product's Description
| 6) Read Master's Sales Rank
| 7) Read Master's Reviews and Ratings
========================================
</mvt:comment>
<mvt:comment> =1 Generate Master Product URL w/ Variant ID </mvt:comment>
<mvt:do file="g.Module_Feature_URI_UT" name="l.settings:product:product_url" value="Store_Product_URL(l.settings:master_product, NULL)" />
<mvt:if expr="'?' IN l.settings:product:product_url">
<mvt:assign name="l.settings:product:product_url" value="l.settings:product:product_url $ '&v=' $ l.parts[1]:variant_id " />
<mvt:else>
<mvt:assign name="l.settings:product:product_url" value="l.settings:product:product_url $ '?v=' $ l.parts[1]:variant_id " />
</mvt:if>
<mvt:comment> =2 Generate Master Product "Add to Cart" URL </mvt:comment>
<mvt:item name="product_attributes" param="master_product:id" />
<mvt:assign name="l.settings:product:add_url" value="l.settings:urls:BASK:auto_sep $ 'Action=ADPR&Quantity=1&Store_Code=' $ g.store:code $ '&Product_Code=' $ l.settings:master_product:code " />
<mvt:foreach iterator="attribute" array="attributes">
<mvt:foreach iterator="option" array="attribute:options">
<mvt:do file="g.Module_Library_DB" name="l.success" value="ProductIDList_Load_Product_Option( l.settings:option:product_id, l.settings:option:attr_id, l.settings:option:attmpat_id, l.settings:option:id, l.settings:variant_product_ids )" />
<mvt:foreach iterator="variant_product_id" array="variant_product_ids">
<mvt:if expr="l.settings:variant_product_id EQ l.settings:product:id">
<mvt:assign name="l.settings:product:add_url" value="l.settings:product:add_url $ '&Product_Attributes[' $ l.pos2 $ ']:code=' $ l.settings:attribute:code $ '&Product_Attributes[' $ l.pos2 $ ']:value=' $ l.settings:option:code" />
</mvt:if>
</mvt:foreach>
</mvt:foreach>
</mvt:foreach>
<mvt:comment> =3 Read Master Product Category Codes </mvt:comment>
<mvt:do file="g.Module_Library_DB" name="l.success" value="CategoryList_Load_Offset_Product_Assigned( l.settings:master_product:id, 0, '', '', 0, l.null, l.settings:assigned_categories )" />
<mvt:foreach iterator="category" array="assigned_categories">
<mvt:if expr="l.settings:category:active GT 0">
<mvt:assign name="l.settings:product:catcodes" value="l.settings:product:catcodes $ l.settings:category:code $ l.comma" />
<mvt:assign name="l.settings:product:categories" value="l.settings:product:categories $ l.settings:category:name $ l.comma" />
<mvt:comment> Load Parent Category </mvt:comment>
<mvt:if expr="l.settings:category:validated_parent_id GT 0">
<mvt:do file="g.Module_Library_DB" name="l.success" value="Category_Load_ID( l.settings:category:validated_parent_id, l.parent_category )" />
<mvt:assign name="l.settings:product:parent_catcodes" value="l.settings:product:parent_catcodes $ l.parent_category:code $ l.comma" />
</mvt:if>
</mvt:if>
</mvt:foreach>
<mvt:assign name="l.settings:product:catcodes" value="substring( l.settings:product:catcodes, 1, (len( l.settings:product:catcodes ) -1) )" />
<mvt:assign name="l.settings:product:categories" value="substring( l.settings:product:categories, 1, (len( l.settings:product:categories ) -1) )" />
<mvt:assign name="l.settings:product:parent_catcodes" value="substring( l.settings:product:parent_catcodes, 1, (len( l.settings:product:parent_catcodes ) -1) )" />
<mvt:comment> =4 Read Master's Custom Fields </mvt:comment>
<mvt:assign name="l.serialized" value="miva_array_serialize( l.settings:product:customfield_values )" />
<mvt:foreach iterator="field_custom" array="all_products:fields_custom">
<mvt:if expr="l.settings:field_custom:module EQ 'productimagecustomfields'">
<mvt:if expr="ISNULL miva_variable_value( 'l.settings:product:imagetypes:' $ l.settings:field_custom:code )">
<mvt:assign name="l.null" value="miva_array_insert_var( l.imagetypes, l.settings:field_custom:code, -1 )" />
<mvt:do file="g.Module_Feature_TUI_UT" name="l.index" value="CommonComponentFields_Initialize_Product_ImageTypes( l.settings:master_product:id, 0, l.settings:product, l.all_settings, l.imagetypes, 'B', l.settings:all_products:b_width, l.settings:all_products:b_height)" />
</mvt:if>
<mvt:else>
<mvt:if expr="ISNULL miva_variable_value( 'l.settings:product:customfield_values:' $ l.settings:field_custom:module $ ':' $ l.settings:field_custom:code )">
<mvt:item name="customfields" param="Read_Product_ID( l.settings:master_product:id, l.settings:field_custom:code, g.master_customfield_value )" />
<mvt:if expr="NOT ISNULL g.master_customfield_value">
<mvt:assign name="l.serialized" value="l.serialized $ ',:' $ l.settings:field_custom:module $ ':' $ l.settings:field_custom:code $ '=' $ encodeattribute( g.master_customfield_value )" />
</mvt:if>
<mvt:comment><mvt:assign name="l.serialized" value="l.serialized $ ',:' $ l.settings:field_custom:module $ ':' $ l.settings:field_custom:code $ '=' $ g.master_customfield_value" /></mvt:comment>
</mvt:if>
</mvt:if>
</mvt:foreach>
<mvt:if expr="g.debug EQ 1">
<textarea><mvt:eval expr="l.serialized" /></textarea>
</mvt:if>
<mvt:assign name="l.settings:product:customfield_values" value="miva_array_deserialize( l.serialized )" />
<mvt:if expr="g.debug EQ 1">
<textarea>
&mvt:master_product:name; ||| &mvt:product:name;
================================================
<mvt:assign name="g.mvt_debug" value="miva_array_serialize( l.settings:product )" />
&mvt:global:mvt_debug;
</textarea><br>
</mvt:if>
<mvt:comment> =5 Read Master's Description </mvt:comment>
<mvt:if expr="ISNULL l.settings:product:descrip">
<mvt:assign name="l.settings:product:descrip" value="l.settings:master_product:descrip" />
</mvt:if>
<mvt:comment> =6 Read Master's Sales Rank </mvt:comment>
<mvt:do file="g.Module_Feature_STA_DB" name="l.success" value="ProdStats_Load_Product( l.settings:master_product:id, l.settings:product:stats )" />
<mvt:comment> =7 Read Master's Reviews / Rating </mvt:comment>
<mvt:item name="ry_toolbelt" param="assign|g.sql|'SELECT total, rating FROM s01_GD_Ratings_Product_Review_Aggregates WHERE product_id = `' $ MySqlEscape(l.all_settings:master_product:id) $ '`'" />
<mvt:item name="ry_toolbelt" param="query|g.sql|gd_ratings" />
<mvt:if expr="miva_array_elements(l.settings:gd_ratings) GT 0">
<mvt:assign name="l.settings:product:gd_ratings:total" value="l.settings:gd_ratings[1]:total" />
<mvt:assign name="l.settings:product:gd_ratings:rating" value="l.settings:gd_ratings[1]:rating" />
</mvt:if>
<mvt:else>
<mvt:comment> Check if (Master)Product Has Variants </mvt:comment>
<mvt:item name="ry_toolbelt" param="assign|g.sql|'SELECT DISTINCT(variant_id) FROM s01_ProductVariants WHERE product_id = `' $ MySqlEscape(l.all_settings:product:id) $ '`'" />
<mvt:item name="ry_toolbelt" param="query|g.sql|has_variants" />
<mvt:if expr="miva_array_elements( l.settings:has_variants ) GT 0">
<mvt:foreachcontinue />
</mvt:if>
<mvt:comment>
Variable Modifications
| 1) Re-Map `:link` Variable to `:product_url` For Consistancy
| 2) Generate "Add to Cart" URL
| 3) Read Category Codes
| 4) Read Sales Rank
| 5) Read Reviews and Ratings
========================================
</mvt:comment>
<mvt:comment> =1 Re-Map `:link` Variable to `:product_url` For Consistancy </mvt:comment>
<mvt:assign name="l.settings:product:product_url" value="l.settings:product:link" />
<mvt:comment> =2 Generate "Add to Cart" URL </mvt:comment>
<mvt:assign name="l.settings:product:add_url" value="l.settings:urls:BASK:auto_sep $ 'Action=ADPR&Quantity=1&Store_Code=' $ g.store:code $ '&Product_Code=' $ l.settings:product:code" />
<mvt:comment> =3 Read Category Codes </mvt:comment>
<mvt:do file="g.Module_Library_DB" name="l.success" value="CategoryList_Load_Offset_Product_Assigned( l.settings:product:id, 0, '', '', 0, l.null, l.settings:assigned_categories )" />
<mvt:foreach iterator="category" array="assigned_categories">
<mvt:if expr="l.settings:category:active GT 0">
<mvt:assign name="l.settings:product:catcodes" value="l.settings:product:catcodes $ l.settings:category:code $ l.comma" />
<mvt:assign name="l.settings:product:categories" value="l.settings:product:categories $ l.settings:category:name $ l.comma" />
<mvt:comment> Load Parent Category </mvt:comment>
<mvt:if expr="l.settings:category:validated_parent_id GT 0">
<mvt:do file="g.Module_Library_DB" name="l.success" value="Category_Load_ID( l.settings:category:validated_parent_id, l.parent_category )" />
<mvt:assign name="l.settings:product:parent_catcodes" value="l.settings:product:parent_catcodes $ l.parent_category:code $ l.comma" />
</mvt:if>
</mvt:if>
</mvt:foreach>
<mvt:assign name="l.settings:product:catcodes" value="substring( l.settings:product:catcodes, 1, (len( l.settings:product:catcodes ) -1) )" />
<mvt:assign name="l.settings:product:categories" value="substring( l.settings:product:categories, 1, (len( l.settings:product:categories ) -1) )" />
<mvt:assign name="l.settings:product:parent_catcodes" value="substring( l.settings:product:parent_catcodes, 1, (len( l.settings:product:parent_catcodes ) -1) )" />
<mvt:comment> =4 Read Sales Rank </mvt:comment>
<mvt:do file="g.Module_Feature_STA_DB" name="l.success" value="ProdStats_Load_Product( l.settings:product:id, l.settings:product:stats )" />
<mvt:comment> =5 Read Reviews and Rating </mvt:comment>
<mvt:item name="ry_toolbelt" param="assign|g.sql|'SELECT total, rating FROM s01_GD_Ratings_Product_Review_Aggregates WHERE product_id = `' $ MySqlEscape(l.all_settings:product:id) $ '`'" />
<mvt:item name="ry_toolbelt" param="query|g.sql|gd_ratings" />
<mvt:if expr="miva_array_elements(l.settings:gd_ratings) GT 0">
<mvt:assign name="l.settings:product:gd_ratings:total" value="l.settings:gd_ratings[1]:total" />
<mvt:assign name="l.settings:product:gd_ratings:rating" value="l.settings:gd_ratings[1]:rating" />
</mvt:if>
</mvt:if>
<mvt:comment>
Output Product Variables
| After Variant Modification... Generate CSV File Row
| - Loop through Custom Fields to Dynamically Generate Row
========================================
</mvt:comment>
<mvt:assign name="g.Row" value="
l.double_quote $ l.settings:product:id $ l.double_quote $ l.delimiter $
l.double_quote $ l.settings:product:code $ l.double_quote $ l.delimiter $
l.double_quote $ l.settings:product:sku $ l.double_quote $ l.delimiter $
l.double_quote $ l.settings:product:name $ l.double_quote $ l.delimiter $
l.double_quote $ l.settings:product:product_url $ l.double_quote $ l.delimiter $
l.double_quote $ l.settings:product:add_url $ l.double_quote $ l.delimiter $
l.double_quote $ l.settings:product:catcodes $ l.double_quote $ l.delimiter $
l.double_quote $ l.settings:product:categories $ l.double_quote $ l.delimiter $
l.double_quote $ l.settings:product:parent_catcodes $ l.double_quote $ l.delimiter $
l.double_quote $ l.settings:product:price $ l.double_quote $ l.delimiter $
l.double_quote $ glosub( l.settings:product:descrip, l.double_quote, l.double_quote $ l.double_quote ) $ l.double_quote $ l.delimiter $
l.double_quote $ l.settings:product:stats:counter $ l.double_quote $ l.delimiter $
l.double_quote $ l.settings:product:gd_ratings:total $ l.double_quote $ l.delimiter $
l.double_quote $ l.settings:product:gd_ratings:rating $ l.double_quote
" />
<mvt:foreach iterator="field_custom" array="all_products:fields_custom">
<mvt:if expr="l.settings:field_custom:module EQ 'productimagecustomfields'">
<mvt:assign name="l.value" value="'l.settings:product:imagetypes:' $ l.settings:field_custom:code" />
<mvt:if expr="len(miva_variable_value( l.value )) EQ 0">
<mvt:assign name="l.value" value="'l.settings:product:fallback_image'" />
</mvt:if>
<mvt:else>
<mvt:assign name="l.value" value="'l.settings:product:customfield_values:' $ l.settings:field_custom:module $ ':' $ l.settings:field_custom:code" />
</mvt:if>
<mvt:assign name="g.Row" value="g.Row $ l.delimiter $ l.double_quote $ glosub( miva_variable_value( l.value ), l.double_quote, l.double_quote $ l.double_quote ) $ l.double_quote" />
</mvt:foreach>
<mvt:assign name="g.Row" value="g.Row $ l.break" />
<mvt:comment> Write Line to File </mvt:comment>
<mvt:if expr="g.debug NE 1">
<mvt:assign name="l.write_line" value="file_append( g.File_Path $ g.File_Name, 'script', g.Row )" />
</mvt:if>
</mvt:if>
<mvt:comment>/End if Search Spring Omit </mvt:comment>
</mvt:foreach>
<mvt:comment>================================================================================</mvt:comment>
<mvt:comment> Output SearchSpring Reponse String </mvt:comment>
<mvt:if expr="g.AllNextOffset GT 0">
<mvt:assign name="g.next" value="l.settings:urls:_self:auto_sep $ 'AllOffset=' $ g.AllNextOffset $ '&continue=' $ g.continue $ '&file_name=' $ g.File_Name $ '&debug=' $ g.debug" />
<mvt:if expr="g.debug EQ 1">
<a href="&mvt:global:next;">NEXT</a>
<mvt:elseif expr="g.continue EQ 'redirect'">
<mvt:assign name="l.header" value="miva_output_header( 'Status', '301 Moved Permanently' )" />
<mvt:assign name="l.header" value="miva_output_header( 'Location', g.next )" />
<mvt:elseif expr="g.continue EQ 'refresh'">
<meta http-equiv="refresh" content="0; URL='&mvt:global:next;'" />
<mvt:elseif expr="g.continue EQ 'js'">
<script> window.location = '&mvt:global:next;'; </script>
</mvt:if>
Continue|&mvt:global:AllNextOffset;
<mvt:else>
Complete
</mvt:if>