src/Models/ElementModel.php
protected function constructPropertyValuesForSave($selectedFields = [])
    {
        $propertyValues = [];
        $saveOnlySelected = !empty($selectedFields);

        $iblockPropertiesData = static::getCachedIblockPropertiesData();

        if ($saveOnlySelected) {
            foreach ($selectedFields as $code) {
                // if we pass PROPERTY_X_DESCRIPTION as selected field, we need to add PROPERTY_X_VALUE as well.
                if (preg_match('/^PROPERTY_(.*)_DESCRIPTION$/', $code, $matches) && !empty($matches[1])) {
                    $propertyCode = $matches[1];
                    $propertyValueKey = "PROPERTY_{$propertyCode}_VALUE";
                    if (!in_array($propertyValueKey, $selectedFields)) {
                        $selectedFields[] = $propertyValueKey;
                    }
                }

                // if we pass PROPERTY_X_ENUM_ID as selected field, we need to add PROPERTY_X_VALUE as well.
                if (preg_match('/^PROPERTY_(.*)_ENUM_ID$/', $code, $matches) && !empty($matches[1])) {
                    $propertyCode = $matches[1];
                    $propertyValueKey = "PROPERTY_{$propertyCode}_VALUE";
                    if (!in_array($propertyValueKey, $selectedFields)) {
                        $selectedFields[] = $propertyValueKey;
                    }
                }
            }
        }

        foreach ($this->fields as $code => $value) {
            if ($saveOnlySelected && !in_array($code, $selectedFields)) {
                continue;
            }

            if (preg_match('/^PROPERTY_(.*)_VALUE$/', $code, $matches) && !empty($matches[1])) {
                $propertyCode = $matches[1];
                $iblockPropertyData = (array) $iblockPropertiesData[$propertyCode];

                // if file was not changed skip it or it will be duplicated
                if ($iblockPropertyData && $iblockPropertyData['PROPERTY_TYPE'] === 'F' && !empty($this->original[$code]) && $this->original[$code] === $value) {
                    continue;
                }

                // if property type is a list we need to use enum ID/IDs as value/values
                if (array_key_exists("PROPERTY_{$propertyCode}_ENUM_ID", $this->fields)) {
                    $value = $this->fields["PROPERTY_{$propertyCode}_ENUM_ID"];
                } elseif ($iblockPropertyData && $iblockPropertyData['PROPERTY_TYPE'] === 'L' && $iblockPropertyData['MULTIPLE'] === 'Y') {
                    $value = array_keys($value);
                }

                // if property values have descriptions
                // we skip file properties here for now because they cause endless problems. Handle them manually.
                if (array_key_exists("PROPERTY_{$propertyCode}_DESCRIPTION", $this->fields) && (!$iblockPropertyData || $iblockPropertyData['PROPERTY_TYPE'] !== 'F')) {
                    $description = $this->fields["PROPERTY_{$propertyCode}_DESCRIPTION"];

                    if (is_array($value) && is_array($description)) {
                        // for multiple property
                        foreach ($value as $rowIndex => $rowValue) {
                            $propertyValues[$propertyCode][] = [
                                'VALUE' => $rowValue,
                                'DESCRIPTION' => $description[$rowIndex]
                            ];
                        }
                    } else {
                        // for single property
                        $propertyValues[$propertyCode] = [
                            'VALUE' => $value,
                            'DESCRIPTION' => $description
                        ];
                    }
                } else {
                    $propertyValues[$propertyCode] = $value;
                }
            }
        }

        return $propertyValues;
    }
protected function constructPropertyValuesForSave($selectedFields = [])
    {
        $propertyValues = [];
        $saveOnlySelected = !empty($selectedFields);

        $iblockPropertiesData = static::getCachedIblockPropertiesData();

        if ($saveOnlySelected) {
            foreach ($selectedFields as $code) {
                // if we pass PROPERTY_X_DESCRIPTION as selected field, we need to add PROPERTY_X_VALUE as well.
                if (preg_match('/^PROPERTY_(.*)_DESCRIPTION$/', $code, $matches) && !empty($matches[1])) {
                    $propertyCode = $matches[1];
                    $propertyValueKey = "PROPERTY_{$propertyCode}_VALUE";
                    if (!in_array($propertyValueKey, $selectedFields)) {
                        $selectedFields[] = $propertyValueKey;
                    }
                }

                // if we pass PROPERTY_X_ENUM_ID as selected field, we need to add PROPERTY_X_VALUE as well.
                if (preg_match('/^PROPERTY_(.*)_ENUM_ID$/', $code, $matches) && !empty($matches[1])) {
                    $propertyCode = $matches[1];
                    $propertyValueKey = "PROPERTY_{$propertyCode}_VALUE";
                    if (!in_array($propertyValueKey, $selectedFields)) {
                        $selectedFields[] = $propertyValueKey;
                    }
                }
            }
        }

        foreach ($this->fields as $code => $value) {
            if ($saveOnlySelected && !in_array($code, $selectedFields)) {
                continue;
            }

            if (preg_match('/^PROPERTY_(.*)_VALUE$/', $code, $matches) && !empty($matches[1])) {
                $propertyCode = $matches[1];
                $iblockPropertyData = (array) $iblockPropertiesData[$propertyCode];

                // if file was not changed skip it or it will be duplicated
                if ($iblockPropertyData && $iblockPropertyData['PROPERTY_TYPE'] === 'F' && !empty($this->original[$code]) && $this->original[$code] === $value) {
                    continue;
                }

                // if property type is a list we need to use enum ID/IDs as value/values
                if (array_key_exists("PROPERTY_{$propertyCode}_ENUM_ID", $this->fields)) {
                    $value = $this->fields["PROPERTY_{$propertyCode}_ENUM_ID"];
                } elseif ($iblockPropertyData && $iblockPropertyData['PROPERTY_TYPE'] === 'L' && $iblockPropertyData['MULTIPLE'] === 'Y') {
                    $value = array_keys($value);
                }

                // if property values have descriptions
                // we skip file properties here for now because they cause endless problems. Handle them manually.
                if (array_key_exists("PROPERTY_{$propertyCode}_DESCRIPTION", $this->fields) && (!$iblockPropertyData || $iblockPropertyData['PROPERTY_TYPE'] !== 'F')) {
                    $description = $this->fields["PROPERTY_{$propertyCode}_DESCRIPTION"];

                    if (is_array($value) && is_array($description)) {
                        // for multiple property
                        foreach ($value as $rowIndex => $rowValue) {
                            $propertyValues[$propertyCode][] = [
                                'VALUE' => $rowValue,
                                'DESCRIPTION' => $description[$rowIndex]
                            ];
                        }
                    } else {
                        // for single property
                        $propertyValues[$propertyCode] = [
                            'VALUE' => $value,
                            'DESCRIPTION' => $description
                        ];
                    }
                } else {
                    $propertyValues[$propertyCode] = $value;
                }
            }
        }

        return $propertyValues;
    }
Construct 'PROPERTY_VALUES' => [...] from flat fields array.
This is used in save.
If $selectedFields are specified only those are saved.

@param $selectedFields

@return array