You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pdd-order-api/app/libs/tool/class.GoodsPropertyTool.php

413 lines
16 KiB
PHP

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
class GoodsPropertyTool {
public static function propertyControlTypeList() {
return [
MoveConst::propControlTypeInput => 'input',
MoveConst::propControlTypeYmdTimeSelect => 'input',
MoveConst::propControlTypeYmTimeSelect => 'input',
MoveConst::propControlTypeNumericalProductV2 => 'input',
MoveConst::propControlTypeInputSelect => 'select',
MoveConst::propControlTypeSelect => 'select',
];
}
public static function implodePropertyValues($goodsPropertyList) {
$newPropertyList = [];
foreach($goodsPropertyList as $prop) {
if(!isset($newPropertyList[$prop['template_pid']])) {
$newPropertyList[$prop['template_pid']] = $prop;
$newPropertyList[$prop['template_pid']]['vid'] = [];
$newPropertyList[$prop['template_pid']]['value'] = [];
}
$newPropertyList[$prop['template_pid']]['vid'][] = $prop['vid'];
$newPropertyList[$prop['template_pid']]['value'][] = $prop['value'];
}
return $newPropertyList;
}
public static function explodePropertyValues($goodsPropertyList) {
$newPropertyList = [];
foreach($goodsPropertyList as $prop) {
if (is_array($prop['value'])) {
foreach($prop['value'] as $key => $value) {
$newProp = $prop;
$newProp['value'] = $value;
$newProp['vid'] = $prop['vid'][$key];
$newPropertyList[] = $newProp;
}
}
}
return $newPropertyList;
}
public static function isSelectControlType($controlType) {
return in_array($controlType, [
MoveConst::propControlTypeInputSelect,
MoveConst::propControlTypeSelect,
]);
}
public static function isSingleSelectControlType($controlType, $chooseMaxNum) {
return self::isSelectControlType($controlType) && $chooseMaxNum == 1;
}
public static function isMultiSelectControlType($controlType, $chooseMaxNum) {
return self::isSelectControlType($controlType) && $chooseMaxNum > 1;
}
public static function getPropertyGroupList($allPropertyList, $excludeBrand = false) {
$controlTypeMap = self::propertyControlTypeList();
foreach ($allPropertyList as $key => $property) {
if ($property['is_sale']) {
unset($allPropertyList[$key]);
continue;
}
if ($excludeBrand && $property['name_alias'] == '品牌') {
unset($allPropertyList[$key]);
continue;
}
$allPropertyList[$key]['control_type_name'] = ($property['choose_max_num'] > 1 ? 'multi-' : '') . $controlTypeMap[$property['control_type']];
}
$groupList = [];
$propertyTreeList = self::getPropertyTreeList($allPropertyList, [], $excludeBrand);
$propIdPropertyMap = ZcArrayHelper::changeKeyRow($allPropertyList, 'id');
foreach($propertyTreeList as $tree) {
$topPropInfo = $propIdPropertyMap[$tree['id']];
list(, , $allChildPropList) = self::getPropTreePropIds($tree, $propIdPropertyMap);
$topPropInfo['all_children'] = $allChildPropList;
$groupList[] = $topPropInfo;
}
return $groupList;
}
public static function buildGoodsPropertyList($allPropertyList, $goodsPropertyList) {
$newProps = [];
$properties = ZcArrayHelper::changeKeyRow($allPropertyList, 'ref_pid');
foreach ($goodsPropertyList as $goodsProperty) {
$propertyInfo = $properties[$goodsProperty['ref_pid']];
if (empty($propertyInfo)) {
continue;
}
$newProps[] = [
'ref_pid' => $propertyInfo['ref_pid'],
'template_pid' => $propertyInfo['id'],
'pid' => $propertyInfo['parent_id'],
'vid' => $goodsProperty['vid'],
'value' => $goodsProperty['vvalue'],
'value_unit' => $goodsProperty['punit'] ? $goodsProperty['punit'] : explode(',', $goodsProperty['value_unit'])[0],
];
}
return $newProps;
}
public static function buildEmptyProperty($propertyId, $parentId = 0) {
return [
'template_pid' => $propertyId,
'pid' => $parentId,
'vid' => 0,
'value' => '',
'value_unit' => '',
];
}
public static function getBrandProperty($allPropertyList) {
foreach ($allPropertyList as $property) {
if ($property['name_alias'] == '品牌') {
return $property;
}
}
return [];
}
public static function replaceGoodsPropertyValues($allPropertyList, $oldProps, $replacePropKvMap, $replacePropUnitKvMap = array()) {
$newProps = [];
$changePropIds = [];
$oldProps = ZcArrayHelper::changeKey($oldProps, 'template_pid', true);
$propertyTreeList = self::getPropertyTreeList($allPropertyList, [], true);
$propIdPropertyMap = ZcArrayHelper::changeKeyRow($allPropertyList, 'id');
$topIdPropGroupIdsMap = [];
foreach ($propertyTreeList as $tree) {
list($treeRequirePropIds, $treePropIds) = self::getPropTreePropIds($tree, $propIdPropertyMap);
$topIdPropGroupIdsMap[$tree['id']] = $treePropIds;
}
$brandProperty = self::getBrandProperty($allPropertyList);
$topTemplateIds = array_keys($topIdPropGroupIdsMap);
$oldTemplateIds = array_keys($oldProps);
$replaceTopTemplateIds = [];
foreach ($replacePropKvMap as $propId => $propValue) {
if (in_array($propId, $topTemplateIds)) {
$replaceTopTemplateIds[] = $propId;
}
}
$deleteTemplateIds = [];
foreach (array_intersect($oldTemplateIds, $replaceTopTemplateIds) as $pid) {
$deleteTemplateIds = array_merge($deleteTemplateIds, $topIdPropGroupIdsMap[$pid] ?: []);
}
foreach ($oldProps as $propId => $propValues) {
if (!in_array($propId, $deleteTemplateIds)) {
$newProps[$propId] = $propValues;
}
}
foreach ($replacePropKvMap as $propId => $propVids) {
if ($brandProperty['id'] == $propId) {
continue;
}
if ($newProps[$propId]) {
continue;
}
$changePropIds[] = $propId;
$propertyInfo = $propIdPropertyMap[$propId];
$valueList = self::findPropertyValue($propertyInfo, $propVids);
foreach ($valueList as $value) {
$newProps[$propId][] = [
'template_pid' => $propertyInfo['id'],
'pid' => $propertyInfo['parent_id'],
'vid' => $value['vid'],
'value' => $value['value'],
'value_unit' => $replacePropUnitKvMap[$propId] ? : explode(',', $propertyInfo['value_unit'])[0],
];
}
}
$retNewProps = [];
foreach($newProps as $newProp) {
$retNewProps = array_merge($retNewProps, $newProp);
}
return [$retNewProps, $changePropIds];
}
public static function findPropertyValue($propertyInfo, $vids) {
$valueList = [];
switch ($propertyInfo['control_type']) {
case MoveConst::propControlTypeInput :
case MoveConst::propControlTypeYmdTimeSelect :
case MoveConst::propControlTypeYmTimeSelect :
case MoveConst::propControlTypeNumericalProductV2 :
case MoveConst::propControlTypeRangeYmdTimeSelect :// zzq 暂时没有测试用例
case MoveConst::propControlTypeRangeYmSelect :// zzq 暂时没有测试用例
$valueList[] = [
'vid' => '',
'value' => $vids
];
break;
case MoveConst::propControlTypeInputSelect:
case MoveConst::propControlTypeSelect :
$vids = is_array($vids) ? $vids : [$vids];
foreach ($propertyInfo['values'] as $value) {
if (in_array($value['vid'], $vids)) {
$valueList[] = $value;
}
}
break;
}
return $valueList;
}
public static function getPropertyTreeList($allPropertyList, $returnFields = [], $excludeBrand = false) {
$parentIdChildPropMap = ZcArrayHelper::changeKey($allPropertyList, 'parent_id', true);
$treeList = [];
foreach ($allPropertyList as $prop) {
if ($prop['parent_id']) {
continue;
}
if ($excludeBrand && $prop['name_alias'] == '品牌') {
continue;
}
$propTree = self::getPropTree($parentIdChildPropMap, $prop, $returnFields);
$treeList[] = $propTree;
}
return $treeList;
}
protected static function getPropTreePropIds($propTree, $propIdPropertyMap) {
$treeRequirePropIds = $treePropIds = $allChildPropList = [];
$propStack = [$propTree];
while (true) {
$prop = array_pop($propStack);
if (empty($prop)) {
break;
}
$propInfo = $propIdPropertyMap[$prop['id']];
if ($propInfo['parent_id']) {
$allChildPropList[] = $propInfo;
}
if ($propInfo['required']) {
$treeRequirePropIds[] = $prop['id'];
}
$treePropIds[] = $prop['id'];
if (!empty($prop['child'])) {
$propStack = array_merge($propStack, $prop['child']);
}
if (count($propStack) == 0) {
break;
}
}
return [$treeRequirePropIds, $treePropIds, $allChildPropList];
}
protected static function getPropTree($parentIdChildPropMap, $parentProp, $returnFields = []) {
$parentId = $parentProp['id'];
$childList = $parentIdChildPropMap[$parentId];
$returnProp = $returnFields ? ZcArrayHelper::filterColumns($parentProp, $returnFields) : $parentProp;
$childTree = [];
if (!empty($childList)) {
foreach ($childList as $childProp) {
$childTree[] = self::getPropTree($parentIdChildPropMap, $childProp);
}
}
$returnProp['child'] = $childTree;
return $returnProp;
}
public static function checkHasOtherKeyWord($word) {
if ((strpos($word, '其它') !== false) || (strpos($word, '其他') !== false) || (stripos($word, 'other') !== false)) {
return true;
} else {
return false;
}
}
public static function checkGoodsNameHasBrand($goodsName, $brandName) {
if (CommonTool::anyEmpty($goodsName, $brandName)) {
return false;
}
$splitPattern = '/[\(\/\)\s]/isuU';
$brandNameArr = preg_split($splitPattern, strtolower($brandName));
foreach ($brandNameArr as $splitBrandName) {
if (stripos($goodsName, $splitBrandName) !== false) {
return true;
}
}
return false;
}
public static function checkBrandNamesIsSame($inputBrandName, $sourceBrandName) {
if (CommonTool::anyEmpty($inputBrandName, $sourceBrandName)) {
return false;
}
$splitPattern = '/[\(\/\)\s]/isuU';
$inputBrandNameArr = preg_split($splitPattern, strtolower($inputBrandName));
$sourceBrandNameArr = preg_split($splitPattern, strtolower($sourceBrandName));
return !empty(array_intersect($inputBrandNameArr, $sourceBrandNameArr));
}
public static function buildGoodsPropertyListByValueMap($allPropertyList, $nameValueMap, $defaultOptions) {
$parentIdChildPropMap = ZcArrayHelper::changeKey($allPropertyList, 'parent_id', true);
$newProps = [];
foreach ($allPropertyList as $property) {
if ($property['parent_id']) {
continue;
}
if ($property['is_sale']) {
continue;
}
$matchProps = self::matchPropertyTreeValue($property, [], $nameValueMap, $parentIdChildPropMap, $defaultOptions);
if ($matchProps && is_array($matchProps)) {
$newProps = array_merge($newProps, $matchProps);
}
}
return self::explodePropertyValues($newProps);
}
public static function matchPropertyTreeValue($property, $parentVids, $nameValueMap, $parentIdChildPropMap, $defaultOptions) {
$parentVids = $parentVids ?: [];
$currentValue = [];
$matchValueList = [];
$value = $nameValueMap[$property['name_alias']];
$valueList = is_array($value['value']) ? $value['value'] : explode(',', $value['value']);
$valueList = array_map('trim', $valueList);
if (self::isSelectControlType($property['control_type'])) {
$usableValues = self::getPropertyUsableValues($property, $parentVids);
foreach ($usableValues as $v) {
if (in_array($v['value'], $valueList)) {
$currentValue['value'][] = $v['value'];
$currentValue['vid'][] = $v['vid'];
}
}
if (empty($currentValue) && $defaultOptions['select'] == 'otherOrLast') {
$currentValue = self::getPropertyValueOtherOrLast($usableValues);
}
} else {
if (self::getPropertyCanShow($property, $parentVids)) {
if (($property['value_type'] == MoveConst::propValueTypeNumber) && ($valueList[0] || $defaultOptions['number'])) {
$currentValue['value'][] = $valueList[0] ?: $defaultOptions['number'];
} else if (($property['value_type'] == MoveConst::propValueTypeText) && ($valueList[0] || $defaultOptions['text'])) {
$currentValue['value'][] = $valueList[0] ?: $defaultOptions['text'];
}
}
}
if ($currentValue) {
if ($property['choose_max_num'] > 1) {
$currentValue['value'] = array_slice( $currentValue['value'], 0, $property['choose_max_num']);
$currentValue['vid'] = array_slice( $currentValue['vid'], 0, $property['choose_max_num']);
}
$currentValue['template_pid'] = $property['id'];
$currentValue['pid'] = $property['parent_id'];
$currentValue['value_unit'] = $value['value_unit'] ? : explode(',', $property['value_unit'])[0];
$matchValueList[] = $currentValue;
}
foreach ($parentIdChildPropMap[$property['id']] as $childProperty) {
if ($childProperty['is_sale']) {
continue;
}
$childMathValueList = self::matchPropertyTreeValue($childProperty, $currentValue['vid'], $nameValueMap, $parentIdChildPropMap, $defaultOptions);
if ($childMathValueList) {
$matchValueList = array_merge($matchValueList, $childMathValueList);
}
}
return $matchValueList;
}
public static function getPropertyValueOtherOrLast($valueList) {
$matchValue = [];
foreach ($valueList as $v) {
if (self::checkHasOtherKeyWord($v['value'])) {
$matchValue['value'][] = $v['value'];
$matchValue['vid'][] = $v['vid'];
break;
}
}
if (empty($matchValue) && $valueList) {
$matchValue['value'][] = end($valueList)['value'];
$matchValue['vid'][] = end($valueList)['vid'];
}
return $matchValue;
}
public static function getPropertyCanShow($property, $parentVids) {
if($property['is_condition_show'] && $property['show_vids'] && !in_array($parentVids[0], $property['show_vids'])){
return false;
}
return true;
}
public static function getPropertyUsableValues($property, $parentVids) {
if (!self::getPropertyCanShow($property, $parentVids)) {
return [];
}
$usableValues = [];
foreach ($property['values'] as $value) {
if (empty($value['parent_vids']) || array_intersect($parentVids, $value['parent_vids'])) {
$usableValues[] = $value;
}
}
return $usableValues;
}
}