1: <?php
2: /**
3: * PHP version 5
4: * @package generalDriver
5: * @author Christian Schiffler <c.schiffler@cyberspectrum.de>
6: * @author Stefan Heimes <stefan_heimes@hotmail.com>
7: * @author Tristan Lins <tristan.lins@bit3.de>
8: * @copyright The MetaModels team.
9: * @license LGPL.
10: * @filesource
11: */
12:
13: namespace DcGeneral\Factory;
14:
15: use ContaoCommunityAlliance\Translator\TranslatorInterface;
16: use DcGeneral\DataDefinition\ContainerInterface;
17: use DcGeneral\EnvironmentInterface;
18: use DcGeneral\Event\EventPropagatorInterface;
19: use DcGeneral\Exception\DcGeneralRuntimeException;
20: use DcGeneral\Factory\Event\BuildDataDefinitionEvent;
21: use DcGeneral\Factory\Event\CreateDcGeneralEvent;
22: use DcGeneral\Factory\Event\PopulateEnvironmentEvent;
23:
24: /**
25: * Factory to create a DcGeneral instance.
26: *
27: * @package DcGeneral\Factory
28: */
29: class DcGeneralFactory implements DcGeneralFactoryInterface
30: {
31: /**
32: * Create a new factory with basic settings from the environment.
33: *
34: * This factory can be used to create a new Container, Environment, DcGeneral with the same base settings as the
35: * given environment.
36: *
37: * @param EnvironmentInterface $environment The environment to use as base.
38: *
39: * @return DcGeneralFactory
40: */
41: public static function deriveEmptyFromEnvironment(EnvironmentInterface $environment)
42: {
43: $factory = new DcGeneralFactory();
44: $factory->setEventPropagator($environment->getEventPropagator());
45: $factory->setTranslator($environment->getTranslator());
46: $factory->setEnvironmentClassName(get_class($environment));
47: $factory->setContainerClassName(get_class($environment->getDataDefinition()));
48: return $factory;
49: }
50:
51: /**
52: * Create a new factory with basic settings and same container name as the given environment is build for.
53: *
54: * This factory can be used to create a second Container, Environment, DcGeneral for the same container.
55: *
56: * @param EnvironmentInterface $environment The environment to use as base.
57: *
58: * @return DcGeneralFactory
59: */
60: public static function deriveFromEnvironment(EnvironmentInterface $environment)
61: {
62: $factory = static::deriveEmptyFromEnvironment($environment);
63: $factory->setContainerName($environment->getDataDefinition()->getName());
64: return $factory;
65: }
66:
67: /**
68: * The class name to use for the environment.
69: *
70: * @var string
71: */
72: protected $environmentClassName = 'DcGeneral\DefaultEnvironment';
73:
74: /**
75: * The name of the data container.
76: *
77: * @var string
78: */
79: protected $containerName;
80:
81: /**
82: * The class name of the class to use for the data definition container.
83: *
84: * @var string
85: */
86: protected $containerClassName = 'DcGeneral\DataDefinition\DefaultContainer';
87:
88: /**
89: * The class name of the class to use as DcGeneral.
90: *
91: * @var string
92: */
93: protected $dcGeneralClassName = 'DcGeneral\DcGeneral';
94:
95: /**
96: * The event propagator to use.
97: *
98: * @var EventPropagatorInterface
99: */
100: protected $eventPropagator = null;
101:
102: /**
103: * The translator that shall be used.
104: *
105: * @var TranslatorInterface
106: */
107: protected $translator = null;
108:
109: /**
110: * The environment for the new instance.
111: *
112: * @var EnvironmentInterface
113: */
114: protected $environment = null;
115:
116: /**
117: * The data definition container instance.
118: *
119: * @var ContainerInterface
120: */
121: protected $dataContainer = null;
122:
123: /**
124: * {@inheritdoc}
125: */
126: public function setEnvironmentClassName($environmentClassName)
127: {
128: $this->environmentClassName = (string)$environmentClassName;
129:
130: return $this;
131: }
132:
133: /**
134: * {@inheritdoc}
135: */
136: public function getEnvironmentClassName()
137: {
138: return $this->environmentClassName;
139: }
140:
141: /**
142: * {@inheritdoc}
143: */
144: public function setContainerName($containerName)
145: {
146: $this->containerName = (string)$containerName;
147:
148: return $this;
149: }
150:
151: /**
152: * {@inheritdoc}
153: */
154: public function getContainerName()
155: {
156: return $this->containerName;
157: }
158:
159: /**
160: * {@inheritdoc}
161: */
162: public function setContainerClassName($containerClassName)
163: {
164: $this->containerClassName = (string)$containerClassName;
165:
166: return $this;
167: }
168:
169: /**
170: * {@inheritdoc}
171: */
172: public function getContainerClassName()
173: {
174: return $this->containerClassName;
175: }
176:
177: /**
178: * {@inheritdoc}
179: */
180: public function setDcGeneralClassName($dcGeneralClassName)
181: {
182: $this->dcGeneralClassName = (string)$dcGeneralClassName;
183:
184: return $this;
185: }
186:
187: /**
188: * {@inheritdoc}
189: */
190: public function getDcGeneralClassName()
191: {
192: return $this->dcGeneralClassName;
193: }
194:
195: /**
196: * {@inheritdoc}
197: */
198: public function setEventPropagator(EventPropagatorInterface $eventPropagator)
199: {
200: $this->eventPropagator = $eventPropagator;
201:
202: return $this;
203: }
204:
205: /**
206: * {@inheritdoc}
207: */
208: public function getEventPropagator()
209: {
210: return $this->eventPropagator;
211: }
212:
213: /**
214: * {@inheritdoc}
215: */
216: public function setTranslator(TranslatorInterface $translator)
217: {
218: $this->translator = $translator;
219:
220: return $this;
221: }
222:
223: /**
224: * {@inheritdoc}
225: */
226: public function getTranslator()
227: {
228: return $this->translator;
229: }
230:
231: /**
232: * {@inheritdoc}
233: */
234: public function setEnvironment(EnvironmentInterface $environment = null)
235: {
236: $this->environment = $environment;
237:
238: return $this;
239: }
240:
241: /**
242: * {@inheritdoc}
243: */
244: public function getEnvironment()
245: {
246: return $this->environment;
247: }
248:
249: /**
250: * {@inheritdoc}
251: */
252: public function setDataContainer(ContainerInterface $dataContainer = null)
253: {
254: $this->dataContainer = $dataContainer;
255:
256: return $this;
257: }
258:
259: /**
260: * {@inheritdoc}
261: */
262: public function getDataContainer()
263: {
264: return $this->dataContainer;
265: }
266:
267: /**
268: * {@inheritdoc}
269: *
270: * @throws DcGeneralRuntimeException When no container name, no container or no event propagator is given.
271: */
272: public function createDcGeneral()
273: {
274: if (empty($this->containerName) && !$this->dataContainer)
275: {
276: throw new DcGeneralRuntimeException('Required container name or container is missing');
277: }
278:
279: if (empty($this->eventPropagator))
280: {
281: throw new DcGeneralRuntimeException('Required event propagator is missing');
282: }
283:
284: if ($this->environment)
285: {
286: $environment = $this->environment;
287: }
288: else
289: {
290: $environment = $this->createEnvironment();
291: }
292:
293: // Create reflections classes at one place.
294: $dcGeneralClass = new \ReflectionClass($this->dcGeneralClassName);
295:
296: /** @var \DcGeneral\DcGeneral $dcGeneral */
297: $dcGeneral = $dcGeneralClass->newInstance($environment);
298:
299: $event = new CreateDcGeneralEvent($dcGeneral);
300: $this->eventPropagator->propagate(
301: $event::NAME,
302: $event,
303: array($this->containerName)
304: );
305:
306: return $dcGeneral;
307: }
308:
309: /**
310: * {@inheritdoc}
311: *
312: * @throws DcGeneralRuntimeException When no container name, no container, no event propagator or no translator
313: * is given.
314: */
315: public function createEnvironment()
316: {
317: if (empty($this->containerName) && !$this->dataContainer)
318: {
319: throw new DcGeneralRuntimeException('Required container name or container is missing');
320: }
321:
322: if (empty($this->eventPropagator))
323: {
324: throw new DcGeneralRuntimeException('Required event propagator is missing');
325: }
326:
327: if (empty($this->translator))
328: {
329: throw new DcGeneralRuntimeException('Required translator is missing');
330: }
331:
332: if ($this->dataContainer)
333: {
334: $dataContainer = $this->dataContainer;
335: }
336: else
337: {
338: $dataContainer = $this->createContainer();
339: }
340:
341: $environmentClass = new \ReflectionClass($this->environmentClassName);
342:
343: /** @var EnvironmentInterface $environment */
344: $environment = $environmentClass->newInstance();
345: $environment->setDataDefinition($dataContainer);
346: $environment->setEventPropagator($this->eventPropagator);
347: $environment->setTranslator($this->translator);
348:
349: $event = new PopulateEnvironmentEvent($environment);
350: $this->eventPropagator->propagate(
351: $event::NAME,
352: $event,
353: array($this->containerName)
354: );
355:
356: return $environment;
357: }
358:
359: /**
360: * {@inheritdoc}
361: *
362: * @throws DcGeneralRuntimeException When no container name or no event propagator is given.
363: */
364: public function createContainer()
365: {
366: if (empty($this->containerName))
367: {
368: throw new DcGeneralRuntimeException('Required container name is missing');
369: }
370:
371: if (empty($this->eventPropagator))
372: {
373: throw new DcGeneralRuntimeException('Required event propagator is missing');
374: }
375:
376: /** @var \DcGeneral\DataDefinitionContainerInterface $definitions */
377: $definitions = $GLOBALS['container']['dc-general.data-definition-container'];
378:
379: if ($definitions->hasDefinition($this->containerName))
380: {
381: return $definitions->getDefinition($this->containerName);
382: }
383:
384: $containerClass = new \ReflectionClass($this->containerClassName);
385:
386: /** @var ContainerInterface $dataContainer */
387: $dataContainer = $containerClass->newInstance($this->containerName);
388:
389: $definitions->setDefinition($this->containerName, $dataContainer);
390:
391: $event = new BuildDataDefinitionEvent($dataContainer);
392: $this->eventPropagator->propagate(
393: $event::NAME,
394: $event,
395: array($this->containerName)
396: );
397:
398: return $dataContainer;
399: }
400: }
401: