Arbeiten mit Übergängen

Mithilfe des Workflows lassen sich Abläufe von Objekten steuern. In diesem Beispiel wird ein fiktiver Workflow definiert und ein Container in diesem verschoben.

Der Workflow besteht aus drei Zuständen und verschiedenen Übergängen. Ein Container kann von A nach B und von B nach A gelangen. Außerdem kann der Container von jedem Zustand in den Zustand A wechseln.

uml diagram

Zuerst werden die verwendeten Status State Objekte, die Erstellvorschrift Admission und der Workflow definiert.

class Item implements \Alvine\Application\Workflow\Container {
    use \Alvine\Application\Workflow\Container\Implementation;
}

/**
 * Verschiedene Status A -> B -> C
 */
$stateA=new \Alvine\Application\Workflow\State('A');
$stateB=new \Alvine\Application\Workflow\State('B');
$stateC=new \Alvine\Application\Workflow\State('C');

/** Ersteller-Klasse; Neue Container vom Type Item im Status A */
$admission=new \Alvine\Application\Workflow\Admission
    (\MyNamespace\Item::class, $stateA);

/** Workflow */
$workflow=new \Alvine\Application\Workflow\Processor
    ('workflow-with-automation');
$workflow->setAdmission($admission);

Im Anschluss werden die einzelnen Übergänge definiert.

$transitions = new \Alvine\Application\Workflow\Transitions;

/** Ein Übergang von allen Zuständen zum Zustand A */
$transitions->addTransition(new \Alvine\Application\Workflow\Transition
    (null, null, $stateA, 'fromAllToA'));

/** Ein Übergang von A nach B  */
$transitions->addTransition(new \Alvine\Application\Workflow\Transition
    ($stateA, null, $stateB, 'fromAToB'));

/** Ein Übergang von B nach C */
$transitions->addTransition(new \Alvine\Application\Workflow\Transition
    ($stateB, null, $stateC, 'fromBToC'));

$workflow->setTransitions($transitions);

Jetzt wird mit \Alvine\Application\Workflow\Processor::create() ein Container erstellt. Die Erstellung erfolgt durch die Admission-Klasse. Als erster Status wird (wie oben definiert) Status A gesetzt.

uml diagram

/** Container erstellen */
$container=$workflow->create();

echo (string) $container->getHistory();

/**

⬤  2019-06-01 10:00:00  workflow-wit...
        ▶ container created
▷  2019-06-01 10:00:00  workflow-wit...        ⬤ ▬▶ A
        ▶ container state changed from  to A

 */

Jetzt soll der Container vom Status A in den Status B überführt werden. Dies erfolgt mit der Methode \Alvine\Application\Workflow\Processor::run()

$workflow->run($container, 'fromAToB');

echo (string) $container->getHistory();

/**

⬤  2019-06-01 10:00:00  workflow-wit...
        ▶ container created
▷  2019-06-01 10:00:00  workflow-wit...        ⬤ ▬▶ A              
        ▶ container state changed from  to A
▷  2019-06-01 10:00:00  workflow-wit...        A ▬▶ B              
        ▶ container state changed from A to B

 */

Der Container befindet sich jetzt im Status B. Von hier aus führt ein Weg zurück zum Status A und ein Weg zum Status C.

uml diagram

Als Nächstes soll der Container von B nach C verschoben werden. Dies erfolgt nach dem gleichen Prinzip.

$workflow->run($container, 'fromBToC');

echo (string) $container->getHistory();

/**

⬤  2019-06-01 10:00:00  workflow-wit...
        ▶ container created
▷  2019-06-01 10:00:00  workflow-wit...        ⬤ ▬▶ A              
        ▶ container state changed from  to A
▷  2019-06-01 10:00:00  workflow-wit...        A ▬▶ B              
        ▶ container state changed from A to B
▷  2019-06-01 10:00:00  workflow-wit...        B ▬▶ C              
        ▶ container state changed from B to C

 */

Der Container befindet sich jetzt im Status C. Von hier aus führt nur ein Weg zurück zum Status A.

uml diagram

Wird nun versucht den Container noch mal von A nach B zu verschieben, so wird eine Exception geworfen, da der Container sich nicht im Zustand A befindet und nicht nach B verschoben werden kann.

try {
    $workflow->run($container, 'fromAToB');
} catch (\Alvine\Application\Workflow\Transition\NotPermittedException $ex) {
    echo "Exception!";
}

echo (string) $container->getHistory();

/**
Exception!

⬤  2019-06-01 10:00:00  workflow-wit...
        ▶ container created
▷  2019-06-01 10:00:00  workflow-wit...        ⬤ ▬▶ A              
        ▶ container state changed from  to A
▷  2019-06-01 10:00:00  workflow-wit...        A ▬▶ B              
        ▶ container state changed from A to B
▷  2019-06-01 10:00:00  workflow-wit...        B ▬▶ C              
        ▶ container state changed from B to C

 */

Als letzten Schritt verschieben wir den Container mit dem Übergang fromAllToA wieder in den Status A.

$workflow->run($container, 'fromAllToA');

echo (string) $container->getHistory();

/**

⬤  2019-06-01 10:00:00  workflow-wit...
        ▶ container created
▷  2019-06-01 10:00:00  workflow-wit...        ⬤ ▬▶ A              
        ▶ container state changed from  to A
▷  2019-06-01 10:00:00  workflow-wit...          A ▬▶ B              
        ▶ container state changed from A to B
▷  2019-06-01 10:00:00  workflow-wit...          B ▬▶ C              
        ▶ container state changed from B to C
▷  2019-06-01 10:00:00  workflow-wit...          C ▬▶ A              
        ▶ container state changed from C to A

 */

uml diagram

Voila!