Skip to content

Commit

Permalink
Merge pull request #119 from bakaphp/0.7-improve-sort-validation
Browse files Browse the repository at this point in the history
  • Loading branch information
kaioken authored Apr 26, 2021
2 parents d0fc7c5 + 9979385 commit 21d9a77
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 54 deletions.
23 changes: 18 additions & 5 deletions src/Database/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ public function beforeUpdate()
*
* @return void
*/
public function cascadeSoftDelete(): void
public function cascadeSoftDelete() : void
{
foreach ($this->getDependentRelationships() as $relation => $data) {
$relationData = $this->{'get'.$relation}();
$relationData = $this->{'get' . $relation}();

if ($data['type'] === Relation::HAS_ONE) {
if (isset($relationData)) {
Expand Down Expand Up @@ -375,7 +375,7 @@ public function getPrimaryKeys() : array
/**
* Get get the primary key, if we have more than 1 , use keys.
*
* @return array
* @return string
*/
public function getPrimaryKey() : string
{
Expand All @@ -400,6 +400,19 @@ protected function throwErrorMessages() : void
);
}

/**
* Get model Table Columns.
*
* @return array
*/
public function getTableColumns() : array
{
$metadata = $this->getModelsMetaData();
$attributes = $metadata->getAttributes($this);

return $attributes;
}

/**
* hasProperty.
*
Expand All @@ -410,8 +423,8 @@ protected function throwErrorMessages() : void
public function hasProperty(string $property) : bool
{
$metadata = $this->getModelsMetaData();
$attributes = $metadata->getAttributes($this);
return key_exists($property, $attributes);

return $metadata->hasAttribute($this, $property);
}

/**
Expand Down
55 changes: 15 additions & 40 deletions src/Http/Converter/RequestUriToSql.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use Phalcon\Db\Column;
use Phalcon\Di;
use Phalcon\Di\Injectable;
use Phalcon\Mvc\Model\MetaData\Memory as MetaDataMemory;
use Phalcon\Mvc\Model\ResultsetInterface;
use ReflectionClass;

Expand Down Expand Up @@ -940,52 +939,28 @@ public static function parseRelationShips(string $relationships, &$results) : ar
*
* @param string $sort
*
* @return string
* @return void
*/
public function setCustomSort(?string $sort) : void
{
if (!is_null($sort)) {
// Get the model, column and sort order from the sent parameter.
list($modelColumn, $order) = explode('|', $sort);
//limit the sort
$order = strtolower($order) === 'asc' ? 'ASC' : 'DESC';
$order = null;
$modelColumn = $sort;
if (Str::contains($sort, '|')) {
// Get the model, column and sort order from the sent parameter.
list($modelColumn, $order) = explode('|', $sort);
}

$modelColumn = Str::cleanup($modelColumn);
// Check to see whether this is a related sorting by looking for a .
if (strpos($modelColumn, '.') !== false) {
// We are using a related sort.
// Get the namespace for the models from the configuration.
$modelNamespace = Di::getDefault()->get('config')->namespace->models;
// Get the model name and the sort column from the sent parameter
list($model, $column) = explode('.', $modelColumn);
// Convert the model name into camel case.
$modelName = str_replace(' ', '', ucwords(str_replace('_', ' ', $model)));
// Create the model name with the appended namespace.
$modelName = $modelNamespace . '\\' . $modelName;

// Make sure the model exists.
if (!class_exists($modelName)) {
throw new Exception('Related model does not exist.');
}

// Instance the model so we have access to the getSource() function.
$modelObject = new $modelName();
// Instance meta data memory to access the primary keys for the table.
$metaData = new MetaDataMemory();

// Get the first matching primary key.
// @TODO This will hurt on compound primary keys.
$primaryKey = $metaData->getPrimaryKeyAttributes($modelObject)[0];
// We need the table to exist in the query in order for the related sort to work.
// Therefore we add it to comply with this by comparing the primary key to not being NULL.
$this->relationSearchFields[$modelName][] = [
$primaryKey, ':', '$$',
];

$this->sort = " ORDER BY {$modelObject->getSource()}.{$column} {$order}";
unset($modelObject);
} else {
$this->sort = " ORDER BY {$modelColumn} {$order}";
if (!$this->model->hasProperty($modelColumn)) {
return ;
}

//limit the sort
$order = strtolower($order) === 'asc' ? 'ASC' : 'DESC';

$this->sort = " ORDER BY {$modelColumn} {$order}";
}
}
}
1 change: 1 addition & 0 deletions src/Support/Str.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public static function includes(string $needle, string $haystack) : bool
*
* @param string $needle
* @param string $haystack
* contains('This is an example string', 'example');
*
* @return bool
*/
Expand Down
20 changes: 20 additions & 0 deletions tests/integration/Database/ModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,24 @@ public function testCascadeSoftDelete()

$this->assertEmpty($user->getSubscriptions());
}

public function testHasProperty()
{
$lead = Leads::findFirst();
$this->assertTrue($lead->hasProperty('id'));
$this->assertTrue($lead->hasProperty('firstname'));
}

public function testGetPrimaryKey()
{
$lead = Leads::findFirst();
$this->assertEquals('id', $lead->getPrimaryKey());
}

public function testGetTableColumns()
{
$lead = Leads::findFirst();
$this->assertIsArray($lead->getTableColumns());
$this->assertArrayHasKey('id', array_flip($lead->getTableColumns()));
}
}
48 changes: 39 additions & 9 deletions tests/integration/Http/UriToSqlTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function testSimpleQuery()
$results = (new SimpleRecords(null, $leads, $leads->getReadConnection()->query($request['sql'], $request['bind'])));
$count = $leads->getReadConnection()->query($request['countSql'], $request['bind'])->fetch(\PDO::FETCH_OBJ)->total;

//confirme records
//confirmed records
foreach ($results as $result) {
$this->assertTrue($result->id > 0);
}
Expand All @@ -48,7 +48,7 @@ public function testQueryColumns()
$params['columns'] = '(users_id, firstname, lastname, is_deleted, is_active, leads_owner_id)';
$params['limit'] = '10';
$params['page'] = '1';
$params['sort'] = 'id|desc';
$params['sort'] = 'columnDoesntExist|asc';

$leads = new Leads();
$requestToSql = new RequestUriToSql($params, $leads);
Expand All @@ -59,7 +59,37 @@ public function testQueryColumns()

//confirmed records
foreach ($results as $result) {
//doesn't existe id
//doesn't exists id
$this->assertFalse(isset($result->id));
}

$this->assertTrue(count($results->toArray()) == 10);
$this->assertTrue($count > 0);
}

/**
* Test normal columns.
*
* @return void
*/
public function testQuerySortAsc()
{
$params = [];
$params['columns'] = '(users_id, firstname, lastname, is_deleted, is_active, leads_owner_id)';
$params['limit'] = '10';
$params['page'] = '1';
$params['sort'] = 'id|asc';

$leads = new Leads();
$requestToSql = new RequestUriToSql($params, $leads);
$request = $requestToSql->convert();

$results = (new SimpleRecords(null, $leads, $leads->getReadConnection()->query($request['sql'], $request['bind'])));
$count = $leads->getReadConnection()->query($request['countSql'], $request['bind'])->fetch(\PDO::FETCH_OBJ)->total;

//confirmed records
foreach ($results as $result) {
//doesn't exists id
$this->assertFalse(isset($result->id));
}

Expand Down Expand Up @@ -116,7 +146,7 @@ public function testQueryConditionalsWithAnd()
$results = (new SimpleRecords(null, $leads, $leads->getReadConnection()->query($request['sql'], $request['bind'])));
$count = $leads->getReadConnection()->query($request['countSql'], $request['bind'])->fetch(\PDO::FETCH_OBJ)->total;

//confirme records
//confirmed records
foreach ($results as $result) {
$this->assertTrue($result->id > 0);
}
Expand Down Expand Up @@ -144,7 +174,7 @@ public function testQueryConditionalsWithOr()
$results = (new SimpleRecords(null, $leads, $leads->getReadConnection()->query($request['sql'], $request['bind'])));
$count = $leads->getReadConnection()->query($request['countSql'], $request['bind'])->fetch(\PDO::FETCH_OBJ)->total;

//confirme records
//confirmed records
foreach ($results as $result) {
$this->assertTrue($result->id > 0);
}
Expand Down Expand Up @@ -173,7 +203,7 @@ public function testQueryConditionalsWithAndOr()
$results = (new SimpleRecords(null, $leads, $leads->getReadConnection()->query($request['sql'], $request['bind'])));
$count = $leads->getReadConnection()->query($request['countSql'], $request['bind'])->fetch(\PDO::FETCH_OBJ)->total;

//confirme records
//confirmed records
foreach ($results as $result) {
$this->assertTrue($result->id > 0);
}
Expand Down Expand Up @@ -202,7 +232,7 @@ public function testQueryConditionalsLimit()
$results = (new SimpleRecords(null, $leads, $leads->getReadConnection()->query($request['sql'], $request['bind'])));
$count = $leads->getReadConnection()->query($request['countSql'], $request['bind'])->fetch(\PDO::FETCH_OBJ)->total;

//confirme records
//confirmed records
foreach ($results as $result) {
$this->assertTrue($result->id > 0);
}
Expand Down Expand Up @@ -251,7 +281,7 @@ public function testQueryConditionalsWithCustomColumns()
$results = (new SimpleRecords(null, $leads, $leads->getReadConnection()->query($request['sql'], $request['bind'])));
$count = $leads->getReadConnection()->query($request['countSql'], $request['bind'])->fetch(\PDO::FETCH_OBJ)->total;

//confirme records
//confirmed records
foreach ($results as $result) {
$this->assertTrue(isset($result->companies_id));
$this->assertFalse(isset($result->users_id));
Expand Down Expand Up @@ -284,7 +314,7 @@ public function testQueryConditionalsWithCustomTable()
$results = (new SimpleRecords(null, $leads, $leads->getReadConnection()->query($request['sql'], $request['bind'])));
$count = $leads->getReadConnection()->query($request['countSql'], $request['bind'])->fetch(\PDO::FETCH_OBJ)->total;

//confirme records
//confirmed records
foreach ($results as $result) {
$this->assertTrue(isset($result->companies_id));
$this->assertTrue(isset($result->users_id));
Expand Down

0 comments on commit 21d9a77

Please sign in to comment.