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\Callback\ContainerGetBreadcrumbCallbackListener;
  16: use DcGeneral\Contao\Callback\ContainerGlobalButtonCallbackListener;
  17: use DcGeneral\Contao\Callback\ContainerHeaderCallbackListener;
  18: use DcGeneral\Contao\Callback\ContainerOnCopyCallbackListener;
  19: use DcGeneral\Contao\Callback\ContainerOnCutCallbackListener;
  20: use DcGeneral\Contao\Callback\ContainerOnDeleteCallbackListener;
  21: use DcGeneral\Contao\Callback\ContainerOnLoadCallbackListener;
  22: use DcGeneral\Contao\Callback\ContainerOnSubmitCallbackListener;
  23: use DcGeneral\Contao\Callback\ContainerPasteButtonCallbackListener;
  24: use DcGeneral\Contao\Callback\ContainerPasteRootButtonCallbackListener;
  25: use DcGeneral\Contao\Callback\ModelChildRecordCallbackListener;
  26: use DcGeneral\Contao\Callback\ModelGroupCallbackListener;
  27: use DcGeneral\Contao\Callback\ModelLabelCallbackListener;
  28: use DcGeneral\Contao\Callback\ModelOperationButtonCallbackListener;
  29: use DcGeneral\Contao\Callback\ModelOptionsCallbackListener;
  30: use DcGeneral\Contao\Callback\PropertyInputFieldCallbackListener;
  31: use DcGeneral\Contao\Callback\PropertyInputFieldGetWizardCallbackListener;
  32: use DcGeneral\Contao\Callback\PropertyOnLoadCallbackListener;
  33: use DcGeneral\Contao\Callback\PropertyOnSaveCallbackListener;
  34: use DcGeneral\Contao\Dca\ContaoDataProviderInformation;
  35: use DcGeneral\Contao\Dca\Palette\LegacyPalettesParser;
  36: use DcGeneral\Contao\View\Contao2BackendView\Event\BuildWidgetEvent;
  37: use DcGeneral\Contao\View\Contao2BackendView\Event\DecodePropertyValueForWidgetEvent;
  38: use DcGeneral\Contao\View\Contao2BackendView\Event\EncodePropertyValueFromWidgetEvent;
  39: use DcGeneral\Contao\View\Contao2BackendView\Event\GetBreadcrumbEvent;
  40: use DcGeneral\Contao\View\Contao2BackendView\Event\GetGlobalButtonEvent;
  41: use DcGeneral\Contao\View\Contao2BackendView\Event\GetGroupHeaderEvent;
  42: use DcGeneral\Contao\View\Contao2BackendView\Event\GetOperationButtonEvent;
  43: use DcGeneral\Contao\View\Contao2BackendView\Event\GetParentHeaderEvent;
  44: use DcGeneral\Contao\View\Contao2BackendView\Event\GetPasteButtonEvent;
  45: use DcGeneral\Contao\View\Contao2BackendView\Event\GetPasteRootButtonEvent;
  46: use DcGeneral\Contao\View\Contao2BackendView\Event\GetPropertyOptionsEvent;
  47: use DcGeneral\Contao\View\Contao2BackendView\Event\ManipulateWidgetEvent;
  48: use DcGeneral\Contao\View\Contao2BackendView\Event\ModelToLabelEvent;
  49: use DcGeneral\Contao\View\Contao2BackendView\Event\ParentViewChildRecordEvent;
  50: use DcGeneral\DataDefinition\ContainerInterface;
  51: use DcGeneral\Contao\DataDefinition\Definition\Contao2BackendViewDefinitionInterface;
  52: use DcGeneral\DataDefinition\Definition\BasicDefinitionInterface;
  53: use DcGeneral\Contao\DataDefinition\Definition\Contao2BackendViewDefinition;
  54: use DcGeneral\DataDefinition\Definition\DefaultBasicDefinition;
  55: use DcGeneral\DataDefinition\Definition\DefaultDataProviderDefinition;
  56: use DcGeneral\DataDefinition\Definition\DefaultModelRelationshipDefinition;
  57: use DcGeneral\DataDefinition\Definition\DefaultPalettesDefinition;
  58: use DcGeneral\DataDefinition\Definition\ModelRelationshipDefinitionInterface;
  59: use DcGeneral\DataDefinition\Definition\Properties\DefaultProperty;
  60: use DcGeneral\DataDefinition\Definition\Properties\PropertyInterface;
  61: use DcGeneral\DataDefinition\Definition\PalettesDefinitionInterface;
  62: use DcGeneral\DataDefinition\Definition\DefaultPropertiesDefinition;
  63: use DcGeneral\DataDefinition\Definition\View\Command;
  64: use DcGeneral\DataDefinition\Definition\View\CommandInterface;
  65: use DcGeneral\DataDefinition\Definition\View\CutCommand;
  66: use DcGeneral\DataDefinition\Definition\View\DefaultModelFormatterConfig;
  67: use DcGeneral\DataDefinition\Definition\View\ListingConfigInterface;
  68: use DcGeneral\DataDefinition\Definition\View\Panel\DefaultFilterElementInformation;
  69: use DcGeneral\DataDefinition\Definition\View\Panel\DefaultLimitElementInformation;
  70: use DcGeneral\DataDefinition\Definition\View\Panel\DefaultSearchElementInformation;
  71: use DcGeneral\DataDefinition\Definition\View\Panel\DefaultSortElementInformation;
  72: use DcGeneral\DataDefinition\Definition\View\Panel\DefaultSubmitElementInformation;
  73: use DcGeneral\DataDefinition\Definition\View\Panel\SubmitElementInformationInterface;
  74: use DcGeneral\DataDefinition\Definition\View\PanelRowInterface;
  75: use DcGeneral\DataDefinition\ModelRelationship\RootCondition;
  76: use DcGeneral\Event\PostDeleteModelEvent;
  77: use DcGeneral\Event\PostDuplicateModelEvent;
  78: use DcGeneral\Event\PostPasteModelEvent;
  79: use DcGeneral\Event\PostPersistModelEvent;
  80: use DcGeneral\Exception\DcGeneralInvalidArgumentException;
  81: use DcGeneral\Exception\DcGeneralRuntimeException;
  82: use DcGeneral\Factory\DcGeneralFactory;
  83: use DcGeneral\Factory\Event\BuildDataDefinitionEvent;
  84: use DcGeneral\Factory\Event\CreateDcGeneralEvent;
  85: use DcGeneral\Factory\Event\PopulateEnvironmentEvent;
  86: use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  87: 
  88: /**
  89:  * Build the container config from legacy DCA syntax.
  90:  */
  91: class LegacyDcaDataDefinitionBuilder extends DcaReadingDataDefinitionBuilder
  92: {
  93:     const PRIORITY = 100;
  94: 
  95:     /**
  96:      * {@inheritDoc}
  97:      */
  98:     public function build(ContainerInterface $container, BuildDataDefinitionEvent $event)
  99:     {
 100:         if (!$this->loadDca($container->getName(), $event->getDispatcher()))
 101:         {
 102:             return;
 103:         }
 104: 
 105:         $this->parseCallbacks($container, $event->getDispatcher());
 106:         $this->parseBasicDefinition($container);
 107:         $this->parseDataProvider($container);
 108:         $this->parseRootEntries($container);
 109:         $this->parseParentChildConditions($container);
 110:         $this->parseBackendView($container);
 111:         $this->parsePalettes($container);
 112:         $this->parseProperties($container);
 113:         $this->loadAdditionalDefinitions($container, $event);
 114:     }
 115: 
 116:     /**
 117:      * Load additional definitions, like naming of parent data provider.
 118:      *
 119:      * This method will register an event to the populate environment event in which the parent data provider container
 120:      * will get loaded.
 121:      *
 122:      * @param ContainerInterface       $container The container where the data shall be stored.
 123:      *
 124:      * @param BuildDataDefinitionEvent $event     The event being emitted.
 125:      *
 126:      * @return void
 127:      */
 128:     protected function loadAdditionalDefinitions(ContainerInterface $container, BuildDataDefinitionEvent $event)
 129:     {
 130:         if ($this->getFromDca('config/ptable'))
 131:         {
 132:             $event->getDispatcher()->addListener(
 133:                 sprintf('%s[%s]', PopulateEnvironmentEvent::NAME, $container->getName()),
 134:                 function (PopulateEnvironmentEvent $event) {
 135:                     $environment      = $event->getEnvironment();
 136:                     $definition       = $environment->getDataDefinition();
 137:                     $parentName       = $definition->getBasicDefinition()->getParentDataProvider();
 138:                     $factory          = DcGeneralFactory::deriveEmptyFromEnvironment($environment)->setContainerName($parentName);
 139:                     $parentDefinition = $factory->createContainer();
 140: 
 141:                     $environment->setParentDataDefinition($parentDefinition);
 142:                 }
 143:             );
 144:         }
 145:     }
 146: 
 147:     /**
 148:      * Parse the basic configuration and populate the definition.
 149:      *
 150:      * @param ContainerInterface       $container  The container where the data shall be stored.
 151:      *
 152:      * @param EventDispatcherInterface $dispatcher The event dispatcher in use.
 153:      *
 154:      * @return void
 155:      */
 156:     protected function parseCallbacks(ContainerInterface $container, EventDispatcherInterface $dispatcher)
 157:     {
 158:         if (isset($GLOBALS['objDcGeneral']) && is_array($callbacks = $this->getFromDca('config/onload_callback')))
 159:         {
 160:             foreach ($callbacks as $callback)
 161:             {
 162:                 $dispatcher->addListener(
 163:                     sprintf('%s[%s]', CreateDcGeneralEvent::NAME, $container->getName()),
 164:                     new ContainerOnLoadCallbackListener($callback, $GLOBALS['objDcGeneral'])
 165:                 );
 166:             }
 167:         }
 168: 
 169:         if (isset($GLOBALS['objDcGeneral']) && is_array($callbacks = $this->getFromDca('config/onsubmit_callback')))
 170:         {
 171:             foreach ($callbacks as $callback)
 172:             {
 173:                 $dispatcher->addListener(
 174:                     sprintf('%s[%s]', PostPersistModelEvent::NAME, $container->getName()),
 175:                     new ContainerOnSubmitCallbackListener($callback, $GLOBALS['objDcGeneral'])
 176:                 );
 177:             }
 178:         }
 179: 
 180:         if (isset($GLOBALS['objDcGeneral']) && is_array($callbacks = $this->getFromDca('config/ondelete_callback')))
 181:         {
 182:             foreach ($callbacks as $callback)
 183:             {
 184:                 $dispatcher->addListener(
 185:                     sprintf('%s[%s]', PostDeleteModelEvent::NAME, $container->getName()),
 186:                     new ContainerOnDeleteCallbackListener($callback, $GLOBALS['objDcGeneral'])
 187:                 );
 188:             }
 189:         }
 190: 
 191:         if (isset($GLOBALS['objDcGeneral']) && is_array($callbacks = $this->getFromDca('config/oncut_callback')))
 192:         {
 193:             foreach ($callbacks as $callback)
 194:             {
 195:                 $dispatcher->addListener(
 196:                     sprintf('%s[%s]', PostPasteModelEvent::NAME, $container->getName()),
 197:                     new ContainerOnCutCallbackListener($callback, $GLOBALS['objDcGeneral'])
 198:                 );
 199:             }
 200:         }
 201: 
 202:         if (isset($GLOBALS['objDcGeneral']) && is_array($callbacks = $this->getFromDca('config/oncopy_callback')))
 203:         {
 204:             foreach ($callbacks as $callback)
 205:             {
 206:                 $dispatcher->addListener(
 207:                     sprintf('%s[%s]', PostDuplicateModelEvent::NAME, $container->getName()),
 208:                     new ContainerOnCopyCallbackListener($callback, $GLOBALS['objDcGeneral'])
 209:                 );
 210:             }
 211:         }
 212: 
 213:         if (isset($GLOBALS['objDcGeneral']) && $callback = $this->getFromDca('list/sorting/header_callback'))
 214:         {
 215:             $dispatcher->addListener(
 216:                 sprintf('%s[%s]', GetParentHeaderEvent::NAME, $container->getName()),
 217:                 new ContainerHeaderCallbackListener($callback, $GLOBALS['objDcGeneral'])
 218:             );
 219:         }
 220: 
 221:         if (isset($GLOBALS['objDcGeneral']) && $callback = $this->getFromDca('list/sorting/paste_button_callback'))
 222:         {
 223:             $dispatcher->addListener(
 224:                 sprintf('%s[%s]', GetPasteRootButtonEvent::NAME, $container->getName()),
 225:                 new ContainerPasteRootButtonCallbackListener($callback, $GLOBALS['objDcGeneral'])
 226:             );
 227:             $dispatcher->addListener(
 228:                 sprintf('%s[%s]', GetPasteButtonEvent::NAME, $container->getName()),
 229:                 new ContainerPasteButtonCallbackListener($callback, $GLOBALS['objDcGeneral'])
 230:             );
 231:         }
 232: 
 233:         if (isset($GLOBALS['objDcGeneral']) && $callback = $this->getFromDca('list/sorting/child_record_callback'))
 234:         {
 235:             $dispatcher->addListener(
 236:                 sprintf('%s[%s]', ParentViewChildRecordEvent::NAME, $container->getName()),
 237:                 new ModelChildRecordCallbackListener($callback)
 238:             );
 239:         }
 240: 
 241:         if (isset($GLOBALS['objDcGeneral']) && $callback = $this->getFromDca('list/label/group_callback'))
 242:         {
 243:             $dispatcher->addListener(
 244:                 sprintf('%s[%s]', GetGroupHeaderEvent::NAME, $container->getName()),
 245:                 new ModelGroupCallbackListener($callback)
 246:             );
 247:         }
 248: 
 249:         if (isset($GLOBALS['objDcGeneral']) && $callback = $this->getFromDca('list/label/label_callback'))
 250:         {
 251:             $dispatcher->addListener(
 252:                 sprintf('%s[%s]', ModelToLabelEvent::NAME, $container->getName()),
 253:                 new ModelLabelCallbackListener($callback, $GLOBALS['objDcGeneral'])
 254:             );
 255:         }
 256: 
 257:         if (isset($GLOBALS['objDcGeneral']))
 258:         {
 259:             if (is_array($operations = $this->getFromDca('global_operations')))
 260:             {
 261:                 foreach ($operations as $operationName => $operationInfo)
 262:                 {
 263:                     if (isset($operationInfo['button_callback']))
 264:                     {
 265:                         $callback = $operationInfo['button_callback'];
 266:                         $dispatcher->addListener(
 267:                             sprintf('%s[%s][%s]', GetGlobalButtonEvent::NAME, $container->getName(), $operationName),
 268:                             new ContainerGlobalButtonCallbackListener($callback)
 269:                         );
 270:                     }
 271:                 }
 272:             }
 273:         }
 274: 
 275:         if (isset($GLOBALS['objDcGeneral']))
 276:         {
 277:             if (is_array($operations = $this->getFromDca('operations')))
 278:             {
 279:                 foreach ($operations as $operationName => $operationInfo)
 280:                 {
 281:                     if (isset($operationInfo['button_callback']))
 282:                     {
 283:                         $callback = $operationInfo['button_callback'];
 284:                         $dispatcher->addListener(
 285:                             sprintf('%s[%s][%s]', GetOperationButtonEvent::NAME, $container->getName(), $operationName),
 286:                             new ModelOperationButtonCallbackListener($callback)
 287:                         );
 288:                     }
 289:                 }
 290:             }
 291:         }
 292: 
 293:         if (isset($GLOBALS['objDcGeneral']))
 294:         {
 295:             foreach ($this->getFromDca('fields') as $propName => $propInfo)
 296:             {
 297:                 if (isset($propInfo['load_callback']))
 298:                 {
 299:                     foreach ($propInfo['load_callback'] as $callback)
 300:                     {
 301:                         $dispatcher->addListener(
 302:                             DecodePropertyValueForWidgetEvent::NAME . sprintf('[%s][%s]', $container->getName(), $propName),
 303:                             new PropertyOnLoadCallbackListener($callback, $GLOBALS['objDcGeneral'])
 304:                         );
 305:                     }
 306:                 }
 307: 
 308:                 if (isset($propInfo['save_callback']))
 309:                 {
 310:                     foreach ($propInfo['save_callback'] as $callback)
 311:                     {
 312:                         $dispatcher->addListener(
 313:                             EncodePropertyValueFromWidgetEvent::NAME . sprintf('[%s][%s]', $container->getName(), $propName),
 314:                             new PropertyOnSaveCallbackListener($callback, $GLOBALS['objDcGeneral'])
 315:                         );
 316:                     }
 317:                 }
 318: 
 319:                 if (isset($propInfo['options_callback']))
 320:                 {
 321:                     $callback = $propInfo['options_callback'];
 322:                     $dispatcher->addListener(
 323:                         GetPropertyOptionsEvent::NAME . sprintf('[%s][%s]', $container->getName(), $propName),
 324:                         new ModelOptionsCallbackListener($callback, $GLOBALS['objDcGeneral'])
 325:                     );
 326:                 }
 327: 
 328:                 if (isset($propInfo['input_field_callback']))
 329:                 {
 330:                     $callback = $propInfo['input_field_callback'];
 331:                     $dispatcher->addListener(
 332:                         BuildWidgetEvent::NAME . sprintf('[%s][%s]', $container->getName(), $propName),
 333:                         new PropertyInputFieldCallbackListener($callback, $GLOBALS['objDcGeneral'])
 334:                     );
 335:                 }
 336: 
 337:                 if (isset($propInfo['wizard']))
 338:                 {
 339:                     $callbacks = $propInfo['wizard'];
 340:                     foreach ($callbacks as $callback) {
 341:                         $dispatcher->addListener(
 342:                             ManipulateWidgetEvent::NAME . sprintf('[%s][%s]', $container->getName(), $propName),
 343:                             new PropertyInputFieldGetWizardCallbackListener($callback, $GLOBALS['objDcGeneral'])
 344:                         );
 345:                     }
 346:                 }
 347:             }
 348:         }
 349: 
 350:         if (isset($GLOBALS['objDcGeneral']) && $callback = $this->getFromDca('list/presentation/breadcrumb_callback'))
 351:         {
 352:             $dispatcher->addListener(
 353:                 sprintf('%s[%s]', GetBreadcrumbEvent::NAME, $container->getName()),
 354:                 new ContainerGetBreadcrumbCallbackListener($callback, $GLOBALS['objDcGeneral'])
 355:             );
 356:         }
 357:     }
 358: 
 359:     /**
 360:      * Parse the mode, flat, parented or hierarchical.
 361:      *
 362:      * @param BasicDefinitionInterface $config The basic definition of the data definition.
 363:      *
 364:      * @return void
 365:      */
 366:     protected function parseBasicMode(BasicDefinitionInterface $config)
 367:     {
 368:         switch ($this->getFromDca('list/sorting/mode'))
 369:         {
 370:             case 0:
 371:                 // Records are not sorted.
 372:             case 1:
 373:                 // Records are sorted by a fixed field.
 374:             case 2:
 375:                 // Records are sorted by a switchable field.
 376:             case 3:
 377:                 // Records are sorted by the parent table.
 378:                 $config->setMode(BasicDefinitionInterface::MODE_FLAT);
 379:                 break;
 380:             case 4:
 381:                 // Displays the child records of a parent record (see style sheets module).
 382:                 $config->setMode(BasicDefinitionInterface::MODE_PARENTEDLIST);
 383:                 break;
 384:             case 5:
 385:                 // Records are displayed as tree (see site structure).
 386:             case 6:
 387:                 // Displays the child records within a tree structure (see articles module).
 388:                 $config->setMode(BasicDefinitionInterface::MODE_HIERARCHICAL);
 389:                 break;
 390:             default:
 391:         }
 392:     }
 393: 
 394:     /**
 395:      * Parse the basic flags.
 396:      *
 397:      * @param BasicDefinitionInterface $config The basic definition of the data definition.
 398:      *
 399:      * @return void
 400:      */
 401:     protected function parseBasicFlags(BasicDefinitionInterface $config)
 402:     {
 403:         if (($switchToEdit = $this->getFromDca('config/switchToEdit')) !== null)
 404:         {
 405:             $config->setSwitchToEditEnabled((bool)$switchToEdit);
 406:         }
 407: 
 408:         if (($value = $this->getFromDca('config/closed')) !== null)
 409:         {
 410:             $config->setClosed((bool)$value);
 411:         }
 412: 
 413:         if (($value = $this->getFromDca('config/notEditable')) !== null)
 414:         {
 415:             $config->setEditable(!$value);
 416:         }
 417: 
 418:         if (($value = $this->getFromDca('config/notDeletable')) !== null)
 419:         {
 420:             $config->setDeletable(!$value);
 421:         }
 422: 
 423:         if (($value = $this->getFromDca('config/notCreatable')) !== null)
 424:         {
 425:             $config->setCreatable(!(bool)$value);
 426:         }
 427:     }
 428: 
 429:     /**
 430:      * Parse the basic configuration and populate the definition.
 431:      *
 432:      * @param ContainerInterface $container The container where the data shall be stored.
 433:      *
 434:      * @return void
 435:      */
 436:     protected function parseBasicDefinition(ContainerInterface $container)
 437:     {
 438:         // Parse data provider.
 439:         if ($container->hasBasicDefinition())
 440:         {
 441:             $config = $container->getBasicDefinition();
 442:         }
 443:         else
 444:         {
 445:             $config = new DefaultBasicDefinition();
 446:             $container->setBasicDefinition($config);
 447:         }
 448: 
 449:         $this->parseBasicMode($config);
 450:         $this->parseBasicFlags($config);
 451: 
 452:         if (($filters = $this->getFromDca('list/sorting/filter')) !== null)
 453:         {
 454:             if (is_array($filters) && !empty($filters))
 455:             {
 456:                 $myFilters = array();
 457:                 foreach ($filters as $filter)
 458:                 {
 459:                     // FIXME: this only takes array('name', 'value') into account. Add support for: array('name=?', 'value').
 460:                     $myFilters = array('operation' => '=', 'property' => $filter[0], 'value' => $filter[1]);
 461:                 }
 462:                 if ($config->hasAdditionalFilter())
 463:                 {
 464:                     $currentFilter = $config->getAdditionalFilter();
 465:                     $currentFilter = array_merge($currentFilter, $myFilters);
 466:                     $filter        = array(
 467:                         'operation' => 'AND',
 468:                         'children'  => array($currentFilter)
 469:                     );
 470:                 }
 471:                 else
 472:                 {
 473:                     $filter = $myFilters;
 474:                 }
 475: 
 476:                 $config->setAdditionalFilter($config->getDataProvider(), $filter);
 477:             }
 478:         }
 479:     }
 480: 
 481:     /**
 482:      * This method parses all data provider related information from Contao legacy data container arrays.
 483:      *
 484:      * @param ContainerInterface $container The container where the data shall be stored.
 485:      *
 486:      * @return void
 487:      */
 488:     protected function parseDataProvider(ContainerInterface $container)
 489:     {
 490:         if ($container->hasDataProviderDefinition())
 491:         {
 492:             $config = $container->getDataProviderDefinition();
 493:         }
 494:         else
 495:         {
 496:             $config = new DefaultDataProviderDefinition();
 497:             $container->setDataProviderDefinition($config);
 498:         }
 499: 
 500:         if (($parentTable = $this->getFromDca('config/ptable')) !== null)
 501:         {
 502:             // Check config if it already exists, if not, add it.
 503:             if (!$config->hasInformation($parentTable))
 504:             {
 505:                 $providerInformation = new ContaoDataProviderInformation();
 506:                 $providerInformation->setName($parentTable);
 507:                 $config->addInformation($providerInformation);
 508:             }
 509:             else
 510:             {
 511:                 $providerInformation = $config->getInformation($parentTable);
 512:             }
 513: 
 514:             if ($providerInformation instanceof ContaoDataProviderInformation)
 515:             {
 516:                 $initializationData = (array)$providerInformation->getInitializationData();
 517: 
 518:                 $providerInformation
 519:                     ->setTableName($parentTable)
 520:                     ->setInitializationData(array_merge(
 521:                         array(
 522:                             'source' => $parentTable
 523:                         ),
 524:                         $initializationData
 525:                     ));
 526: 
 527:                 $container->getBasicDefinition()->setRootDataProvider($parentTable);
 528:                 $container->getBasicDefinition()->setParentDataProvider($parentTable);
 529:             }
 530:         }
 531: 
 532:         // Check config if it already exists, if not, add it.
 533:         if (!$config->hasInformation($container->getName()))
 534:         {
 535:             $providerInformation = new ContaoDataProviderInformation();
 536:             $providerInformation->setName($container->getName());
 537:             $config->addInformation($providerInformation);
 538:         }
 539:         else
 540:         {
 541:             $providerInformation = $config->getInformation($container->getName());
 542:         }
 543: 
 544:         if ($providerInformation instanceof ContaoDataProviderInformation)
 545:         {
 546:             $initializationData = (array)$providerInformation->getInitializationData();
 547: 
 548:             $providerInformation
 549:                 ->setTableName($container->getName())
 550:                 ->setInitializationData(array_merge(
 551:                     array(
 552:                         'source' => $container->getName()
 553:                     ),
 554:                     $initializationData
 555:                 ))
 556:                 ->isVersioningEnabled((bool)$this->getFromDca('config/enableVersioning'));
 557: 
 558:             $container->getBasicDefinition()->setDataProvider($container->getName());
 559:         }
 560:     }
 561: 
 562:     /**
 563:      * This method parses the root entries definition.
 564:      *
 565:      * @param ContainerInterface $container The container where the data shall be stored.
 566:      *
 567:      * @return void
 568:      */
 569:     protected function parseRootEntries(ContainerInterface $container)
 570:     {
 571:         // FIXME: to be implemented.
 572:     }
 573: 
 574:     /**
 575:      * Determine the root provider name from the container.
 576:      *
 577:      * @param ContainerInterface $container The container from where the name shall be retrieved.
 578:      *
 579:      * @return string
 580:      *
 581:      * @throws DcGeneralRuntimeException If the root provider can not be determined.
 582:      */
 583:     protected function getRootProviderName(ContainerInterface $container)
 584:     {
 585:         $rootProvider = $container->getBasicDefinition()->getRootDataProvider();
 586: 
 587:         if (!$rootProvider)
 588:         {
 589:             throw new DcGeneralRuntimeException(
 590:                 'Root data provider name not specified in DCA but rootEntries section specified.'
 591:             );
 592:         }
 593: 
 594:         if (!$container->getDataProviderDefinition()->hasInformation($rootProvider))
 595:         {
 596:             throw new DcGeneralRuntimeException('Unknown root data provider but rootEntries section specified.');
 597:         }
 598: 
 599:         return $rootProvider;
 600:     }
 601: 
 602:     /**
 603:      * This method parses the parent-child conditions.
 604:      *
 605:      * @param ContainerInterface $container The container where the data shall be stored.
 606:      *
 607:      * @return void
 608:      */
 609:     protected function parseParentChildConditions(ContainerInterface $container)
 610:     {
 611:         if ($container->hasDefinition(ModelRelationshipDefinitionInterface::NAME))
 612:         {
 613:             $definition = $container->getDefinition(ModelRelationshipDefinitionInterface::NAME);
 614:         }
 615:         else
 616:         {
 617:             $definition = new DefaultModelRelationshipDefinition();
 618:         }
 619: 
 620:         // If ptable defined and no root setter we need to add (Contao default id=>pid mapping).
 621:         if (($value = $this->getFromDca('config/ptable')) !== null)
 622:         {
 623:             $rootProvider = $this->getRootProviderName($container);
 624: 
 625:             if (($relationship = $definition->getRootCondition()) === null)
 626:             {
 627:                 $relationship = new RootCondition();
 628:                 $relationship
 629:                     ->setSourceName($rootProvider);
 630:                 $definition->setRootCondition($relationship);
 631:             }
 632:             if (!$relationship->getSetters())
 633:             {
 634:                 $relationship
 635:                     ->setSetters(array(array('property' => 'pid', 'value' => '0')));
 636:             }
 637: 
 638:             $container->setDefinition(ModelRelationshipDefinitionInterface::NAME, $definition);
 639:         }
 640: 
 641:         // If root id defined, add condition to root filter for id=?.
 642:         if ($value = $this->getFromDca('list/sorting/root'))
 643:         {
 644:             $rootProvider = $this->getRootProviderName($container);
 645: 
 646:             $myFilter = array('operation' => 'IN', 'property' => 'id', 'value' => $value);
 647: 
 648:             if (($relationship = $definition->getRootCondition()) === null)
 649:             {
 650:                 $relationship = new RootCondition();
 651:                 $filter       = $myFilter;
 652:             }
 653:             else
 654:             {
 655:                 $filter = $relationship->getFilterArray();
 656:                 if ($filter)
 657:                 {
 658:                     $filter = array(
 659:                         'operation' => 'AND',
 660:                         'children' => array($filter)
 661:                     );
 662: 
 663:                     $filter['children'][] = $myFilter;
 664:                 }
 665:                 else{
 666:                     $filter = $myFilter;
 667:                 }
 668:             }
 669: 
 670:             $relationship
 671:                 ->setSourceName($rootProvider)
 672:                 ->setFilterArray(array($filter));
 673:             $definition->setRootCondition($relationship);
 674: 
 675:             $container->setDefinition(ModelRelationshipDefinitionInterface::NAME, $definition);
 676:         }
 677:     }
 678: 
 679:     /**
 680:      * Parse and build the backend view definition for the old Contao2 backend view.
 681:      *
 682:      * @param ContainerInterface $container The container where the data shall be stored.
 683:      *
 684:      * @return void
 685:      *
 686:      * @throws DcGeneralInvalidArgumentException If the stored backend view definition does not implement the correct
 687:      *                                           interface.
 688:      */
 689:     protected function parseBackendView(ContainerInterface $container)
 690:     {
 691:         if ($container->hasDefinition(Contao2BackendViewDefinitionInterface::NAME))
 692:         {
 693:             $view = $container->getDefinition(Contao2BackendViewDefinitionInterface::NAME);
 694:         }
 695:         else
 696:         {
 697:             $view = new Contao2BackendViewDefinition();
 698:             $container->setDefinition(Contao2BackendViewDefinitionInterface::NAME, $view);
 699:         }
 700: 
 701:         if (!$view instanceof Contao2BackendViewDefinitionInterface)
 702:         {
 703:             throw new DcGeneralInvalidArgumentException(
 704:                 'Configured BackendViewDefinition does not implement Contao2BackendViewDefinitionInterface.'
 705:             );
 706:         }
 707: 
 708:         $this->parseListing($container, $view);
 709:         $this->parsePanel($view);
 710:         $this->parseGlobalOperations($view);
 711:         $this->parseModelOperations($view);
 712:     }
 713: 
 714:     /**
 715:      * Parse the listing configuration.
 716:      *
 717:      * @param ContainerInterface                    $container The container where the data shall be stored.
 718:      *
 719:      * @param Contao2BackendViewDefinitionInterface $view      The view information for the backend view.
 720:      *
 721:      * @return void
 722:      */
 723:     protected function parseListing(ContainerInterface $container, Contao2BackendViewDefinitionInterface $view)
 724:     {
 725:         $listing = $view->getListingConfig();
 726:         $listDca = $this->getFromDca('list');
 727: 
 728:         // Cancel if no list configuration found.
 729:         if (!$listDca)
 730:         {
 731:             return;
 732:         }
 733: 
 734:         $this->parseListSorting($listing, $listDca);
 735:         $this->parseListLabel($container, $listing, $listDca);
 736:     }
 737: 
 738:     /**
 739:      * Parse the sorting part of listing configuration.
 740:      *
 741:      * NOTE: this method currently does NOT support the custom SQL sorting information as supported by DC_Table in
 742:      * Contao.
 743:      *
 744:      * @param ListingConfigInterface $listing The listing configuration definition to populate.
 745:      *
 746:      * @param array                  $listDca The DCA part containing the information to use.
 747:      *
 748:      * @return void
 749:      *
 750:      * @throws DcGeneralRuntimeException In case unsupported values are encountered.
 751:      */
 752:     protected function parseListSorting(ListingConfigInterface $listing, array $listDca)
 753:     {
 754:         $sortingDca = isset($listDca['sorting']) ? $listDca['sorting'] : array();
 755: 
 756:         if (isset($sortingDca['flag']))
 757:         {
 758:             $this->evalFlag($listing, $sortingDca['flag']);
 759:         }
 760: 
 761:         if (isset($sortingDca['fields']))
 762:         {
 763:             $fields = array();
 764: 
 765:             foreach ($sortingDca['fields'] as $field)
 766:             {
 767:                 if (preg_match('~^(\w+)(?: (ASC|DESC))?$~', $field, $matches))
 768:                 {
 769:                     $fields[$matches[1]] = isset($matches[2]) ? $matches[2] : 'ASC';
 770:                 }
 771:                 else
 772:                 {
 773:                     throw new DcGeneralRuntimeException('Custom SQL in sorting fields are currently unsupported');
 774:                 }
 775:             }
 776: 
 777:             $listing->setDefaultSortingFields($fields);
 778:         }
 779: 
 780:         if (isset($sortingDca['headerFields']))
 781:         {
 782:             $listing->setHeaderPropertyNames((array)$sortingDca['headerFields']);
 783:         }
 784: 
 785:         if (isset($sortingDca['icon']))
 786:         {
 787:             $listing->setRootIcon($sortingDca['icon']);
 788:         }
 789: 
 790:         if (isset($sortingDca['disableGrouping']) && $sortingDca['disableGrouping'])
 791:         {
 792:             $listing->setGroupingMode(ListingConfigInterface::GROUP_NONE);
 793:         }
 794: 
 795:         if (isset($sortingDca['child_record_class']))
 796:         {
 797:             $listing->setItemCssClass($sortingDca['child_record_class']);
 798:         }
 799:     }
 800: 
 801:     /**
 802:      * Parse the sorting part of listing configuration.
 803:      *
 804:      * @param ContainerInterface     $container The container where the data shall be stored.
 805:      *
 806:      * @param ListingConfigInterface $listing   The listing configuration definition to populate.
 807:      *
 808:      * @param array                  $listDca   The DCA part containing the information to use.
 809:      *
 810:      * @return void
 811:      */
 812:     protected function parseListLabel(ContainerInterface $container, ListingConfigInterface $listing, array $listDca)
 813:     {
 814:         $labelDca   = isset($listDca['label']) ? $listDca['label'] : array();
 815:         $formatter  = new DefaultModelFormatterConfig();
 816:         $configured = false;
 817: 
 818:         if (isset($labelDca['fields']))
 819:         {
 820:             $formatter->setPropertyNames($labelDca['fields']);
 821:             $configured = true;
 822:         }
 823: 
 824:         if (isset($labelDca['format']))
 825:         {
 826:             $formatter->setFormat($labelDca['format']);
 827:             $configured = true;
 828:         }
 829: 
 830:         if (isset($labelDca['maxCharacters']))
 831:         {
 832:             $formatter->setMaxLength($labelDca['maxCharacters']);
 833:             $configured = true;
 834:         }
 835: 
 836:         if ($configured)
 837:         {
 838:             $listing->setLabelFormatter($container->getBasicDefinition()->getDataProvider(), $formatter);
 839:         }
 840: 
 841:         if (isset($labelDca['showColumns']))
 842:         {
 843:             $listing->setShowColumns($labelDca['showColumns']);
 844:         }
 845:     }
 846: 
 847:     /**
 848:      * Add filter elements to the panel.
 849:      *
 850:      * @param PanelRowInterface $row The row to which the element shall get added to.
 851:      *
 852:      * @return void
 853:      */
 854:     protected function parsePanelFilter(PanelRowInterface $row)
 855:     {
 856:         foreach ($this->getFromDca('fields') as $property => $value)
 857:         {
 858:             if (isset($value['filter']))
 859:             {
 860:                 $element = new DefaultFilterElementInformation();
 861:                 $element->setPropertyName($property);
 862:                 if (!$row->hasElement($element->getName()))
 863:                 {
 864:                     $row->addElement($element);
 865:                 }
 866:             }
 867:         }
 868:     }
 869: 
 870:     /**
 871:      * Add sort element to the panel.
 872:      *
 873:      * @param PanelRowInterface $row The row to which the element shall get added to.
 874:      *
 875:      * @return void
 876:      */
 877:     protected function parsePanelSort(PanelRowInterface $row)
 878:     {
 879:         if ($row->hasElement('sort'))
 880:         {
 881:             $element = $row->getElement('sort');
 882:         }
 883:         else
 884:         {
 885:             $element = new DefaultSortElementInformation();
 886:             $row->addElement($element);
 887:         }
 888: 
 889:         foreach ($this->getFromDca('fields') as $property => $value)
 890:         {
 891:             if (isset($value['sorting']))
 892:             {
 893:                 $element->addProperty($property, (int)$value['flag']);
 894:             }
 895:         }
 896:     }
 897: 
 898:     /**
 899:      * Add search element to the panel.
 900:      *
 901:      * @param PanelRowInterface $row The row to which the element shall get added to.
 902:      *
 903:      * @return void
 904:      */
 905:     protected function parsePanelSearch(PanelRowInterface $row)
 906:     {
 907:         if ($row->hasElement('search'))
 908:         {
 909:             $element = $row->getElement('search');
 910:         }
 911:         else
 912:         {
 913:             $element = new DefaultSearchElementInformation();
 914:         }
 915:         foreach ($this->getFromDca('fields') as $property => $value)
 916:         {
 917:             if (isset($value['search']))
 918:             {
 919:                 $element->addProperty($property);
 920:             }
 921:         }
 922:         if ($element->getPropertyNames() && !$row->hasElement('search'))
 923:         {
 924:             $row->addElement($element);
 925:         }
 926:     }
 927: 
 928:     /**
 929:      * Add  elements to the panel.
 930:      *
 931:      * @param PanelRowInterface $row The row to which the element shall get added to.
 932:      *
 933:      * @return void
 934:      */
 935:     protected function parsePanelLimit(PanelRowInterface $row)
 936:     {
 937:         if (!$row->hasElement('limit'))
 938:         {
 939:             $row->addElement(new DefaultLimitElementInformation());
 940:         }
 941:     }
 942: 
 943:     /**
 944:      * Add  elements to the panel.
 945:      *
 946:      * @param PanelRowInterface $row The row to which the element shall get added to.
 947:      *
 948:      * @return void
 949:      */
 950:     protected function parsePanelSubmit(PanelRowInterface $row)
 951:     {
 952:         if (!$row->hasElement('submit'))
 953:         {
 954:             $row->addElement(new DefaultSubmitElementInformation());
 955:         }
 956:     }
 957: 
 958:     /**
 959:      * Parse a single panel row.
 960:      *
 961:      * @param PanelRowInterface $row         The row to be populated.
 962:      *
 963:      * @param string            $elementList A comma separated list of elements to be stored in the row.
 964:      *
 965:      * @return void
 966:      */
 967:     protected function parsePanelRow(PanelRowInterface $row, $elementList)
 968:     {
 969:         foreach (explode(',', $elementList) as $element)
 970:         {
 971:             switch ($element)
 972:             {
 973:                 case 'filter':
 974:                     $this->parsePanelFilter($row);
 975:                     break;
 976: 
 977:                 case 'sort':
 978:                     $this->parsePanelSort($row);
 979:                     break;
 980: 
 981:                 case 'search':
 982:                     $this->parsePanelSearch($row);
 983:                     break;
 984: 
 985:                 case 'limit':
 986:                     $this->parsePanelLimit($row);
 987:                     break;
 988: 
 989:                 case 'submit':
 990:                     $this->parsePanelSubmit($row);
 991:                     break;
 992: 
 993:                 default:
 994:             }
 995:         }
 996:     }
 997: 
 998:     /**
 999:      * Parse the defined palettes and populate the definition.
1000:      *
1001:      * @param Contao2BackendViewDefinitionInterface $view The listing configuration definition to populate.
1002:      *
1003:      * @return void
1004:      */
1005:     protected function parsePanel(Contao2BackendViewDefinitionInterface $view)
1006:     {
1007:         $layout = $view->getPanelLayout();
1008:         $rows   = $layout->getRows();
1009: 
1010:         foreach (explode(';', (string)$this->getFromDca('list/sorting/panelLayout')) as $rowNo => $elementRow)
1011:         {
1012:             if ($rows->getRowCount() < ($rowNo + 1))
1013:             {
1014:                 $row = $rows->addRow();
1015:             }
1016:             else
1017:             {
1018:                 $row = $rows->getRow($rowNo);
1019:             }
1020: 
1021:             $this->parsePanelRow($row, $elementRow);
1022: 
1023:             if ($row->getCount() == 0)
1024:             {
1025:                 $rows->deleteRow($rowNo);
1026:             }
1027:         }
1028: 
1029:         $hasSubmit = false;
1030:         foreach ($rows as $row)
1031:         {
1032:             foreach ($row as $element)
1033:             {
1034:                 if ($element instanceof SubmitElementInformationInterface)
1035:                 {
1036:                     $hasSubmit = true;
1037:                     break;
1038:                 }
1039: 
1040:                 if ($hasSubmit)
1041:                 {
1042:                     break;
1043:                 }
1044:             }
1045:         }
1046: 
1047:         if (!$hasSubmit && $rows->getRowCount())
1048:         {
1049:             $row = $rows->getRow($rows->getRowCount() - 1);
1050:             $row->addElement(new DefaultSubmitElementInformation(), 0);
1051:         }
1052:     }
1053: 
1054:     /**
1055:      * Parse the defined container scoped operations and populate the definition.
1056:      *
1057:      * @param Contao2BackendViewDefinitionInterface $view The backend view configuration definition to populate.
1058:      *
1059:      * @return void
1060:      */
1061:     protected function parseGlobalOperations(Contao2BackendViewDefinitionInterface $view)
1062:     {
1063:         $operationsDca = $this->getFromDca('list/global_operations');
1064: 
1065:         if (!is_array($operationsDca))
1066:         {
1067:             return;
1068:         }
1069: 
1070:         $collection = $view->getGlobalCommands();
1071: 
1072:         foreach ($operationsDca as $operationName => $operationDca)
1073:         {
1074:             $command = $this->createCommand($operationName, $operationsDca[$operationName]);
1075:             $collection->addCommand($command);
1076:         }
1077:     }
1078: 
1079:     /**
1080:      * Parse the defined model scoped operations and populate the definition.
1081:      *
1082:      * @param Contao2BackendViewDefinitionInterface $view The backend view configuration definition to populate.
1083:      *
1084:      * @return void
1085:      */
1086:     protected function parseModelOperations(Contao2BackendViewDefinitionInterface $view)
1087:     {
1088:         $operationsDca = $this->getFromDca('list/operations');
1089: 
1090:         if (!is_array($operationsDca))
1091:         {
1092:             return;
1093:         }
1094: 
1095:         $collection = $view->getModelCommands();
1096: 
1097:         foreach ($operationsDca as $operationName => $operationDca)
1098:         {
1099:             $command = $this->createCommand($operationName, $operationsDca[$operationName]);
1100:             $collection->addCommand($command);
1101:         }
1102:     }
1103: 
1104:     /**
1105:      * Parse the defined palettes and populate the definition.
1106:      *
1107:      * @param ContainerInterface $container The container where the data shall be stored.
1108:      *
1109:      * @return void
1110:      */
1111:     protected function parsePalettes(ContainerInterface $container)
1112:     {
1113:         $palettesDefinitionArray    = $this->getFromDca('palettes');
1114:         $subPalettesDefinitionArray = $this->getFromDca('subpalettes');
1115: 
1116:         // Skip while there is no legacy palette definition.
1117:         if (!is_array($palettesDefinitionArray))
1118:         {
1119:             return;
1120:         }
1121: 
1122:         // Ignore non-legacy sub palette definition.
1123:         if (!is_array($subPalettesDefinitionArray))
1124:         {
1125:             $subPalettesDefinitionArray = array();
1126:         }
1127: 
1128:         if ($container->hasDefinition(PalettesDefinitionInterface::NAME))
1129:         {
1130:             $palettesDefinition = $container->getDefinition(PalettesDefinitionInterface::NAME);
1131:         }
1132:         else
1133:         {
1134:             $palettesDefinition = new DefaultPalettesDefinition();
1135:             $container->setDefinition(PalettesDefinitionInterface::NAME, $palettesDefinition);
1136:         }
1137: 
1138:         $palettesParser = new LegacyPalettesParser();
1139:         $palettesParser->parse(
1140:             $palettesDefinitionArray,
1141:             $subPalettesDefinitionArray,
1142:             $palettesDefinition
1143:         );
1144:     }
1145: 
1146:     /**
1147:      * Parse the label of a single property.
1148:      *
1149:      * @param PropertyInterface $property The property to parse the label for.
1150:      *
1151:      * @param string|array      $label    The label value.
1152:      *
1153:      * @return void
1154:      */
1155:     protected function parseSinglePropertyLabel(PropertyInterface $property, $label)
1156:     {
1157:         if (!$property->getLabel())
1158:         {
1159:             if (is_array($label))
1160:             {
1161:                 $lang        = $label;
1162:                 $label       = reset($lang);
1163:                 $description = next($lang);
1164: 
1165:                 $property->setDescription($description);
1166:             }
1167: 
1168:             $property->setLabel($label);
1169:         }
1170:     }
1171: 
1172:     /**
1173:      * Parse a single property.
1174:      *
1175:      * @param PropertyInterface $property The property to parse.
1176:      *
1177:      * @param array             $propInfo The property information.
1178:      *
1179:      * @return void
1180:      */
1181:     // @codingStandardsIgnoreStart - cyclomatic complexity can not be lowered any further.
1182:     protected function parseSingleProperty(PropertyInterface $property, array $propInfo)
1183:     // @codingStandardsIgnoreEnd
1184:     {
1185:         foreach ($propInfo as $key => $value)
1186:         {
1187:             switch ($key)
1188:             {
1189:                 case 'label':
1190:                     $this->parseSinglePropertyLabel($property, $value);
1191:                     break;
1192: 
1193:                 case 'description':
1194:                     if (!$property->getDescription())
1195:                     {
1196:                         $property->setDescription($value);
1197:                     }
1198:                     break;
1199: 
1200:                 case 'default':
1201:                     if (!$property->getDefaultValue())
1202:                     {
1203:                         $property->setDefaultValue($value);
1204:                     }
1205:                     break;
1206: 
1207:                 case 'exclude':
1208:                     $property->setExcluded((bool)$value);
1209:                     break;
1210: 
1211:                 case 'search':
1212:                     $property->setSearchable((bool)$value);
1213:                     break;
1214: 
1215:                 case 'sorting':
1216:                     $property->setSortable((bool)$value);
1217:                     break;
1218: 
1219:                 case 'filter':
1220:                     $property->setFilterable((bool)$value);
1221:                     break;
1222: 
1223:                 case 'flag':
1224:                     $this->evalFlag($property, $value);
1225:                     break;
1226: 
1227:                 case 'length':
1228:                     $property->setGroupingLength($value);
1229:                     break;
1230: 
1231:                 case 'inputType':
1232:                     $property->setWidgetType($value);
1233:                     break;
1234: 
1235:                 case 'options':
1236:                     $property->setOptions($value);
1237:                     break;
1238: 
1239:                 case 'explanation':
1240:                     $property->setExplanation($value);
1241:                     break;
1242: 
1243:                 case 'eval':
1244:                     $property->setExtra($value);
1245:                     break;
1246: 
1247:                 default:
1248:             }
1249:         }
1250:     }
1251: 
1252:     /**
1253:      * Parse the defined properties and populate the definition.
1254:      *
1255:      * @param ContainerInterface $container The container where the data shall be stored.
1256:      *
1257:      * @return void
1258:      */
1259:     protected function parseProperties(ContainerInterface $container)
1260:     {
1261:         if ($container->hasPropertiesDefinition())
1262:         {
1263:             $definition = $container->getPropertiesDefinition();
1264:         }
1265:         else
1266:         {
1267:             $definition = new DefaultPropertiesDefinition();
1268:             $container->setPropertiesDefinition($definition);
1269:         }
1270: 
1271:         foreach ($this->getFromDca('fields') as $propName => $propInfo)
1272:         {
1273:             if ($definition->hasProperty($propName))
1274:             {
1275:                 $property = $definition->getProperty($propName);
1276:             }
1277:             else
1278:             {
1279:                 $property = new DefaultProperty($propName);
1280:                 $definition->addProperty($property);
1281:             }
1282: 
1283:             $this->parseSingleProperty($property, $propInfo);
1284:         }
1285:     }
1286: 
1287:     /**
1288:      * Create the correct command instance for the given information.
1289:      *
1290:      * @param string $commandName The name of the command to create.
1291:      *
1292:      * @param array  $commandDca  The Dca information of the command.
1293:      *
1294:      * @return Command|CutCommand
1295:      */
1296:     protected function createCommandInstance($commandName, array $commandDca)
1297:     {
1298:         switch ($commandName)
1299:         {
1300:             case 'cut':
1301:                 return new CutCommand();
1302:             default:
1303:                 return new Command();
1304:         }
1305:     }
1306: 
1307:     /**
1308:      * Create a command from dca.
1309:      *
1310:      * @param string $commandName The name of the command to parse.
1311:      *
1312:      * @param array  $commandDca  The chunk from the DCA containing the command specification.
1313:      *
1314:      * @return CommandInterface
1315:      */
1316:     protected function createCommand($commandName, array $commandDca)
1317:     {
1318: 
1319:         $command = $this->createCommandInstance($commandName, $commandDca);
1320:         $command->setName($commandName);
1321: 
1322:         $parameters = $command->getParameters();
1323: 
1324:         if (isset($commandDca['href']))
1325:         {
1326:             parse_str($commandDca['href'], $queryParameters);
1327:             foreach ($queryParameters as $name => $value)
1328:             {
1329:                 $parameters[$name] = $value;
1330:             }
1331:             unset($commandDca['href']);
1332:         }
1333: 
1334:         if (isset($commandDca['parameters']))
1335:         {
1336:             foreach ($commandDca['parameters'] as $name => $value)
1337:             {
1338:                 $parameters[$name] = $value;
1339:             }
1340:             unset($commandDca['parameters']);
1341:         }
1342: 
1343:         if (isset($commandDca['label']))
1344:         {
1345:             $lang = $commandDca['label'];
1346: 
1347:             if (is_array($lang))
1348:             {
1349:                 $label       = reset($lang);
1350:                 $description = next($lang);
1351: 
1352:                 $command->setDescription($description);
1353:             }
1354:             else {
1355:                 $label = $lang;
1356:             }
1357: 
1358:             $command->setLabel($label);
1359: 
1360:             unset($commandDca['label']);
1361:         }
1362: 
1363:         if (isset($commandDca['description']))
1364:         {
1365:             $command->setDescription($commandDca['description']);
1366: 
1367:             unset($commandDca['description']);
1368:         }
1369: 
1370:         // Callback is transformed into event in parseCallbacks().
1371:         if (isset($commandDca['button_callback']))
1372:         {
1373:             unset($commandDca['button_callback']);
1374:         }
1375: 
1376:         if (count($commandDca))
1377:         {
1378:             $extra = $command->getExtra();
1379: 
1380:             foreach ($commandDca as $name => $value)
1381:             {
1382:                 $extra[$name] = $value;
1383:             }
1384:         }
1385: 
1386:         return $command;
1387:     }
1388: 
1389:     /**
1390:      * Evaluate the contao 2 sorting flag into sorting mode.
1391:      *
1392:      * @param ListingConfigInterface|PropertyInterface $config The property to evaluate the flag for.
1393:      *
1394:      * @param int                                      $flag   The flag to be evaluated.
1395:      *
1396:      * @return void
1397:      */
1398:     protected function evalFlagSorting($config, $flag)
1399:     {
1400:         if (($flag < 0) || ($flag > 12))
1401:         {
1402:             return;
1403:         }
1404: 
1405:         if (($flag % 2) == 1)
1406:         {
1407:             $config->setSortingMode(ListingConfigInterface::SORT_ASC);
1408:         }
1409:         else
1410:         {
1411:             $config->setSortingMode(ListingConfigInterface::SORT_DESC);
1412:         }
1413:     }
1414: 
1415:     /**
1416:      * Evaluate the contao 2 sorting flag into grouping mode.
1417:      *
1418:      * @param ListingConfigInterface|PropertyInterface $config The property to evaluate the flag for.
1419:      *
1420:      * @param int                                      $flag   The flag to be evaluated.
1421:      *
1422:      * @return void
1423:      */
1424:     protected function evalFlagGrouping($config, $flag)
1425:     {
1426:         if (($flag < 0) || ($flag > 12))
1427:         {
1428:             return;
1429:         }
1430: 
1431:         if ($flag <= 4)
1432:         {
1433:             $config->setGroupingMode(ListingConfigInterface::GROUP_CHAR);
1434:         }
1435:         elseif ($flag <= 6)
1436:         {
1437:             $config->setGroupingMode(ListingConfigInterface::GROUP_DAY);
1438:         }
1439:         elseif ($flag <= 8)
1440:         {
1441:             $config->setGroupingMode(ListingConfigInterface::GROUP_MONTH);
1442:         }
1443:         elseif ($flag <= 10)
1444:         {
1445:             $config->setGroupingMode(ListingConfigInterface::GROUP_YEAR);
1446:         }
1447:         else
1448:         {
1449:             $config->setGroupingMode(ListingConfigInterface::GROUP_NONE);
1450:         }
1451:     }
1452: 
1453:     /**
1454:      * Evaluate the contao 2 sorting flag into grouping length.
1455:      *
1456:      * @param ListingConfigInterface|PropertyInterface $config The property to evaluate the flag for.
1457:      *
1458:      * @param int                                      $flag   The flag to be evaluated.
1459:      *
1460:      * @return void
1461:      */
1462:     protected function evalFlagGroupingLength($config, $flag)
1463:     {
1464:         if (($flag == 1) || ($flag == 2))
1465:         {
1466:             $config->setGroupingLength(1);
1467:         }
1468:         elseif(($flag == 3) || ($flag == 4))
1469:         {
1470:             $config->setGroupingLength(2);
1471:         }
1472:     }
1473: 
1474:     /**
1475:      * Evaluate the contao 2 sorting flag into sorting mode, grouping mode and grouping length.
1476:      *
1477:      * @param ListingConfigInterface|PropertyInterface $config The property to evaluate the flag for.
1478:      *
1479:      * @param int                                      $flag   The flag to be evaluated.
1480:      *
1481:      * @return void
1482:      */
1483:     protected function evalFlag($config, $flag)
1484:     {
1485:         $this->evalFlagSorting($config, $flag);
1486:         $this->evalFlagGrouping($config, $flag);
1487:         $this->evalFlagGroupingLength($config, $flag);
1488:     }
1489: }
1490: 
contao-community-alliance/dc-general API documentation generated by ApiGen 2.8.0