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
1 change: 0 additions & 1 deletion .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ jobs:
- ubuntu-latest

php:
- "8.1"
- "8.2"
- "8.3"

Expand Down
1 change: 0 additions & 1 deletion .github/workflows/cs-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ jobs:
- ubuntu-latest

php:
- "8.1"
- "8.2"
- "8.3"

Expand Down
1 change: 0 additions & 1 deletion .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ jobs:
- ubuntu-latest

php:
- "8.1"
- "8.2"
- "8.3"

Expand Down
1 change: 0 additions & 1 deletion .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ jobs:
- ubuntu-latest

php:
- "8.1"
- "8.2"
- "8.3"

Expand Down
2 changes: 1 addition & 1 deletion OSSMETADATA
Original file line number Diff line number Diff line change
@@ -1 +1 @@
osslifecycle=active
osslifecycle=active
131 changes: 42 additions & 89 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
# 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 dependency injection service.

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

![OSS Lifecycle](https://img.shields.io/osslifecycle/dotkernel/dot-annotated-services)
![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-annotated-services/4.1.7)
![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-annotated-services/5.0.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)
[![GitHub license](https://img.shields.io/github/license/dotkernel/dot-annotated-services)](https://github.com/dotkernel/dot-annotated-services/blob/5.0/LICENSE.md)

[![Build Static](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)
[![Build Static](https://github.com/dotkernel/dot-annotated-services/actions/workflows/static-analysis.yml/badge.svg?branch=5.0)](https://github.com/dotkernel/dot-annotated-services/actions/workflows/static-analysis.yml)
[![codecov](https://codecov.io/gh/dotkernel/dot-annotated-services/graph/badge.svg?token=ZBZDEA3LY8)](https://codecov.io/gh/dotkernel/dot-annotated-services)

[![SymfonyInsight](https://insight.symfony.com/projects/a0d7016e-fc3f-46b8-9b36-571ff060d744/big.svg)](https://insight.symfony.com/projects/a0d7016e-fc3f-46b8-9b36-571ff060d744)


## Installation

Run the following command in your project directory
Install `dot-annotated-services` by running the following command in your project directory:

composer require dotkernel/dot-annotated-services


After installing, add the `ConfigProvider` class to your configuration aggregate.
After installing, register `dot-annotated-services` in your project by adding the below line to your configuration aggregate (usually: `config/config.php`):

Dot\AnnotatedServices\ConfigProvider::class,


## Usage

### Using the AnnotatedServiceFactory

You can register services in the service manager using the `AnnotatedServiceFactory` as below
You can register services in the service manager using `AnnotatedServiceFactory` as seen in the below example:

```php
return [
'factories' => [
Expand All @@ -40,20 +44,20 @@ return [
];
```


### NOTE
> You can use only the fully qualified class name as the service key

The next step is to annotate the service constructor or setters with the service names to inject
The next step is to add the `#[Inject]` attribute to the service constructor with the service FQCNs to inject:

```php
use Dot\AnnotatedServices\Annotation\Inject;

/**
* @Inject({
* Dependency1::class,
* Dependency2::class,
* "config"
* })
*/
use Dot\AnnotatedServices\Attribute\Inject;

#[Inject(
Dependency1::class,
Dependency2::class,
"config",
)]
public function __construct(
protected Dependency1 $dep1,
protected Dependency2 $dep2,
Expand All @@ -62,105 +66,54 @@ public function __construct(
}
```

The annotation `@Inject` is telling the factory to inject the services between curly braces.
The `#[Inject]` attribute is telling `AnnotatedServiceFactory` to inject the services specified as parameters.
Valid service names should be provided, as registered in the service manager.

To inject an array value from the service manager, you can use dot notation as below

```php
use Dot\AnnotatedServices\Annotation\Inject;
use Dot\AnnotatedServices\Attribute\Inject;

/**
* @Inject({"config.debug"})
*/
#[Inject(
"config.debug",
)]
```
which will inject `$container->get('config')['debug'];`.

which will inject `$container->get('config')['debug'];`

### NOTE
> Even if using dot annotation, the annotated factory will check first if a service name exists with that name
> Even if using dot notation, `AnnotatedServiceFactory` will check first if a service name exists with that name.

You can use the inject annotation on setters too, they will be called at creation time and injected with the configured dependencies.

### Using the AnnotatedRepositoryFactory
You can register doctrine repositories and inject them using the AnnotatedRepositoryFactory as below:
### Using the AttributedRepositoryFactory
You can register doctrine repositories and inject them using the `AttributedRepositoryFactory` as below:
```php
return [
'factories' => [
ExampleRepository::class => AnnotatedRepositoryFactory::class,
ExampleRepository::class => AttributedRepositoryFactory::class,
],
];
```

The next step is to add the `@Entity` annotation in the repository class.
The next step is to add the `#[Entity]` attribute in the repository class.

The `name` field has to be the fully qualified class name.

Every repository should extend `Doctrine\ORM\EntityRepository`.
```php
use Api\App\Entity\Example;
use Doctrine\ORM\EntityRepository;
use Dot\AnnotatedServices\Annotation\Entity;
use Dot\AnnotatedServices\Attribute\Entity;

/**
* @Entity(name="App\Entity\Example")
*/
#[Entity(name: Example::class)]
class ExampleRepository extends EntityRepository
{

}
```


### Using the abstract factory

Using this approach, no service manager configuration is required. It uses the registered abstract factory to create annotated services.

In order to tell the abstract factory which services are to be created, you need to annotate the service class with the `@Service` annotation.
```php
use Dot\AnnotatedServices\Annotation\Service;

/*
* @Service
*/
class ServiceClass
{
// configure injections as described in the previous section
}
```

And that's it, you don't need to configure the service manager with this class, creation will happen automatically.


## Cache annotations

This package is built on top of `doctrine/annotation` and `doctrine/cache`.
In order to cache annotations, you should register a service factory at key `AbstractAnnotatedFactory::CACHE_SERVICE` that should return a valid `Doctrine\Common\Cache\Cache` cache driver. See [Cache Drivers](https://github.com/doctrine/cache/tree/master/lib/Doctrine/Common/Cache) for available implementations offered by doctrine.

Below, we give an example, as defined in our frontend and admin starter applications
```php
return [
'annotations_cache_dir' => __DIR__ . '/../../data/cache/annotations',
'dependencies' => [
'factories' => [
// used by dot-annotated-services to cache annotations
// needs to return a cache instance from Doctrine\Common\Cache
AbstractAnnotatedFactory::CACHE_SERVICE => AnnotationsCacheFactory::class,
]
],
];
```

```php
namespace Frontend\App\Factory;

use Doctrine\Common\Cache\FilesystemCache;
use Psr\Container\ContainerInterface;

class AnnotationsCacheFactory
{
public function __invoke(ContainerInterface $container)
{
//change this to suite your caching needs
return new FilesystemCache($container->get('config')['annotations_cache_dir']);
}
}
```
### NOTE
Starting from version `5.0` of `dot-annotated-services`:
- services can only be injected using the `#[Inject]` attribute (`@Inject` and `@Service` annotations are no longer supported)
- repository-entity relation can only be established using the `#[Entity]` attribute (`@Entity` annotation is no longer supported)
- dependencies injected via the`#[Entity]`/`#[Inject]` attributes are not cached
- injecting dependencies into property setters is no longer supported
41 changes: 41 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Security Policy

## Supported Versions


| Version | Supported | PHP Version |
|---------|--------------------|------------------------------------------------------------------------------------------------------------------------|
| 5.x | :white_check_mark: | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-annotated-services/5.0.0) |
| 4.x | :white_check_mark: | ![PHP from Packagist (specify version)](https://img.shields.io/packagist/php-v/dotkernel/dot-annotated-services/4.0.0) |
| <= 3.x | :x: | |


## Reporting Potential Security Issues

If you have encountered a potential security vulnerability in this project,
please report it to us at <security@dotkernel.com>. We will work with you to
verify the vulnerability and patch it.

When reporting issues, please provide the following information:

- Component(s) affected
- A description indicating how to reproduce the issue
- A summary of the security vulnerability and impact

We request that you contact us via the email address above and give the
project contributors a chance to resolve the vulnerability and issue a new
release prior to any public exposure; this helps protect the project's
users, and provides them with a chance to upgrade and/or update in order to
protect their applications.


## Policy

If we verify a reported security vulnerability, our policy is:

- We will patch the current release branch, as well as the immediate prior minor
release branch.

- After patching the release branches, we will immediately issue new security
fix releases for each patched release branch.

24 changes: 11 additions & 13 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "dotkernel/dot-annotated-services",
"type": "library",
"description": "DotKernel service creation component through laminas-servicemanager and annotations",
"description": "DotKernel dependency injection component using class attributes.",
"license": "MIT",
"homepage": "https://github.com/dotkernel/dot-annotated-services",
"authors": [
Expand All @@ -11,23 +11,21 @@
}
],
"keywords": [
"annotations",
"services",
"factories",
"attribute",
"container",
"laminas",
"mezzio",
"service-manager"
"dependency",
"di",
"factory",
"inject",
"service"
],
"require": {
"php": "~8.1.0 || ~8.2.0 || ~8.3.0",
"laminas/laminas-servicemanager": "^3.22.1",
"doctrine/annotations": "^1.14.3",
"doctrine/cache": "^1.12.1 || ^2.1.1",
"doctrine/orm" : "^2.17.3"
"php": "~8.2.0 || ~8.3.0",
"doctrine/orm": "^2.0 || ^3.0",
"psr/container": "^1.0 || ^2.0"
},
"require-dev": {
"phpunit/phpunit": "^10.5.9",
"phpunit/phpunit": "^10.5",
"vimeo/psalm": "^5.20",
"laminas/laminas-coding-standard": "^2.5"
},
Expand Down
1 change: 1 addition & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<testsuites>
<testsuite name="dot-annotated-services Test Suite">
<directory>./test</directory>
<exclude>./test/TestData</exclude>
</testsuite>
</testsuites>
<coverage/>
Expand Down
8 changes: 8 additions & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="5.22.2@d768d914152dbbf3486c36398802f74e80cfde48">
<file src="test/Factory/AttributedRepositoryFactoryTest.php">
<MissingTemplateParam>
<code>class ($entityManager, $metadata) extends EntityRepository {</code>
</MissingTemplateParam>
</file>
</files>
2 changes: 2 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
errorBaseline="psalm-baseline.xml"
>
<projectFiles>
<directory name="src" />
<directory name="test" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
Expand Down
31 changes: 0 additions & 31 deletions src/Annotation/Entity.php

This file was deleted.

Loading