diff options
Diffstat (limited to 'lib/public/AppFramework')
45 files changed, 380 insertions, 105 deletions
diff --git a/lib/public/AppFramework/ApiController.php b/lib/public/AppFramework/ApiController.php index dae80456e26..729582c8505 100644 --- a/lib/public/AppFramework/ApiController.php +++ b/lib/public/AppFramework/ApiController.php @@ -58,9 +58,8 @@ abstract class ApiController extends Controller { #[PublicPage] #[NoAdminRequired] public function preflightedCors() { - if (isset($this->request->server['HTTP_ORIGIN'])) { - $origin = $this->request->server['HTTP_ORIGIN']; - } else { + $origin = $this->request->getHeader('origin'); + if ($origin === '') { $origin = '*'; } diff --git a/lib/public/AppFramework/App.php b/lib/public/AppFramework/App.php index 06404baea70..c00fde47418 100644 --- a/lib/public/AppFramework/App.php +++ b/lib/public/AppFramework/App.php @@ -9,10 +9,10 @@ declare(strict_types=1); */ namespace OCP\AppFramework; -use OC\AppFramework\Routing\RouteConfig; -use OC\Route\Router; +use OC\AppFramework\Utility\SimpleContainer; use OC\ServerContainer; -use OCP\Route\IRouter; +use OCP\IConfig; +use OCP\Server; use Psr\Log\LoggerInterface; /** @@ -47,7 +47,7 @@ class App { * @since 6.0.0 */ public function __construct(string $appName, array $urlParams = []) { - $runIsSetupDirectly = \OC::$server->getConfig()->getSystemValueBool('debug') + $runIsSetupDirectly = Server::get(IConfig::class)->getSystemValueBool('debug') && !ini_get('zend.exception_ignore_args'); if ($runIsSetupDirectly) { @@ -58,23 +58,30 @@ class App { $classNameParts = explode('\\', trim($applicationClassName, '\\')); foreach ($e->getTrace() as $step) { - if (isset($step['class'], $step['function'], $step['args'][0]) && - $step['class'] === ServerContainer::class && - $step['function'] === 'query' && - $step['args'][0] === $applicationClassName) { + if (isset($step['class'], $step['function'], $step['args'][0]) + && $step['class'] === ServerContainer::class + && $step['function'] === 'query' + && $step['args'][0] === $applicationClassName) { $setUpViaQuery = true; break; - } elseif (isset($step['class'], $step['function'], $step['args'][0]) && - $step['class'] === ServerContainer::class && - $step['function'] === 'getAppContainer' && - $step['args'][1] === $classNameParts[1]) { + } elseif (isset($step['class'], $step['function'], $step['args'][0]) + && $step['class'] === ServerContainer::class + && $step['function'] === 'getAppContainer' + && $step['args'][1] === $classNameParts[1]) { + $setUpViaQuery = true; + break; + } elseif (isset($step['class'], $step['function'], $step['args'][0]) + && $step['class'] === SimpleContainer::class + && preg_match('/{closure:OC\\\\AppFramework\\\\Utility\\\\SimpleContainer::buildClass\\(\\):\\d+}/', $step['function']) + && $step['args'][0] === $this) { + /* We are setup through a lazy ghost, fine */ $setUpViaQuery = true; break; } } if (!$setUpViaQuery && $applicationClassName !== \OCP\AppFramework\App::class) { - \OCP\Server::get(LoggerInterface::class)->error($e->getMessage(), [ + Server::get(LoggerInterface::class)->error($e->getMessage(), [ 'app' => $appName, 'exception' => $e, ]); @@ -97,35 +104,6 @@ class App { } /** - * This function is to be called to create single routes and restful routes based on the given $routes array. - * - * Example code in routes.php of tasks app (it will register two restful resources): - * $routes = array( - * 'resources' => array( - * 'lists' => array('url' => '/tasklists'), - * 'tasks' => array('url' => '/tasklists/{listId}/tasks') - * ) - * ); - * - * $a = new TasksApp(); - * $a->registerRoutes($this, $routes); - * - * @param \OCP\Route\IRouter $router - * @param array $routes - * @since 6.0.0 - * @suppress PhanAccessMethodInternal - * @deprecated 20.0.0 Just return an array from your routes.php - */ - public function registerRoutes(IRouter $router, array $routes) { - if (!($router instanceof Router)) { - throw new \RuntimeException('Can only setup routes with real router'); - } - - $routeConfig = new RouteConfig($this->container, $router, $routes); - $routeConfig->register(); - } - - /** * This function is called by the routing component to fire up the frameworks dispatch mechanism. * * Example code in routes.php of the task app: diff --git a/lib/public/AppFramework/Attribute/ASince.php b/lib/public/AppFramework/Attribute/ASince.php new file mode 100644 index 00000000000..1e0c45348cf --- /dev/null +++ b/lib/public/AppFramework/Attribute/ASince.php @@ -0,0 +1,34 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\AppFramework\Attribute; + +use Attribute; + +/** + * Abstract base attribute to declare an API's stability. + * + * @since 32.0.0 + */ +#[Consumable(since: '32.0.0')] +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. + */ + public function __construct( + protected string $since, + ) { + } + + public function getSince(): string { + return $this->since; + } +} diff --git a/lib/public/AppFramework/Attribute/Catchable.php b/lib/public/AppFramework/Attribute/Catchable.php new file mode 100644 index 00000000000..d45401550f6 --- /dev/null +++ b/lib/public/AppFramework/Attribute/Catchable.php @@ -0,0 +1,23 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\AppFramework\Attribute; + +use Attribute; + +/** + * Attribute to declare that the exception is "catchable" by apps. + * + * @since 32.0.0 + */ +#[Attribute(Attribute::TARGET_ALL | Attribute::IS_REPEATABLE)] +#[Consumable(since: '32.0.0')] +#[Implementable(since: '32.0.0')] +class Catchable extends ASince { +} diff --git a/lib/public/AppFramework/Attribute/Consumable.php b/lib/public/AppFramework/Attribute/Consumable.php new file mode 100644 index 00000000000..2175bb0af88 --- /dev/null +++ b/lib/public/AppFramework/Attribute/Consumable.php @@ -0,0 +1,27 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\AppFramework\Attribute; + +use Attribute; + +/** + * Attribute to declare that the API stability is limited to "consuming" the + * class, interface, enum, etc. Apps are not allowed to implement or replace them. + * + * For events use @see \OCP\AppFramework\Attribute\Listenable + * For exceptions use @see \OCP\AppFramework\Attribute\Catchable + * + * @since 32.0.0 + */ +#[Attribute(Attribute::TARGET_ALL | Attribute::IS_REPEATABLE)] +#[Consumable(since: '32.0.0')] +#[Implementable(since: '32.0.0')] +class Consumable extends ASince { +} diff --git a/lib/public/AppFramework/Attribute/Dispatchable.php b/lib/public/AppFramework/Attribute/Dispatchable.php new file mode 100644 index 00000000000..ff703d4749e --- /dev/null +++ b/lib/public/AppFramework/Attribute/Dispatchable.php @@ -0,0 +1,23 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\AppFramework\Attribute; + +use Attribute; + +/** + * Attribute to declare that the event is "dispatchable" by apps. + * + * @since 32.0.0 + */ +#[Attribute(Attribute::TARGET_ALL | Attribute::IS_REPEATABLE)] +#[Consumable(since: '32.0.0')] +#[Implementable(since: '32.0.0')] +class Dispatchable extends ASince { +} diff --git a/lib/public/AppFramework/Attribute/ExceptionalImplementable.php b/lib/public/AppFramework/Attribute/ExceptionalImplementable.php new file mode 100644 index 00000000000..23e9f830d9b --- /dev/null +++ b/lib/public/AppFramework/Attribute/ExceptionalImplementable.php @@ -0,0 +1,38 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\AppFramework\Attribute; + +use Attribute; + +/** + * Attribute to declare that the API marked as Consumable/Listenable/Catchable + * has an exception and is Implementable/Dispatchable/Throwable by a dedicated + * app. Changes to such an API have to be communicated to the affected app maintainers. + * + * @since 32.0.0 + */ +#[Attribute(Attribute::TARGET_ALL | Attribute::IS_REPEATABLE)] +#[Consumable(since: '32.0.0')] +#[Implementable(since: '32.0.0')] +class ExceptionalImplementable { + public function __construct( + protected string $app, + protected ?string $class = null, + ) { + } + + public function getApp(): string { + return $this->app; + } + + public function getClass(): ?string { + return $this->class; + } +} diff --git a/lib/public/AppFramework/Attribute/Implementable.php b/lib/public/AppFramework/Attribute/Implementable.php new file mode 100644 index 00000000000..40ce0e0cf06 --- /dev/null +++ b/lib/public/AppFramework/Attribute/Implementable.php @@ -0,0 +1,27 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\AppFramework\Attribute; + +use Attribute; + +/** + * Attribute to declare that the API stability is limited to "implementing" the + * class, interface, enum, etc. + * + * For events use @see \OCP\AppFramework\Attribute\Dispatchable + * For exceptions use @see \OCP\AppFramework\Attribute\Throwable + * + * @since 32.0.0 + */ +#[Attribute(Attribute::TARGET_ALL | Attribute::IS_REPEATABLE)] +#[Consumable(since: '32.0.0')] +#[Implementable(since: '32.0.0')] +class Implementable extends ASince { +} diff --git a/lib/public/AppFramework/Attribute/Listenable.php b/lib/public/AppFramework/Attribute/Listenable.php new file mode 100644 index 00000000000..98c2ca78690 --- /dev/null +++ b/lib/public/AppFramework/Attribute/Listenable.php @@ -0,0 +1,23 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\AppFramework\Attribute; + +use Attribute; + +/** + * Attribute to declare that the event is "listenable" by apps. + * + * @since 32.0.0 + */ +#[Attribute(Attribute::TARGET_ALL | Attribute::IS_REPEATABLE)] +#[Consumable(since: '32.0.0')] +#[Implementable(since: '32.0.0')] +class Listenable extends ASince { +} diff --git a/lib/public/AppFramework/Attribute/Throwable.php b/lib/public/AppFramework/Attribute/Throwable.php new file mode 100644 index 00000000000..2c763c76b4c --- /dev/null +++ b/lib/public/AppFramework/Attribute/Throwable.php @@ -0,0 +1,23 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\AppFramework\Attribute; + +use Attribute; + +/** + * Attribute to declare that the exception is "throwable" by apps. + * + * @since 32.0.0 + */ +#[Attribute(Attribute::TARGET_ALL | Attribute::IS_REPEATABLE)] +#[Consumable(since: '32.0.0')] +#[Implementable(since: '32.0.0')] +class Throwable extends ASince { +} diff --git a/lib/public/AppFramework/Bootstrap/IBootstrap.php b/lib/public/AppFramework/Bootstrap/IBootstrap.php index 81c34524191..7260d2b77a1 100644 --- a/lib/public/AppFramework/Bootstrap/IBootstrap.php +++ b/lib/public/AppFramework/Bootstrap/IBootstrap.php @@ -25,8 +25,6 @@ interface IBootstrap { * At this stage you can assume that all services are registered and the DI * container(s) are ready to be queried. * - * This is also the state where an optional `appinfo/app.php` was loaded. - * * @param IBootContext $context * * @since 20.0.0 diff --git a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php index b9e5413e5c2..011d1520414 100644 --- a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php +++ b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php @@ -415,6 +415,19 @@ interface IRegistrationContext { public function registerTaskProcessingTaskType(string $taskProcessingTaskTypeClass): void; /** + * Register an implementation of \OCP\Files\Conversion\IConversionProvider + * that will handle the conversion of files from one MIME type to another + * + * @param string $class + * @psalm-param class-string<\OCP\Files\Conversion\IConversionProvider> $class + * + * @return void + * + * @since 31.0.0 + */ + public function registerFileConversionProvider(string $class): void; + + /** * Register a mail provider * * @param string $class @@ -423,4 +436,15 @@ interface IRegistrationContext { */ public function registerMailProvider(string $class): void; + + /** + * Register an implementation of \OCP\Config\Lexicon\IConfigLexicon that + * will handle the config lexicon + * + * @param string $configLexiconClass + * + * @psalm-param class-string<\NCU\Config\Lexicon\IConfigLexicon> $configLexiconClass + * @since 31.0.0 + */ + public function registerConfigLexicon(string $configLexiconClass): void; } diff --git a/lib/public/AppFramework/Controller.php b/lib/public/AppFramework/Controller.php index 7c25b3382e7..cdeaac99366 100644 --- a/lib/public/AppFramework/Controller.php +++ b/lib/public/AppFramework/Controller.php @@ -135,7 +135,7 @@ abstract class Controller { return $responder($response); } - throw new \DomainException('No responder registered for format ' . - $format . '!'); + throw new \DomainException('No responder registered for format ' + . $format . '!'); } } diff --git a/lib/public/AppFramework/Db/Entity.php b/lib/public/AppFramework/Db/Entity.php index d90d3ed4837..3094070af5f 100644 --- a/lib/public/AppFramework/Db/Entity.php +++ b/lib/public/AppFramework/Db/Entity.php @@ -159,8 +159,8 @@ abstract class Entity { if (property_exists($this, $name)) { return $this->$name; } else { - throw new \BadFunctionCallException($name . - ' is not a valid attribute'); + throw new \BadFunctionCallException($name + . ' is not a valid attribute'); } } @@ -180,8 +180,8 @@ abstract class Entity { } elseif ($this->isGetterForBoolProperty($methodName)) { return $this->getter(lcfirst(substr($methodName, 2))); } else { - throw new \BadFunctionCallException($methodName . - ' does not exist'); + throw new \BadFunctionCallException($methodName + . ' does not exist'); } } @@ -215,7 +215,7 @@ abstract class Entity { * @return string the property name * @since 7.0.0 */ - public function columnToProperty(string $columnName): string { + public function columnToProperty(string $columnName) { $parts = explode('_', $columnName); $property = ''; diff --git a/lib/public/AppFramework/Db/QBMapper.php b/lib/public/AppFramework/Db/QBMapper.php index 4071a4a47a4..7fb5b2a9afd 100644 --- a/lib/public/AppFramework/Db/QBMapper.php +++ b/lib/public/AppFramework/Db/QBMapper.php @@ -296,8 +296,8 @@ abstract class QBMapper { * @since 14.0.0 */ private function buildDebugMessage(string $msg, IQueryBuilder $sql): string { - return $msg . - ': query "' . $sql->getSQL() . '"; '; + return $msg + . ': query "' . $sql->getSQL() . '"; '; } diff --git a/lib/public/AppFramework/Http/Attribute/CORS.php b/lib/public/AppFramework/Http/Attribute/CORS.php index 2c3eac362cf..ff639635635 100644 --- a/lib/public/AppFramework/Http/Attribute/CORS.php +++ b/lib/public/AppFramework/Http/Attribute/CORS.php @@ -12,7 +12,9 @@ namespace OCP\AppFramework\Http\Attribute; use Attribute; /** - * Attribute for controller methods that can also be accessed by not logged-in user + * Attribute for controller methods that can also be accessed by other websites. + * See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS for an explanation of the functionality and the security implications. + * See https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/rest_apis.html on how to implement it in your controller. * * @since 27.0.0 */ diff --git a/lib/public/AppFramework/Http/Attribute/RequestHeader.php b/lib/public/AppFramework/Http/Attribute/RequestHeader.php new file mode 100644 index 00000000000..1d0fbbfa0c3 --- /dev/null +++ b/lib/public/AppFramework/Http/Attribute/RequestHeader.php @@ -0,0 +1,34 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\AppFramework\Http\Attribute; + +use Attribute; + +/** + * This attribute allows documenting request headers and is primarily intended for OpenAPI documentation. + * It should be added whenever you use a request header in a controller method, in order to properly describe the header and its functionality. + * There are no checks that ensure the header is set, so you will still need to do this yourself in the controller method. + * + * @since 32.0.0 + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +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. + */ + public function __construct( + protected string $name, + protected string $description, + protected bool $indirect = false, + ) { + } +} diff --git a/lib/public/AppFramework/Http/DataDisplayResponse.php b/lib/public/AppFramework/Http/DataDisplayResponse.php index 889c57a7901..e1ded910328 100644 --- a/lib/public/AppFramework/Http/DataDisplayResponse.php +++ b/lib/public/AppFramework/Http/DataDisplayResponse.php @@ -13,9 +13,9 @@ use OCP\AppFramework\Http; * Class DataDisplayResponse * * @since 8.1.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class DataDisplayResponse extends Response { /** diff --git a/lib/public/AppFramework/Http/DataDownloadResponse.php b/lib/public/AppFramework/Http/DataDownloadResponse.php index 80100137c48..ee6bcf0d0c5 100644 --- a/lib/public/AppFramework/Http/DataDownloadResponse.php +++ b/lib/public/AppFramework/Http/DataDownloadResponse.php @@ -13,10 +13,10 @@ use OCP\AppFramework\Http; * Class DataDownloadResponse * * @since 8.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template C of string * @template H of array<string, mixed> - * @template-extends DownloadResponse<int, string, array<string, mixed>> + * @template-extends DownloadResponse<Http::STATUS_*, string, array<string, mixed>> */ class DataDownloadResponse extends DownloadResponse { /** diff --git a/lib/public/AppFramework/Http/DataResponse.php b/lib/public/AppFramework/Http/DataResponse.php index 2ebb66f9e73..2b54ce848ef 100644 --- a/lib/public/AppFramework/Http/DataResponse.php +++ b/lib/public/AppFramework/Http/DataResponse.php @@ -14,10 +14,10 @@ use OCP\AppFramework\Http; * for responders to transform * @since 8.0.0 * @psalm-type DataResponseType = array|int|float|string|bool|object|null|\stdClass|\JsonSerializable - * @template S of int + * @template S of Http::STATUS_* * @template-covariant T of DataResponseType * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class DataResponse extends Response { /** diff --git a/lib/public/AppFramework/Http/DownloadResponse.php b/lib/public/AppFramework/Http/DownloadResponse.php index 058b3070297..190de022d36 100644 --- a/lib/public/AppFramework/Http/DownloadResponse.php +++ b/lib/public/AppFramework/Http/DownloadResponse.php @@ -12,10 +12,10 @@ use OCP\AppFramework\Http; /** * Prompts the user to download the a file * @since 7.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template C of string * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class DownloadResponse extends Response { /** diff --git a/lib/public/AppFramework/Http/FileDisplayResponse.php b/lib/public/AppFramework/Http/FileDisplayResponse.php index 0cc51f7c59f..c18404b7d91 100644 --- a/lib/public/AppFramework/Http/FileDisplayResponse.php +++ b/lib/public/AppFramework/Http/FileDisplayResponse.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -13,9 +14,9 @@ use OCP\Files\SimpleFS\ISimpleFile; * Class FileDisplayResponse * * @since 11.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class FileDisplayResponse extends Response implements ICallbackResponse { /** @var File|ISimpleFile */ diff --git a/lib/public/AppFramework/Http/JSONResponse.php b/lib/public/AppFramework/Http/JSONResponse.php index afe36c4a8c3..a226e29a1b5 100644 --- a/lib/public/AppFramework/Http/JSONResponse.php +++ b/lib/public/AppFramework/Http/JSONResponse.php @@ -12,10 +12,10 @@ use OCP\AppFramework\Http; /** * A renderer for JSON calls * @since 6.0.0 - * @template S of int - * @template-covariant T of array|object|\stdClass|\JsonSerializable + * @template S of Http::STATUS_* + * @template-covariant T of null|string|int|float|bool|array|\stdClass|\JsonSerializable * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class JSONResponse extends Response { /** @@ -58,6 +58,9 @@ class JSONResponse extends Response { * @return string the rendered json * @since 6.0.0 * @throws \Exception If data could not get encoded + * + * @psalm-taint-escape has_quotes + * @psalm-taint-escape html */ public function render() { return json_encode($this->data, JSON_HEX_TAG | JSON_THROW_ON_ERROR | $this->encodeFlags, 2048); diff --git a/lib/public/AppFramework/Http/NotFoundResponse.php b/lib/public/AppFramework/Http/NotFoundResponse.php index 9ebefe69be1..137d1a26655 100644 --- a/lib/public/AppFramework/Http/NotFoundResponse.php +++ b/lib/public/AppFramework/Http/NotFoundResponse.php @@ -12,9 +12,9 @@ use OCP\AppFramework\Http; /** * A generic 404 response showing an 404 error page as well to the end-user * @since 8.1.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends TemplateResponse<int, array<string, mixed>> + * @template-extends TemplateResponse<Http::STATUS_*, array<string, mixed>> */ class NotFoundResponse extends TemplateResponse { /** diff --git a/lib/public/AppFramework/Http/RedirectResponse.php b/lib/public/AppFramework/Http/RedirectResponse.php index 41fc4d83856..74847205976 100644 --- a/lib/public/AppFramework/Http/RedirectResponse.php +++ b/lib/public/AppFramework/Http/RedirectResponse.php @@ -12,9 +12,9 @@ use OCP\AppFramework\Http; /** * Redirects to a different URL * @since 7.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class RedirectResponse extends Response { private $redirectURL; diff --git a/lib/public/AppFramework/Http/RedirectToDefaultAppResponse.php b/lib/public/AppFramework/Http/RedirectToDefaultAppResponse.php index 3e2fcf6f6c7..0a0c04f671d 100644 --- a/lib/public/AppFramework/Http/RedirectToDefaultAppResponse.php +++ b/lib/public/AppFramework/Http/RedirectToDefaultAppResponse.php @@ -16,9 +16,9 @@ use OCP\IURLGenerator; * * @since 16.0.0 * @deprecated 23.0.0 Use RedirectResponse() with IURLGenerator::linkToDefaultPageUrl() instead - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends RedirectResponse<int, array<string, mixed>> + * @template-extends RedirectResponse<Http::STATUS_*, array<string, mixed>> */ class RedirectToDefaultAppResponse extends RedirectResponse { /** @@ -30,8 +30,7 @@ class RedirectToDefaultAppResponse extends RedirectResponse { * @deprecated 23.0.0 Use RedirectResponse() with IURLGenerator::linkToDefaultPageUrl() instead */ public function __construct(int $status = Http::STATUS_SEE_OTHER, array $headers = []) { - /** @var IURLGenerator $urlGenerator */ - $urlGenerator = \OC::$server->get(IURLGenerator::class); + $urlGenerator = \OCP\Server::get(IURLGenerator::class); parent::__construct($urlGenerator->linkToDefaultPageUrl(), $status, $headers); } } diff --git a/lib/public/AppFramework/Http/Response.php b/lib/public/AppFramework/Http/Response.php index d1860402359..bdebb12c00d 100644 --- a/lib/public/AppFramework/Http/Response.php +++ b/lib/public/AppFramework/Http/Response.php @@ -18,7 +18,7 @@ use Psr\Log\LoggerInterface; * * It handles headers, HTTP status code, last modified and ETag. * @since 6.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> */ class Response { @@ -93,11 +93,10 @@ class Response { // Set expires header $expires = new \DateTime(); - /** @var ITimeFactory $time */ $time = \OCP\Server::get(ITimeFactory::class); $expires->setTimestamp($time->getTime()); $expires->add(new \DateInterval('PT' . $cacheSeconds . 'S')); - $this->addHeader('Expires', $expires->format(\DateTimeInterface::RFC2822)); + $this->addHeader('Expires', $expires->format(\DateTimeInterface::RFC7231)); } else { $this->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); unset($this->headers['Expires']); @@ -184,10 +183,10 @@ class Response { if ($this->status === Http::STATUS_NOT_MODIFIED && stripos($name, 'x-') === 0) { /** @var IConfig $config */ - $config = \OC::$server->get(IConfig::class); + $config = \OCP\Server::get(IConfig::class); if ($config->getSystemValueBool('debug', false)) { - \OC::$server->get(LoggerInterface::class)->error('Setting custom header on a 304 is not supported (Header: {header})', [ + \OCP\Server::get(LoggerInterface::class)->error('Setting custom header on a 304 is not supported (Header: {header})', [ 'header' => $name, ]); } @@ -229,7 +228,7 @@ class Response { /** * @psalm-suppress UndefinedClass */ - $request = \OC::$server->get(IRequest::class); + $request = \OCP\Server::get(IRequest::class); $mergeWith = [ 'X-Request-Id' => $request->getId(), 'Cache-Control' => 'no-cache, no-store, must-revalidate', @@ -239,7 +238,7 @@ class Response { ]; if ($this->lastModified) { - $mergeWith['Last-Modified'] = $this->lastModified->format(\DateTimeInterface::RFC2822); + $mergeWith['Last-Modified'] = $this->lastModified->format(\DateTimeInterface::RFC7231); } if ($this->ETag) { diff --git a/lib/public/AppFramework/Http/StandaloneTemplateResponse.php b/lib/public/AppFramework/Http/StandaloneTemplateResponse.php index f729bd772fb..244a6b80f9f 100644 --- a/lib/public/AppFramework/Http/StandaloneTemplateResponse.php +++ b/lib/public/AppFramework/Http/StandaloneTemplateResponse.php @@ -7,6 +7,8 @@ declare(strict_types=1); */ namespace OCP\AppFramework\Http; +use OCP\AppFramework\Http; + /** * A template response that does not emit the loadAdditionalScripts events. * @@ -14,9 +16,9 @@ namespace OCP\AppFramework\Http; * full nextcloud UI. Like the 2FA page, or the grant page in the login flow. * * @since 16.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends TemplateResponse<int, array<string, mixed>> + * @template-extends TemplateResponse<Http::STATUS_*, array<string, mixed>> */ class StandaloneTemplateResponse extends TemplateResponse { } diff --git a/lib/public/AppFramework/Http/StreamResponse.php b/lib/public/AppFramework/Http/StreamResponse.php index 1039e20e5c5..d0e6e3e148a 100644 --- a/lib/public/AppFramework/Http/StreamResponse.php +++ b/lib/public/AppFramework/Http/StreamResponse.php @@ -13,9 +13,9 @@ use OCP\AppFramework\Http; * Class StreamResponse * * @since 8.1.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class StreamResponse extends Response implements ICallbackResponse { /** @var string */ diff --git a/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php b/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php index 4f958a2620c..281bb559a10 100644 --- a/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php +++ b/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/Http/Template/IMenuAction.php b/lib/public/AppFramework/Http/Template/IMenuAction.php index 50b346add86..124e95fe019 100644 --- a/lib/public/AppFramework/Http/Template/IMenuAction.php +++ b/lib/public/AppFramework/Http/Template/IMenuAction.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/Http/Template/LinkMenuAction.php b/lib/public/AppFramework/Http/Template/LinkMenuAction.php index 6ae1fcdf13b..391802a1dce 100644 --- a/lib/public/AppFramework/Http/Template/LinkMenuAction.php +++ b/lib/public/AppFramework/Http/Template/LinkMenuAction.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php b/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php index 1000f4db549..4c156cdecea 100644 --- a/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php +++ b/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -15,8 +16,8 @@ use OCP\IInitialStateService; * * @since 14.0.0 * @template H of array<string, mixed> - * @template S of int - * @template-extends TemplateResponse<int, array<string, mixed>> + * @template S of Http::STATUS_* + * @template-extends TemplateResponse<Http::STATUS_*, array<string, mixed>> */ class PublicTemplateResponse extends TemplateResponse { private $headerTitle = ''; @@ -44,6 +45,7 @@ class PublicTemplateResponse extends TemplateResponse { ) { parent::__construct($appName, $templateName, $params, 'public', $status, $headers); \OCP\Util::addScript('core', 'public-page-menu'); + \OCP\Util::addScript('core', 'public-page-user-menu'); $state = \OCP\Server::get(IInitialStateService::class); $state->provideLazyInitialState('core', 'public-page-menu', function () { diff --git a/lib/public/AppFramework/Http/Template/SimpleMenuAction.php b/lib/public/AppFramework/Http/Template/SimpleMenuAction.php index 4cbbd5302d7..03cb9b4c7ea 100644 --- a/lib/public/AppFramework/Http/Template/SimpleMenuAction.php +++ b/lib/public/AppFramework/Http/Template/SimpleMenuAction.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/Http/TemplateResponse.php b/lib/public/AppFramework/Http/TemplateResponse.php index 2c7567c080b..af37a1a2313 100644 --- a/lib/public/AppFramework/Http/TemplateResponse.php +++ b/lib/public/AppFramework/Http/TemplateResponse.php @@ -1,21 +1,27 @@ <?php +declare(strict_types=1); + + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ + namespace OCP\AppFramework\Http; use OCP\AppFramework\Http; +use OCP\Server; +use OCP\Template\ITemplateManager; /** * Response for a normal template * @since 6.0.0 * - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class TemplateResponse extends Response { /** @@ -180,7 +186,7 @@ class TemplateResponse extends Response { $renderAs = $this->renderAs; } - $template = new \OCP\Template($this->appName, $this->templateName, $renderAs); + $template = Server::get(ITemplateManager::class)->getTemplate($this->appName, $this->templateName, $renderAs); foreach ($this->params as $key => $value) { $template->assign($key, $value); diff --git a/lib/public/AppFramework/Http/TextPlainResponse.php b/lib/public/AppFramework/Http/TextPlainResponse.php index e7c728c37ab..9dfa2c5544d 100644 --- a/lib/public/AppFramework/Http/TextPlainResponse.php +++ b/lib/public/AppFramework/Http/TextPlainResponse.php @@ -12,9 +12,9 @@ use OCP\AppFramework\Http; /** * A renderer for text responses * @since 22.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class TextPlainResponse extends Response { /** @var string */ diff --git a/lib/public/AppFramework/Http/TooManyRequestsResponse.php b/lib/public/AppFramework/Http/TooManyRequestsResponse.php index b7b0a98c9e1..f7084ec768d 100644 --- a/lib/public/AppFramework/Http/TooManyRequestsResponse.php +++ b/lib/public/AppFramework/Http/TooManyRequestsResponse.php @@ -8,14 +8,15 @@ declare(strict_types=1); namespace OCP\AppFramework\Http; use OCP\AppFramework\Http; -use OCP\Template; +use OCP\Server; +use OCP\Template\ITemplateManager; /** * A generic 429 response showing an 404 error page as well to the end-user * @since 19.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class TooManyRequestsResponse extends Response { /** @@ -34,7 +35,7 @@ class TooManyRequestsResponse extends Response { * @since 19.0.0 */ public function render() { - $template = new Template('core', '429', 'blank'); + $template = Server::get(ITemplateManager::class)->getTemplate('core', '429', TemplateResponse::RENDER_AS_BLANK); return $template->fetchPage(); } } diff --git a/lib/public/AppFramework/Http/ZipResponse.php b/lib/public/AppFramework/Http/ZipResponse.php index 3b9e251d332..a552eb1294f 100644 --- a/lib/public/AppFramework/Http/ZipResponse.php +++ b/lib/public/AppFramework/Http/ZipResponse.php @@ -15,9 +15,9 @@ use OCP\IRequest; * Public library to send several files in one zip archive. * * @since 15.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class ZipResponse extends Response implements ICallbackResponse { /** @var array{internalName: string, resource: resource, size: int, time: int}[] Files to be added to the zip response */ diff --git a/lib/public/AppFramework/OCS/OCSBadRequestException.php b/lib/public/AppFramework/OCS/OCSBadRequestException.php index c229468fb0d..77b8ec6c86d 100644 --- a/lib/public/AppFramework/OCS/OCSBadRequestException.php +++ b/lib/public/AppFramework/OCS/OCSBadRequestException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/OCS/OCSException.php b/lib/public/AppFramework/OCS/OCSException.php index 962bad830e7..02901992f8d 100644 --- a/lib/public/AppFramework/OCS/OCSException.php +++ b/lib/public/AppFramework/OCS/OCSException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/OCS/OCSForbiddenException.php b/lib/public/AppFramework/OCS/OCSForbiddenException.php index 03b1db6104f..0d001377043 100644 --- a/lib/public/AppFramework/OCS/OCSForbiddenException.php +++ b/lib/public/AppFramework/OCS/OCSForbiddenException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/OCS/OCSNotFoundException.php b/lib/public/AppFramework/OCS/OCSNotFoundException.php index 997b0c390f9..67cea9ed759 100644 --- a/lib/public/AppFramework/OCS/OCSNotFoundException.php +++ b/lib/public/AppFramework/OCS/OCSNotFoundException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/OCS/OCSPreconditionFailedException.php b/lib/public/AppFramework/OCS/OCSPreconditionFailedException.php index 2e67263bcb9..4fc2820eaec 100644 --- a/lib/public/AppFramework/OCS/OCSPreconditionFailedException.php +++ b/lib/public/AppFramework/OCS/OCSPreconditionFailedException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/PublicShareController.php b/lib/public/AppFramework/PublicShareController.php index 458606455d1..999b3827565 100644 --- a/lib/public/AppFramework/PublicShareController.php +++ b/lib/public/AppFramework/PublicShareController.php @@ -98,8 +98,8 @@ abstract class PublicShareController extends Controller { } // If we are authenticated properly - if ($this->session->get('public_link_authenticated_token') === $this->getToken() && - $this->session->get('public_link_authenticated_password_hash') === $this->getPasswordHash()) { + if ($this->session->get('public_link_authenticated_token') === $this->getToken() + && $this->session->get('public_link_authenticated_password_hash') === $this->getPasswordHash()) { return true; } diff --git a/lib/public/AppFramework/Services/IInitialState.php b/lib/public/AppFramework/Services/IInitialState.php index 24698108d68..ac58bcad3cc 100644 --- a/lib/public/AppFramework/Services/IInitialState.php +++ b/lib/public/AppFramework/Services/IInitialState.php @@ -37,7 +37,7 @@ interface IInitialState { * * @param string $key * @param Closure $closure returns a primitive or an object that implements JsonSerializable - * @psalm-param Closure():bool|Closure():int|Closure():float|Closure():string|Closure():\JsonSerializable $closure + * @psalm-param Closure():bool|Closure():int|Closure():float|Closure():string|Closure():array|Closure():\JsonSerializable $closure */ public function provideLazyInitialState(string $key, Closure $closure): void; } |