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.             
  94.             return $columns;
  95.         }
  96.         return $columns;
  97.     }
  98.     /**
  99.      * @return string|null
  100.      */
  101.     public function getDescription()
  102.     {
  103.         $tableDefinitions $this->databaseSchemaCache->getTableDefinitions();
  104.         if (isset($tableDefinitions[$this->getTablename()])) {
  105.             if (isset($tableDefinitions[$this->getTablename()]['TableDefinition_Description'])) {
  106.                 return $tableDefinitions[$this->getTablename()]['TableDefinition_Description'];
  107.             }
  108.         }
  109.         return null;
  110.     }
  111.     public function hasGenericEditPermission($rights)
  112.     {
  113.         $tableDefinitions $this->databaseSchemaCache->getTableDefinitions();
  114.         if (isset($tableDefinitions[$this->getTablename()])) {
  115.             $user_rights gmp_init($rights);
  116.             $permissions gmp_init($tableDefinitions[$this->getTablename()]['TableDefinition_GenericEdit_Permission']);
  117.             return gmp_cmp(gmp_and($user_rights$permissions), '0') > 0;
  118.         }
  119.         return false;
  120.     }
  121.     /**
  122.      * @inheritdoc
  123.      */
  124.     abstract public function buildFrom(QueryBuilder $builder$mainTableName 'mt');
  125.     /**
  126.      * @inheritdoc
  127.      */
  128.     public function isReadable($column$rights)
  129.     {
  130.         $parts explode(':'$column);
  131.         $numParts count($parts);
  132.         switch ($numParts) {
  133.             case 1:
  134.                 return in_array($parts[0], $this->getReadableColumns($rights));
  135.             case 2:
  136.                 if (!in_array($parts[0], $this->getReadableColumns($rights))) {
  137.                     return false;
  138.                 }
  139.                 $colDef $this->getColumnDefinitions()[$parts[0]];
  140.                 $source $colDef->getSource();
  141.                 if ((null === $source) || !array_key_exists('table'$source)) {
  142.                     return false;
  143.                 }
  144.                 $sourceTableInfo $this->tableHelper->getTableInfo($source['table']);
  145.                 if (null === $sourceTableInfo) {
  146.                     return false;
  147.                 }
  148.                 return in_array($parts[1], $sourceTableInfo->getReadableColumns($rights));
  149.             case 0:
  150.             default:
  151.                 return false;
  152.         }
  153.     }
  154.     /**
  155.      * @inheritdoc
  156.      */
  157.     public function getReadableColumns($rights)
  158.     {
  159.         if (!isset($this->cachedReadableColumns[$rights])) {
  160.             $readableColumns = [];
  161.             $colDefs $this->getColumnDefinitions();
  162.             foreach ($this->getColumns() as $column) {
  163.                 $defName = (new Column($column'view'))->getDefinitionName();
  164.                 if (
  165.                     isset($colDefs[$defName]) &&
  166.                     $colDefs[$defName]->checkReadRights($rights)
  167.                 ) {
  168.                     $readableColumns[] = $column;
  169.                 }
  170.             }
  171.             $this->cachedReadableColumns[$rights] = $readableColumns;
  172.         }
  173.         return $this->cachedReadableColumns[$rights];
  174.     }
  175.     /**
  176.      * @inheritdoc
  177.      */
  178.     abstract public function getColumnDefinitions();
  179.     /**
  180.      * @inheritdoc
  181.      */
  182.     public function getColumnDefinition($viewName)
  183.     {
  184.         $colDefs $this->getColumnDefinitions();
  185.         if (strpos($viewName':') !== false) {
  186.             $parts explode(':'$viewName);
  187.             $column = new Column($parts[0], 'view');
  188.             if (!isset($colDefs[$column->getDefinitionName()])) {
  189.                 throw new \Exception('Missing ColumnDefinition');
  190.             }
  191.             $sourceTableInfo $this->getSourceTableInfo($column->getDefinitionName());
  192.             return $sourceTableInfo->getColumnDefinition($parts[1]);
  193.         } else {
  194.             $column = new Column($viewName'view');
  195.             return $colDefs[$column->getDefinitionName()];
  196.         }
  197.     }
  198.     /**
  199.      * @inheritdoc
  200.      */
  201.     abstract public function getColumns();
  202.     /**
  203.      * @inheritdoc
  204.      */
  205.     abstract public function getColumnSelectionForView();
  206.     /**
  207.      * @inheritdoc
  208.      */
  209.     public function isWriteable($column$rights)
  210.     {
  211.         return in_array($column$this->getWriteableColumns($rights));
  212.     }
  213.     /**
  214.      * @inheritdoc
  215.      */
  216.     public function getWriteableColumns($rights)
  217.     {
  218.         if (!isset($this->cachedWriteableColumns[$rights])) {
  219.             $writeableColumns = [];
  220.             $colDefs $this->getColumnDefinitions();
  221.             foreach ($this->getColumns() as $column) {
  222.                 $defName = (new Column($column'view'))->getDefinitionName();
  223.                 if (
  224.                     isset($colDefs[$defName]) &&
  225.                     $colDefs[$defName]->checkWriteRights($rights)
  226.                 ) {
  227.                     $writeableColumns[] = $column;
  228.                 }
  229.             }
  230.             $this->cachedWriteableColumns[$rights] = $writeableColumns;
  231.         }
  232.         return $this->cachedWriteableColumns[$rights];
  233.     }
  234.     /**
  235.      * @inheritdoc
  236.      */
  237.     public function getTableConstraints($repo)
  238.     {
  239.         if (!isset($this->cachedTableConstraints)) {
  240.             $this->cachedTableConstraints $this->buildTableConstraints($repo);
  241.         }
  242.         return $this->cachedTableConstraints;
  243.     }
  244.     protected function buildTableConstraints($repo)
  245.     {
  246.         $indices $this->databaseSchemaCache->getIndices($this->getTablename());
  247.         $constraints = [];
  248.         foreach ($indices as $index) {
  249.             if ($index->isUnique()) {
  250.                 $constraints[] = new UniqueConstraint($repo$index->getColumns());
  251.             }
  252.         }
  253.         return $constraints;
  254.     }
  255.     /**
  256.      * @inheritdoc
  257.      */
  258.     public function getTablename()
  259.     {
  260.         return $this->tablename;
  261.     }
  262.     /**
  263.      * @inheritdoc
  264.      */
  265.     public function getColumnConstraints($column)
  266.     {
  267.         if (!isset($this->constraints[$column])) {
  268.             $this->constraints[$column] = $this->buildConstraints($column);
  269.         }
  270.         return $this->constraints[$column];
  271.     }
  272.     /**
  273.      * Automatically build constraints based on the database table description and the values that are set
  274.      * in the ColumnDefinitions.
  275.      *
  276.      * @param $column
  277.      *
  278.      * @return array
  279.      */
  280.     protected function buildConstraints($column)
  281.     {
  282.         // Build database based contraints
  283.         $constraints = [];
  284.         $defColumnName = (new Column($column'view'))->getDefinitionName();
  285.         $columnDesc $this->describeColumn($column);
  286.         if (isset($columnDesc)) {
  287.             if ($columnDesc->getNotnull() && ($defColumnName != $this->getPrimaryKey())) {
  288.                 $constraints[] = new NotNull();
  289.             }
  290.         }
  291.         // Build ColumnDefinitionsConstraints
  292.         $columnDefinitions $this->getColumnDefinitions();
  293.         if (isset($columnDefinitions[$defColumnName])) {
  294.             if (
  295.                 ($columnDefinitions[$defColumnName]->getType() == 'datetime') ||
  296.                 ($columnDefinitions[$defColumnName]->getType() == 'date')
  297.             ) {
  298.                 // Add datetime constraint
  299.                 $constraints[] = new DateTimeConstraint();
  300.             }
  301.         }
  302.         return $constraints;
  303.     }
  304.     /**
  305.      * @inheritdoc
  306.      */
  307.     public function describeColumn($column)
  308.     {
  309.         if (!in_array($column$this->getColumns())) {
  310.             return null;
  311.         }
  312.         $columnDefinitions $this->getColumnDefinitions();
  313.         $defColumnName = (new Column($column'view'))->getDefinitionName();
  314.         if (!isset($columnDefinitions[$defColumnName])) {
  315.             return null;
  316.         }
  317.         if ($columnDefinitions[$defColumnName]->isVirtual()) {
  318.             return null;
  319.         }
  320.         $tablename $columnDefinitions[$defColumnName]->getTable();
  321.         $columns $this->getColumnsForTable($tablename);
  322.         $lowerColumnName strtolower($defColumnName);
  323.         if (isset($columns[$lowerColumnName])) {
  324.             return $columns[$lowerColumnName];
  325.         }
  326.         return null;
  327.     }
  328.     /**
  329.      * @param $tablename
  330.      *
  331.      * @return \Doctrine\DBAL\Schema\Column[]
  332.      */
  333.     protected function getColumnsForTable($tablename)
  334.     {
  335.         return $this->databaseSchemaCache->getColumnsForTable($tablename);
  336.     }
  337.     /**
  338.      * @inheritdoc
  339.      */
  340.     abstract public function getPrimaryKey();
  341.     public function getSourceTableInfo($column)
  342.     {
  343.         $colDefs $this->getColumnDefinitions();
  344.         if (!array_key_exists($column$colDefs)) {
  345.             return null;
  346.         }
  347.         $colDef $colDefs[$column];
  348.         $source $colDef->getSource();
  349.         if ((null === $source) || (!array_key_exists('table'$source))) {
  350.             return null;
  351.         }
  352.         return $this->tableHelper->getTableInfo($source['table']);
  353.     }
  354.     public function getLabelForViewColumn($columnName)
  355.     {
  356.         $parts explode(':'$columnName);
  357.         $numParts count($parts);
  358.         switch ($numParts) {
  359.             case 1:
  360.                 $column = new Column($columnName'view');
  361.                 $colDefs $this->getColumnDefinitions();
  362.                 if (!array_key_exists($column->getDefinitionName(), $colDefs)) {
  363.                     return $columnName;
  364.                 }
  365.                 /*
  366.                  * Return the caption and translate it at once.
  367.                  */
  368.                 return $this->translator->trans($colDefs[$column->getDefinitionName()]->getCaption());
  369.             case 2:
  370.                 $name $this->getLabelForViewColumn($parts[0]);
  371.                 $column = new Column($parts[0], 'view');
  372.                 $sourceTableInfo $this->getSourceTableInfo($column->getDefinitionName());
  373.                 $name $name.': '.(is_null($sourceTableInfo) ? '?' $sourceTableInfo->getLabelForViewColumn(
  374.                         $parts[1]
  375.                     ));
  376.                 return $name;
  377.         }
  378.     }
  379.     public function getViewEditPermissions() {
  380.         $tableDefinitions $this->databaseSchemaCache->getTableDefinitions();
  381.         if (isset($tableDefinitions[$this->getTablename()])) {
  382.             return $tableDefinitions[$this->getTablename()]['TableDefinition_View_Edit_Permission'];
  383.         }
  384.         return null;
  385.     }
  386. }