Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/php-unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Tests

on:
push:
branches:
- main
pull_request:

jobs:
test:
name: PHPUnit Tests (PHP ${{ matrix.php }})
runs-on: ubuntu-latest

strategy:
matrix:
php: ["8.2", "8.3"]

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Setup PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none

- name: Install dependencies
run: composer install --prefer-dist --no-progress

- name: Run PHPUnit tests
run: vendor/bin/phpunit
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ composer.lock
vendor/
content/
.phpunit.result.cache
.phpunit.cache
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"symfony/console": "^7",
"symfony/filesystem": "^7"
},
"require-dev": {
"phpunit/phpunit": "^10.0"
},
"autoload": {
"psr-4": {
"Teak\\": "lib",
Expand Down
14 changes: 14 additions & 0 deletions lib/Compiler/ClassLinkList.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ public function generate($project, $filePrefix)
'filename' => $filePrefix . mb_strtolower(str_replace("\\", '-', ltrim($class->getFqsen(), "\\"))),
];
}

// Process traits
foreach ($file->getTraits() as $trait) {
$classReflection = new ClassReflection($trait);

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

$classes[ltrim($trait->getFqsen()->__toString(), "\\")] = [
'path' => $file->getPath(),
'filename' => $filePrefix . mb_strtolower(str_replace("\\", '-', ltrim($trait->getFqsen(), "\\"))),
];
}
}

$this->set($classes);
Expand Down
7 changes: 5 additions & 2 deletions lib/Compiler/Class_/ApiTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,16 @@ public function compile()
$properties = $this->class->getProperties();
$methods = $this->class->getMethods();

if (!empty($properties) || !empty($methods) || $this->class->getParent() || $this->class->getInterfaces()) {
$hasUsedTraits = !empty($this->class->getUsedTraits());

if (!empty($properties) || !empty($methods) || $this->class->getParent() || $this->class->getInterfaces() || $hasUsedTraits) {
$contents .= (new Heading('Overview', 2))->compile();
}

if ($this->class->getParent() || $this->class->getInterfaces()) {
if ($this->class->getParent() || $this->class->getInterfaces() || $hasUsedTraits) {
$contents .= (new ParentList($this->class))->compile();
$contents .= (new InterfaceList($this->class))->compile();
$contents .= (new TraitList($this->class))->compile();
$contents .= self::NEWLINE;
}

Expand Down
53 changes: 53 additions & 0 deletions lib/Compiler/Class_/TraitList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Teak\Compiler\Class_;

use Teak\Compiler\CompilerInterface;
use Teak\Reflection\ClassReflection;

/**
* Class TraitList
*/
class TraitList implements CompilerInterface
{
/**
* @var ClassReflection
*/
public $class;

/**
* TraitList constructor.
*
* @param ClassReflection $class
*/
public function __construct($class)
{
$this->class = $class;
}

/**
* Compile.
*
* @return string
*/
public function compile()
{
$contents = '';

$usedTraits = $this->class->getUsedTraits();

if (!empty($usedTraits)) {
$traitNames = array_map(function ($trait) {
return '`' . ltrim((string) $trait, '\\') . '`';
}, $usedTraits);

if (count($traitNames) === 1) {
$contents .= '*This class uses the trait ' . reset($traitNames) . '*';
} else {
$contents .= '*This class uses the traits ' . implode(', ', $traitNames) . '*';
}
}

return $contents . self::BREAK;
}
}
30 changes: 28 additions & 2 deletions lib/Console/ClassReferenceHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Teak\Console;

use phpDocumentor\Reflection\Php\Class_;
use phpDocumentor\Reflection\Php\Trait_;
use phpDocumentor\Reflection\Php\ProjectFactory;
use phpDocumentor\Reflection\Project;
use Teak\Compiler\ClassLinkList;
Expand Down Expand Up @@ -72,10 +73,14 @@ protected function generateClassList($project)
$files = $project->getFiles();

$classMap = [];
$traitMap = [];

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

Expand All @@ -88,6 +93,27 @@ protected function generateClassList($project)
$classReflection->addParentInformation($parent);
}

// Add trait information
if (method_exists($class, 'getUsedTraits')) {
foreach ($class->getUsedTraits() as $usedTrait) {
$trait = $traitMap[$usedTrait->__toString()] ?? null;
if ($trait) {
$classReflection->addTraitInformation($trait);
}
}
}

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

$classReflections[] = $classReflection;
}

// Process traits
foreach ($file->getTraits() as $trait) {
$classReflection = new ClassReflection($trait);

if ($classReflection->shouldIgnore()) {
continue;
}
Expand Down Expand Up @@ -117,7 +143,7 @@ protected function getParentsRecursive($class, $classMap)
return $parents;
}

public function getProject() : Project
public function getProject(): Project
{
return $this->project;
}
Expand Down
60 changes: 53 additions & 7 deletions lib/Reflection/ClassReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ class ClassReflection extends Reflection
{
private array $parentMethods = [];
private array $parentProperties = [];
private array $traitMethods = [];
private array $traitProperties = [];

/**
* ClassReflection constructor.
*
* @param \phpDocumentor\Reflection\Php\Class_ $reflection
* @param \phpDocumentor\Reflection\Php\Class_|\phpDocumentor\Reflection\Php\Trait_ $reflection
*/
public function __construct($reflection)
{
Expand All @@ -33,6 +35,19 @@ public function addParentInformation($parentClass)
$this->parentProperties = $parentClass->getProperties();
}

public function addTraitInformation($trait)
{
$methods = array_map(function ($method) {
return $method->getName();
}, $this->traitMethods);
$trait_methods = array_filter($trait->getMethods(), function ($trait_method) use ($methods) {
return !in_array($trait_method->getName(), $methods);
});

$this->traitMethods = array_merge($this->traitMethods, $trait_methods);
$this->traitProperties = array_merge($this->traitProperties, $trait->getProperties());
}

public function hasMethods()
{
if (method_exists($this, 'getMethods')) {
Expand All @@ -46,7 +61,19 @@ public function getMethods()
{
$methods = $this->reflection->getMethods();

if ($this->reflection->getParent() && !empty($this->parentMethods)) {
// Add trait methods first (so they can be overridden by class/parent methods)
if (!empty($this->traitMethods)) {
$method_names = array_map(function ($method) {
return $method->getName();
}, $methods);
$trait_methods = array_filter($this->traitMethods, function ($trait_method) use ($method_names) {
return !in_array($trait_method->getName(), $method_names);
});

$methods = array_merge($methods, $trait_methods);
}

if (method_exists($this->reflection, 'getParent') && $this->reflection->getParent() && !empty($this->parentMethods)) {
// Filter out parent methods that are already defined in the child class.
$method_names = array_map(function ($method) {
return $method->getName();
Expand Down Expand Up @@ -74,7 +101,12 @@ public function getProperties()
{
$properties = $this->reflection->getProperties();

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

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

Expand All @@ -92,21 +124,35 @@ public function getProperties()

public function getParent()
{
return $this->reflection->getParent();
if (method_exists($this->reflection, 'getParent')) {
return $this->reflection->getParent();
}
return null;
}

public function getInterfaces()
{
return $this->reflection->getInterfaces();
if (method_exists($this->reflection, 'getInterfaces')) {
return $this->reflection->getInterfaces();
}
return [];
}

public function getParentMethods() : array
public function getParentMethods(): array
{
return $this->parentMethods;
}

public function getParentProperties() : array
public function getParentProperties(): array
{
return $this->parentProperties;
}

public function getUsedTraits(): array
{
if (method_exists($this->reflection, 'getUsedTraits')) {
return $this->reflection->getUsedTraits();
}
return [];
}
}
Loading