Class yii\apidoc\models\Context
| Inheritance | yii\apidoc\models\Context » yii\base\Component |
|---|---|
| Source Code | https://github.com/yiisoft/yii2-apidoc/blob/master/models/Context.php |
Public Properties
| Property | Type | Description | Defined By |
|---|---|---|---|
| $classes | yii\apidoc\models\ClassDoc[] | yii\apidoc\models\Context | |
| $errors | array | yii\apidoc\models\Context | |
| $files | array | List of php files that have been added to this context. | yii\apidoc\models\Context |
| $interfaces | yii\apidoc\models\InterfaceDoc[] | yii\apidoc\models\Context | |
| $reflectionProject | \phpDocumentor\Reflection\Php\Project | yii\apidoc\models\Context | |
| $traits | yii\apidoc\models\TraitDoc[] | yii\apidoc\models\Context | |
| $warnings | array | yii\apidoc\models\Context |
Public Methods
| Method | Description | Defined By |
|---|---|---|
| addFile() | Adds file to context | yii\apidoc\models\Context |
| getReflectionProject() | yii\apidoc\models\Context | |
| getType() | Returning TypeDoc for a type given | yii\apidoc\models\Context |
| processFiles() | yii\apidoc\models\Context | |
| updateReferences() | yii\apidoc\models\Context |
Protected Methods
| Method | Description | Defined By |
|---|---|---|
| handleClassInheritance() | yii\apidoc\models\Context | |
| handlePropertyFeature() | Add properties for getters and setters if class is subclass of \yii\base\BaseObject. | yii\apidoc\models\Context |
| handleTraitInheritance() | yii\apidoc\models\Context | |
| inheritDocs() | Inherit docsblocks using @inheritDoc tag. |
yii\apidoc\models\Context |
| isSubclassOf() | yii\apidoc\models\Context | |
| updateSubInterfaceInheritance() | Add methods to subinterfaces | yii\apidoc\models\Context |
| updateSubclassInterfacesTraits() | Add implemented interfaces and used traits to subclasses | yii\apidoc\models\Context |
Property Details
List of php files that have been added to this context.
Method Details
Adds file to context
| public mixed addFile ( string $fileName ) | ||
| $fileName | string | |
public function addFile($fileName)
{
$this->files[$fileName] = sha1_file($fileName);
}
| public \phpDocumentor\Reflection\Php\Project getReflectionProject ( ) |
public function getReflectionProject()
{
$files = [];
foreach ($this->files as $fileName => $hash) {
$files[] = new LocalFile($fileName);
}
$projectFactory = ProjectFactory::createInstance();
$docBlockFactory = DocBlockFactory::createInstance();
$priority = 1200;
$projectFactory->addStrategy(new ClassConstantFactory($docBlockFactory, new PrettyPrinter()), $priority);
$projectFactory->addStrategy(new PropertyFactory($docBlockFactory, new PrettyPrinter()), $priority);
/** @var Project $project */
$project = $projectFactory->create('ApiDoc', $files);
return $project;
}
Returning TypeDoc for a type given
| public null|yii\apidoc\models\ClassDoc|yii\apidoc\models\InterfaceDoc|yii\apidoc\models\TraitDoc getType ( string $type ) | ||
| $type | string | |
public function getType($type)
{
$type = ltrim($type, '\\');
return $this->classes[$type] ?? $this->interfaces[$type] ?? $this->traits[$type] ?? null;
}
| protected mixed handleClassInheritance ( yii\apidoc\models\ClassDoc $class ) | ||
| $class | yii\apidoc\models\ClassDoc | |
protected function handleClassInheritance($class)
{
$parents = $this->getParents($class);
if (!$parents) {
return;
}
$attrNames = ['events', 'constants', 'properties', 'methods'];
foreach ($parents as $parent) {
$parent = $this->classes[$parent->name];
foreach ($attrNames as $attrName) {
foreach ($parent->$attrName as $item) {
if (
isset($class->$attrName[$item->name]) &&
!isset($this->traits[$class->$attrName[$item->name]->definedBy])
) {
continue;
}
$class->$attrName[$item->name] = $item;
}
}
}
}
Add properties for getters and setters if class is subclass of \yii\base\BaseObject.
| protected mixed handlePropertyFeature ( yii\apidoc\models\ClassDoc $class ) | ||
| $class | yii\apidoc\models\ClassDoc | |
protected function handlePropertyFeature($class)
{
if (!$this->isSubclassOf($class, 'yii\base\BaseObject')) {
return;
}
foreach ($class->getPublicMethods() as $name => $method) {
if ($method->isStatic) {
continue;
}
if (!strncmp((string) $name, 'get', 3) && strlen((string) $name) > 3 && $this->hasNonOptionalParams($method)) {
$propertyName = '$' . lcfirst(substr((string) $method->name, 3));
$property = $class->properties[$propertyName] ?? null;
if ($property && $property->getter === null && $property->setter === null) {
$this->errors[] = [
'line' => $property->startLine,
'file' => $class->sourceFile,
'message' => "Property $propertyName conflicts with a defined getter {$method->name} in {$class->name}.",
];
} else {
$descriptions = TextHelper::getDescriptionsByFullDescription((string) $method->return);
// Override the setter-defined property if it exists already
$class->properties[$propertyName] = new PropertyDoc($class, null, $this, [
'name' => $propertyName,
'fullName' => "$class->name::$propertyName",
'definedBy' => $method->definedBy,
'sourceFile' => $class->sourceFile,
'visibility' => 'public',
'isStatic' => false,
'type' => $method->returnType,
'shortDescription' => $descriptions['short'],
'description' => $descriptions['detailed'],
'since' => $method->since,
'getter' => $method,
'setter' => $property->setter ?? null,
// TODO set default value
]);
}
}
if (!strncmp((string) $name, 'set', 3) && strlen((string) $name) > 3 && $this->hasNonOptionalParams($method, 1)) {
$propertyName = '$' . lcfirst(substr((string) $method->name, 3));
$property = $class->properties[$propertyName] ?? null;
if ($property) {
if ($property->getter === null && $property->setter === null) {
$this->errors[] = [
'line' => $property->startLine,
'file' => $class->sourceFile,
'message' => "Property $propertyName conflicts with a defined setter {$method->name} in {$class->name}.",
];
} else {
// Just set the setter
$property->setter = $method;
}
} else {
$param = $this->getFirstNotOptionalParameter($method);
$descriptions = TextHelper::getDescriptionsByFullDescription((string) $param->description);
$class->properties[$propertyName] = new PropertyDoc($class, null, $this, [
'name' => $propertyName,
'fullName' => "$class->name::$propertyName",
'definedBy' => $method->definedBy,
'sourceFile' => $class->sourceFile,
'visibility' => 'public',
'isStatic' => false,
'type' => $param->type,
'shortDescription' => $descriptions['short'],
'description' => $descriptions['detailed'],
'since' => $method->since,
'setter' => $method,
]);
}
}
}
}
| protected mixed handleTraitInheritance ( yii\apidoc\models\ClassDoc $class ) | ||
| $class | yii\apidoc\models\ClassDoc | |
protected function handleTraitInheritance($class)
{
foreach ($class->traits as $traitName) {
if (!isset($this->traits[$traitName])) {
continue;
}
$trait = $this->traits[$traitName];
$trait->usedBy[] = $class->name;
foreach ($trait->properties as $property) {
if (!isset($class->properties[$property->name])) {
$class->properties[$property->name] = $property;
}
}
foreach ($trait->methods as $method) {
if (!isset($class->methods[$method->name])) {
$class->methods[$method->name] = $method;
}
}
foreach ($trait->constants as $constant) {
if (!isset($class->constants[$constant->name])) {
$class->constants[$constant->name] = $constant;
}
}
}
}
Inherit docsblocks using @inheritDoc tag.
See also https://docs.phpdoc.org/3.0/guide/guides/inheritance.html.
| protected mixed inheritDocs ( yii\apidoc\models\ClassDoc $class ) | ||
| $class | yii\apidoc\models\ClassDoc | |
protected function inheritDocs($class)
{
if ($class->hasTag(BaseDoc::INHERITDOC_TAG_NAME)) {
$inheritTag = $class->getFirstTag(BaseDoc::INHERITDOC_TAG_NAME);
$parentClass = $this->classes[$class->parentClass] ?? null;
if ($inheritTag !== null && $parentClass !== null) {
$class->shortDescription = $parentClass->shortDescription;
$class->description = $this->inheritDescription(
$class->description,
$parentClass->description,
$inheritTag,
);
$class->removeTag(BaseDoc::INHERITDOC_TAG_NAME);
}
}
// inherit for properties
foreach ($class->properties as $p) {
if (
$p->hasTag(BaseDoc::INHERITDOC_TAG_NAME)
&& ($inheritTag = $p->getFirstTag(BaseDoc::INHERITDOC_TAG_NAME)) !== null
) {
$inheritedProperty = $this->inheritPropertyRecursive($p, $class);
if (!$inheritedProperty) {
$this->errors[] = [
'line' => $p->startLine,
'file' => $class->sourceFile,
'message' => "Property {$p->name} has no parent to inherit from in {$class->name}.",
];
continue;
}
// set all properties that are empty.
foreach (['shortDescription', 'type', 'since'] as $property) {
if (empty($p->$property) || is_string($p->$property) && trim($p->$property) === '') {
// only copy @since if the package names are equal (or missing)
if ($property === 'since' && $p->getPackageName() !== $inheritedProperty->getPackageName()) {
continue;
}
$p->$property = $inheritedProperty->$property;
}
}
// descriptions will be concatenated.
$p->description = $this->inheritDescription(
$p->description,
$inheritedProperty->description,
$inheritTag
);
$p->removeTag(BaseDoc::INHERITDOC_TAG_NAME);
}
}
// inherit for methods
foreach ($class->methods as $m) {
if (
$m->hasTag(BaseDoc::INHERITDOC_TAG_NAME)
&& ($inheritTag = $m->getFirstTag(BaseDoc::INHERITDOC_TAG_NAME)) !== null
) {
$inheritedMethod = $this->inheritMethodRecursive($m, $class);
if (!$inheritedMethod) {
$this->errors[] = [
'line' => $m->startLine,
'file' => $class->sourceFile,
'message' => "Method {$m->name} has no parent to inherit from in {$class->name}.",
];
continue;
}
// set all properties that are empty.
foreach (['shortDescription', 'return', 'returnType', 'exceptions', 'since'] as $property) {
if (empty($m->$property) || is_string($m->$property) && trim($m->$property) === '') {
// only copy @since if the package names are equal (or missing)
if ($property === 'since' && $m->getPackageName() !== $inheritedMethod->getPackageName()) {
continue;
}
$m->$property = $inheritedMethod->$property;
}
}
// descriptions will be concatenated.
$m->description = $this->inheritDescription(
$m->description,
$inheritedMethod->description,
$inheritTag,
);
foreach ($m->params as $i => $param) {
if (!isset($inheritedMethod->params[$i])) {
$this->errors[] = [
'line' => $m->startLine,
'file' => $class->sourceFile,
'message' => "Method param $i does not exist in parent method, @inheritdoc not possible in {$m->name} in {$class->name}.",
];
continue;
}
if (empty($param->description) || trim((string) $param->description) === '') {
$param->description = $inheritedMethod->params[$i]->description;
}
if ($param->type === null) {
$param->type = $inheritedMethod->params[$i]->type;
}
}
$m->removeTag(BaseDoc::INHERITDOC_TAG_NAME);
}
}
}
| protected boolean isSubclassOf ( yii\apidoc\models\ClassDoc $classA, yii\apidoc\models\ClassDoc|string $classB ) | ||
| $classA | yii\apidoc\models\ClassDoc | |
| $classB | yii\apidoc\models\ClassDoc|string | |
protected function isSubclassOf($classA, $classB)
{
if (is_object($classB)) {
$classB = $classB->name;
}
if ($classA->name == $classB) {
return true;
}
while ($classA->parentClass !== null && isset($this->classes[$classA->parentClass])) {
$classA = $this->classes[$classA->parentClass];
if ($classA->name == $classB) {
return true;
}
}
return false;
}
| public mixed processFiles ( ) |
public function processFiles()
{
$projectFiles = $this->getReflectionProject()->getFiles();
foreach ($this->files as $fileName => $hash) {
$reflection = $projectFiles[$fileName];
$this->parseFile($reflection, $fileName);
}
}
| public mixed updateReferences ( ) |
public function updateReferences()
{
// update all subclass references
foreach ($this->classes as $class) {
$className = $class->name;
while ($class->parentClass !== null && isset($this->classes[$class->parentClass])) {
$class = $this->classes[$class->parentClass];
$class->subclasses[] = $className;
}
}
// update interfaces of subclasses
foreach ($this->classes as $class) {
$this->updateSubclassInterfacesTraits($class);
}
// update implementedBy and usedBy for traits
foreach ($this->classes as $class) {
$this->handleTraitInheritance($class);
}
foreach ($this->interfaces as $interface) {
foreach ($interface->parentInterfaces as $pInterface) {
if (isset($this->interfaces[$pInterface])) {
$this->interfaces[$pInterface]->implementedBy[] = $interface->name;
}
}
}
// inherit docs
foreach ($this->classes as $class) {
$this->inheritDocs($class);
}
// inherit properties, methods, constants and events from parent classes
foreach ($this->classes as $class) {
$this->handleClassInheritance($class);
}
// update implementedBy and usedBy for interfaces
foreach ($this->classes as $class) {
$this->handleInterfaceInheritance($class);
}
foreach ($this->interfaces as $interface) {
$this->updateSubInterfaceInheritance($interface);
}
// add properties from getters and setters
foreach ($this->classes as $class) {
$this->handlePropertyFeature($class);
}
// TODO reference exceptions to methods where they are thrown
}
Add methods to subinterfaces
| protected mixed updateSubInterfaceInheritance ( yii\apidoc\models\InterfaceDoc $interface ) | ||
| $interface | yii\apidoc\models\InterfaceDoc | |
protected function updateSubInterfaceInheritance($interface)
{
foreach ($interface->implementedBy as $name) {
if (!isset($this->interfaces[$name])) {
continue;
}
$subInterface = $this->interfaces[$name];
$subInterface->methods = array_merge($interface->methods, $subInterface->methods);
$subInterface->constants = array_merge($interface->constants, $subInterface->constants);
$this->updateSubInterfaceInheritance($subInterface);
}
}
Add implemented interfaces and used traits to subclasses
| protected mixed updateSubclassInterfacesTraits ( yii\apidoc\models\ClassDoc $class ) | ||
| $class | yii\apidoc\models\ClassDoc | |
protected function updateSubclassInterfacesTraits($class)
{
foreach ($class->subclasses as $subclass) {
$subclass = $this->classes[$subclass];
$subclass->interfaces = array_unique(array_merge($subclass->interfaces, $class->interfaces));
$subclass->traits = array_unique(array_merge($subclass->traits, $class->traits));
$this->updateSubclassInterfacesTraits($subclass);
}
}