%PDF- %PDF-
Direktori : /home/bitrix/www/bitrix/modules/main/lib/cli/ |
Current File : //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); } } }