1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\Workflow;
13
14use Symfony\Component\Workflow\Exception\InvalidArgumentException;
15use Symfony\Component\Workflow\Exception\LogicException;
16
17/**
18 * @author Fabien Potencier <fabien@symfony.com>
19 * @author Grégoire Pineau <lyrixx@lyrixx.info>
20 * @author Tobias Nyholm <tobias.nyholm@gmail.com>
21 */
22final class Definition
23{
24    private $places = [];
25    private $transitions = [];
26    private $initialPlace;
27
28    /**
29     * @param string[]     $places
30     * @param Transition[] $transitions
31     * @param string|null  $initialPlace
32     */
33    public function __construct(array $places, array $transitions, $initialPlace = null)
34    {
35        foreach ($places as $place) {
36            $this->addPlace($place);
37        }
38
39        foreach ($transitions as $transition) {
40            $this->addTransition($transition);
41        }
42
43        $this->setInitialPlace($initialPlace);
44    }
45
46    /**
47     * @return string|null
48     */
49    public function getInitialPlace()
50    {
51        return $this->initialPlace;
52    }
53
54    /**
55     * @return string[]
56     */
57    public function getPlaces()
58    {
59        return $this->places;
60    }
61
62    /**
63     * @return Transition[]
64     */
65    public function getTransitions()
66    {
67        return $this->transitions;
68    }
69
70    private function setInitialPlace($place)
71    {
72        if (null === $place) {
73            return;
74        }
75
76        if (!isset($this->places[$place])) {
77            throw new LogicException(sprintf('Place "%s" cannot be the initial place as it does not exist.', $place));
78        }
79
80        $this->initialPlace = $place;
81    }
82
83    private function addPlace($place)
84    {
85        if (!preg_match('{^[\w_-]+$}', $place)) {
86            throw new InvalidArgumentException(sprintf('The place "%s" contains invalid characters.', $place));
87        }
88
89        if (!\count($this->places)) {
90            $this->initialPlace = $place;
91        }
92
93        $this->places[$place] = $place;
94    }
95
96    private function addTransition(Transition $transition)
97    {
98        $name = $transition->getName();
99
100        foreach ($transition->getFroms() as $from) {
101            if (!isset($this->places[$from])) {
102                throw new LogicException(sprintf('Place "%s" referenced in transition "%s" does not exist.', $from, $name));
103            }
104        }
105
106        foreach ($transition->getTos() as $to) {
107            if (!isset($this->places[$to])) {
108                throw new LogicException(sprintf('Place "%s" referenced in transition "%s" does not exist.', $to, $name));
109            }
110        }
111
112        $this->transitions[] = $transition;
113    }
114}
115