403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/main/lib/orm/annotations/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/main/lib/orm/annotations/annotationtrait.php
<?php

namespace Bitrix\Main\ORM\Annotations;

use Bitrix\Main\Authentication\Context;
use Bitrix\Main\DB\SqlExpression;
use Bitrix\Main\Loader;
use Bitrix\Main\ORM\Data\AddResult;
use Bitrix\Main\ORM\Data\DataManager;
use Bitrix\Main\ORM\Data\Result;
use Bitrix\Main\ORM\Data\UpdateResult;
use Bitrix\Main\ORM\Entity;
use Bitrix\Main\ORM\Fields\ExpressionField;
use Bitrix\Main\ORM\Fields\FieldTypeMask;
use Bitrix\Main\ORM\Fields\Relations\ManyToMany;
use Bitrix\Main\ORM\Fields\Relations\OneToMany;
use Bitrix\Main\ORM\Fields\Relations\Reference;
use Bitrix\Main\ORM\Fields\ScalarField;
use Bitrix\Main\ORM\Fields\UserTypeField;
use Bitrix\Main\ORM\Objectify\Collection;
use Bitrix\Main\ORM\Objectify\State;
use Bitrix\Main\ORM\Query\Query;
use Bitrix\Main\Text\StringHelper;
use Bitrix\Main\Type\Dictionary;

/**
 * Bitrix Framework
 * @package    bitrix
 * @subpackage main
 * @copyright  2001-2018 Bitrix
 */

trait AnnotationTrait
{
	/**
	 * @param Entity $entity
	 * @param false  $separateTable
	 *
	 * @return array|string
	 */
	public static function annotateEntity(Entity $entity, $ufOnly = false, $separateTable = false)
	{
		$entityNamespace = trim($entity->getNamespace(), '\\');
		$dataClass = $entity->getDataClass();

		$objectClass = $entity->getObjectClass();
		$objectClassName = $entity->getObjectClassName();
		$objectDefaultClassName = Entity::getDefaultObjectClassName($entity->getName());

		$collectionClass = $entity->getCollectionClass();
		$collectionClassName = $entity->getCollectionClassName();
		$collectionDefaultClassName = Entity::getDefaultCollectionClassName($entity->getName());

		$code = [];
		$objectCode = [];
		$collectionCode = [];

		$code[] = "namespace {$entityNamespace} {"; // start namespace
		$code[] = "\t/**"; // start class annotations
		$code[] = "\t * {$objectClassName}";
		$code[] = "\t * @see {$dataClass}";
		$code[] = "\t *";
		$code[] = "\t * Custom methods:";
		$code[] = "\t * ---------------";
		$code[] = "\t *";

		$exceptions = [];

		foreach ($entity->getFields() as $field)
		{
			$objectFieldCode = [];
			$collectionFieldCode = [];

			if ($ufOnly && !($field instanceof UserTypeField))
			{
				continue;
			}

			try
			{
				if ($field instanceof ScalarField)
				{
					[$objectFieldCode, $collectionFieldCode] = static::annotateScalarField($field);
				}
				elseif ($field instanceof UserTypeField)
				{
					[$objectFieldCode, $collectionFieldCode] = static::annotateUserType($field);
				}
				elseif ($field instanceof ExpressionField)
				{
					[$objectFieldCode, $collectionFieldCode] = static::annotateExpression($field);
				}
				elseif ($field instanceof Reference)
				{
					[$objectFieldCode, $collectionFieldCode] = static::annotateReference($field);
				}
				elseif ($field instanceof OneToMany)
				{
					[$objectFieldCode, $collectionFieldCode] = static::annotateOneToMany($field);
				}
				elseif ($field instanceof ManyToMany)
				{
					[$objectFieldCode, $collectionFieldCode] = static::annotateManyToMany($field);
				}

				$objectCode = array_merge($objectCode, $objectFieldCode);
				$collectionCode = array_merge($collectionCode, $collectionFieldCode);
			}
			catch (\Exception $e)
			{
				$exceptions[] = new \Exception(
					"Can not annotate `{$entity->getFullName()}.{$field->getName()}` field", 0, $e
				);
			}
		}

		// return if there is no fields to annotate (e.g. empty uf)
		if ($ufOnly && empty($objectCode))
		{
			return null;
		}

		$code = array_merge($code, $objectCode);

		if (!$ufOnly)
		{
			// common class methods
			$code[] = "\t *";
			$code[] = "\t * Common methods:";
			$code[] = "\t * ---------------";
			$code[] = "\t *";
			$code[] = "\t * @property-read \\".Entity::class." \$entity";
			$code[] = "\t * @property-read array \$primary";
			$code[] = "\t * @property-read int \$state @see \\".State::class;
			$code[] = "\t * @property-read \\".Dictionary::class." \$customData";
			$code[] = "\t * @property \\".Context::class." \$authContext";
			$code[] = "\t * @method mixed get(\$fieldName)";
			$code[] = "\t * @method mixed remindActual(\$fieldName)";
			$code[] = "\t * @method mixed require(\$fieldName)";
			$code[] = "\t * @method bool has(\$fieldName)";
			$code[] = "\t * @method bool isFilled(\$fieldName)";
			$code[] = "\t * @method bool isChanged(\$fieldName)";
			$code[] = "\t * @method {$objectClass} set(\$fieldName, \$value)";
			$code[] = "\t * @method {$objectClass} reset(\$fieldName)";
			$code[] = "\t * @method {$objectClass} unset(\$fieldName)";
			$code[] = "\t * @method void addTo(\$fieldName, \$value)";
			$code[] = "\t * @method void removeFrom(\$fieldName, \$value)";
			$code[] = "\t * @method void removeAll(\$fieldName)";
			$code[] = "\t * @method \\".Result::class." delete()";
			$code[] = "\t * @method mixed fill(\$fields = \\".FieldTypeMask::class."::ALL) flag or array of field names";
			$code[] = "\t * @method mixed[] collectValues(\$valuesType = \Bitrix\Main\ORM\Objectify\Values::ALL, \$fieldsMask = \Bitrix\Main\ORM\Fields\FieldTypeMask::ALL)";
			$code[] = "\t * @method \\".AddResult::class."|\\".UpdateResult::class."|\\".Result::class." save()";
			$code[] = "\t * @method static {$objectClass} wakeUp(\$data)";
		}

		//$code[] = "\t *";
		//$code[] = "\t * for parent class, @see \\".EntityObject::class;
		// xTODO we can put path to the original file here
		$code[] = "\t */"; // end class annotations
		$code[] = "\tclass {$objectDefaultClassName} {";
		$code[] = "\t\t/* @var {$dataClass} */";
		$code[] = "\t\tstatic public \$dataClass = '{$dataClass}';";
		$code[] = "\t\t/**";
		$code[] = "\t\t * @param bool|array \$setDefaultValues";
		$code[] = "\t\t */";
		$code[] = "\t\tpublic function __construct(\$setDefaultValues = true) {}";
		$code[] = "\t}"; // end class

		// compatibility with default classes
		if (!str_starts_with($objectClassName, Entity::DEFAULT_OBJECT_PREFIX)) // better to compare full classes definitions
		{
			$defaultObjectClassName = Entity::getDefaultObjectClassName($entity->getName());

			// no need anymore as far as custom class inherits EO_
			//$code[] = "\tclass_alias('{$objectClass}', '{$entityNamespace}\\{$defaultObjectClassName}');";
		}

		$code[] = "}"; // end namespace

		// annotate collection class
		$code[] = "namespace {$entityNamespace} {"; // start namespace
		$code[] = "\t/**";
		$code[] = "\t * {$collectionClassName}";
		$code[] = "\t *";
		$code[] = "\t * Custom methods:";
		$code[] = "\t * ---------------";
		$code[] = "\t *";

		$code = array_merge($code, $collectionCode);

		if (!$ufOnly)
		{
			$code[] = "\t *";
			$code[] = "\t * Common methods:";
			$code[] = "\t * ---------------";
			$code[] = "\t *";
			$code[] = "\t * @property-read \\".Entity::class." \$entity";
			$code[] = "\t * @method void add({$objectClass} \$object)";
			$code[] = "\t * @method bool has({$objectClass} \$object)";
			$code[] = "\t * @method bool hasByPrimary(\$primary)";
			$code[] = "\t * @method {$objectClass} getByPrimary(\$primary)";
			$code[] = "\t * @method {$objectClass}[] getAll()";
			$code[] = "\t * @method bool remove({$objectClass} \$object)";
			$code[] = "\t * @method void removeByPrimary(\$primary)";
			$code[] = "\t * @method array|\\".Collection::class."|null fill(\$fields = \\".FieldTypeMask::class."::ALL) flag or array of field names";
			$code[] = "\t * @method static {$collectionClass} wakeUp(\$data)";
			$code[] = "\t * @method \\".Result::class." save(\$ignoreEvents = false)";
			$code[] = "\t * @method void offsetSet() ArrayAccess";
			$code[] = "\t * @method void offsetExists() ArrayAccess";
			$code[] = "\t * @method void offsetUnset() ArrayAccess";
			$code[] = "\t * @method void offsetGet() ArrayAccess";
			$code[] = "\t * @method void rewind() Iterator";
			$code[] = "\t * @method {$objectClass} current() Iterator";
			$code[] = "\t * @method mixed key() Iterator";
			$code[] = "\t * @method void next() Iterator";
			$code[] = "\t * @method bool valid() Iterator";
			$code[] = "\t * @method int count() Countable";
			$code[] = "\t * @method {$collectionClass} merge(?{$collectionClass} \$collection)";
			$code[] = "\t * @method bool isEmpty()";
			$code[] = "\t * @method array collectValues(int \$valuesType = \Bitrix\Main\ORM\Objectify\Values::ALL, int \$fieldsMask = \Bitrix\Main\ORM\Fields\FieldTypeMask::ALL, bool \$recursive = false)";
		}

		// xTODO we can put path to the original file here
		$code[] = "\t */";
		$code[] = "\tclass {$collectionDefaultClassName} implements \ArrayAccess, \Iterator, \Countable {";
		$code[] = "\t\t/* @var {$dataClass} */";
		$code[] = "\t\tstatic public \$dataClass = '{$dataClass}';";
		$code[] = "\t}"; // end class

		// compatibility with default classes
		if (!str_starts_with($collectionClassName, Entity::DEFAULT_OBJECT_PREFIX)) // better to compare full classes definitions
		{
			$defaultCollectionClassName = Entity::getDefaultCollectionClassName($entity->getName());

			// no need anymore as far as custom class inherits EO_
			//$code[] = "\tclass_alias('{$entityNamespace}\\{$collectionClassName}', '{$entityNamespace}\\{$defaultCollectionClassName}');";
		}

		$code[] = "}"; // end namespace

		if (!$ufOnly)
		{
			// annotate Table class
			$dataClassName = $entity->getName().'Table';
			$resultClassName = Entity::DEFAULT_OBJECT_PREFIX.$entity->getName().'_Result';
			$entityClassName = Entity::DEFAULT_OBJECT_PREFIX.$entity->getName().'_Entity';
			$eoQueryClassName = Entity::DEFAULT_OBJECT_PREFIX.$entity->getName().'_Query';

			// custom query class
			if ($entity->getDataClass()::getQueryClass() !== Query::class)
			{
				$queryClassName = '\\'.$entity->getDataClass()::getQueryClass();
				$reflectionClass = new \ReflectionClass($queryClassName);

				if ($reflectionClass->getNamespaceName() === $entityNamespace)
				{
					// short syntax for the same namespace
					$queryClassName = $reflectionClass->getShortName();
				}
			}
			else
			{
				$queryClassName = $eoQueryClassName;
			}

			$code[] = "namespace {$entityNamespace} {"; // start namespace

			if (!$separateTable)
			{
				$code[] = "\t/**";
			}

			$codeTable = [];
			$codeTable[] = " * @method static {$queryClassName} query()";
			$codeTable[] = " * @method static {$resultClassName} getByPrimary(\$primary, array \$parameters = [])";
			$codeTable[] = " * @method static {$resultClassName} getById(\$id)";
			$codeTable[] = " * @method static {$resultClassName} getList(array \$parameters = [])";
			$codeTable[] = " * @method static {$entityClassName} getEntity()";
			$codeTable[] = " * @method static {$objectClass} createObject(\$setDefaultValues = true)";
			$codeTable[] = " * @method static {$collectionClass} createCollection()";
			$codeTable[] = " * @method static {$objectClass} wakeUpObject(\$row)";
			$codeTable[] = " * @method static {$collectionClass} wakeUpCollection(\$rows)";

			if (!$separateTable)
			{
				// add tabs
				foreach ($codeTable as $i => $line)
				{
					$codeTable[$i] = "\t".$line;
				}

				$code = array_merge($code, $codeTable);
				$code[] = "\t */";
				$code[] = "\tclass {$dataClassName} extends \\".DataManager::class." {}";
			}

			// annotate Query class
			$code[] = "\t/**";
			$code[] = "\t * Common methods:";
			$code[] = "\t * ---------------";
			$code[] = "\t *";
			$code[] = "\t * @method {$resultClassName} exec()";
			$code[] = "\t * @method {$objectClass} fetchObject()";
			$code[] = "\t * @method {$collectionClass} fetchCollection()";

			$customQueryMethodsCode = [];

			foreach (get_class_methods($dataClass) as $method)
			{
				// search for with* methods
				if (str_starts_with($method, 'with'))
				{
					$reflectionMethod = new \ReflectionMethod($dataClass, $method);

					if ($reflectionMethod->isStatic())
					{
						$arguments = [];

						// get parameters except the first one (query itself)
						foreach (array_slice($reflectionMethod->getParameters(), 1) as $parameter)
						{
							$arguments[] = '$'.$parameter->getName();
						}

						$argumentsMeta = join(', ', $arguments);

						$customQueryMethodsCode[] = "\t * @see {$dataClass}::{$method}()";
						$customQueryMethodsCode[] = "\t * @method self {$method}({$argumentsMeta})";
					}
				}
			}

			if (!empty($customQueryMethodsCode))
			{
				$code[] = "\t *";
				$code[] = "\t * Custom methods:";
				$code[] = "\t * ---------------";
				$code[] = "\t *";

				array_push($code, $customQueryMethodsCode);
			}

			$code[] = "\t */";
			$code[] = "\tclass {$eoQueryClassName} extends \\".Query::class." {}";

			// annotate Result class
			$code[] = "\t/**";
			$code[] = "\t * @method {$objectClass} fetchObject()";
			$code[] = "\t * @method {$collectionClass} fetchCollection()";
			$code[] = "\t */";
			$code[] = "\tclass {$resultClassName} extends \\".\Bitrix\Main\ORM\Query\Result::class." {}";

			// annotate Entity class
			$code[] = "\t/**";
			$code[] = "\t * @method {$objectClass} createObject(\$setDefaultValues = true)";
			$code[] = "\t * @method {$collectionClass} createCollection()";
			$code[] = "\t * @method {$objectClass} wakeUpObject(\$row)";
			$code[] = "\t * @method {$collectionClass} wakeUpCollection(\$rows)";
			$code[] = "\t */";
			$code[] = "\tclass {$entityClassName} extends \\".Entity::class." {}";

			$code[] = "}"; // end namespace
		}

		if (!$separateTable)
		{
			return join("\n", $code);
		}
		else
		{
			return [
				join("\n", $codeTable),
				join("\n", $code),
				$exceptions
			];
		}
	}

	public static function annotateScalarField(ScalarField $field)
	{
		// TODO no setter if it is reference-elemental (could expressions become elemental?)

		$objectClass = $field->getEntity()->getObjectClass();
		$getterDataType = $field->getGetterTypeHint();
		$setterDataType = $field->getSetterTypeHint();
		list($lName, $uName) = static::getFieldNameCamelCase($field->getName());

		$objectCode = [];
		$collectionCode = [];

		$objectCode[] = "\t * @method {$getterDataType} get{$uName}()";
		$objectCode[] = "\t * @method {$objectClass} set{$uName}({$setterDataType}|\\".SqlExpression::class." \${$lName})";

		$objectCode[] = "\t * @method bool has{$uName}()";
		$objectCode[] = "\t * @method bool is{$uName}Filled()";
		$objectCode[] = "\t * @method bool is{$uName}Changed()";

		$collectionCode[] = "\t * @method {$getterDataType}[] get{$uName}List()";

		if (!$field->isPrimary())
		{
			$objectCode[] = "\t * @method {$getterDataType} remindActual{$uName}()";
			$objectCode[] = "\t * @method {$getterDataType} require{$uName}()";

			$objectCode[] = "\t * @method {$objectClass} reset{$uName}()";
			$objectCode[] = "\t * @method {$objectClass} unset{$uName}()";

			$objectCode[] = "\t * @method {$getterDataType} fill{$uName}()";
			$collectionCode[] = "\t * @method {$getterDataType}[] fill{$uName}()";
		}

		return [$objectCode, $collectionCode];
	}

	public static function annotateUserType(UserTypeField $field)
	{
		// no setter
		$objectClass = $field->getEntity()->getObjectClass();

		/** @var ScalarField $scalarFieldClass */
		$scalarFieldClass = $field->getValueType();
		$dataType = (new $scalarFieldClass('TMP'))->getSetterTypeHint();
		$dataType = $field->isMultiple() ? $dataType.'[]' : $dataType;
		list($lName, $uName) = static::getFieldNameCamelCase($field->getName());

		list($objectCode, $collectionCode) = static::annotateExpression($field);

		// add setter
		$objectCode[] = "\t * @method {$objectClass} set{$uName}({$dataType} \${$lName})";

		$objectCode[] = "\t * @method bool is{$uName}Changed()";

		return [$objectCode, $collectionCode];
	}

	public static function annotateExpression(ExpressionField $field)
	{
		// no setter
		$objectClass = $field->getEntity()->getObjectClass();

		$scalarFieldClass = $field->getValueType();
		$dataType = (new $scalarFieldClass('TMP'))->getGetterTypeHint();
		list($lName, $uName) = static::getFieldNameCamelCase($field->getName());

		$objectCode = [];
		$collectionCode = [];

		$objectCode[] = "\t * @method {$dataType} get{$uName}()";
		$objectCode[] = "\t * @method {$dataType} remindActual{$uName}()";
		$objectCode[] = "\t * @method {$dataType} require{$uName}()";

		$objectCode[] = "\t * @method bool has{$uName}()";
		$objectCode[] = "\t * @method bool is{$uName}Filled()";

		$collectionCode[] = "\t * @method {$dataType}[] get{$uName}List()";

		$objectCode[] = "\t * @method {$objectClass} unset{$uName}()";

		$objectCode[] = "\t * @method {$dataType} fill{$uName}()";
		$collectionCode[] = "\t * @method {$dataType}[] fill{$uName}()";

		return [$objectCode, $collectionCode];
	}

	public static function annotateReference(Reference $field)
	{
		if (!static::tryToFindEntity($field->getRefEntityName()))
		{
			return [[], []];
		}

		$objectClass = $field->getEntity()->getObjectClass();
		$collectionClass = $field->getEntity()->getCollectionClass();
		$collectionDataType = $field->getRefEntity()->getCollectionClass();

		$getterTypeHint = $field->getGetterTypeHint();
		$setterTypeHint = $field->getSetterTypeHint();

		list($lName, $uName) = static::getFieldNameCamelCase($field->getName());

		$objectCode = [];
		$collectionCode = [];

		$objectCode[] = "\t * @method {$getterTypeHint} get{$uName}()";
		$objectCode[] = "\t * @method {$getterTypeHint} remindActual{$uName}()";
		$objectCode[] = "\t * @method {$getterTypeHint} require{$uName}()";

		$objectCode[] = "\t * @method {$objectClass} set{$uName}({$setterTypeHint} \$object)";
		$objectCode[] = "\t * @method {$objectClass} reset{$uName}()";
		$objectCode[] = "\t * @method {$objectClass} unset{$uName}()";

		$objectCode[] = "\t * @method bool has{$uName}()";
		$objectCode[] = "\t * @method bool is{$uName}Filled()";
		$objectCode[] = "\t * @method bool is{$uName}Changed()";

		$collectionCode[] = "\t * @method {$getterTypeHint}[] get{$uName}List()";
		$collectionCode[] = "\t * @method {$collectionClass} get{$uName}Collection()";

		$objectCode[] = "\t * @method {$getterTypeHint} fill{$uName}()";
		$collectionCode[] = "\t * @method {$collectionDataType} fill{$uName}()";

		return [$objectCode, $collectionCode];
	}

	public static function annotateOneToMany(OneToMany $field)
	{
		if (!static::tryToFindEntity($field->getRefEntityName()))
		{
			return [[], []];
		}

		$objectClass = $field->getEntity()->getObjectClass();
		$collectionDataType = $field->getRefEntity()->getCollectionClass();
		$objectVarName = lcfirst($field->getRefEntity()->getName());

		$setterTypeHint = $field->getSetterTypeHint();

		list($lName, $uName) = static::getFieldNameCamelCase($field->getName());

		$objectCode = [];
		$collectionCode = [];

		$objectCode[] = "\t * @method {$collectionDataType} get{$uName}()";
		$objectCode[] = "\t * @method {$collectionDataType} require{$uName}()";
		$objectCode[] = "\t * @method {$collectionDataType} fill{$uName}()";

		$objectCode[] = "\t * @method bool has{$uName}()";
		$objectCode[] = "\t * @method bool is{$uName}Filled()";
		$objectCode[] = "\t * @method bool is{$uName}Changed()";

		$objectCode[] = "\t * @method void addTo{$uName}({$setterTypeHint} \${$objectVarName})";
		$objectCode[] = "\t * @method void removeFrom{$uName}({$setterTypeHint} \${$objectVarName})";
		$objectCode[] = "\t * @method void removeAll{$uName}()";

		$objectCode[] = "\t * @method {$objectClass} reset{$uName}()";
		$objectCode[] = "\t * @method {$objectClass} unset{$uName}()";

		$collectionCode[] = "\t * @method {$collectionDataType}[] get{$uName}List()";
		$collectionCode[] = "\t * @method {$collectionDataType} get{$uName}Collection()";
		$collectionCode[] = "\t * @method {$collectionDataType} fill{$uName}()";

		return [$objectCode, $collectionCode];
	}

	public static function annotateManyToMany(ManyToMany $field)
	{
		if (!static::tryToFindEntity($field->getRefEntityName()))
		{
			return [[], []];
		}

		$objectClass = $field->getEntity()->getObjectClass();
		$collectionDataType = $field->getRefEntity()->getCollectionClass();
		$objectVarName = lcfirst($field->getRefEntity()->getName());

		$setterTypeHint = $field->getSetterTypeHint();

		list($lName, $uName) = static::getFieldNameCamelCase($field->getName());

		$objectCode = [];
		$collectionCode = [];

		$objectCode[] = "\t * @method {$collectionDataType} get{$uName}()";
		$objectCode[] = "\t * @method {$collectionDataType} require{$uName}()";
		$objectCode[] = "\t * @method {$collectionDataType} fill{$uName}()";

		$objectCode[] = "\t * @method bool has{$uName}()";
		$objectCode[] = "\t * @method bool is{$uName}Filled()";
		$objectCode[] = "\t * @method bool is{$uName}Changed()";

		$objectCode[] = "\t * @method void addTo{$uName}({$setterTypeHint} \${$objectVarName})";
		$objectCode[] = "\t * @method void removeFrom{$uName}({$setterTypeHint} \${$objectVarName})";
		$objectCode[] = "\t * @method void removeAll{$uName}()";

		$objectCode[] = "\t * @method {$objectClass} reset{$uName}()";
		$objectCode[] = "\t * @method {$objectClass} unset{$uName}()";

		$collectionCode[] = "\t * @method {$collectionDataType}[] get{$uName}List()";
		$collectionCode[] = "\t * @method {$collectionDataType} get{$uName}Collection()";
		$collectionCode[] = "\t * @method {$collectionDataType} fill{$uName}()";

		return [$objectCode, $collectionCode];
	}

	public static function tryToFindEntity($entityClass)
	{
		$entityClass = Entity::normalizeEntityClass($entityClass);

		if (!class_exists($entityClass))
		{
			// try to find remote entity
			$classParts = array_values(array_filter(
				explode('\\', strtolower($entityClass))
			));

			if ($classParts[0] == 'bitrix')
			{
				$moduleName = $classParts[1];
			}
			else
			{
				$moduleName = $classParts[0].'.'.$classParts[1];
			}

			if (!Loader::includeModule($moduleName) || !class_exists($entityClass))
			{
				return false;
			}
		}

		if ((new \ReflectionClass($entityClass))->isAbstract())
		{
			return false;
		}

		return true;
	}

	protected static function getFieldNameCamelCase($fieldName)
	{
		$upperFirstName = StringHelper::snake2camel($fieldName);
		$lowerFirstName = lcfirst($upperFirstName);

		return [$lowerFirstName, $upperFirstName];
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit