Class yii\apidoc\models\Context

Inheritanceyii\apidoc\models\Context » yii\base\Component
Available since extension's version2.0
Source Code https://github.com/yiisoft/yii2-apidoc/blob/master/models/Context.php

Public Methods

Hide inherited methods

Method Description Defined By
addFile() Adds file to context yii\apidoc\models\Context
getType() Returning TypeDoc for a type given yii\apidoc\models\Context
updateReferences() Updates references yii\apidoc\models\Context

Protected Methods

Hide inherited methods

Method Description Defined By
handlePropertyFeature() Add properties for getters and setters if class is subclass of \yii\base\BaseObject. 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
updateSubclassInheritance() Add implemented interfaces and used traits to subclasses 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
$traits public property
$warnings public property (available since version 2.0.6)
public array $warnings = []

Method Details

Hide inherited methods

addFile() public method

Adds file to context

public void addFile ( $fileName )
$fileName string

                public function addFile($fileName)
{
    $this->files[$fileName] = sha1_file($fileName);
    $reflection = new FileReflector($fileName, true);
    $reflection->process();
    foreach ($reflection->getClasses() as $class) {
        $class = new ClassDoc($class, $this, ['sourceFile' => $fileName]);
        $this->classes[$class->name] = $class;
    }
    foreach ($reflection->getInterfaces() as $interface) {
        $interface = new InterfaceDoc($interface, $this, ['sourceFile' => $fileName]);
        $this->interfaces[$interface->name] = $interface;
    }
    foreach ($reflection->getTraits() as $trait) {
        $trait = new TraitDoc($trait, $this, ['sourceFile' => $fileName]);
        $this->traits[$trait->name] = $trait;
    }
}

            
getType() public method

Returning TypeDoc for a type given

public null|yii\apidoc\models\ClassDoc|yii\apidoc\models\InterfaceDoc|yii\apidoc\models\TraitDoc getType ( $type )
$type string

                public function getType($type)
{
    $type = ltrim($type, '\\');
    if (isset($this->classes[$type])) {
        return $this->classes[$type];
    } elseif (isset($this->interfaces[$type])) {
        return $this->interfaces[$type];
    } elseif (isset($this->traits[$type])) {
        return $this->traits[$type];
    }
    return null;
}

            
handlePropertyFeature() protected method

Add properties for getters and setters if class is subclass of \yii\base\BaseObject.

protected void handlePropertyFeature ( $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($name, 'get', 3) && strlen($name) > 3 && $this->hasNonOptionalParams($method)) {
            $propertyName = '$' . lcfirst(substr($method->name, 3));
            $property = isset($class->properties[$propertyName]) ? $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 {
                // Override the setter-defined property if it exists already
                $class->properties[$propertyName] = new PropertyDoc(null, $this, [
                    'name' => $propertyName,
                    'definedBy' => $method->definedBy,
                    'sourceFile' => $class->sourceFile,
                    'visibility' => 'public',
                    'isStatic' => false,
                    'type' => $method->returnType,
                    'types' => $method->returnTypes,
                    'shortDescription' => BaseDoc::extractFirstSentence($method->return),
                    'description' => $method->return,
                    'since' => $method->since,
                    'getter' => $method,
                    'setter' => isset($property->setter) ? $property->setter : null,
                    // TODO set default value
                ]);
            }
        }
        if (!strncmp($name, 'set', 3) && strlen($name) > 3 && $this->hasNonOptionalParams($method, 1)) {
            $propertyName = '$' . lcfirst(substr($method->name, 3));
            $property = isset($class->properties[$propertyName]) ? $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);
                $class->properties[$propertyName] = new PropertyDoc(null, $this, [
                    'name' => $propertyName,
                    'definedBy' => $method->definedBy,
                    'sourceFile' => $class->sourceFile,
                    'visibility' => 'public',
                    'isStatic' => false,
                    'type' => $param->type,
                    'types' => $param->types,
                    'shortDescription' => BaseDoc::extractFirstSentence($param->description),
                    'description' => $param->description,
                    'since' => $method->since,
                    'setter' => $method,
                ]);
            }
        }
    }
}

            
inheritDocs() protected method

Inherit docsblocks using @inheritDoc tag.

See also http://phpdoc.org/docs/latest/guides/inheritance.html.

protected void inheritDocs ( $class )
$class yii\apidoc\models\ClassDoc

                protected function inheritDocs($class)
{
    // inherit for properties
    foreach ($class->properties as $p) {
        if ($p->hasTag('inheritdoc') && ($inheritTag = $p->getFirstTag('inheritdoc')) !== null) {
            $inheritedProperty = $this->inheritPropertyRecursive($p, $class);
            if (!$inheritedProperty) {
                $this->errors[] = [
                    'line' => $p->startLine,
                    'file' => $class->sourceFile,
                    'message' => "Method {$p->name} has no parent to inherit from in {$class->name}.",
                ];
                continue;
            }
            // set all properties that are empty.
            foreach (['shortDescription', 'type', 'types', '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 = trim($p->description) . "\n\n"
                . trim($inheritedProperty->description) . "\n\n"
                . $inheritTag->getContent();
            $p->removeTag('inheritdoc');
        }
    }
    // inherit for methods
    foreach ($class->methods as $m) {
        if ($m->hasTag('inheritdoc') && ($inheritTag = $m->getFirstTag('inheritdoc')) !== 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', 'returnTypes', '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 = trim($m->description) . "\n\n"
                . trim($inheritedMethod->description) . "\n\n"
                . $inheritTag->getContent();
            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($param->description) === '') {
                    $param->description = $inheritedMethod->params[$i]->description;
                }
                if (empty($param->type) || trim($param->type) === '') {
                    $param->type = $inheritedMethod->params[$i]->type;
                }
                if (empty($param->types)) {
                    $param->types = $inheritedMethod->params[$i]->types;
                }
            }
            $m->removeTag('inheritdoc');
        }
    }
}

            
isSubclassOf() protected method

protected boolean isSubclassOf ( $classA, $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;
}

            
updateReferences() public method

Updates references

public void updateReferences ( )

                public function updateReferences()
{
    // update all subclass references
    foreach ($this->classes as $class) {
        $className = $class->name;
        while (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 interfaces and traits
    foreach ($this->classes as $class) {
        foreach ($class->traits as $trait) {
            if (isset($this->traits[$trait])) {
                $trait = $this->traits[$trait];
                $trait->usedBy[] = $class->name;
                $class->properties = array_merge($trait->properties, $class->properties);
                $class->methods = array_merge($trait->methods, $class->methods);
            }
        }
        foreach ($class->interfaces as $interface) {
            if (isset($this->interfaces[$interface])) {
                $this->interfaces[$interface]->implementedBy[] = $class->name;
                if ($class->isAbstract) {
                    // add not implemented interface methods
                    foreach ($this->interfaces[$interface]->methods as $method) {
                        if (!isset($class->methods[$method->name])) {
                            $class->methods[$method->name] = $method;
                        }
                    }
                }
            }
        }
    }
    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 to subclasses
    foreach ($this->classes as $class) {
        $this->updateSubclassInheritance($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 void updateSubInterfaceInheritance ( $interface )
$interface yii\apidoc\models\InterfaceDoc

                protected function updateSubInterfaceInheritance($interface)
{
    foreach ($interface->implementedBy as $subInterface) {
        if (isset($this->interfaces[$subInterface])) {
            $subInterface = $this->interfaces[$subInterface];
            $subInterface->methods = array_merge($interface->methods, $subInterface->methods);
            $this->updateSubInterfaceInheritance($subInterface);
        }
    }
}

            
updateSubclassInheritance() protected method

Add implemented interfaces and used traits to subclasses

protected void updateSubclassInheritance ( $class )
$class yii\apidoc\models\ClassDoc

                protected function updateSubclassInheritance($class)
{
    foreach ($class->subclasses as $subclass) {
        $subclass = $this->classes[$subclass];
        $subclass->events = array_merge($class->events, $subclass->events);
        $subclass->constants = array_merge($class->constants, $subclass->constants);
        $subclass->properties = array_merge($class->properties, $subclass->properties);
        $subclass->methods = array_merge($class->methods, $subclass->methods);
        $this->updateSubclassInheritance($subclass);
    }
}

            
updateSubclassInterfacesTraits() protected method

Add implemented interfaces and used traits to subclasses

protected void updateSubclassInterfacesTraits ( $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);
    }
}