Esempio n. 1
0
 public function testBetweenNumbers()
 {
     $this->list->filter(new Between("FavouriteNumber", 10, 20));
     $this->assertCount(2, $this->list);
     $this->assertEquals("John", $this->list[0]->Forename);
     $this->assertEquals("Mary", $this->list[1]->Forename);
 }
Esempio n. 2
0
 public function testCanFilterOnRelatedModelProperties()
 {
     $gcd = new Company();
     $gcd->CompanyName = "GCD";
     $gcd->save();
     $widgetCo = new Company();
     $widgetCo->CompanyName = "Widgets";
     $widgetCo->save();
     $example = new User();
     $example->Username = "******";
     $widgetCo->Users->Append($example);
     $example = new User();
     $example->Username = "******";
     $gcd->Users->Append($example);
     $example = new User();
     $example->Username = "******";
     $widgetCo->Users->Append($example);
     $example = new User();
     $example->Username = "******";
     $gcd->Users->Append($example);
     $list = new Collection("Rhubarb\\Stem\\Tests\\Fixtures\\User");
     $list->filter(new Equals("Company.CompanyName", "GCD"));
     $this->assertCount(2, $list);
     $this->assertEquals("b", $list[0]->Username);
     $this->assertEquals("d", $list[1]->Username);
 }
Esempio n. 3
0
 public function testFiltersOnOtherColumn()
 {
     $filter = new \Rhubarb\Stem\Filters\LessThan("Forename", "@{Surname}", true);
     $this->list->filter($filter);
     $this->assertCount(1, $this->list);
     $this->assertEquals("Morris", $this->list[0]->Surname);
 }
Esempio n. 4
0
 public function testFiltersMatchingRows()
 {
     $filter = new \Rhubarb\Stem\Filters\Equals("Forename", "Tom");
     $this->list->filter($filter);
     $this->assertCount(1, $this->list);
     $this->assertEquals("Thumb", $this->list[0]->Surname);
 }
Esempio n. 5
0
 public function calculateByIteration(Collection $collection)
 {
     // If the list hasn't been fetched, sizeof() will still calculate it with an Aggregate,
     // so we need for force the list to be fetched now so the sizeof() can calculate by iteration
     $collection->fetchList();
     return sizeof($collection);
 }
 public function testSumIsCalculatedOnRepository()
 {
     $examples = new Collection("Company");
     list($sumTotal) = $examples->calculateAggregates([new MySqlCountDistinct("CompanyName")]);
     $this->assertEquals(2, $sumTotal);
     $lastStatement = MySql::getPreviousStatement(false);
     $this->assertContains("COUNT( DISTINCT `CompanyName` ) AS `DistinctCountOfCompanyName`", $lastStatement);
 }
Esempio n. 7
0
 public function testSumIsCalculatedOnRepository()
 {
     $examples = new Collection("Company");
     list($sumTotal) = $examples->calculateAggregates([new MySqlAverage("Balance")]);
     $this->assertEquals(3, $sumTotal);
     $lastStatement = MySql::getPreviousStatement(false);
     $this->assertContains("AVG( `Balance` ) AS `AverageOfBalance`", $lastStatement);
 }
 public function testFiltersAlpha()
 {
     $filter = new \Rhubarb\Stem\Filters\GreaterThan("Forename", "Mary", true);
     $this->list->filter($filter);
     $this->assertCount(2, $this->list);
     $filter = new \Rhubarb\Stem\Filters\GreaterThan("Forename", "Mary", false);
     $this->list->filter($filter);
     $this->assertCount(1, $this->list);
     $this->assertContains("Tom", $this->list[0]->Forename);
 }
Esempio n. 9
0
 /**
  * Returns an array of unique identifiers to filter from the list.
  *
  * This will be an empty array if a repository has used this filter to do it's filtering.
  *
  * @param Collection $list The data list to filter.
  * @return array
  */
 public final function getUniqueIdentifiersToFilter(Collection $list)
 {
     if ($this->wasFilteredByRepository()) {
         return [];
     }
     $list->disableRanging();
     $filtered = $this->doGetUniqueIdentifiersToFilter($list);
     $list->enableRanging();
     return $filtered;
 }
Esempio n. 10
0
 public function testFiltersCaseSensitive()
 {
     $filter = new \Rhubarb\Stem\Filters\Contains("Forename", "Jo", true);
     $this->list->filter($filter);
     $this->assertCount(1, $this->list);
     $this->assertContains("John", $this->list[0]->Forename);
     $filter = new \Rhubarb\Stem\Filters\Contains("Forename", "oH", true);
     $this->list->filter($filter);
     $this->assertCount(0, $this->list);
 }
Esempio n. 11
0
 public function testFiltersCaseSensitive()
 {
     $filter = new \Rhubarb\Stem\Filters\EndsWith("Forename", "ry", true);
     $this->list->filter($filter);
     $this->assertCount(1, $this->list);
     $this->assertContains("Mary", $this->list[0]->Forename);
     $filter = new \Rhubarb\Stem\Filters\EndsWith("Forename", "RY", true);
     $this->list->filter($filter);
     $this->assertCount(0, $this->list);
 }
Esempio n. 12
0
 public function testFilters()
 {
     $filter = new \Rhubarb\Stem\Filters\OneOf("Forename", ["Cuthbert", "Dibble", "Grub", "Pugh"]);
     $this->list->filter($filter);
     $this->assertCount(5, $this->list);
     $this->assertContains("Pugh", $this->list[0]->Forename);
     $filter = new \Rhubarb\Stem\Filters\OneOf("Forename", ["Cuthbert", "Dibble", "Grub"]);
     $this->list->filter($filter);
     $this->assertCount(3, $this->list);
     $this->assertContains("Cuthbert", $this->list[0]->Forename);
 }
Esempio n. 13
0
 /**
  * Converts the comparison value used in the constructor to one which can be compared against that returned
  * by the relevant model.
  *
  * @param $rawComparisonValue
  * @param Collection $list
  * @return mixed
  */
 protected final function getTransformedComparisonValue($rawComparisonValue, Collection $list)
 {
     $exampleObject = SolutionSchema::getModel($list->getModelClassName());
     $columnSchema = $exampleObject->getColumnSchemaForColumnReference($this->columnName);
     if ($columnSchema != null) {
         $closure = $columnSchema->getTransformIntoModelData();
         if ($closure !== null) {
             $rawComparisonValue = $closure($rawComparisonValue);
         }
     }
     return $rawComparisonValue;
 }
 function testFiltersWithGroupedGroup()
 {
     $filterGroup1 = new \Rhubarb\Stem\Filters\Group("And");
     $filterGroup1->addFilters(new \Rhubarb\Stem\Filters\Contains("Forename", "Jo", true), new \Rhubarb\Stem\Filters\Contains("Surname", "Jo", true));
     $filterGroup2 = new \Rhubarb\Stem\Filters\Group("Or");
     $filterGroup2->addFilters(new \Rhubarb\Stem\Filters\Contains("Surname", "Luc", true), new \Rhubarb\Stem\Filters\LessThan("DateOfBirth", "1980-01-01", true));
     $filterGroup = new \Rhubarb\Stem\Filters\Group("Or");
     $filterGroup->addFilters($filterGroup1, $filterGroup2);
     $this->list->Not($filterGroup);
     $this->assertCount(1, $this->list);
     $this->assertContains("Smithe", $this->list[0]->Surname);
 }
Esempio n. 15
0
 public function testSumIsCalculatedOnRepository()
 {
     $examples = new Collection("Company");
     list($sumTotal) = $examples->calculateAggregates([new MySqlSum("Balance")]);
     $this->assertEquals(6, $sumTotal);
     $lastStatement = MySql::getPreviousStatement(false);
     $this->assertContains("SUM( `Balance` ) AS `SumOfBalance`", $lastStatement);
     $examples = new Collection("Company");
     $examples->filter(new GreaterThan("Balance", 1));
     list($sumTotal) = $examples->calculateAggregates(new MySqlSum("Balance"));
     $this->assertEquals(5, $sumTotal);
     $lastStatement = MySql::getPreviousStatement(false);
     $this->assertContains("SUM( `Balance` ) AS `SumOfBalance`", $lastStatement);
     $this->assertContains("WHERE `tblCompany`.`Balance` > ", $lastStatement);
 }
 protected function getCurrentlyAvailableSelectionItems()
 {
     if ($this->Phrase == "") {
         return [];
     }
     $class = $this->modelClassName;
     $list = new Collection($class);
     $filter = $this->getCollectionFilter($this->Phrase);
     $list->filter($filter);
     $results = [];
     foreach ($list as $item) {
         $result = $this->makeItem($item->getUniqueIdentifier(), $item->getLabel(), $this->getDataForItem($item));
         $results[] = $result;
     }
     return $results;
 }
 public function login($username, $password)
 {
     // We don't allow spaces around our usernames and passwords
     $username = trim($username);
     $password = trim($password);
     if ($username == "") {
         throw new LoginFailedException();
     }
     $list = new Collection($this->modelClassName);
     $list->filter(new Equals($this->usernameColumnName, $username));
     if (!sizeof($list)) {
         throw new LoginFailedException();
     }
     $hashProvider = HashProvider::getHashProvider();
     // There should only be one user matching the username. It would be possible to support
     // unique *combinations* of username and password but it's a potential security issue and
     // could trip us up when supporting the project.
     if (sizeof($list) > 1) {
         throw new LoginFailedException();
     }
     $user = $list[0];
     $this->checkUserIsPermitted($user);
     // Test the password matches.
     $userPasswordHash = $user[$this->passwordColumnName];
     if ($hashProvider->compareHash($password, $userPasswordHash)) {
         // Matching login - but is it enabled?
         if ($this->isModelActive($user)) {
             $this->LoggedIn = true;
             $this->LoggedInUserIdentifier = $user->getUniqueIdentifier();
             $this->storeSession();
             return true;
         } else {
             throw new LoginDisabledException();
         }
     }
     throw new LoginFailedException();
 }
Esempio n. 18
0
 function testXOR()
 {
     $filterOne = new \Rhubarb\Stem\Filters\Contains("Forename", "Jo", true);
     $filterTwo = new \Rhubarb\Stem\Filters\Contains("Surname", "Jo", true);
     $filterAnd = new \Rhubarb\Stem\Filters\Group("And");
     $filterAnd->addFilters($filterOne, $filterTwo);
     $filterOr = new \Rhubarb\Stem\Filters\Group("Or");
     $filterOr->addFilters($filterOne, $filterTwo);
     $filterNotAnd = new \Rhubarb\Stem\Filters\Not($filterAnd);
     $filterXor = new \Rhubarb\Stem\Filters\Group("And");
     $filterXor->addFilters($filterNotAnd, $filterOr);
     $this->list->filter($filterXor);
     $this->assertCount(2, $this->list);
     $this->assertContains("Luc", $this->list[0]->Surname);
 }
Esempio n. 19
0
 public function testSum()
 {
     $examples = new Collection("Example");
     list($sumTotal) = $examples->calculateAggregates([new Sum("CompanyID")]);
     $this->assertEquals(6, $sumTotal);
 }
Esempio n. 20
0
 public function testEmptyCandidatesArray()
 {
     $filter = new InArray("Surname", []);
     $this->list->filter($filter);
     $this->assertCount(0, $this->list);
 }
Esempio n. 21
0
 protected function getManualSortsRequiredForList(Collection $list)
 {
     $sorts = $list->getSorts();
     $sorts = array_diff_key($sorts, array_flip($this->lastSortsUsed));
     return $sorts;
 }
Esempio n. 22
0
 /**
  * Returns the Collection of models matching the given filter.
  *
  * @param Filter $filter
  * @return Collection
  */
 public static function find(Filter $filter = null)
 {
     $modelClass = get_called_class();
     $collections = new Collection($modelClass);
     if ($filter !== null) {
         $collections->filter($filter);
     }
     return $collections;
 }
Esempio n. 23
0
 public function fetchFor(Model $relatedTo)
 {
     $targetModel = SolutionSchema::getModel($this->targetModelName);
     $sourceValue = $relatedTo[$this->getSourceColumnName()];
     $targetColumnName = $this->getTargetColumnName();
     if ($targetColumnName == $targetModel->UniqueIdentifierColumnName) {
         if ($sourceValue === null) {
             return null;
         }
         try {
             return SolutionSchema::getModel($this->targetModelName, $sourceValue);
         } catch (RecordNotFoundException $er) {
             return null;
         }
     } else {
         $collection = new Collection($this->targetModelName);
         $collection->filter(new Equals($targetColumnName, $sourceValue));
         if (sizeof($collection) > 0) {
             return $collection[0];
         }
     }
     return null;
 }
Esempio n. 24
0
 /**
  * Returns the sorts needed for manual sorting.
  *
  * @param Collection $list
  * @return array
  */
 protected function getManualSortsRequiredForList(Collection $list)
 {
     return $list->getSorts();
 }
 public function testLimits()
 {
     MySql::executeStatement("TRUNCATE TABLE tblCompany");
     $company = new Company();
     $repos = $company->getRepository();
     $repos->clearObjectCache();
     $company = new Company();
     $company->CompanyName = "A";
     $company->save();
     $company = new Company();
     $company->CompanyName = "B";
     $company->save();
     $company = new Company();
     $company->CompanyName = "B";
     $company->save();
     $company = new Company();
     $company->CompanyName = "B";
     $company->save();
     $company = new Company();
     $company->CompanyName = "C";
     $company->save();
     $company = new Company();
     $company->CompanyName = "D";
     $company->save();
     $list = new Collection("\\Rhubarb\\Stem\\Tests\\Fixtures\\Company");
     $list->setRange(2, 6);
     $this->assertCount(6, $list);
     $this->assertEquals("C", $list[2]->CompanyName);
     $sql = MySql::getPreviousStatement(true);
     $this->assertContains("LIMIT 2, 6", $sql);
     // Sorting by a computed column should mean that limits are no longer used.
     $list->addSort("CompanyIDSquared", true);
     $this->assertCount(6, $list);
     $this->assertEquals("C", $list[2]->CompanyName);
     $sql = MySql::getPreviousStatement();
     $this->assertNotContains("LIMIT 2, 6", $sql);
     $sql = MySql::getPreviousStatement(true);
     $this->assertNotContains("LIMIT 2, 6", $sql);
 }
Esempio n. 26
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;
 }
Esempio n. 27
0
 public function testIsNullFilter()
 {
     MySql::executeStatement("TRUNCATE TABLE tblCompany");
     $company = new \Rhubarb\Stem\Tests\Fixtures\Company();
     $company->CompanyName = "GCD";
     $company->save();
     $companies = new Collection('Rhubarb\\Stem\\Tests\\Fixtures\\Company');
     $companies->filter(new Equals("CompanyName", null));
     $this->assertEquals(0, $companies->count());
     $companies = new Collection('Rhubarb\\Stem\\Tests\\Fixtures\\Company');
     $companies->filter(new Equals("ProjectCount", null));
     $this->assertEquals(1, $companies->count());
 }