| @@ -47,9 +47,13 @@ | ||
| 47 | 47 | $fieldName = substr($value, 2, strlen($value) - 3); |
| 48 | 48 | $fieldValue = null; |
| 49 | 49 | if (isset($fieldValues[$fieldName])) { |
| 50 | 50 | $targetFieldValue = isset($fieldValues[$fieldName]['value']) ? $fieldValues[$fieldName]['value'] : $fieldValues[$fieldName]; |
| 51 | - if ('array' === gettype($targetFieldValue) || 'object' === gettype($targetFieldValue)) { | |
| 51 | + $targetFieldType = self::fieldTypeForSmartTag($fieldValues[$fieldName], $fieldName, $formID); | |
| 52 | + if (self::isCompositeFieldType($targetFieldType) && ('array' === gettype($targetFieldValue) || 'object' === gettype($targetFieldValue))) { | |
| 53 | + // Name/Address parts are words of one value: never summed, joined like everywhere else. | |
| 54 | + $fieldValue = self::joinCompositeFieldValue((array) $targetFieldValue, $targetFieldType); | |
| 55 | + } elseif ('array' === gettype($targetFieldValue) || 'object' === gettype($targetFieldValue)) { | |
| 52 | 56 | foreach (self::stripMetaSubfields((array) $targetFieldValue) as $singleTargetVal) { |
| 53 | 57 | if (isset($fieldValue)) { |
| 54 | 58 | if (is_numeric($fieldValue) && is_numeric($singleTargetVal)) { |
| 55 | 59 | $fieldValue = $fieldValue + $singleTargetVal; |
| @@ -1274,8 +1278,29 @@ | ||
| 1274 | 1278 | return $formFields[$fldKey]['type']; |
| 1275 | 1279 | } |
| 1276 | 1280 | } |
| 1277 | 1281 | |
| 1282 | + /** | |
| 1283 | + * The type of the field a Smart Tag points at: from the value itself when it carries | |
| 1284 | + * one, otherwise from the form. | |
| 1285 | + * | |
| 1286 | + * @param mixed $fieldValue Entry of $fieldValues for this field | |
| 1287 | + * @param string $fieldKey | |
| 1288 | + * @param int|null $formID | |
| 1289 | + * @return string|null | |
| 1290 | + */ | |
| 1291 | + private static function fieldTypeForSmartTag($fieldValue, $fieldKey, $formID) | |
| 1292 | + { | |
| 1293 | + if (is_array($fieldValue) && isset($fieldValue['type']) && is_string($fieldValue['type'])) { | |
| 1294 | + return $fieldValue['type']; | |
| 1295 | + } | |
| 1296 | + if (!$formID) { | |
| 1297 | + return null; | |
| 1298 | + } | |
| 1299 | + $formFields = FormManager::getInstance($formID)->getFields(); | |
| 1300 | + return is_array($formFields) && isset($formFields[$fieldKey]['type']) ? $formFields[$fieldKey]['type'] : null; | |
| 1301 | + } | |
| 1302 | + | |
| 1278 | 1303 | private static function isCompositeFieldType($fieldType) |
| 1279 | 1304 | { |
| 1280 | 1305 | return in_array($fieldType, ['name', 'address'], true); |
| 1281 | 1306 | } |
| @@ -1487,8 +1512,29 @@ | ||
| 1487 | 1512 | return $matches[1]; |
| 1488 | 1513 | } |
| 1489 | 1514 | |
| 1490 | 1515 | return str_replace(['[', ']', (string) $parentFieldName], '', $childFieldName); |
| 1516 | + } | |
| 1517 | + | |
| 1518 | + /** | |
| 1519 | + * The HTML name a composite child (Name/Address) renders with: the parent's current name plus | |
| 1520 | + * the child's own suffix. The child stores a full "parent[suffix]" copy that goes stale when the | |
| 1521 | + * parent is renamed, and a stale prefix posts the value away from the parent. | |
| 1522 | + * | |
| 1523 | + * @param string $childFieldName stored child name, e.g. "address-1[city]" | |
| 1524 | + * @param string $parentFieldName parent's current name, e.g. "home_address" | |
| 1525 | + * | |
| 1526 | + * @return string e.g. "home_address[city]"; the stored name when it has no suffix or the parent has no name | |
| 1527 | + */ | |
| 1528 | + public static function rebaseChildFieldName($childFieldName, $parentFieldName) | |
| 1529 | + { | |
| 1530 | + $childFieldName = (string) $childFieldName; | |
| 1531 | + $parentFieldName = (string) $parentFieldName; | |
| 1532 | + if ('' === $parentFieldName || !preg_match('/\[([^\]]+)\]$/', $childFieldName, $matches)) { | |
| 1533 | + return $childFieldName; | |
| 1534 | + } | |
| 1535 | + | |
| 1536 | + return $parentFieldName . '[' . $matches[1] . ']'; | |
| 1491 | 1537 | } |
| 1492 | 1538 | |
| 1493 | 1539 | /** |
| 1494 | 1540 | * Pull a child value out of a parent composite field's nested submitted value. |