Skip to content

Commit 21d9a77

Browse files
authored
Merge pull request #119 from bakaphp/0.7-improve-sort-validation
2 parents d0fc7c5 + 9979385 commit 21d9a77

File tree

5 files changed

+93
-54
lines changed

5 files changed

+93
-54
lines changed

src/Database/Model.php

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ public function beforeUpdate()
107107
*
108108
* @return void
109109
*/
110-
public function cascadeSoftDelete(): void
110+
public function cascadeSoftDelete() : void
111111
{
112112
foreach ($this->getDependentRelationships() as $relation => $data) {
113-
$relationData = $this->{'get'.$relation}();
113+
$relationData = $this->{'get' . $relation}();
114114

115115
if ($data['type'] === Relation::HAS_ONE) {
116116
if (isset($relationData)) {
@@ -375,7 +375,7 @@ public function getPrimaryKeys() : array
375375
/**
376376
* Get get the primary key, if we have more than 1 , use keys.
377377
*
378-
* @return array
378+
* @return string
379379
*/
380380
public function getPrimaryKey() : string
381381
{
@@ -400,6 +400,19 @@ protected function throwErrorMessages() : void
400400
);
401401
}
402402

403+
/**
404+
* Get model Table Columns.
405+
*
406+
* @return array
407+
*/
408+
public function getTableColumns() : array
409+
{
410+
$metadata = $this->getModelsMetaData();
411+
$attributes = $metadata->getAttributes($this);
412+
413+
return $attributes;
414+
}
415+
403416
/**
404417
* hasProperty.
405418
*
@@ -410,8 +423,8 @@ protected function throwErrorMessages() : void
410423
public function hasProperty(string $property) : bool
411424
{
412425
$metadata = $this->getModelsMetaData();
413-
$attributes = $metadata->getAttributes($this);
414-
return key_exists($property, $attributes);
426+
427+
return $metadata->hasAttribute($this, $property);
415428
}
416429

417430
/**

src/Http/Converter/RequestUriToSql.php

Lines changed: 15 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use Phalcon\Db\Column;
1313
use Phalcon\Di;
1414
use Phalcon\Di\Injectable;
15-
use Phalcon\Mvc\Model\MetaData\Memory as MetaDataMemory;
1615
use Phalcon\Mvc\Model\ResultsetInterface;
1716
use ReflectionClass;
1817

@@ -940,52 +939,28 @@ public static function parseRelationShips(string $relationships, &$results) : ar
940939
*
941940
* @param string $sort
942941
*
943-
* @return string
942+
* @return void
944943
*/
945944
public function setCustomSort(?string $sort) : void
946945
{
947946
if (!is_null($sort)) {
948-
// Get the model, column and sort order from the sent parameter.
949-
list($modelColumn, $order) = explode('|', $sort);
950-
//limit the sort
951-
$order = strtolower($order) === 'asc' ? 'ASC' : 'DESC';
947+
$order = null;
948+
$modelColumn = $sort;
949+
if (Str::contains($sort, '|')) {
950+
// Get the model, column and sort order from the sent parameter.
951+
list($modelColumn, $order) = explode('|', $sort);
952+
}
953+
952954
$modelColumn = Str::cleanup($modelColumn);
953-
// Check to see whether this is a related sorting by looking for a .
954-
if (strpos($modelColumn, '.') !== false) {
955-
// We are using a related sort.
956-
// Get the namespace for the models from the configuration.
957-
$modelNamespace = Di::getDefault()->get('config')->namespace->models;
958-
// Get the model name and the sort column from the sent parameter
959-
list($model, $column) = explode('.', $modelColumn);
960-
// Convert the model name into camel case.
961-
$modelName = str_replace(' ', '', ucwords(str_replace('_', ' ', $model)));
962-
// Create the model name with the appended namespace.
963-
$modelName = $modelNamespace . '\\' . $modelName;
964-
965-
// Make sure the model exists.
966-
if (!class_exists($modelName)) {
967-
throw new Exception('Related model does not exist.');
968-
}
969955

970-
// Instance the model so we have access to the getSource() function.
971-
$modelObject = new $modelName();
972-
// Instance meta data memory to access the primary keys for the table.
973-
$metaData = new MetaDataMemory();
974-
975-
// Get the first matching primary key.
976-
// @TODO This will hurt on compound primary keys.
977-
$primaryKey = $metaData->getPrimaryKeyAttributes($modelObject)[0];
978-
// We need the table to exist in the query in order for the related sort to work.
979-
// Therefore we add it to comply with this by comparing the primary key to not being NULL.
980-
$this->relationSearchFields[$modelName][] = [
981-
$primaryKey, ':', '$$',
982-
];
983-
984-
$this->sort = " ORDER BY {$modelObject->getSource()}.{$column} {$order}";
985-
unset($modelObject);
986-
} else {
987-
$this->sort = " ORDER BY {$modelColumn} {$order}";
956+
if (!$this->model->hasProperty($modelColumn)) {
957+
return ;
988958
}
959+
960+
//limit the sort
961+
$order = strtolower($order) === 'asc' ? 'ASC' : 'DESC';
962+
963+
$this->sort = " ORDER BY {$modelColumn} {$order}";
989964
}
990965
}
991966
}

src/Support/Str.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public static function includes(string $needle, string $haystack) : bool
7777
*
7878
* @param string $needle
7979
* @param string $haystack
80+
* contains('This is an example string', 'example');
8081
*
8182
* @return bool
8283
*/

tests/integration/Database/ModelTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,24 @@ public function testCascadeSoftDelete()
119119

120120
$this->assertEmpty($user->getSubscriptions());
121121
}
122+
123+
public function testHasProperty()
124+
{
125+
$lead = Leads::findFirst();
126+
$this->assertTrue($lead->hasProperty('id'));
127+
$this->assertTrue($lead->hasProperty('firstname'));
128+
}
129+
130+
public function testGetPrimaryKey()
131+
{
132+
$lead = Leads::findFirst();
133+
$this->assertEquals('id', $lead->getPrimaryKey());
134+
}
135+
136+
public function testGetTableColumns()
137+
{
138+
$lead = Leads::findFirst();
139+
$this->assertIsArray($lead->getTableColumns());
140+
$this->assertArrayHasKey('id', array_flip($lead->getTableColumns()));
141+
}
122142
}

tests/integration/Http/UriToSqlTest.php

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public function testSimpleQuery()
2828
$results = (new SimpleRecords(null, $leads, $leads->getReadConnection()->query($request['sql'], $request['bind'])));
2929
$count = $leads->getReadConnection()->query($request['countSql'], $request['bind'])->fetch(\PDO::FETCH_OBJ)->total;
3030

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

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

6060
//confirmed records
6161
foreach ($results as $result) {
62-
//doesn't existe id
62+
//doesn't exists id
63+
$this->assertFalse(isset($result->id));
64+
}
65+
66+
$this->assertTrue(count($results->toArray()) == 10);
67+
$this->assertTrue($count > 0);
68+
}
69+
70+
/**
71+
* Test normal columns.
72+
*
73+
* @return void
74+
*/
75+
public function testQuerySortAsc()
76+
{
77+
$params = [];
78+
$params['columns'] = '(users_id, firstname, lastname, is_deleted, is_active, leads_owner_id)';
79+
$params['limit'] = '10';
80+
$params['page'] = '1';
81+
$params['sort'] = 'id|asc';
82+
83+
$leads = new Leads();
84+
$requestToSql = new RequestUriToSql($params, $leads);
85+
$request = $requestToSql->convert();
86+
87+
$results = (new SimpleRecords(null, $leads, $leads->getReadConnection()->query($request['sql'], $request['bind'])));
88+
$count = $leads->getReadConnection()->query($request['countSql'], $request['bind'])->fetch(\PDO::FETCH_OBJ)->total;
89+
90+
//confirmed records
91+
foreach ($results as $result) {
92+
//doesn't exists id
6393
$this->assertFalse(isset($result->id));
6494
}
6595

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

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

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

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

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

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

287-
//confirme records
317+
//confirmed records
288318
foreach ($results as $result) {
289319
$this->assertTrue(isset($result->companies_id));
290320
$this->assertTrue(isset($result->users_id));

0 commit comments

Comments
 (0)