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
49 changes: 49 additions & 0 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
on:
- push

name: Run PHPStan checks

jobs:
mutation:
name: PHPStan ${{ matrix.php }}-${{ matrix.os }}

runs-on: ${{ matrix.os }}

strategy:
matrix:
os:
- ubuntu-latest

php:
- "8.2"
- "8.3"
- "8.4"

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: "${{ matrix.php }}"
coverage: pcov
ini-values: assert.exception=1, zend.assertions=1, error_reporting=-1, log_errors_max_len=0, display_errors=On
tools: composer:v2, cs2pr

- name: Determine composer cache directory
run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV

- name: Cache dependencies installed with composer
uses: actions/cache@v4
with:
path: ${{ env.COMPOSER_CACHE_DIR }}
key: php${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }}
restore-keys: |
php${{ matrix.php }}-composer-

- name: Install dependencies with composer
run: composer install --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi

- name: Run static analysis with PHPStan
run: vendor/bin/phpstan analyse
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
# dot-annotated-services

Dotkernel component used to create services through [Laminas Service Manager](https://github.com/laminas/laminas-servicemanager) and inject them with dependencies just using method annotations. It can also create services without the need to write factories. Annotation parsing can be cached, to improve performance.
Dotkernel component used to create services through [Laminas Service Manager](https://github.com/laminas/laminas-servicemanager) and inject them with dependencies just using method annotations.
It can also create services without the need to write factories.
Annotation parsing can be cached, to improve performance.

This package can clean up your code, by getting rid of all the factories you write, sometimes just to inject a dependency or two.

## Documentation

Documentation is available at: https://docs.dotkernel.org/dot-annotated-services/.

## Badges

![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-annotated-services%2Fblob%2F4.0%2FOSSMETADATA)
![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-annotated-services/4.2.1)
![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-annotated-services/4.3.0)

[![GitHub issues](https://img.shields.io/github/issues/dotkernel/dot-annotated-services)](https://github.com/dotkernel/dot-annotated-services/issues)
[![GitHub forks](https://img.shields.io/github/forks/dotkernel/dot-annotated-services)](https://github.com/dotkernel/dot-annotated-services/network)
Expand All @@ -14,6 +22,7 @@ This package can clean up your code, by getting rid of all the factories you wri

[![Build Static](https://github.com/dotkernel/dot-annotated-services/actions/workflows/continuous-integration.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/dot-annotated-services/actions/workflows/continuous-integration.yml)
[![codecov](https://codecov.io/gh/dotkernel/dot-annotated-services/graph/badge.svg?token=ZBZDEA3LY8)](https://codecov.io/gh/dotkernel/dot-annotated-services)
[![PHPStan](https://github.com/dotkernel/dot-annotated-services/actions/workflows/static-analysis.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/dot-annotated-services/actions/workflows/static-analysis.yml)

## Installation

Expand Down
15 changes: 8 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "dotkernel/dot-annotated-services",
"type": "library",
"description": "DotKernel service creation component through laminas-servicemanager and annotations",
"description": "Dotkernel service creation component through laminas-servicemanager and annotations",
"license": "MIT",
"homepage": "https://github.com/dotkernel/dot-annotated-services",
"authors": [
{
"name": "DotKernel Team",
"name": "Dotkernel Team",
"email": "[email protected]"
}
],
Expand All @@ -28,8 +28,9 @@
},
"require-dev": {
"laminas/laminas-coding-standard": "^3.0",
"phpunit/phpunit": "^10.5.9",
"vimeo/psalm": "^6.0"
"phpstan/phpstan": "^2.1",
"phpstan/phpstan-phpunit": "^2.0",
"phpunit/phpunit": "^10.5.9"
},
"autoload": {
"psr-4": {
Expand All @@ -44,13 +45,13 @@
"scripts": {
"check": [
"@cs-check",
"@test"
"@test",
"@static-analysis"
],
"cs-check": "phpcs",
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml",
"static-analysis": "psalm --shepherd --stats"
"static-analysis": "phpstan analyse --memory-limit 1G"
},
"config": {
"sort-packages": true,
Expand Down
16 changes: 15 additions & 1 deletion docs/book/v4/overview.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Overview

`dot-annotated-services` is Dotkernel's dependency injection service.
`dot-annotated-services` is Dotkernel's dependency injection service using annotations.

By providing reusable factories for service and repository injection, it reduces code complexity in projects.

## Badges

![OSS Lifecycle](https://img.shields.io/osslifecycle?file_url=https%3A%2F%2Fgithub.com%2Fdotkernel%2Fdot-annotated-services%2Fblob%2F4.0%2FOSSMETADATA)
![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-annotated-services/4.3.0)

[![GitHub issues](https://img.shields.io/github/issues/dotkernel/dot-annotated-services)](https://github.com/dotkernel/dot-annotated-services/issues)
[![GitHub forks](https://img.shields.io/github/forks/dotkernel/dot-annotated-services)](https://github.com/dotkernel/dot-annotated-services/network)
[![GitHub stars](https://img.shields.io/github/stars/dotkernel/dot-annotated-services)](https://github.com/dotkernel/dot-annotated-services/stargazers)
[![GitHub license](https://img.shields.io/github/license/dotkernel/dot-annotated-services)](https://github.com/dotkernel/dot-annotated-services/blob/4.0/LICENSE.md)

[![Build Static](https://github.com/dotkernel/dot-annotated-services/actions/workflows/continuous-integration.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/dot-annotated-services/actions/workflows/continuous-integration.yml)
[![codecov](https://codecov.io/gh/dotkernel/dot-annotated-services/graph/badge.svg?token=ZBZDEA3LY8)](https://codecov.io/gh/dotkernel/dot-annotated-services)
[![PHPStan](https://github.com/dotkernel/dot-annotated-services/actions/workflows/static-analysis.yml/badge.svg?branch=4.0)](https://github.com/dotkernel/dot-annotated-services/actions/workflows/static-analysis.yml)
2 changes: 1 addition & 1 deletion docs/book/v5/overview.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Overview

`dot-annotated-services` is DotKernel's dependency injection service.
`dot-annotated-services` is Dotkernel's dependency injection service.

By providing reusable factories for service and repository injection, it reduces code complexity in projects.

Expand Down
8 changes: 8 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
includes:
- vendor/phpstan/phpstan-phpunit/extension.neon
parameters:
level: 5
paths:
- src
- test
treatPhpDocTypesAsCertain: false
17 changes: 0 additions & 17 deletions psalm.xml

This file was deleted.

43 changes: 36 additions & 7 deletions test/AnnotatedRepositoryFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,38 @@
use Dot\AnnotatedServices\Annotation\Entity;
use Dot\AnnotatedServices\Exception\RuntimeException;
use Dot\AnnotatedServices\Factory\AnnotatedRepositoryFactory as Subject;
//use DotTest\AnnotatedServices\TestClass;
use PHPUnit\Framework\MockObject\Exception;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use ReflectionException;

use function get_class;

class AnnotatedRepositoryFactoryTest extends TestCase
{
private ContainerInterface $container;

private Subject $subject;

private Reader $annotationReader;
private MockObject&ContainerInterface $container;
private MockObject&Subject $subject;
private MockObject&Reader $annotationReader;

/**
* @throws Exception
*/
public function setUp(): void
{
$this->container = $this->createMock(ContainerInterface::class);
$this->annotationReader = $this->createMock(Reader::class);
$this->subject = $this->createPartialMock(Subject::class, ['createAnnotationReader']);
}

/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws ReflectionException
*/
public function testThrowsExceptionClassNotFound()
{
$requestedName = 'TestRepository';
Expand All @@ -39,9 +51,14 @@ public function testThrowsExceptionClassNotFound()
$this->subject->__invoke($this->container, $requestedName);
}

/**
* @throws ContainerExceptionInterface
* @throws ReflectionException
* @throws NotFoundExceptionInterface
*/
public function testThrowsExceptionClassNotExtendsEntityRepository()
{
$requestedName = 'TestRepository';
$requestedName = TestClass::class;

$this->getMockBuilder($requestedName)->getMock();

Expand All @@ -50,6 +67,12 @@ public function testThrowsExceptionClassNotExtendsEntityRepository()
$this->subject->__invoke($this->container, $requestedName);
}

/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws Exception
* @throws ReflectionException
*/
public function testCreateObjectThrowsExceptionAnnotationNotFound()
{
$repository = $this->createMock(EntityRepository::class);
Expand All @@ -67,6 +90,12 @@ public function testCreateObjectThrowsExceptionAnnotationNotFound()
$this->subject->__invoke($this->container, $repository::class);
}

/**
* @throws ContainerExceptionInterface
* @throws Exception
* @throws NotFoundExceptionInterface
* @throws ReflectionException
*/
public function testCreateObjectReturnsEntityRepository()
{
$repository = $this->createMock(EntityRepository::class);
Expand All @@ -87,6 +116,6 @@ public function testCreateObjectReturnsEntityRepository()

$object = $this->subject->__invoke($this->container, $repository::class);

$this->assertInstanceOf(EntityRepository::class, $object);
$this->assertContainsOnlyInstancesOf(EntityRepository::class, [$object]);
}
}
49 changes: 39 additions & 10 deletions test/AnnotatedServiceFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,27 @@
use Dot\AnnotatedServices\Annotation\Inject;
use Dot\AnnotatedServices\Exception\RuntimeException;
use Dot\AnnotatedServices\Factory\AnnotatedServiceFactory as Subject;
use PHPUnit\Framework\MockObject\Exception;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;

use function get_class;

class AnnotatedServiceFactoryTest extends TestCase
{
private ContainerInterface $container;

private Subject $subject;

private Reader $annotationReader;
private MockObject&ContainerInterface $container;
private MockObject&Subject $subject;
private MockObject&Reader $annotationReader;

/**
* @throws Exception
*/
public function setUp(): void
{
$this->container = $this->createMock(ContainerInterface::class);
Expand All @@ -33,6 +39,11 @@ public function setUp(): void
]);
}

/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws ReflectionException
*/
public function testThrowsExceptionClassNotFound()
{
$requestedName = 'TestService';
Expand All @@ -43,9 +54,15 @@ public function testThrowsExceptionClassNotFound()
$this->subject->__invoke($this->container, $requestedName);
}

/**
* @throws ContainerExceptionInterface
* @throws Exception
* @throws NotFoundExceptionInterface
* @throws ReflectionException
*/
public function testReturnServiceWithNoDependencies()
{
$requestedName = 'TestService';
$requestedName = TestClass::class;
$this->getMockBuilder($requestedName)->allowMockingUnknownTypes()->getMock();
$refClass = $this->createMock(ReflectionClass::class);

Expand All @@ -60,12 +77,18 @@ public function testReturnServiceWithNoDependencies()

$object = $this->subject->__invoke($this->container, $requestedName);

$this->assertInstanceOf($requestedName, $object);
$this->assertSame($requestedName, $object::class);
}

/**
* @throws ContainerExceptionInterface
* @throws Exception
* @throws NotFoundExceptionInterface
* @throws ReflectionException
*/
public function testThrowsExceptionAnnotationNotFound()
{
$requestedName = 'TestService';
$requestedName = TestClass::class;
$this->getMockBuilder($requestedName)->allowMockingUnknownTypes()->getMock();
$refClass = $this->createMock(ReflectionClass::class);
$refConstructor = $this->createMock(ReflectionMethod::class);
Expand All @@ -89,9 +112,15 @@ public function testThrowsExceptionAnnotationNotFound()
$this->subject->__invoke($this->container, $requestedName);
}

/**
* @throws ContainerExceptionInterface
* @throws Exception
* @throws NotFoundExceptionInterface
* @throws ReflectionException
*/
public function testReturnService()
{
$requestedName = 'TestService';
$requestedName = TestClass::class;
$this->getMockBuilder($requestedName)->allowMockingUnknownTypes()->getMock();
$refClass = $this->createMock(ReflectionClass::class);
$refConstructor = $this->createMock(ReflectionMethod::class);
Expand All @@ -108,6 +137,6 @@ public function testReturnService()

$service = $this->subject->__invoke($this->container, $requestedName);

$this->assertInstanceOf($requestedName, $service);
$this->assertSame($requestedName, $service::class);
}
}
9 changes: 9 additions & 0 deletions test/TestClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace DotTest\AnnotatedServices;

class TestClass
{
}