Skip to content

Commit

Permalink
Merge pull request #9 from timber/next
Browse files Browse the repository at this point in the history
fix: Add inherited methods and properties to Class Reference
  • Loading branch information
gchtr authored Jul 3, 2024
2 parents 5c6e8cd + ccb55bf commit b5e172a
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 50 deletions.
9 changes: 0 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,6 @@ You can install the package with Composer:
composer require timber/teak --dev
```

Currently, the required packages for Teak require a minimum stability of `alpha`. To load stable version for all packages, but still be able to load Teak into your project, you can use the following config in your **composer.json** file:

```json
{
"minimum-stability": "alpha",
"prefer-stable": true
}
```

## CLI Usage

### Generate a class reference
Expand Down
11 changes: 4 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,11 @@
}
],
"require": {
"php": ">=7.4.0",
"phpdocumentor/reflection": "^5.0",
"php": ">=8.1.0",
"phpdocumentor/reflection": "^6.0",
"phpdocumentor/reflection-docblock": "^5.3",
"symfony/console": "^4.0",
"symfony/filesystem": "^4.0"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
"symfony/console": "^7",
"symfony/filesystem": "^7"
},
"autoload": {
"psr-4": {
Expand Down
8 changes: 4 additions & 4 deletions lib/Compiler/ClassReference.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ class ClassReference implements CompilerInterface
*
* @param \phpDocumentor\Reflection\Php\Class_ $class
*/
public function __construct($class)
public function __construct(ClassReflection $classReflection)
{
$this->reflection = $class;
$this->class = new ClassReflection($class);
$this->reflection = $classReflection->reflection;
$this->class = $classReflection;
}

/**
Expand Down Expand Up @@ -68,7 +68,7 @@ public function compile()
$contents .= (new Example($this->class->getDocBlock()))->compile();

// Class properties and methods table
$contents .= (new ApiTable($this->reflection))->compile();
$contents .= (new ApiTable($this->class))->compile();

$contents .= (new Heading('Class Methods', 2))->compile();

Expand Down
10 changes: 2 additions & 8 deletions lib/Compiler/Class_/ApiTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,14 @@ class ApiTable extends Reflection implements CompilerInterface
*/
public $class;

/**
* @var \phpDocumentor\Reflection\Php\Class_
*/
public $reflection;

/**
* ClassApiTableCompiler constructor.
*
* @param \phpDocumentor\Reflection\Php\Class_ $class
* @param ClassReflection $class
*/
public function __construct($class)
{
$this->class = new ClassReflection($class);
$this->reflection = $class;
$this->class = $class;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/Compiler/SanitizeTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public function sanitizeAnchor($link)

public function removeLineBreaks($text)
{
return str_replace(PHP_EOL, ' ', $text);
return str_replace(PHP_EOL, ' ', $text ?? '');
}

public function escapeMarkdownChars($text)
Expand Down
3 changes: 2 additions & 1 deletion lib/Compiler/Tag/Example.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class Example implements CompilerInterface
public function __construct($docBlock)
{
$docBlock = new DocBlock($docBlock);
$this->tag = trim($docBlock->getTag('example'));

$this->tag = trim($docBlock->getTag('example') ?? '');
}

/**
Expand Down
6 changes: 3 additions & 3 deletions lib/Console/ClassReferenceGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ protected function handleClassCollection($input, $output, $files)
// Make sure there’s a trailing slash.
$outputFolder = rtrim($input->getOption(self::OPT_OUTPUT), '/') . '/';

foreach ($classReferenceHandler->getClassList() as $class) {
$contents = $classReferenceHandler->compile($class);
foreach ($classReferenceHandler->getClassList() as $classReflection) {
$contents = $classReferenceHandler->compileClass($classReflection);

$filename = $filePrefix . mb_strtolower(str_replace("\\", '-', ltrim($class->getFqsen(), "\\"))) . '.md';
$filename = $filePrefix . mb_strtolower(str_replace("\\", '-', ltrim($classReflection->reflection->getFqsen(), "\\"))) . '.md';
$filepath = $outputFolder . $filename;

try {
Expand Down
67 changes: 54 additions & 13 deletions lib/Console/ClassReferenceHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use phpDocumentor\Reflection\Php\Class_;
use phpDocumentor\Reflection\Php\ProjectFactory;
use phpDocumentor\Reflection\Project;
use Teak\Compiler\ClassLinkList;
use Teak\Compiler\ClassReference;
use Teak\Compiler\FrontMatter\Yaml;
Expand All @@ -13,7 +14,7 @@
class ClassReferenceHandler
{
protected $options;
protected $project;
protected Project $project;

public function __construct($files, $options = [])
{
Expand All @@ -28,30 +29,33 @@ public function __construct($files, $options = [])
ClassLinkList::getInstance()->generate($this->project, $this->options['filePrefix']);
}

public function getClassList()
/**
* @return ClassReflection[]
*/
public function getClassList(): array
{
return $this->generateClassList($this->project);
}

/**
* @param Class_ $class
* @param ClassReflection $classReflection
*
* @return string
*/
public function compile($class)
public function compileClass(ClassReflection $classReflection)
{
$contents = '';

if (empty($this->options['frontMatterStyle'])) {
$contents .= (new Heading($class->getName(), 1))->compile();
$contents .= (new Heading($classReflection->getName(), 1))->compile();
} elseif ('YAML' === $this->options['frontMatterStyle']) {
$contents = (new Yaml(
$class->getFqsen(),
$class->getName()
$classReflection->reflection->getFqsen(),
$classReflection->getName()
))->compile();
}

$classReference = new ClassReference($class);
$classReference = new ClassReference($classReflection);
$contents .= $classReference->compile();

return $contents;
Expand All @@ -60,24 +64,61 @@ public function compile($class)
/**
* @param \phpDocumentor\Reflection\Php\Project $project
*
* @return Class_[]
* @return ClassReflection[]
*/
protected function generateClassList($project)
{
$classes = [];
$classReflections = [];
$files = $project->getFiles();

$classMap = [];

foreach ($project->getFiles() as $file) {
foreach ($files as $file) {
foreach ($file->getClasses() as $class) {
$classMap[$class->getFqsen()->__toString() ] = $class;
}
}

foreach ($files as $file) {
foreach ($file->getClasses() as $class) {
$classReflection = new ClassReflection($class);
$parents = $this->getParentsRecursive($class, $classMap);

foreach ($parents as $parent) {
$classReflection->addParentInformation($parent);
}

if ($classReflection->shouldIgnore()) {
continue;
}

$classes[] = $class;
$classReflections[] = $classReflection;
}
}

return $classes;
return $classReflections;
}

protected function getParentsRecursive($class, $classMap)
{
$parents = [];

if ($class->getParent()) {
$parent = $class->getParent();
$parentClass = $classMap[$parent->__toString()] ?? null;

if ($parentClass) {
$parents[] = $parentClass;

$parents = array_merge($parents, $this->getParentsRecursive($parentClass, $classMap));
}
}

return $parents;
}

public function getProject() : Project
{
return $this->project;
}
}
8 changes: 5 additions & 3 deletions lib/Console/ReferenceGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ protected function configure()
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int|null|void
* @return int
* @throws \InvalidArgumentException
*/
protected function execute(InputInterface $input, OutputInterface $output)
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$files = $this->getFiles($input);
$message = $this->handleClassCollection($input, $output, $files);
Expand All @@ -102,6 +102,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
}

$output->writeln($message);

return 0;
}

/**
Expand All @@ -114,7 +116,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
public function getFiles(InputInterface $input)
{
$files = $input->getArgument(self::ARG_FILES);
$ignore = explode(',', $input->getOption(self::OPT_IGNORE));
$ignore = explode(',', $input->getOption(self::OPT_IGNORE) ?: '');

if (is_dir($files)) {
$files = $this->getFilesInFolder($files, $ignore);
Expand Down
29 changes: 29 additions & 0 deletions lib/Reflection/ClassReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
*/
class ClassReflection extends Reflection
{
private array $parentMethods = [];
private array $parentProperties = [];

/**
* ClassReflection constructor.
*
Expand All @@ -17,6 +20,12 @@ public function __construct($reflection)
parent::__construct($reflection);
}

public function addParentInformation($parentClass)
{
$this->parentMethods = array_merge($this->parentMethods, $parentClass->getMethods());
$this->parentProperties = $parentClass->getProperties();
}

public function hasMethods()
{
if (method_exists($this, 'getMethods')) {
Expand All @@ -29,20 +38,40 @@ public function hasMethods()
public function getMethods()
{
$methods = $this->reflection->getMethods();

if ($this->reflection->getParent() && !empty($this->parentMethods)) {
$methods = array_merge($methods, $this->parentMethods);
}

$methods = array_filter($methods, function ($item) {
return ! (new Reflection($item))->shouldIgnore();
});

// Sort methods by name.
usort($methods, function ($a, $b) {
return strcmp($a->getName(), $b->getName());
});

return $methods;
}

public function getProperties()
{
$properties = $this->reflection->getProperties();

if ($this->reflection->getParent() && !empty($this->parentProperties)) {
$properties = array_merge($properties, $this->parentProperties);
}

$properties = array_filter($properties, function ($item) {
return ! (new Reflection($item))->shouldIgnore();
});

// Sort properties by name.
usort($properties, function ($a, $b) {
return strcmp($a->getName(), $b->getName());
});

return $properties;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/ClassCompilerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function testDefault()
$classReferenceHandler = new ClassReferenceHandler($files);

foreach ($classReferenceHandler->getClassList() as $class) {
$contents = $classReferenceHandler->compile($class);
$contents = $classReferenceHandler->compileClass($class);
}

/*$fs = new FileSystem();
Expand Down

0 comments on commit b5e172a

Please sign in to comment.