Class yii\apidoc\models\Context

Inheritanceyii\apidoc\models\Context » yii\base\Component
Source Code https://github.com/yiisoft/yii2-apidoc/blob/master/models/Context.php

Protected Methods

Hide inherited 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

Hide inherited properties

$classes public property
$errors public property
public array $errors = []
$files public property

List of php files that have been added to this context.

public array $files = []
$interfaces public property
$reflectionProject public property
public \phpDocumentor\Reflection\Php\Project $reflectionProject null
$traits public property
$warnings public property
public array $warnings = []

Method Details

Hide inherited methods

addFile() public method

Adds file to context

public mixed addFile ( string $fileName )
$fileName string

                public function addFile($fileName)
{
    $this->files[$fileName] = sha1_file($fileName);
}

            
getReflectionProject() public method

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;
}

            
getType() public method

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;
}

            
handleClassInheritance() protected method

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;
            }
        }
    }
}

            
handlePropertyFeature() protected method

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,
                ]);
            }
        }
    }
}

            
handleTraitInheritance() protected 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;
            }
        }
    }
}

            
inheritDocs() protected method

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);
        }
    }
}

            
isSubclassOf() protected method

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;
}

            
processFiles() public method

public mixed processFiles ( )

                public function processFiles()
{
    $projectFiles = $this->getReflectionProject()->getFiles();
    foreach ($this->files as $fileName => $hash) {
        $reflection = $projectFiles[$fileName];
        $this->parseFile($reflection, $fileName);
    }
}

            
updateReferences() public method

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
}

            
updateSubInterfaceInheritance() protected method

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);
    }
}

            
updateSubclassInterfacesTraits() protected method

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);
    }
}