Merge pull request #60219 from nextcloud/backport/59940/stable33

[stable33] Fix since checker
This commit is contained in:
Joas Schilling 2026-05-08 14:43:21 +02:00 committed by GitHub
commit 29cc5dd32c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 320 additions and 6 deletions

View file

@ -44,6 +44,9 @@
<DeprecatedConstant>
<code><![CDATA[CommentsEvent::EVENT_ADD]]></code>
</DeprecatedConstant>
<DeprecatedMethod>
<code><![CDATA[getEvent]]></code>
</DeprecatedMethod>
</file>
<file src="apps/comments/lib/Listener/CommentsEventListener.php">
<DeprecatedConstant>
@ -52,6 +55,9 @@
<code><![CDATA[CommentsEvent::EVENT_PRE_UPDATE]]></code>
<code><![CDATA[CommentsEvent::EVENT_UPDATE]]></code>
</DeprecatedConstant>
<DeprecatedMethod>
<code><![CDATA[getEvent]]></code>
</DeprecatedMethod>
</file>
<file src="apps/comments/lib/MaxAutoCompleteResultsInitialState.php">
<DeprecatedMethod>
@ -63,6 +69,10 @@
<code><![CDATA[CommentsEvent::EVENT_DELETE]]></code>
<code><![CDATA[CommentsEvent::EVENT_PRE_UPDATE]]></code>
</DeprecatedConstant>
<DeprecatedMethod>
<code><![CDATA[getEvent]]></code>
<code><![CDATA[getEvent]]></code>
</DeprecatedMethod>
</file>
<file src="apps/dav/appinfo/v1/publicwebdav.php">
<InternalMethod>
@ -2222,7 +2232,6 @@
<file src="apps/provisioning_api/lib/Middleware/ProvisioningApiMiddleware.php">
<DeprecatedMethod>
<code><![CDATA[hasAnnotation]]></code>
<code><![CDATA[hasAnnotation]]></code>
</DeprecatedMethod>
<InvalidReturnType>
<code><![CDATA[Response]]></code>

View file

@ -1,12 +1,17 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\EnumCase;
use Psalm\CodeLocation;
use Psalm\DocComment;
use Psalm\Exception\DocblockParseException;
@ -34,13 +39,12 @@ class OcpSinceChecker implements Psalm\Plugin\EventHandler\AfterClassLikeVisitIn
} else {
self::checkClassComment($classLike, $statementsSource);
}
foreach ($classLike->stmts as $stmt) {
if ($stmt instanceof ClassConst) {
self::checkStatementComment($stmt, $statementsSource, 'constant');
}
if ($stmt instanceof ClassMethod) {
if ($stmt instanceof ClassMethod && ($stmt->isPublic() || $stmt->isProtected())) {
self::checkStatementComment($stmt, $statementsSource, 'method');
}

View file

@ -22,12 +22,16 @@ abstract class ASince {
* @param string $since For shipped apps and server code such as core/ and lib/,
* this should be the server version. For other apps it
* should be the semantic app version.
* @since 32.0.0
*/
public function __construct(
protected string $since,
) {
}
/**
* @since 32.0.0
*/
public function getSince(): string {
return $this->since;
}

View file

@ -22,16 +22,25 @@ use Attribute;
#[Consumable(since: '32.0.0')]
#[Implementable(since: '32.0.0')]
class ExceptionalImplementable {
/**
* @since 32.0.0
*/
public function __construct(
protected string $app,
protected ?string $class = null,
) {
}
/**
* @since 32.0.0
*/
public function getApp(): string {
return $this->app;
}
/**
* @since 32.0.0
*/
public function getClass(): ?string {
return $this->class;
}

View file

@ -141,6 +141,9 @@ abstract class Controller {
. $format . '!');
}
/**
* @since 33.0.0
*/
public function isResponderRegistered(string $responder): bool {
return isset($this->responders[$responder]);
}

View file

@ -26,12 +26,16 @@ abstract class SnowflakeAwareEntity extends Entity {
/** @psalm-param $_fieldTypes array<string, Types::*> */
protected array $_fieldTypes = ['id' => Types::STRING];
/**
* @since 33.0.0
*/
public function setId($id): void {
throw new \LogicException('Use generated id to set a new id to the Snowflake aware entity.');
}
/**
* Automatically creates a snowflake ID
* @since 33.0.0
*/
public function generateId(): void {
if ($this->id === null) {
@ -41,10 +45,16 @@ abstract class SnowflakeAwareEntity extends Entity {
}
}
/**
* @since 33.0.0
*/
public function getCreatedAt(): ?\DateTimeImmutable {
return $this->getSnowflake()?->getCreatedAt();
}
/**
* @since 33.0.0
*/
public function getSnowflake(): ?Snowflake {
if ($this->id === null) {
return null;

View file

@ -24,6 +24,7 @@ class RequestHeader {
* @param lowercase-string $name The name of the request header
* @param non-empty-string $description The description of the request header
* @param bool $indirect Allow indirect usage of the header for example in a middleware. Enabling this turns off the check which ensures that the header must be referenced in the controller method.
* @since 32.0.0
*/
public function __construct(
protected string $name,

View file

@ -26,6 +26,9 @@ use OCP\ISession;
*/
abstract class PublicShareController extends Controller {
/**
* @since 33.0.0
*/
public const DAV_AUTHENTICATED_FRONTEND = 'public_link_authenticated_frontend';
/** @var string */
@ -118,6 +121,8 @@ abstract class PublicShareController extends Controller {
/**
* Validate the token and password hash stored in session
*
* @since 33.0.0
*/
protected function validateTokenSession(string $token, string $passwordHash): bool {
$allowedTokensJSON = $this->session->get(self::DAV_AUTHENTICATED_FRONTEND) ?? '[]';
@ -131,6 +136,8 @@ abstract class PublicShareController extends Controller {
/**
* Store the token and password hash in session
*
* @since 33.0.0
*/
protected function storeTokenSession(string $token, string $passwordHash = ''): void {
$allowedTokensJSON = $this->session->get(self::DAV_AUTHENTICATED_FRONTEND) ?? '[]';

View file

@ -35,6 +35,9 @@ abstract class Job implements IJob, IParallelAwareJob {
) {
}
/**
* @since 25.0.0
*/
#[Override]
public function start(IJobList $jobList): void {
$jobList->setLastRun($this);
@ -59,45 +62,72 @@ abstract class Job implements IJob, IParallelAwareJob {
}
}
/**
* @since 15.0.0
*/
#[Override]
final public function setId(string $id): void {
$this->id = $id;
}
/**
* @since 15.0.0
*/
#[Override]
final public function setLastRun(int $lastRun): void {
$this->lastRun = $lastRun;
}
/**
* @since 15.0.0
*/
#[Override]
public function setArgument(mixed $argument): void {
$this->argument = $argument;
}
/**
* @since 15.0.0
*/
#[Override]
final public function getId(): string {
return $this->id;
}
/**
* @since 15.0.0
*/
#[Override]
final public function getLastRun(): int {
return $this->lastRun;
}
/**
* @since 15.0.0
*/
#[Override]
public function getArgument(): mixed {
return $this->argument;
}
/**
* @since 25.0.0
*/
#[Override]
public function setAllowParallelRuns(bool $allow): void {
$this->allowParallelRuns = $allow;
}
/**
* @since 25.0.0
*/
#[Override]
public function getAllowParallelRuns(): bool {
return $this->allowParallelRuns;
}
/**
* @since 15.0.0
*/
abstract protected function run($argument);
}

View file

@ -24,6 +24,7 @@ final class CalendarExportOptions {
* Gets the export format
*
* @return 'ical'|'jcal'|'xcal' (defaults to ical)
* @since 32.0.0
*/
public function getFormat(): string {
return $this->format;
@ -33,6 +34,7 @@ final class CalendarExportOptions {
* Sets the export format
*
* @param 'ical'|'jcal'|'xcal' $format
* @since 32.0.0
*/
public function setFormat(string $format): void {
$this->format = $format;
@ -40,6 +42,8 @@ final class CalendarExportOptions {
/**
* Gets the start of the range to export
*
* @since 32.0.0
*/
public function getRangeStart(): ?string {
return $this->rangeStart;
@ -47,6 +51,8 @@ final class CalendarExportOptions {
/**
* Sets the start of the range to export
*
* @since 32.0.0
*/
public function setRangeStart(?string $rangeStart): void {
$this->rangeStart = $rangeStart;
@ -54,6 +60,8 @@ final class CalendarExportOptions {
/**
* Gets the number of objects to export
*
* @since 32.0.0
*/
public function getRangeCount(): ?int {
return $this->rangeCount;
@ -61,6 +69,8 @@ final class CalendarExportOptions {
/**
* Sets the number of objects to export
*
* @since 32.0.0
*/
public function setRangeCount(?int $rangeCount): void {
$this->rangeCount = $rangeCount;

View file

@ -16,18 +16,42 @@ use InvalidArgumentException;
*/
final class CalendarImportOptions {
/**
* @since 32.0.0
*/
public const FORMATS = ['ical', 'jcal', 'xcal'];
/**
* @since 32.0.0
*/
public const VALIDATE_NONE = 0;
/**
* @since 32.0.0
*/
public const VALIDATE_SKIP = 1;
/**
* @since 32.0.0
*/
public const VALIDATE_FAIL = 2;
/**
* @since 32.0.0
*/
public const VALIDATE_OPTIONS = [
self::VALIDATE_NONE,
self::VALIDATE_SKIP,
self::VALIDATE_FAIL,
];
/**
* @since 32.0.0
*/
public const ERROR_CONTINUE = 0;
/**
* @since 32.0.0
*/
public const ERROR_FAIL = 1;
/**
* @since 32.0.0
*/
public const ERROR_OPTIONS = [
self::ERROR_CONTINUE,
self::ERROR_FAIL,
@ -43,6 +67,7 @@ final class CalendarImportOptions {
* Gets the import format
*
* @return 'ical'|'jcal'|'xcal' (defaults to ical)
* @since 32.0.0
*/
public function getFormat(): string {
return $this->format;
@ -52,6 +77,7 @@ final class CalendarImportOptions {
* Sets the import format
*
* @param 'ical'|'jcal'|'xcal' $value
* @since 32.0.0
*/
public function setFormat(string $value): void {
if (!in_array($value, self::FORMATS, true)) {
@ -62,6 +88,8 @@ final class CalendarImportOptions {
/**
* Gets whether to supersede existing objects
*
* @since 32.0.0
*/
public function getSupersede(): bool {
return $this->supersede;
@ -69,6 +97,8 @@ final class CalendarImportOptions {
/**
* Sets whether to supersede existing objects
*
* @since 32.0.0
*/
public function setSupersede(bool $supersede): void {
$this->supersede = $supersede;
@ -78,6 +108,7 @@ final class CalendarImportOptions {
* Gets how to handle object errors
*
* @return int 0 - continue, 1 - fail
* @since 32.0.0
*/
public function getErrors(): int {
return $this->errors;
@ -89,6 +120,7 @@ final class CalendarImportOptions {
* @param int $value 0 - continue, 1 - fail
*
* @template $value of self::ERROR_*
* @since 32.0.0
*/
public function setErrors(int $value): void {
if (!in_array($value, CalendarImportOptions::ERROR_OPTIONS, true)) {
@ -101,6 +133,7 @@ final class CalendarImportOptions {
* Gets how to handle object validation
*
* @return int 0 - no validation, 1 - validate and skip on issue, 2 - validate and fail on issue
* @since 32.0.0
*/
public function getValidate(): int {
return $this->validate;
@ -112,6 +145,7 @@ final class CalendarImportOptions {
* @param int $value 0 - no validation, 1 - validate and skip on issue, 2 - validate and fail on issue
*
* @template $value of self::VALIDATE_*
* @since 32.0.0
*/
public function setValidate(int $value): void {
if (!in_array($value, CalendarImportOptions::VALIDATE_OPTIONS, true)) {

View file

@ -57,7 +57,7 @@ class CommentsEvent extends Event {
/**
* @since 9.0.0
* @depreacted Since 33.0.0 use instanceof CommentAddedEvent, CommentRemovedEvent, CommentUpdatedEvent or BeforeCommentUpdatedEvent instead.
* @deprecated 33.0.0 Use instanceof CommentAddedEvent, CommentRemovedEvent, CommentUpdatedEvent or BeforeCommentUpdatedEvent instead.
*/
public function getEvent(): string {
return $this->event;

View file

@ -20,6 +20,8 @@ use OCP\Comments\IComment;
final class BeforeCommentUpdatedEvent extends CommentsEvent {
/**
* CommentEvent constructor.
*
* @since 33.0.0
*/
public function __construct(IComment $comment) {
/** @psalm-suppress DeprecatedConstant */

View file

@ -20,6 +20,8 @@ use OCP\Comments\IComment;
final class CommentAddedEvent extends CommentsEvent {
/**
* CommentAddedEvent constructor.
*
* @since 33.0.0
*/
public function __construct(IComment $comment) {
/** @psalm-suppress DeprecatedConstant */

View file

@ -20,6 +20,8 @@ use OCP\Comments\IComment;
final class CommentDeletedEvent extends CommentsEvent {
/**
* CommentRemovedEvent constructor.
*
* @since 33.0.0
*/
public function __construct(IComment $comment) {
/** @psalm-suppress DeprecatedConstant */

View file

@ -20,6 +20,8 @@ use OCP\Comments\IComment;
final class CommentUpdatedEvent extends CommentsEvent {
/**
* CommentUpdatedEvent constructor.
*
* @since 33.0.0
*/
public function __construct(IComment $comment) {
/** @psalm-suppress DeprecatedConstant */

View file

@ -17,6 +17,9 @@ use OCP\EventDispatcher\Event;
* @since 32.0.0
*/
class ContentProviderRegisterEvent extends Event {
/**
* @since 32.0.0
*/
public function __construct(
private IContentManager $contentManager,
) {

View file

@ -13,6 +13,12 @@ namespace OCP\ContextChat\Type;
* @since 32.0.0
*/
class UpdateAccessOp {
/**
* @since 32.0.0
*/
public const ALLOW = 'allow';
/**
* @since 32.0.0
*/
public const DENY = 'deny';
}

View file

@ -12,15 +12,19 @@ namespace OCP\DB\QueryBuilder;
/**
* Conflict resolution mode for "FOR UPDATE" select queries.
*
* @since 34.0.0
* @since 33.0.0
*/
enum ConflictResolutionMode {
/**
* Wait for the row to be unlocked.
*
* @since 33.0.0
*/
case Ordinary;
/**
* Skip the row if it is locked.
*
* @since 33.0.0
*/
case SkipLocked;
}

View file

@ -1097,7 +1097,7 @@ interface IQueryBuilder {
* Locks the queried rows for a subsequent update.
*
* @return $this
* @since 34.0.0
* @since 33.0.0
*/
public function forUpdate(ConflictResolutionMode $conflictResolutionMode = ConflictResolutionMode::Ordinary): self;
}

View file

@ -18,6 +18,9 @@ use OCP\Files\Config\ICachedMountInfo;
* @since 32.0.0
*/
class UserMountAddedEvent extends Event {
/**
* @since 32.0.0
*/
public function __construct(
public readonly ICachedMountInfo $mountPoint,
) {

View file

@ -18,6 +18,9 @@ use OCP\Files\Config\ICachedMountInfo;
* @since 32.0.0
*/
class UserMountRemovedEvent extends Event {
/**
* @since 32.0.0
*/
public function __construct(
public readonly ICachedMountInfo $mountPoint,
) {

View file

@ -18,6 +18,9 @@ use OCP\Files\Config\ICachedMountInfo;
* @since 32.0.0
*/
class UserMountUpdatedEvent extends Event {
/**
* @since 32.0.0
*/
public function __construct(
public readonly ICachedMountInfo $oldMountPoint,
public readonly ICachedMountInfo $newMountPoint,

View file

@ -50,6 +50,7 @@ interface IPartialMountProvider extends IMountProvider {
* in the scope of the setup request.
* @param IStorageFactory $loader
* @return array<string, IMountPoint> IMountPoint instances, indexed by mount-point
* @since 33.0.0
*/
public function getMountsForPath(
string $setupPathHint,

View file

@ -16,6 +16,9 @@ use OCP\Files\Cache\ICacheEntry;
* @since 33.0.0
*/
class MountProviderArgs {
/**
* @since 33.0.0
*/
public function __construct(
public readonly ICachedMountInfo $mountInfo,
public readonly ICacheEntry $cacheEntry,

View file

@ -34,18 +34,30 @@ class ConversionMimeProvider implements JsonSerializable {
) {
}
/**
* @since 31.0.0
*/
public function getFrom(): string {
return $this->from;
}
/**
* @since 31.0.0
*/
public function getTo(): string {
return $this->to;
}
/**
* @since 31.0.0
*/
public function getExtension(): string {
return $this->extension;
}
/**
* @since 31.0.0
*/
public function getDisplayName(): string {
return $this->displayName;
}

View file

@ -18,6 +18,9 @@ use OCP\EventDispatcher\Event;
* @since 33.0.0
*/
class BeforeRemotePropfindEvent extends Event {
/**
* @since 33.0.0
*/
public function __construct(
private array $properties,
) {

View file

@ -17,6 +17,9 @@ use OCP\EventDispatcher\Event;
#[Consumable(since: '33.0.0')]
class BucketCreatedEvent extends Event {
/**
* @since 33.0.0
*/
public function __construct(
private readonly string $bucket,
private readonly string $endpoint,
@ -26,18 +29,30 @@ class BucketCreatedEvent extends Event {
parent::__construct();
}
/**
* @since 33.0.0
*/
public function getBucket(): string {
return $this->bucket;
}
/**
* @since 33.0.0
*/
public function getEndpoint(): string {
return $this->endpoint;
}
/**
* @since 33.0.0
*/
public function getRegion(): string {
return $this->region;
}
/**
* @since 33.0.0
*/
public function getVersion(): string {
return $this->version;
}

View file

@ -11,9 +11,24 @@ namespace OCP\Files\Template;
* @since 30.0.0
*/
enum FieldType: string {
/**
* @since 30.0.0
*/
case RichText = 'rich-text';
/**
* @since 30.0.0
*/
case CheckBox = 'checkbox';
/**
* @since 30.0.0
*/
case DropDownList = 'drop-down-list';
/**
* @since 30.0.0
*/
case Picture = 'picture';
/**
* @since 30.0.0
*/
case Date = 'date';
}

View file

@ -17,8 +17,20 @@ use OCP\AppFramework\Attribute\Consumable;
*/
#[Consumable(since: '33.0.0')]
enum ParamType: string {
/**
* @since 33.0.0
*/
case STRING = 'string';
/**
* @since 33.0.0
*/
case INT = 'int';
/**
* @since 33.0.0
*/
case FLOAT = 'float';
/**
* @since 33.0.0
*/
case BOOL = 'bool';
}

View file

@ -13,6 +13,9 @@ namespace OCP\OpenMetrics;
* @since 33.0.0
*/
final readonly class Metric {
/**
* @since 33.0.0
*/
public function __construct(
public int|float|bool|MetricValue $value = false,
/** @var string[] */
@ -21,6 +24,9 @@ final readonly class Metric {
) {
}
/**
* @since 33.0.0
*/
public function label(string $name): ?string {
return $this->labels[$name] ?? null;
}

View file

@ -15,12 +15,36 @@ namespace OCP\OpenMetrics;
* @since 33.0.0
*/
enum MetricType {
/**
* @since 33.0.0
*/
case counter;
/**
* @since 33.0.0
*/
case gauge;
/**
* @since 33.0.0
*/
case histogram;
/**
* @since 33.0.0
*/
case gaugehistogram;
/**
* @since 33.0.0
*/
case stateset;
/**
* @since 33.0.0
*/
case info;
/**
* @since 33.0.0
*/
case summary;
/**
* @since 33.0.0
*/
case unknown;
}

View file

@ -14,7 +14,16 @@ namespace OCP\OpenMetrics;
* @since 33.0.0
*/
enum MetricValue: string {
/**
* @since 33.0.0
*/
case NOT_A_NUMBER = 'NaN';
/**
* @since 33.0.0
*/
case POSITIVE_INFINITY = '+Inf';
/**
* @since 33.0.0
*/
case NEGATIVE_INFINITY = '-Inf';
}

View file

@ -23,6 +23,7 @@ final readonly class Snowflake {
* @psalm-param int<0,4095> $sequenceId
* @psalm-param non-negative-int $seconds
* @psalm-param int<0,999> $milliseconds
* @since 33.0.0
*/
public function __construct(
private int $serverId,
@ -36,6 +37,7 @@ final readonly class Snowflake {
/**
* @psalm-return int<0,1023>
* @since 33.0.0
*/
public function getServerId(): int {
return $this->serverId;
@ -43,17 +45,22 @@ final readonly class Snowflake {
/**
* @psalm-return int<0,4095>
* @since 33.0.0
*/
public function getSequenceId(): int {
return $this->sequenceId;
}
/**
* @since 33.0.0
*/
public function isCli(): bool {
return $this->isCli;
}
/**
* @psalm-return non-negative-int
* @since 33.0.0
*/
public function getSeconds(): int {
return $this->seconds;
@ -61,11 +68,15 @@ final readonly class Snowflake {
/**
* @psalm-return int<0,999>
* @since 33.0.0
*/
public function getMilliseconds(): int {
return $this->milliseconds;
}
/**
* @since 33.0.0
*/
public function getCreatedAt(): \DateTimeImmutable {
return $this->createdAt;
}

View file

@ -17,18 +17,57 @@ use OCP\TaskProcessing\Exception\ValidationException;
* @since 30.0.0
*/
enum EShapeType: int {
/**
* @since 30.0.0
*/
case Number = 0;
/**
* @since 30.0.0
*/
case Text = 1;
/**
* @since 30.0.0
*/
case Image = 2;
/**
* @since 30.0.0
*/
case Audio = 3;
/**
* @since 30.0.0
*/
case Video = 4;
/**
* @since 30.0.0
*/
case File = 5;
/**
* @since 30.0.0
*/
case Enum = 6;
/**
* @since 30.0.0
*/
case ListOfNumbers = 10;
/**
* @since 30.0.0
*/
case ListOfTexts = 11;
/**
* @since 30.0.0
*/
case ListOfImages = 12;
/**
* @since 30.0.0
*/
case ListOfAudios = 13;
/**
* @since 30.0.0
*/
case ListOfVideos = 14;
/**
* @since 30.0.0
*/
case ListOfFiles = 15;
/**

View file

@ -20,6 +20,9 @@ use OCP\TaskProcessing\ShapeDescriptor;
* @since 32.0.0
*/
class ContextAgentAudioInteraction implements IInternalTaskType {
/**
* @since 31.0.0
*/
public const ID = 'core:contextagent:audio-interaction';
private IL10N $l;

View file

@ -20,6 +20,9 @@ use OCP\TaskProcessing\ShapeDescriptor;
* @since 31.0.0
*/
class ContextAgentInteraction implements IInternalTaskType {
/**
* @since 31.0.0
*/
public const ID = 'core:contextagent:interaction';
private IL10N $l;

View file

@ -20,6 +20,9 @@ use OCP\TaskProcessing\ShapeDescriptor;
* @since 31.0.0
*/
class TextToTextChangeTone implements ITaskType {
/**
* @since 31.0.0
*/
public const ID = 'core:text2text:changetone';
private IL10N $l;

View file

@ -20,6 +20,9 @@ use OCP\TaskProcessing\ShapeDescriptor;
* @since 31.0.0
*/
class TextToTextChatWithTools implements IInternalTaskType {
/**
* @since 31.0.0
*/
public const ID = 'core:text2text:chatwithtools';
private IL10N $l;

View file

@ -42,6 +42,7 @@ interface ITemplate {
* This function assigns a variable in an array context. If the key already
* exists, the value will be appended. It can be accessed via
* $_[$key][$position] in the template.
* @since 32.0.0
*/
public function append(string $key, mixed $value): void;
}