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
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3']
php-versions: ['8.3', '8.4']
name: PHP ${{ matrix.php-versions }}
steps:
- uses: actions/checkout@v2
Expand Down
164 changes: 85 additions & 79 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ Welcome to the Accessor Generator composer plugin.

## Goals
The goal of this plugin is to provide dynamically generated get, set, add, remove
accessor methods for Classes based on information that we can read from the doc comment.
Currently we can process Doctrine ORM annotations.
accessor methods for Classes based on information that we can read from PHP 8 native
attributes or from doc comments.
Currently we can process Doctrine ORM annotations and their native attribute equivalents.

Since the code is automatically generated you do not have to (unit) test it and it
will be very consistent with a lot of added boilerplate code that will make your code
Expand All @@ -28,6 +29,29 @@ Add `-vv` to the dump-autoload command for more verbosity.
<?php
namespace Hostnet\Product\Entity;

use Doctrine\ORM\Mapping as ORM;
use Hostnet\Component\AccessorGenerator\Attribute as AG;

#[ORM\Entity]
#[ORM\Table(name: 'periode')]
class Period
{
/** This is the file that is generated with the accessor methods inside. */
use Generated\PeriodMethodsTrait;

#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(name: 'id', type: 'integer')]
#[AG\Generate]
private int $id;

// ...
}
```

Docblock-style annotations are also supported and can be mixed freely with native attributes:

```php
use Doctrine\ORM\Mapping as ORM;
use Hostnet\Component\AccessorGenerator\Annotation as AG;

Expand All @@ -37,18 +61,15 @@ use Hostnet\Component\AccessorGenerator\Annotation as AG;
*/
class Period
{
use Generated\PeriodMethodsTrait; // This is the file that is generated with the
// accessor methods inside.
use Generated\PeriodMethodsTrait;

/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(name="id", type="integer")
* @AG\Generate // Here you ask methods to be generated
*
* @AG\Generate
*/
private int $id;

// ...
}
```

Expand All @@ -58,8 +79,13 @@ file. This file can be included as trait.
### Specify which methods to generate

It is possible to disable generation of certain accessor methods by specifying them in
the annotation.
the attribute.

```php
#[AG\Generate(add: 'none', set: 'none', remove: 'none', get: 'none', is: 'none')]
```

Docblock equivalent:
```php
/**
* @AG\Generate(add="none",set="none",remove="none",get="none",is="none")
Expand All @@ -76,15 +102,21 @@ when the type is iterable (e.g. DoctrineCollection or array).

### Encryption

To use asymmetric encryption on a column's value add the 'encryption_alias' field to the `Generate` annotation.
To use asymmetric encryption on a column's value add the `encryption_alias` field to the `Generate` attribute.
Also make sure the type of the database column has a big enough length. At least 1064 for key and IV is needed,
plus the length of the sealed data itself.

```php
#[AG\Generate(encryption_alias: 'database.table.column')]
private $encrypted_variable;
```

Docblock equivalent:
```php
/**
* @AG\Generate(encryption_alias="database.table.column")
*/
private $encrypted_variable;
private $encrypted_variable;
```

The alias used there should be added to the application's composer.json as follows:
Expand Down Expand Up @@ -124,17 +156,14 @@ to the composer.json file.

Do not forget to use the *setter method* in the constructor to trigger the encryption of the given value instead
of assigning a value to the property directly.
.

```php
<?php
class MyEntity
{
/**
* @AG\Generate(encryption_alias="<encryption_alias>")
*/
#[AG\Generate(encryption_alias: '<encryption_alias>')]
private $my_value;

public function __construct(string $my_value)
{
$this->my_value = $my_value; // No encryption is taking place.
Expand Down Expand Up @@ -178,8 +207,7 @@ Example composer.json config:

## Parameters using ENUM classes

Since version 2.8.0, the support of accessor generation of parameterized collections has been added. With this addition,
the requirement of PHP 7.1 has been added due to the need of `ReflectionConstant`, which was added in PHP 7.1.
Since version 2.8.0, the support of accessor generation of parameterized collections has been added.

Imagine having an entity that holds an `ArrayCollection` to another entity that holds parameters. For example:
```php
Expand All @@ -199,17 +227,15 @@ Version 2.8.0 introduces the ability to generate accessors for enum classes.

### Requirements

The owning entity - `Task` in the example above - must implement a property that is of type `ArrayCollection` which \
The owning entity - `Task` in the example above - must implement a property that is of type `ArrayCollection` which
defines a `OneToMany` relationship with a `Parameter`-entity.

```php
class Task
{
// ...

/**
* @ORM\OneToMany(targetEntity="Parameter", cascade={"persist"})
*/

#[ORM\OneToMany(targetEntity: Parameter::class, cascade: ['persist'])]
private $parameters;

// ...
Expand All @@ -222,22 +248,16 @@ use Hostnet\Component\AccessorGenerator\Enum\EnumeratorCompatibleEntityInterface

class Parameter implements EnumeratorCompatibleEntityInterface
{
/**
* @ORM\ManyToOne(targetEntity="Task")
*/
#[ORM\ManyToOne(targetEntity: Task::class)]
private $owner;

/**
* @ORM\Column(type="string")
*/

#[ORM\Column(type: 'string')]
private $name;

/**
* @ORM\Column(type="string")
* @AG\Generate()
*/

#[ORM\Column(type: 'string')]
#[AG\Generate]
private $value;

// This signature is a requirement for enum accessor generation.
public function __construct($task, string $name, ?string $value)
{
Expand Down Expand Up @@ -272,7 +292,7 @@ class MyTaskParamNames
* Represents the client if the task is currently runnnig for.
*/
public const I_CLIENT_ID = 'CLIENT_ID';

/**
* An awesome URL.
*/
Expand All @@ -282,40 +302,34 @@ class MyTaskParamNames

Now that we have our three classes (`Task`, `Parameter` and `MyTaskParamNames`), we can start generating code.

### The "Enumerator" annotation
### The Enumerator attribute

With version 2.8.0 comes the `Enumerator` annotation which can be used inside the existing `Generate` annotation.
With version 2.8.0 comes the `Enumerator` attribute which can be used inside the existing `Generate` attribute.

> **Upgrading from 2.8.0 to 2.8.1:**
> The "name" setting in the annotation has been changed to "property" to be more consistent. Since 2.8.1, the ability
> to add inline enumerators through other class properties has been added. See below for more information.

Taking the code that we just wrote in the examples above, we can generate an accessor method for `MyTaskParamNames`
by modifying the annotation of the `parameters` property of our `Task` class.
by modifying the attribute of the `parameters` property of our `Task` class.

```php
class Task
{
use Generated\TaskMethodsTrait;

/**
* @ORM\OneToMany(targetEntity="Parameter", cascade={"persist"})
* @AG\Generate(enumerators={
* @AG\Enumerator("MyTaskParamNames", property="my_params")
* })
*/
private $property;

/**
* @var Generated\MyTaskParamNamesEnum
*/
#[ORM\OneToMany(targetEntity: Parameter::class, cascade: ['persist'])]
#[AG\Generate(enumerators: [new AG\Enumerator('MyTaskParamNames', property: 'my_params')])]
private $parameters;

/** @var Generated\MyTaskParamNamesEnum */
private $my_params;
}
```

Once the code is generated, you will now have a newly generated class called `MyTaskParamNamesEnum` in the
`Generated` directory (and namespace) relative to the namespace of `MyTaskParamNames`. An accessor for this class is
generated using the `property` settting in the `TaskMethodsTrait`.
generated using the `property` setting in the `TaskMethodsTrait`.

The accessor for this enum based on the code above will be called `getMyParams()`. You can give this any name you want
as long as it is suitable for a method name.
Expand Down Expand Up @@ -357,29 +371,23 @@ see an example of the generated code.
> specify them explicitly.

### Multiple enumerators
As you might have noticed, the `enumerators` property of the `Generate` annotation accepts a list
of one or more `Enumerator` annotations. You can specify one ore more enum classes that utilize
As you might have noticed, the `enumerators` parameter of the `Generate` attribute accepts a list
of one or more `Enumerator` instances. You can specify one or more enum classes that utilize
the same collection for their "storage".

If your annotation looks like this:
```php
/**
* @AG\Generate(enumerators={
* @AG\Enumerator("MyTaskParamNames", property="my_params"),
* @AG\Enumerator("BetterParamNames", property="better_params")
* });
*/
private $parameters;

/**
* @var Generated\MyTaskParamNamesEnum
*/
private $my_params;

/**
* @var Generated\BetterParamNamesEnum
*/
private $better_params;
#[ORM\OneToMany(targetEntity: Parameter::class, cascade: ['persist'])]
#[AG\Generate(enumerators: [
new AG\Enumerator('MyTaskParamNames', property: 'my_params'),
new AG\Enumerator('BetterParamNames', property: 'better_params'),
])]
private $parameters;

/** @var Generated\MyTaskParamNamesEnum */
private $my_params;

/** @var Generated\BetterParamNamesEnum */
private $better_params;
```

The generator will now create two accessors for these parameter enumerators that you can use like
Expand All @@ -390,26 +398,24 @@ $task->getBetterParams()->setFoobar(1234); // From BetterParamNames
```

### Separated enumerator accessor generation
You can also define enumerators outside the `@Generate` annotation. If used in combination with the `entity-plugin-lib`,
You can also define enumerators outside the `Generate` attribute. If used in combination with the `entity-plugin-lib`,
it is possible to define a `trait` that holds an enumerator property that refers to a collection on your entity.

Lets say we want to add an extra enumerator to our - already existing - Task entity that we have written before.

```php
use Hostnet\Component\AccessorGenerator\Annotation as AG;
use Hostnet\Component\AccessorGenerator\Attribute as AG;

trait TaskTrait
{
use Generated\TaskTraitMethodsTrait;

/**
* @AG\Enumerator("\My\Namespace\MyExtraParamName", name="parameters")
* @var \My\Namespace\Generated\MyExtraParamNameEnum
*/
#[AG\Enumerator('\My\Namespace\MyExtraParamName', name: 'parameters')]
/** @var \My\Namespace\Generated\MyExtraParamNameEnum */
private $some_extra_params;
}
```
The `name` setting refers to the ArrayCollection property that holds all parameters owned by that entity.
The `name` parameter refers to the ArrayCollection property that holds all parameters owned by that entity.

Once the code is generated, you can now invoke the enumerator like any other:
```php
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"license": "MIT",
"minimum-stability": "stable",
"require": {
"php": "^8.1",
"php": "^8.3",
"composer-plugin-api": "^2.0",
"ext-bcmath": "*",
"ext-json": "*",
Expand Down
Loading
Loading