Skip to content

Commit

Permalink
Merge pull request #94 from xavierleune/feature/support-public-proper…
Browse files Browse the repository at this point in the history
…ties

[Feature] Support for public properties
  • Loading branch information
vgreb authored Jan 2, 2025
2 parents 5b0be39 + 256176c commit d9d8564
Show file tree
Hide file tree
Showing 13 changed files with 592 additions and 109 deletions.
13 changes: 9 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ jobs:
- 8.2
- 8.3
- 8.4
deps:
- highest
- lowest
composer:
- v2
name: Run Unit Tests on PHP ${{ matrix.php }}
name: Run Unit Tests on PHP ${{ matrix.php }}, ${{ matrix.deps }} dependencies
steps:
- name: Checkout
uses: actions/checkout@v3
Expand All @@ -29,10 +32,12 @@ jobs:
with:
php-version: ${{ matrix.php }}
extensions: bcmath, bz2, gettext, mbstring, memcached, mcrypt, mysqli, opcache, pdo_mysql, zip, pdo, intl, json, pdo_pgsql, pgsql, session, simplexml, xml
tools: composer:v1, pecl
tools: composer:v2, pecl

- name: Install vendors
run: composer install --prefer-source --no-interaction
- name: "Install ${{ matrix.dependencies }} dependencies with composer"
uses: "ramsey/composer-install@v2"
with:
dependency-versions: "${{ matrix.dependencies }}"

- name: Run Atoum tests
run: php vendor/bin/atoum
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Add uuid support with symfony/uid
* Refacto: use, when possible, Weakmap for UnitOfWork internal storage instead of uuid indexed array
* Fix: Query Generator now handle null values
* Feature: Support for public properties with hooks (8.4+)

3.9.1 (2024-07-19):
* Fix: Mysqli/Driver::ping() try to reconnect when mysqli::ping() throws an exception
Expand Down
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"require": {
"php": ">=8.0",
"aura/sqlquery": "^2.6",
"doctrine/cache": "^1.6"
"doctrine/cache": "^1.6",
"symfony/property-access": "^6.0 || ^7.0"
},
"require-dev": {
"ext-pgsql": "*",
Expand All @@ -32,7 +33,8 @@
"atoum/stubs": "^2.0",
"brick/geo": "^0.5.1",
"pimple/pimple": "^3.0",
"symfony/uid": "^6.0 || ^7.0"
"symfony/uid": "^6.0 || ^7.0",
"symfony/cache": "^6.0 || ^7.0"
},
"suggest": {
"brick/geo": "Allow support of MariaDB Geometry type",
Expand Down
6 changes: 3 additions & 3 deletions src/Ting/MetadataRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@
use CCMBenchmark\Ting\Repository\MetadataInitializer;
use CCMBenchmark\Ting\Repository\Repository;
use CCMBenchmark\Ting\Serializer\SerializerFactoryInterface;

use function get_class;
use Psr\Cache\CacheItemPoolInterface;
use function is_object;

class MetadataRepository
Expand Down Expand Up @@ -61,7 +60,7 @@ class MetadataRepository
/**
* @param SerializerFactoryInterface $serializerFactory
*/
public function __construct(SerializerFactoryInterface $serializerFactory)
public function __construct(SerializerFactoryInterface $serializerFactory, private ?CacheItemPoolInterface $cacheItemPool = null)
{
$this->serializerFactory = $serializerFactory;
}
Expand Down Expand Up @@ -163,6 +162,7 @@ public function findMetadataForEntity($entity, \Closure $callbackFound, \Closure
*/
public function addMetadata($repositoryClass, Metadata $metadata)
{
$metadata->propertyAccessor->setCacheItemPool($this->cacheItemPool);
$this->metadataList[$repositoryClass] = $metadata;
$metadataTable = $metadata->getTable();
$metadataConnection = $metadata->getConnectionName();
Expand Down
6 changes: 5 additions & 1 deletion src/Ting/Repository/Hydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ class Hydrator implements HydratorInterface
protected $unserializeAliases = [];
protected WeakMap $alreadyManaged;
protected $references = [];

/**
* @var Metadata[]
*/
protected $metadataList = [];

/**
Expand Down Expand Up @@ -404,7 +408,7 @@ function (Metadata $metadata) use ($column, &$result): void {
if (\is_int($table) === false) {
$ref = $table . '-';
foreach ($this->metadataList[$table]->getPrimaries() as $primary) {
$ref .= $entity->{$this->metadataList[$table]->getGetter($primary['fieldName'])}() . '-';
$ref .= $this->metadataList[$table]->getEntityPropertyByFieldName($entity, $primary['fieldName']) . '-';
}

if (isset($this->references[$ref]) === false) {
Expand Down
2 changes: 1 addition & 1 deletion src/Ting/Repository/HydratorRelational.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ private function getIdentifiers($table, $entity)
{
$id = '';
foreach ($this->metadataList[$table]->getPrimaries() as $primary) {
$id .= $entity->{$this->metadataList[$table]->getGetter($primary['fieldName'])}() . '-';
$id .= $this->metadataList[$table]->getEntityPropertyByFieldName($entity, $primary['fieldName']) . '-';
}

if ($id === '') {
Expand Down
55 changes: 32 additions & 23 deletions src/Ting/Repository/Metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use CCMBenchmark\Ting\Query\PreparedQuery;
use CCMBenchmark\Ting\Query\QueryFactoryInterface;
use CCMBenchmark\Ting\Serializer;
use CCMBenchmark\Ting\Util\PropertyAccessor;

/**
* @template T of object
Expand All @@ -51,10 +52,6 @@
*/
class Metadata
{
/**
* @var Serializer\SerializerFactoryInterface|null
*/
protected $serializerFactory = null;
protected $connectionName = null;
protected $databaseName = null;
/** @var class-string<Repository<T>>|null */
Expand All @@ -78,13 +75,14 @@ class Metadata
'geometry' => Serializer\Geometry::class,
'uuid' => Serializer\Uuid::class,
];
public PropertyAccessor $propertyAccessor;

/**
* @param Serializer\SerializerFactoryInterface $serializerFactory
*/
public function __construct(Serializer\SerializerFactoryInterface $serializerFactory)
public function __construct(private Serializer\SerializerFactoryInterface $serializerFactory)
{
$this->serializerFactory = $serializerFactory;
$this->propertyAccessor = new PropertyAccessor();
}

/**
Expand Down Expand Up @@ -372,8 +370,7 @@ public function setEntityPropertyForAutoIncrement($entity, DriverInterface $driv
$insertId = $driver->getInsertedId();
}

$property = 'set' . $this->autoincrement['fieldName'];
$entity->$property($insertId);
$this->propertyAccessor->setValue($entity, $this->autoincrement['fieldName'], $insertId, $this->fieldsByProperty[$this->autoincrement['fieldName']]['setter'] ?? null);
return $this;
}

Expand All @@ -387,8 +384,6 @@ public function setEntityPropertyForAutoIncrement($entity, DriverInterface $driv
*/
public function setEntityProperty($entity, $column, $value)
{
$setter = $this->getSetter($this->fields[$column]['fieldName']);

if (isset($this->fields[$column]['serializer']) === true) {
$options = [];

Expand All @@ -410,7 +405,7 @@ public function setEntityProperty($entity, $column, $value)
}
}

$entity->$setter($value);
$this->propertyAccessor->setValue($entity, $this->fields[$column]['fieldName'], $value, $this->fields[$column]['setter'] ?? null);
}

/**
Expand All @@ -422,8 +417,7 @@ public function setEntityProperty($entity, $column, $value)
*/
protected function getEntityProperty($entity, $field)
{
$getter = $this->getGetter($field['fieldName']);
$value = $entity->$getter();
$value = $this->propertyAccessor->getValue($entity, $field['fieldName'], $field['getter'] ?? null);

if (isset($field['serializer']) === true) {
$options = [];
Expand All @@ -436,8 +430,13 @@ protected function getEntityProperty($entity, $field)

return $value;
}



public function getEntityPropertyByFieldName($entity, $fieldName)
{
$field = $this->fieldsByProperty[$fieldName];
return $this->getEntityProperty($entity, $field);
}

/**
* Return a Query to get one object by it's primaries
*
Expand Down Expand Up @@ -648,11 +647,15 @@ public function generateQueryForInsert(
$values = [];

foreach ($this->fields as $column => $field) {
if (isset($field['autoincrement']) === true && $field['autoincrement'] === true) {
if ($field['autoincrement'] ?? false) {
continue;
}

$values[$column] = $this->getEntityProperty($entity, $field);

// Public typed properties non initialized is non-readable
// In this case we don't insert it, relying on database default value
if ($this->propertyAccessor->isReadable($entity, $field['fieldName'], $field['getter'] ?? null)) {
$values[$column] = $this->getEntityProperty($entity, $field);
}
}

$fields = array_keys($this->fields);
Expand Down Expand Up @@ -696,7 +699,12 @@ public function generateQueryForUpdate(
$values = [];
foreach ($properties as $name => $value) {
$columnName = $this->fieldsByProperty[$name]['columnName'];
$values[$columnName] = $this->getEntityProperty($entity, $this->fieldsByProperty[$name]);

// Public typed properties non initialized is non-readable
// In this case we don't update it, so it will keep the current value
if ($this->propertyAccessor->isReadable($entity, $this->fieldsByProperty[$name]['fieldName'], $this->fieldsByProperty[$name]['getter'] ?? null)) {
$values[$columnName] = $this->getEntityProperty($entity, $this->fieldsByProperty[$name]);
}
}

$primariesKeyValue = $this->getPrimariesKeyValuesByProperties($properties, $entity);
Expand Down Expand Up @@ -749,8 +757,7 @@ protected function getPrimariesKeyValuesByProperties($properties, $entity)
$primariesKeyValue[$key] = $properties[$fieldName];
} else {
// No update, get the actual
$propertyName = 'get' . $primary['fieldName'];
$primariesKeyValue[$key] = $entity->$propertyName();
$primariesKeyValue[$key] = $this->propertyAccessor->getValue($entity, $primary['fieldName']);
}
}
return $primariesKeyValue;
Expand All @@ -760,8 +767,9 @@ protected function getPrimariesKeyValuesByProperties($properties, $entity)
* Returns the getter name for a given field name
*
* @param $fieldName
*
* @return string
*
* @deprecated Use getEntityProperty, never try to get the value from the outside
*/
public function getGetter($fieldName)
{
Expand All @@ -775,8 +783,9 @@ public function getGetter($fieldName)
* Returns the setter name for a given field name
*
* @param $fieldName
*
* @return string
*
* @deprecated Use setEntityProperty, never try to set the value from the outside
*/
public function getSetter($fieldName)
{
Expand Down
8 changes: 8 additions & 0 deletions src/Ting/Services.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

namespace CCMBenchmark\Ting;

use CCMBenchmark\Ting\Util\PropertyAccessor;
use Pimple\Container;

class Services implements ContainerInterface
Expand Down Expand Up @@ -131,6 +132,13 @@ public function __construct()
'Cache',
fn () => new Cache\Cache()
);

$this->container->offsetSet(
'PropertyAccessor',
function () {
return new PropertyAccessor();
}
);
}

public function set($id, \Closure $callable, $factory = false)
Expand Down
Loading

0 comments on commit d9d8564

Please sign in to comment.