Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions apps/twofactor_backupcodes/lib/Db/BackupCode.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,29 @@
*/
namespace OCA\TwoFactorBackupCodes\Db;

use OCP\AppFramework\Db\Attribute\Column;
use OCP\AppFramework\Db\Attribute\Table;
use OCP\AppFramework\Db\Entity;
use OCP\DB\Types;

/**
* @method string getId()
* @method void setId(string $id)
* @method string getUserId()
* @method void setUserId(string $userId)
* @method string getCode()
* @method void setCode(string $code)
* @method int getUsed()
* @method void setUsed(int $code)
*/
#[Table(name: 'twofactor_backupcodes', useSnowflakeId: true)]
class BackupCode extends Entity {
#[Column(name: 'user_id', type: Types::STRING, length: 64, nullable: false)]
protected ?string $userId = null;

/** @var string */
protected $userId;
#[Column(name: 'code', type: Types::STRING, length: 128, nullable: false)]
protected ?string $code = null;

/** @var string */
protected $code;

/** @var int */
protected $used;
#[Column(name: 'used', type: Types::SMALLINT, nullable: false)]
protected ?int $used = null;
}
65 changes: 20 additions & 45 deletions lib/private/Tagging/Tag.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,71 +7,46 @@
*/
namespace OC\Tagging;

use OCP\AppFramework\Db\Attribute\Column;
use OCP\AppFramework\Db\Attribute\Table;
use OCP\AppFramework\Db\Entity;
use OCP\DB\Types;

/**
* Class to represent a tag.
*
* @method string getId()
* @method void setId(string $id)
* @method string getOwner()
* @method void setOwner(string $owner)
* @method string getType()
* @method void setType(string $type)
* @method string getName()
* @method void setName(string $name)
*/
#[Table(name: 'vcategory', useSnowflakeId: true)]
class Tag extends Entity {
protected $owner;
protected $type;
protected $name;
#[Column(name: 'uid', type: Types::STRING, length: 64, nullable: false)]
protected ?string $owner = null;

#[Column(name: 'type', type: Types::STRING, length: 64, nullable: false)]
protected ?string $type = null;

#[Column(name: 'category', type: Types::STRING, length: 255, nullable: false)]
protected ?string $name = null;

/**
* Constructor.
*
* @param string $owner The tag's owner
* @param string $type The type of item this tag is used for
* @param string $name The tag's name
* @param ?string $owner The tag's owner
* @param ?string $type The type of item this tag is used for
* @param ?string $name The tag's name
*/
public function __construct($owner = null, $type = null, $name = null) {
public function __construct(?string $owner = null, ?string $type = null, ?string $name = null) {
parent::__construct();

$this->setOwner($owner);
$this->setType($type);
$this->setName($name);
}

/**
* Transform a database columnname to a property
*
* @param string $columnName the name of the column
* @return string the property name
* @todo migrate existing database columns to the correct names
* to be able to drop this direct mapping
*/
public function columnToProperty(string $columnName): string {
if ($columnName === 'category') {
return 'name';
}

if ($columnName === 'uid') {
return 'owner';
}

return parent::columnToProperty($columnName);
}

/**
* Transform a property to a database column name
*
* @param string $property the name of the property
* @return string the column name
*/
public function propertyToColumn(string $property): string {
if ($property === 'name') {
return 'category';
}

if ($property === 'owner') {
return 'uid';
}

return parent::propertyToColumn($property);
}
}
28 changes: 28 additions & 0 deletions lib/public/AppFramework/Db/Attribute/Column.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH
* SPDX-FileContributor: Carl Schwan
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCP\AppFramework\Db\Attribute;

use Attribute;
use OCP\AppFramework\Attribute\Consumable;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\Types;

#[Attribute(Attribute::TARGET_PROPERTY)]

Check failure on line 18 in lib/public/AppFramework/Db/Attribute/Column.php

View workflow job for this annotation

GitHub Actions / static-code-analysis-ocp

InvalidDocblock

lib/public/AppFramework/Db/Attribute/Column.php:18:1: InvalidDocblock: PHPDoc is required for classes/interfaces in OCP. (see https://psalm.dev/008)
#[Consumable(since: '33.0.0')]
final readonly class Column {
public function __construct(
public string $name,
public string|null $type,
public int|null $length = null,
public bool $nullable = false,
) {
}
}
26 changes: 26 additions & 0 deletions lib/public/AppFramework/Db/Attribute/Table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH
* SPDX-FileContributor: Carl Schwan
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCP\AppFramework\Db\Attribute;

use Attribute;
use OCP\AppFramework\Attribute\Consumable;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\Types;

#[Attribute(Attribute::TARGET_CLASS)]

Check failure on line 18 in lib/public/AppFramework/Db/Attribute/Table.php

View workflow job for this annotation

GitHub Actions / static-code-analysis-ocp

InvalidDocblock

lib/public/AppFramework/Db/Attribute/Table.php:18:1: InvalidDocblock: PHPDoc is required for classes/interfaces in OCP. (see https://psalm.dev/008)
#[Consumable(since: '33.0.0')]
final readonly class Table {
public function __construct(
public string $name,
public bool $useSnowflakeId = false,
) {
}
}
51 changes: 48 additions & 3 deletions lib/public/AppFramework/Db/Entity.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
*/
namespace OCP\AppFramework\Db;

use OCP\AppFramework\Db\Attribute\Column;
use OCP\AppFramework\Db\Attribute\Table;
use OCP\DB\Types;

use function lcfirst;
Expand All @@ -19,12 +21,44 @@
* @psalm-consistent-constructor
*/
abstract class Entity {
/** @var int $id */
public $id = null;
#[Column(name: 'id', type: Types::BIGINT)]
public string|int|null $id = null;

/** @var array<string, bool> */
private array $_updatedFields = [];

/** @var array<string, \OCP\DB\Types::*> */
private array $_fieldTypes = ['id' => 'integer'];
private array $_fieldTypes = ['id' => Types::INTEGER];

/** @var array<string, string> */
private array $_mappingColumnToProperty = [];

/** @var array<string, string> */
private array $_mappingPropertyToColumn = [];

public function __construct() {
$reflection = new \ReflectionObject($this);

foreach ($reflection->getProperties() as $property) {
$columnAttributes = $property->getAttributes(Column::class);
if (count($columnAttributes) > 0) {
/** @var Column $columnAttribute */
$columnAttribute = $columnAttributes[0];
$this->_fieldTypes[$property->name] = $columnAttribute->type;

Check failure on line 47 in lib/public/AppFramework/Db/Entity.php

View workflow job for this annotation

GitHub Actions / static-code-analysis-ocp

InvalidPropertyAssignmentValue

lib/public/AppFramework/Db/Entity.php:47:5: InvalidPropertyAssignmentValue: $this->_fieldTypes with declared type 'array<string, 'bigint'|'binary'|'blob'|'boolean'|'date'|'date_immutable'|'datetime'|'datetime_immutable'|'datetimetz'|'datetimetz_immutable'|'decimal'|'float'|'integer'|'json'|'smallint'|'string'|'text'|'time'|'time_immutable'>' cannot be assigned type 'non-empty-array<string, null|string>' (see https://psalm.dev/145)
$this->_mappingColumnToProperty[$columnAttribute->name] = $property->name;
$this->_mappingPropertyToColumn[$property->name] = $columnAttribute->name;
}
}

$tableAttributes =$reflection->getAttributes(Table::class);
if (count($tableAttributes) > 0) {
/** @var Table $tableAttribute */
$tableAttribute = $tableAttributes[0];
if ($tableAttribute->useSnowflakeId) {
$this->_fieldTypes['id'] = Types::STRING;

Check failure on line 58 in lib/public/AppFramework/Db/Entity.php

View workflow job for this annotation

GitHub Actions / static-code-analysis-ocp

InvalidPropertyAssignmentValue

lib/public/AppFramework/Db/Entity.php:58:5: InvalidPropertyAssignmentValue: $this->_fieldTypes with declared type 'array<string, 'bigint'|'binary'|'blob'|'boolean'|'date'|'date_immutable'|'datetime'|'datetime_immutable'|'datetimetz'|'datetimetz_immutable'|'decimal'|'float'|'integer'|'json'|'smallint'|'string'|'text'|'time'|'time_immutable'>' cannot be assigned type 'array{id: 'string', ...<string, null|string>}' (see https://psalm.dev/145)
}
}
}

/**
* Simple alternative constructor for building entities from a request
Expand Down Expand Up @@ -101,6 +135,7 @@
// if type definition exists, cast to correct type
if ($args[0] !== null && array_key_exists($name, $this->_fieldTypes)) {
$type = $this->_fieldTypes[$name];

if ($type === Types::BLOB) {
// (B)LOB is treated as string when we read from the DB
if (is_resource($args[0])) {
Expand Down Expand Up @@ -212,11 +247,16 @@
* @param string $columnName the name of the column
* @return string the property name
* @since 7.0.0
* @deprecated Use Column attribute to map a property to a column
*/
public function columnToProperty(string $columnName) {
$parts = explode('_', $columnName);
$property = '';

if (isset($this->_mappingColumnToProperty[$columnName])) {
return $this->_mappingColumnToProperty[$columnName];
}

foreach ($parts as $part) {
if ($property === '') {
$property = $part;
Expand All @@ -235,10 +275,15 @@
* @param string $property the name of the property
* @return string the column name
* @since 7.0.0
* @deprecated Use Column attribute to map a property to a column
*/
public function propertyToColumn(string $property): string {
$parts = preg_split('/(?=[A-Z])/', $property);

if (isset($this->_mappingPropertyToColumn[$property])) {
return $this->_mappingPropertyToColumn[$property];
}

$column = '';
foreach ($parts as $part) {
if ($column === '') {
Expand Down
Loading
Loading