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

  • BaseView
  • ContaoBackendViewTemplate
  • ContaoWidgetManager
  • ListView
  • ParentView
  • TreeView

Interfaces

  • BackendViewInterface
  • 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\View\Contao2BackendView;
 14: 
 15: use ContaoCommunityAlliance\Contao\Bindings\ContaoEvents;
 16: use ContaoCommunityAlliance\Contao\Bindings\Events\Backend\AddToUrlEvent;
 17: use ContaoCommunityAlliance\Contao\Bindings\Events\Controller\LoadDataContainerEvent;
 18: use ContaoCommunityAlliance\Contao\Bindings\Events\Controller\RedirectEvent;
 19: use ContaoCommunityAlliance\Contao\Bindings\Events\Image\GenerateHtmlEvent;
 20: use ContaoCommunityAlliance\Contao\Bindings\Events\System\LoadLanguageFileEvent;
 21: use ContaoCommunityAlliance\Contao\Bindings\Events\System\LogEvent;
 22: use DcGeneral\Contao\BackendBindings;
 23: use DcGeneral\Data\CollectionInterface;
 24: use DcGeneral\Data\DCGE;
 25: use DcGeneral\Contao\View\Contao2BackendView\Event\GetParentHeaderEvent;
 26: use DcGeneral\Contao\View\Contao2BackendView\Event\ParentViewChildRecordEvent;
 27: use DcGeneral\Data\ModelInterface;
 28: use DcGeneral\DataDefinition\Definition\View\ListingConfigInterface;
 29: use DcGeneral\Exception\DcGeneralRuntimeException;
 30: 
 31: /**
 32:  * Class ParentView.
 33:  *
 34:  * Implementation of the parent view.
 35:  *
 36:  * @package DcGeneral\Contao\View\Contao2BackendView
 37:  */
 38: class ParentView extends BaseView
 39: {
 40:     /**
 41:      * Load the collection of child items and the parent item for the currently selected parent item.
 42:      *
 43:      * Consumes input parameter "id".
 44:      *
 45:      * @return CollectionInterface
 46:      */
 47:     public function loadCollection()
 48:     {
 49:         $environment = $this->getEnvironment();
 50: 
 51:         $objCurrentDataProvider = $environment->getDataProvider();
 52: 
 53:         $objChildConfig = $environment->getController()->getBaseConfig();
 54: 
 55:         if (!$objChildConfig->getSorting())
 56:         {
 57:             $objChildConfig->setSorting($this->getViewSection()->getListingConfig()->getDefaultSortingFields());
 58:         }
 59: 
 60:         $this->getPanel()->initialize($objChildConfig);
 61: 
 62:         $objChildCollection = $objCurrentDataProvider->fetchAll($objChildConfig);
 63: 
 64:         return $objChildCollection;
 65:     }
 66: 
 67:     /**
 68:      * Load the parent model for the current list.
 69:      *
 70:      * @return \DcGeneral\Data\ModelInterface
 71:      *
 72:      * @throws DcGeneralRuntimeException If the parent view requirements are not fulfilled - either no data provider
 73:      *                                   defined or no parent model id given.
 74:      */
 75:     protected function loadParentModel()
 76:     {
 77:         $environment = $this->getEnvironment();
 78: 
 79:         if (!($parentId = $environment->getInputProvider()->getParameter('pid')))
 80:         {
 81:             throw new DcGeneralRuntimeException(
 82:                 'ParentView needs a proper parent id defined, somehow none is defined?',
 83:                 1
 84:             );
 85:         }
 86: 
 87:         if (!($objParentProvider =
 88:             $environment->getDataProvider(
 89:                 $environment->getDataDefinition()->getBasicDefinition()->getParentDataProvider()
 90:             )
 91:         ))
 92:         {
 93:             throw new DcGeneralRuntimeException(
 94:                 'ParentView needs a proper parent data provider defined, somehow none is defined?',
 95:                 1
 96:             );
 97:         }
 98: 
 99:         $objParentItem = $objParentProvider->fetch($objParentProvider->getEmptyConfig()->setId($parentId));
100: 
101:         if (!$objParentItem)
102:         {
103:             // No parent item found, might have been deleted.
104:             // We transparently create it for our filter to be able to filter to nothing.
105:             // TODO: shall we rather bail with "parent not found"?
106:             $objParentItem = $objParentProvider->getEmptyModel();
107:             $objParentItem->setID($parentId);
108:         }
109: 
110:         return $objParentItem;
111:     }
112: 
113:     /**
114:      * Render the entries for parent view.
115:      *
116:      * @param CollectionInterface $collection          The collection to render.
117:      *
118:      * @param array               $groupingInformation The grouping information as retrieved via
119:      *                            BaseView::getGroupingMode().
120:      *
121:      * @return void
122:      */
123:     protected function renderEntries($collection, $groupingInformation)
124:     {
125:         $environment = $this->getEnvironment();
126:         $definition  = $environment->getDataDefinition();
127:         $view        = $this->getViewSection();
128:         $listing     = $view->getListingConfig();
129:         $remoteCur   = null;
130:         $groupClass  = 'tl_folder_tlist';
131:         $eoCount     = -1;
132: 
133:         $objConfig = $environment->getDataProvider()->getEmptyConfig();
134:         $this->getPanel()->initialize($objConfig);
135: 
136:         // Run each model.
137:         $i = 0;
138:         foreach ($collection as $model)
139:         {
140:             /** @var ModelInterface $model */
141:             $i++;
142: 
143:             // Add the group header.
144:             if ($groupingInformation)
145:             {
146:                 $remoteNew = $this->formatCurrentValue(
147:                     $groupingInformation['property'],
148:                     $model,
149:                     $groupingInformation['mode'],
150:                     $groupingInformation['length']
151:                 );
152: 
153:                 // Add the group header if it differs from the last header.
154:                 if (!$listing->getShowColumns()
155:                     && ($groupingInformation['mode'] !== ListingConfigInterface::GROUP_NONE)
156:                     && (($remoteNew != $remoteCur) || ($remoteCur === null))
157:                 )
158:                 {
159:                     $eoCount = -1;
160: 
161:                     $model->setMeta(DCGE::MODEL_GROUP_VALUE, array(
162:                         'class' => $groupClass,
163:                         'value' => $remoteNew
164:                     ));
165: 
166:                     $groupClass = 'tl_folder_list';
167:                     $remoteCur  = $remoteNew;
168:                 }
169:             }
170: 
171:             if ($listing->getItemCssClass())
172:             {
173:                 $model->setMeta(DCGE::MODEL_CLASS, $listing->getItemCssClass());
174:             }
175: 
176:             // Regular buttons.
177:             if (!$this->isSelectModeActive())
178:             {
179:                 $previous = ((!is_null($collection->get($i - 1))) ? $collection->get($i - 1) : null);
180:                 $next     = ((!is_null($collection->get($i + 1))) ? $collection->get($i + 1) : null);
181: 
182:                 $buttons = $this->generateButtons($model, $previous, $next);
183: 
184:                 $model->setMeta(DCGE::MODEL_BUTTONS, $buttons);
185:             }
186: 
187:             $event = new ParentViewChildRecordEvent($this->getEnvironment(), $model);
188: 
189:             $this->getEnvironment()->getEventPropagator()->propagate(
190:                 $event::NAME,
191:                 $event,
192:                 array(
193:                     $this->getEnvironment()->getDataDefinition()->getName(),
194:                     $model->getId()
195:                 )
196:             );
197: 
198:             $model->setMeta(DCGE::MODEL_EVEN_ODD_CLASS, (((++$eoCount) % 2 == 0) ? 'even' : 'odd'));
199: 
200:             if ($event->getHtml() !== null)
201:             {
202:                 $information = array(
203:                     array(
204:                         'colspan' => 1,
205:                         'class'   => 'tl_file_list col_1',
206:                         'content' => $event->getHtml()
207:                     )
208:                 );
209:                 $model->setMeta(DCGE::MODEL_LABEL_VALUE, $information);
210:             }
211:             else
212:             {
213:                 $model->setMeta(DCGE::MODEL_LABEL_VALUE, $this->formatModel($model));
214:             }
215:         }
216:     }
217: 
218:     /**
219:      * Render the header of the parent view with information from the parent table.
220:      *
221:      * @param ModelInterface $parentModel The parent model.
222:      *
223:      * @return array
224:      */
225:     protected function renderFormattedHeaderFields($parentModel)
226:     {
227:         $environment       = $this->getEnvironment();
228:         $definition        = $environment->getDataDefinition();
229:         $viewDefinition    = $this->getViewSection();
230:         $listingDefinition = $viewDefinition->getListingConfig();
231:         $headerFields      = $listingDefinition->getHeaderPropertyNames();
232:         $parentDefinition  = $environment->getParentDataDefinition();
233:         $parentName        = $definition->getBasicDefinition()->getParentDataProvider();
234:         $add               = array();
235: 
236:         foreach ($headerFields as $v)
237:         {
238:             $value = deserialize($parentModel->getProperty($v));
239: 
240:             if ($v == 'tstamp')
241:             {
242:                 $value = date($GLOBALS['TL_CONFIG']['datimFormat'], $value);
243:             }
244: 
245:             $property = $parentDefinition->getPropertiesDefinition()->getProperty($v);
246: 
247:             // FIXME: foreignKey is not implemented yet.
248:             if ($property && (($v != 'tstamp')/* || $property->get('foreignKey')*/))
249:             {
250:                 $evaluation = $property->getExtra();
251:                 // FIXME: reference is not implemented yet.
252:                 // $reference  = $property->get('reference');
253:                 $options    = $property->getOptions();
254: 
255:                 if (is_array($value))
256:                 {
257:                     $value = implode(', ', $value);
258:                 }
259:                 elseif ($property->getWidgetType() == 'checkbox' && !$evaluation['multiple'])
260:                 {
261:                     $value = strlen($value) ? $this->translate('yes', 'MSC') : $this->translate('no', 'MSC');
262:                 }
263:                 elseif ($value && $evaluation['rgxp'] == 'date')
264:                 {
265:                     $value = BackendBindings::parseDate($GLOBALS['TL_CONFIG']['dateFormat'], $value);
266:                 }
267:                 elseif ($value && $evaluation['rgxp'] == 'time')
268:                 {
269:                     $value = BackendBindings::parseDate($GLOBALS['TL_CONFIG']['timeFormat'], $value);
270:                 }
271:                 elseif ($value && $evaluation['rgxp'] == 'datim')
272:                 {
273:                     $value = BackendBindings::parseDate($GLOBALS['TL_CONFIG']['datimFormat'], $value);
274:                 }
275:                 elseif (is_array($reference[$value]))
276:                 {
277:                     $value = $reference[$value][0];
278:                 }
279:                 elseif (isset($reference[$value]))
280:                 {
281:                     $value = $reference[$value];
282:                 }
283:                 elseif ($evaluation['isAssociative'] || array_is_assoc($options))
284:                 {
285:                     $value = $options[$value];
286:                 }
287:             }
288: 
289:             // Add the sorting field.
290:             if ($value != '')
291:             {
292:                 $lang = $this->translate(sprintf('%s.0', $v), $parentName);
293:                 $key  = $lang ? $lang : $v;
294: 
295:                 $add[$key] = $value;
296:             }
297:         }
298: 
299:         $event = new GetParentHeaderEvent($environment);
300:         $event->setAdditional($add);
301: 
302:         $this->getEnvironment()->getEventPropagator()->propagate(
303:             $event::NAME,
304:             $event,
305:             $this->getEnvironment()->getDataDefinition()->getName()
306:         );
307: 
308:         if (!$event->getAdditional() !== null)
309:         {
310:             $add = $event->getAdditional();
311:         }
312: 
313:         // Set header data.
314:         $arrHeader = array();
315:         foreach ($add as $k => $v)
316:         {
317:             if (is_array($v))
318:             {
319:                 $v = $v[0];
320:             }
321: 
322:             $arrHeader[$k] = $v;
323:         }
324: 
325:         return $arrHeader;
326:     }
327: 
328:     /**
329:      * Retrieve a list of html buttons to use in the top panel (submit area).
330:      *
331:      * @param ModelInterface $parentModel The parent model.
332:      *
333:      * @return array
334:      */
335:     protected function getHeaderButtons($parentModel)
336:     {
337:         $environment      = $this->getEnvironment();
338:         $definition       = $environment->getDataDefinition();
339:         $clipboard        = $environment->getClipboard();
340:         $basicDefinition  = $definition->getBasicDefinition();
341:         $parentDefinition = $environment->getParentDataDefinition();
342:         $parentName       = $basicDefinition->getParentDataProvider();
343: 
344:         $headerButtons = array();
345:         if ($this->isSelectModeActive())
346:         {
347:             $headerButtons['selectAll'] = sprintf(
348:                 '<label for="tl_select_trigger" class="tl_select_label">%s</label>
349:                 <input type="checkbox"
350:                     id="tl_select_trigger"
351:                     onclick="Backend.toggleCheckboxes(this)"
352:                     class="tl_tree_checkbox" />',
353:                 $this->translate('selectAll', 'MSC')
354:             );
355:         }
356:         else
357:         {
358:             $propagator = $environment->getEventPropagator();
359: 
360:             $objConfig = $this->getEnvironment()->getController()->getBaseConfig();
361:             $this->getPanel()->initialize($objConfig);
362:             $sorting = $objConfig->getSorting();
363: 
364:             if ($sorting
365:                 && !$basicDefinition->isClosed()
366:                 && $basicDefinition->isCreatable())
367:             {
368:                 /** @var AddToUrlEvent $urlEvent */
369:                 $urlEvent = $propagator->propagate(
370:                     ContaoEvents::BACKEND_ADD_TO_URL,
371:                     new AddToUrlEvent(
372:                         'act=paste&amp;mode=create&amp;pid=' . $parentModel->getID()
373:                     )
374:                 );
375: 
376:                 /** @var GenerateHtmlEvent $imageEvent */
377:                 $imageEvent = $propagator->propagate(
378:                     ContaoEvents::IMAGE_GET_HTML,
379:                     new GenerateHtmlEvent(
380:                         'new.gif',
381:                         $this->translate('pastenew.0', $definition->getName())
382:                     )
383:                 );
384: 
385:                 $headerButtons['pasteNew'] = sprintf(
386:                     '<a href="%s" title="%s" onclick="Backend.getScrollOffset()">%s</a>',
387:                     $urlEvent->getUrl(),
388:                     specialchars($this->translate('pastenew.1', $definition->getName())),
389:                     $imageEvent->getHtml()
390:                 );
391:             }
392: 
393:             if ($parentDefinition && $parentDefinition->getBasicDefinition()->isEditable())
394:             {
395:                 /** @var GenerateHtmlEvent $imageEvent */
396:                 $imageEvent = $propagator->propagate(
397:                     ContaoEvents::IMAGE_GET_HTML,
398:                     new GenerateHtmlEvent(
399:                         'edit.gif',
400:                         $this->translate('editheader.0', $definition->getName())
401:                     )
402:                 );
403: 
404:                 $headerButtons['editHeader'] = sprintf(
405:                     '<a href="%s" title="%s" onclick="Backend.getScrollOffset()">%s</a>',
406:                     sprintf(
407:                         'contao/main.php?do=%s&amp;act=edit&amp;table=%s&amp;id=%s',
408:                         $environment->getInputProvider()->getParameter('do'),
409:                         $parentName,
410:                         $parentModel->getID()
411:                     ),
412:                     specialchars($this->translate('editheader.1', $definition->getName())),
413:                     $imageEvent->getHtml()
414:                 );
415:             }
416: 
417:             if ($sorting && $clipboard->isNotEmpty())
418:             {
419:                 /** @var AddToUrlEvent $urlEvent */
420:                 $urlEvent = $propagator->propagate(
421:                     ContaoEvents::BACKEND_ADD_TO_URL,
422:                     new AddToUrlEvent('act=' . $clipboard->getMode() . '&amp;mode=2&amp;pid=' . $parentModel->getID())
423:                 );
424: 
425:                 /** @var GenerateHtmlEvent $imageEvent */
426:                 $imageEvent = $propagator->propagate(
427:                     ContaoEvents::IMAGE_GET_HTML,
428:                     new GenerateHtmlEvent(
429:                         'pasteafter.gif',
430:                         $this->translate('pasteafter.0', $definition->getName()),
431:                         'class="blink"'
432:                     )
433:                 );
434: 
435:                 $headerButtons['pasteAfter'] = sprintf(
436:                     '<a href="%s" title="%s" onclick="Backend.getScrollOffset()">%s</a>',
437:                     $urlEvent->getUrl(),
438:                     specialchars($this->translate('pasteafter.1', $definition->getName())),
439:                     $imageEvent->getHtml()
440:                 );
441:             }
442:         }
443: 
444:         return implode(' ', $headerButtons);
445:     }
446: 
447: 
448:     /**
449:      * Show parent view mode 4.
450:      *
451:      * @param CollectionInterface $collection  The collection containing the models.
452:      *
453:      * @param ModelInterface      $parentModel The parent model.
454:      *
455:      * @return string HTML output
456:      */
457:     protected function viewParent($collection, $parentModel)
458:     {
459:         $definition          = $this->getEnvironment()->getDataDefinition();
460:         $parentProvider      = $definition->getBasicDefinition()->getParentDataProvider();
461:         $groupingInformation = $this->getGroupingMode();
462:         $propagator          = $this->getEnvironment()->getEventPropagator();
463: 
464: 
465:         // Skip if we have no parent or parent collection.
466:         if (!$parentModel)
467:         {
468:             $propagator->propagate(
469:                 ContaoEvents::SYSTEM_LOG,
470:                 new LogEvent(
471:                     sprintf(
472:                         'The view for %s has either a empty parent data provider or collection.',
473:                         $parentProvider
474:                     ),
475:                     __CLASS__ . '::' . __FUNCTION__ . '()',
476:                     TL_ERROR
477:                 )
478:             );
479: 
480:             $propagator->propagate(
481:                 ContaoEvents::CONTROLLER_REDIRECT,
482:                 new RedirectEvent('contao/main.php?act=error')
483:             );
484:         }
485: 
486:         // Add template.
487:         if ($groupingInformation['mode'] != ListingConfigInterface::GROUP_NONE)
488:         {
489:             $objTemplate = $this->getTemplate('dcbe_general_grouping');
490:         }
491:         else
492:         {
493:             $objTemplate = $this->getTemplate('dcbe_general_parentView');
494:         }
495: 
496:         $this
497:             ->addToTemplate('tableName', strlen($definition->getName())? $definition->getName() : 'none', $objTemplate)
498:             ->addToTemplate('collection', $collection, $objTemplate)
499:             ->addToTemplate('select', $this->isSelectModeActive(), $objTemplate)
500:             ->addToTemplate('action', ampersand(\Environment::getInstance()->request, true), $objTemplate)
501:             ->addToTemplate('header', $this->renderFormattedHeaderFields($parentModel), $objTemplate)
502:             ->addToTemplate('hasSorting', ($groupingInformation['property'] == 'sorting'), $objTemplate)
503:             ->addToTemplate('mode', ($groupingInformation ? $groupingInformation['mode'] : null), $objTemplate)
504:             ->addToTemplate('pdp', (string)$parentProvider, $objTemplate)
505:             ->addToTemplate('cdp', $definition->getName(), $objTemplate)
506:             ->addToTemplate('selectButtons', $this->getSelectButtons(), $objTemplate)
507:             ->addToTemplate('headerButtons', $this->getHeaderButtons($parentModel), $objTemplate);
508: 
509:         $this->renderEntries($collection, $groupingInformation);
510: 
511:         // Add breadcrumb, if we have one.
512:         $strBreadcrumb = $this->breadcrumb();
513:         if ($strBreadcrumb != null)
514:         {
515:             $this->addToTemplate('breadcrumb', $strBreadcrumb, $objTemplate);
516:         }
517: 
518:         return $objTemplate->parse();
519:     }
520: 
521:     /**
522:      * {@inheritDoc}
523:      */
524:     public function enforceModelRelationship($model)
525:     {
526:         $definition = $this->getEnvironment()->getDataDefinition();
527:         $basic      = $definition->getBasicDefinition();
528:         $parent     = $this->loadParentModel();
529: 
530:         $condition = $definition
531:             ->getModelRelationshipDefinition()
532:             ->getChildCondition(
533:                 $basic->getParentDataProvider(),
534:                 $basic->getDataProvider()
535:             );
536: 
537:         if ($condition)
538:         {
539:             $condition->applyTo($parent, $model);
540:         }
541:     }
542: 
543:     /**
544:      * Show all entries from one table.
545:      *
546:      * @return string HTML
547:      */
548:     public function showAll()
549:     {
550:         $this->checkClipboard();
551:         $collection  = $this->loadCollection();
552:         $parentModel = $this->loadParentModel();
553: 
554:         $arrReturn            = array();
555:         $arrReturn['panel']   = $this->panel();
556:         $arrReturn['buttons'] = $this->generateHeaderButtons('tl_buttons_a');
557:         $arrReturn['body']    = $this->viewParent($collection, $parentModel);
558: 
559:         return implode("\n", $arrReturn);
560:     }
561: }
562: 
contao-community-alliance/dc-general API documentation generated by ApiGen 2.8.0