function SetPropertyValues($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUES, $PROPERTY_CODE = false) { global $DB; global $BX_IBLOCK_PROP_CACHE; $ELEMENT_ID = (int) $ELEMENT_ID; $IBLOCK_ID = (int) $IBLOCK_ID; if (!is_array($PROPERTY_VALUES)) { $PROPERTY_VALUES = array($PROPERTY_VALUES); } $uniq_flt = $IBLOCK_ID; $arFilter = array("IBLOCK_ID" => $IBLOCK_ID, "CHECK_PERMISSIONS" => "N"); if ($PROPERTY_CODE === false) { $arFilter["ACTIVE"] = "Y"; $uniq_flt .= "|ACTIVE:" . $arFilter["ACTIVE"]; } elseif ((int) $PROPERTY_CODE > 0) { $arFilter["ID"] = (int) $PROPERTY_CODE; $uniq_flt .= "|ID:" . $arFilter["ID"]; } else { $arFilter["CODE"] = $PROPERTY_CODE; $uniq_flt .= "|CODE:" . $arFilter["CODE"]; } if (!isset($BX_IBLOCK_PROP_CACHE[$IBLOCK_ID])) { $BX_IBLOCK_PROP_CACHE[$IBLOCK_ID] = array(); } if (!isset($BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt])) { $BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt] = array(); $db_prop = CIBlockProperty::GetList(array(), $arFilter); while ($prop = $db_prop->Fetch()) { $BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt][$prop["ID"]] = $prop; } unset($prop); unset($db_prop); } $ar_prop =& $BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt]; reset($ar_prop); $bRecalcSections = false; //Read current property values from database $arDBProps = array(); if (CIBLock::GetArrayByID($IBLOCK_ID, "VERSION") == 2) { $rs = $DB->Query("\n\t\t\t\tselect *\n\t\t\t\tfrom b_iblock_element_prop_m" . $IBLOCK_ID . "\n\t\t\t\twhere IBLOCK_ELEMENT_ID = " . $ELEMENT_ID . "\n\t\t\t\torder by ID asc\n\t\t\t"); while ($ar = $rs->Fetch()) { $property_id = $ar["IBLOCK_PROPERTY_ID"]; if (!isset($arDBProps[$property_id])) { $arDBProps[$property_id] = array(); } $arDBProps[$property_id][$ar["ID"]] = $ar; } unset($ar); unset($rs); $rs = $DB->Query("\n\t\t\t\tselect *\n\t\t\t\tfrom b_iblock_element_prop_s" . $IBLOCK_ID . "\n\t\t\t\twhere IBLOCK_ELEMENT_ID = " . $ELEMENT_ID . "\n\t\t\t"); if ($ar = $rs->Fetch()) { foreach ($ar_prop as $property) { $property_id = $property["ID"]; if ($property["MULTIPLE"] == "N" && isset($ar["PROPERTY_" . $property_id]) && strlen($ar["PROPERTY_" . $property_id])) { if (!isset($arDBProps[$property_id])) { $arDBProps[$property_id] = array(); } $arDBProps[$property_id][$ELEMENT_ID . ":" . $property_id] = array("ID" => $ELEMENT_ID . ":" . $property_id, "IBLOCK_PROPERTY_ID" => $property_id, "VALUE" => $ar["PROPERTY_" . $property_id], "DESCRIPTION" => $ar["DESCRIPTION_" . $property_id]); } } if (isset($property)) { unset($property); } } unset($ar); unset($rs); } else { $rs = $DB->Query("\n\t\t\t\tselect *\n\t\t\t\tfrom b_iblock_element_property\n\t\t\t\twhere IBLOCK_ELEMENT_ID = " . $ELEMENT_ID . "\n\t\t\t\torder by ID asc\n\t\t\t"); while ($ar = $rs->Fetch()) { $property_id = $ar["IBLOCK_PROPERTY_ID"]; if (!isset($arDBProps[$property_id])) { $arDBProps[$property_id] = array(); } $arDBProps[$property_id][$ar["ID"]] = $ar; } unset($ar); unset($rs); } foreach (GetModuleEvents("iblock", "OnIBlockElementSetPropertyValues", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUES, $PROPERTY_CODE, $ar_prop, $arDBProps)); } if (isset($arEvent)) { unset($arEvent); } $arFilesToDelete = array(); $arV2ClearCache = array(); foreach ($ar_prop as $prop) { if ($PROPERTY_CODE) { $PROP = $PROPERTY_VALUES; } else { if (strlen($prop["CODE"]) > 0 && array_key_exists($prop["CODE"], $PROPERTY_VALUES)) { $PROP = $PROPERTY_VALUES[$prop["CODE"]]; } else { $PROP = $PROPERTY_VALUES[$prop["ID"]]; } } if (!is_array($PROP) || $prop["PROPERTY_TYPE"] == "F" && (array_key_exists("tmp_name", $PROP) || array_key_exists("del", $PROP)) || count($PROP) == 2 && array_key_exists("VALUE", $PROP) && array_key_exists("DESCRIPTION", $PROP)) { $PROP = array($PROP); } if ($prop["USER_TYPE"] != "") { $arUserType = CIBlockProperty::GetUserType($prop["USER_TYPE"]); if (array_key_exists("ConvertToDB", $arUserType)) { foreach ($PROP as $key => $value) { if (!is_array($value) || !array_key_exists("VALUE", $value)) { $value = array("VALUE" => $value); } $prop["ELEMENT_ID"] = $ELEMENT_ID; $PROP[$key] = call_user_func_array($arUserType["ConvertToDB"], array($prop, $value)); } } } if ($prop["VERSION"] == 2) { if ($prop["MULTIPLE"] == "Y") { $strTable = "b_iblock_element_prop_m" . $prop["IBLOCK_ID"]; } else { $strTable = "b_iblock_element_prop_s" . $prop["IBLOCK_ID"]; } } else { $strTable = "b_iblock_element_property"; } if ($prop["PROPERTY_TYPE"] == "L") { $DB->Query(CIBLockElement::DeletePropertySQL($prop, $ELEMENT_ID)); if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_" . $prop["ID"] . " = NULL" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]); } $ids = "0"; foreach ($PROP as $key => $value) { if (is_array($value)) { $value = intval($value["VALUE"]); } else { $value = intval($value); } if ($value <= 0) { continue; } $ids .= "," . $value; if ($prop["MULTIPLE"] != "Y") { break; } } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query("\n\t\t\t\t\t\tUPDATE\n\t\t\t\t\t\t\tb_iblock_element_prop_s" . $prop["IBLOCK_ID"] . " E\n\t\t\t\t\t\t\t,b_iblock_property P\n\t\t\t\t\t\t\t,b_iblock_property_enum PEN\n\t\t\t\t\t\tSET\n\t\t\t\t\t\t\tE.PROPERTY_" . $prop["ID"] . " = PEN.ID\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\tE.IBLOCK_ELEMENT_ID = " . $ELEMENT_ID . "\n\t\t\t\t\t\t\tAND P.ID = " . $prop["ID"] . "\n\t\t\t\t\t\t\tAND P.ID = PEN.PROPERTY_ID\n\t\t\t\t\t\t\tAND PEN.ID IN (" . $ids . ")\n\t\t\t\t\t"); } else { $DB->Query("\n\t\t\t\t\t\tINSERT INTO " . $strTable . "\n\t\t\t\t\t\t(IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_ENUM)\n\t\t\t\t\t\tSELECT " . $ELEMENT_ID . ", P.ID, PEN.ID, PEN.ID\n\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\tb_iblock_property P\n\t\t\t\t\t\t\t,b_iblock_property_enum PEN\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\tP.ID = " . $prop["ID"] . "\n\t\t\t\t\t\t\tAND P.ID = PEN.PROPERTY_ID\n\t\t\t\t\t\t\tAND PEN.ID IN (" . $ids . ")\n\t\t\t\t\t"); } } elseif ($prop["PROPERTY_TYPE"] == "G") { $bRecalcSections = true; $DB->Query(CIBLockElement::DeletePropertySQL($prop, $ELEMENT_ID)); if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_" . $prop["ID"] . " = NULL" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]); } $DB->Query("\n\t\t\t\t\tDELETE FROM b_iblock_section_element\n\t\t\t\t\tWHERE ADDITIONAL_PROPERTY_ID = " . $prop["ID"] . "\n\t\t\t\t\tAND IBLOCK_ELEMENT_ID = " . $ELEMENT_ID . "\n\t\t\t\t"); $ids = "0"; foreach ($PROP as $key => $value) { if (is_array($value)) { $value = intval($value["VALUE"]); } else { $value = intval($value); } if ($value <= 0) { continue; } $ids .= "," . $value; if ($prop["MULTIPLE"] != "Y") { break; } } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query("\n\t\t\t\t\t\tUPDATE\n\t\t\t\t\t\t\tb_iblock_element_prop_s" . $prop["IBLOCK_ID"] . " E\n\t\t\t\t\t\t\t,b_iblock_property P\n\t\t\t\t\t\t\t,b_iblock_section S\n\t\t\t\t\t\tSET\n\t\t\t\t\t\t\tE.PROPERTY_" . $prop["ID"] . " = S.ID\n\t\t\t\t\t\t\t" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) . "\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\tE.IBLOCK_ELEMENT_ID = " . $ELEMENT_ID . "\n\t\t\t\t\t\t\tAND P.ID = " . $prop["ID"] . "\n\t\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\t\tP.LINK_IBLOCK_ID IS NULL\n\t\t\t\t\t\t\t\tOR P.LINK_IBLOCK_ID = 0\n\t\t\t\t\t\t\t\tOR S.IBLOCK_ID = P.LINK_IBLOCK_ID\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tAND S.ID IN (" . $ids . ")\n\t\t\t\t\t"); } else { $DB->Query("\n\t\t\t\t\t\tINSERT INTO " . $strTable . "\n\t\t\t\t\t\t(IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_NUM)\n\t\t\t\t\t\tSELECT " . $ELEMENT_ID . ", P.ID, S.ID, S.ID\n\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\tb_iblock_property P\n\t\t\t\t\t\t\t,b_iblock_section S\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\tP.ID=" . $prop["ID"] . "\n\t\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\t\tP.LINK_IBLOCK_ID IS NULL\n\t\t\t\t\t\t\t\tOR P.LINK_IBLOCK_ID = 0\n\t\t\t\t\t\t\t\tOR S.IBLOCK_ID = P.LINK_IBLOCK_ID\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tAND S.ID IN (" . $ids . ")\n\t\t\t\t\t"); } $DB->Query("\n\t\t\t\t\tINSERT INTO b_iblock_section_element\n\t\t\t\t\t(IBLOCK_ELEMENT_ID, IBLOCK_SECTION_ID, ADDITIONAL_PROPERTY_ID)\n\t\t\t\t\tSELECT " . $ELEMENT_ID . ", S.ID, P.ID\n\t\t\t\t\tFROM\n\t\t\t\t\t\tb_iblock_property P\n\t\t\t\t\t\t,b_iblock_section S\n\t\t\t\t\tWHERE\n\t\t\t\t\t\tP.ID = " . $prop["ID"] . "\n\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\tP.LINK_IBLOCK_ID IS NULL\n\t\t\t\t\t\t\tOR P.LINK_IBLOCK_ID = 0\n\t\t\t\t\t\t\tOR S.IBLOCK_ID = P.LINK_IBLOCK_ID\n\t\t\t\t\t\t)\n\t\t\t\t\t\tAND S.ID IN (" . $ids . ")\n\t\t\t\t"); } elseif ($prop["PROPERTY_TYPE"] == "E") { $arWas = array(); if ($arDBProps[$prop["ID"]]) { foreach ($arDBProps[$prop["ID"]] as $res) { $val = $PROP[$res["ID"]]; if (is_array($val)) { $val_desc = $val["DESCRIPTION"]; $val = $val["VALUE"]; } else { $val_desc = false; } if (isset($arWas[$val])) { $val = ""; } else { $arWas[$val] = true; } if (strlen($val) <= 0) { if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query($s = "\n\t\t\t\t\t\t\t\t\tUPDATE b_iblock_element_prop_s" . $prop["IBLOCK_ID"] . "\n\t\t\t\t\t\t\t\t\tSET PROPERTY_" . $prop["ID"] . " = null\n\t\t\t\t\t\t\t\t\t" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) . "\n\t\t\t\t\t\t\t\t\tWHERE IBLOCK_ELEMENT_ID = " . $ELEMENT_ID . "\n\t\t\t\t\t\t\t\t"); } else { $DB->Query($s = "\n\t\t\t\t\t\t\t\t\tDELETE FROM " . $strTable . "\n\t\t\t\t\t\t\t\t\tWHERE ID=" . $res["ID"] . "\n\t\t\t\t\t\t\t\t"); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_" . $prop["ID"] . " = NULL" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]); } } elseif ($res["VALUE"] !== $val || $res["DESCRIPTION"] . '' !== $val_desc . '') { if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query("\n\t\t\t\t\t\t\t\t\tUPDATE b_iblock_element_prop_s" . $prop["IBLOCK_ID"] . "\n\t\t\t\t\t\t\t\t\tSET PROPERTY_" . $prop["ID"] . " = '" . $DB->ForSql($val) . "'\n\t\t\t\t\t\t\t\t\t" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"], $val_desc) . "\n\t\t\t\t\t\t\t\t\tWHERE IBLOCK_ELEMENT_ID = " . $ELEMENT_ID . "\n\t\t\t\t\t\t\t\t"); } else { $DB->Query("\n\t\t\t\t\t\t\t\t\tUPDATE " . $strTable . "\n\t\t\t\t\t\t\t\t\tSET VALUE = '" . $DB->ForSql($val) . "'\n\t\t\t\t\t\t\t\t\t\t,VALUE_NUM = " . CIBlock::roundDB($val) . "\n\t\t\t\t\t\t\t\t\t\t" . ($val_desc !== false ? ",DESCRIPTION = '" . $DB->ForSql($val_desc, 255) . "'" : "") . "\n\t\t\t\t\t\t\t\t\tWHERE ID=" . $res["ID"] . "\n\t\t\t\t\t\t\t\t"); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_" . $prop["ID"] . " = NULL" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]); } } unset($PROP[$res["ID"]]); } //foreach($arDBProps[$prop["ID"]] as $res) } foreach ($PROP as $val) { if (is_array($val)) { $val_desc = $val["DESCRIPTION"]; $val = $val["VALUE"]; } else { $val_desc = false; } if (isset($arWas[$val])) { $val = ""; } else { $arWas[$val] = true; } if (strlen($val) <= 0) { continue; } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query("\n\t\t\t\t\t\t\tUPDATE b_iblock_element_prop_s" . $prop["IBLOCK_ID"] . "\n\t\t\t\t\t\t\tSET\n\t\t\t\t\t\t\t\tPROPERTY_" . $prop["ID"] . " = '" . $DB->ForSql($val) . "'\n\t\t\t\t\t\t\t\t" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"], $val_desc) . "\n\t\t\t\t\t\t\tWHERE IBLOCK_ELEMENT_ID=" . $ELEMENT_ID . "\n\t\t\t\t\t\t"); } else { $DB->Query("\n\t\t\t\t\t\t\tINSERT INTO " . $strTable . "\n\t\t\t\t\t\t\t(IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_NUM" . ($val_desc !== false ? ", DESCRIPTION" : "") . ")\n\t\t\t\t\t\t\tSELECT\n\t\t\t\t\t\t\t\t" . $ELEMENT_ID . "\n\t\t\t\t\t\t\t\t,P.ID\n\t\t\t\t\t\t\t\t,'" . $DB->ForSql($val) . "'\n\t\t\t\t\t\t\t\t," . CIBlock::roundDB($val) . "\n\t\t\t\t\t\t\t\t" . ($val_desc !== false ? ", '" . $DB->ForSQL($val_desc, 255) . "'" : "") . "\n\t\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\t\tb_iblock_property P\n\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\tID = " . IntVal($prop["ID"]) . "\n\t\t\t\t\t\t"); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_" . $prop["ID"] . " = NULL" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]); } if ($prop["MULTIPLE"] != "Y") { break; } } //foreach($PROP as $value) } elseif ($prop["PROPERTY_TYPE"] == "F") { //We'll be adding values from the database into the head //for multiple values and into tje tail for single //these values were not passed into API call. if ($prop["MULTIPLE"] == "Y") { $orderedPROP = array_reverse($PROP, true); } else { $orderedPROP = $PROP; } if ($arDBProps[$prop["ID"]]) { //Go from high ID to low foreach (array_reverse($arDBProps[$prop["ID"]], true) as $res) { //Preserve description from database if (strlen($res["DESCRIPTION"])) { $description = $res["DESCRIPTION"]; } else { $description = false; } if (!array_key_exists($res["ID"], $orderedPROP)) { $orderedPROP[$res["ID"]] = array("VALUE" => $res["VALUE"], "DESCRIPTION" => $description); } else { $val = $orderedPROP[$res["ID"]]; if (is_array($val) && !array_key_exists("tmp_name", $val) && !array_key_exists("del", $val)) { $val = $val["VALUE"]; } //Check if no new file and no delete command if (!strlen($val["tmp_name"]) && !strlen($val["del"])) { //But save description from incoming value if (array_key_exists("description", $val)) { $description = trim($val["description"]); } $orderedPROP[$res["ID"]] = array("VALUE" => $res["VALUE"], "DESCRIPTION" => $description); } } } } //Restore original order if ($prop["MULTIPLE"] == "Y") { $orderedPROP = array_reverse($orderedPROP, true); } $preserveID = array(); //Now delete from database all marked for deletion records if ($arDBProps[$prop["ID"]]) { foreach ($arDBProps[$prop["ID"]] as $res) { $val = $orderedPROP[$res["ID"]]; if (is_array($val) && !array_key_exists("tmp_name", $val) && !array_key_exists("del", $val)) { $val = $val["VALUE"]; } if (is_array($val) && strlen($val["del"])) { unset($orderedPROP[$res["ID"]]); $arFilesToDelete[$res["VALUE"]] = array("FILE_ID" => $res["VALUE"], "ELEMENT_ID" => $ELEMENT_ID, "IBLOCK_ID" => $prop["IBLOCK_ID"]); } elseif ($prop["MULTIPLE"] != "Y") { //Delete all stored in database for replacement. $arFilesToDelete[$res["VALUE"]] = array("FILE_ID" => $res["VALUE"], "ELEMENT_ID" => $ELEMENT_ID, "IBLOCK_ID" => $prop["IBLOCK_ID"]); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query("\n\t\t\t\t\t\t\t\tUPDATE b_iblock_element_prop_s" . $prop["IBLOCK_ID"] . "\n\t\t\t\t\t\t\t\tSET PROPERTY_" . $prop["ID"] . " = null\n\t\t\t\t\t\t\t\t" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) . "\n\t\t\t\t\t\t\t\tWHERE IBLOCK_ELEMENT_ID = " . $ELEMENT_ID . "\n\t\t\t\t\t\t\t"); } else { $DB->Query("DELETE FROM " . $strTable . " WHERE ID = " . $res["ID"]); $preserveID[$res["ID"]] = $res["ID"]; } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_" . $prop["ID"] . " = NULL" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]); } } //foreach($arDBProps[$prop["ID"]] as $res) } //Check if we have to save property values id's if ($preserveID) { //Find tail mark where all added files started $tailStart = null; foreach (array_reverse($orderedPROP, true) as $propertyValueId => $val) { if (intval($propertyValueId) > 0) { break; } $tailStart = $propertyValueId; } $prevId = 0; foreach ($orderedPROP as $propertyValueId => $val) { if ($propertyValueId === $tailStart) { break; } if (intval($propertyValueId) < $prevId) { $preserveID = array(); break; } $prevId = $propertyValueId; } } //Write new values into database in specified order foreach ($orderedPROP as $propertyValueId => $val) { if (is_array($val) && !array_key_exists("tmp_name", $val)) { $val_desc = $val["DESCRIPTION"]; $val = $val["VALUE"]; } else { $val_desc = false; } if (is_array($val)) { $val["MODULE_ID"] = "iblock"; if ($val_desc !== false) { $val["description"] = $val_desc; } $val = CFile::SaveFile($val, "iblock"); } elseif ($val > 0 && $val_desc !== false) { CFile::UpdateDesc($val, $val_desc); } if (intval($val) <= 0) { continue; } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query($s = "\n\t\t\t\t\t\t\tUPDATE b_iblock_element_prop_s" . $prop["IBLOCK_ID"] . "\n\t\t\t\t\t\t\tSET\n\t\t\t\t\t\t\t\tPROPERTY_" . $prop["ID"] . " = '" . $DB->ForSql($val) . "'\n\t\t\t\t\t\t\t\t" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"], $val_desc) . "\n\t\t\t\t\t\t\tWHERE IBLOCK_ELEMENT_ID=" . $ELEMENT_ID . "\n\t\t\t\t\t\t"); } elseif (array_key_exists($propertyValueId, $preserveID)) { $DB->Query("\n\t\t\t\t\t\t\tINSERT INTO " . $strTable . "\n\t\t\t\t\t\t\t(ID, IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_NUM" . ($val_desc !== false ? ", DESCRIPTION" : "") . ")\n\t\t\t\t\t\t\tSELECT\n\t\t\t\t\t\t\t\t" . $preserveID[$propertyValueId] . "\n\t\t\t\t\t\t\t\t," . $ELEMENT_ID . "\n\t\t\t\t\t\t\t\t,P.ID\n\t\t\t\t\t\t\t\t,'" . $DB->ForSql($val) . "'\n\t\t\t\t\t\t\t\t," . CIBlock::roundDB($val) . "\n\t\t\t\t\t\t\t\t" . ($val_desc !== false ? ", '" . $DB->ForSQL($val_desc, 255) . "'" : "") . "\n\t\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\t\tb_iblock_property P\n\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\tID = " . IntVal($prop["ID"]) . "\n\t\t\t\t\t\t"); } else { $DB->Query("\n\t\t\t\t\t\t\tINSERT INTO " . $strTable . "\n\t\t\t\t\t\t\t(IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_NUM" . ($val_desc !== false ? ", DESCRIPTION" : "") . ")\n\t\t\t\t\t\t\tSELECT\n\t\t\t\t\t\t\t\t" . $ELEMENT_ID . "\n\t\t\t\t\t\t\t\t,P.ID\n\t\t\t\t\t\t\t\t,'" . $DB->ForSql($val) . "'\n\t\t\t\t\t\t\t\t," . CIBlock::roundDB($val) . "\n\t\t\t\t\t\t\t\t" . ($val_desc !== false ? ", '" . $DB->ForSQL($val_desc, 255) . "'" : "") . "\n\t\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\t\tb_iblock_property P\n\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\tID = " . IntVal($prop["ID"]) . "\n\t\t\t\t\t\t"); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_" . $prop["ID"] . " = NULL" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]); } if ($prop["MULTIPLE"] != "Y") { break; } } //foreach($PROP as $value) } else { if ($arDBProps[$prop["ID"]]) { foreach ($arDBProps[$prop["ID"]] as $res) { $val = $PROP[$res["ID"]]; if (is_array($val)) { $val_desc = $val["DESCRIPTION"]; $val = $val["VALUE"]; } else { $val_desc = false; } if (strlen($val) <= 0) { if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query("\n\t\t\t\t\t\t\t\t\tUPDATE b_iblock_element_prop_s" . $prop["IBLOCK_ID"] . "\n\t\t\t\t\t\t\t\t\tSET\n\t\t\t\t\t\t\t\t\t\tPROPERTY_" . $prop["ID"] . " = null\n\t\t\t\t\t\t\t\t\t\t" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) . "\n\t\t\t\t\t\t\t\t\tWHERE IBLOCK_ELEMENT_ID=" . $ELEMENT_ID . "\n\t\t\t\t\t\t\t\t"); } else { $DB->Query("DELETE FROM " . $strTable . " WHERE ID=" . $res["ID"]); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_" . $prop["ID"] . " = NULL" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]); } } else { if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { if ($prop["PROPERTY_TYPE"] == "N") { $val = CIBlock::roundDB($val); } $DB->Query("\n\t\t\t\t\t\t\t\t\tUPDATE b_iblock_element_prop_s" . $prop["IBLOCK_ID"] . "\n\t\t\t\t\t\t\t\t\tSET PROPERTY_" . $prop["ID"] . "='" . $DB->ForSql($val) . "'\n\t\t\t\t\t\t\t\t\t" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"], $val_desc) . "\n\t\t\t\t\t\t\t\t\tWHERE IBLOCK_ELEMENT_ID=" . $ELEMENT_ID . "\n\t\t\t\t\t\t\t\t"); } else { $DB->Query("\n\t\t\t\t\t\t\t\t\tUPDATE " . $strTable . "\n\t\t\t\t\t\t\t\t\tSET \tVALUE='" . $DB->ForSql($val) . "'\n\t\t\t\t\t\t\t\t\t\t,VALUE_NUM=" . CIBlock::roundDB($val) . "\n\t\t\t\t\t\t\t\t\t\t" . ($val_desc !== false ? ",DESCRIPTION='" . $DB->ForSql($val_desc, 255) . "'" : "") . "\n\t\t\t\t\t\t\t\t\tWHERE ID=" . $res["ID"] . "\n\t\t\t\t\t\t\t\t"); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_" . $prop["ID"] . " = NULL" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]); } } unset($PROP[$res["ID"]]); } //foreach ($arDBProps[$prop["ID"]] as $res) } foreach ($PROP as $val) { if (is_array($val) && !is_set($val, "tmp_name")) { $val_desc = $val["DESCRIPTION"]; $val = $val["VALUE"]; } else { $val_desc = false; } if (strlen($val) <= 0) { continue; } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { if ($prop["PROPERTY_TYPE"] == "N") { $val = CIBlock::roundDB($val); } $DB->Query("\n\t\t\t\t\t\t\tUPDATE b_iblock_element_prop_s" . $prop["IBLOCK_ID"] . "\n\t\t\t\t\t\t\tSET\n\t\t\t\t\t\t\t\tPROPERTY_" . $prop["ID"] . " = '" . $DB->ForSql($val) . "'\n\t\t\t\t\t\t\t\t" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"], $val_desc) . "\n\t\t\t\t\t\t\tWHERE IBLOCK_ELEMENT_ID=" . $ELEMENT_ID . "\n\t\t\t\t\t\t"); } else { $DB->Query("\n\t\t\t\t\t\t\tINSERT INTO " . $strTable . "\n\t\t\t\t\t\t\t(IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_NUM" . ($val_desc !== false ? ", DESCRIPTION" : "") . ")\n\t\t\t\t\t\t\tSELECT\n\t\t\t\t\t\t\t\t" . $ELEMENT_ID . "\n\t\t\t\t\t\t\t\t,P.ID\n\t\t\t\t\t\t\t\t,'" . $DB->ForSql($val) . "'\n\t\t\t\t\t\t\t\t," . CIBlock::roundDB($val) . "\n\t\t\t\t\t\t\t\t" . ($val_desc !== false ? ", '" . $DB->ForSQL($val_desc, 255) . "'" : "") . "\n\t\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\t\tb_iblock_property P\n\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\tID = " . IntVal($prop["ID"]) . "\n\t\t\t\t\t\t"); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_" . $prop["ID"] . " = NULL" . self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]); } if ($prop["MULTIPLE"] != "Y") { break; } } //foreach($PROP as $value) } //if($prop["PROPERTY_TYPE"]=="F") } if ($arV2ClearCache) { $DB->Query("\n\t\t\t\tUPDATE b_iblock_element_prop_s" . $IBLOCK_ID . "\n\t\t\t\tSET " . implode(",", $arV2ClearCache) . "\n\t\t\t\tWHERE IBLOCK_ELEMENT_ID = " . $ELEMENT_ID . "\n\t\t\t"); } foreach ($arFilesToDelete as $deleteTask) { CIBLockElement::DeleteFile($deleteTask["FILE_ID"], false, "PROPERTY", $deleteTask["ELEMENT_ID"], $deleteTask["IBLOCK_ID"]); } if ($bRecalcSections) { CIBlockElement::RecalcSections($ELEMENT_ID); } /****************************** QUOTA ******************************/ $_SESSION["SESS_RECOUNT_DB"] = "Y"; /****************************** QUOTA ******************************/ foreach (GetModuleEvents("iblock", "OnAfterIBlockElementSetPropertyValues", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUES, $PROPERTY_CODE)); } }
public static function Delete($ID) { global $DB, $APPLICATION, $USER; $USER_ID = is_object($USER) ? intval($USER->GetID()) : 0; $ID = IntVal($ID); $APPLICATION->ResetException(); foreach (GetModuleEvents("iblock", "OnBeforeIBlockElementDelete", true) as $arEvent) { if (ExecuteModuleEventEx($arEvent, array($ID)) === false) { $err = GetMessage("MAIN_BEFORE_DEL_ERR") . ' ' . $arEvent['TO_NAME']; $err_id = false; if ($ex = $APPLICATION->GetException()) { $err .= ': ' . $ex->GetString(); $err_id = $ex->GetID(); } $APPLICATION->throwException($err, $err_id); return false; } } $arSql = array("ID='" . $ID . "'", "WF_PARENT_ELEMENT_ID='" . $ID . "'"); foreach ($arSql as $strWhere) { $strSql = "\n\t\t\t\tSELECT\n\t\t\t\t\tID\n\t\t\t\t\t,IBLOCK_ID\n\t\t\t\t\t,WF_PARENT_ELEMENT_ID\n\t\t\t\t\t,WF_STATUS_ID\n\t\t\t\t\t,PREVIEW_PICTURE\n\t\t\t\t\t,DETAIL_PICTURE\n\t\t\t\t\t,XML_ID as EXTERNAL_ID\n\t\t\t\t\t,CODE\n\t\t\t\t\t,NAME\n\t\t\t\tFROM b_iblock_element\n\t\t\t\tWHERE " . $strWhere . "\n\t\t\t\tORDER BY ID DESC\n\t\t\t"; $z = $DB->Query($strSql); while ($zr = $z->Fetch()) { $elementId = (int) $zr["ID"]; $VERSION = CIBlockElement::GetIBVersion($zr["IBLOCK_ID"]); $db_res = CIBlockElement::GetProperty($zr["IBLOCK_ID"], $zr["ID"], "sort", "asc", array("PROPERTY_TYPE" => "F")); $arIBlockFields = CIBLock::GetArrayByID($zr["IBLOCK_ID"], "FIELDS"); if (IntVal($zr["WF_PARENT_ELEMENT_ID"]) <= 0 && $arIBlockFields["LOG_ELEMENT_DELETE"]["IS_REQUIRED"] == "Y") { $arEvents = GetModuleEvents("main", "OnBeforeEventLog", true); if (empty($arEvents) || ExecuteModuleEventEx($arEvents[0], array($USER_ID)) === false) { $rsElement = CIBlockElement::GetList(array(), array("=ID" => $ID), false, false, array("LIST_PAGE_URL", "NAME", "CODE")); $arElement = $rsElement->GetNext(); $arIblock = CIBlock::GetArrayByID($zr['IBLOCK_ID']); $res_log = array("ID" => $ID, "CODE" => $arElement["CODE"], "NAME" => $arElement["NAME"], "ELEMENT_NAME" => $arIblock["ELEMENT_NAME"], "USER_ID" => $USER_ID, "IBLOCK_PAGE_URL" => $arElement["LIST_PAGE_URL"]); CEventLog::Log("IBLOCK", "IBLOCK_ELEMENT_DELETE", "iblock", $zr["IBLOCK_ID"], serialize($res_log)); } } $piId = \Bitrix\Iblock\PropertyIndex\Manager::resolveElement($zr["IBLOCK_ID"], $zr["ID"]); foreach (GetModuleEvents("iblock", "OnIBlockElementDelete", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($elementId, $zr)); } while ($res = $db_res->Fetch()) { CIBlockElement::DeleteFile($res["VALUE"], $zr["ID"], "PROPERTY", $zr["WF_PARENT_ELEMENT_ID"], $zr["IBLOCK_ID"]); } if ($VERSION == 2) { if (!$DB->Query("DELETE FROM b_iblock_element_prop_m" . $zr["IBLOCK_ID"] . " WHERE IBLOCK_ELEMENT_ID = " . $elementId)) { return false; } if (!$DB->Query("DELETE FROM b_iblock_element_prop_s" . $zr["IBLOCK_ID"] . " WHERE IBLOCK_ELEMENT_ID = " . $elementId)) { return false; } } else { if (!$DB->Query("DELETE FROM b_iblock_element_property WHERE IBLOCK_ELEMENT_ID = " . $elementId)) { return false; } } static $arDelCache = array(); if (!is_set($arDelCache, $zr["IBLOCK_ID"])) { $arDelCache[$zr["IBLOCK_ID"]] = false; $db_ps = $DB->Query("SELECT ID,IBLOCK_ID,VERSION,MULTIPLE FROM b_iblock_property WHERE PROPERTY_TYPE='E' AND (LINK_IBLOCK_ID=" . $zr["IBLOCK_ID"] . " OR LINK_IBLOCK_ID=0 OR LINK_IBLOCK_ID IS NULL)"); while ($ar_ps = $db_ps->Fetch()) { if ($ar_ps["VERSION"] == 2) { if ($ar_ps["MULTIPLE"] == "Y") { $strTable = "b_iblock_element_prop_m" . $ar_ps["IBLOCK_ID"]; } else { $strTable = "b_iblock_element_prop_s" . $ar_ps["IBLOCK_ID"]; } } else { $strTable = "b_iblock_element_property"; } $arDelCache[$zr["IBLOCK_ID"]][$strTable][] = $ar_ps["ID"]; } } if ($arDelCache[$zr["IBLOCK_ID"]]) { foreach ($arDelCache[$zr["IBLOCK_ID"]] as $strTable => $arProps) { if (strncmp("b_iblock_element_prop_s", $strTable, 23) == 0) { $tableFields = $DB->GetTableFields($strTable); foreach ($arProps as $prop_id) { $strSql = "UPDATE " . $strTable . " SET PROPERTY_" . $prop_id . "=null"; if (isset($tableFields["DESCRIPTION_" . $prop_id])) { $strSql .= ",DESCRIPTION_" . $prop_id . "=null"; } $strSql .= " WHERE PROPERTY_" . $prop_id . "=" . $zr["ID"]; if (!$DB->Query($strSql)) { return false; } } } elseif (strncmp("b_iblock_element_prop_m", $strTable, 23) == 0) { $tableFields = $DB->GetTableFields(str_replace("prop_m", "prop_s", $strTable)); $strSql = "SELECT IBLOCK_PROPERTY_ID, IBLOCK_ELEMENT_ID FROM " . $strTable . " WHERE IBLOCK_PROPERTY_ID IN (" . implode(", ", $arProps) . ") AND VALUE_NUM=" . $zr["ID"]; $rs = $DB->Query($strSql); while ($ar = $rs->Fetch()) { $strSql = "\n\t\t\t\t\t\t\t\t\tUPDATE " . str_replace("prop_m", "prop_s", $strTable) . "\n\t\t\t\t\t\t\t\t\tSET PROPERTY_" . $ar["IBLOCK_PROPERTY_ID"] . "=null\n\t\t\t\t\t\t\t\t\t" . (isset($tableFields["DESCRIPTION_" . $ar["IBLOCK_PROPERTY_ID"]]) ? ",DESCRIPTION_" . $ar["IBLOCK_PROPERTY_ID"] . "=null" : "") . "\n\t\t\t\t\t\t\t\t\tWHERE IBLOCK_ELEMENT_ID = " . $ar["IBLOCK_ELEMENT_ID"] . "\n\t\t\t\t\t\t\t\t"; if (!$DB->Query($strSql)) { return false; } } $strSql = "DELETE FROM " . $strTable . " WHERE IBLOCK_PROPERTY_ID IN (" . implode(", ", $arProps) . ") AND VALUE_NUM=" . $zr["ID"]; if (!$DB->Query($strSql)) { return false; } } else { $strSql = "DELETE FROM " . $strTable . " WHERE IBLOCK_PROPERTY_ID IN (" . implode(", ", $arProps) . ") AND VALUE_NUM=" . $zr["ID"]; if (!$DB->Query($strSql)) { return false; } } } } if (!$DB->Query("DELETE FROM b_iblock_section_element WHERE IBLOCK_ELEMENT_ID = " . $elementId)) { return false; } $obIBlockElementRights = new CIBlockElementRights($zr["IBLOCK_ID"], $zr["ID"]); $obIBlockElementRights->DeleteAllRights(); $ipropTemplates = new \Bitrix\Iblock\InheritedProperty\ElementTemplates($zr["IBLOCK_ID"], $zr["ID"]); $ipropTemplates->delete(); if (IntVal($zr["WF_PARENT_ELEMENT_ID"]) <= 0 && $zr["WF_STATUS_ID"] == 1 && CModule::IncludeModule("search")) { CSearch::DeleteIndex("iblock", $elementId); } CIBlockElement::DeleteFile($zr["PREVIEW_PICTURE"], $zr["ID"], "PREVIEW", $zr["WF_PARENT_ELEMENT_ID"], $zr["IBLOCK_ID"]); CIBlockElement::DeleteFile($zr["DETAIL_PICTURE"], $zr["ID"], "DETAIL", $zr["WF_PARENT_ELEMENT_ID"], $zr["IBLOCK_ID"]); if (CModule::IncludeModule("workflow")) { $DB->Query("DELETE FROM b_workflow_move WHERE IBLOCK_ELEMENT_ID=" . $elementId); } $DB->Query("DELETE FROM b_iblock_element_lock WHERE IBLOCK_ELEMENT_ID=" . $elementId); $DB->Query("DELETE FROM b_rating_vote WHERE ENTITY_TYPE_ID = 'IBLOCK_ELEMENT' AND ENTITY_ID = " . $elementId); $DB->Query("DELETE FROM b_rating_voting WHERE ENTITY_TYPE_ID = 'IBLOCK_ELEMENT' AND ENTITY_ID = " . $elementId); if (!$DB->Query("DELETE FROM b_iblock_element WHERE ID=" . $elementId)) { return false; } if (isset(self::$elementIblock[$elementId])) { unset(self::$elementIblock[$elementId]); } \Bitrix\Iblock\PropertyIndex\Manager::deleteElementIndex($zr["IBLOCK_ID"], $piId); if (CModule::IncludeModule("bizproc")) { CBPDocument::OnDocumentDelete(array("iblock", "CIBlockDocument", $zr["ID"]), $arErrorsTmp); } foreach (GetModuleEvents("iblock", "OnAfterIBlockElementDelete", true) as $arEvent) { ExecuteModuleEventEx($arEvent, array($zr)); } CIBlock::clearIblockTagCache($zr['IBLOCK_ID']); unset($elementId); } } /************* QUOTA *************/ $_SESSION["SESS_RECOUNT_DB"] = "Y"; /************* QUOTA *************/ return true; }
function SetPropertyValues($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUES, $PROPERTY_CODE = false) { global $DB; global $BX_IBLOCK_PROP_CACHE; $ELEMENT_ID = intVal($ELEMENT_ID); $IBLOCK_ID = intval($IBLOCK_ID); if (!is_array($PROPERTY_VALUES)) $PROPERTY_VALUES = array($PROPERTY_VALUES); $uniq_flt = $IBLOCK_ID; $arFilter = array( "IBLOCK_ID" => $IBLOCK_ID, "CHECK_PERMISSIONS" => "N", ); if ($PROPERTY_CODE === false) { $arFilter["ACTIVE"] = "Y"; $uniq_flt .= "|ACTIVE:".$arFilter["ACTIVE"]; } elseif(intval($PROPERTY_CODE) > 0) { $arFilter["ID"] = intval($PROPERTY_CODE); $uniq_flt .= "|ID:".$arFilter["ID"]; } else { $arFilter["CODE"] = $PROPERTY_CODE; $uniq_flt .= "|CODE:".$arFilter["CODE"]; } if (!isset($BX_IBLOCK_PROP_CACHE[$IBLOCK_ID])) $BX_IBLOCK_PROP_CACHE[$IBLOCK_ID] = array(); if (!isset($BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt])) { $BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt] = array(); $db_prop = CIBlockProperty::GetList(array(), $arFilter); while($prop = $db_prop->Fetch()) { $BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt][] = $prop; } } $ar_prop = &$BX_IBLOCK_PROP_CACHE[$IBLOCK_ID][$uniq_flt]; reset($ar_prop); $bRecalcSections = false; //Read current property values from database $arDBProps = array(); if (CIBLock::GetArrayByID($IBLOCK_ID, "VERSION") == 2) { $rs = $DB->Query(" select * from b_iblock_element_prop_m".$IBLOCK_ID." where IBLOCK_ELEMENT_ID = ".$ELEMENT_ID." order by ID asc "); while ($ar = $rs->Fetch()) { $property_id = $ar["IBLOCK_PROPERTY_ID"]; if (!isset($arDBProps[$property_id])) $arDBProps[$property_id] = array(); $arDBProps[$property_id][$ar["ID"]] = $ar; } $rs = $DB->Query(" select * from b_iblock_element_prop_s".$IBLOCK_ID." where IBLOCK_ELEMENT_ID = ".$ELEMENT_ID." "); if ($ar = $rs->Fetch()) { foreach($ar_prop as $property) { $property_id = $property["ID"]; if( $property["MULTIPLE"] == "N" && isset($ar["PROPERTY_".$property_id]) && strlen($ar["PROPERTY_".$property_id]) ) { if (!isset($arDBProps[$property_id])) $arDBProps[$property_id] = array(); $arDBProps[$property_id][$pr["ID"]] = array( "ID" => $ELEMENT_ID.":".$property_id, "IBLOCK_PROPERTY_ID" => $property_id, "VALUE" => $ar["PROPERTY_".$property_id], "DESCRIPTION" => $ar["DESCRIPTION_".$property_id], ); } } } } else { $rs = $DB->Query(" select * from b_iblock_element_property where IBLOCK_ELEMENT_ID = ".$ELEMENT_ID." order by ID asc "); while ($ar = $rs->Fetch()) { $property_id = $ar["IBLOCK_PROPERTY_ID"]; if (!isset($arDBProps[$property_id])) $arDBProps[$property_id] = array(); $arDBProps[$property_id][$ar["ID"]] = $ar; } } $arFilesToDelete = array(); $arV2ClearCache = array(); foreach ($ar_prop as $prop) { if ($PROPERTY_CODE) { $PROP = $PROPERTY_VALUES; } else { if (strlen($prop["CODE"]) > 0 && array_key_exists($prop["CODE"], $PROPERTY_VALUES)) $PROP = $PROPERTY_VALUES[$prop["CODE"]]; else $PROP = $PROPERTY_VALUES[$prop["ID"]]; } if ( !is_array($PROP) || ( $prop["PROPERTY_TYPE"] == "F" && ( array_key_exists("tmp_name", $PROP) || array_key_exists("del", $PROP) ) ) || ( count($PROP) == 2 && array_key_exists("VALUE", $PROP) && array_key_exists("DESCRIPTION", $PROP) ) ) { $PROP = array($PROP); } if ($prop["USER_TYPE"] != "") { $arUserType = CIBlockProperty::GetUserType($prop["USER_TYPE"]); if (array_key_exists("ConvertToDB", $arUserType)) { foreach ($PROP as $key => $value) { if( !is_array($value) || !array_key_exists("VALUE", $value) ) { $value = array("VALUE"=>$value); } $PROP[$key] = call_user_func_array($arUserType["ConvertToDB"], array($prop, $value)); } } } if ($prop["VERSION"] == 2) { if ($prop["MULTIPLE"] == "Y") $strTable = "b_iblock_element_prop_m".$prop["IBLOCK_ID"]; else $strTable = "b_iblock_element_prop_s".$prop["IBLOCK_ID"]; } else { $strTable = "b_iblock_element_property"; } if ($prop["PROPERTY_TYPE"] == "L") { $DB->Query(CIBLockElement::DeletePropertySQL($prop, $ELEMENT_ID)); if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_".$prop["ID"]." = NULL" .self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) ; } $ids = "0"; foreach ($PROP as $key => $value) { if (is_array($value)) $value = intval($value["VALUE"]); else $value = intval($value); if ($value <= 0) continue; $ids .= ",".$value; if ($prop["MULTIPLE"] != "Y") break; } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query(" UPDATE b_iblock_element_prop_s".$prop["IBLOCK_ID"]." E ,b_iblock_property P ,b_iblock_property_enum PEN SET E.PROPERTY_".$prop["ID"]." = PEN.ID WHERE E.IBLOCK_ELEMENT_ID = ".$ELEMENT_ID." AND P.ID = ".$prop["ID"]." AND P.ID = PEN.PROPERTY_ID AND PEN.ID IN (".$ids.") "); } else { $DB->Query(" INSERT INTO ".$strTable." (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_ENUM) SELECT ".$ELEMENT_ID.", P.ID, PEN.ID, PEN.ID FROM b_iblock_property P ,b_iblock_property_enum PEN WHERE P.ID = ".$prop["ID"]." AND P.ID = PEN.PROPERTY_ID AND PEN.ID IN (".$ids.") "); } } elseif ($prop["PROPERTY_TYPE"] == "G") { $bRecalcSections = true; $DB->Query(CIBLockElement::DeletePropertySQL($prop, $ELEMENT_ID)); if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_".$prop["ID"]." = NULL" .self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) ; } $DB->Query(" DELETE FROM b_iblock_section_element WHERE ADDITIONAL_PROPERTY_ID = ".$prop["ID"]." AND IBLOCK_ELEMENT_ID = ".$ELEMENT_ID." "); $ids = "0"; foreach ($PROP as $key => $value) { if (is_array($value)) $value = intval($value["VALUE"]); else $value = intval($value); if ($value <= 0) continue; $ids .= ",".$value; if ($prop["MULTIPLE"] != "Y") break; } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query(" UPDATE b_iblock_element_prop_s".$prop["IBLOCK_ID"]." E ,b_iblock_property P ,b_iblock_section S SET E.PROPERTY_".$prop["ID"]." = S.ID ".self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"])." WHERE E.IBLOCK_ELEMENT_ID = ".$ELEMENT_ID." AND P.ID = ".$prop["ID"]." AND ( P.LINK_IBLOCK_ID IS NULL OR P.LINK_IBLOCK_ID = 0 OR S.IBLOCK_ID = P.LINK_IBLOCK_ID ) AND S.ID IN (".$ids.") "); } else { $DB->Query(" INSERT INTO ".$strTable." (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_NUM) SELECT ".$ELEMENT_ID.", P.ID, S.ID, S.ID FROM b_iblock_property P ,b_iblock_section S WHERE P.ID=".$prop["ID"]." AND ( P.LINK_IBLOCK_ID IS NULL OR P.LINK_IBLOCK_ID = 0 OR S.IBLOCK_ID = P.LINK_IBLOCK_ID ) AND S.ID IN (".$ids.") "); } $DB->Query(" INSERT INTO b_iblock_section_element (IBLOCK_ELEMENT_ID, IBLOCK_SECTION_ID, ADDITIONAL_PROPERTY_ID) SELECT ".$ELEMENT_ID.", S.ID, P.ID FROM b_iblock_property P ,b_iblock_section S WHERE P.ID = ".$prop["ID"]." AND ( P.LINK_IBLOCK_ID IS NULL OR P.LINK_IBLOCK_ID = 0 OR S.IBLOCK_ID = P.LINK_IBLOCK_ID ) AND S.ID IN (".$ids.") "); } elseif ($prop["PROPERTY_TYPE"] == "E") { $arWas = array(); if ($arDBProps[$prop["ID"]]) { foreach($arDBProps[$prop["ID"]] as $res) { $val = $PROP[$res["ID"]]; if (is_array($val)) { $val_desc = $val["DESCRIPTION"]; $val = $val["VALUE"]; } else { $val_desc = false; } if (isset($arWas[$val])) $val = ""; else $arWas[$val] = true; if (strlen($val) <= 0) //Delete property value { $DB->Query(CIBLockElement::DeletePropertySQL($prop, $ELEMENT_ID)); if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_".$prop["ID"]." = NULL" .self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) ; } } elseif ($res["VALUE"] !== $val) //Update property value { if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query(" UPDATE b_iblock_element_prop_s".$prop["IBLOCK_ID"]." SET PROPERTY_".$prop["ID"]." = '".$DB->ForSql($val)."' ".self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"], $val_desc)." WHERE IBLOCK_ELEMENT_ID = ".$ELEMENT_ID." "); } else { $DB->Query(" UPDATE ".$strTable." SET VALUE = '".$DB->ForSql($val)."' ,VALUE_NUM = ".CIBlock::roundDB($val)." ".($val_desc!==false ? ",DESCRIPTION = '".$DB->ForSql($val_desc, 255)."'" : "")." WHERE ID=".$res["ID"]." "); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_".$prop["ID"]." = NULL" .self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) ; } } unset($PROP[$res["ID"]]); } //foreach($arDBProps[$prop["ID"]] as $res) } foreach ($PROP as $val) { if (is_array($val)) { $val_desc = $val["DESCRIPTION"]; $val = $val["VALUE"]; } else { $val_desc = false; } if (isset($arWas[$val])) $val = ""; else $arWas[$val] = true; if (strlen($val) <= 0) continue; if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query(" UPDATE b_iblock_element_prop_s".$prop["IBLOCK_ID"]." SET PROPERTY_".$prop["ID"]." = '".$DB->ForSql($val)."' ".self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"], $val_desc)." WHERE IBLOCK_ELEMENT_ID=".$ELEMENT_ID." "); } else { $DB->Query(" INSERT INTO ".$strTable." (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_NUM".($val_desc!==false?", DESCRIPTION":"").") SELECT ".$ELEMENT_ID." ,P.ID ,'".$DB->ForSql($val)."' ,".CIBlock::roundDB($val)." ".($val_desc!==false?", '".$DB->ForSQL($val_desc, 255)."'":"")." FROM b_iblock_property P WHERE ID = ".IntVal($prop["ID"])." "); } if($prop["VERSION"]==2 && $prop["MULTIPLE"]=="Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_".$prop["ID"]." = NULL" .self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) ; } if ($prop["MULTIPLE"] != "Y") break; } //foreach($PROP as $value) } elseif ($prop["PROPERTY_TYPE"] == "F") { //We'll be adding values from the database into the tail //this values was not passed into API call. $orderedPROP = array_reverse($PROP, true); if ($arDBProps[$prop["ID"]]) { //Go from high ID to low foreach (array_reverse($arDBProps[$prop["ID"]], true) as $res) { //Preserve description from database if (strlen($res["DESCRIPTION"])) $description = $res["DESCRIPTION"]; else $description = false; if (!array_key_exists($res["ID"], $orderedPROP)) { $orderedPROP[$res["ID"]] = array( "VALUE" => $res["VALUE"], "DESCRIPTION" => $description, ); } else { $val = $orderedPROP[$res["ID"]]; if ( is_array($val) && !array_key_exists("tmp_name", $val) && !array_key_exists("del", $val) ) $val = $val["VALUE"]; //Check if no new file and no delete command if ( !strlen($val["tmp_name"]) && !strlen($val["del"]) ) //Overwrite with database value { //But save description from incoming value if (array_key_exists("description", $val)) $description = trim($val["description"]); $orderedPROP[$res["ID"]] = array( "VALUE" => $res["VALUE"], "DESCRIPTION" => $description, ); } } } } //Reverse the array and now lower ID is in the beginning $orderedPROP = array_reverse($orderedPROP, true); //Now delete from database all marked for deletion records if ($arDBProps[$prop["ID"]]) { foreach ($arDBProps[$prop["ID"]] as $res) { $val = $orderedPROP[$res["ID"]]; if ( is_array($val) && !array_key_exists("tmp_name", $val) && !array_key_exists("del", $val) ) { $val = $val["VALUE"]; } if (is_array($val) && strlen($val["del"])) { unset($orderedPROP[$res["ID"]]); $arFilesToDelete[] = array( "FILE_ID" => $res["VALUE"], "ELEMENT_ID" => $ELEMENT_ID, "IBLOCK_ID" => $prop["IBLOCK_ID"], ); } elseif ($prop["MULTIPLE"] != "Y") { //Delete all stored in database for replacement. $arFilesToDelete[] = array( "FILE_ID" => $res["VALUE"], "ELEMENT_ID" => $ELEMENT_ID, "IBLOCK_ID" => $prop["IBLOCK_ID"], ); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query(" UPDATE b_iblock_element_prop_s".$prop["IBLOCK_ID"]." SET PROPERTY_".$prop["ID"]." = null ".self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"])." WHERE IBLOCK_ELEMENT_ID = ".$ELEMENT_ID." "); } else { $DB->Query("DELETE FROM ".$strTable." WHERE ID = ".$res["ID"]); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_".$prop["ID"]." = NULL" .self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) ; } } //foreach($arDBProps[$prop["ID"]] as $res) } //Write new values into database in specified order foreach ($orderedPROP as $val) { if( is_array($val) && !array_key_exists("tmp_name", $val) ) { $val_desc = $val["DESCRIPTION"]; $val = $val["VALUE"]; } else { $val_desc = false; } if (is_array($val)) { $val["MODULE_ID"] = "iblock"; if ($val_desc !== false) $val["description"] = $val_desc; $val = CFile::SaveFile($val, "iblock"); } elseif ( $val > 0 && $val_desc !== false ) { CFile::UpdateDesc($val, $val_desc); } if (intval($val) <= 0) continue; if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query($s=" UPDATE b_iblock_element_prop_s".$prop["IBLOCK_ID"]." SET PROPERTY_".$prop["ID"]." = '".$DB->ForSql($val)."' ".self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"], $val_desc)." WHERE IBLOCK_ELEMENT_ID=".$ELEMENT_ID." "); } else { $DB->Query(" INSERT INTO ".$strTable." (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_NUM".($val_desc!==false?", DESCRIPTION":"").") SELECT ".$ELEMENT_ID." ,P.ID ,'".$DB->ForSql($val)."' ,".CIBlock::roundDB($val)." ".($val_desc!==false?", '".$DB->ForSQL($val_desc, 255)."'":"")." FROM b_iblock_property P WHERE ID = ".IntVal($prop["ID"])." "); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_".$prop["ID"]." = NULL" .self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) ; } if ($prop["MULTIPLE"] != "Y") break; } //foreach($PROP as $value) } else //if($prop["PROPERTY_TYPE"] == "S" || $prop["PROPERTY_TYPE"] == "N") { if ($arDBProps[$prop["ID"]]) { foreach ($arDBProps[$prop["ID"]] as $res) { $val = $PROP[$res["ID"]]; if (is_array($val)) { $val_desc = $val["DESCRIPTION"]; $val = $val["VALUE"]; } else { $val_desc = false; } if (strlen($val) <= 0) { if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query(" UPDATE b_iblock_element_prop_s".$prop["IBLOCK_ID"]." SET PROPERTY_".$prop["ID"]." = null ".self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"])." WHERE IBLOCK_ELEMENT_ID=".$ELEMENT_ID." "); } else { $DB->Query("DELETE FROM ".$strTable." WHERE ID=".$res["ID"]); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_".$prop["ID"]." = NULL" .self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) ; } } else { if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { if($prop["PROPERTY_TYPE"]=="N") $val = CIBlock::roundDB($val); $DB->Query(" UPDATE b_iblock_element_prop_s".$prop["IBLOCK_ID"]." SET PROPERTY_".$prop["ID"]."='".$DB->ForSql($val)."' ".self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"], $val_desc)." WHERE IBLOCK_ELEMENT_ID=".$ELEMENT_ID." "); } else { $DB->Query(" UPDATE ".$strTable." SET VALUE='".$DB->ForSql($val)."' ,VALUE_NUM=".CIBlock::roundDB($val)." ".($val_desc!==false ? ",DESCRIPTION='".$DB->ForSql($val_desc, 255)."'" : "")." WHERE ID=".$res["ID"]." "); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_".$prop["ID"]." = NULL" .self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) ; } } unset($PROP[$res["ID"]]); } //foreach ($arDBProps[$prop["ID"]] as $res) } foreach($PROP as $val) { if(is_array($val) && !is_set($val, "tmp_name")) { $val_desc = $val["DESCRIPTION"]; $val = $val["VALUE"]; } else { $val_desc = false; } if (strlen($val) <= 0) continue; if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "N") { $DB->Query(" UPDATE b_iblock_element_prop_s".$prop["IBLOCK_ID"]." SET PROPERTY_".$prop["ID"]." = '".$DB->ForSql($val)."' ".self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"], $val_desc)." WHERE IBLOCK_ELEMENT_ID=".$ELEMENT_ID." "); } else { $DB->Query(" INSERT INTO ".$strTable." (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE, VALUE_NUM".($val_desc!==false?", DESCRIPTION":"").") SELECT ".$ELEMENT_ID." ,P.ID ,'".$DB->ForSql($val)."' ,".CIBlock::roundDB($val)." ".($val_desc!==false?", '".$DB->ForSQL($val_desc, 255)."'":"")." FROM b_iblock_property P WHERE ID = ".IntVal($prop["ID"])." "); } if ($prop["VERSION"] == 2 && $prop["MULTIPLE"] == "Y") { $arV2ClearCache[$prop["ID"]] = "PROPERTY_".$prop["ID"]." = NULL" .self::__GetDescriptionUpdateSql($prop["IBLOCK_ID"], $prop["ID"]) ; } if ($prop["MULTIPLE"] != "Y") break; } //foreach($PROP as $value) } //if($prop["PROPERTY_TYPE"]=="F") } if ($arV2ClearCache) { $DB->Query(" UPDATE b_iblock_element_prop_s".$IBLOCK_ID." SET ".implode(",", $arV2ClearCache)." WHERE IBLOCK_ELEMENT_ID = ".$ELEMENT_ID." "); } foreach ($arFilesToDelete as $deleteTask) { CIBLockElement::DeleteFile( $deleteTask["FILE_ID"], false, "PROPERTY", $deleteTask["ELEMENT_ID"], $deleteTask["IBLOCK_ID"] ); } if($bRecalcSections) CIBlockElement::RecalcSections($ELEMENT_ID); /****************************** QUOTA ******************************/ $_SESSION["SESS_RECOUNT_DB"] = "Y"; /****************************** QUOTA ******************************/ foreach (GetModuleEvents("iblock", "OnAfterIBlockElementSetPropertyValues", true) as $arEvent) ExecuteModuleEventEx($arEvent, array($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUES, $PROPERTY_CODE)); }