• Модуль: tasks
  • Путь к файлу: ~/bitrix/modules/tasks/classes/general/task.php
  • Класс: CTasks
  • Вызов: CTasks::FilterCreate
static function FilterCreate($fname, $vals, $type, &$bFullJoin, $cOperationType = false, $bSkipEmpty = true)
{
	global $DB;
	if (!is_array($vals))
	{
		$vals = [$vals];
	}
	else
	{
		$vals = array_unique(array_values($vals));
	}

	if (count($vals) < 1)
	{
		return "";
	}

	if (is_bool($cOperationType))
	{
		if ($cOperationType === true)
		{
			$cOperationType = "N";
		}
		else
		{
			$cOperationType = "E";
		}
	}

	if ($cOperationType == "G")
	{
		$strOperation = ">";
	}
	elseif ($cOperationType == "GE")
	{
		$strOperation = ">=";
	}
	elseif ($cOperationType == "LE")
	{
		$strOperation = "<=";
	}
	elseif ($cOperationType == "L")
	{
		$strOperation = "<";
	}
	elseif ($cOperationType === "NI")
	{
		$strOperation = "!=";
	}
	else
	{
		$strOperation = "=";
	}

	$bFullJoin = false;
	$bWasLeftJoin = false;

	// special case for array of number
	if ($type === 'number' && is_array($vals) && count($vals) > 1 && count($vals) < 80)
	{
		$vals = implode(', ', array_unique(array_map('intval', $vals)));

		$res = $fname . ' ' . ($cOperationType == 'N' ? 'not' : '') . ' in (' . $vals . ')';

		// INNER JOIN in this case
		if ($cOperationType != "N")
		{
			$bFullJoin = true;
		}

		return $res;
	}

	$res = [];

	foreach ($vals as $key => $val)
	{
		if (($type === 'number') && !$val)
		{
			$val = 0;
		}

		if (!$bSkipEmpty || $val === 0 || $val <> '' || (is_bool($val) && $val === false))
		{
			switch ($type)
			{
				case "string_equal":
					if ($val == '')
					{
						$res[] = ($cOperationType == "N" ? "NOT" : "") .
							"(" .
							$fname .
							" IS NULL OR " .
							$DB->Length($fname) .
							"<=0)";
					}
					else
					{
						$res[] = "(" .
							($cOperationType == "N" ? " " . $fname . " IS NULL OR NOT (" : "") .
							$fname .
							$strOperation .
							"'" .
							$DB->ForSql($val) .
							"'" .
							($cOperationType == "N" ? ")" : "") .
							")";
					}
					break;

				case "string":
					if ($cOperationType == "?")
					{
						if ($val === 0 || $val <> '')
						{
							$res[] = GetFilterQuery($fname, $val, "Y", [], "N");
						}
					}
					elseif ($cOperationType == "S")
					{
						$res[] = "(UPPER(" . $fname . ") LIKE UPPER('%" . $DB->ForSqlLike($val) . "%'))";
					}
					elseif ($cOperationType == "NS")
					{
						$res[] = "(UPPER(" . $fname . ") NOT LIKE UPPER('%" . $DB->ForSqlLike($val) . "%'))";
					}
					elseif ($cOperationType == "FTL")
					{
						$sqlWhere = new CSQLWhere();
						$res[] = $sqlWhere->matchLike($fname, $val);
					}
					elseif ($val == '')
					{
						$res[] = ($cOperationType == "N" ? "NOT" : "") .
							"(" .
							$fname .
							" IS NULL OR " .
							$DB->Length($fname) .
							"<=0)";
					}
					else
					{
						if ($strOperation == "=")
						{
							$res[] = "(" .
								($cOperationType == "N" ? " " . $fname . " IS NULL OR NOT (" : "") .
								($fname .
									" " .
									($strOperation ==
									"="
										? "LIKE"
										: $strOperation) .
									" '" .
									$DB->ForSqlLike(
										$val
									) .
									"'") .
								($cOperationType == "N" ? ")" : "") .
								")";
						}
						else
						{
							$res[] = "(" .
								($cOperationType == "N" ? " " . $fname . " IS NULL OR NOT (" : "") .
								($fname .
									" " .
									$strOperation .
									" '" .
									$DB->ForSql($val) .
									"'") .
								($cOperationType == "N" ? ")" : "") .
								")";
						}
					}
					break;
				case "fulltext":
					echo '';
					if ($cOperationType == "FT" || $cOperationType == "FTI")
					{
						$sqlWhere = new CSQLWhere();
						$res[] = $sqlWhere->match($fname, $val, $cOperationType == "FT");
					}
					elseif ($cOperationType == "FTL")
					{
						$sqlWhere = new CSQLWhere();
						$res[] = $sqlWhere->matchLike($fname, $val);
					}
					elseif ($cOperationType == "?")
					{
						if ($val === 0 || $val <> '')
						{
							$sr = GetFilterQuery(
								$fname,
								$val,
								"Y",
								[],
								($fname == "BE.SEARCHABLE_CONTENT" || $fname == "BE.DETAIL_TEXT" ? "Y" : "N")
							);
							if ($sr != "0")
							{
								$res[] = $sr;
							}
						}
					}
					elseif (
						($cOperationType == "B" || $cOperationType == "NB") && is_array($val)
						&& count($val)
						== 2
					)
					{
						$res[] = ($cOperationType == "NB" ? " " . $fname . " IS NULL OR NOT " : "") .
							"(" .
							CIBlock::_Upper($fname) .
							" " .
							$strOperation[0] .
							" '" .
							CIBlock::_Upper($DB->ForSql($val[0])) .
							"' " .
							$strOperation[1] .
							" '" .
							CIBlock::_Upper($DB->ForSql($val[1])) .
							"')";
					}
					elseif ($cOperationType == "S" || $cOperationType == "NS")
					{
						$res[] = ($cOperationType == "NS" ? " " . $fname . " IS NULL OR NOT " : "") .
							"(" .
							CIBlock::_Upper($fname) .
							" LIKE " .
							CIBlock::_Upper("'%" . CIBlock::ForLIKE($val) . "%'") .
							")";
					}
					else
					{
						if ($val == '')
						{
							$res[] = ($bNegative ? "NOT" : "")
								. "("
								. $fname
								. " IS NULL OR "
								. $DB->Length($fname)
								. "<=0)";
						}
						elseif ($strOperation == "=" && $cOperationType != "I" && $cOperationType != "NI")
						{
							$res[] = ($cOperationType == "N" ? " " . $fname . " IS NULL OR NOT " : "") .
								"(" .
								($fname .
									" LIKE '" .
									$DB->ForSqlLike($val) .
									"'") .
								")";
						}
						else
						{
							$res[] = ($bNegative ? " " . $fname . " IS NULL OR NOT " : "") .
								"(" .
								($fname .
									" " .
									$strOperation .
									" '" .
									$DB->ForSql($val) .
									"'") .
								")";
						}
					}
					break;
				case "date":
					if ($val == '')
					{
						$res[] = ($cOperationType == "N" ? "NOT" : "") . "(" . $fname . " IS NULL)";
					}
					else
					{
						$res[] = "(" .
							($cOperationType == "N" ? " " . $fname . " IS NULL OR NOT (" : "") .
							$fname .
							" " .
							$strOperation .
							" " .
							$val .
							"" .
							($cOperationType == "N" ? ")" : "") .
							")";
					}
					break;

				case "number":
					$isOperationTypeN = $cOperationType === 'N';
					if ($vals[$key] === false || strlen($val) <= 0)
					{
						$res[] = ($isOperationTypeN ? 'NOT' : '') . "({$fname} IS NULL)";
					}
					else
					{
						$res[] = "("
							. ($isOperationTypeN ? "{$fname} IS NULL OR NOT (" : "")
							. "{$fname} {$strOperation} '" . DoubleVal($val) . "'"
							. ($isOperationTypeN ? ")" : "")
							. ")";
					}
					break;

				case "number_wo_nulls":
					$res[] = "(" .
						($cOperationType == "N" ? "NOT (" : "") .
						$fname .
						" " .
						$strOperation .
						" " .
						DoubleVal($val) .
						($cOperationType == "N" ? ")" : "") .
						")";
					break;

				case "null_or_zero":
					if ($cOperationType == "N")
					{
						$res[] = "((" . $fname . " IS NOT NULL) AND (" . $fname . " != 0))";
					}
					else
					{
						$res[] = "((" . $fname . " IS NULL) OR (" . $fname . " = 0))";
					}

					break;

				case "left_existence":

					if ($strOperation != '=')
					{
						CTaskAssert::logError('Operation type not supported for ' . $fname . ': ' . $strOperation);
					}
					elseif ($val != 'Y' && $val != 'N' && 0)
					{
						CTaskAssert::logError('Filter value not supported for ' . $fname . ': ' . $val);
					}
					else
					{
						$otNot = $cOperationType == "N";

						if (($val == 'Y' && !$otNot) || ($val == 'N' && $otNot))
						{
							$res[] = "(" . $fname . " IS NOT NULL)";
						}
						else
						{
							$res[] = "(" . $fname . " IS NULL)";
						}
					}

					break;

				case 'reference':

					$val = trim($val);

					if (preg_match('#^[a-z0-9_]+(.{1}[a-z0-9_]+)*$#i', $val))
					{
						if ($cOperationType === 'E')
						{
							$res[] = '(' . $fname . ' = ' . $DB->ForSql($val) . ')';
						}
						elseif ($cOperationType === 'N')
						{
							$res[] = '(' . $fname . ' != ' . $DB->ForSql($val) . ')';
						}
						elseif ($cOperationType === 'L')
						{
							$res[] = '(' . $fname . ' < ' . $DB->ForSql($val) . ')';
						}
						elseif ($cOperationType === 'G')
						{
							$res[] = '(' . $fname . ' > ' . $DB->ForSql($val) . ')';
						}
						else
						{
							CTaskAssert::logError('[0xcf017223] Operation type not supported: ' . $cOperationType);
						}
					}
					else
					{
						CTaskAssert::logError("Bad reference: " . $fname . " => '" . $val . "'");
					}

					break;
			}

			// INNER JOIN in this case
			if (($val === 0 || $val <> '') && $cOperationType != "N")
			{
				$bFullJoin = true;
			}
			else
			{
				$bWasLeftJoin = true;
			}
		}
	}

	$strResult = "";
	for ($i = 0, $resCnt = count($res); $i < $resCnt; $i++)
	{
		if ($i > 0)
		{
			$strResult .= ($cOperationType == "N" ? " AND " : " OR ");
		}
		$strResult .= $res[$i];
	}

	if (count($res) > 1)
	{
		$strResult = "(" . $strResult . ")";
	}

	if ($bFullJoin && $bWasLeftJoin && $cOperationType != "N")
	{
		$bFullJoin = false;
	}

	return $strResult;
}