vendor\project-biz\database-bundle\src\Database\TableAndViewInfo.php line 52

Open in your IDE?
  1. <?php
  2. namespace ProjectBiz\DatabaseBundle\Database;
  3. use Doctrine\DBAL\Connection;
  4. use Doctrine\DBAL\Query\QueryBuilder;
  5. use Doctrine\ORM\EntityRepository;
  6. use ProjectBiz\DatabaseBundle\Entity\ColumnDefinition;
  7. use ProjectBiz\DatabaseBundle\Form\Constraints\DateTimeConstraint;
  8. use ProjectBiz\DatabaseBundle\Form\Constraints\UniqueConstraint;
  9. use Symfony\Component\Validator\Constraints\NotNull;
  10. use Symfony\Contracts\Translation\TranslatorInterface;
  11. abstract class TableAndViewInfo implements TableInfoInterface
  12. {
  13.     protected static $columnDescriptions = [];
  14.     /**
  15.      * @var Connection
  16.      */
  17.     protected $tablename;
  18.     protected $databaseSchemaCache;
  19.     protected $tableHelper;
  20.     protected $userRights;
  21.     /**
  22.      * @var \Symfony\Component\Validator\Constraint[]
  23.      */
  24.     protected $constraints = [];
  25.     private $cachedReadableColumns = [];
  26.     private $cachedWriteableColumns = [];
  27.     private $cachedTableConstraints;
  28.     static private $cachedTableDefinition null;
  29.     /**
  30.      * Construct.
  31.      *
  32.      * @param Connection $connection
  33.      * @param                  $tablename
  34.      * @param EntityRepository $columnDefinitionRepository
  35.      * @param                  $prefix
  36.      */
  37.     public function __construct(
  38.         $tablename,
  39.         DatabaseSchemaCache $databaseSchemaCache,
  40.         TableHelper $tableHelper,
  41.         TranslatorInterface $translator
  42.     ) {
  43.         $this->tablename $tablename;
  44.         $this->databaseSchemaCache $databaseSchemaCache;
  45.         $this->tableHelper $tableHelper;
  46.         $this->translator          $translator;
  47.         $this->userRights $this->tableHelper->securityContext->getUser() ? $this->tableHelper->securityContext->getUser()->getRights()->getRights() : null;
  48.     }
  49.     /**
  50.      * @return string
  51.      */
  52.     public function getCaption()
  53.     {
  54.         $tableDefinitions $this->databaseSchemaCache->getTableDefinitions();
  55.         if (isset($tableDefinitions[$this->getTablename()])) {
  56.             if (isset($tableDefinitions[$this->getTablename()]['TableDefinition_Caption'])) {
  57.                 return $tableDefinitions[$this->getTablename()]['TableDefinition_Caption'];
  58.             }
  59.         }
  60.         return $this->getTablename();
  61.     }
  62.     /**
  63.      * Return the referenced columns of other tables
  64.      *
  65.      * @param type $columns
  66.      * @param type $columnName
  67.      * @param ColumnDefinition $columnDefinition
  68.      * @return string
  69.      */
  70.     protected function addReferencedColumns($columns$columnNameColumnDefinition $columnDefinition)
  71.     {
  72.         $type $columnDefinition->getType();
  73.         if (($type === 'link' || $type === 'file' || $type === null ) && (null !== $columnDefinition->getSource())) {
  74.             $source                  $columnDefinition->getSource();
  75.             $sourceTableInfo         $this->tableHelper->getTableInfo($source['table']);
  76.             $sourceColumnDefinitions $sourceTableInfo->getColumnDefinitions();
  77.             /*
  78.              * Hide all referenced columns in view-editor when the user rights (of »TableDefinition_View_Edit_Permission«) are not sufficient. Show all columns if permissions are »NULL«.
  79.              */
  80.             if ($sourceTableInfo->getViewEditPermissions() !== NULL && !$this->tableHelper->securityContext->checkRights($sourceTableInfo->getViewEditPermissions())) {
  81.                 return $columns;
  82.             }
  83.             foreach ($sourceColumnDefinitions as $columnDefinition) {
  84.                 /*
  85.                  * Hide the referenced column in view-editor when the user rights are not sufficient.
  86.                  */
  87.                 if ($this->userRights && !$columnDefinition->checkReadRights($this->userRights)) {
  88.                     continue;
  89.                 }
  90.                 $sourceColumnName $columnName ':' $columnDefinition->getColumn();
  91.                 $columns[]        = $sourceColumnName;
  92.             }
  93.             return $columns;
  94.         }
  95.         return $columns;
  96.     }
  97.     /**
  98.      * @return string|null
  99.      */
  100.     public function getDescription()
  101.     {
  102.         $tableDefinitions $this->databaseSchemaCache->getTableDefinitions();
  103.         if (isset($tableDefinitions[$this->getTablename()])) {
  104.             if (isset($tableDefinitions[$this->getTablename()]['TableDefinition_Description'])) {
  105.                 return $tableDefinitions[$this->getTablename()]['TableDefinition_Description'];
  106.             }
  107.         }
  108.         return null;
  109.     }
  110.     public function hasGenericEditPermission($rights)
  111.     {
  112.         $tableDefinitions $this->databaseSchemaCache->getTableDefinitions();
  113.         if (isset($tableDefinitions[$this->getTablename()])) {
  114.             $user_rights gmp_init($rights);
  115.             $permissions gmp_init($tableDefinitions[$this->getTablename()]['TableDefinition_GenericEdit_Permission']);
  116.             return gmp_cmp(gmp_and($user_rights$permissions), '0') > 0;
  117.         }
  118.         return false;
  119.     }
  120.     /**
  121.      * @inheritdoc
  122.      */
  123.     abstract public function buildFrom(QueryBuilder $builder$mainTableName 'mt');
  124.     /**
  125.      * @inheritdoc
  126.      */
  127.     public function isReadable($column$rights)
  128.     {
  129.         $parts explode(':'$column);
  130.         $numParts count($parts);
  131.         switch ($numParts) {
  132.             case 1:
  133.                 return in_array($parts[0], $this->getReadableColumns($rights));
  134.             case 2:
  135.                 if (!in_array($parts[0], $this->getReadableColumns($rights))) {
  136.                     return false;
  137.                 }
  138.                 $colDef $this->getColumnDefinitions()[$parts[0]];
  139.                 $source $colDef->getSource();
  140.                 if ((null === $source) || !array_key_exists('table'$source)) {
  141.                     return false;
  142.                 }
  143.                 $sourceTableInfo $this->tableHelper->getTableInfo($source['table']);
  144.                 if (null === $sourceTableInfo) {
  145.                     return false;
  146.                 }
  147.                 return in_array($parts[1], $sourceTableInfo->getReadableColumns($rights));
  148.             case 0:
  149.             default:
  150.                 return false;
  151.         }
  152.     }
  153.     /**
  154.      * @inheritdoc
  155.      */
  156.     public function getReadableColumns($rights)
  157.     {
  158.         if (!isset($this->cachedReadableColumns[$rights])) {
  159.             $readableColumns = [];
  160.             $colDefs $this->getColumnDefinitions();
  161.             foreach ($this->getColumns() as $column) {
  162.                 $defName = (new Column($column'view'))->getDefinitionName();
  163.                 if (
  164.                     isset($colDefs[$defName]) &&
  165.                     $colDefs[$defName]->checkReadRights($rights)
  166.                 ) {
  167.                     $readableColumns[] = $column;
  168.                 }
  169.             }
  170.             $this->cachedReadableColumns[$rights] = $readableColumns;
  171.         }
  172.         return $this->cachedReadableColumns[$rights];
  173.     }
  174.     /**
  175.      * @inheritdoc
  176.      */
  177.     abstract public function getColumnDefinitions();
  178.     /**
  179.      * @inheritdoc
  180.      */
  181.     public function getColumnDefinition($viewName)
  182.     {
  183.         $colDefs $this->getColumnDefinitions();
  184.         if (strpos($viewName':') !== false) {
  185.             $parts explode(':'$viewName);
  186.             $column = new Column($parts[0], 'view');
  187.             if (!isset($colDefs[$column->getDefinitionName()])) {
  188.                 throw new \Exception('Missing ColumnDefinition');
  189.             }
  190.             $sourceTableInfo $this->getSourceTableInfo($column->getDefinitionName());
  191.             return $sourceTableInfo->getColumnDefinition($parts[1]);
  192.         } else {
  193.             $column = new Column($viewName'view');    
  194.             return $colDefs[$column->getDefinitionName()];
  195.         }
  196.     }
  197.     /**
  198.      * @inheritdoc
  199.      */
  200.     abstract public function getColumns();
  201.     /**
  202.      * @inheritdoc
  203.      */
  204.     abstract public function getColumnSelectionForView();
  205.     /**
  206.      * @inheritdoc
  207.      */
  208.     public function isWriteable($column$rights)
  209.     {
  210.         return in_array($column$this->getWriteableColumns($rights));
  211.     }
  212.     /**
  213.      * @inheritdoc
  214.      */
  215.     public function getWriteableColumns($rights)
  216.     {
  217.         if (!isset($this->cachedWriteableColumns[$rights])) {
  218.             $writeableColumns = [];
  219.             $colDefs $this->getColumnDefinitions();
  220.             foreach ($this->getColumns() as $column) {
  221.                 $defName = (new Column($column'view'))->getDefinitionName();
  222.                 if (
  223.                     isset($colDefs[$defName]) &&
  224.                     $colDefs[$defName]->checkWriteRights($rights)
  225.                 ) {
  226.                     $writeableColumns[] = $column;
  227.                 }
  228.             }
  229.             $this->cachedWriteableColumns[$rights] = $writeableColumns;
  230.         }
  231.         return $this->cachedWriteableColumns[$rights];
  232.     }
  233.     /**
  234.      * @inheritdoc
  235.      */
  236.     public function getTableConstraints($repo)
  237.     {
  238.         if (!isset($this->cachedTableConstraints)) {
  239.             $this->cachedTableConstraints $this->buildTableConstraints($repo);
  240.         }
  241.         return $this->cachedTableConstraints;
  242.     }
  243.     protected function buildTableConstraints($repo)
  244.     {
  245.         $indices $this->databaseSchemaCache->getIndices($this->getTablename());
  246.         $constraints = [];
  247.         foreach ($indices as $index) {
  248.             if ($index->isUnique()) {
  249.                 $constraints[] = new UniqueConstraint($repo$index->getColumns());
  250.             }
  251.         }
  252.         return $constraints;
  253.     }
  254.     /**
  255.      * @inheritdoc
  256.      */
  257.     public function getTablename()
  258.     {
  259.         return $this->tablename;
  260.     }
  261.     /**
  262.      * @inheritdoc
  263.      */
  264.     public function getColumnConstraints($column)
  265.     {
  266.         if (!isset($this->constraints[$column])) {
  267.             $this->constraints[$column] = $this->buildConstraints($column);
  268.         }
  269.         return $this->constraints[$column];
  270.     }
  271.     /**
  272.      * Automatically build constraints based on the database table description and the values that are set
  273.      * in the ColumnDefinitions.
  274.      *
  275.      * @param $column
  276.      *
  277.      * @return array
  278.      */
  279.     protected function buildConstraints($column)
  280.     {
  281.         // Build database based contraints
  282.         $constraints = [];
  283.         $defColumnName = (new Column($column'view'))->getDefinitionName();
  284.         $columnDesc $this->describeColumn($column);
  285.         if (isset($columnDesc)) {
  286.             if ($columnDesc->getNotnull() && ($defColumnName != $this->getPrimaryKey())) {
  287.                 $constraints[] = new NotNull();
  288.             }
  289.         }
  290.         // Build ColumnDefinitionsConstraints
  291.         $columnDefinitions $this->getColumnDefinitions();
  292.         if (isset($columnDefinitions[$defColumnName])) {
  293.             if (
  294.                 ($columnDefinitions[$defColumnName]->getType() == 'datetime') ||
  295.                 ($columnDefinitions[$defColumnName]->getType() == 'date')
  296.             ) {
  297.                 // Add datetime constraint
  298.                 $constraints[] = new DateTimeConstraint();
  299.             }
  300.         }
  301.         return $constraints;
  302.     }
  303.     /**
  304.      * @inheritdoc
  305.      */
  306.     public function describeColumn($column)
  307.     {
  308.         if (!in_array($column$this->getColumns())) {
  309.             return null;
  310.         }
  311.         $columnDefinitions $this->getColumnDefinitions();
  312.         $defColumnName = (new Column($column'view'))->getDefinitionName();
  313.         if (!isset($columnDefinitions[$defColumnName])) {
  314.             return null;
  315.         }
  316.         if ($columnDefinitions[$defColumnName]->isVirtual()) {
  317.             return null;
  318.         }
  319.         $tablename $columnDefinitions[$defColumnName]->getTable();
  320.         $columns $this->getColumnsForTable($tablename);
  321.         $lowerColumnName strtolower($defColumnName);
  322.         if (isset($columns[$lowerColumnName])) {
  323.             return $columns[$lowerColumnName];
  324.         }
  325.         return null;
  326.     }
  327.     /**
  328.      * @param $tablename
  329.      *
  330.      * @return \Doctrine\DBAL\Schema\Column[]
  331.      */
  332.     protected function getColumnsForTable($tablename)
  333.     {
  334.         return $this->databaseSchemaCache->getColumnsForTable($tablename);
  335.     }
  336.     /**
  337.      * @inheritdoc
  338.      */
  339.     abstract public function getPrimaryKey();
  340.     public function getSourceTableInfo($column)
  341.     {
  342.         $colDefs $this->getColumnDefinitions();
  343.         if (!array_key_exists($column$colDefs)) {
  344.             return null;
  345.         }
  346.         $colDef $colDefs[$column];
  347.         $source $colDef->getSource();
  348.         if ((null === $source) || (!array_key_exists('table'$source))) {
  349.             return null;
  350.         }
  351.         return $this->tableHelper->getTableInfo($source['table']);
  352.     }
  353.     public function getLabelForViewColumn($columnName)
  354.     {
  355.         $parts explode(':'$columnName);
  356.         $numParts count($parts);
  357.         switch ($numParts) {
  358.             case 1:
  359.                 $column = new Column($columnName'view');
  360.                 $colDefs $this->getColumnDefinitions();
  361.                 if (!array_key_exists($column->getDefinitionName(), $colDefs)) {
  362.                     return $columnName;
  363.                 }
  364.                 /*
  365.                  * Return the caption and translate it at once.
  366.                  */
  367.                 return $this->translator->trans($colDefs[$column->getDefinitionName()]->getCaption());
  368.             case 2:
  369.                 $name $this->getLabelForViewColumn($parts[0]);
  370.                 $column = new Column($parts[0], 'view');
  371.                 $sourceTableInfo $this->getSourceTableInfo($column->getDefinitionName());
  372.                 $name $name.': '.(is_null($sourceTableInfo) ? '?' $sourceTableInfo->getLabelForViewColumn(
  373.                         $parts[1]
  374.                     ));
  375.                 return $name;
  376.         }
  377.     }
  378.     public function getViewEditPermissions() {
  379.         $tableDefinitions $this->databaseSchemaCache->getTableDefinitions();
  380.         if (isset($tableDefinitions[$this->getTablename()])) {
  381.             return $tableDefinitions[$this->getTablename()]['TableDefinition_View_Edit_Permission'];
  382.         }
  383.         return null;
  384.     }
  385. }