nur-sery/nur_src/mapper/base/Producer.php

89 lines
2.2 KiB
PHP
Raw Normal View History

2024-04-04 16:26:22 +04:00
<?php
namespace nur\mapper\base;
use Generator;
use IteratorAggregate;
use nur\b\ICloseable;
use nur\b\params\IParametrable;
use nur\b\params\Parametrable;
use nur\mapper\base\oobd\IOobdManager;
use nur\mapper\base\oobd\TOobdManager;
/**
* Class Producer: un générateur qu'il est possible de piloter
* - notamment, il est possible de le fermer avant d'arriver à la fin de la
* génération avec la méthode {@link close()}
*
* La méthode {@link close()} doit être appelée à la fin de la génération, ce
* qui est automatique si on utilise des outils qui supportent {@link ICloseable}.
* le cas échéant, il faut le faire manuellement:
* ~~~
* $producer = new MyProducer();
* try {
* foreach ($producer as $value) {
* ...
* }
* } finally {
* $producer->close();
* }
* ~~~
*/
abstract class Producer extends Parametrable implements IteratorAggregate, ICloseable, IParametrable, IOobdManager {
use TOobdManager;
/**
* initialiser le générateur. cette méthode est appelée avant de lancer
* la génération
*/
protected function setup(): void {
}
/**
* terminer le générateur. cette méthode est appelée à la fin de la génération
*/
protected function teardown(): void {
}
/**
* retourner un générateur qui produit les données. ce générateur doit être
* préparé à prendre une exception {@link StopException} à chaque occurrence
* de yield
*/
abstract function producer();
/** @var Generator */
private $generator;
function getIterator() {
$this->setup();
$this->return = null;
return $this->generator = $this->producer();
}
function close(): void {
if ($this->generator !== null) {
if ($this->generator instanceof Generator) {
try {
$this->generator->throw(new StopException());
$hasReturned = true;
} catch (StopException $e) {
$hasReturned = false;
}
$this->return = $hasReturned? $this->generator->getReturn(): null;
}
$this->generator = null;
}
$this->teardown();
}
protected $return;
/**
* retourner la valeur de retour du générateur. il faut d'abord appeler la
* méthode {@link close()}
*/
function getReturn() {
return $this->return;
}
}