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

  • AbstractModel
  • DCGE
  • DefaultCollection
  • DefaultConfig
  • DefaultDataProvider
  • DefaultLanguageInformation
  • DefaultLanguageInformationCollection
  • DefaultModel
  • MultiLanguageDataProvider
  • NoOpDataProvider
  • PropertyValueBag
  • TableRowsAsRecordsDataProvider

Interfaces

  • CollectionInterface
  • ConfigInterface
  • DataProviderInterface
  • LanguageInformationCollectionInterface
  • LanguageInformationInterface
  • ModelInterface
  • MultiLanguageDataProviderInterface
  • PropertyValueBagInterface
  • VersionModelInterface
  • 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\Data;
 14: 
 15: use DcGeneral\Exception\DcGeneralRuntimeException;
 16: 
 17: /**
 18:  * Class DefaultDataProvider.
 19:  *
 20:  * Default implementation for a data provider using the Contao default database as backend.
 21:  *
 22:  * @package DcGeneral\Data
 23:  */
 24: class DefaultDataProvider implements DataProviderInterface
 25: {
 26:     /**
 27:      * Name of current source.
 28:      *
 29:      * @var string
 30:      */
 31:     protected $strSource = null;
 32: 
 33:     /**
 34:      * The Database instance.
 35:      *
 36:      * @var \Database
 37:      *
 38:      * @todo: Use DI container for database instance.
 39:      */
 40:     protected $objDatabase = null;
 41: 
 42:     /**
 43:      * Create a new instance of the data provider.
 44:      */
 45:     public function __construct()
 46:     {
 47:         $this->objDatabase = \Database::getInstance();
 48:     }
 49: 
 50:     /**
 51:      * {@inheritDoc}
 52:      *
 53:      * @throws DcGeneralRuntimeException When no source has been defined.
 54:      */
 55:     public function setBaseConfig(array $arrConfig)
 56:     {
 57:         // Check configuration.
 58:         if (!isset($arrConfig['source']))
 59:         {
 60:             throw new DcGeneralRuntimeException('Missing table name.');
 61:         }
 62: 
 63:         $this->strSource = $arrConfig['source'];
 64:     }
 65: 
 66:     /**
 67:      * {@inheritDoc}
 68:      */
 69:     public function getEmptyConfig()
 70:     {
 71:         return DefaultConfig::init();
 72:     }
 73: 
 74:     /**
 75:      * {@inheritDoc}
 76:      */
 77:     public function getEmptyModel()
 78:     {
 79:         $objModel = new DefaultModel();
 80:         $objModel->setProviderName($this->strSource);
 81:         return $objModel;
 82:     }
 83: 
 84:     /**
 85:      * {@inheritDoc}
 86:      */
 87:     public function getEmptyCollection()
 88:     {
 89:         return new DefaultCollection();
 90:     }
 91: 
 92:     /**
 93:      * Build the field list.
 94:      *
 95:      * Returns all values from $objConfig->getFields() as comma separated list.
 96:      *
 97:      * @param ConfigInterface $objConfig The configuration to use.
 98:      *
 99:      * @return string
100:      */
101:     protected function buildFieldQuery($objConfig)
102:     {
103:         $strFields = '*';
104: 
105:         if ($objConfig->getIdOnly())
106:         {
107:             $strFields = 'id';
108:         }
109:         elseif (!is_null($objConfig->getFields()))
110:         {
111:             $strFields = implode(', ', $objConfig->getFields());
112: 
113:             if (!stristr($strFields, 'DISTINCT'))
114:             {
115:                 $strFields = 'id, ' . $strFields;
116:             }
117:         }
118: 
119:         return $strFields;
120:     }
121: 
122:     /**
123:      * Build an AND or OR query.
124:      *
125:      * @param array $operation The operation to convert.
126:      *
127:      * @param array $params    The parameter array for the resulting query.
128:      *
129:      * @return string
130:      */
131:     protected function getAndOrFilter($operation, &$params)
132:     {
133:         // FIXME: backwards compat - remove when done.
134:         if (is_array($operation['childs']))
135:         {
136:             trigger_error('Filter array uses deprecated entry "childs", please use "children" instead.', E_USER_DEPRECATED);
137:             $operation['children'] = $operation['childs'];
138:         }
139: 
140:         $children = $operation['children'];
141: 
142:         if (!$children)
143:         {
144:             return '';
145:         }
146: 
147:         $combine = array();
148:         foreach ($children as $child)
149:         {
150: 
151:             $combine[] = $this->calculateSubfilter($child, $params);
152:         }
153: 
154:         return implode(sprintf(' %s ', $operation['operation']), $combine);
155:     }
156: 
157:     /**
158:      * Build the sub query for a comparing operator like =,<,>.
159:      *
160:      * @param array $operation The operation to apply.
161:      *
162:      * @param array $params    The parameters of the entire query.
163:      *
164:      * @return string
165:      */
166:     protected function getFilterForComparingOperator($operation, &$params)
167:     {
168:         $params[] = $operation['value'];
169: 
170:         return sprintf('(%s %s ?)', $operation['property'], $operation['operation']);
171:     }
172: 
173:     /**
174:      * Return the filter query for a "foo IN ('a', 'b')" filter.
175:      *
176:      * @param array $operation The operation to apply.
177:      *
178:      * @param array $params    The parameters of the entire query.
179:      *
180:      * @return string
181:      */
182:     protected function getFilterForInList($operation, &$params)
183:     {
184:         $params    = array_merge($params, array_values($operation['values']));
185:         $wildcards = rtrim(str_repeat('?,', count($operation['values'])), ',');
186: 
187:         return sprintf('(%s IN (%s))', $operation['property'], $wildcards);
188:     }
189: 
190:     /**
191:      * Return the filter query for a "foo LIKE '%ba_r%'" filter.
192:      *
193:      * The searched value may contain the wildcards '*' and '?' which will get converted to proper SQL.
194:      *
195:      * @param array $operation The operation to apply.
196:      *
197:      * @param array $params    The parameters of the entire query.
198:      *
199:      * @return string
200:      */
201:     protected function getFilterForLike($operation, &$params)
202:     {
203:         $wildcards = str_replace(array('*', '?'), array('%', '_'), $operation['value']);
204:         $params[]  = $wildcards;
205: 
206:         return sprintf('(%s LIKE ?)', $operation['property'], $wildcards);
207:     }
208: 
209:     /**
210:      * Combine a filter in standard filter array notation.
211:      *
212:      * Supported operations are:
213:      * operation      needed arguments     argument type.
214:      * AND
215:      *                'children'           array
216:      * OR
217:      *                'children'           array
218:      * =
219:      *                'property'           string (the name of a property)
220:      *                'value'              literal
221:      * >
222:      *                'property'           string (the name of a property)
223:      *                'value'              literal
224:      * <
225:      *                'property'           string (the name of a property)
226:      *                'value'              literal
227:      * IN
228:      *                'property'           string (the name of a property)
229:      *                'values'             array of literal
230:      *
231:      * LIKE
232:      *                'property'           string (the name of a property)
233:      *                'value'              literal - Wildcards * (Many) ? (One)
234:      *
235:      * @param array $arrFilter The filter to be combined to a valid SQL filter query.
236:      *
237:      * @param array $arrParams The query parameters will get stored into this array.
238:      *
239:      * @return string The combined WHERE conditions.
240:      *
241:      * @throws DcGeneralRuntimeException If an invalid filter entry is encountered.
242:      */
243:     protected function calculateSubfilter($arrFilter, array &$arrParams)
244:     {
245:         if (!is_array($arrFilter))
246:         {
247:             throw new DcGeneralRuntimeException('Error Processing sub filter: ' . var_export($arrFilter, true), 1);
248:         }
249: 
250:         switch ($arrFilter['operation'])
251:         {
252:             case 'AND':
253:             case 'OR':
254:                 return $this->getAndOrFilter($arrFilter, $arrParams);
255: 
256:             case '=':
257:             case '>':
258:             case '<':
259:                 return $this->getFilterForComparingOperator($arrFilter, $arrParams);
260: 
261:             case 'IN':
262:                 return $this->getFilterForInList($arrFilter, $arrParams);
263: 
264:             case 'LIKE':
265:                 return $this->getFilterForLike($arrFilter, $arrParams);
266: 
267:             default:
268:         }
269: 
270:         throw new DcGeneralRuntimeException('Error processing filter array ' . var_export($arrFilter, true), 1);
271:     }
272: 
273:     /**
274:      * Build the WHERE clause for a configuration.
275:      *
276:      * @param ConfigInterface $objConfig The configuration to use.
277:      *
278:      * @param array           $arrParams The query parameters will get stored into this array.
279:      *
280:      * @return string  The combined WHERE clause (including the word "WHERE").
281:      */
282:     protected function buildWhereQuery($objConfig, array &$arrParams = null)
283:     {
284:         $arrParams || $arrParams = array();
285: 
286:         $arrQuery = array();
287: 
288:         $arrQuery['filter'] = $this->buildFilterQuery($objConfig, $arrParams);
289: 
290:         $arrQuery = array_filter($arrQuery, 'strlen');
291: 
292:         return count($arrQuery) ? ' WHERE ' . implode(' AND ', $arrQuery) : '';
293:     }
294: 
295:     /**
296:      * Build the WHERE conditions via calculateSubfilter().
297:      *
298:      * @param ConfigInterface $objConfig The configuration to use.
299:      *
300:      * @param array           $arrParams The query parameters will get stored into this array.
301:      *
302:      * @return string The combined WHERE conditions.
303:      */
304:     protected function buildFilterQuery($objConfig, array &$arrParams = null)
305:     {
306:         $arrParams || $arrParams = array();
307: 
308:         $strReturn = $this->calculateSubfilter(
309:             array(
310:                 'operation' => 'AND',
311:                 'children' => $objConfig->getFilter()
312:             ), $arrParams
313:         );
314: 
315:         // Combine filter syntax.
316:         return $strReturn ? $strReturn : '';
317:     }
318: 
319:     /**
320:      * Build the order by part of a query.
321:      *
322:      * @param ConfigInterface $objConfig The configuration to use.
323:      *
324:      * @return string
325:      */
326:     protected function buildSortingQuery($objConfig)
327:     {
328:         $arrSorting = $objConfig->getSorting();
329:         $strReturn  = '';
330:         $arrFields  = array();
331: 
332:         if (!is_null($arrSorting) && is_array($arrSorting) && count($arrSorting) > 0)
333:         {
334:             foreach ($arrSorting as $strField => $strOrder)
335:             {
336:                 if (!in_array($strOrder, array(DCGE::MODEL_SORTING_ASC, DCGE::MODEL_SORTING_DESC)))
337:                 {
338:                     $strOrder = DCGE::MODEL_SORTING_ASC;
339:                 }
340: 
341:                 $arrFields[] = $strField . ' ' . $strOrder;
342:             }
343: 
344:             $strReturn .= ' ORDER BY ' . implode(', ', $arrFields);
345:         }
346: 
347:         return $strReturn;
348:     }
349: 
350:     /**
351:      * {@inheritDoc}
352:      *
353:      * @throws DcGeneralRuntimeException When an unusable object has been passed.
354:      */
355:     public function delete($item)
356:     {
357:         $id = null;
358:         if (is_numeric($item) || is_string($item))
359:         {
360:             $id = $item;
361:         }
362:         elseif (is_object($item) && $item instanceof ModelInterface && strlen($item->getID()) != 0)
363:         {
364:             $id = $item->getID();
365:         }
366:         else
367:         {
368:             throw new DcGeneralRuntimeException("ID missing or given object not of type 'ModelInterface'.");
369:         }
370: 
371:         // Insert undo.
372:         $this->insertUndo(
373:             sprintf(
374:                 'DELETE FROM %1$s WHERE id = %2$s',
375:                 $this->strSource,
376:                 $id
377:             ),
378:             sprintf(
379:                 'SELECT * FROM %1$s WHERE id = %2$s',
380:                 $this->strSource,
381:                 $id
382:             ),
383:             $this->strSource
384:         );
385: 
386:         $this->objDatabase
387:             ->prepare(sprintf('DELETE FROM %s WHERE id=?', $this->strSource))
388:             ->execute($id);
389:     }
390: 
391:     /**
392:      * Create a model from a database result.
393:      *
394:      * @param \Database\Result $dbResult The database result to create a model from.
395:      *
396:      * @return ModelInterface
397:      */
398:     protected function createModelFromDatabaseResult($dbResult)
399:     {
400:         $objModel = $this->getEmptyModel();
401: 
402:         /** @var \Contao\Database\Result $dbResult */
403:         foreach ($dbResult->row() as $key => $value)
404:         {
405:             if ($key == 'id')
406:             {
407:                 $objModel->setID($value);
408:             }
409: 
410:             $objModel->setProperty($key, deserialize($value));
411:         }
412: 
413:         return $objModel;
414:     }
415: 
416:     /**
417:      * {@inheritDoc}
418:      */
419:     public function fetch(ConfigInterface $objConfig)
420:     {
421:         if ($objConfig->getId() != null)
422:         {
423:             $strQuery = sprintf(
424:                 'SELECT %s  FROM %s WHERE id = ?',
425:                 $this->buildFieldQuery($objConfig),
426:                 $this->strSource
427:             );
428: 
429:             $dbResult = $this->objDatabase
430:                 ->prepare($strQuery)
431:                 ->execute($objConfig->getId());
432:         }
433:         else
434:         {
435:             $arrParams = array();
436:             // Build SQL.
437:             $query  = sprintf(
438:                 'SELECT %s FROM %s',
439:                 $this->buildFieldQuery($objConfig),
440:                 $this->strSource
441:             );
442:             $query .= $this->buildWhereQuery($objConfig, $arrParams);
443:             $query .= $this->buildSortingQuery($objConfig);
444: 
445:             // Execute db query.
446:             $dbResult = $this->objDatabase
447:                 ->prepare($query)
448:                 ->limit(1, 0)
449:                 ->executeUncached($arrParams);
450:         }
451: 
452:         if ($dbResult->numRows == 0)
453:         {
454:             return null;
455:         }
456: 
457:         return $this->createModelFromDatabaseResult($dbResult);
458:     }
459: 
460:     /**
461:      * {@inheritDoc}
462:      */
463:     public function fetchAll(ConfigInterface $objConfig)
464:     {
465:         $arrParams = array();
466:         // Build SQL.
467:         $query  = sprintf(
468:             'SELECT %s FROM %s',
469:             $this->buildFieldQuery($objConfig),
470:             $this->strSource
471:         );
472:         $query .= $this->buildWhereQuery($objConfig, $arrParams);
473:         $query .= $this->buildSortingQuery($objConfig);
474: 
475:         // Execute db query.
476:         $objDatabaseQuery = $this->objDatabase->prepare($query);
477: 
478:         if ($objConfig->getAmount() != 0)
479:         {
480:             $objDatabaseQuery->limit($objConfig->getAmount(), $objConfig->getStart());
481:         }
482: 
483:         $dbResult = $objDatabaseQuery->executeUncached($arrParams);
484: 
485:         if ($objConfig->getIdOnly())
486:         {
487:             return $dbResult->fetchEach('id');
488:         }
489: 
490:         $objCollection = $this->getEmptyCollection();
491: 
492:         if ($dbResult->numRows == 0)
493:         {
494:             return $objCollection;
495:         }
496: 
497:         while ($dbResult->next())
498:         {
499:             $objCollection->add($this->createModelFromDatabaseResult($dbResult));
500:         }
501: 
502:         return $objCollection;
503:     }
504: 
505:     /**
506:      * {@inheritDoc}
507:      *
508:      * @throws DcGeneralRuntimeException if improper values have been passed (i.e. not exactly one field requested).
509:      */
510:     public function getFilterOptions(ConfigInterface $objConfig)
511:     {
512:         $arrProperties = $objConfig->getFields();
513:         $strProperty   = $arrProperties[0];
514: 
515:         if (count($arrProperties) <> 1)
516:         {
517:             throw new DcGeneralRuntimeException('objConfig must contain exactly one property to be retrieved.');
518:         }
519: 
520:         $arrParams = array();
521: 
522:         $objValues = $this->objDatabase
523:             ->prepare(sprintf('SELECT DISTINCT(%s) FROM %s %s',
524:                 $strProperty,
525:                 $this->strSource,
526:                 $this->buildWhereQuery($objConfig, $arrParams)
527:             ))
528:             ->executeUncached($arrParams);
529: 
530:         $objCollection = $this->getEmptyCollection();
531:         while ($objValues->next())
532:         {
533:             $objNewModel = $this->getEmptyModel();
534:             $objNewModel->setProperty($strProperty, $objValues->$strProperty);
535:             $objCollection->add($objNewModel);
536:         }
537: 
538:         return $objCollection;
539:     }
540: 
541:     /**
542:      * {@inheritDoc}
543:      */
544:     public function getCount(ConfigInterface $objConfig)
545:     {
546:         $arrParams = array();
547: 
548:         $query  = sprintf(
549:             'SELECT COUNT(*) AS count FROM %s',
550:             $this->strSource
551:         );
552:         $query .= $this->buildWhereQuery($objConfig, $arrParams);
553: 
554:         $objCount = $this->objDatabase
555:             ->prepare($query)
556:             ->executeUncached($arrParams);
557: 
558:         return $objCount->count;
559:     }
560: 
561:     /**
562:      * {@inheritDoc}
563:      */
564:     public function isUniqueValue($strField, $varNew, $intId = null)
565:     {
566:         $objUnique = $this->objDatabase
567:             ->prepare('SELECT * FROM ' . $this->strSource . ' WHERE ' . $strField . ' = ? ')
568:             ->executeUncached($varNew);
569: 
570:         if ($objUnique->numRows == 0)
571:         {
572:             return true;
573:         }
574: 
575:         if (($objUnique->numRows == 1) && ($objUnique->id == $intId))
576:         {
577:             return true;
578:         }
579: 
580:         return false;
581:     }
582: 
583:     /**
584:      * {@inheritDoc}
585:      */
586:     public function resetFallback($strField)
587:     {
588:         $this->objDatabase->query('UPDATE ' . $this->strSource . ' SET ' . $strField . ' = \'\'');
589:     }
590: 
591:     /**
592:      * {@inheritDoc}
593:      */
594:     public function save(ModelInterface $objItem)
595:     {
596:         $arrSet = array();
597: 
598:         foreach ($objItem as $key => $value)
599:         {
600:             if ($key == 'id')
601:             {
602:                 continue;
603:             }
604: 
605:             if (is_array($value))
606:             {
607:                 $arrSet[$key] = serialize($value);
608:             }
609:             else
610:             {
611:                 $arrSet[$key] = $value;
612:             }
613:         }
614: 
615:         if ($objItem->getID() == null || $objItem->getID() == '')
616:         {
617:             $objInsert = $this->objDatabase
618:                 ->prepare(sprintf('INSERT INTO %s %%s', $this->strSource))
619:                 ->set($arrSet)
620:                 ->execute();
621: 
622:             if (strlen($objInsert->insertId) != 0)
623:             {
624:                 $objItem->setID($objInsert->insertId);
625:             }
626:         }
627:         else
628:         {
629:             $this->objDatabase
630:                 ->prepare(sprintf('UPDATE %s %%s WHERE id=?', $this->strSource))
631:                 ->set($arrSet)
632:                 ->execute($objItem->getID());
633:         }
634: 
635:         return $objItem;
636:     }
637: 
638:     /**
639:      * {@inheritDoc}
640:      */
641:     public function saveEach(CollectionInterface $objItems)
642:     {
643:         foreach ($objItems as $value)
644:         {
645:             $this->save($value);
646:         }
647:     }
648: 
649:     /**
650:      * {@inheritDoc}
651:      */
652:     public function fieldExists($strField)
653:     {
654:         return $this->objDatabase->fieldExists($strField, $this->strSource);
655:     }
656: 
657:     /**
658:      * {@inheritDoc}
659:      */
660:     public function getVersion($mixID, $mixVersion)
661:     {
662:         $objVersion = $this->objDatabase
663:             ->prepare('SELECT * FROM tl_version WHERE pid=? AND version=? AND fromTable=?')
664:             ->execute($mixID, $mixVersion, $this->strSource);
665: 
666:         if ($objVersion->numRows == 0)
667:         {
668:             return null;
669:         }
670: 
671:         $arrData = deserialize($objVersion->data);
672: 
673:         if (!is_array($arrData) || count($arrData) == 0)
674:         {
675:             return null;
676:         }
677: 
678:         $objModel = $this->getEmptyModel();
679:         $objModel->setID($mixID);
680:         foreach ($arrData as $key => $value)
681:         {
682:             if ($key == 'id')
683:             {
684:                 continue;
685:             }
686: 
687:             $objModel->setProperty($key, $value);
688:         }
689: 
690:         return $objModel;
691:     }
692: 
693:     /**
694:      * Return a list with all versions for the row with the given Id.
695:      *
696:      * @param mixed   $mixID         The ID of the row.
697:      *
698:      * @param boolean $blnOnlyActive If true, only active versions will get returned, if false all version will get
699:      *                               returned.
700:      *
701:      * @return CollectionInterface
702:      */
703:     public function getVersions($mixID, $blnOnlyActive = false)
704:     {
705:         $sql = 'SELECT tstamp, version, username, active FROM tl_version WHERE fromTable = ? AND pid = ?';
706:         if ($blnOnlyActive)
707:         {
708:             $sql .= ' AND active = 1';
709:         }
710:         else
711:         {
712:             $sql .= ' ORDER BY version DESC';
713:         }
714: 
715:         $arrVersion = $this->objDatabase
716:             ->prepare($sql)
717:             ->execute($this->strSource, $mixID)
718:             ->fetchAllAssoc();
719: 
720:         if (count($arrVersion) == 0)
721:         {
722:             return null;
723:         }
724: 
725:         $objCollection = $this->getEmptyCollection();
726: 
727:         foreach ($arrVersion as $versionValue)
728:         {
729:             $objReturn = $this->getEmptyModel();
730:             $objReturn->setID($mixID);
731: 
732:             foreach ($versionValue as $key => $value)
733:             {
734:                 if ($key == 'id')
735:                 {
736:                     continue;
737:                 }
738: 
739:                 $objReturn->setProperty($key, $value);
740:             }
741: 
742:             $objCollection->add($objReturn);
743:         }
744: 
745:         return $objCollection;
746:     }
747: 
748:     /**
749:      * Save a new version of a row.
750:      *
751:      * @param ModelInterface $objModel    The model for which a new version shall be created.
752:      *
753:      * @param string         $strUsername The username to attach to the version as creator.
754:      *
755:      * @return void
756:      */
757:     public function saveVersion(ModelInterface $objModel, $strUsername)
758:     {
759:         $objCount = $this->objDatabase
760:             ->prepare('SELECT count(*) as mycount FROM tl_version WHERE pid=? AND fromTable = ?')
761:             ->execute($objModel->getID(), $this->strSource);
762: 
763:         $mixNewVersion = (intval($objCount->mycount) + 1);
764: 
765:         $mixData       = $objModel->getPropertiesAsArray();
766:         $mixData['id'] = $objModel->getID();
767: 
768:         $arrInsert              = array();
769:         $arrInsert['pid']       = $objModel->getID();
770:         $arrInsert['tstamp']    = time();
771:         $arrInsert['version']   = $mixNewVersion;
772:         $arrInsert['fromTable'] = $this->strSource;
773:         $arrInsert['username']  = $strUsername;
774:         $arrInsert['data']      = serialize($mixData);
775: 
776:         $this->objDatabase->prepare('INSERT INTO tl_version %s')
777:             ->set($arrInsert)
778:             ->execute();
779: 
780:         $this->setVersionActive($objModel->getID(), $mixNewVersion);
781:     }
782: 
783:     /**
784:      * Set a version as active.
785:      *
786:      * @param mixed $mixID      The ID of the row.
787:      *
788:      * @param mixed $mixVersion The version number to set active.
789:      *
790:      * @return void
791:      */
792:     public function setVersionActive($mixID, $mixVersion)
793:     {
794:         $this->objDatabase
795:             ->prepare('UPDATE tl_version SET active=\'\' WHERE pid = ? AND fromTable = ?')
796:             ->execute($mixID, $this->strSource);
797: 
798:         $this->objDatabase
799:             ->prepare('UPDATE tl_version SET active = 1 WHERE pid = ? AND version = ? AND fromTable = ?')
800:             ->execute($mixID, $mixVersion, $this->strSource);
801:     }
802: 
803:     /**
804:      * Retrieve the current active version for a row.
805:      *
806:      * @param mixed $mixID The ID of the row.
807:      *
808:      * @return mixed The current version number of the requested row.
809:      */
810:     public function getActiveVersion($mixID)
811:     {
812:         $objVersionID = $this->objDatabase
813:             ->prepare('SELECT version FROM tl_version WHERE pid = ? AND fromTable = ? AND active = 1')
814:             ->execute($mixID, $this->strSource);
815: 
816:         if ($objVersionID->numRows == 0)
817:         {
818:             return null;
819:         }
820: 
821:         return $objVersionID->version;
822:     }
823: 
824:     /**
825:      * Check if two models have the same values in all properties.
826:      *
827:      * @param ModelInterface $objModel1 The first model to compare.
828:      *
829:      * @param ModelInterface $objModel2 The second model to compare.
830:      *
831:      * @return boolean True - If both models are same, false if not.
832:      */
833:     public function sameModels($objModel1, $objModel2)
834:     {
835:         foreach ($objModel1 as $key => $value)
836:         {
837:             if ($key == 'id')
838:             {
839:                 continue;
840:             }
841: 
842:             if (is_array($value))
843:             {
844:                 if (!is_array($objModel2->getProperty($key)))
845:                 {
846:                     return false;
847:                 }
848: 
849:                 if (serialize($value) != serialize($objModel2->getProperty($key)))
850:                 {
851:                     return false;
852:                 }
853:             }
854:             elseif ($value != $objModel2->getProperty($key))
855:             {
856:                 return false;
857:             }
858:         }
859: 
860:         return true;
861:     }
862: 
863:     /**
864:      * Store an undo entry in the table tl_undo.
865:      *
866:      * Currently this only supports delete queries.
867:      *
868:      * @param string $strSourceSQL The SQL used to perform the action to be undone.
869:      *
870:      * @param string $strSaveSQL   The SQL query to retrieve the current entries.
871:      *
872:      * @param string $strTable     The table to be affected by the action.
873:      *
874:      * @return void
875:      */
876:     protected function insertUndo($strSourceSQL, $strSaveSQL, $strTable)
877:     {
878:         // Load row.
879:         $arrResult = $this->objDatabase
880:             ->prepare($strSaveSQL)
881:             ->executeUncached()
882:             ->fetchAllAssoc();
883: 
884:         // Check if we have a result.
885:         if (count($arrResult) == 0)
886:         {
887:             return;
888:         }
889: 
890:         // Save information in array.
891:         $arrSave = array();
892:         foreach ($arrResult as $value)
893:         {
894:             $arrSave[$strTable][] = $value;
895:         }
896: 
897:         $strPrefix = '<span style="color:#b3b3b3; padding-right:3px;">(DC General)</span>';
898:         $objUser   = \BackendUser::getInstance();
899: 
900:         // Write into undo.
901:         $this->objDatabase
902:             ->prepare('INSERT INTO tl_undo (pid, tstamp, fromTable, query, affectedRows, data) VALUES (?, ?, ?, ?, ?, ?)')
903:             ->execute(
904:                 $objUser->id,
905:                 time(),
906:                 $strTable,
907:                 $strPrefix .
908:                 $strSourceSQL,
909:                 count($arrSave[$strTable]),
910:                 serialize($arrSave)
911:             );
912:     }
913: }
914: 
contao-community-alliance/dc-general API documentation generated by ApiGen 2.8.0