%PDF- %PDF-
| Direktori : /proc/self/root/proc/10573/cwd/home/bitrix/www/bitrix/modules/main/lib/cli/ |
| Current File : //proc/self/root/proc/10573/cwd/home/bitrix/www/bitrix/modules/main/lib/cli/ormannotatecommand.php |
<?php
/**
* Bitrix Framework
* @package bitrix
* @subpackage main
* @copyright 2001-2018 Bitrix
*/
namespace Bitrix\Main\Cli;
use Bitrix\Main\Application;
use Bitrix\Main\Loader;
use Bitrix\Main\ORM\Data\AddResult;
use Bitrix\Main\ORM\Data\UpdateResult;
use Bitrix\Main\ORM\Fields\BooleanField;
use Bitrix\Main\ORM\Data\DataManager;
use Bitrix\Main\ORM\Entity;
use Bitrix\Main\ORM\Fields\FieldTypeMask;
use Bitrix\Main\ORM\Fields\UserTypeField;
use Bitrix\Main\ORM\Objectify\EntityObject;
use Bitrix\Main\ORM\Fields\DateField;
use Bitrix\Main\ORM\Fields\DatetimeField;
use Bitrix\Main\ORM\Fields\ExpressionField;
use Bitrix\Main\ORM\Fields\Relations\ManyToMany;
use Bitrix\Main\ORM\Fields\Relations\OneToMany;
use Bitrix\Main\ORM\Fields\FloatField;
use Bitrix\Main\ORM\Fields\IntegerField;
use Bitrix\Main\ORM\Objectify\Collection;
use Bitrix\Main\ORM\Fields\Relations\Reference;
use Bitrix\Main\ORM\Fields\ScalarField;
use Bitrix\Main\ORM\Query\Query;
use Bitrix\Main\Type\Date;
use Bitrix\Main\Type\DateTime;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* @package bitrix
* @subpackage main
*/
class OrmAnnotateCommand extends Command
{
protected $debug = 0;
protected $modulesScanned = [];
protected $filesIncluded = 0;
protected $entitiesFound = [];
protected $excludedFiles = [
'main/lib/text/string.php',
'main/lib/composite/compatibility/aliases.php',
'sale/lib/delivery/extra_services/string.php',
];
const ANNOTATION_MARKER = 'ORMENTITYANNOTATION';
protected function configure()
{
$inBitrixDir = realpath(Application::getDocumentRoot().Application::getPersonalRoot()) === realpath(getcwd());
$this
// the name of the command (the part after "bin/console")
->setName('orm:annotate')
// the short description shown while running "php bin/console list"
->setDescription('Scans project for ORM Entities.')
// the full command description shown when running the command with
// the "--help" option
->setHelp('This system command optimizes Entity Relation Map building.')
->setDefinition(
new InputDefinition(array(
new InputArgument(
'output', InputArgument::OPTIONAL, 'File for annotations to be saved to',
$inBitrixDir
? 'modules/orm_annotations.php'
: Application::getDocumentRoot().Application::getPersonalRoot().'/modules/orm_annotations.php'
),
new InputOption(
'modules', 'm', InputOption::VALUE_OPTIONAL,
'Modules to be scanned, separated by comma.', 'main'
),
new InputOption(
'clean', 'c', InputOption::VALUE_NONE,
'Clean current entity map.'
),
))
)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln([
'Entity Scanner',
'==============',
'',
]);
$time = getmicrotime();
$memoryBefore = memory_get_usage();
// handle already known classes (but we don't know their modules)
// as long as there are no any Table by default, we can ignore it
$this->handleClasses(get_declared_classes(), $input, $output);
// scan dirs
$inputModules = [];
$inputModulesRaw = $input->getOption('modules');
if (!empty($inputModulesRaw) && $inputModulesRaw != 'all')
{
$inputModules = explode(',', $inputModulesRaw);
}
$dirs = $this->getDirsToScan($inputModules, $input, $output);
foreach ($dirs as $dir)
{
$this->scanDir($dir, $input, $output);
}
// output file path
$filePath = $input->getArgument('output');
$filePath = ($filePath{0} == '/')
? $filePath // absolute
: getcwd().'/'.$filePath; // relative
// handle entities
$annotations = [];
// get current annotations
if (!$input->getOption('clean') && file_exists($filePath) && is_readable($filePath))
{
$rawAnnotations = explode('/* '.static::ANNOTATION_MARKER, file_get_contents($filePath));
foreach ($rawAnnotations as $rawAnnotation)
{
if ($rawAnnotation{0} === ':')
{
$endPos = strpos($rawAnnotation, ' */');
$entityClass = substr($rawAnnotation, 1, $endPos-1);
//$annotation = substr($rawAnnotation, $endPos + 3 + strlen(PHP_EOL));
$annotations[$entityClass] = '/* '.static::ANNOTATION_MARKER.rtrim($rawAnnotation);
}
}
}
// add/rewrite new entities
foreach ($this->entitiesFound as $entityClass)
{
$entity = Entity::getInstance($entityClass);
$entityAnnotation = static::annotateEntity($entity, $input,$output);
$annotations[$entityClass] = "/* ".static::ANNOTATION_MARKER.":{$entityClass} */".PHP_EOL;
$annotations[$entityClass] .= $entityAnnotation;
}
// write to file
$fileContent = '<?php'.PHP_EOL.PHP_EOL.join(PHP_EOL, $annotations);
file_put_contents($filePath, $fileContent);
$output->writeln('Map has been saved to: '.$filePath);
// summary stats
$time = round(getmicrotime() - $time, 2);
$memoryAfter = memory_get_usage();
$memoryDiff = $memoryAfter - $memoryBefore;
$output->writeln('Scanned modules: '.join(', ', $this->modulesScanned));
$output->writeln('Scanned files: '.$this->filesIncluded);
$output->writeln('Found entities: '.count($this->entitiesFound));
$output->writeln('Time: '.$time.' sec');
$output->writeln('Memory usage: '.(round($memoryAfter/1024/1024, 1)).'M (+'.(round($memoryDiff/1024/1024, 1)).'M)');
$output->writeln('Memory peak usage: '.(round(memory_get_peak_usage()/1024/1024, 1)).'M');
}
protected function getDirsToScan($inputModules, InputInterface $input, OutputInterface $output)
{
$basePaths = [
Application::getDocumentRoot().Application::getPersonalRoot().'/modules/',
Application::getDocumentRoot().'/local/modules/'
];
$dirs = [];
foreach ($basePaths as $basePath)
{
if (!file_exists($basePath))
{
continue;
}
$moduleList = [];
foreach (new \DirectoryIterator($basePath) as $item)
{
if($item->isDir() && !$item->isDot())
{
$moduleList[] = $item->getFilename();
}
}
// filter for input modules
if (!empty($inputModules))
{
$moduleList = array_intersect($moduleList, $inputModules);
}
foreach ($moduleList as $moduleName)
{
// filter for installed modules
if (!Loader::includeModule($moduleName))
{
continue;
}
$libDir = $basePath.$moduleName.'/lib';
if (is_dir($libDir) && is_readable($libDir))
{
$dirs[] = $libDir;
}
$libDir = $basePath.$moduleName.'/dev/lib';
if (is_dir($libDir) && is_readable($libDir))
{
$dirs[] = $libDir;
}
$this->modulesScanned[] = $moduleName;
}
}
return $dirs;
}
protected function scanDir($dir, InputInterface $input, OutputInterface $output)
{
$this->debug($output,'scan dir: '.$dir);
foreach (
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS | \RecursiveDirectoryIterator::FOLLOW_SYMLINKS),
\RecursiveIteratorIterator::SELF_FIRST) as $item
)
{
// check for stop list
foreach ($this->excludedFiles as $excludedFile)
{
$currentPath = str_replace('\\', '/', $item->getPathname());
if (substr($currentPath, -strlen($excludedFile)) === $excludedFile)
{
continue 2;
}
}
/** @var $iterator \RecursiveDirectoryIterator */
/** @var $item \SplFileInfo */
if ($item->isFile() && $item->isReadable() && substr($item->getFilename(), -4) == '.php')
{
$this->debug($output,'handle file: '.$item->getPathname());
// get classes from file
$classes = get_declared_classes();
try
{
include_once $item->getPathname();
$this->filesIncluded++;
}
catch (\Exception $e)
{
throw $e;
}
$classes = array_diff(get_declared_classes(), $classes);
// check classes
$this->handleClasses($classes, $input, $output);
}
}
}
protected function handleClasses($classes, InputInterface $input, OutputInterface $output)
{
foreach ($classes as $class)
{
$debugMsg = $class;
if (is_subclass_of($class, DataManager::class) && substr($class, -5) == 'Table')
{
$debugMsg .= ' found!';
$this->entitiesFound[] = $class;
}
$this->debug($output, $debugMsg);
}
}
public static function annotateEntity(Entity $entity, InputInterface $input, OutputInterface $output)
{
$entityNamespace = trim($entity->getNamespace(), '\\');
$dataClass = $entity->getDataClass();
$objectClass = $entity->getObjectClass();
$objectClassName = $entity->getObjectClassName();
$objectDefaultClassName = Entity::getDefaultObjectClassName($entity->getName());
$objectNamespace = trim(
substr($objectClass, 0, strrpos($objectClass, '\\')),
'\\'
);
$collectionClass = $entity->getCollectionClass();
$collectionClassName = $entity->getCollectionClassName();
$collectionDefaultClassName = Entity::getDefaultCollectionClassName($entity->getName());
$collectionNamespace = trim(
substr($collectionClass, 0, strrpos($collectionClass, '\\')),
'\\'
);
$code = [];
$objectCode = [];
$collectionCode = [];
$code[] = "namespace {$objectNamespace} {"; // start namespace
$code[] = "\t/**"; // start class annotations
$code[] = "\t * {$objectClassName}";
$code[] = "\t * @see {$dataClass}";
$code[] = "\t *";
$code[] = "\t * Custom methods:";
$code[] = "\t * ---------------";
$code[] = "\t *";
foreach ($entity->getFields() as $field)
{
$objectFieldCode = [];
$collectionFieldCode = [];
if ($field instanceof ScalarField)
{
list($objectFieldCode, $collectionFieldCode) = static::annotateScalarField($field);
}
elseif ($field instanceof UserTypeField)
{
list($objectFieldCode, $collectionFieldCode) = static::annotateUserType($field);
}
elseif ($field instanceof ExpressionField)
{
list($objectFieldCode, $collectionFieldCode) = static::annotateExpression($field);
}
elseif ($field instanceof Reference)
{
list($objectFieldCode, $collectionFieldCode) = static::annotateReference($field);
}
elseif ($field instanceof OneToMany)
{
list($objectFieldCode, $collectionFieldCode) = static::annotateOneToMany($field);
}
elseif ($field instanceof ManyToMany)
{
list($objectFieldCode, $collectionFieldCode) = static::annotateManyToMany($field);
}
$objectCode = array_merge($objectCode, $objectFieldCode);
$collectionCode = array_merge($collectionCode, $collectionFieldCode);
}
// common class methods
$code = array_merge($code, $objectCode);
$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 * @method mixed get(\$fieldName)";
$code[] = "\t * @method mixed remindActual(\$fieldName)";
$code[] = "\t * @method mixed require(\$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 void delete()";
$code[] = "\t * @method void 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."|bool 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}"; // end class
// compatibility with default classes
if (strpos($objectClassName, Entity::DEFAULT_OBJECT_PREFIX) !== 0) // 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 {$collectionNamespace} {"; // start namespace
$code[] = "\t/**";
$code[] = "\t * {$collectionClassName}";
$code[] = "\t *";
$code[] = "\t * Custom methods:";
$code[] = "\t * ---------------";
$code[] = "\t *";
$code = array_merge($code, $collectionCode);
$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 fill(\$fields = \\".FieldTypeMask::class."::ALL) flag or array of field names";
$code[] = "\t * @method static {$collectionClass} wakeUp(\$data)";
$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";
// 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 (strpos($collectionClassName, Entity::DEFAULT_OBJECT_PREFIX) !== 0) // 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
// annotate query and result
$dataClassName = $entity->getName().'Table';
$queryClassName = Entity::DEFAULT_OBJECT_PREFIX.$entity->getName().'_Query';
$resultClassName = Entity::DEFAULT_OBJECT_PREFIX.$entity->getName().'_Result';
$entityClassName = Entity::DEFAULT_OBJECT_PREFIX.$entity->getName().'_Entity';
$code[] = "namespace {$entityNamespace} {"; // start namespace
$code[] = "\t/**";
$code[] = "\t * @method static {$queryClassName} query()";
$code[] = "\t * @method static {$resultClassName} getByPrimary()";
$code[] = "\t * @method static {$resultClassName} getById()";
$code[] = "\t * @method static {$resultClassName} getList()";
$code[] = "\t * @method static {$entityClassName} getEntity()";
$code[] = "\t * @method static {$objectClass} createObject(\$setDefaultValues = true)";
$code[] = "\t * @method static {$collectionClass} createCollection()";
$code[] = "\t * @method static {$objectClass} wakeUpObject()";
$code[] = "\t * @method static {$collectionClass} wakeUpCollection()";
$code[] = "\t */";
$code[] = "\tclass {$dataClassName} {}";
$code[] = "\t/**";
$code[] = "\t * @method {$resultClassName} exec()";
$code[] = "\t * @method {$objectClass} fetchObject()";
$code[] = "\t * @method {$collectionClass} fetchCollection()";
$code[] = "\t */";
$code[] = "\tclass {$queryClassName} extends \\".Query::class." {}";
$code[] = "\t/**";
$code[] = "\t * @method {$objectClass} fetchObject()";
$code[] = "\t * @method {$collectionClass} fetchCollection()";
$code[] = "\t */";
$code[] = "\tclass {$resultClassName} {}";
$code[] = "\t/**";
$code[] = "\t * @method {$objectClass} createObject(\$setDefaultValues = true)";
$code[] = "\t * @method {$collectionClass} createCollection()";
$code[] = "\t * @method {$objectClass} wakeUpObject()";
$code[] = "\t * @method {$collectionClass} wakeUpCollection()";
$code[] = "\t */";
$code[] = "\tclass {$entityClassName} {}";
$code[] = "}"; // end namespace
return join(PHP_EOL, $code);
}
public static function annotateScalarField(ScalarField $field)
{
// TODO no setter if it is reference-elemental (could expressions become elemental?)
$objectClass = $field->getEntity()->getObjectClass();
$dataType = static::scalarFieldToTypeHint($field);
list($lName, $uName) = static::getFieldNameCamelCase($field->getName());
$objectCode = [];
$collectionCode = [];
$objectCode[] = "\t * @method {$dataType} get{$uName}()";
$objectCode[] = "\t * @method {$objectClass} set{$uName}({$dataType} \${$lName})";
$collectionCode[] = "\t * @method {$dataType}[] get{$uName}List()";
if (!$field->isPrimary())
{
$objectCode[] = "\t * @method {$dataType} remindActual{$uName}()";
$objectCode[] = "\t * @method {$dataType} require{$uName}()";
$objectCode[] = "\t * @method {$objectClass} reset{$uName}()";
$objectCode[] = "\t * @method {$objectClass} unset{$uName}()";
$objectCode[] = "\t * @method {$dataType} fill{$uName}()";
$collectionCode[] = "\t * @method fill{$uName}()";
}
return [$objectCode, $collectionCode];
}
public static function annotateUserType(UserTypeField $field)
{
// no setter
$objectClass = $field->getEntity()->getObjectClass();
$dataType = static::scalarFieldToTypeHint($field->getValueType());
$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})";
return [$objectCode, $collectionCode];
}
public static function annotateExpression(ExpressionField $field)
{
// no setter
$objectClass = $field->getEntity()->getObjectClass();
$dataType = static::scalarFieldToTypeHint($field->getValueType());
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}()";
$collectionCode[] = "\t * @method {$dataType}[] get{$uName}List()";
$objectCode[] = "\t * @method {$objectClass} unset{$uName}()";
$objectCode[] = "\t * @method {$dataType} fill{$uName}()";
$collectionCode[] = "\t * @method fill{$uName}()";
return [$objectCode, $collectionCode];
}
public static function annotateReference(Reference $field)
{
if (!static::tryToFindEntity($field->getRefEntityName()))
{
return [[], []];
}
$objectClass = $field->getEntity()->getObjectClass();
$dataType = $field->getRefEntity()->getObjectClass();
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 {$objectClass} set{$uName}({$dataType} \$object)";
$objectCode[] = "\t * @method {$objectClass} reset{$uName}()";
$objectCode[] = "\t * @method {$objectClass} unset{$uName}()";
$collectionCode[] = "\t * @method {$dataType}[] get{$uName}List()";
$objectCode[] = "\t * @method {$dataType} fill{$uName}()";
$collectionCode[] = "\t * @method 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();
$objectDataType = $field->getRefEntity()->getObjectClass();
$objectVarName = lcfirst($field->getRefEntity()->getName());
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 void addTo{$uName}({$objectDataType} \${$objectVarName})";
$objectCode[] = "\t * @method void removeFrom{$uName}({$objectDataType} \${$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 void 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();
$objectDataType = $field->getRefEntity()->getObjectClass();
$objectVarName = lcfirst($field->getRefEntity()->getName());
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 void addTo{$uName}({$objectDataType} \${$objectVarName})";
$objectCode[] = "\t * @method void removeFrom{$uName}({$objectDataType} \${$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 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;
}
}
return true;
}
protected static function getFieldNameCamelCase($fieldName)
{
$upperFirstName = Entity::snake2camel($fieldName);
$lowerFirstName = lcfirst($upperFirstName);
return [$lowerFirstName, $upperFirstName];
}
public static function scalarFieldToTypeHint($field)
{
if (is_string($field))
{
$fieldClass = $field;
}
else
{
$fieldClass = get_class($field);
}
switch ($fieldClass)
{
case DateField::class:
return '\\'.Date::class;
case DatetimeField::class:
return '\\'.DateTime::class;
case IntegerField::class:
return '\\int';
case BooleanField::class:
return '\\boolean';
case FloatField::class:
return '\\float';
default:
return '\\string';
}
}
protected function debug(OutputInterface $output, $message)
{
if ($this->debug)
{
$output->writeln($message);
}
}
}