Skip to content

Commit

Permalink
Merge pull request #1052 from searchspring/develop
Browse files Browse the repository at this point in the history
Release v0.56.2
  • Loading branch information
korgon authored May 23, 2024
2 parents 119ff8b + f16f454 commit 0d9be6a
Show file tree
Hide file tree
Showing 6 changed files with 382 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/patchGenerate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ jobs:
- name: Create PR
run: |
gh pr create --title "Patch file ${{ matrix.framework }}/${{ env.version }}" --body "" --repo "https://github.com/searchspring/snapfu-patches" --base "main" --head "patch-generate-${{ matrix.framework }}-${{ env.version }}" --project "Snap Beta" --reviewer "searchspring/snap-team"
gh pr create --title "Patch file ${{ matrix.framework }}/${{ env.version }}" --body "" --repo "https://github.com/searchspring/snapfu-patches" --base "main" --head "patch-generate-${{ matrix.framework }}-${{ env.version }}" --project "Snap" --reviewer "searchspring/snap-team"
env:
GITHUB_TOKEN: ${{ secrets.MACHINE_ACTION_WORKFLOW_PAT }}
67 changes: 67 additions & 0 deletions packages/snap-platforms/bigcommerce/groovy/ss_variants.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
Snap variants script for BigCommerce
Generates a JSON string with format:
ss_variants = [
{
attributes: { ... },
mappings: { core: { ... } },
options: {
[optionName]: { value: '', ... }
}
}
]
Each object (variant) in the array represents a variation of the product and each of the `options` should reflect that configuration.
When using this in Snap any properties found in `mappings.core` and `attributes` will be "masked" when the variant is selected.
See Snap documentation for more details.
*/

import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import org.apache.commons.lang.StringUtils

def slurper = new JsonSlurper()
def ss_variants = []

if (Objects.nonNull(doc?.child_sku_options) && !StringUtils.isEmpty(doc?.child_sku_options)) {
def sku_options = slurper.parseText(doc.child_sku_options as String)
if(Objects.nonNull(sku_options) && !(sku_options as List).isEmpty()){
sku_options.each { sku_option ->
def sku = [:]
def mappings = [:]
def core = [:]
def attributes = [:]
def option_data = [:]
def options = [:]

core.put("imageUrl" , sku_option?.image_url)
core.put("url", doc.url)
core.put("uid" ,sku_option.child_sku)
mappings.put("core", core)
sku.put("mappings",mappings)

if(Objects.nonNull(sku_option?.inventory_level)){
attributes.put("available", sku_option?.inventory_level > 0)
}

if(Objects.nonNull(sku_option?.option) && !StringUtils.isEmpty(sku_option?.option) && Objects.nonNull(sku_option?.value) && !StringUtils.isEmpty(sku_option?.value)){
attributes.put("title", sku_option?.option + " / " + sku_option?.value)

}
sku.put("attributes",attributes)

option_data.put("value", sku_option?.value)

if(Objects.nonNull(sku_option?.option)){
options.put(sku_option?.option, option_data)
}

sku.put("options",options)
ss_variants.add(sku)
}
}
}

index.put("ss_variants", JsonOutput.toJson(ss_variants))
124 changes: 124 additions & 0 deletions packages/snap-platforms/magento2/groovy/ss_variants.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
Snap variants script for Magento2
Generates a JSON string with format:
ss_variants = [
{
attributes: { ... },
mappings: { core: { ... } },
options: {
[optionName]: { value: '', ... }
}
}
]
Each object (variant) in the array represents a variation of the product and each of the `options` should reflect that configuration.
When using this in Snap any properties found in `mappings.core` and `attributes` will be "masked" when the variant is selected.
See Snap documentation for more details.
*/

import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import org.apache.commons.lang.StringUtils


def slurper = new JsonSlurper()

def imageUrls = [:]
if (Objects.nonNull(doc.swatch_json_data) && !StringUtils.isEmpty(doc.swatch_json_data as String)) {
def swatchData = slurper.parseText(doc.swatch_json_data as String)
if (Objects.nonNull(swatchData)) {
swatchData.each { imageData ->
if (Objects.nonNull(imageData?.color) && Objects.nonNull(imageData?.image)) {
imageUrls.put(imageData?.color, imageData?.image)
}
}
}
}

if (Objects.nonNull(doc.json_config) && !StringUtils.isEmpty(doc.json_config as String)) {
def jsonConfig = slurper.parseText(doc.json_config as String)
def ss_swatches = []

if (Objects.nonNull(jsonConfig?.attributes)) {
def productIds = []
jsonConfig.attributes*.value*.options*.products?.each { rawProductIds ->
if (Objects.nonNull(rawProductIds)) {
rawProductIds.each {
if (Objects.nonNull(it)) {
productIds.addAll(it)
}
}
}
}
productIds = productIds?.unique()

productIds.each { uniqueProductId ->
def productId = uniqueProductId
def ss_variants = [:]
def options = [:]

def colour = null
def size = null
def colourAttributeId = null
def colourOptionId = null
def sizeAttributeId = null
def sizeOptionId = null
jsonConfig?.attributes?.each { attribute ->
if (Objects.nonNull(attribute?.value?.code)) {
def isColour = attribute?.value?.code == "colour"
def optionData = [:]

optionData.put("attributeId", attribute?.key)

if (Objects.nonNull(attribute?.value?.options) && !(attribute?.value?.options as List).isEmpty()) {
(attribute?.value?.options as List).each { attributeSubOption ->
if (Objects.nonNull(attributeSubOption?.products) && (attributeSubOption?.products as List).contains(productId)) {
if (isColour) {
colour = attributeSubOption?.label
colourAttributeId = attribute?.key
colourOptionId = attributeSubOption?.id
} else {
size = attributeSubOption?.label
sizeAttributeId = attribute?.key
sizeOptionId = attributeSubOption?.id
}
optionData.put("value", attributeSubOption?.label)
optionData.put("optionId", attributeSubOption?.id)
}
}
}
options.put(attribute?.value?.code, optionData)
}
}

def core = [:]

if (colourAttributeId && colourOptionId && sizeOptionId && sizeAttributeId) {
core.put("url", doc?.url + "#" + colourAttributeId + "=" + colourOptionId + "&" + sizeAttributeId + "=" + sizeOptionId)
}

if (Objects.nonNull(colour) && Objects.nonNull(imageUrls?.get(colour))) {
core.put("imageUrl", imageUrls?.get(colour))
}

core.put("uid", uniqueProductId)
def mappings = [:]
mappings.put("core", core)

ss_variants.put("mappings", mappings)

def attributes = [:]
attributes.put("available", true)
if (Objects.nonNull(colour) && Objects.nonNull(size)) {
attributes.put("title", "$colour / $size")
}
ss_variants.put("attributes", attributes)
ss_variants.put("options", options)
ss_swatches.add(ss_variants)
}

index.ss_variants = JsonOutput.toJson(ss_swatches)
}
}
188 changes: 188 additions & 0 deletions packages/snap-platforms/shopify/groovy/ss_variants.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/*
Snap variants script for Shopify
Generates a JSON string with format:
ss_variants = [
{
attributes: { ... },
mappings: { core: { ... } },
options: {
[optionName]: { value: '', ... }
}
}
]
Each object (variant) in the array represents a variation of the product and each of the `options` should reflect that configuration.
When using this in Snap any properties found in `mappings.core` and `attributes` will be "masked" when the variant is selected.
See Snap documentation for more details.
*/

import groovy.json.JsonSlurper
import groovy.json.JsonOutput

/* CONFIGURATION */

// optional image to use if no variant image is found
def fallback_image = ''

// dimension modification for variant images
def shopify_image_dimension_suffix = ''
def shopify_thumbnail_dimension_suffix = ''


/* CODE */

// helper function to add a suffix to the Shopify images
def addImageSuffix = { img, suffix ->
matcher = (img =~ /(.+)(\.(?:(?i)jpg|jpeg|gif|png|svg|webp|avif|heic).+)/)
if (matcher) {
return matcher[0][1] + "_" + suffix + matcher[0][2]
} else {
return img
}
}

// JSON slurper
def slurper = new JsonSlurper()
def variants_json = slurper.parseText(doc.variants)
def options_json = slurper.parseText(doc.options)
def variant_images_json
try{
variant_images_json = slurper.parseText(doc.variant_images_json)
} catch (err) {
variant_images_json = []
}

/* create an options map and array from options_json */
def options_map = [:]

options_json.each { option ->
def option_position_string = 'option' + option.position
def option_name = option.name.toLowerCase().replace(' ', '_')
options_map[option_position_string] = option_name
}

/* create an options_image_map from variant_images_json*/
def options_image_map = [:]

variant_images_json.each { variant_image ->
def option_map_reference = options_image_map

options_map.eachWithIndex { option_key, option, idx ->
def option_value = variant_image[option]
if (idx + 1 == options_map.size()) {
if ( option_value ) {
option_map_reference[option_value] = variant_image.img
}
} else {
if (!option_map_reference[option_value] && option_value) {
option_map_reference[option_value] = [:]
}
if (option_value) {
option_map_reference = option_map_reference[option_value]
}
}
}
}

/* map variants_json -> variants structure and put into array */
def variant_array = []

// variant data to put into core fields
def core_fields_mapping = [
uid: "id",
msrp: "compare_at_price",
price: "price",
sku: "sku",
]

// attributes outside of the options
def attributes_fields_mapping = [
quantity: "inventory_quantity", // property must be named "quantity" for proper functionality
title: "title",
]

variants_json.each { variant ->
def variant_object = [:]
variant_object.mappings = [:]
variant_object.mappings.core = [:]
variant_object.attributes = [:]
variant_object.options = [:]

// convert into a variant object
/*
{
"mappings": {
"core": { ... }
},
"attributes": {
...
}
}
*/

/* populate core mappings */
core_fields_mapping.each { core_field_name, variant_field_name ->
variant_object.mappings.core[core_field_name] = variant[variant_field_name]
}
// add variant URL to core fields
variant_object.mappings.core.url = "/products/" + doc.handle + "?variant=" + variant.id
// add image core fields if an image if found for the variant
def option_path = [variant.option1, variant.option2, variant.option3]

def variant_image_reference = options_image_map
option_path.each { option ->
try {
if (option && variant_image_reference[option]) {
variant_image_reference = variant_image_reference[option]
}
} catch (err) {
variant_image_reference = variant_image_reference
}
}

// image found in mapping
if (variant_image_reference && variant_image_reference instanceof String) {
variant_object.mappings.core.imageUrl = variant_image_reference
variant_object.mappings.core.thumbnailImageUrl = variant_image_reference

// add image suffix
if (shopify_image_dimension_suffix) {
variant_object.mappings.core.imageUrl = addImageSuffix(variant_image_reference, shopify_image_dimension_suffix)
}
// add thumbnail image suffix
if (shopify_thumbnail_dimension_suffix) {
variant_object.mappings.core.thumbnailImageUrl = addImageSuffix(variant_image_reference, shopify_thumbnail_dimension_suffix)
}
} else if (fallback_image) {
variant_object.mappings.core.imageUrl = fallback_image
variant_object.mappings.core.thumbnailImageUrl = fallback_image
}

/* populate attributes */
attributes_fields_mapping.each { attribute_field_name, variant_field_name ->
variant_object.attributes[attribute_field_name] = variant[variant_field_name]
}

// determine availability
if (variant.inventory_policy == "continue" || variant.inventory_management == "null" || (variant.inventory_policy == "deny" && variant.inventory_quantity > 0)) {
variant_object.attributes.available = true
} else {
variant_object.attributes.available = false
}

/* populate options */
options_map.each { option_number, option_name ->
if(variant[option_number]) {
variant_object.options[option_name] = [
value: variant[option_number]
]
}
}

// add variant object to the array
variant_array.push(variant_object)
}

index.ss_variants = JsonOutput.toJson(variant_array)
Loading

0 comments on commit 0d9be6a

Please sign in to comment.