Example #1
0
 /**
  * Get's the unique identifiers required for the matching filters and loads the data into
  * the cache for performance reasons.
  *
  * @param Collection $list
  * @param int $unfetchedRowCount
  * @param array $relationshipNavigationPropertiesToAutoHydrate
  * @return array
  */
 public function getUniqueIdentifiersForDataList(Collection $list, &$unfetchedRowCount = 0, $relationshipNavigationPropertiesToAutoHydrate = [])
 {
     $this->lastSortsUsed = [];
     $schema = $this->schema;
     $table = $schema->schemaName;
     $whereClause = "";
     $filter = $list->getFilter();
     $namedParams = [];
     $propertiesToAutoHydrate = $relationshipNavigationPropertiesToAutoHydrate;
     $filteredExclusivelyByRepository = true;
     if ($filter !== null) {
         $filterSql = $filter->filterWithRepository($this, $namedParams, $propertiesToAutoHydrate);
         if ($filterSql != "") {
             $whereClause .= " WHERE " . $filterSql;
         }
         $filteredExclusivelyByRepository = $filter->wasFilteredByRepository();
     }
     $relationships = SolutionSchema::getAllRelationshipsForModel($this->getModelClass());
     $aggregateColumnClause = "";
     $aggregateColumnClauses = [];
     $aggregateColumnAliases = [];
     $aggregateRelationshipPropertiesToAutoHydrate = [];
     foreach ($list->getAggregates() as $aggregate) {
         $clause = $aggregate->aggregateWithRepository($this, $aggregateRelationshipPropertiesToAutoHydrate);
         if ($clause != "") {
             $aggregateColumnClauses[] = $clause;
             $aggregateColumnAliases[] = $aggregate->getAlias();
         }
     }
     if (sizeof($aggregateColumnClauses) > 0) {
         $aggregateColumnClause = ", " . implode(", ", $aggregateColumnClauses);
     }
     $aggregateRelationshipPropertiesToAutoHydrate = array_unique($aggregateRelationshipPropertiesToAutoHydrate);
     $joins = [];
     $groups = [];
     foreach ($aggregateRelationshipPropertiesToAutoHydrate as $joinRelationship) {
         /**
          * @var OneToMany $relationship
          */
         $relationship = $relationships[$joinRelationship];
         $targetModelName = $relationship->getTargetModelName();
         $targetModelClass = SolutionSchema::getModelClass($targetModelName);
         /**
          * @var Model $targetModel
          */
         $targetModel = new $targetModelClass();
         $targetSchema = $targetModel->getSchema();
         $joins[] = "LEFT JOIN `{$targetSchema->schemaName}` AS `{$joinRelationship}` ON `{$this->schema->schemaName}`.`" . $relationship->getSourceColumnName() . "` = `{$joinRelationship}`.`" . $relationship->getTargetColumnName() . "`";
         $groups[] = "`{$table}`.`" . $relationship->getSourceColumnName() . '`';
     }
     $joinColumns = [];
     $joinOriginalToAliasLookup = [];
     $joinColumnsByModel = [];
     $sorts = $list->getSorts();
     $possibleSorts = [];
     $columns = $schema->getColumns();
     foreach ($sorts as $columnName => $ascending) {
         if (!isset($columns[$columnName])) {
             // If this is a one to one relationship we can still sort by using auto hydration.
             $parts = explode(".", $columnName);
             $relationshipProperty = $parts[0];
             $escapedColumnName = '`' . implode('`.`', $parts) . '`';
             if (isset($relationships[$relationshipProperty]) && $relationships[$relationshipProperty] instanceof OneToOne) {
                 $propertiesToAutoHydrate[] = $relationshipProperty;
                 $possibleSorts[] = $escapedColumnName . " " . ($ascending ? "ASC" : "DESC");
                 $this->lastSortsUsed[] = $columnName;
             } else {
                 // If the request sorts contain any that we can't sort by we must only sort by those
                 // after this column.
                 $possibleSorts = [];
                 $this->lastSortsUsed = [];
             }
         } else {
             $possibleSorts[] = '`' . str_replace('.', '`.`', $columnName) . "` " . ($ascending ? "ASC" : "DESC");
             $this->lastSortsUsed[] = $columnName;
         }
     }
     $propertiesToAutoHydrate = array_unique($propertiesToAutoHydrate);
     foreach ($propertiesToAutoHydrate as $joinRelationship) {
         /**
          * @var OneToMany $relationship
          */
         $relationship = $relationships[$joinRelationship];
         $targetModelName = $relationship->getTargetModelName();
         $targetModelClass = SolutionSchema::getModelClass($targetModelName);
         /**
          * @var Model $targetModel
          */
         $targetModel = new $targetModelClass();
         $targetSchema = $targetModel->getSchema();
         $columns = $targetSchema->getColumns();
         foreach ($columns as $columnName => $column) {
             $joinColumns[$targetModelName . $columnName] = "`{$joinRelationship}`.`{$columnName}`";
             $joinOriginalToAliasLookup[$targetModelName . "." . $columnName] = $targetModelName . $columnName;
             if (!isset($joinColumnsByModel[$targetModelName])) {
                 $joinColumnsByModel[$targetModelName] = [];
             }
             $joinColumnsByModel[$targetModelName][$targetModelName . $columnName] = $columnName;
         }
         $joins[] = "LEFT JOIN `{$targetSchema->schemaName}` AS `{$joinRelationship}` ON `{$this->schema->schemaName}`.`" . $relationship->getSourceColumnName() . "` = `{$joinRelationship}`.`" . $relationship->getTargetColumnName() . "`";
     }
     $joinString = "";
     $joinColumnClause = "";
     if (sizeof($joins)) {
         $joinString = " " . implode(" ", $joins);
         $joinClauses = [];
         foreach ($joinColumns as $aliasName => $columnName) {
             $joinClauses[] = "{$columnName} AS `{$aliasName}`";
         }
         if (sizeof($joinClauses)) {
             $joinColumnClause = ", " . implode(", ", $joinClauses);
         }
     }
     $groupClause = "";
     if (sizeof($groups)) {
         $groupClause = " GROUP BY " . implode(", ", $groups);
     }
     $orderBy = "";
     if (sizeof($possibleSorts)) {
         $orderBy .= " ORDER BY " . implode(", ", $possibleSorts);
     }
     $sql = "SELECT `{$table}`.*{$joinColumnClause}{$aggregateColumnClause} FROM `{$table}`" . $joinString . $whereClause . $groupClause . $orderBy;
     $ranged = false;
     if ($filteredExclusivelyByRepository && sizeof($possibleSorts) == sizeof($sorts)) {
         $range = $list->getRange();
         if ($range != false) {
             $ranged = true;
             $sql .= " LIMIT " . $range[0] . ", " . $range[1];
             $sql = preg_replace("/^SELECT /", "SELECT SQL_CALC_FOUND_ROWS ", $sql);
         }
     }
     $statement = self::executeStatement($sql, $namedParams);
     $results = $statement->fetchAll(\PDO::FETCH_ASSOC);
     $uniqueIdentifiers = [];
     if (sizeof($joinColumns)) {
         foreach ($joinColumnsByModel as $joinModel => $modelJoinedColumns) {
             $model = SolutionSchema::getModel($joinModel);
             $repository = $model->getRepository();
             foreach ($results as &$result) {
                 $aliasedUniqueIdentifierColumnName = $joinOriginalToAliasLookup[$joinModel . "." . $model->UniqueIdentifierColumnName];
                 if (isset($result[$aliasedUniqueIdentifierColumnName]) && !isset($repository->cachedObjectData[$result[$aliasedUniqueIdentifierColumnName]])) {
                     $joinedData = array_intersect_key($result, $modelJoinedColumns);
                     $modelData = array_combine($modelJoinedColumns, $joinedData);
                     $repository->cachedObjectData[$modelData[$model->UniqueIdentifierColumnName]] = $modelData;
                 }
                 $result = array_diff_key($result, $modelJoinedColumns);
             }
             unset($result);
         }
     }
     foreach ($results as $result) {
         $uniqueIdentifier = $result[$schema->uniqueIdentifierColumnName];
         $result = $this->transformDataFromRepository($result);
         // Store the data in the cache and add the unique identifier to our list.
         $this->cachedObjectData[$uniqueIdentifier] = $result;
         $uniqueIdentifiers[] = $uniqueIdentifier;
     }
     if ($ranged) {
         $foundRows = Mysql::returnSingleValue("SELECT FOUND_ROWS()");
         $unfetchedRowCount = $foundRows - sizeof($uniqueIdentifiers);
     }
     return $uniqueIdentifiers;
 }