<?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; } }