Overview

Namespaces

  • DcGeneral
    • Clipboard
    • Contao
      • Callback
      • Compatibility
      • DataDefinition
        • Definition
      • Dca
        • Builder
          • Legacy
        • Definition
        • Palette
        • Populator
      • Event
      • View
        • Contao2BackendView
          • Event
    • Controller
    • Data
    • DataDefinition
      • Builder
      • Definition
        • Properties
        • View
          • Panel
      • ModelRelationship
      • Palette
        • Builder
          • Event
        • Condition
          • Palette
          • Property
    • EnvironmentPopulator
    • Event
    • Exception
    • Factory
      • Event
    • Panel
    • View
      • Event

Classes

  • DcaReadingDataDefinitionBuilder
  • ExtendedLegacyDcaDataDefinitionBuilder
  • LegacyDcaDataDefinitionBuilder
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Todo
  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\Contao\Dca\Builder\Legacy;
 14: 
 15: use DcGeneral\Contao\DataDefinition\Definition\Contao2BackendViewDefinition;
 16: use DcGeneral\Contao\DataDefinition\Definition\Contao2BackendViewDefinitionInterface;
 17: use DcGeneral\Contao\Dca\ContaoDataProviderInformation;
 18: use DcGeneral\Contao\Dca\Definition\ExtendedDca;
 19: use DcGeneral\DataDefinition\ContainerInterface;
 20: use DcGeneral\DataDefinition\Definition\DataProviderDefinitionInterface;
 21: use DcGeneral\DataDefinition\Definition\DefaultBasicDefinition;
 22: use DcGeneral\DataDefinition\Definition\DefaultDataProviderDefinition;
 23: use DcGeneral\DataDefinition\Definition\DefaultModelRelationshipDefinition;
 24: use DcGeneral\DataDefinition\Definition\DefaultPalettesDefinition;
 25: use DcGeneral\DataDefinition\Definition\ModelRelationshipDefinitionInterface;
 26: use DcGeneral\DataDefinition\Definition\PalettesDefinitionInterface;
 27: use DcGeneral\DataDefinition\Definition\View\DefaultModelFormatterConfig;
 28: use DcGeneral\DataDefinition\Definition\View\ListingConfigInterface;
 29: use DcGeneral\DataDefinition\ModelRelationship\ParentChildCondition;
 30: use DcGeneral\DataDefinition\ModelRelationship\RootCondition;
 31: use DcGeneral\Exception\DcGeneralInvalidArgumentException;
 32: use DcGeneral\Exception\DcGeneralRuntimeException;
 33: use DcGeneral\Factory\DcGeneralFactory;
 34: use DcGeneral\Factory\Event\BuildDataDefinitionEvent;
 35: use DcGeneral\Factory\Event\PopulateEnvironmentEvent;
 36: 
 37: /**
 38:  * Build the container config from legacy DCA syntax.
 39:  */
 40: class ExtendedLegacyDcaDataDefinitionBuilder extends DcaReadingDataDefinitionBuilder
 41: {
 42:     const PRIORITY = 101;
 43: 
 44:     /**
 45:      * {@inheritdoc}
 46:      */
 47:     public function build(ContainerInterface $container, BuildDataDefinitionEvent $event)
 48:     {
 49:         if (!$this->loadDca($container->getName(), $event->getDispatcher()))
 50:         {
 51:             return;
 52:         }
 53: 
 54:         $this->parseBasicDefinition($container);
 55:         $this->parseDataProvider($container);
 56:         $this->parsePalettes($container);
 57:         $this->parseConditions($container);
 58:         $this->parseBackendView($container);
 59:         $this->parseClassNames($container);
 60:         $this->loadAdditionalDefinitions($container, $event);
 61:     }
 62: 
 63:     /**
 64:      * Ensure that the basic configuration is set in the definition.
 65:      *
 66:      * @param ContainerInterface $container The container where the data shall be stored.
 67:      *
 68:      * @return void
 69:      */
 70:     protected function parseBasicDefinition(ContainerInterface $container)
 71:     {
 72:         if (!$container->hasBasicDefinition())
 73:         {
 74:             $config = new DefaultBasicDefinition();
 75:             $container->setBasicDefinition($config);
 76:         }
 77:     }
 78: 
 79:     /**
 80:      * Load all additional definitions, like naming of parent data provider etc.
 81:      *
 82:      * @param ContainerInterface       $container The container where the data shall be stored.
 83:      *
 84:      * @param BuildDataDefinitionEvent $event     The event being emitted.
 85:      *
 86:      * @return void
 87:      */
 88:     protected function loadAdditionalDefinitions(ContainerInterface $container, BuildDataDefinitionEvent $event)
 89:     {
 90:         if (($providers = $this->getFromDca('dca_config/data_provider')) !== null)
 91:         {
 92:             $event->getDispatcher()->addListener(
 93:                 sprintf('%s[%s]', PopulateEnvironmentEvent::NAME, $container->getName()),
 94:                 function (PopulateEnvironmentEvent $event) {
 95:                     $environment = $event->getEnvironment();
 96:                     $definition  = $environment->getDataDefinition();
 97:                     $parentName  = $definition->getBasicDefinition()->getParentDataProvider();
 98: 
 99:                     if ($parentName)
100:                     {
101:                         $factory          = DcGeneralFactory::deriveEmptyFromEnvironment($environment)->setContainerName($parentName);
102:                         $parentDefinition = $factory->createContainer();
103: 
104:                         $environment->setParentDataDefinition($parentDefinition);
105:                     }
106: 
107:                     $rootName = $definition->getBasicDefinition()->getRootDataProvider();
108:                     if ($rootName)
109:                     {
110: 
111:                         $factory        = DcGeneralFactory::deriveEmptyFromEnvironment($environment)->setContainerName($rootName);
112:                         $rootDefinition = $factory->createContainer();
113: 
114:                         $environment->setRootDataDefinition($rootDefinition);
115:                     }
116:                 }
117:             );
118:         }
119:     }
120: 
121:     /**
122:      * Parse all class names for view, controller and callback class.
123:      *
124:      * @param ContainerInterface $container The container where the data shall be stored.
125:      *
126:      * @return void
127:      *
128:      * @throws DcGeneralInvalidArgumentException When the container is of invalid type.
129:      */
130:     protected function parseClassNames(ContainerInterface $container)
131:     {
132:         if ($container->hasDefinition(ExtendedDca::NAME))
133:         {
134:             $definition = $container->getDefinition(ExtendedDca::NAME);
135: 
136:             if (!($definition instanceof ExtendedDca))
137:             {
138:                 throw new DcGeneralInvalidArgumentException(sprintf(
139:                     'Definition with name %s must be an instance of ExtendedDca but instance of %s encountered.',
140:                     ExtendedDca::NAME,
141:                     get_class($definition)
142:                 ));
143:             }
144:         }
145:         else
146:         {
147:             $definition = new ExtendedDca();
148:             $container->setDefinition(ExtendedDca::NAME, $definition);
149:         }
150: 
151:         if ($this->getFromDca('dca_config') === null)
152:         {
153:             return;
154:         }
155: 
156:         if (($class = $this->getFromDca('dca_config/controller')) !== null)
157:         {
158:             $definition->setControllerClass($class);
159:         }
160: 
161:         if (($class = $this->getFromDca('dca_config/view')) !== null)
162:         {
163:             $definition->setViewClass($class);
164:         }
165:     }
166: 
167:     /**
168:      * Parse a single data provider information and prepare the definition object for it.
169:      *
170:      * @param ContainerInterface              $container   The container where the data shall be stored.
171:      *
172:      * @param DataProviderDefinitionInterface $providers   The data provider container.
173:      *
174:      * @param array                           $information The information for the data provider to be parsed.
175:      *
176:      * @return ContaoDataProviderInformation|null
177:      */
178:     protected function parseSingleDataProvider(
179:         ContainerInterface $container,
180:         DataProviderDefinitionInterface $providers,
181:         array $information
182:     )
183:     {
184:         if (isset($information['factory']))
185:         {
186:             $factoryClass        = new \ReflectionClass($information['factory']);
187:             $factory             = $factoryClass->newInstance();
188:             $providerInformation = $factory->build($information);
189:         }
190:         else
191:         {
192:             // Determine the name.
193:             if (isset($information['source']))
194:             {
195:                 $providerName = $information['source'];
196:             }
197:             else
198:             {
199:                 $providerName = $container->getName();
200:             }
201: 
202:             // Check config if it already exists, if not, add it.
203:             if (!$providers->hasInformation($providerName))
204:             {
205:                 $providerInformation = new ContaoDataProviderInformation();
206:                 $providerInformation->setName($providerName);
207:                 $providers->addInformation($providerInformation);
208:             }
209:             else
210:             {
211:                 $providerInformation = $providers->getInformation($providerName);
212:             }
213: 
214:             if (!$providerInformation->getTableName())
215:             {
216:                 $providerInformation
217:                     ->setTableName($providerName);
218:             }
219: 
220:             if (isset($information['class']))
221:             {
222:                 $providerInformation->setClassName($information['class']);
223:             }
224:         }
225: 
226:         return $providerInformation;
227:     }
228: 
229:     /**
230:      * This method parses all data provider related information from Contao legacy data container arrays.
231:      *
232:      * @param ContainerInterface $container The container where the data shall be stored.
233:      *
234:      * @return void
235:      */
236:     protected function parseDataProvider(ContainerInterface $container)
237:     {
238:         // Parse data provider.
239:         if ($container->hasDataProviderDefinition())
240:         {
241:             $config = $container->getDataProviderDefinition();
242:         }
243:         else
244:         {
245:             $config = new DefaultDataProviderDefinition();
246:             $container->setDataProviderDefinition($config);
247:         }
248: 
249:         // First check if we are using the "new" notation used in DcGeneral 0.9.
250:         if (!is_array($this->getFromDca('dca_config/data_provider')))
251:         {
252:             return;
253:         }
254: 
255:         $dataProvidersDca = $this->getFromDca('dca_config/data_provider');
256: 
257:         foreach ($dataProvidersDca as $dataProviderDcaName => $dataProviderDca)
258:         {
259:             $providerInformation = $this->parseSingleDataProvider($container, $config, $dataProviderDca);
260: 
261:             if ($providerInformation instanceof ContaoDataProviderInformation)
262:             {
263:                 $initializationData = (array)$providerInformation->getInitializationData();
264: 
265:                 $providerInformation->setInitializationData(array_merge(
266:                     $dataProviderDca,
267:                     $initializationData
268:                 ));
269: 
270:                 switch ($dataProviderDcaName)
271:                 {
272:                     case 'default':
273:                         $providerInformation->setVersioningEnabled(
274:                             (bool)$this->getFromDca('config/enableVersioning')
275:                         );
276: 
277:                         $container->getBasicDefinition()->setDataProvider($providerInformation->getName());
278:                         break;
279: 
280:                     case 'root':
281:                         $container->getBasicDefinition()->setRootDataProvider($providerInformation->getName());
282:                         break;
283: 
284:                     case 'parent':
285:                         $container->getBasicDefinition()->setParentDataProvider($providerInformation->getName());
286:                         break;
287: 
288:                     default:
289:                 }
290:             }
291:         }
292:     }
293: 
294:     /**
295:      * Parse the palette information.
296:      *
297:      * @param ContainerInterface $container The container where the data shall be stored.
298:      *
299:      * @return void
300:      */
301:     protected function parsePalettes(ContainerInterface $container)
302:     {
303:         $palettesDca = $this->getFromDca('palettes');
304: 
305:         // Skip while there is no extended palette definition.
306:         if (!is_callable($palettesDca))
307:         {
308:             return;
309:         }
310: 
311:         if ($container->hasDefinition(PalettesDefinitionInterface::NAME))
312:         {
313:             $palettesDefinition = $container->getDefinition(PalettesDefinitionInterface::NAME);
314:         }
315:         else
316:         {
317:             $palettesDefinition = new DefaultPalettesDefinition();
318:             $container->setDefinition(PalettesDefinitionInterface::NAME, $palettesDefinition);
319:         }
320: 
321:         call_user_func($palettesDca, $palettesDefinition, $container);
322:     }
323: 
324:     /**
325:      * Parse the conditions for model relationships from the definition.
326:      *
327:      * This includes root entry filters, parent child relationship.
328:      *
329:      * @param ContainerInterface $container The container where the data shall be stored.
330:      *
331:      * @return void
332:      *
333:      * @throws DcGeneralRuntimeException If any information is missing or invalid.
334:      */
335:     protected function parseConditions(ContainerInterface $container)
336:     {
337:         if ($container->hasDefinition(ModelRelationshipDefinitionInterface::NAME))
338:         {
339:             $definition = $container->getDefinition(ModelRelationshipDefinitionInterface::NAME);
340:         }
341:         else
342:         {
343:             $definition = new DefaultModelRelationshipDefinition();
344:             $container->setDefinition(ModelRelationshipDefinitionInterface::NAME, $definition);
345:         }
346: 
347:         if (($rootCondition = $this->getFromDca('dca_config/rootEntries')) !== null)
348:         {
349:             $rootProvider = $container->getBasicDefinition()->getRootDataProvider();
350: 
351:             if (!$rootProvider)
352:             {
353:                 throw new DcGeneralRuntimeException(
354:                     'Root data provider name not specified in DCA but rootEntries section specified.'
355:                 );
356:             }
357: 
358:             if (!$container->getDataProviderDefinition()->hasInformation($rootProvider))
359:             {
360:                 throw new DcGeneralRuntimeException('Unknown root data provider but rootEntries section specified.');
361:             }
362: 
363:             if (isset($rootCondition[$rootProvider]))
364:             {
365:                 $rootCondition = $rootCondition[$rootProvider];
366: 
367:                 $myFilter = $rootCondition['filter'];
368:                 $mySetter = $rootCondition['setOn'];
369: 
370:                 if (($relationship = $definition->getRootCondition()) === null)
371:                 {
372:                     $relationship = new RootCondition();
373:                     $setter       = $mySetter;
374:                     $filter       = array(
375:                         'operation' => 'AND',
376:                         'children' => $myFilter
377:                     );
378:                 }
379:                 else
380:                 {
381:                     /** @var \DcGeneral\DataDefinition\ModelRelationship\RootConditionInterface $relationship */
382:                     if ($relationship->getSetters())
383:                     {
384:                         $setter = array_merge_recursive($mySetter, $relationship->getSetters());
385:                     }
386:                     else
387:                     {
388:                         $setter = $mySetter;
389:                     }
390:                     $filter = array_merge($relationship->getFilterArray(), $myFilter);
391:                     $filter = array(
392:                         'operation' => 'AND',
393:                         'children' => array($filter)
394:                     );
395:                 }
396: 
397:                 $relationship
398:                     ->setSourceName($rootProvider)
399:                     ->setFilterArray(array($filter))
400:                     ->setSetters($setter);
401:                 $definition->setRootCondition($relationship);
402:             }
403:         }
404: 
405:         if (($childConditions = $this->getFromDca('dca_config/childCondition')) !== null)
406:         {
407:             foreach ((array)$childConditions as $childCondition)
408:             {
409:                 $relationship = new ParentChildCondition();
410:                 /** @var \DcGeneral\DataDefinition\ModelRelationship\ParentChildConditionInterface $relationship */
411:                 $relationship
412:                     ->setSourceName($childCondition['from'])
413:                     ->setDestinationName($childCondition['to'])
414:                     ->setFilterArray($childCondition['filter'])
415:                     ->setSetters($childCondition['setOn'])
416:                     ->setInverseFilterArray($childCondition['inverse']);
417:                 $definition->addChildCondition($relationship);
418:             }
419:         }
420:     }
421: 
422:     /**
423:      * Parse and build the backend view definition for the old Contao2 backend view.
424:      *
425:      * This method expects to find an instance of Contao2BackendViewDefinitionInterface in the container.
426:      *
427:      * @param ContainerInterface $container The container where the data shall be stored.
428:      *
429:      * @return void
430:      *
431:      * @throws DcGeneralInvalidArgumentException If the stored definition in the container is of invalid type.
432:      */
433:     protected function parseBackendView(ContainerInterface $container)
434:     {
435:         if ($container->hasDefinition(Contao2BackendViewDefinitionInterface::NAME))
436:         {
437:             $view = $container->getDefinition(Contao2BackendViewDefinitionInterface::NAME);
438:         }
439:         else
440:         {
441:             $view = new Contao2BackendViewDefinition();
442:             $container->setDefinition(Contao2BackendViewDefinitionInterface::NAME, $view);
443:         }
444: 
445:         if (!$view instanceof Contao2BackendViewDefinitionInterface)
446:         {
447:             throw new DcGeneralInvalidArgumentException(
448:                 'Configured BackendViewDefinition does not implement Contao2BackendViewDefinitionInterface.'
449:             );
450:         }
451: 
452:         $this->parseListing($view);
453:     }
454: 
455:     /**
456:      * Parse the listing configuration.
457:      *
458:      * @param Contao2BackendViewDefinitionInterface $view The backend view definition.
459:      *
460:      * @return void
461:      */
462:     protected function parseListing(Contao2BackendViewDefinitionInterface $view)
463:     {
464:         $listing = $view->getListingConfig();
465: 
466:         $this->parseListLabel($listing);
467:     }
468: 
469:     /**
470:      * Parse the sorting part of listing configuration.
471:      *
472:      * @param ListingConfigInterface $listing The listing configuration to be populated.
473:      *
474:      * @return void
475:      */
476:     protected function parseListLabel(ListingConfigInterface $listing)
477:     {
478:         if (($formats = $this->getFromDca('dca_config/child_list')) === null)
479:         {
480:             return;
481:         }
482: 
483:         foreach ($formats as $providerName => $format)
484:         {
485:             $formatter  = new DefaultModelFormatterConfig();
486:             $configured = false;
487: 
488:             if (isset($format['fields']))
489:             {
490:                 $formatter->setPropertyNames($format['fields']);
491:                 $configured = true;
492:             }
493: 
494:             if (isset($format['format']))
495:             {
496:                 $formatter->setFormat($format['format']);
497:                 $configured = true;
498:             }
499: 
500:             if (isset($format['maxCharacters']))
501:             {
502:                 $formatter->setMaxLength($format['maxCharacters']);
503:                 $configured = true;
504:             }
505: 
506:             if ($configured)
507:             {
508:                 $listing->setLabelFormatter($providerName, $formatter);
509:             }
510:         }
511:     }
512: }
513: 
contao-community-alliance/dc-general API documentation generated by ApiGen 2.8.0