Upgrade to Nextcloud 28
General
info.xml
Make sure your appinfo/info.xml allows for Nextcloud 28.
<dependencies>
    <nextcloud min-version="26" max-version="28" />
</dependencies>
Front-end changes
Added APIs
The new Files initialising much faster than the old one, you will face some race conditions if you register some custom properties loading your scripts by using the
Util::addScriptmethod. We recommend you use the newUtil::addInitScriptmethod instead, your script will be loaded right after the common core scripts and right before the Files app. See JavaScript for more information.File actions: to register file actions, please use the dedicated API from https://npmjs.org/@nextcloud/files or https://nextcloud-libraries.github.io/nextcloud-files/functions/registerFileAction.html
New file menu: to register entries in the new file menu, please use the dedicated API from https://npmjs.org/@nextcloud/files or https://nextcloud-libraries.github.io/nextcloud-files/functions/addNewFileMenuEntry.html
Reminder from 27, to interact with the Files app router, use
OCP.Files.Router. See FilesTo Interact with the Files app data, please use the following events. All of them have a Node object as main parameter.
files:node:created: the node has been createdfiles:node:deleted: the node has been deletedfiles:node:moved: the node has been moved (and its data is already updated)files:node:updated: the node data has been updated
Changed APIs
tbd
Deprecated APIs
The CSS variables
--color-text-lightand--color-text-lighterwere made aliases of--color-main-textand--color-text-maxcontrastin Nextcloud 20 and are now officially deprecated and will be removed in the near future.
Removed APIs
OC.loadScriptandOC.loadStyle: UseOCP.Loaderinstead.OC.appSettings: There is no replacement.OCA.Files: Everything removed but Sidebar and Settings. See the Added API section for replacements.
Back-end changes
PHP 8.3
In this release support for PHP 8.3 was added. Follow the steps below to make your app compatible.
If
appinfo/info.xmlhas a dependency specification for PHP, increase themax-versionto 8.3.
<dependencies>
  <php min-version="8.0" max-version="8.3" />
  <nextcloud min-version="26" max-version="28" />
</dependencies>
If your app has a
composer.jsonand the file contains the PHP restrictions frominfo.xml, adjust it as well.
{
  "require": {
    "php": ">=8.0 <=8.3"
  }
}
If you have continuous integration set up, extend your test matrix with PHP 8.3 tests and linters.
Information about code changes can be found on php.net and stitcher.io.
Development dependency hell
Due to the popularity of CLI tools for development of Nextcloud apps, the likelihood of package conflicts has increased. It’s highly recommended to see Development tools and migrate to composer bin directories.
Updated core libraries
If apps use only official public APIs of Nextcloud, the update of core libraries should have little to no effect on apps. However, there are some edge cases where an app still has a code dependency to a library shipped with Nextcloud, e.g. when those 3rdparty classes or functions are used, and therefore app developers are recommended to check their code for any incompatibility. Moreover it’s recommended to check compatibility with sophisticated tools, as documented at the static analysis section.
doctrine/dbal
The Doctrine Database Abstraction Layer powers Nextcloud’s database connection and query builder. In Nextcloud 28, this dependency was updated from 3.3 to 3.7.
Optimistically speaking, the database connection and the query builder should mostly work like in Nextcloud 27 or older. Some (minor) breaking changes were inevitable. Here’s the summary:
When a query builder instance is using positional parameters
->setValue('name', '?')setParameter(0, $name), all parameters need to be set again when executing the query multiple times, e.g. in a loop. It is recommended to switch to named parameters usingcreateParameter()instead.
The details of this change can also be seen in the pull request on GitHub and in the upstream documentation dbal 3.7.x upgrade document.
symfony/event-dispatcher
Over the last 2 major versions the symfony/event-dispatcher package first deprecated and then removed the way Nextcloud
server dispatched old events. This means the way we wrapped away symfony’s \Symfony\Component\EventDispatcher\EventDispatcherInterface
as well as using the \Symfony\Component\EventDispatcher\GenericEvent could not be kept alive in a backwards compatible way.
Therefore migrating from \Symfony\Component\EventDispatcher\EventDispatcherInterface
to \OCP\EventDispatcher\IEventDispatcher (exists since Nextcloud 17) is required to be compatible with Nextcloud 28.
All code places that dispatched a \Symfony\Component\EventDispatcher\GenericEvent have been adjusted
and have \OCP\EventDispatcher\Event based dedicated event now that is dispatched as a typed-event so all available parameters are documented.
The details of this change can also be seen in the todo items that are linked from the pull request on GitHub.
Added APIs
\OCP\AppFramework\Http\EmptyContentSecurityPolicy::useStrictDynamicOnScriptsto set ‘strict-dynamic’ on the ‘script-src-elem’ CSP, this is set by default to true to allow apps using module JS to import dependencies.\OCP\Mail\IMessage::setSubjectto set an email subject. See Email for an example.\OCP\Mail\IMessage::setHtmlBodyand\OCP\Mail\IMessage::setPlainBodyto set an email body See Email for an example.\OCP\IEventSourceFactoryto create aOCP\IEventSourceinstance.\OCP\Preview\BeforePreviewFetchedEvent::getCrop\OCP\Preview\BeforePreviewFetchedEvent::getHeight\OCP\Preview\BeforePreviewFetchedEvent::getMode\OCP\Preview\BeforePreviewFetchedEvent::getWidth\OCP\IPhoneNumberUtil::convertToStandardFormatto convert input into an E164 formatted phone number. See Phone number util for an example.\OCP\IPhoneNumberUtil::getCountryCodeForRegionto get the E164 country code for a given region. See Phone number util for an example.\OCP\AppFramework\Http\EmptyContentSecurityPolicy::allowEvalWasm(bool): setswasm-unsafe-evalinscript-srcof the Content Security Policy to allow compilation and execution of WebAssembly on the page\OCP\FilesMetadata\IMetadataBackgroundEvent::getNode\OCP\FilesMetadata\IMetadataBackgroundEvent::getMetadata\OCP\FilesMetadata\IMetadataLiveEvent::getNode\OCP\FilesMetadata\IMetadataLiveEvent::getMetadata\OCP\FilesMetadata\IMetadataLiveEvent::requestBackgroundJob\OCP\FilesMetadata\IFilesMetadataManager::refreshMetadata\OCP\FilesMetadata\IFilesMetadataManager::getMetadata\OCP\FilesMetadata\IFilesMetadataManager::saveMetadata\OCP\FilesMetadata\IFilesMetadataManager::deleteMetadata\OCP\FilesMetadata\IFilesMetadataManager::getMetadataQuery\OCP\FilesMetadata\IFilesMetadataManager::getKnownMetadata\OCP\FilesMetadata\IFilesMetadataManager::initMetadata\OCP\FilesMetadata\IMetadataQuery::retrieveMetadata\OCP\FilesMetadata\IMetadataQuery::extractMetadata\OCP\FilesMetadata\IMetadataQuery::joinIndex\OCP\FilesMetadata\IMetadataQuery::getMetadataKeyField\OCP\FilesMetadata\IMetadataQuery::getMetadataValueFieldwasm-unsafe-evalis supported by most browsersWebAssembly compilation and execution in worker threads is not affected by this directive (browsers allow compilation and execution of WebAssembly in worker threads by default)
OCP\Authentication\Token\IProvider::getTokento get a token by its token string idOCP\Authentication\Token\ITokenpublic interface for tokens returned by the function above. Please use those instead of things fromOCnamespace.OCP\User\Backend\IProvideEnabledStateBackendfor user backends that wants to alter disabled state of users (used by user_ldap to mark remnants as disabled if the option is enabled).
Changed APIs
\OCP\Preview\BeforePreviewFetchedEventnow accepts:width, height, crop and modeas optional constructor arguments.Interface
\OCP\Files\Foldergot a new method:searchBySystemTag(string $tagName, string $userId, int $limit = 0, int $offset = 0).OCP\SystemTag\ISystemTagManager::getTagsByIds()now optionally accepts IUser as second parameter, to only retrieve system tags visible to that user.
Deprecated APIs
\OCP\DB\IResult::fetch: use the newfetchAssociative,fetchNumericandfetchOneinstead. If you calledfetchwithout arguments,fetchAssociativeis the direct replacement. Beware that the new methods throw a different exception.\OCP\DB\IResult::fetchAll: use the newfetchAllAssociative,fetchAllNumericandfetchOneinstead. If you calledfetchAllwithout arguments,fetchAllAssociativeis the direct replacement. Beware that the new methods throw a different exception.\OCP\Preview\BeforePreviewFetchedEventpassingnullforwidth, height, crop or modeis deprecated. Starting with Nextcloud 31 they are mandatory.
Removed APIs
\OC_App::getAppVersion: inject\OCP\App\IAppManagerand call\OCP\App\IAppManager::getAppVersion.\OC_App::getAppInfo: inject\OCP\App\IAppManagerand call\OCP\App\IAppManager::getAppInfo.\OC_App::getNavigation: inject\OCP\App\IAppManagerand call\OCP\App\IAppManager::getAll.\OC_App::getSettingsNavigation: inject\OCP\App\IAppManagerand call\OCP\App\IAppManager::getAll('settings').\OC_App::isEnabled: inject\OCP\App\IAppManagerand call\OCP\App\IAppManager::isEnabledForUser.\OC_Defaults::getLogoClaim: there is no replacement.\OCP\Util::linkToPublic: there is no replacement.\OC_Defaults::getLogoClaim: There is no replacement.\OC::$server->createEventSource()has been removed, use\OCP\Server::get(\OCP\IEventSourceFactory::class)->create()instead.\OCP\Util::writeLoghas been removed, use\OCP\Server::get(LoggerInterface::class)->…instead.
The factory \OCP\IEventSourceFactory works only from Nextcloud 28.
For older versions use \OC::$server->createEventSource().
If you want to support Nextcloud 27 and Nextcloud 28:
// @TODO: Remove method_exists when min-version="28"
if (method_exists(\OC::$server, 'createEventSource')) {
    $eventSource = \OC::$server->createEventSource();
} else {
    $eventSource = \OCP\Server::get(IEventSourceFactory::class)->create();
}
Added events
Typed event
OCA\DAV\Events\SabrePluginAddEventwas addedTyped event
OCP\Accounts\UserUpdatedEventwas addedTyped event
OCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengeFailedwas addedTyped event
OCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengePassedwas addedTyped event
OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserRegisteredwas addedTyped event
OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserUnregisteredwas addedTyped event
OCP\Authentication\TwoFactorAuth\TwoFactorProviderUserDeletedwas addedTyped event
OCP\Comments\CommentsEntityEventwas addedTyped event
OCP\DB\Events\AddMissingColumnsEventto add missing indices to the database schema.Typed event
OCP\DB\Events\AddMissingIndicesEventto add missing indices to the database schema.Typed event
OCP\DB\Events\AddMissingPrimaryKeyEventto add missing indices to the database schema.Typed event
OCP\Files\Events\NodeAddedToFavoritewas addedTyped event
OCP\Files\Events\NodeRemovedFromFavoritewas addedTyped event
OCP\FilesMetadata\Event\MetadataBackgroundEventwas addedTyped event
OCP\FilesMetadata\Event\MetadataLiveEventwas addedTyped event
OCP\Share\Events\BeforeShareCreatedEventwas addedTyped event
OCP\Share\Events\BeforeShareDeletedEventwas addedTyped event
OCP\Share\Events\ShareAcceptedEventwas addedTyped event
OCP\Share\Events\ShareDeletedFromSelfEventwas addedTyped event
OCP\SystemTag\SystemTagsEntityEventwas addedTyped event
OCP\User\Events\UserFirstTimeLoggedInEventwas added
Deprecated events
OC\Console\Application::runwas deprecated. Listen to the typed eventOCP\Console\ConsoleEventinsteadOCA\DAV\Connector\Sabre::addPluginwas deprecated. Listen to the typed eventOCA\DAV\Events\SabrePluginAddEventinsteadOCA\Files_Trashbin::moveToTrashwas deprecated. Listen to the typed eventOCA\Files_Trashbin\Events\MoveToTrashEventinsteadOCA\Files_Trashbin::moveToTrashwas deprecated. Listen to the typed eventOCA\Files_Trashbin\Events\MoveToTrashEventinsteadOCP\Console\ConsoleEvent::EVENT_RUNwas deprecated. Listen to the typed eventOCP\Console\ConsoleEventinsteadOCP\Authentication\TwoFactorAuth\RegistryEventwas deprecated. Listen to the typed eventOCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserRegisteredandOCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserUnregisteredinsteadOCP\Authentication\TwoFactorAuth\IRegistry::enablewas deprecated. Listen to the typed eventOCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserRegisteredinsteadOCP\Authentication\TwoFactorAuth\IRegistry::disablewas deprecated. Listen to the typed eventOCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserUnregisteredinsteadOCP\Authentication\TwoFactorAuth\TwoFactorProviderDisabledwas deprecated. Listen to the typed eventOCP\Authentication\TwoFactorAuth\TwoFactorProviderUserDeletedinsteadOCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserDisabledwas deprecated. Listen to the typed eventOCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengeFailedinsteadOCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserEnabledwas deprecated. Listen to the typed eventOCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengePassedinsteadOCP\Comments\CommentsEntityEvent::EVENT_ENTITYwas deprecated. Listen to the typed eventOCP\Comments\CommentsEntityEventinsteadOCP\Comments\ICommentsManager::registerEntitywas deprecated. Listen to the typed eventOCP\Comments\CommentsEntityEventinsteadOCP\SystemTag\ISystemTagManager::registerEntitywas deprecated. Listen to the typed eventOCP\SystemTag\SystemTagsEntityEventinsteadOCP\SystemTag\SystemTagsEntityEvent::EVENT_ENTITYwas deprecated. Listen to the typed eventOCP\SystemTag\SystemTagsEntityEventinsteadOCP\IUser::firstLoginwas deprecated. Listen to the typed eventOCP\User\Events\UserFirstTimeLoggedInEventinstead
Removed events
OC\AccountManager::userUpdatedwas removed. Listen to the typed eventOCP\Accounts\UserUpdatedEventinsteadOCA\Files::loadAdditionalScriptswas removed. Listen to the typed eventOCA\Files\Event\LoadAdditionalScriptsEventinsteadOCA\Files\Service\TagService::addFavoritewas removed. Listen to the typed eventOCP\Files\Events\NodeAddedToFavoriteinsteadOCA\Files\Service\TagService::removeFavoritewas removed. Listen to the typed eventOCP\Files\Events\NodeRemovedFromFavoriteinsteadOCA\Files_Sharing::loadAdditionalScriptswas removed. Listen to the typed eventOCA\Files_Sharing\Event\BeforeTemplateRenderedEventinsteadOCP\AppFramework\Http\TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS(deprecated since 20) was removed. Listen to the typed eventOCP\AppFramework\Http\Events\BeforeTemplateRenderedEventinsteadOCP\AppFramework\Http\TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS_LOGGEDIN(deprecated since 20) was removed. Listen to the typed eventOCP\AppFramework\Http\Events\BeforeTemplateRenderedEventinsteadOCP\AppFramework\Http\TemplateResponse::loadAdditionalScripts(deprecated since 20) was removed. Listen to the typed eventOCP\AppFramework\Http\Events\BeforeTemplateRenderedEventinsteadOCP\AppFramework\Http\TemplateResponse::loadAdditionalScriptsLoggedIn(deprecated since 20) was removed. Listen to the typed eventOCP\AppFramework\Http\Events\BeforeTemplateRenderedEventinsteadOCP\Authentication\TwoFactorAuth\IProvider::EVENT_SUCCESS(deprecated since 22) was removed. Listen to the typed eventOCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengePassedinsteadOCP\Authentication\TwoFactorAuth\IProvider::EVENT_FAILED(deprecated since 22) was removed. Listen to the typed eventOCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengeFailedinsteadOCP\Authentication\TwoFactorAuth\IProvider::failed(deprecated since 22) was removed. Listen to the typed eventOCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengeFailedinsteadOCP\Authentication\TwoFactorAuth\IProvider::success(deprecated since 22) was removed. Listen to the typed eventOCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengePassedinsteadOCP\IDBConnection::ADD_MISSING_COLUMNS(deprecated since 22) was removed. Listen to the typed eventOCP\DB\Events\AddMissingColumnsEventinsteadOCP\IDBConnection::ADD_MISSING_INDEXES(deprecated since 22) was removed. Listen to the typed eventOCP\DB\Events\AddMissingIndicesEventinsteadOCP\IDBConnection::ADD_MISSING_PRIMARY_KEYS(deprecated since 22) was removed. Listen to the typed eventOCP\DB\Events\AddMissingPrimaryKeyEventinsteadOCP\IDBConnection::CHECK_MISSING_COLUMNS(deprecated since 22) was removed. Listen to the typed eventOCP\DB\Events\AddMissingColumnsEventinsteadOCP\IDBConnection::CHECK_MISSING_COLUMNS_EVENT(deprecated since 22) was removed. Listen to the typed eventOCP\DB\Events\AddMissingColumnsEventinsteadOCP\IDBConnection::CHECK_MISSING_INDEXES(deprecated since 22) was removed. Listen to the typed eventOCP\DB\Events\AddMissingIndicesEventinsteadOCP\IDBConnection::CHECK_MISSING_INDEXES_EVENT(deprecated since 22) was removed. Listen to the typed eventOCP\DB\Events\AddMissingIndicesEventinsteadOCP\IDBConnection::CHECK_MISSING_PRIMARY_KEYS(deprecated since 22) was removed. Listen to the typed eventOCP\DB\Events\AddMissingPrimaryKeyEventinsteadOCP\IDBConnection::CHECK_MISSING_PRIMARY_KEYS_EVENT(deprecated since 22) was removed. Listen to the typed eventOCP\DB\Events\AddMissingPrimaryKeyEventinsteadOCP\IGroup::postAddUserwas removed. Listen to the typed eventOCP\Group\Events\UserAddedEventinsteadOCP\IGroup::postDeletewas removed. Listen to the typed eventOCP\Group\Events\GroupDeletedEventinsteadOCP\IGroup::postRemoveUserwas removed. Listen to the typed eventOCP\Group\Events\UserRemovedEventinsteadOCP\IGroup::preAddUserwas removed. Listen to the typed eventOCP\Group\Events\BeforeUserAddedEventinsteadOCP\IGroup::preDeletewas removed. Listen to the typed eventOCP\Group\Events\BeforeGroupDeletedEventinsteadOCP\IGroup::preRemoveUserwas removed. Listen to the typed eventOCP\Group\Events\BeforeUserRemovedEventinsteadOCP\IPreview::EVENT(deprecated since 22) was removed. Listen to the typed eventOCP\Preview\BeforePreviewFetchedEventinsteadOCP\IPreview:PreviewRequested(deprecated since 22) was removed. Listen to the typed eventOCP\Preview\BeforePreviewFetchedEventinsteadOCP\IUser::changeUserwas removed. Listen to the typed eventOCP\User\Events\UserChangedEventinsteadOCP\IUser::postDelete(deprecated since 17) was removed. Listen to the typed eventOCP\User\Events\UserDeletedEventinsteadOCP\IUser::postSetPasswordwas removed. Listen to the typed eventOCP\User\Events\PasswordUpdatedEventinsteadOCP\IUser::preDelete(deprecated since 17) was removed. Listen to the typed eventOCP\User\Events\BeforeUserDeletedEventinsteadOCP\IUser::preSetPasswordwas removed. Listen to the typed eventOCP\User\Events\BeforePasswordUpdatedEventinsteadOCP\Share::preSharewas removed. Listen to the typed eventOCP\Share\Events\BeforeShareCreatedEventinsteadOCP\Share::preUnsharewas removed. Listen to the typed eventOCP\Share\Events\BeforeShareDeletedEventinsteadOCP\Share::postAcceptSharewas removed. Listen to the typed eventOCP\Share\Events\ShareAcceptedEventinsteadOCP\Share::postSharewas removed. Listen to the typed eventOCP\Share\Events\ShareCreatedEventinsteadOCP\Share::postUnsharewas removed. Listen to the typed eventOCP\Share\Events\ShareDeletedEventinsteadOCP\Share::postUnshareFromSelfwas removed. Listen to the typed eventOCP\Share\Events\ShareDeletedFromSelfEventinsteadOCP\WorkflowEngine::registerChecks(deprecated since 17) was removed. Listen to the typed eventOCP\WorkflowEngine\Events\RegisterChecksEventinsteadOCP\WorkflowEngine::registerEntities(deprecated since 17) was removed. Listen to the typed eventOCP\WorkflowEngine\Events\RegisterEntitiesEventinsteadOCP\WorkflowEngine::registerOperations(deprecated since 17) was removed. Listen to the typed eventOCP\WorkflowEngine\Events\RegisterOperationsEventinstead\OCP\Collaboration\Resources::loadAdditionalScriptswas removed. Listen to the typed eventOCP\Collaboration\Resources\LoadAdditionalScriptsEventinstead
Removed WebDAV properties
<nc:file-metadata-size>
<nc:file-metadata-gps>