Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 10a1758

Browse files
committedSep 15, 2024·
feat(db): switch from settype to casts
Signed-off-by: Anna Larch <anna@nextcloud.com>
1 parent 3fe3f8d commit 10a1758

File tree

5 files changed

+82
-60
lines changed

5 files changed

+82
-60
lines changed
 

‎lib/private/Tagging/Tag.php

+12-8
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,16 @@ public function __construct($owner = null, $type = null, $name = null) {
4545
* @todo migrate existing database columns to the correct names
4646
* to be able to drop this direct mapping
4747
*/
48-
public function columnToProperty($columnName) {
48+
public function columnToProperty(string $columnName): string {
4949
if ($columnName === 'category') {
5050
return 'name';
51-
} elseif ($columnName === 'uid') {
51+
}
52+
53+
if ($columnName === 'uid') {
5254
return 'owner';
53-
} else {
54-
return parent::columnToProperty($columnName);
5555
}
56+
57+
return parent::columnToProperty($columnName);
5658
}
5759

5860
/**
@@ -61,13 +63,15 @@ public function columnToProperty($columnName) {
6163
* @param string $property the name of the property
6264
* @return string the column name
6365
*/
64-
public function propertyToColumn($property) {
66+
public function propertyToColumn(string $property): string {
6567
if ($property === 'name') {
6668
return 'category';
67-
} elseif ($property === 'owner') {
69+
}
70+
71+
if ($property === 'owner') {
6872
return 'uid';
69-
} else {
70-
return parent::propertyToColumn($property);
7173
}
74+
75+
return parent::propertyToColumn($property);
7276
}
7377
}

‎lib/public/AppFramework/Db/Entity.php

+64-46
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
/**
1414
* @method int getId()
1515
* @method void setId(int $id)
16+
* @psalm-type AllowedTypes = 'json'|'blob'|'datetime'|'string'|'int'|'integer'|'bool'|'boolean'|'float'|'double'|'array'|'object'
1617
* @since 7.0.0
1718
* @psalm-consistent-constructor
1819
*/
@@ -23,6 +24,7 @@ abstract class Entity {
2324
public $id;
2425

2526
private array $_updatedFields = [];
27+
/** @var array<string, AllowedTypes> */
2628
private array $_fieldTypes = ['id' => 'integer'];
2729

2830
/**
@@ -64,10 +66,10 @@ public static function fromRow(array $row): static {
6466

6567

6668
/**
67-
* @return array with attribute and type
69+
* @return array<string, AllowedTypes> with attribute and type
6870
* @since 7.0.0
6971
*/
70-
public function getFieldTypes() {
72+
public function getFieldTypes(): array {
7173
return $this->_fieldTypes;
7274
}
7375

@@ -76,50 +78,63 @@ public function getFieldTypes() {
7678
* Marks the entity as clean needed for setting the id after the insertion
7779
* @since 7.0.0
7880
*/
79-
public function resetUpdatedFields() {
81+
public function resetUpdatedFields(): void {
8082
$this->_updatedFields = [];
8183
}
8284

8385
/**
8486
* Generic setter for properties
87+
*
88+
* @throws \InvalidArgumentException
8589
* @since 7.0.0
90+
*
8691
*/
8792
protected function setter(string $name, array $args): void {
8893
// setters should only work for existing attributes
89-
if (property_exists($this, $name)) {
90-
if ($args[0] === $this->$name) {
91-
return;
92-
}
93-
$this->markFieldUpdated($name);
94-
95-
// if type definition exists, cast to correct type
96-
if ($args[0] !== null && array_key_exists($name, $this->_fieldTypes)) {
97-
$type = $this->_fieldTypes[$name];
98-
if ($type === 'blob') {
99-
// (B)LOB is treated as string when we read from the DB
100-
if (is_resource($args[0])) {
101-
$args[0] = stream_get_contents($args[0]);
102-
}
103-
$type = 'string';
94+
if (!property_exists($this, $name)) {
95+
throw new \BadFunctionCallException($name .
96+
' is not a valid attribute');
97+
}
98+
99+
if ($args[0] === $this->$name) {
100+
return;
101+
}
102+
$this->markFieldUpdated($name);
103+
104+
// if type definition exists, cast to correct type
105+
if ($args[0] !== null && array_key_exists($name, $this->_fieldTypes)) {
106+
$type = $this->_fieldTypes[$name];
107+
if ($type === 'blob') {
108+
// (B)LOB is treated as string when we read from the DB
109+
if (is_resource($args[0])) {
110+
$args[0] = stream_get_contents($args[0]);
104111
}
112+
$type = 'string';
113+
}
105114

106-
if ($type === 'datetime') {
107-
if (!$args[0] instanceof \DateTime) {
108-
$args[0] = new \DateTime($args[0]);
109-
}
110-
} elseif ($type === 'json') {
111-
if (!is_array($args[0])) {
112-
$args[0] = json_decode($args[0], true);
113-
}
114-
} else {
115-
settype($args[0], $type);
115+
if ($type === 'datetime') {
116+
if (!$args[0] instanceof \DateTime) {
117+
$args[0] = new \DateTime($args[0]);
118+
}
119+
} elseif ($type === 'json') {
120+
if (!is_array($args[0])) {
121+
$args[0] = json_decode($args[0], true);
116122
}
123+
} else {
124+
$args[0] = match($type) {
125+
'string' => (string)$args[0],
126+
'bool', 'boolean', => (bool)$args[0],
127+
'int', 'integer', => (int)$args[0],
128+
'float' => (float)$args[0],
129+
'double' => (float)$args[0],
130+
'array' => (array)$args[0],
131+
'object' => (object)$args[0],
132+
default => new \InvalidArgumentException()
133+
};
117134
}
118-
$this->$name = $args[0];
119-
} else {
120-
throw new \BadFunctionCallException($name .
121-
' is not a valid attribute');
122135
}
136+
$this->$name = $args[0];
137+
123138
}
124139

125140
/**
@@ -182,16 +197,17 @@ protected function markFieldUpdated(string $attribute): void {
182197

183198
/**
184199
* Transform a database columnname to a property
200+
*
185201
* @param string $columnName the name of the column
186202
* @return string the property name
187203
* @since 7.0.0
188204
*/
189-
public function columnToProperty($columnName) {
205+
public function columnToProperty(string $columnName): string {
190206
$parts = explode('_', $columnName);
191-
$property = null;
207+
$property = '';
192208

193209
foreach ($parts as $part) {
194-
if ($property === null) {
210+
if ($property === '') {
195211
$property = $part;
196212
} else {
197213
$property .= ucfirst($part);
@@ -204,16 +220,17 @@ public function columnToProperty($columnName) {
204220

205221
/**
206222
* Transform a property to a database column name
223+
*
207224
* @param string $property the name of the property
208225
* @return string the column name
209226
* @since 7.0.0
210227
*/
211-
public function propertyToColumn($property) {
228+
public function propertyToColumn(string $property): string {
212229
$parts = preg_split('/(?=[A-Z])/', $property);
213-
$column = null;
214230

231+
$column = '';
215232
foreach ($parts as $part) {
216-
if ($column === null) {
233+
if ($column === '') {
217234
$column = $part;
218235
} else {
219236
$column .= '_' . lcfirst($part);
@@ -228,32 +245,34 @@ public function propertyToColumn($property) {
228245
* @return array array of updated fields for update query
229246
* @since 7.0.0
230247
*/
231-
public function getUpdatedFields() {
248+
public function getUpdatedFields(): array {
232249
return $this->_updatedFields;
233250
}
234251

235252

236253
/**
237-
* Adds type information for a field so that its automatically casted to
254+
* Adds type information for a field so that it's automatically cast to
238255
* that value once its being returned from the database
256+
*
239257
* @param string $fieldName the name of the attribute
240-
* @param string $type the type which will be used to call settype()
258+
* @param AllowedTypes $type the type which will be used to match a cast
241259
* @since 7.0.0
242260
*/
243-
protected function addType($fieldName, $type) {
261+
protected function addType(string $fieldName, string $type): void {
244262
$this->_fieldTypes[$fieldName] = $type;
245263
}
246264

247265

248266
/**
249267
* Slugify the value of a given attribute
250268
* Warning: This doesn't result in a unique value
269+
*
251270
* @param string $attributeName the name of the attribute, which value should be slugified
252271
* @return string slugified value
253272
* @since 7.0.0
254273
* @deprecated 24.0.0
255274
*/
256-
public function slugify($attributeName) {
275+
public function slugify(string $attributeName): string {
257276
// toSlug should only work for existing attributes
258277
if (property_exists($this, $attributeName)) {
259278
$value = $this->$attributeName;
@@ -262,9 +281,8 @@ public function slugify($attributeName) {
262281
$value = strtolower($value);
263282
// trim '-'
264283
return trim($value, '-');
265-
} else {
266-
throw new \BadFunctionCallException($attributeName .
267-
' is not a valid attribute');
268284
}
285+
286+
throw new \BadFunctionCallException($attributeName . ' is not a valid attribute');
269287
}
270288
}

‎tests/lib/AppTest.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -460,9 +460,9 @@ public function appConfigValuesProvider() {
460460
public function testEnabledApps($user, $expectedApps, $forceAll) {
461461
$userManager = \OC::$server->getUserManager();
462462
$groupManager = \OC::$server->getGroupManager();
463-
$user1 = $userManager->createUser(self::TEST_USER1, self::TEST_USER1);
464-
$user2 = $userManager->createUser(self::TEST_USER2, self::TEST_USER2);
465-
$user3 = $userManager->createUser(self::TEST_USER3, self::TEST_USER3);
463+
$user1 = $userManager->createUser(self::TEST_USER1, 'NotAnEasyPassword123456+');
464+
$user2 = $userManager->createUser(self::TEST_USER2, 'NotAnEasyPassword123456_');
465+
$user3 = $userManager->createUser(self::TEST_USER3, 'NotAnEasyPassword123456?');
466466

467467
$group1 = $groupManager->createGroup(self::TEST_GROUP1);
468468
$group1->addUser($user1);
@@ -508,7 +508,7 @@ public function testEnabledApps($user, $expectedApps, $forceAll) {
508508
*/
509509
public function testEnabledAppsCache() {
510510
$userManager = \OC::$server->getUserManager();
511-
$user1 = $userManager->createUser(self::TEST_USER1, self::TEST_USER1);
511+
$user1 = $userManager->createUser(self::TEST_USER1, 'NotAnEasyPassword123456+');
512512

513513
\OC_User::setUserId(self::TEST_USER1);
514514

‎tests/lib/Comments/ManagerTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ public function testDeleteReferencesOfActor() {
671671
}
672672

673673
public function testDeleteReferencesOfActorWithUserManagement() {
674-
$user = \OC::$server->getUserManager()->createUser('xenia', '123456');
674+
$user = \OC::$server->getUserManager()->createUser('xenia', 'NotAnEasyPassword123456+');
675675
$this->assertTrue($user instanceof IUser);
676676

677677
$manager = \OC::$server->get(ICommentsManager::class);

‎tests/lib/Files/Cache/UpdaterLegacyTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ protected function setUp(): void {
5656
self::$user = $this->getUniqueID();
5757
}
5858

59-
\OC::$server->getUserManager()->createUser(self::$user, 'password');
59+
\OC::$server->getUserManager()->createUser(self::$user, 'NotAnEasyPassword123456+');
6060
$this->loginAsUser(self::$user);
6161

6262
Filesystem::init(self::$user, '/' . self::$user . '/files');

0 commit comments

Comments
 (0)
Please sign in to comment.