40 public static function annotateEntity(Entity $entity, $ufOnly =
false, $separateTable =
false)
42 $entityNamespace = trim($entity->getNamespace(),
'\\');
43 $dataClass = $entity->getDataClass();
45 $objectClass = $entity->getObjectClass();
46 $objectClassName = $entity->getObjectClassName();
47 $objectDefaultClassName = Entity::getDefaultObjectClassName($entity->getName());
49 $collectionClass = $entity->getCollectionClass();
50 $collectionClassName = $entity->getCollectionClassName();
51 $collectionDefaultClassName = Entity::getDefaultCollectionClassName($entity->getName());
57 $code[] =
"namespace {$entityNamespace} {";
59 $code[] =
"\t * {$objectClassName}";
60 $code[] =
"\t * @see {$dataClass}";
62 $code[] =
"\t * Custom methods:";
63 $code[] =
"\t * ---------------";
68 foreach ($entity->getFields() as $field)
70 $objectFieldCode = [];
71 $collectionFieldCode = [];
73 if ($ufOnly && !($field instanceof UserTypeField))
80 if ($field instanceof ScalarField)
82 [$objectFieldCode, $collectionFieldCode] = static::annotateScalarField($field);
84 elseif ($field instanceof UserTypeField)
86 [$objectFieldCode, $collectionFieldCode] = static::annotateUserType($field);
88 elseif ($field instanceof ExpressionField)
90 [$objectFieldCode, $collectionFieldCode] = static::annotateExpression($field);
92 elseif ($field instanceof Reference)
94 [$objectFieldCode, $collectionFieldCode] = static::annotateReference($field);
96 elseif ($field instanceof OneToMany)
98 [$objectFieldCode, $collectionFieldCode] = static::annotateOneToMany($field);
100 elseif ($field instanceof ManyToMany)
102 [$objectFieldCode, $collectionFieldCode] = static::annotateManyToMany($field);
105 $objectCode = array_merge($objectCode, $objectFieldCode);
106 $collectionCode = array_merge($collectionCode, $collectionFieldCode);
108 catch (\Exception $e)
110 $exceptions[] = new \Exception(
111 "Can not annotate `{$entity->getFullName()}.{$field->getName()}` field", 0, $e
117 if ($ufOnly && empty($objectCode))
122 $code = array_merge($code, $objectCode);
128 $code[] =
"\t * Common methods:";
129 $code[] =
"\t * ---------------";
131 $code[] =
"\t * @property-read \\".Entity::class.
" \$entity";
132 $code[] =
"\t * @property-read array \$primary";
133 $code[] =
"\t * @property-read int \$state @see \\".State::class;
134 $code[] =
"\t * @property-read \\".Dictionary::class.
" \$customData";
135 $code[] =
"\t * @property \\".Context::class.
" \$authContext";
136 $code[] =
"\t * @method mixed get(\$fieldName)";
137 $code[] =
"\t * @method mixed remindActual(\$fieldName)";
138 $code[] =
"\t * @method mixed require(\$fieldName)";
139 $code[] =
"\t * @method bool has(\$fieldName)";
140 $code[] =
"\t * @method bool isFilled(\$fieldName)";
141 $code[] =
"\t * @method bool isChanged(\$fieldName)";
142 $code[] =
"\t * @method {$objectClass} set(\$fieldName, \$value)";
143 $code[] =
"\t * @method {$objectClass} reset(\$fieldName)";
144 $code[] =
"\t * @method {$objectClass} unset(\$fieldName)";
145 $code[] =
"\t * @method void addTo(\$fieldName, \$value)";
146 $code[] =
"\t * @method void removeFrom(\$fieldName, \$value)";
147 $code[] =
"\t * @method void removeAll(\$fieldName)";
148 $code[] =
"\t * @method \\".Result::class.
" delete()";
149 $code[] =
"\t * @method void fill(\$fields = \\".FieldTypeMask::class.
"::ALL) flag or array of field names";
150 $code[] =
"\t * @method mixed[] collectValues(\$valuesType = \Bitrix\Main\ORM\Objectify\Values::ALL, \$fieldsMask = \Bitrix\Main\ORM\Fields\FieldTypeMask::ALL)";
151 $code[] =
"\t * @method \\".AddResult::class.
"|\\".UpdateResult::class.
"|\\".Result::class.
" save()";
152 $code[] =
"\t * @method static {$objectClass} wakeUp(\$data)";
159 $code[] =
"\tclass {$objectDefaultClassName} {";
160 $code[] =
"\t\t/* @var {$dataClass} */";
161 $code[] =
"\t\tstatic public \$dataClass = '{$dataClass}';";
163 $code[] =
"\t\t * @param bool|array \$setDefaultValues";
165 $code[] =
"\t\tpublic function __construct(\$setDefaultValues = true) {}";
169 if (strpos($objectClassName, Entity::DEFAULT_OBJECT_PREFIX) !== 0)
171 $defaultObjectClassName = Entity::getDefaultObjectClassName($entity->getName());
180 $code[] =
"namespace {$entityNamespace} {";
182 $code[] =
"\t * {$collectionClassName}";
184 $code[] =
"\t * Custom methods:";
185 $code[] =
"\t * ---------------";
188 $code = array_merge($code, $collectionCode);
193 $code[] =
"\t * Common methods:";
194 $code[] =
"\t * ---------------";
196 $code[] =
"\t * @property-read \\".Entity::class.
" \$entity";
197 $code[] =
"\t * @method void add({$objectClass} \$object)";
198 $code[] =
"\t * @method bool has({$objectClass} \$object)";
199 $code[] =
"\t * @method bool hasByPrimary(\$primary)";
200 $code[] =
"\t * @method {$objectClass} getByPrimary(\$primary)";
201 $code[] =
"\t * @method {$objectClass}[] getAll()";
202 $code[] =
"\t * @method bool remove({$objectClass} \$object)";
203 $code[] =
"\t * @method void removeByPrimary(\$primary)";
204 $code[] =
"\t * @method void fill(\$fields = \\".FieldTypeMask::class.
"::ALL) flag or array of field names";
205 $code[] =
"\t * @method static {$collectionClass} wakeUp(\$data)";
206 $code[] =
"\t * @method \\".Result::class.
" save(\$ignoreEvents = false)";
207 $code[] =
"\t * @method void offsetSet() ArrayAccess";
208 $code[] =
"\t * @method void offsetExists() ArrayAccess";
209 $code[] =
"\t * @method void offsetUnset() ArrayAccess";
210 $code[] =
"\t * @method void offsetGet() ArrayAccess";
211 $code[] =
"\t * @method void rewind() Iterator";
212 $code[] =
"\t * @method {$objectClass} current() Iterator";
213 $code[] =
"\t * @method mixed key() Iterator";
214 $code[] =
"\t * @method void next() Iterator";
215 $code[] =
"\t * @method bool valid() Iterator";
216 $code[] =
"\t * @method int count() Countable";
217 $code[] =
"\t * @method {$collectionClassName} merge(?{$collectionClassName} \$collection)";
218 $code[] =
"\t * @method bool isEmpty()";
223 $code[] =
"\tclass {$collectionDefaultClassName} implements \ArrayAccess, \Iterator, \Countable {";
224 $code[] =
"\t\t/* @var {$dataClass} */";
225 $code[] =
"\t\tstatic public \$dataClass = '{$dataClass}';";
229 if (strpos($collectionClassName, Entity::DEFAULT_OBJECT_PREFIX) !== 0)
231 $defaultCollectionClassName = Entity::getDefaultCollectionClassName($entity->getName());
242 $dataClassName = $entity->getName().
'Table';
243 $queryClassName = Entity::DEFAULT_OBJECT_PREFIX.$entity->getName().
'_Query';
244 $resultClassName = Entity::DEFAULT_OBJECT_PREFIX.$entity->getName().
'_Result';
245 $entityClassName = Entity::DEFAULT_OBJECT_PREFIX.$entity->getName().
'_Entity';
247 $code[] =
"namespace {$entityNamespace} {";
255 $codeTable[] =
" * @method static {$queryClassName} query()";
256 $codeTable[] =
" * @method static {$resultClassName} getByPrimary(\$primary, array \$parameters = [])";
257 $codeTable[] =
" * @method static {$resultClassName} getById(\$id)";
258 $codeTable[] =
" * @method static {$resultClassName} getList(array \$parameters = [])";
259 $codeTable[] =
" * @method static {$entityClassName} getEntity()";
260 $codeTable[] =
" * @method static {$objectClass} createObject(\$setDefaultValues = true)";
261 $codeTable[] =
" * @method static {$collectionClass} createCollection()";
262 $codeTable[] =
" * @method static {$objectClass} wakeUpObject(\$row)";
263 $codeTable[] =
" * @method static {$collectionClass} wakeUpCollection(\$rows)";
268 foreach ($codeTable as $i => $line)
270 $codeTable[$i] =
"\t".$line;
273 $code = array_merge($code, $codeTable);
275 $code[] =
"\tclass {$dataClassName} extends \\".DataManager::class.
" {}";
280 $code[] =
"\t * Common methods:";
281 $code[] =
"\t * ---------------";
283 $code[] =
"\t * @method {$resultClassName} exec()";
284 $code[] =
"\t * @method {$objectClass} fetchObject()";
285 $code[] =
"\t * @method {$collectionClass} fetchCollection()";
287 $code[] =
"\t * Custom methods:";
288 $code[] =
"\t * ---------------";
291 foreach (get_class_methods($dataClass) as $method)
294 if (substr($method, 0, 4) ===
'with')
296 $reflectionMethod = new \ReflectionMethod($dataClass, $method);
298 if ($reflectionMethod->isStatic())
303 foreach (array_slice($reflectionMethod->getParameters(), 1) as $parameter)
305 $arguments[] =
'$'.$parameter->getName();
308 $argumentsMeta = join(
', ', $arguments);
310 $code[] =
"\t * @see {$dataClass}::{$method}()";
311 $code[] =
"\t * @method {$queryClassName} {$method}({$argumentsMeta})";
317 $code[] =
"\tclass {$queryClassName} extends \\".Query::class.
" {}";
321 $code[] =
"\t * @method {$objectClass} fetchObject()";
322 $code[] =
"\t * @method {$collectionClass} fetchCollection()";
324 $code[] =
"\tclass {$resultClassName} extends \\".\Bitrix\Main\ORM\Query\Result::class.
" {}";
328 $code[] =
"\t * @method {$objectClass} createObject(\$setDefaultValues = true)";
329 $code[] =
"\t * @method {$collectionClass} createCollection()";
330 $code[] =
"\t * @method {$objectClass} wakeUpObject(\$row)";
331 $code[] =
"\t * @method {$collectionClass} wakeUpCollection(\$rows)";
333 $code[] =
"\tclass {$entityClassName} extends \\".Entity::class.
" {}";
340 return join(
"\n", $code);
345 join(
"\n", $codeTable),
352 public static function annotateScalarField(ScalarField $field)
356 $objectClass = $field->getEntity()->getObjectClass();
357 $getterDataType = $field->getGetterTypeHint();
358 $setterDataType = $field->getSetterTypeHint();
359 list($lName, $uName) = static::getFieldNameCamelCase($field->getName());
362 $collectionCode = [];
364 $objectCode[] =
"\t * @method {$getterDataType} get{$uName}()";
365 $objectCode[] =
"\t * @method {$objectClass} set{$uName}({$setterDataType}|\\".SqlExpression::class.
" \${$lName})";
367 $objectCode[] =
"\t * @method bool has{$uName}()";
368 $objectCode[] =
"\t * @method bool is{$uName}Filled()";
369 $objectCode[] =
"\t * @method bool is{$uName}Changed()";
371 $collectionCode[] =
"\t * @method {$getterDataType}[] get{$uName}List()";
373 if (!$field->isPrimary())
375 $objectCode[] =
"\t * @method {$getterDataType} remindActual{$uName}()";
376 $objectCode[] =
"\t * @method {$getterDataType} require{$uName}()";
378 $objectCode[] =
"\t * @method {$objectClass} reset{$uName}()";
379 $objectCode[] =
"\t * @method {$objectClass} unset{$uName}()";
381 $objectCode[] =
"\t * @method {$getterDataType} fill{$uName}()";
382 $collectionCode[] =
"\t * @method {$getterDataType}[] fill{$uName}()";
385 return [$objectCode, $collectionCode];
388 public static function annotateUserType(UserTypeField $field)
391 $objectClass = $field->getEntity()->getObjectClass();
394 $scalarFieldClass = $field->getValueType();
396 $dataType = $field->isMultiple() ? $dataType.
'[]' : $dataType;
397 list($lName, $uName) = static::getFieldNameCamelCase($field->getName());
399 list($objectCode, $collectionCode) = static::annotateExpression($field);
402 $objectCode[] =
"\t * @method {$objectClass} set{$uName}({$dataType} \${$lName})";
404 $objectCode[] =
"\t * @method bool is{$uName}Changed()";
406 return [$objectCode, $collectionCode];
409 public static function annotateExpression(ExpressionField $field)
412 $objectClass = $field->getEntity()->getObjectClass();
414 $scalarFieldClass = $field->getValueType();
415 $dataType = (
new $scalarFieldClass(
'TMP'))->getGetterTypeHint();
416 list($lName, $uName) = static::getFieldNameCamelCase($field->getName());
419 $collectionCode = [];
421 $objectCode[] =
"\t * @method {$dataType} get{$uName}()";
422 $objectCode[] =
"\t * @method {$dataType} remindActual{$uName}()";
423 $objectCode[] =
"\t * @method {$dataType} require{$uName}()";
425 $objectCode[] =
"\t * @method bool has{$uName}()";
426 $objectCode[] =
"\t * @method bool is{$uName}Filled()";
428 $collectionCode[] =
"\t * @method {$dataType}[] get{$uName}List()";
430 $objectCode[] =
"\t * @method {$objectClass} unset{$uName}()";
432 $objectCode[] =
"\t * @method {$dataType} fill{$uName}()";
433 $collectionCode[] =
"\t * @method {$dataType}[] fill{$uName}()";
435 return [$objectCode, $collectionCode];
438 public static function annotateReference(Reference $field)
440 if (!static::tryToFindEntity($field->getRefEntityName()))
445 $objectClass = $field->getEntity()->getObjectClass();
446 $collectionClass = $field->getEntity()->getCollectionClass();
447 $collectionDataType = $field->getRefEntity()->getCollectionClass();
449 $getterTypeHint = $field->getGetterTypeHint();
450 $setterTypeHint = $field->getSetterTypeHint();
452 list($lName, $uName) = static::getFieldNameCamelCase($field->getName());
455 $collectionCode = [];
457 $objectCode[] =
"\t * @method {$getterTypeHint} get{$uName}()";
458 $objectCode[] =
"\t * @method {$getterTypeHint} remindActual{$uName}()";
459 $objectCode[] =
"\t * @method {$getterTypeHint} require{$uName}()";
461 $objectCode[] =
"\t * @method {$objectClass} set{$uName}({$setterTypeHint} \$object)";
462 $objectCode[] =
"\t * @method {$objectClass} reset{$uName}()";
463 $objectCode[] =
"\t * @method {$objectClass} unset{$uName}()";
465 $objectCode[] =
"\t * @method bool has{$uName}()";
466 $objectCode[] =
"\t * @method bool is{$uName}Filled()";
467 $objectCode[] =
"\t * @method bool is{$uName}Changed()";
469 $collectionCode[] =
"\t * @method {$getterTypeHint}[] get{$uName}List()";
470 $collectionCode[] =
"\t * @method {$collectionClass} get{$uName}Collection()";
472 $objectCode[] =
"\t * @method {$getterTypeHint} fill{$uName}()";
473 $collectionCode[] =
"\t * @method {$collectionDataType} fill{$uName}()";
475 return [$objectCode, $collectionCode];
478 public static function annotateOneToMany(OneToMany $field)
480 if (!static::tryToFindEntity($field->getRefEntityName()))
485 $objectClass = $field->getEntity()->getObjectClass();
486 $collectionDataType = $field->getRefEntity()->getCollectionClass();
487 $objectVarName = lcfirst($field->getRefEntity()->getName());
489 $setterTypeHint = $field->getSetterTypeHint();
491 list($lName, $uName) = static::getFieldNameCamelCase($field->getName());
494 $collectionCode = [];
496 $objectCode[] =
"\t * @method {$collectionDataType} get{$uName}()";
497 $objectCode[] =
"\t * @method {$collectionDataType} require{$uName}()";
498 $objectCode[] =
"\t * @method {$collectionDataType} fill{$uName}()";
500 $objectCode[] =
"\t * @method bool has{$uName}()";
501 $objectCode[] =
"\t * @method bool is{$uName}Filled()";
502 $objectCode[] =
"\t * @method bool is{$uName}Changed()";
504 $objectCode[] =
"\t * @method void addTo{$uName}({$setterTypeHint} \${$objectVarName})";
505 $objectCode[] =
"\t * @method void removeFrom{$uName}({$setterTypeHint} \${$objectVarName})";
506 $objectCode[] =
"\t * @method void removeAll{$uName}()";
508 $objectCode[] =
"\t * @method {$objectClass} reset{$uName}()";
509 $objectCode[] =
"\t * @method {$objectClass} unset{$uName}()";
511 $collectionCode[] =
"\t * @method {$collectionDataType}[] get{$uName}List()";
512 $collectionCode[] =
"\t * @method {$collectionDataType} get{$uName}Collection()";
513 $collectionCode[] =
"\t * @method {$collectionDataType} fill{$uName}()";
515 return [$objectCode, $collectionCode];
518 public static function annotateManyToMany(ManyToMany $field)
520 if (!static::tryToFindEntity($field->getRefEntityName()))
525 $objectClass = $field->getEntity()->getObjectClass();
526 $collectionDataType = $field->getRefEntity()->getCollectionClass();
527 $objectVarName = lcfirst($field->getRefEntity()->getName());
529 $setterTypeHint = $field->getSetterTypeHint();
531 list($lName, $uName) = static::getFieldNameCamelCase($field->getName());
534 $collectionCode = [];
536 $objectCode[] =
"\t * @method {$collectionDataType} get{$uName}()";
537 $objectCode[] =
"\t * @method {$collectionDataType} require{$uName}()";
538 $objectCode[] =
"\t * @method {$collectionDataType} fill{$uName}()";
540 $objectCode[] =
"\t * @method bool has{$uName}()";
541 $objectCode[] =
"\t * @method bool is{$uName}Filled()";
542 $objectCode[] =
"\t * @method bool is{$uName}Changed()";
544 $objectCode[] =
"\t * @method void addTo{$uName}({$setterTypeHint} \${$objectVarName})";
545 $objectCode[] =
"\t * @method void removeFrom{$uName}({$setterTypeHint} \${$objectVarName})";
546 $objectCode[] =
"\t * @method void removeAll{$uName}()";
548 $objectCode[] =
"\t * @method {$objectClass} reset{$uName}()";
549 $objectCode[] =
"\t * @method {$objectClass} unset{$uName}()";
551 $collectionCode[] =
"\t * @method {$collectionDataType}[] get{$uName}List()";
552 $collectionCode[] =
"\t * @method {$collectionDataType} get{$uName}Collection()";
553 $collectionCode[] =
"\t * @method {$collectionDataType} fill{$uName}()";
555 return [$objectCode, $collectionCode];
558 public static function tryToFindEntity($entityClass)
560 $entityClass = Entity::normalizeEntityClass($entityClass);
562 if (!class_exists($entityClass))
565 $classParts = array_values(array_filter(
566 explode(
'\\', strtolower($entityClass))
569 if ($classParts[0] ==
'bitrix')
571 $moduleName = $classParts[1];
575 $moduleName = $classParts[0].
'.'.$classParts[1];
584 if ((
new \ReflectionClass($entityClass))->isAbstract())
592 protected static function getFieldNameCamelCase($fieldName)
594 $upperFirstName = StringHelper::snake2camel($fieldName);
595 $lowerFirstName = lcfirst($upperFirstName);
597 return [$lowerFirstName, $upperFirstName];
static includeModule($moduleName)