public function CheckFields(&$arFields, $ID=false, $bCheckDiskQuota=true)
{
global $DB, $APPLICATION, $USER;
$this->LAST_ERROR = "";
$APPLICATION->ResetException();
if($ID===false)
{
$db_events = GetModuleEvents("iblock", "OnStartIBlockElementAdd", true);
}
else
{
$arFields["ID"] = $ID;
$db_events = GetModuleEvents("iblock", "OnStartIBlockElementUpdate", true);
}
foreach ($db_events as $arEvent)
{
$bEventRes = ExecuteModuleEventEx($arEvent, array(&$arFields));
if($bEventRes===false)
break;
}
if(($ID===false || array_key_exists("NAME", $arFields)) && (string)$arFields["NAME"] === '')
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_ELEMENT_NAME")."
";
if(
isset($arFields["ACTIVE_FROM"])
&& $arFields["ACTIVE_FROM"] != ''
&& !$DB->IsDate($arFields["ACTIVE_FROM"], false, LANG, "FULL")
)
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_ACTIVE_FROM")."
";
if(
isset($arFields["ACTIVE_TO"])
&& $arFields["ACTIVE_TO"] != ''
&& !$DB->IsDate($arFields["ACTIVE_TO"], false, LANG, "FULL")
)
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_ACTIVE_TO")."
";
if(is_set($arFields, "PREVIEW_PICTURE"))
{
if(
is_array($arFields["PREVIEW_PICTURE"])
&& array_key_exists("bucket", $arFields["PREVIEW_PICTURE"])
&& is_object($arFields["PREVIEW_PICTURE"]["bucket"])
)
{
//This is trusted image from xml import
}
elseif(is_array($arFields["PREVIEW_PICTURE"]))
{
$error = CFile::CheckImageFile($arFields["PREVIEW_PICTURE"]);
if($error <> '')
$this->LAST_ERROR .= $error."
";
elseif(($error = CFile::checkForDb($arFields, "PREVIEW_PICTURE")) !== "")
$this->LAST_ERROR .= GetMessage("IBLOCK_ERR_PREVIEW_PICTURE")."
".$error."
";
}
elseif((int)$arFields["PREVIEW_PICTURE"] > 0)
{
if(
(int)$arFields["WF_PARENT_ELEMENT_ID"] <= 0
|| CIBlockElement::DeleteFile(
$arFields["PREVIEW_PICTURE"],
$ID,
"PREVIEW",
(int)$arFields["WF_PARENT_ELEMENT_ID"],
$arFields["IBLOCK_ID"],
true
) <= 0
)
{
$this->LAST_ERROR .= GetMessage("IBLOCK_ERR_PREVIEW_PICTURE")."
";
}
}
}
if(is_set($arFields, "DETAIL_PICTURE"))
{
if(
is_array($arFields["DETAIL_PICTURE"])
&& array_key_exists("bucket", $arFields["DETAIL_PICTURE"])
&& is_object($arFields["DETAIL_PICTURE"]["bucket"])
)
{
//This is trusted image from xml import
}
elseif(is_array($arFields["DETAIL_PICTURE"]))
{
$error = CFile::CheckImageFile($arFields["DETAIL_PICTURE"]);
if($error <> '')
$this->LAST_ERROR .= $error."
";
elseif(($error = CFile::checkForDb($arFields, "DETAIL_PICTURE")) !== "")
$this->LAST_ERROR .= GetMessage("IBLOCK_ERR_DETAIL_PICTURE")."
".$error."
";
}
elseif((int)$arFields["DETAIL_PICTURE"] > 0)
{
if(
(int)($arFields["WF_PARENT_ELEMENT_ID"]) <= 0
|| CIBlockElement::DeleteFile(
$arFields["DETAIL_PICTURE"],
$ID,
"DETAIL",
(int)$arFields["WF_PARENT_ELEMENT_ID"],
$arFields["IBLOCK_ID"],
true
) <= 0
)
{
$this->LAST_ERROR .= GetMessage("IBLOCK_ERR_DETAIL_PICTURE")."
";
}
}
}
if(array_key_exists("TAGS", $arFields) && CModule::IncludeModule('search'))
{
$arFields["TAGS"] = implode(", ", tags_prepare($arFields["TAGS"]));
}
if($ID===false && !is_set($arFields, "IBLOCK_ID"))
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_BLOCK_ID")."
";
//Find out IBLOCK_ID from fields or from element
$IBLOCK_ID = (int)($arFields["IBLOCK_ID"] ?? 0);
if($IBLOCK_ID <= 0)
{
$IBLOCK_ID = 0;
$res = $DB->Query("SELECT IBLOCK_ID FROM b_iblock_element WHERE ID=".intval($ID));
if($ar = $res->Fetch())
$IBLOCK_ID = (int)$ar["IBLOCK_ID"];
}
//Read iblock metadata
static $IBLOCK_CACHE = array();
if(!isset($IBLOCK_CACHE[$IBLOCK_ID]))
{
if($IBLOCK_ID > 0)
$IBLOCK_CACHE[$IBLOCK_ID] = CIBlock::GetArrayByID($IBLOCK_ID);
else
$IBLOCK_CACHE[$IBLOCK_ID] = false;
}
if($IBLOCK_CACHE[$IBLOCK_ID])
$arFields["IBLOCK_ID"] = $IBLOCK_ID;
else
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_BLOCK_ID")."
";
if (is_set($arFields,'IBLOCK_SECTION') && !empty($arFields['IBLOCK_SECTION']))
{
if (!is_array($arFields['IBLOCK_SECTION']))
$arFields['IBLOCK_SECTION'] = array($arFields['IBLOCK_SECTION']);
$arFields['IBLOCK_SECTION'] = array_filter($arFields['IBLOCK_SECTION']);
}
if($IBLOCK_CACHE[$IBLOCK_ID])
{
$ar = $IBLOCK_CACHE[$IBLOCK_ID]["FIELDS"];
if(is_array($ar))
{
$WF_PARENT_ELEMENT_ID = (int)($arFields["WF_PARENT_ELEMENT_ID"] ?? 0);
if(
(
$WF_PARENT_ELEMENT_ID == 0
|| $WF_PARENT_ELEMENT_ID == (int)$ID
)
&& array_key_exists("CODE", $arFields)
&& $arFields["CODE"] <> ''
&& is_array($ar["CODE"]["DEFAULT_VALUE"])
&& $ar["CODE"]["DEFAULT_VALUE"]["UNIQUE"] == "Y"
)
{
$res = $DB->Query("
SELECT ID
FROM b_iblock_element
WHERE IBLOCK_ID = ".$IBLOCK_ID."
AND CODE = '".$DB->ForSQL($arFields["CODE"])."'
AND WF_PARENT_ELEMENT_ID IS NULL
AND ID <> ".(int)$ID
);
if($res->Fetch())
$this->LAST_ERROR .= GetMessage("IBLOCK_DUP_ELEMENT_CODE")."
";
}
$arOldElement = false;
foreach($ar as $FIELD_ID => $field)
{
if(preg_match("/^(SECTION_|LOG_)/", $FIELD_ID))
continue;
if($field["IS_REQUIRED"] === "Y")
{
switch($FIELD_ID)
{
case "NAME":
case "ACTIVE":
case "PREVIEW_TEXT_TYPE":
case "DETAIL_TEXT_TYPE":
case "SORT":
//We should never check for this fields
break;
case "IBLOCK_SECTION":
if($ID===false || array_key_exists($FIELD_ID, $arFields))
{
$sum = 0;
if(is_array($arFields[$FIELD_ID]))
{
foreach($arFields[$FIELD_ID] as $k => $v)
if(intval($v) > 0)
$sum += intval($v);
}
else
{
$sum = intval($arFields[$FIELD_ID]);
}
if($sum <= 0)
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."
";
}
break;
case "PREVIEW_PICTURE":
case "DETAIL_PICTURE":
if($ID !== false && !$arOldElement)
{
$rs = $DB->Query("SELECT PREVIEW_PICTURE, DETAIL_PICTURE from b_iblock_element WHERE ID = ".intval($ID));
$arOldElement = $rs->Fetch();
}
if($arOldElement && $arOldElement[$FIELD_ID] > 0)
{//There was an picture so just check that it is not deleted
if(
array_key_exists($FIELD_ID, $arFields)
&& is_array($arFields[$FIELD_ID])
&& $arFields[$FIELD_ID]["del"] === "Y"
)
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."
";
}
else
{//There was NO picture so it MUST be present
if(!array_key_exists($FIELD_ID, $arFields))
{
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."
";
}
elseif(is_array($arFields[$FIELD_ID]))
{
if(
$arFields[$FIELD_ID]["del"] === "Y"
|| (array_key_exists("error", $arFields[$FIELD_ID]) && $arFields[$FIELD_ID]["error"] !== 0)
|| $arFields[$FIELD_ID]["size"] <= 0
)
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."
";
}
else
{
if(intval($arFields[$FIELD_ID]) <= 0)
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."
";
}
}
break;
case "XML_ID":
if ($ID !== false && array_key_exists($FIELD_ID, $arFields))
{
$val = $arFields[$FIELD_ID];
if($val == '')
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."
";
}
break;
default:
if($ID===false || array_key_exists($FIELD_ID, $arFields))
{
if(is_array($arFields[$FIELD_ID]))
$val = implode("", $arFields[$FIELD_ID]);
else
$val = $arFields[$FIELD_ID];
if($val == '')
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_FIELD", array("#FIELD_NAME#" => $field["NAME"]))."
";
}
break;
}
}
}
}
}
if(
array_key_exists("PROPERTY_VALUES", $arFields)
&& is_array($arFields["PROPERTY_VALUES"])
//&& intval($arFields["WF_PARENT_ELEMENT_ID"]) <= 0 //
)
{
//First "normalize" properties to form:
//$arFields["PROPERTY_VALUES"][][] => $value
$arProperties = array();
foreach($arFields["PROPERTY_VALUES"] as $key => $property_values)
{
$arProperties[$key] = array();
if(is_array($property_values)) //This is multiple values
{
if(array_key_exists("VALUE", $property_values)) //Or single "complex" value
{
$arProperties[$key][] = $property_values["VALUE"];
}
elseif(array_key_exists("tmp_name", $property_values)) //Or single file value
{
$arProperties[$key][] = $property_values;
}
else //true multiple
{
foreach($property_values as $key2 => $property_value)
{
if(is_array($property_value) && array_key_exists("VALUE", $property_value)) //each of these may be "complex"
$arProperties[$key][] = $property_value["VALUE"];
else //or simple
$arProperties[$key][] = $property_value;
}
}
}
else //just one simple value
{
$arProperties[$key][] = $property_values;
}
}
foreach($arProperties as $key => $property_values)
{
$arProperty = CIBlockProperty::GetPropertyArray($key, $IBLOCK_ID);
if($arProperty["USER_TYPE"] != "")
$arUserType = CIBlockProperty::GetUserType($arProperty["USER_TYPE"]);
else
$arUserType = array();
if(array_key_exists("CheckFields", $arUserType))
{
foreach($property_values as $key2 => $property_value)
{
$arError = call_user_func_array($arUserType["CheckFields"],array($arProperty ,array("VALUE"=>$property_value)));
if(is_array($arError))
foreach($arError as $err_mess)
$this->LAST_ERROR .= $err_mess."
";
}
}
//Files check
$bError = false;
if(
$arProperty["IS_REQUIRED"] == "Y"
&& $arProperty['PROPERTY_TYPE'] == 'F'
)
{
//New element
if($ID===false)
{
$bError = true;
foreach($property_values as $key2 => $property_value)
{
if(
is_array($property_value)
&& array_key_exists("tmp_name", $property_value)
&& array_key_exists("size", $property_value)
)
{
if($property_value['size'] > 0)
{
$bError = false;
break;
}
}
elseif(intval($property_value) > 0)
{//This is history copy of the file
$bError = false;
break;
}
}
}
else
{
$dbProperty = CIBlockElement::GetProperty(
$arProperty["IBLOCK_ID"],
$ID,
"sort", "asc",
array(
"ID" => $arProperty["ORIG_ID"],
"EMPTY" => "N",
)
);
$bCount = 0;
while ($a=$dbProperty->Fetch())
{
if ($a["VALUE"] > 0)
$bCount++;
}
foreach($property_values as $key2 => $property_value)
{
if(is_array($property_value))
{
if ($property_value['size'] > 0)
{
$bCount++;
break;
}
elseif ($property_value['del'] == 'Y')
{
$bCount--;
}
}
elseif(intval($property_value) > 0)
{//This is history copy of the file
$bCount++;
break;
}
}
$bError = $bCount <= 0;
}
}
if(
$arProperty["IS_REQUIRED"] == "Y"
&& $arProperty['PROPERTY_TYPE'] != 'F'
)
{
$len = 0;
foreach($property_values as $key2 => $property_value)
{
if(array_key_exists("GetLength", $arUserType))
$len += call_user_func_array($arUserType["GetLength"], array($arProperty, array("VALUE" => $property_value)));
else
$len += mb_strlen($property_value);
if($len > 0)
break;
}
$bError = $len <= 0;
}
if ($bError)
$this->LAST_ERROR .= GetMessage("IBLOCK_BAD_PROPERTY", array("#PROPERTY#" => $arProperty["NAME"]))."
";
// check file properties for correctness
if($arProperty['PROPERTY_TYPE'] == 'F')
{
$bImageOnly = False;
$arImageExtentions = explode(",", mb_strtoupper(CFile::GetImageExtensions()));
if($arProperty["FILE_TYPE"] <> '')
{
$bImageOnly = True;
$arAvailTypes = explode(",", mb_strtoupper($arProperty["FILE_TYPE"]));
foreach($arAvailTypes as $avail_type)
{
if(!in_array(trim($avail_type), $arImageExtentions))
{
$bImageOnly = False;
break;
}
}
}
foreach($property_values as $key2 => $property_value)
{
if(
!is_array($property_value)
&& (int)$property_value > 0
&& isset($arFields['WF_PARENT_ELEMENT_ID'])
&& (int)$arFields['WF_PARENT_ELEMENT_ID'] > 0
)
{
if (CIBlockElement::DeleteFile($property_value, $ID, "PROPERTY",
(int)$arFields["WF_PARENT_ELEMENT_ID"], $arFields["IBLOCK_ID"], true) <= 0)
{
$this->LAST_ERROR .= GetMessage("IBLOCK_ERR_FILE_PROPERTY")."
";
}
}
elseif(is_array($property_value))
{
if (
array_key_exists('bucket', $property_value)
&& is_object($property_value["bucket"])
)
{
//This is trusted image from xml import
$error = "";
}
else
{
if($bImageOnly)
$error = CFile::CheckImageFile($property_value);
else
$error = CFile::CheckFile($property_value, 0, false, $arProperty["FILE_TYPE"]);
}
//For user without edit php permissions
//we allow only pictures upload
if(!is_object($USER) || !$USER->IsAdmin())
{
if(HasScriptExtension($property_value["name"]))
{
$error = GetMessage("FILE_BAD_TYPE")." (".$property_value["name"].").";
}
}
if ($error <> '')
$this->LAST_ERROR .= $error."
";
}
}
}
}
}
$APPLICATION->ResetException();
if($ID===false)
$db_events = GetModuleEvents("iblock", "OnBeforeIBlockElementAdd", true);
else
{
$arFields["ID"] = $ID;
$db_events = GetModuleEvents("iblock", "OnBeforeIBlockElementUpdate", true);
}
foreach($db_events as $arEvent)
{
$bEventRes = ExecuteModuleEventEx($arEvent, array(&$arFields));
if($bEventRes===false)
{
if($err = $APPLICATION->GetException())
$this->LAST_ERROR .= $err->GetString()."
";
else
{
$APPLICATION->ThrowException("Unknown error");
$this->LAST_ERROR .= "Unknown error.
";
}
break;
}
}
/****************************** QUOTA ******************************/
if(
$bCheckDiskQuota
&& empty($this->LAST_ERROR)
&& (COption::GetOptionInt("main", "disk_space") > 0)
)
{
$quota = new CDiskQuota();
if(!$quota->checkDiskQuota($arFields))
$this->LAST_ERROR = $quota->LAST_ERROR;
}
/****************************** QUOTA ******************************/
if(!empty($this->LAST_ERROR))
return false;
return true;
}