Merge branch 'release/3.0.0'

This commit is contained in:
Ferdinand Kuhl 2021-08-26 10:53:26 +02:00
commit 891da480a9
8 changed files with 97 additions and 70 deletions

View file

@ -1,8 +1,12 @@
<?php <?php
declare(strict_types=1);
namespace DigiComp\Sequence\Command; namespace DigiComp\Sequence\Command;
use DigiComp\Sequence\Domain\Model\Insert;
use DigiComp\Sequence\Service\SequenceGenerator; use DigiComp\Sequence\Service\SequenceGenerator;
use Doctrine\ORM\EntityManagerInterface;
use Neos\Flow\Annotations as Flow; use Neos\Flow\Annotations as Flow;
use Neos\Flow\Cli\CommandController; use Neos\Flow\Cli\CommandController;
@ -14,21 +18,50 @@ use Neos\Flow\Cli\CommandController;
class SequenceCommandController extends CommandController class SequenceCommandController extends CommandController
{ {
/** /**
* @var SequenceGenerator
* @Flow\Inject * @Flow\Inject
* @var SequenceGenerator
*/ */
protected $sequenceGenerator; protected $sequenceGenerator;
/**
* @Flow\Inject
* @var EntityManagerInterface
*/
protected $entityManager;
/** /**
* Sets minimum number for sequence generator * Sets minimum number for sequence generator
* *
* @param int $to * @param int $to
* @param string $type * @param string $type
*/ */
public function advanceCommand($to, $type) public function advanceCommand(int $to, string $type): void
{ {
$this->sequenceGenerator->advanceTo($to, $type); $this->sequenceGenerator->advanceTo($to, $type);
} }
// TODO: make clean up job to delete all but the biggest number to save resources /**
* @param string[] $typesToClean
*/
public function cleanSequenceInsertsCommand(array $typesToClean = [])
{
$cleanArray = [];
if (empty($typesToClean)) {
$results = $this->entityManager
->createQuery('SELECT i.type, MAX(i.number) max_number FROM ' . Insert::class . ' i GROUP BY i.type')
->getScalarResult();
foreach ($results as $result) {
$cleanArray[$result['type']] = (int) $result['max_number'];
}
} else {
foreach ($typesToClean as $typeToClean) {
$cleanArray[$typeToClean] = $this->sequenceGenerator->getLastNumberFor($typeToClean);
}
}
foreach ($cleanArray as $typeToClean => $number) {
$this->entityManager
->createQuery('DELETE FROM ' . Insert::class . ' i WHERE i.type = ?0 AND i.number < ?1')
->execute([$typeToClean, $number]);
}
}
} }

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace DigiComp\Sequence\Domain\Model; namespace DigiComp\Sequence\Domain\Model;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
@ -16,24 +18,24 @@ use Neos\Flow\Annotations as Flow;
class Insert class Insert
{ {
/** /**
* @var int
* @Flow\Identity * @Flow\Identity
* @ORM\Id * @ORM\Id
* @var int
*/ */
protected $number; protected int $number;
/** /**
* @var string
* @Flow\Identity * @Flow\Identity
* @ORM\Id * @ORM\Id
* @var string
*/ */
protected $type; protected string $type;
/** /**
* @param int $number * @param int $number
* @param string|object $type * @param string|object $type
*/ */
public function __construct($number, $type) public function __construct(int $number, $type)
{ {
$this->setNumber($number); $this->setNumber($number);
$this->setType($type); $this->setType($type);
@ -42,7 +44,7 @@ class Insert
/** /**
* @return int * @return int
*/ */
public function getNumber() public function getNumber(): int
{ {
return $this->number; return $this->number;
} }
@ -50,7 +52,7 @@ class Insert
/** /**
* @param int $number * @param int $number
*/ */
public function setNumber($number) public function setNumber(int $number): void
{ {
$this->number = $number; $this->number = $number;
} }
@ -58,7 +60,7 @@ class Insert
/** /**
* @return string * @return string
*/ */
public function getType() public function getType(): string
{ {
return $this->type; return $this->type;
} }
@ -66,10 +68,10 @@ class Insert
/** /**
* @param string|object $type * @param string|object $type
*/ */
public function setType($type) public function setType($type): void
{ {
if (is_object($type)) { if (\is_object($type)) {
$type = get_class($type); $type = \get_class($type);
} }
$this->type = $type; $this->type = $type;
} }

View file

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace DigiComp\Sequence\Service; namespace DigiComp\Sequence\Service;
/** /**

View file

@ -1,15 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace DigiComp\Sequence\Service; namespace DigiComp\Sequence\Service;
use DigiComp\Sequence\Domain\Model\Insert; use DigiComp\Sequence\Domain\Model\Insert;
use Doctrine\Common\Persistence\ObjectManager; use Doctrine\DBAL\Exception as DBALException;
use Doctrine\DBAL\DBALException; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityManager;
use Neos\Flow\Annotations as Flow; use Neos\Flow\Annotations as Flow;
use Neos\Flow\Log\SystemLoggerInterface;
use Neos\Flow\Reflection\ReflectionService;
use Neos\Utility\TypeHandling; use Neos\Utility\TypeHandling;
use Psr\Log\LoggerInterface;
/** /**
* A SequenceNumber generator working for transactional databases * A SequenceNumber generator working for transactional databases
@ -22,21 +22,14 @@ use Neos\Utility\TypeHandling;
class SequenceGenerator class SequenceGenerator
{ {
/** /**
* @var ObjectManager
* @Flow\Inject * @Flow\Inject
* @var EntityManagerInterface
*/ */
protected $entityManager; protected $entityManager;
/** /**
* @var ReflectionService
* @Flow\Inject
* @deprecated
*/
protected $reflectionService;
/**
* @var SystemLoggerInterface
* @Flow\Inject * @Flow\Inject
* @var LoggerInterface
*/ */
protected $systemLogger; protected $systemLogger;
@ -44,8 +37,10 @@ class SequenceGenerator
* @param string|object $type * @param string|object $type
* *
* @return int * @return int
* @throws Exception
* @throws DBALException
*/ */
public function getNextNumberFor($type) public function getNextNumberFor($type): int
{ {
$type = $this->inferTypeFromSource($type); $type = $this->inferTypeFromSource($type);
$count = $this->getLastNumberFor($type); $count = $this->getLastNumberFor($type);
@ -61,13 +56,11 @@ class SequenceGenerator
/** /**
* @param int $count * @param int $count
* @param string|object $type * @param string $type
*
* @return bool * @return bool
*/ */
protected function validateFreeNumber($count, $type) protected function validateFreeNumber(int $count, string $type): bool
{ {
/* @var EntityManager $em */
$em = $this->entityManager; $em = $this->entityManager;
try { try {
$em->getConnection()->insert( $em->getConnection()->insert(
@ -79,10 +72,10 @@ class SequenceGenerator
return false; return false;
} catch (DBALException $e) { } catch (DBALException $e) {
if (! $e->getPrevious() instanceof \PDOException) { if (! $e->getPrevious() instanceof \PDOException) {
$this->systemLogger->logException($e); $this->systemLogger->critical('Exception occured: ' . $e->getMessage());
} }
} catch (\Exception $e) { } catch (\Exception $e) {
$this->systemLogger->logException($e); $this->systemLogger->critical('Exception occured: ' . $e->getMessage());
} }
return false; return false;
@ -93,8 +86,9 @@ class SequenceGenerator
* @param string|object $type * @param string|object $type
* *
* @return bool * @return bool
* @throws Exception
*/ */
public function advanceTo($to, $type) public function advanceTo(int $to, $type): bool
{ {
$type = $this->inferTypeFromSource($type); $type = $this->inferTypeFromSource($type);
@ -105,27 +99,27 @@ class SequenceGenerator
* @param string|object $type * @param string|object $type
* *
* @return int * @return int
* @throws Exception
* @throws DBALException
*/ */
public function getLastNumberFor($type) public function getLastNumberFor($type): int
{ {
/* @var EntityManager $em */ return (int) $this->entityManager->getConnection()->executeQuery(
$em = $this->entityManager; 'SELECT MAX(number) FROM '
. $this->entityManager->getClassMetadata(Insert::class)->getTableName()
return $em->getConnection()->executeQuery( . ' WHERE type = :type',
'SELECT MAX(number) FROM ' . $em->getClassMetadata(Insert::class)->getTableName() . ' WHERE type = :type',
['type' => $this->inferTypeFromSource($type)] ['type' => $this->inferTypeFromSource($type)]
)->fetchAll(\PDO::FETCH_COLUMN)[0]; )->fetchAll(\PDO::FETCH_COLUMN)[0];
} }
/** /**
* @param string|object $stringOrObject * @param string|object $stringOrObject
*
* @return string * @return string
* @throws Exception * @throws Exception
*/ */
protected function inferTypeFromSource($stringOrObject) protected function inferTypeFromSource($stringOrObject): string
{ {
if (is_object($stringOrObject)) { if (\is_object($stringOrObject)) {
$stringOrObject = TypeHandling::getTypeForValue($stringOrObject); $stringOrObject = TypeHandling::getTypeForValue($stringOrObject);
} }
if (! $stringOrObject) { if (! $stringOrObject) {

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Neos\Flow\Persistence\Doctrine\Migrations; namespace Neos\Flow\Persistence\Doctrine\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration; use Doctrine\DBAL\Migrations\AbstractMigration;
@ -25,11 +26,9 @@ class Version20140505093853 extends AbstractMigration
public function up(Schema $schema) public function up(Schema $schema)
{ {
// this up() migration is autogenerated, please modify it to your needs // this up() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql"); $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on "mysql".');
$this->addSql( $this->addSql('CREATE TABLE digicomp_sequence_domain_model_insert (number INT NOT NULL, type VARCHAR(255) NOT NULL, PRIMARY KEY(number, type))');
"CREATE TABLE digicomp_sequence_domain_model_insert (number INT NOT NULL, type VARCHAR(255) NOT NULL, PRIMARY KEY(number, type))"
);
} }
/** /**
@ -39,8 +38,8 @@ class Version20140505093853 extends AbstractMigration
public function down(Schema $schema) public function down(Schema $schema)
{ {
// this down() migration is autogenerated, please modify it to your needs // this down() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql"); $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on "mysql".');
$this->addSql("DROP TABLE digicomp_sequence_domain_model_insert"); $this->addSql('DROP TABLE digicomp_sequence_domain_model_insert');
} }
} }

View file

@ -1,4 +1,5 @@
<?php <?php
namespace Neos\Flow\Persistence\Doctrine\Migrations; namespace Neos\Flow\Persistence\Doctrine\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration; use Doctrine\DBAL\Migrations\AbstractMigration;
@ -25,10 +26,7 @@ class Version20160624203903 extends AbstractMigration
public function up(Schema $schema) public function up(Schema $schema)
{ {
// this up() migration is autogenerated, please modify it to your needs // this up() migration is autogenerated, please modify it to your needs
$this->abortIf( $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on "mysql".');
$this->connection->getDatabasePlatform()->getName() != 'mysql',
'Migration can only be executed safely on "mysql".'
);
$this->addSql('CREATE INDEX type_idx ON digicomp_sequence_domain_model_insert (type)'); $this->addSql('CREATE INDEX type_idx ON digicomp_sequence_domain_model_insert (type)');
} }
@ -40,10 +38,7 @@ class Version20160624203903 extends AbstractMigration
public function down(Schema $schema) public function down(Schema $schema)
{ {
// this down() migration is autogenerated, please modify it to your needs // this down() migration is autogenerated, please modify it to your needs
$this->abortIf( $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on "mysql".');
$this->connection->getDatabasePlatform()->getName() != 'mysql',
'Migration can only be executed safely on "mysql".'
);
$this->addSql('DROP INDEX type_idx ON digicomp_sequence_domain_model_insert'); $this->addSql('DROP INDEX type_idx ON digicomp_sequence_domain_model_insert');
} }

View file

@ -2,18 +2,18 @@ DigiComp.Sequence
------------------------- -------------------------
This is a very simple and stupid tool, helping in generation of gapless sequences. For this task it relies on key This is a very simple and stupid tool, helping in generation of gapless sequences. For this task it relies on key
integrity of the database of your choice. integrity of the database of your choice.
Usage is quite simple also: Usage is quite simple also:
/** /**
* @param \DigiComp\Sequence\Service\SequenceNumberGenerator $sequenceNumberGenerator * @param \DigiComp\Sequence\Service\SequenceNumberGenerator $sequenceNumberGenerator
*/ */
public function __construct(SequenceNumberGenerator $sequenceNumberGenerator) public function __construct(SequenceNumberGenerator $sequenceNumberGenerator)
{ {
$this->orderId = $sequenceNumberGenerator->getNextNumberFor($this); $this->orderId = $sequenceNumberGenerator->getNextNumberFor($this);
} }
``getNextNumberFor`` allows you to give an object which will be resolved to its FQCN or a custom sequence name. ``getNextNumberFor`` allows you to give an object which will be resolved to its FQCN or a custom sequence name.

View file

@ -19,7 +19,8 @@
"license": "MIT", "license": "MIT",
"homepage": "https://github.com/digicomp/DigiComp.Sequence", "homepage": "https://github.com/digicomp/DigiComp.Sequence",
"require": { "require": {
"neos/flow": "~4.1|~5.3" "neos/flow": "~5.3 | ^6.3.5",
"php": "^7.4"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "3.7.*", "phpunit/phpunit": "3.7.*",
@ -33,7 +34,8 @@
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-version/1.x-dev": "1.1.x-dev", "dev-version/1.x-dev": "1.1.x-dev",
"dev-develop": "2.0.x-dev" "dev-version/2.x-dev": "2.1.x-dev",
"dev-develop": "3.0.x-dev"
}, },
"applied-flow-migrations": [ "applied-flow-migrations": [
"Inwebs.Basket-201409170938", "Inwebs.Basket-201409170938",
@ -70,4 +72,4 @@
"Neos.Flow-20180415105700" "Neos.Flow-20180415105700"
] ]
} }
} }