# Table of Contents - [Nextcloud developer documentation — Nextcloud latest Developer Manual latest documentation](#nextcloud-developer-documentation-nextcloud-latest-developer-manual-latest-documentation) - [Development process — Nextcloud latest Developer Manual latest documentation](#development-process-nextcloud-latest-developer-manual-latest-documentation) - [Coding style & general guidelines — Nextcloud latest Developer Manual latest documentation](#coding-style-general-guidelines-nextcloud-latest-developer-manual-latest-documentation) - [Prologue — Nextcloud latest Developer Manual latest documentation](#prologue-nextcloud-latest-developer-manual-latest-documentation) - [Interface & interaction design — Nextcloud latest Developer Manual latest documentation](#interface-interaction-design-nextcloud-latest-developer-manual-latest-documentation) - [Code of conduct — Nextcloud latest Developer Manual latest documentation](#code-of-conduct-nextcloud-latest-developer-manual-latest-documentation) - [Getting started — Nextcloud latest Developer Manual latest documentation](#getting-started-nextcloud-latest-developer-manual-latest-documentation) - [ExApp development — Nextcloud latest Developer Manual latest documentation](#exapp-development-nextcloud-latest-developer-manual-latest-documentation) - [Development overview — Nextcloud latest Developer Manual latest documentation](#development-overview-nextcloud-latest-developer-manual-latest-documentation) - [Technical details — Nextcloud latest Developer Manual latest documentation](#technical-details-nextcloud-latest-developer-manual-latest-documentation) - [Compatibility with the app ecosystem — Nextcloud latest Developer Manual latest documentation](#compatibility-with-the-app-ecosystem-nextcloud-latest-developer-manual-latest-documentation) - [Help and communication — Nextcloud latest Developer Manual latest documentation](#help-and-communication-nextcloud-latest-developer-manual-latest-documentation) - [Bugtracker — Nextcloud latest Developer Manual latest documentation](#bugtracker-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Frequently Asked Questions — Nextcloud latest Developer Manual latest documentation](#frequently-asked-questions-nextcloud-latest-developer-manual-latest-documentation) - [Setting up dev environment — Nextcloud latest Developer Manual latest documentation](#setting-up-dev-environment-nextcloud-latest-developer-manual-latest-documentation) - [Security guidelines — Nextcloud latest Developer Manual latest documentation](#security-guidelines-nextcloud-latest-developer-manual-latest-documentation) - [App publishing and maintenance — Nextcloud latest Developer Manual latest documentation](#app-publishing-and-maintenance-nextcloud-latest-developer-manual-latest-documentation) - [Static analysis — Nextcloud latest Developer Manual latest documentation](#static-analysis-nextcloud-latest-developer-manual-latest-documentation) - [Front-end code — Nextcloud latest Developer Manual latest documentation](#front-end-code-nextcloud-latest-developer-manual-latest-documentation) - [Server development — Nextcloud latest Developer Manual latest documentation](#server-development-nextcloud-latest-developer-manual-latest-documentation) - [Unit-Testing — Nextcloud latest Developer Manual latest documentation](#unit-testing-nextcloud-latest-developer-manual-latest-documentation) - [Back-end code — Nextcloud latest Developer Manual latest documentation](#back-end-code-nextcloud-latest-developer-manual-latest-documentation) - [Nextcloud architecture — Nextcloud latest Developer Manual latest documentation](#nextcloud-architecture-nextcloud-latest-developer-manual-latest-documentation) - [External API — Nextcloud latest Developer Manual latest documentation](#external-api-nextcloud-latest-developer-manual-latest-documentation) - [App development — Nextcloud latest Developer Manual latest documentation](#app-development-nextcloud-latest-developer-manual-latest-documentation) - [Navigation and pre-app configuration — Nextcloud latest Developer Manual latest documentation](#navigation-and-pre-app-configuration-nextcloud-latest-developer-manual-latest-documentation) - [Bootstrapping — Nextcloud latest Developer Manual latest documentation](#bootstrapping-nextcloud-latest-developer-manual-latest-documentation) - [Dependency management — Nextcloud latest Developer Manual latest documentation](#dependency-management-nextcloud-latest-developer-manual-latest-documentation) - [Translation — Nextcloud latest Developer Manual latest documentation](#translation-nextcloud-latest-developer-manual-latest-documentation) - [HTML/CSS guidelines — Nextcloud latest Developer Manual latest documentation](#html-css-guidelines-nextcloud-latest-developer-manual-latest-documentation) - [Tutorial — Nextcloud latest Developer Manual latest documentation](#tutorial-nextcloud-latest-developer-manual-latest-documentation) - [How to test … — Nextcloud latest Developer Manual latest documentation](#how-to-test-nextcloud-latest-developer-manual-latest-documentation) - [Extending the DAV server — Nextcloud latest Developer Manual latest documentation](#extending-the-dav-server-nextcloud-latest-developer-manual-latest-documentation) - [Development environment — Nextcloud latest Developer Manual latest documentation](#development-environment-nextcloud-latest-developer-manual-latest-documentation) - [Clients and Client APIs — Nextcloud latest Developer Manual latest documentation](#clients-and-client-apis-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [App metadata — Nextcloud latest Developer Manual latest documentation](#app-metadata-nextcloud-latest-developer-manual-latest-documentation) - [Desktop Clients — Nextcloud latest Developer Manual latest documentation](#desktop-clients-nextcloud-latest-developer-manual-latest-documentation) - [Front-end — Nextcloud latest Developer Manual latest documentation](#front-end-nextcloud-latest-developer-manual-latest-documentation) - [Storage and database — Nextcloud latest Developer Manual latest documentation](#storage-and-database-nextcloud-latest-developer-manual-latest-documentation) - [Middlewares — Nextcloud latest Developer Manual latest documentation](#middlewares-nextcloud-latest-developer-manual-latest-documentation) - [Routing — Nextcloud latest Developer Manual latest documentation](#routing-nextcloud-latest-developer-manual-latest-documentation) - [Logging — Nextcloud latest Developer Manual latest documentation](#logging-nextcloud-latest-developer-manual-latest-documentation) - [Basic concepts — Nextcloud latest Developer Manual latest documentation](#basic-concepts-nextcloud-latest-developer-manual-latest-documentation) - [Testing — Nextcloud latest Developer Manual latest documentation](#testing-nextcloud-latest-developer-manual-latest-documentation) - [Caching — Nextcloud latest Developer Manual latest documentation](#caching-nextcloud-latest-developer-manual-latest-documentation) - [Public share template — Nextcloud latest Developer Manual latest documentation](#public-share-template-nextcloud-latest-developer-manual-latest-documentation) - [Background jobs (Cron) — Nextcloud latest Developer Manual latest documentation](#background-jobs-cron-nextcloud-latest-developer-manual-latest-documentation) - [Translations — Nextcloud latest Developer Manual latest documentation](#translations-nextcloud-latest-developer-manual-latest-documentation) - [Dependency injection — Nextcloud latest Developer Manual latest documentation](#dependency-injection-nextcloud-latest-developer-manual-latest-documentation) - [Request lifecycle — Nextcloud latest Developer Manual latest documentation](#request-lifecycle-nextcloud-latest-developer-manual-latest-documentation) - [Events — Nextcloud latest Developer Manual latest documentation](#events-nextcloud-latest-developer-manual-latest-documentation) - [Controllers — Nextcloud latest Developer Manual latest documentation](#controllers-nextcloud-latest-developer-manual-latest-documentation) - [Settings — Nextcloud latest Developer Manual latest documentation](#settings-nextcloud-latest-developer-manual-latest-documentation) - [Monetizing your app — Nextcloud latest Developer Manual latest documentation](#monetizing-your-app-nextcloud-latest-developer-manual-latest-documentation) - [Code signing — Nextcloud latest Developer Manual latest documentation](#code-signing-nextcloud-latest-developer-manual-latest-documentation) - [Release Automation — Nextcloud latest Developer Manual latest documentation](#release-automation-nextcloud-latest-developer-manual-latest-documentation) - [Building the Client — Nextcloud latest Developer Manual latest documentation](#building-the-client-nextcloud-latest-developer-manual-latest-documentation) - [Classloader — Nextcloud latest Developer Manual latest documentation](#classloader-nextcloud-latest-developer-manual-latest-documentation) - [Continuous Integration — Nextcloud latest Developer Manual latest documentation](#continuous-integration-nextcloud-latest-developer-manual-latest-documentation) - [Deadlocks — Nextcloud latest Developer Manual latest documentation](#deadlocks-nextcloud-latest-developer-manual-latest-documentation) - [OpenID Connect (Oidc) — Nextcloud latest Developer Manual latest documentation](#openid-connect-oidc-nextcloud-latest-developer-manual-latest-documentation) - [Debugging — Nextcloud latest Developer Manual latest documentation](#debugging-nextcloud-latest-developer-manual-latest-documentation) - [Nextcloud Flow — Nextcloud latest Developer Manual latest documentation](#nextcloud-flow-nextcloud-latest-developer-manual-latest-documentation) - [Groupware integration — Nextcloud latest Developer Manual latest documentation](#groupware-integration-nextcloud-latest-developer-manual-latest-documentation) - [Config & Preferences — Nextcloud latest Developer Manual latest documentation](#config-preferences-nextcloud-latest-developer-manual-latest-documentation) - [NPM — Nextcloud latest Developer Manual latest documentation](#npm-nextcloud-latest-developer-manual-latest-documentation) - [Out-of-office periods — Nextcloud latest Developer Manual latest documentation](#out-of-office-periods-nextcloud-latest-developer-manual-latest-documentation) - [API reference — Nextcloud latest Developer Manual latest documentation](#api-reference-nextcloud-latest-developer-manual-latest-documentation) - [Phone number util — Nextcloud latest Developer Manual latest documentation](#phone-number-util-nextcloud-latest-developer-manual-latest-documentation) - [Email — Nextcloud latest Developer Manual latest documentation](#email-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Layout — Nextcloud latest Developer Manual latest documentation](#layout-nextcloud-latest-developer-manual-latest-documentation) - [Layout components — Nextcloud latest Developer Manual latest documentation](#layout-components-nextcloud-latest-developer-manual-latest-documentation) - [Atomic components — Nextcloud latest Developer Manual latest documentation](#atomic-components-nextcloud-latest-developer-manual-latest-documentation) - [Notifications — Nextcloud latest Developer Manual latest documentation](#notifications-nextcloud-latest-developer-manual-latest-documentation) - [HTTP Client — Nextcloud latest Developer Manual latest documentation](#http-client-nextcloud-latest-developer-manual-latest-documentation) - [JavaScript APIs — Nextcloud latest Developer Manual latest documentation](#javascript-apis-nextcloud-latest-developer-manual-latest-documentation) - [Repair steps — Nextcloud latest Developer Manual latest documentation](#repair-steps-nextcloud-latest-developer-manual-latest-documentation) - [Machine Translation — Nextcloud latest Developer Manual latest documentation](#machine-translation-nextcloud-latest-developer-manual-latest-documentation) - [Open Metrics exporter — Nextcloud latest Developer Manual latest documentation](#open-metrics-exporter-nextcloud-latest-developer-manual-latest-documentation) - [Profiler — Nextcloud latest Developer Manual latest documentation](#profiler-nextcloud-latest-developer-manual-latest-documentation) - [Security — Nextcloud latest Developer Manual latest documentation](#security-nextcloud-latest-developer-manual-latest-documentation) - [Projects — Nextcloud latest Developer Manual latest documentation](#projects-nextcloud-latest-developer-manual-latest-documentation) - [Dashboard — Nextcloud latest Developer Manual latest documentation](#dashboard-nextcloud-latest-developer-manual-latest-documentation) - [Foundations — Nextcloud latest Developer Manual latest documentation](#foundations-nextcloud-latest-developer-manual-latest-documentation) - [Performance considerations — Nextcloud latest Developer Manual latest documentation](#performance-considerations-nextcloud-latest-developer-manual-latest-documentation) - [Profile — Nextcloud latest Developer Manual latest documentation](#profile-nextcloud-latest-developer-manual-latest-documentation) - [PSR — Nextcloud latest Developer Manual latest documentation](#psr-nextcloud-latest-developer-manual-latest-documentation) - [Maintainers — Nextcloud latest Developer Manual latest documentation](#maintainers-nextcloud-latest-developer-manual-latest-documentation) - [Release process — Nextcloud latest Developer Manual latest documentation](#release-process-nextcloud-latest-developer-manual-latest-documentation) - [Content list — Nextcloud latest Developer Manual latest documentation](#content-list-nextcloud-latest-developer-manual-latest-documentation) - [Talk Integration — Nextcloud latest Developer Manual latest documentation](#talk-integration-nextcloud-latest-developer-manual-latest-documentation) - [Files Metadata — Nextcloud latest Developer Manual latest documentation](#files-metadata-nextcloud-latest-developer-manual-latest-documentation) - [REST APIs — Nextcloud latest Developer Manual latest documentation](#rest-apis-nextcloud-latest-developer-manual-latest-documentation) - [Digging deeper — Nextcloud latest Developer Manual latest documentation](#digging-deeper-nextcloud-latest-developer-manual-latest-documentation) - [Setup checks — Nextcloud latest Developer Manual latest documentation](#setup-checks-nextcloud-latest-developer-manual-latest-documentation) - [Public Pages — Nextcloud latest Developer Manual latest documentation](#public-pages-nextcloud-latest-developer-manual-latest-documentation) - [App upgrade guide — Nextcloud latest Developer Manual latest documentation](#app-upgrade-guide-nextcloud-latest-developer-manual-latest-documentation) - [Main content — Nextcloud latest Developer Manual latest documentation](#main-content-nextcloud-latest-developer-manual-latest-documentation) - [HTML elements — Nextcloud latest Developer Manual latest documentation](#html-elements-nextcloud-latest-developer-manual-latest-documentation) - [Icons — Nextcloud latest Developer Manual latest documentation](#icons-nextcloud-latest-developer-manual-latest-documentation) - [Text-To-Image — Nextcloud latest Developer Manual latest documentation](#text-to-image-nextcloud-latest-developer-manual-latest-documentation) - [Search — Nextcloud latest Developer Manual latest documentation](#search-nextcloud-latest-developer-manual-latest-documentation) - [Popover menu — Nextcloud latest Developer Manual latest documentation](#popover-menu-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [CSS — Nextcloud latest Developer Manual latest documentation](#css-nextcloud-latest-developer-manual-latest-documentation) - [User migration — Nextcloud latest Developer Manual latest documentation](#user-migration-nextcloud-latest-developer-manual-latest-documentation) - [Web Host Metadata — Nextcloud latest Developer Manual latest documentation](#web-host-metadata-nextcloud-latest-developer-manual-latest-documentation) - [Reference providers — Nextcloud latest Developer Manual latest documentation](#reference-providers-nextcloud-latest-developer-manual-latest-documentation) - [Text Processing — Nextcloud latest Developer Manual latest documentation](#text-processing-nextcloud-latest-developer-manual-latest-documentation) - [Snowflake IDs — Nextcloud latest Developer Manual latest documentation](#snowflake-ids-nextcloud-latest-developer-manual-latest-documentation) - [Android — Nextcloud latest Developer Manual latest documentation](#android-nextcloud-latest-developer-manual-latest-documentation) - [Activity — Nextcloud latest Developer Manual latest documentation](#activity-nextcloud-latest-developer-manual-latest-documentation) - [General — Nextcloud latest Developer Manual latest documentation](#general-nextcloud-latest-developer-manual-latest-documentation) - [Login Flow — Nextcloud latest Developer Manual latest documentation](#login-flow-nextcloud-latest-developer-manual-latest-documentation) - [Files — Nextcloud latest Developer Manual latest documentation](#files-nextcloud-latest-developer-manual-latest-documentation) - [Remote wipe — Nextcloud latest Developer Manual latest documentation](#remote-wipe-nextcloud-latest-developer-manual-latest-documentation) - [Client Integration — Nextcloud latest Developer Manual latest documentation](#client-integration-nextcloud-latest-developer-manual-latest-documentation) - [Webdav — Nextcloud latest Developer Manual latest documentation](#webdav-nextcloud-latest-developer-manual-latest-documentation) - [WebDAV collection preload events — Nextcloud latest Developer Manual latest documentation](#webdav-collection-preload-events-nextcloud-latest-developer-manual-latest-documentation) - [The Nextcloud app store rules — Nextcloud latest Developer Manual latest documentation](#the-nextcloud-app-store-rules-nextcloud-latest-developer-manual-latest-documentation) - [Context Chat — Nextcloud latest Developer Manual latest documentation](#context-chat-nextcloud-latest-developer-manual-latest-documentation) - [OCS API — Nextcloud latest Developer Manual latest documentation](#ocs-api-nextcloud-latest-developer-manual-latest-documentation) - [Settings — Nextcloud latest Developer Manual latest documentation](#settings-nextcloud-latest-developer-manual-latest-documentation) - [Speech-To-Text — Nextcloud latest Developer Manual latest documentation](#speech-to-text-nextcloud-latest-developer-manual-latest-documentation) - [Two-factor providers — Nextcloud latest Developer Manual latest documentation](#two-factor-providers-nextcloud-latest-developer-manual-latest-documentation) - [Task Processing — Nextcloud latest Developer Manual latest documentation](#task-processing-nextcloud-latest-developer-manual-latest-documentation) - [User Status — Nextcloud latest Developer Manual latest documentation](#user-status-nextcloud-latest-developer-manual-latest-documentation) - [Working with time — Nextcloud latest Developer Manual latest documentation](#working-with-time-nextcloud-latest-developer-manual-latest-documentation) - [User management — Nextcloud latest Developer Manual latest documentation](#user-management-nextcloud-latest-developer-manual-latest-documentation) - [Nextcloud developer documentation — Nextcloud latest Developer Manual latest documentation](#nextcloud-developer-documentation-nextcloud-latest-developer-manual-latest-documentation) - [Nextcloud developer documentation — Nextcloud latest Developer Manual latest documentation](#nextcloud-developer-documentation-nextcloud-latest-developer-manual-latest-documentation) - [Nextcloud developer documentation — Nextcloud latest Developer Manual latest documentation](#nextcloud-developer-documentation-nextcloud-latest-developer-manual-latest-documentation) - [Desktop Clients — Nextcloud latest Administration Manual latest documentation](#desktop-clients-nextcloud-latest-administration-manual-latest-documentation) - [Installation and server configuration — Nextcloud latest Administration Manual latest documentation](#installation-and-server-configuration-nextcloud-latest-administration-manual-latest-documentation) - [Administration privileges (Delegation) — Nextcloud latest Administration Manual latest documentation](#administration-privileges-delegation-nextcloud-latest-administration-manual-latest-documentation) - [Desktop Clients — Nextcloud latest User Manual latest documentation](#desktop-clients-nextcloud-latest-user-manual-latest-documentation) - [Prologue — Nextcloud latest Developer Manual latest documentation](#prologue-nextcloud-latest-developer-manual-latest-documentation) - [Getting started — Nextcloud latest Developer Manual latest documentation](#getting-started-nextcloud-latest-developer-manual-latest-documentation) - [Prologue — Nextcloud latest Developer Manual latest documentation](#prologue-nextcloud-latest-developer-manual-latest-documentation) - [Server development — Nextcloud latest Developer Manual latest documentation](#server-development-nextcloud-latest-developer-manual-latest-documentation) - [ExApp development — Nextcloud latest Developer Manual latest documentation](#exapp-development-nextcloud-latest-developer-manual-latest-documentation) - [App development — Nextcloud latest Developer Manual latest documentation](#app-development-nextcloud-latest-developer-manual-latest-documentation) - [Declarative settings — Nextcloud latest Developer Manual latest documentation](#declarative-settings-nextcloud-latest-developer-manual-latest-documentation) - [App development — Nextcloud latest Developer Manual latest documentation](#app-development-nextcloud-latest-developer-manual-latest-documentation) - [Basic concepts — Nextcloud latest Developer Manual latest documentation](#basic-concepts-nextcloud-latest-developer-manual-latest-documentation) - [ExApp development — Nextcloud latest Developer Manual latest documentation](#exapp-development-nextcloud-latest-developer-manual-latest-documentation) - [Interface & interaction design — Nextcloud latest Developer Manual latest documentation](#interface-interaction-design-nextcloud-latest-developer-manual-latest-documentation) - [Server development — Nextcloud latest Developer Manual latest documentation](#server-development-nextcloud-latest-developer-manual-latest-documentation) - [App publishing and maintenance — Nextcloud latest Developer Manual latest documentation](#app-publishing-and-maintenance-nextcloud-latest-developer-manual-latest-documentation) - [Server development — Nextcloud latest Developer Manual latest documentation](#server-development-nextcloud-latest-developer-manual-latest-documentation) - [Interface & interaction design — Nextcloud latest Developer Manual latest documentation](#interface-interaction-design-nextcloud-latest-developer-manual-latest-documentation) - [Code of conduct — Nextcloud latest Developer Manual latest documentation](#code-of-conduct-nextcloud-latest-developer-manual-latest-documentation) - [App publishing and maintenance — Nextcloud latest Developer Manual latest documentation](#app-publishing-and-maintenance-nextcloud-latest-developer-manual-latest-documentation) - [Interface & interaction design — Nextcloud latest Developer Manual latest documentation](#interface-interaction-design-nextcloud-latest-developer-manual-latest-documentation) - [Help and communication — Nextcloud latest Developer Manual latest documentation](#help-and-communication-nextcloud-latest-developer-manual-latest-documentation) - [Bugtracker — Nextcloud latest Developer Manual latest documentation](#bugtracker-nextcloud-latest-developer-manual-latest-documentation) - [HTML/CSS guidelines — Nextcloud latest Developer Manual latest documentation](#html-css-guidelines-nextcloud-latest-developer-manual-latest-documentation) - [Development process — Nextcloud latest Developer Manual latest documentation](#development-process-nextcloud-latest-developer-manual-latest-documentation) - [App publishing and maintenance — Nextcloud latest Developer Manual latest documentation](#app-publishing-and-maintenance-nextcloud-latest-developer-manual-latest-documentation) - [Code of conduct — Nextcloud latest Developer Manual latest documentation](#code-of-conduct-nextcloud-latest-developer-manual-latest-documentation) - [Compatibility with the app ecosystem — Nextcloud latest Developer Manual latest documentation](#compatibility-with-the-app-ecosystem-nextcloud-latest-developer-manual-latest-documentation) - [Security guidelines — Nextcloud latest Developer Manual latest documentation](#security-guidelines-nextcloud-latest-developer-manual-latest-documentation) - [Clients and Client APIs — Nextcloud latest Developer Manual latest documentation](#clients-and-client-apis-nextcloud-latest-developer-manual-latest-documentation) - [Coding style & general guidelines — Nextcloud latest Developer Manual latest documentation](#coding-style-general-guidelines-nextcloud-latest-developer-manual-latest-documentation) - [HTML/CSS guidelines — Nextcloud latest Developer Manual latest documentation](#html-css-guidelines-nextcloud-latest-developer-manual-latest-documentation) - [HTML/CSS guidelines — Nextcloud latest Developer Manual latest documentation](#html-css-guidelines-nextcloud-latest-developer-manual-latest-documentation) - [Code of conduct — Nextcloud latest Developer Manual latest documentation](#code-of-conduct-nextcloud-latest-developer-manual-latest-documentation) - [Help and communication — Nextcloud latest Developer Manual latest documentation](#help-and-communication-nextcloud-latest-developer-manual-latest-documentation) - [Help and communication — Nextcloud latest Developer Manual latest documentation](#help-and-communication-nextcloud-latest-developer-manual-latest-documentation) - [Bugtracker — Nextcloud latest Developer Manual latest documentation](#bugtracker-nextcloud-latest-developer-manual-latest-documentation) - [Bugtracker — Nextcloud latest Developer Manual latest documentation](#bugtracker-nextcloud-latest-developer-manual-latest-documentation) - [Development process — Nextcloud latest Developer Manual latest documentation](#development-process-nextcloud-latest-developer-manual-latest-documentation) - [Desktop Clients — Nextcloud latest Developer Manual latest documentation](#desktop-clients-nextcloud-latest-developer-manual-latest-documentation) - [Desktop Clients — Nextcloud latest Developer Manual latest documentation](#desktop-clients-nextcloud-latest-developer-manual-latest-documentation) - [Clients and Client APIs — Nextcloud latest Developer Manual latest documentation](#clients-and-client-apis-nextcloud-latest-developer-manual-latest-documentation) - [Clients and Client APIs — Nextcloud latest Developer Manual latest documentation](#clients-and-client-apis-nextcloud-latest-developer-manual-latest-documentation) - [Development process — Nextcloud latest Developer Manual latest documentation](#development-process-nextcloud-latest-developer-manual-latest-documentation) - [Security guidelines — Nextcloud latest Developer Manual latest documentation](#security-guidelines-nextcloud-latest-developer-manual-latest-documentation) - [Compatibility with the app ecosystem — Nextcloud latest Developer Manual latest documentation](#compatibility-with-the-app-ecosystem-nextcloud-latest-developer-manual-latest-documentation) - [Compatibility with the app ecosystem — Nextcloud latest Developer Manual latest documentation](#compatibility-with-the-app-ecosystem-nextcloud-latest-developer-manual-latest-documentation) - [Coding style & general guidelines — Nextcloud latest Developer Manual latest documentation](#coding-style-general-guidelines-nextcloud-latest-developer-manual-latest-documentation) - [Development environment — Nextcloud latest Developer Manual latest documentation](#development-environment-nextcloud-latest-developer-manual-latest-documentation) - [Security guidelines — Nextcloud latest Developer Manual latest documentation](#security-guidelines-nextcloud-latest-developer-manual-latest-documentation) - [Coding style & general guidelines — Nextcloud latest Developer Manual latest documentation](#coding-style-general-guidelines-nextcloud-latest-developer-manual-latest-documentation) - [Development environment — Nextcloud latest Developer Manual latest documentation](#development-environment-nextcloud-latest-developer-manual-latest-documentation) - [Development environment — Nextcloud latest Developer Manual latest documentation](#development-environment-nextcloud-latest-developer-manual-latest-documentation) - [Routing — Nextcloud latest Developer Manual latest documentation](#routing-nextcloud-latest-developer-manual-latest-documentation) - [Request lifecycle — Nextcloud latest Developer Manual latest documentation](#request-lifecycle-nextcloud-latest-developer-manual-latest-documentation) - [Middlewares — Nextcloud latest Developer Manual latest documentation](#middlewares-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Navigation and pre-app configuration — Nextcloud latest Developer Manual latest documentation](#navigation-and-pre-app-configuration-nextcloud-latest-developer-manual-latest-documentation) - [Tutorial — Nextcloud latest Developer Manual latest documentation](#tutorial-nextcloud-latest-developer-manual-latest-documentation) - [Front-end — Nextcloud latest Developer Manual latest documentation](#front-end-nextcloud-latest-developer-manual-latest-documentation) - [Dependency injection — Nextcloud latest Developer Manual latest documentation](#dependency-injection-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Bootstrapping — Nextcloud latest Developer Manual latest documentation](#bootstrapping-nextcloud-latest-developer-manual-latest-documentation) - [Dependency management — Nextcloud latest Developer Manual latest documentation](#dependency-management-nextcloud-latest-developer-manual-latest-documentation) - [Development overview — Nextcloud latest Developer Manual latest documentation](#development-overview-nextcloud-latest-developer-manual-latest-documentation) - [Technical details — Nextcloud latest Developer Manual latest documentation](#technical-details-nextcloud-latest-developer-manual-latest-documentation) - [Frequently Asked Questions — Nextcloud latest Developer Manual latest documentation](#frequently-asked-questions-nextcloud-latest-developer-manual-latest-documentation) - [Routing — Nextcloud latest Developer Manual latest documentation](#routing-nextcloud-latest-developer-manual-latest-documentation) - [Routing — Nextcloud latest Developer Manual latest documentation](#routing-nextcloud-latest-developer-manual-latest-documentation) - [App metadata — Nextcloud latest Developer Manual latest documentation](#app-metadata-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Setting up dev environment — Nextcloud latest Developer Manual latest documentation](#setting-up-dev-environment-nextcloud-latest-developer-manual-latest-documentation) - [Translation setup — Nextcloud latest Developer Manual latest documentation](#translation-setup-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Middlewares — Nextcloud latest Developer Manual latest documentation](#middlewares-nextcloud-latest-developer-manual-latest-documentation) - [Tutorial — Nextcloud latest Developer Manual latest documentation](#tutorial-nextcloud-latest-developer-manual-latest-documentation) - [Technical details — Nextcloud latest Developer Manual latest documentation](#technical-details-nextcloud-latest-developer-manual-latest-documentation) - [Development overview — Nextcloud latest Developer Manual latest documentation](#development-overview-nextcloud-latest-developer-manual-latest-documentation) - [Development overview — Nextcloud latest Developer Manual latest documentation](#development-overview-nextcloud-latest-developer-manual-latest-documentation) - [Frequently Asked Questions — Nextcloud latest Developer Manual latest documentation](#frequently-asked-questions-nextcloud-latest-developer-manual-latest-documentation) - [Frequently Asked Questions — Nextcloud latest Developer Manual latest documentation](#frequently-asked-questions-nextcloud-latest-developer-manual-latest-documentation) - [Technical details — Nextcloud latest Developer Manual latest documentation](#technical-details-nextcloud-latest-developer-manual-latest-documentation) - [Dependency injection — Nextcloud latest Developer Manual latest documentation](#dependency-injection-nextcloud-latest-developer-manual-latest-documentation) - [Background jobs (Cron) — Nextcloud latest Developer Manual latest documentation](#background-jobs-cron-nextcloud-latest-developer-manual-latest-documentation) - [Translations — Nextcloud latest Developer Manual latest documentation](#translations-nextcloud-latest-developer-manual-latest-documentation) - [Bootstrapping — Nextcloud latest Developer Manual latest documentation](#bootstrapping-nextcloud-latest-developer-manual-latest-documentation) - [Front-end — Nextcloud latest Developer Manual latest documentation](#front-end-nextcloud-latest-developer-manual-latest-documentation) - [Controllers — Nextcloud latest Developer Manual latest documentation](#controllers-nextcloud-latest-developer-manual-latest-documentation) - [Tutorial — Nextcloud latest Developer Manual latest documentation](#tutorial-nextcloud-latest-developer-manual-latest-documentation) - [Front-end code — Nextcloud latest Developer Manual latest documentation](#front-end-code-nextcloud-latest-developer-manual-latest-documentation) - [Nextcloud Assistant — Nextcloud latest Administration Manual latest documentation](#nextcloud-assistant-nextcloud-latest-administration-manual-latest-documentation) - [Request lifecycle — Nextcloud latest Developer Manual latest documentation](#request-lifecycle-nextcloud-latest-developer-manual-latest-documentation) - [Request lifecycle — Nextcloud latest Developer Manual latest documentation](#request-lifecycle-nextcloud-latest-developer-manual-latest-documentation) - [Middlewares — Nextcloud latest Developer Manual latest documentation](#middlewares-nextcloud-latest-developer-manual-latest-documentation) - [Caching — Nextcloud latest Developer Manual latest documentation](#caching-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Bootstrapping — Nextcloud latest Developer Manual latest documentation](#bootstrapping-nextcloud-latest-developer-manual-latest-documentation) - [Setting up dev environment — Nextcloud latest Developer Manual latest documentation](#setting-up-dev-environment-nextcloud-latest-developer-manual-latest-documentation) - [Static analysis — Nextcloud latest Developer Manual latest documentation](#static-analysis-nextcloud-latest-developer-manual-latest-documentation) - [Setting up dev environment — Nextcloud latest Developer Manual latest documentation](#setting-up-dev-environment-nextcloud-latest-developer-manual-latest-documentation) - [Back-end code — Nextcloud latest Developer Manual latest documentation](#back-end-code-nextcloud-latest-developer-manual-latest-documentation) - [Dependency injection — Nextcloud latest Developer Manual latest documentation](#dependency-injection-nextcloud-latest-developer-manual-latest-documentation) - [Navigation and pre-app configuration — Nextcloud latest Developer Manual latest documentation](#navigation-and-pre-app-configuration-nextcloud-latest-developer-manual-latest-documentation) - [Nextcloud architecture — Nextcloud latest Developer Manual latest documentation](#nextcloud-architecture-nextcloud-latest-developer-manual-latest-documentation) - [External API — Nextcloud latest Developer Manual latest documentation](#external-api-nextcloud-latest-developer-manual-latest-documentation) - [Unit-Testing — Nextcloud latest Developer Manual latest documentation](#unit-testing-nextcloud-latest-developer-manual-latest-documentation) - [Front-end — Nextcloud latest Developer Manual latest documentation](#front-end-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Navigation and pre-app configuration — Nextcloud latest Developer Manual latest documentation](#navigation-and-pre-app-configuration-nextcloud-latest-developer-manual-latest-documentation) - [Logging — Nextcloud latest Developer Manual latest documentation](#logging-nextcloud-latest-developer-manual-latest-documentation) - [Dependency management — Nextcloud latest Developer Manual latest documentation](#dependency-management-nextcloud-latest-developer-manual-latest-documentation) - [App metadata — Nextcloud latest Developer Manual latest documentation](#app-metadata-nextcloud-latest-developer-manual-latest-documentation) - [App metadata — Nextcloud latest Developer Manual latest documentation](#app-metadata-nextcloud-latest-developer-manual-latest-documentation) - [Front-end code — Nextcloud latest Developer Manual latest documentation](#front-end-code-nextcloud-latest-developer-manual-latest-documentation) - [Back-end code — Nextcloud latest Developer Manual latest documentation](#back-end-code-nextcloud-latest-developer-manual-latest-documentation) - [Front-end code — Nextcloud latest Developer Manual latest documentation](#front-end-code-nextcloud-latest-developer-manual-latest-documentation) - [How to test … — Nextcloud latest Developer Manual latest documentation](#how-to-test-nextcloud-latest-developer-manual-latest-documentation) - [Static analysis — Nextcloud latest Developer Manual latest documentation](#static-analysis-nextcloud-latest-developer-manual-latest-documentation) - [Static analysis — Nextcloud latest Developer Manual latest documentation](#static-analysis-nextcloud-latest-developer-manual-latest-documentation) - [Back-end code — Nextcloud latest Developer Manual latest documentation](#back-end-code-nextcloud-latest-developer-manual-latest-documentation) - [Events — Nextcloud latest Developer Manual latest documentation](#events-nextcloud-latest-developer-manual-latest-documentation) - [Controllers — Nextcloud latest Developer Manual latest documentation](#controllers-nextcloud-latest-developer-manual-latest-documentation) - [Extending the DAV server — Nextcloud latest Developer Manual latest documentation](#extending-the-dav-server-nextcloud-latest-developer-manual-latest-documentation) - [Extending the DAV server — Nextcloud latest Developer Manual latest documentation](#extending-the-dav-server-nextcloud-latest-developer-manual-latest-documentation) - [Dependency management — Nextcloud latest Developer Manual latest documentation](#dependency-management-nextcloud-latest-developer-manual-latest-documentation) - [Translation setup — Nextcloud latest Developer Manual latest documentation](#translation-setup-nextcloud-latest-developer-manual-latest-documentation) - [Translation setup — Nextcloud latest Developer Manual latest documentation](#translation-setup-nextcloud-latest-developer-manual-latest-documentation) - [Nextcloud architecture — Nextcloud latest Developer Manual latest documentation](#nextcloud-architecture-nextcloud-latest-developer-manual-latest-documentation) - [Unit-Testing — Nextcloud latest Developer Manual latest documentation](#unit-testing-nextcloud-latest-developer-manual-latest-documentation) - [Controllers — Nextcloud latest Developer Manual latest documentation](#controllers-nextcloud-latest-developer-manual-latest-documentation) - [External API — Nextcloud latest Developer Manual latest documentation](#external-api-nextcloud-latest-developer-manual-latest-documentation) - [External API — Nextcloud latest Developer Manual latest documentation](#external-api-nextcloud-latest-developer-manual-latest-documentation) - [Unit-Testing — Nextcloud latest Developer Manual latest documentation](#unit-testing-nextcloud-latest-developer-manual-latest-documentation) - [Nextcloud architecture — Nextcloud latest Developer Manual latest documentation](#nextcloud-architecture-nextcloud-latest-developer-manual-latest-documentation) - [How to test … — Nextcloud latest Developer Manual latest documentation](#how-to-test-nextcloud-latest-developer-manual-latest-documentation) - [Background jobs (Cron) — Nextcloud latest Developer Manual latest documentation](#background-jobs-cron-nextcloud-latest-developer-manual-latest-documentation) - [Background jobs (Cron) — Nextcloud latest Developer Manual latest documentation](#background-jobs-cron-nextcloud-latest-developer-manual-latest-documentation) - [Translations — Nextcloud latest Developer Manual latest documentation](#translations-nextcloud-latest-developer-manual-latest-documentation) - [Storage and database — Nextcloud latest Developer Manual latest documentation](#storage-and-database-nextcloud-latest-developer-manual-latest-documentation) - [Public share template — Nextcloud latest Developer Manual latest documentation](#public-share-template-nextcloud-latest-developer-manual-latest-documentation) - [How to test … — Nextcloud latest Developer Manual latest documentation](#how-to-test-nextcloud-latest-developer-manual-latest-documentation) - [Events — Nextcloud latest Developer Manual latest documentation](#events-nextcloud-latest-developer-manual-latest-documentation) - [Caching — Nextcloud latest Developer Manual latest documentation](#caching-nextcloud-latest-developer-manual-latest-documentation) - [Translations — Nextcloud latest Developer Manual latest documentation](#translations-nextcloud-latest-developer-manual-latest-documentation) - [Events — Nextcloud latest Developer Manual latest documentation](#events-nextcloud-latest-developer-manual-latest-documentation) - [Logging — Nextcloud latest Developer Manual latest documentation](#logging-nextcloud-latest-developer-manual-latest-documentation) - [Logging — Nextcloud latest Developer Manual latest documentation](#logging-nextcloud-latest-developer-manual-latest-documentation) - [Caching — Nextcloud latest Developer Manual latest documentation](#caching-nextcloud-latest-developer-manual-latest-documentation) - [Testing — Nextcloud latest Developer Manual latest documentation](#testing-nextcloud-latest-developer-manual-latest-documentation) - [Storage and database — Nextcloud latest Developer Manual latest documentation](#storage-and-database-nextcloud-latest-developer-manual-latest-documentation) - [Storage and database — Nextcloud latest Developer Manual latest documentation](#storage-and-database-nextcloud-latest-developer-manual-latest-documentation) - [Public share template — Nextcloud latest Developer Manual latest documentation](#public-share-template-nextcloud-latest-developer-manual-latest-documentation) - [Testing — Nextcloud latest Developer Manual latest documentation](#testing-nextcloud-latest-developer-manual-latest-documentation) - [Public share template — Nextcloud latest Developer Manual latest documentation](#public-share-template-nextcloud-latest-developer-manual-latest-documentation) - [Testing — Nextcloud latest Developer Manual latest documentation](#testing-nextcloud-latest-developer-manual-latest-documentation) - [Settings — Nextcloud latest Developer Manual latest documentation](#settings-nextcloud-latest-developer-manual-latest-documentation) - [ExApp development — Nextcloud latest Developer Manual latest documentation](#exapp-development-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Foundations — Nextcloud latest Developer Manual latest documentation](#foundations-nextcloud-latest-developer-manual-latest-documentation) - [Layout — Nextcloud latest Developer Manual latest documentation](#layout-nextcloud-latest-developer-manual-latest-documentation) - [Settings — Nextcloud latest Developer Manual latest documentation](#settings-nextcloud-latest-developer-manual-latest-documentation) - [Atomic components — Nextcloud latest Developer Manual latest documentation](#atomic-components-nextcloud-latest-developer-manual-latest-documentation) - [Layout components — Nextcloud latest Developer Manual latest documentation](#layout-components-nextcloud-latest-developer-manual-latest-documentation) - [Maintainers — Nextcloud latest Developer Manual latest documentation](#maintainers-nextcloud-latest-developer-manual-latest-documentation) - [Monetizing your app — Nextcloud latest Developer Manual latest documentation](#monetizing-your-app-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Layout — Nextcloud latest Developer Manual latest documentation](#layout-nextcloud-latest-developer-manual-latest-documentation) - [Building the Client — Nextcloud latest Developer Manual latest documentation](#building-the-client-nextcloud-latest-developer-manual-latest-documentation) - [Building the Client — Nextcloud latest Developer Manual latest documentation](#building-the-client-nextcloud-latest-developer-manual-latest-documentation) - [Release process — Nextcloud latest Developer Manual latest documentation](#release-process-nextcloud-latest-developer-manual-latest-documentation) - [Foundations — Nextcloud latest Developer Manual latest documentation](#foundations-nextcloud-latest-developer-manual-latest-documentation) - [Layout — Nextcloud latest Developer Manual latest documentation](#layout-nextcloud-latest-developer-manual-latest-documentation) - [Foundations — Nextcloud latest Developer Manual latest documentation](#foundations-nextcloud-latest-developer-manual-latest-documentation) - [Code signing — Nextcloud latest Developer Manual latest documentation](#code-signing-nextcloud-latest-developer-manual-latest-documentation) - [Release Automation — Nextcloud latest Developer Manual latest documentation](#release-automation-nextcloud-latest-developer-manual-latest-documentation) - [App upgrade guide — Nextcloud latest Developer Manual latest documentation](#app-upgrade-guide-nextcloud-latest-developer-manual-latest-documentation) - [Layout components — Nextcloud latest Developer Manual latest documentation](#layout-components-nextcloud-latest-developer-manual-latest-documentation) - [Layout components — Nextcloud latest Developer Manual latest documentation](#layout-components-nextcloud-latest-developer-manual-latest-documentation) - [Atomic components — Nextcloud latest Developer Manual latest documentation](#atomic-components-nextcloud-latest-developer-manual-latest-documentation) - [Getting started — Nextcloud latest Developer Manual latest documentation](#getting-started-nextcloud-latest-developer-manual-latest-documentation) - [Getting started — Nextcloud latest Developer Manual latest documentation](#getting-started-nextcloud-latest-developer-manual-latest-documentation) - [Main content — Nextcloud latest Developer Manual latest documentation](#main-content-nextcloud-latest-developer-manual-latest-documentation) - [Atomic components — Nextcloud latest Developer Manual latest documentation](#atomic-components-nextcloud-latest-developer-manual-latest-documentation) - [Icons — Nextcloud latest Developer Manual latest documentation](#icons-nextcloud-latest-developer-manual-latest-documentation) - [Content list — Nextcloud latest Developer Manual latest documentation](#content-list-nextcloud-latest-developer-manual-latest-documentation) - [Maintainers — Nextcloud latest Developer Manual latest documentation](#maintainers-nextcloud-latest-developer-manual-latest-documentation) - [Maintainers — Nextcloud latest Developer Manual latest documentation](#maintainers-nextcloud-latest-developer-manual-latest-documentation) - [HTML elements — Nextcloud latest Developer Manual latest documentation](#html-elements-nextcloud-latest-developer-manual-latest-documentation) - [Popover menu — Nextcloud latest Developer Manual latest documentation](#popover-menu-nextcloud-latest-developer-manual-latest-documentation) - [Settings — Nextcloud latest Developer Manual latest documentation](#settings-nextcloud-latest-developer-manual-latest-documentation) - [Monetizing your app — Nextcloud latest Developer Manual latest documentation](#monetizing-your-app-nextcloud-latest-developer-manual-latest-documentation) - [Release process — Nextcloud latest Developer Manual latest documentation](#release-process-nextcloud-latest-developer-manual-latest-documentation) - [App upgrade guide — Nextcloud latest Developer Manual latest documentation](#app-upgrade-guide-nextcloud-latest-developer-manual-latest-documentation) - [Monetizing your app — Nextcloud latest Developer Manual latest documentation](#monetizing-your-app-nextcloud-latest-developer-manual-latest-documentation) - [App upgrade guide — Nextcloud latest Developer Manual latest documentation](#app-upgrade-guide-nextcloud-latest-developer-manual-latest-documentation) - [Release process — Nextcloud latest Developer Manual latest documentation](#release-process-nextcloud-latest-developer-manual-latest-documentation) - [Release Automation — Nextcloud latest Developer Manual latest documentation](#release-automation-nextcloud-latest-developer-manual-latest-documentation) - [Code signing — Nextcloud latest Developer Manual latest documentation](#code-signing-nextcloud-latest-developer-manual-latest-documentation) - [Code signing — Nextcloud latest Developer Manual latest documentation](#code-signing-nextcloud-latest-developer-manual-latest-documentation) - [Release Automation — Nextcloud latest Developer Manual latest documentation](#release-automation-nextcloud-latest-developer-manual-latest-documentation) - [Android — Nextcloud latest Developer Manual latest documentation](#android-nextcloud-latest-developer-manual-latest-documentation) - [Main content — Nextcloud latest Developer Manual latest documentation](#main-content-nextcloud-latest-developer-manual-latest-documentation) - [General — Nextcloud latest Developer Manual latest documentation](#general-nextcloud-latest-developer-manual-latest-documentation) - [Activity — Nextcloud latest Developer Manual latest documentation](#activity-nextcloud-latest-developer-manual-latest-documentation) - [Main content — Nextcloud latest Developer Manual latest documentation](#main-content-nextcloud-latest-developer-manual-latest-documentation) - [Prologue — Nextcloud latest Developer Manual latest documentation](#prologue-nextcloud-latest-developer-manual-latest-documentation) - [CSS — Nextcloud latest Developer Manual latest documentation](#css-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Files — Nextcloud latest Developer Manual latest documentation](#files-nextcloud-latest-developer-manual-latest-documentation) - [Popover menu — Nextcloud latest Developer Manual latest documentation](#popover-menu-nextcloud-latest-developer-manual-latest-documentation) - [Content list — Nextcloud latest Developer Manual latest documentation](#content-list-nextcloud-latest-developer-manual-latest-documentation) - [Content list — Nextcloud latest Developer Manual latest documentation](#content-list-nextcloud-latest-developer-manual-latest-documentation) - [Remote wipe — Nextcloud latest Developer Manual latest documentation](#remote-wipe-nextcloud-latest-developer-manual-latest-documentation) - [Icons — Nextcloud latest Developer Manual latest documentation](#icons-nextcloud-latest-developer-manual-latest-documentation) - [Icons — Nextcloud latest Developer Manual latest documentation](#icons-nextcloud-latest-developer-manual-latest-documentation) - [Webdav — Nextcloud latest Developer Manual latest documentation](#webdav-nextcloud-latest-developer-manual-latest-documentation) - [Login Flow — Nextcloud latest Developer Manual latest documentation](#login-flow-nextcloud-latest-developer-manual-latest-documentation) - [Popover menu — Nextcloud latest Developer Manual latest documentation](#popover-menu-nextcloud-latest-developer-manual-latest-documentation) - [HTML elements — Nextcloud latest Developer Manual latest documentation](#html-elements-nextcloud-latest-developer-manual-latest-documentation) - [HTML elements — Nextcloud latest Developer Manual latest documentation](#html-elements-nextcloud-latest-developer-manual-latest-documentation) - [CSS — Nextcloud latest Developer Manual latest documentation](#css-nextcloud-latest-developer-manual-latest-documentation) - [CSS — Nextcloud latest Developer Manual latest documentation](#css-nextcloud-latest-developer-manual-latest-documentation) - [General — Nextcloud latest Developer Manual latest documentation](#general-nextcloud-latest-developer-manual-latest-documentation) - [General — Nextcloud latest Developer Manual latest documentation](#general-nextcloud-latest-developer-manual-latest-documentation) - [Activity — Nextcloud latest Developer Manual latest documentation](#activity-nextcloud-latest-developer-manual-latest-documentation) - [App development — Nextcloud latest Developer Manual latest documentation](#app-development-nextcloud-latest-developer-manual-latest-documentation) - [Android — Nextcloud latest Developer Manual latest documentation](#android-nextcloud-latest-developer-manual-latest-documentation) - [Remote wipe — Nextcloud latest Developer Manual latest documentation](#remote-wipe-nextcloud-latest-developer-manual-latest-documentation) - [Android — Nextcloud latest Developer Manual latest documentation](#android-nextcloud-latest-developer-manual-latest-documentation) - [Activity — Nextcloud latest Developer Manual latest documentation](#activity-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [Login Flow — Nextcloud latest Developer Manual latest documentation](#login-flow-nextcloud-latest-developer-manual-latest-documentation) - [Login Flow — Nextcloud latest Developer Manual latest documentation](#login-flow-nextcloud-latest-developer-manual-latest-documentation) - [Files — Nextcloud latest Developer Manual latest documentation](#files-nextcloud-latest-developer-manual-latest-documentation) - [Remote wipe — Nextcloud latest Developer Manual latest documentation](#remote-wipe-nextcloud-latest-developer-manual-latest-documentation) - [Webdav — Nextcloud latest Developer Manual latest documentation](#webdav-nextcloud-latest-developer-manual-latest-documentation) - [Files — Nextcloud latest Developer Manual latest documentation](#files-nextcloud-latest-developer-manual-latest-documentation) - [Webdav — Nextcloud latest Developer Manual latest documentation](#webdav-nextcloud-latest-developer-manual-latest-documentation) - [Introduction — Nextcloud latest Developer Manual latest documentation](#introduction-nextcloud-latest-developer-manual-latest-documentation) - [The Nextcloud app store rules — Nextcloud latest Developer Manual latest documentation](#the-nextcloud-app-store-rules-nextcloud-latest-developer-manual-latest-documentation) - [The Nextcloud app store rules — Nextcloud latest Developer Manual latest documentation](#the-nextcloud-app-store-rules-nextcloud-latest-developer-manual-latest-documentation) - [The Nextcloud app store rules — Nextcloud latest Developer Manual latest documentation](#the-nextcloud-app-store-rules-nextcloud-latest-developer-manual-latest-documentation) - [Digging deeper — Nextcloud latest Developer Manual latest documentation](#digging-deeper-nextcloud-latest-developer-manual-latest-documentation) - [OCS API — Nextcloud latest Developer Manual latest documentation](#ocs-api-nextcloud-latest-developer-manual-latest-documentation) - [OCS API — Nextcloud latest Developer Manual latest documentation](#ocs-api-nextcloud-latest-developer-manual-latest-documentation) --- # Nextcloud developer documentation — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/#) * Nextcloud developer documentation * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/index.rst) * * * Nextcloud developer documentation[](https://docs.nextcloud.com/server/latest/developer_manual/#nextcloud-developer-documentation "Link to this heading") ========================================================================================================================================================== Table of contents[](https://docs.nextcloud.com/server/latest/developer_manual/#table-of-contents "Link to this heading") -------------------------------------------------------------------------------------------------------------------------- * [Prologue](https://docs.nextcloud.com/server/latest/developer_manual/prologue/index.html) * [Code of conduct](https://docs.nextcloud.com/server/latest/developer_manual/prologue/code-of-conduct.html) * [Help and communication](https://docs.nextcloud.com/server/latest/developer_manual/prologue/help_communication.html) * [Bugtracker](https://docs.nextcloud.com/server/latest/developer_manual/prologue/bugtracker/index.html) * [Security guidelines](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html) * [Compatibility with the app ecosystem](https://docs.nextcloud.com/server/latest/developer_manual/prologue/compatibility_app_ecosystem.html) * [Getting started](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/index.html) * [Development process](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/development_process.html) * [Development environment](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html) * [Coding style & general guidelines](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * [Request lifecycle](https://docs.nextcloud.com/server/latest/developer_manual/basics/request_lifecycle.html) * [Routing](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html) * [Dependency injection](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html) * [Controllers](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html) * [Middlewares](https://docs.nextcloud.com/server/latest/developer_manual/basics/middlewares.html) * [Events](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html) * [Front-end](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/index.html) * [Translations](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html) * [Background jobs (Cron)](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html) * [Caching](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html) * [Logging](https://docs.nextcloud.com/server/latest/developer_manual/basics/logging.html) * [Settings](https://docs.nextcloud.com/server/latest/developer_manual/basics/setting.html) * [Storage and database](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/index.html) * [Public share template](https://docs.nextcloud.com/server/latest/developer_manual/basics/public_share_template.html) * [Testing](https://docs.nextcloud.com/server/latest/developer_manual/basics/testing.html) * [App development](https://docs.nextcloud.com/server/latest/developer_manual/app_development/index.html) * [Introduction](https://docs.nextcloud.com/server/latest/developer_manual/app_development/intro.html) * [Tutorial](https://docs.nextcloud.com/server/latest/developer_manual/app_development/tutorial.html) * [Bootstrapping](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html) * [App metadata](https://docs.nextcloud.com/server/latest/developer_manual/app_development/info.html) * [Navigation and pre-app configuration](https://docs.nextcloud.com/server/latest/developer_manual/app_development/init.html) * [Dependency management](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html) * [Extending the DAV server](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dav_extension.html) * [Translation](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html) * [ExApp development](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/index.html) * [Introduction](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/Introduction.html) * [Setting up dev environment](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/DevSetup.html) * [Development overview](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/index.html) * [Technical details](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/index.html) * [Frequently Asked Questions](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/index.html) * [Server development](https://docs.nextcloud.com/server/latest/developer_manual/server/index.html) * [Front-end code](https://docs.nextcloud.com/server/latest/developer_manual/server/code-front-end.html) * [Back-end code](https://docs.nextcloud.com/server/latest/developer_manual/server/code-back-end.html) * [Static analysis](https://docs.nextcloud.com/server/latest/developer_manual/server/static-analysis.html) * [Unit-Testing](https://docs.nextcloud.com/server/latest/developer_manual/server/unit-testing.html) * [External API](https://docs.nextcloud.com/server/latest/developer_manual/server/externalapi.html) * [Nextcloud architecture](https://docs.nextcloud.com/server/latest/developer_manual/server/architecture/index.html) * [How to test …](https://docs.nextcloud.com/server/latest/developer_manual/how_to/index.html) * [Digging deeper](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/index.html) * [API reference](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/api.html) * [Config & Preferences](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/config/index.html) * [Classloader](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/classloader.html) * [Context Chat](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/context_chat.html) * [Continuous Integration](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/continuous_integration.html) * [Dashboard](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/dashboard.html) * [Deadlocks](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/deadlock.html) * [Debugging](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/debugging.html) * [Email](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/email.html) * [Files Metadata](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/files-metadata.html) * [Groupware integration](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/groupware/index.html) * [HTTP Client](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/http_client.html) * [JavaScript APIs](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/javascript-apis.html) * [Machine Translation](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/machinetranslation.html) * [Nextcloud Flow](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/flow.html) * [NPM](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/npm.html) * [Notifications](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/notifications.html) * [OpenID Connect (Oidc)](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/oidc.html) * [Out-of-office periods](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/out_of_office.html) * [Open Metrics exporter](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/openmetrics.html) * [Performance considerations](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/performance.html) * [Phone number util](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/phonenumberutil.html) * [PSR](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/psr.html) * [Profile](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/profile.html) * [Profiler](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/profiler.html) * [Projects](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/projects.html) * [Public Pages](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/publicpage.html) * [Reference providers](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/reference.html) * [Repair steps](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/repair.html) * [REST APIs](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/rest_apis.html) * [Search](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/search.html) * [Security](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/security.html) * [Settings](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/settings.html) * [Setup checks](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/setup_checks.html) * [Snowflake IDs](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/snowflake_ids.html) * [Speech-To-Text](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/speech-to-text.html) * [Talk Integration](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/talk.html) * [Task Processing](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/task_processing.html) * [Text Processing](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/text_processing.html) * [Text-To-Image](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/text2image.html) * [Two-factor providers](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/two-factor-provider.html) * [User Status](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/status.html) * [User migration](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/user_migration.html) * [User management](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/users.html) * [Web Host Metadata](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/web_host_metadata.html) * [WebDAV collection preload events](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/webdav_collection_preload.html) * [Working with time](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/time.html) * [App publishing and maintenance](https://docs.nextcloud.com/server/latest/developer_manual/app_publishing_maintenance/index.html) * [Maintainers](https://docs.nextcloud.com/server/latest/developer_manual/app_publishing_maintenance/maintainer.html) * [Release process](https://docs.nextcloud.com/server/latest/developer_manual/app_publishing_maintenance/release_process.html) * [Publishing App on the App Store](https://nextcloudappstore.readthedocs.io/en/latest/developer.html) * [Monetizing your app](https://docs.nextcloud.com/server/latest/developer_manual/app_publishing_maintenance/monetizing.html) * [The Nextcloud app store rules](https://docs.nextcloud.com/server/latest/developer_manual/app_publishing_maintenance/publishing.html) * [Code signing](https://docs.nextcloud.com/server/latest/developer_manual/app_publishing_maintenance/code_signing.html) * [Release Automation](https://docs.nextcloud.com/server/latest/developer_manual/app_publishing_maintenance/release_automation.html) * [App upgrade guide](https://docs.nextcloud.com/server/latest/developer_manual/app_publishing_maintenance/app_upgrade_guide/index.html) * [Interface & interaction design](https://docs.nextcloud.com/server/latest/developer_manual/design/index.html) * [Introduction](https://docs.nextcloud.com/server/latest/developer_manual/design/introduction.html) * [Foundations](https://docs.nextcloud.com/server/latest/developer_manual/design/foundations.html) * [Layout](https://docs.nextcloud.com/server/latest/developer_manual/design/layout.html) * [Layout components](https://docs.nextcloud.com/server/latest/developer_manual/design/layoutcomponents.html) * [Atomic components](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html) * [HTML/CSS guidelines](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/index.html) * [Introduction](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html) * [New button](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#new-button) * [App navigation menu](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#app-navigation-menu) * [Settings](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#settings) * [Main content](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/content.html) * [Content list](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/list.html) * [Popover menu](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/popovermenu.html) * [HTML elements](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/html.html) * [CSS](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/css.html) * [Icons](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/icons.html) * [Clients and Client APIs](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/index.html) * [General](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/general.html) * [Activity](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/activity-api.html) * [Android](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/android_library/index.html) * [Files](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/files.html) * [Login Flow](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html) * [OCS API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/index.html) * [Remote wipe](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/RemoteWipe/index.html) * [Webdav](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/index.html) * [Client Integration](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/ClientIntegration/index.html) * [Desktop Clients](https://docs.nextcloud.com/server/latest/developer_manual/desktop/index.html) * [Building the Client](https://docs.nextcloud.com/server/latest/developer_manual/desktop/building.html) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Development process — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Getting started](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/index.html) * Development process * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/getting_started/development_process.rst) * * * Development process[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/development_process.html#development-process "Link to this heading") ====================================================================================================================================================================== This page gives an overview of how Nextcloud code is developed. Source Code Version Control[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/development_process.html#source-code-version-control "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nextcloud uses [git](https://git-scm.com/) to manage revisions of the code. Software components have their own repositories. ### Branch Names[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/development_process.html#branch-names "Link to this heading") Default branches of Nextcloud and its app repositories are named `main` or `master`. Additionally, there are _stable branches_ whenever a major version of Nextcloud is released. Those are named `stableX`, where X refers to the version. For Nextcloud 25, for example, the stable branch is named `stable25`. Target Branches for Contributions[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/development_process.html#target-branches-for-contributions "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Any changes made to the source code go into the default branch of a repository through a [pull request](https://docs.github.com/en/pull-requests) . \# Switch to the default branch and update it git checkout main git pull origin main \# Create the new feature branch git checkout \-b feature/foo-bar \# Add and commit the changes git add file1 file2 git commit \--signoff \-m 'Add foo bar' \# Push the new commit to the remote repository and open a pull request git push origin feature/foo-bar ### Bugfixes[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/development_process.html#bugfixes "Link to this heading") If a contribution fixes a bug that also affects older Nextcloud or app releases, it may qualify for a _backport_. Backporting a fix means applying the change on an older version of the code. Git calls this operation _cherry picking_. #### Automatic Backport[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/development_process.html#automatic-backport "Link to this heading") In many cases the cherry pick results in a clean apply of the patch and git is able to resolve any small conflicts. In those cases it’s easiest to let the [backport bot](https://github.com/nextcloud/backportbot) do the backport. See the [bot usage](https://github.com/nextcloud/backportbot#usage) for its commands. #### Manual Backport[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/development_process.html#manual-backport "Link to this heading") More complex changes may require the developer to do the backport manually. This can be done as follows: \# Switch to the target branch and update it git checkout stable25 git pull origin stable25 \# Create the new backport branch git checkout \-b fix/foo-stable25 \# Cherry pick the change from the commit sha1 of the change against the default branch \# This might cause conflicts. Resolve them. git cherry-pick abc123 \# Push the cherry pick commit to the remote repository and open a pull request git push origin fix/foo-stable25 ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Coding style & general guidelines — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Getting started](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/index.html) * Coding style & general guidelines * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/getting_started/coding_standards/index.rst) * * * Coding style & general guidelines[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html#coding-style-general-guidelines "Link to this heading") =================================================================================================================================================================================================== General[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html#general "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------- * Ideally, discuss your plans on the [forums](https://help.nextcloud.com/) to see if others want to work with you on it * We use [GitHub](https://github.com/nextcloud) , please get an account there and clone the repositories you want to work on * Fixes go directly to the main branch, nevertheless they need to be tested thoroughly. * New features are always developed in a branch and only merged to the main branch once they are fully done. * Software should work. We only put features into the main branch when they are complete. It’s better to not have a feature instead of having one that works poorly. * It is best to start working based on an issue - create one if there is none. You describe what you want to do, ask feedback on the direction you take it and take it from there. * When you are finished, use the merge request function on GitHub to create a pull request. The other developers will look at it and give you feedback. You can signify that your PR is ready for review by adding the label “3. to review” to it. See [the code review page for more information](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/prologue/bugtracker/codereviews.html) * It is key to keep changes separate and small. The bigger and more hairy a PR grows, the harder it is to get it in. So split things up where you can in smaller changes - if you need a small improvement like a API addition for a big feature addition, get it in first rather than adding it to the big piece of work! * Decisions are made by consensus. We strive for making the best technical decisions and as nobody can know everything, we collaborate. That means a first negative comment might not be the final word, neither is positive feedback an immediate GO. Nextcloud is built out of modular pieces (apps) and maintainers have a strong influence. In case of disagreement we consult other seasoned contributors. Labels[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html#labels "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------- We assign labels to issues and pull requests to make it easy to find them and to signal what needs to be done. Some of these are assigned by the developers, others by QA, bug triagers, project lead or maintainers and so on. It is not desired that users/reporters of bugs assign labels themselves, unless they are developers/contributors to Nextcloud. The most important labels and their meaning: * Tags showing the state of the issue or PR, numbered 0-4: * `0. to triage` - issue or feature request needs to get triaged and approved for development * `1. to develop` - ready to start development on this * `2. developing` - development in progress * `3. to review` - ready for review * `4. to release` - reviewed PR that awaits unfreeze of a branch to get merged or has pending CI jobs * `needs info` - this issue needs further information from the reporter, see [Nextcloud bug triaging](https://docs.nextcloud.com/server/latest/developer_manual/prologue/bugtracker/triaging.html) . This tag is typically combined with `0. to triage` to signal a bug report is not confirmed yet or a feature request has not been approved. * `needs review` - this issue needs further investigation from the Nextcloud team, see [Nextcloud bug triaging](https://docs.nextcloud.com/server/latest/developer_manual/prologue/bugtracker/triaging.html) . * Tags showing the type of issue or PR * `bug` - this issue is a bug * `enhancement` - this issue is a feature request/idea for improvement of Nextcloud * `technical debt` - this issue or PR is about [technical debt](https://en.wikipedia.org/wiki/Technical_debt) * `overview` - this issue is a summary of a global effort, usually referencing other issues * Tags that classify an issue or PR * `high`, `medium` and `low` – signify how important the bug is. * `regression` - something that worked in a previous release but is now not working as expected or missing. * `feature: *`, e.g. `feature: dav` – these tags group tickets of specific feature or subsystems. * `design` - this needs help from the design team or is a design-related issue/pull request * `good first issue` - these are issues which are relatively easy to solve and ideal for people who want to learn how to code in Nextcloud * `backport-request` - the pull requests also needs to be applied to older Nextcloud versions. This tag is typically assigned by automation. User interface[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html#user-interface "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------- * Software should get out of the way. Do things automatically instead of offering configuration options. * Software should be easy to use. Show only the most important elements. Secondary elements only on hover or via Advanced function. * User data is sacred. Provide undo instead of asking for confirmation - [which might be dismissed](http://www.alistapart.com/articles/neveruseawarning/) * The state of the application should be clear. If something loads, provide feedback. * Do not adapt broken concepts (for example design of desktop apps) just for the sake of consistency. We aim to provide a better interface, so let’s find out how to do that! * Regularly reset your installation to see how the first-run experience is like. And improve it. * Ideally do [usability testing](http://jancborchardt.net/usability-in-free-software) to know how people use the software. * For further UX principles, read [Alex Faaborg from Mozilla](http://uxmag.com/articles/quantifying-usability) . Coding standards[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html#coding-standards "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Maximum line-length of 80 characters * Use tabs to indent * A tab is 4 spaces wide * Opening braces of blocks are on the same line as the definition * Quotes: ‘ for everything, “ for HTML attributes (

) * End of Lines : Unix style (LF / ‘n’) only * No global variables or functions * Code should be tested, ideally with unit and integration tests. * When you `git pull`, always `git pull --rebase` to avoid generating extra commits like: _merged main into main_ The most part of Nextcloud is written in PHP, Typescript / JavaScript, so we have some more fine grained coding standards for those languages: * [PHP coding standards](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/php.html) * [JavaScript and Typescript](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/javascript.html) * [CSS and HTML coding standards](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/html_css.html) License headers[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html#license-headers "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- Nextcloud is licensed under the [GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl) . From 16 June 2016, we switched to “GNU Affero General Public License v3.0 or later” for better long-term maintainability. If you create a new file please use this header: /\*\* \* SPDX-FileCopyrightText: \[year\] \[your name\] \[\] \* SPDX-License-Identifier: AGPL-3.0-or-later \*/ The year should then be the creation time and the email address is optional. If you edit an existing file please, please keep the existing license header as it is and just add your copyright notice, if you consider your changes substantial enough to claim copyright. In order to do so there are two options: * If a generic header is already present, please just add yourself to the AUTHORS.md file * If no generic header is present, you can add yourself with a copyright line as described above. As a rule of thumb, this is the case if you contributed more than seven lines of code. An example of a generic license header where adding yourself to the AUTHORS.md file is preferred please see the example below /\*\* \* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors \* SPDX-License-Identifier: AGPL-3.0-or-later \*/ The Nextcloud GmbH part only applies to employees of the company not to contributors. For more, general information on SPDX headers and their usage for reuse-compliance, please see * [REUSE](https://reuse.software/) * [SPDX](https://spdx.dev/) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Prologue — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * Prologue * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/index.rst) * * * Prologue[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/index.html#prologue "Link to this heading") =========================================================================================================================== * [Code of conduct](https://docs.nextcloud.com/server/latest/developer_manual/prologue/code-of-conduct.html) * [Help and communication](https://docs.nextcloud.com/server/latest/developer_manual/prologue/help_communication.html) * [Forums](https://docs.nextcloud.com/server/latest/developer_manual/prologue/help_communication.html#forums) * [Maintainers](https://docs.nextcloud.com/server/latest/developer_manual/prologue/help_communication.html#maintainers) * [Bugtracker](https://docs.nextcloud.com/server/latest/developer_manual/prologue/bugtracker/index.html) * [Security guidelines](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html) * [SQL injection](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#sql-injection) * [Cross site scripting](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#cross-site-scripting) * [Clickjacking](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#clickjacking) * [Code executions / file inclusions](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#code-executions-file-inclusions) * [Directory traversal](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#directory-traversal) * [Shell injection](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#shell-injection) * [Auth bypass / privilege escalations](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#auth-bypass-privilege-escalations) * [Sensitive data exposure](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#sensitive-data-exposure) * [Cross site request forgery](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#cross-site-request-forgery) * [Unvalidated redirects](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#unvalidated-redirects) * [CORS](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#cors) * [Getting help](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#getting-help) * [Compatibility with the app ecosystem](https://docs.nextcloud.com/server/latest/developer_manual/prologue/compatibility_app_ecosystem.html) * [Documentation procedures of changes that affect app developers](https://docs.nextcloud.com/server/latest/developer_manual/prologue/compatibility_app_ecosystem.html#documentation-procedures-of-changes-that-affect-app-developers) * [Other documentation requirements](https://docs.nextcloud.com/server/latest/developer_manual/prologue/compatibility_app_ecosystem.html#other-documentation-requirements) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Interface & interaction design — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * Interface & interaction design * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/design/index.rst) * * * Interface & interaction design[](https://docs.nextcloud.com/server/latest/developer_manual/design/index.html#interface-interaction-design "Link to this heading") =================================================================================================================================================================== * [Introduction](https://docs.nextcloud.com/server/latest/developer_manual/design/introduction.html) * [Foundations](https://docs.nextcloud.com/server/latest/developer_manual/design/foundations.html) * [Color](https://docs.nextcloud.com/server/latest/developer_manual/design/foundations.html#color) * [Typography](https://docs.nextcloud.com/server/latest/developer_manual/design/foundations.html#typography) * [Icons](https://docs.nextcloud.com/server/latest/developer_manual/design/foundations.html#icons) * [Naming](https://docs.nextcloud.com/server/latest/developer_manual/design/foundations.html#naming) * [Wording](https://docs.nextcloud.com/server/latest/developer_manual/design/foundations.html#wording) * [Layout](https://docs.nextcloud.com/server/latest/developer_manual/design/layout.html) * [Navigation → Content → Sidebar](https://docs.nextcloud.com/server/latest/developer_manual/design/layout.html#navigation-content-sidebar) * [Navigation → List → Content](https://docs.nextcloud.com/server/latest/developer_manual/design/layout.html#navigation-list-content) * [Layout components](https://docs.nextcloud.com/server/latest/developer_manual/design/layoutcomponents.html) * [Navigation](https://docs.nextcloud.com/server/latest/developer_manual/design/layoutcomponents.html#navigation) * [List item](https://docs.nextcloud.com/server/latest/developer_manual/design/layoutcomponents.html#list-item) * [Content](https://docs.nextcloud.com/server/latest/developer_manual/design/layoutcomponents.html#content) * [Sidebar](https://docs.nextcloud.com/server/latest/developer_manual/design/layoutcomponents.html#sidebar) * [Atomic components](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html) * [Buttons](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html#buttons) * [Action menu](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html#action-menu) * [Input fields](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html#input-fields) * [Pickers](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html#pickers) * [Tags](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html#tags) * [Modal](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html#modal) * [Avatar](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html#avatar) * [Progress bars and meters](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html#progress-bars-and-meters) * [User bubbles](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html#user-bubbles) * [Counter bubbles](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html#counter-bubbles) * [Empty content](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html#empty-content) * [Skeleton screens](https://docs.nextcloud.com/server/latest/developer_manual/design/atomiccomponents.html#skeleton-screens) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Code of conduct — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/latest/developer_manual/prologue/index.html) * Code of conduct * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/code-of-conduct.rst) * * * Code of conduct[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/code-of-conduct.html#code-of-conduct "Link to this heading") =================================================================================================================================================== We want the Nextcloud community to be a fun and productive environment for everyone. For that reason, we ask all contributors and participants to familiarize themselves with our [Code of Conduct](https://nextcloud.com/code-of-conduct) . ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Getting started — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * Getting started * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/getting_started/index.rst) * * * Getting started[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/index.html#getting-started "Link to this heading") ================================================================================================================================================ * [Development process](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/development_process.html) * [Source Code Version Control](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/development_process.html#source-code-version-control) * [Target Branches for Contributions](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/development_process.html#target-branches-for-contributions) * [Development environment](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html) * [Set up Web server and database](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html#set-up-web-server-and-database) * [Get the source](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html#get-the-source) * [Coding style & general guidelines](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html) * [General](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html#general) * [Labels](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html#labels) * [User interface](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html#user-interface) * [Coding standards](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html#coding-standards) * [License headers](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/coding_standards/index.html#license-headers) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # ExApp development — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * ExApp development * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/index.rst) * * * ExApp development[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/index.html#exapp-development "Link to this heading") ====================================================================================================================================================== * [Introduction](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/Introduction.html) * [Overview](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/Introduction.html#overview) * [Glossary](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/Introduction.html#glossary) * [Setting up dev environment](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/DevSetup.html) * [Install AppAPI](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/DevSetup.html#install-appapi) * [In Place of a Conclusion](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/DevSetup.html#in-place-of-a-conclusion) * [Development overview](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/index.html) * [ExApp development](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html) * [ExApp overview](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppOverview.html) * [ExApp lifecycle](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppLifecycle.html) * [Adapting ExApps to HaRP](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppHarpIntegration.html) * [Technical details](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/index.html) * [App Installation Flow](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/InstallationFlow.html) * [Deployment](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Deployment.html) * [Authentication](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Authentication.html) * [Translations](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Translations.html) * [AppAPI Nextcloud APIs](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/index.html) * [Frequently Asked Questions](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/index.html) * [Docker Container Registry](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/DockerContainerRegistry.html) * [Docker Socket Proxy](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/DockerSocketProxy.html) * [GPU support](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/GpuSupport.html) * [Scaling](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/Scaling.html) * [Corporate Proxy - Permanent Settings for PHP CLI](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/BehindCompanyProxy.html) * [Troubleshooting](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/Troubleshooting.html) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Development overview — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/index.html) * Development overview * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/development_overview/index.rst) * * * Development overview[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/index.html#development-overview "Link to this heading") ================================================================================================================================================================================= This section contains the most common information for ExApp developers, grouped from other parts of documentation. * [ExApp development](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html) * [0\. Setting up the development environment](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#setting-up-the-development-environment) * [1\. Starting from template](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#starting-from-template) * [3\. Development](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#development) * [4\. Packaging](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#packaging) * [5\. AppStore publishing](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#appstore-publishing) * [6\. Testing](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#testing) * [ExApp overview](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppOverview.html) * [ExApp structure](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppOverview.html#exapp-structure) * [Backend](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppOverview.html#backend) * [Frontend](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppOverview.html#frontend) * [L10n translations](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppOverview.html#l10n-translations) * [Makefile](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppOverview.html#makefile) * [ExApp lifecycle](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppLifecycle.html) * [ExApp lifecycle methods](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#exapp-lifecycle-methods) * [ExApp lifecycle scheme](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#exapp-lifecycle-scheme) * [Nextcloud-side ExApp lifecycle methods](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#nextcloud-side-exapp-lifecycle-methods) * [AppAPI Authentication](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#appapi-authentication) * [Adapting ExApps to HaRP](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppHarpIntegration.html) * [Summary](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppHarpIntegration.html#summary) * [Key integration considerations](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppHarpIntegration.html#key-integration-considerations) * [Steps needed to adapt an ExApp](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppHarpIntegration.html#steps-needed-to-adapt-an-exapp) * [Running your ExApp with a non-root user](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppHarpIntegration.html#running-your-exapp-with-a-non-root-user) * [Integration test example](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/development_overview/ExAppHarpIntegration.html#integration-test-example) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Technical details — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/index.html) * Technical details * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/tech_details/index.rst) * * * Technical details[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/index.html#technical-details "Link to this heading") =================================================================================================================================================================== * [App Installation Flow](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/InstallationFlow.html) * [Image Pulling (Docker)](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/InstallationFlow.html#image-pulling-docker) * [Heartbeat](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/InstallationFlow.html#heartbeat) * [Init](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/InstallationFlow.html#init) * [Enabled](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/InstallationFlow.html#enabled) * [Deployment](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Deployment.html) * [Overview](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Deployment.html#overview) * [DaemonConfig registration](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Deployment.html#daemonconfig-registration) * [ExApp registration](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Deployment.html#exapp-registration) * [Application installation scheme](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Deployment.html#application-installation-scheme) * [ExApp info.xml schema](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Deployment.html#exapp-info-xml-schema) * [Authentication](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Authentication.html) * [Authentication flow](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Authentication.html#authentication-flow) * [Authentication headers](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Authentication.html#authentication-headers) * [AppAPIAuth](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Authentication.html#appapiauth) * [AppAPI session keys](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Authentication.html#appapi-session-keys) * [Translations](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Translations.html) * [Front-end](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Translations.html#front-end) * [Back-end](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Translations.html#back-end) * [Manual translations](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Translations.html#manual-translations) * [Manual install](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Translations.html#manual-install) * [Docker install](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Translations.html#docker-install) * [Translation tool](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Translations.html#translation-tool) * [AppAPI Nextcloud APIs](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/index.html) * [Logging](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/logging.html) * [AppConfig](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/appconfig.html) * [Preferences](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/preferences.html) * [ExApp](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/exapp.html) * [Routes](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/routes.html) * [Miscellaneous OCS APIs](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/utils.html) * [File Actions Menu](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/fileactionsmenu.html) * [Top Menu Entry](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/topmenu.html) * [Declarative Settings](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/settings.html) * [Notifications](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/notifications.html) * [Events Listener](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/events_listener.html) * [OCC Command](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/occ_command.html) * [Talk bots](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/talkbots.html) * [Other OCS APIs](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/api/other_ocs.html) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Compatibility with the app ecosystem — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/latest/developer_manual/prologue/index.html) * Compatibility with the app ecosystem * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/compatibility_app_ecosystem.rst) * * * Compatibility with the app ecosystem[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/compatibility_app_ecosystem.html#compatibility-with-the-app-ecosystem "Link to this heading") ========================================================================================================================================================================================================= The Nextcloud app ecosystem consists of hundreds of apps and app maintainers. The development process may require changes that affect apps in this ecosystem. These changes may either be a change in standards or best practises, yet in more extreme cases the changes may also be breaking apps. While developers are expected to aim for limiting the number of changes that break apps, this cannot always be avoided or is not always reasonable to do to maintain an up-to-date technology stack. Informing app developers about any change that affect them is therefore key to a thriving ecosystem. This page describes the three procedures to document changes that are relevant to app developers. Documentation procedures of changes that affect app developers[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/compatibility_app_ecosystem.html#documentation-procedures-of-changes-that-affect-app-developers "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- There are three procedures in place to facilitate communication to app developers about changes that affect them: 1. The definition of **Done** of a pull request includes documentation. > This means the development of your pull request cannot be considered done if you introduced changes (additions, removals or modifications) that affect app developers that you did not document. 2. A change that affects app developers, has to be reported and documented by the author of the pull request in the [App Upgrade guide](https://docs.nextcloud.com/server/latest/developer_manual/app_publishing_maintenance/app_upgrade_guide/index.html#app-upgrade-guide) section. > The requirements for this documentation are: > > * It should be written so that app developers understand how to work around the change for their app in a tutorial format > > * The steps should be explicitly written, so the documentation shall not rely upon links to external resources for the steps. While it is encouraged to add an external links as additional reference, it is a hard requirement that the documentation is readable and actionable without browsing to this link. > > * The change author’s name should be added to the section so readers can reach out to the author if they have questions or if something is unclear. > > * Timeline: the documentation is required to be handed in when finalizing the pull request and should be merged timely close to the actual change. > Other documentation requirements[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/compatibility_app_ecosystem.html#other-documentation-requirements "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A change that affects administrators who upgrade their Nextcloud should be documented in the release notes section of the admin documentation of that release. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Help and communication — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/latest/developer_manual/prologue/index.html) * Help and communication * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/help_communication.rst) * * * Help and communication[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/help_communication.html#help-and-communication "Link to this heading") ==================================================================================================================================================================== Forums[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/help_communication.html#forums "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------ Communicate via our [forums](https://help.nextcloud.com/) . Maintainers[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/help_communication.html#maintainers "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- * [Contact](https://nextcloud.com/contact/) a maintainer of a certain app or division ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Bugtracker — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/latest/developer_manual/prologue/index.html) * Bugtracker * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/bugtracker/index.rst) * * * Bugtracker[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/bugtracker/index.html#bugtracker "Link to this heading") ========================================================================================================================================== Thank you for helping Nextcloud by reporting bugs. Before submitting an issue, please read [Issue submission guidelines](https://github.com/nextcloud/server/blob/master/.github/CONTRIBUTING.md#submitting-issues) first. * If the issue is with the Nextcloud server, report it to the [Server repository](https://github.com/nextcloud/server/issues) * If the issue is with the Nextcloud desktop client, report it to the [Desktop repository](https://github.com/nextcloud/desktop/issues) * If the issue is with the Nextcloud Android client, report it to the [Android repository](https://github.com/nextcloud/android/issues) * If the issue is with the Nextcloud iOS client, report it to the [iOS repository](https://github.com/nextcloud/ios/issues) * If the issue is with a Nextcloud app, report it to where that app is developed. See [App Store](https://apps.nextcloud.com/) page for related links. * If the app is listed in our [main GitHub organization](https://github.com/nextcloud) report it to the correct sub repository ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Introduction — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/index.html) * Introduction * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/Introduction.rst) * * * Introduction[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/Introduction.html#introduction "Link to this heading") =================================================================================================================================================== **ExApps** (short for “External Apps”) are Nextcloud apps that are developed in another programming language (outside of PHP) using the AppAPI OCS API. [AppAPI](https://apps.nextcloud.com/apps/app_api) is a project introduced by Nextcloud to revolutionize the process of application development within the Nextcloud ecosystem. Overview[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/Introduction.html#overview "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------- The main tasks of the AppAPI ecosystem are: > * Providing a reliable and fast method for authenticating applications > > * Supporting various application deployment options > > * Offering a clear and straightforward application administration interface > > * Ensuring a reliable implementation of all the necessary missing APIs for applications > > * Supplying clear, understandable documentation and support on how to implement libraries in other programming languages for writing next-gen applications for Nextcloud > The system should support the expansion and integration of new deployment methods, avoiding any tight coupling with a specific deployment type. Applications should be capable of indicating the deployment methods they can accommodate. Given the evolving landscape of new technologies and the potential emergence of more intricate or simplified deployment options, the system is architected to seamlessly embrace the integration of novel deployment modes. If you have any questions or corrections regarding the documentation, we would be glad to address them in discussions, incorporate corrections through pull requests, and handle complex problems through issues. Glossary[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/Introduction.html#glossary "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------- AppAPI brings out the following terms frequently used in the code: * `ExApp` (External App) - the app on another (from PHP) programming language, which uses AppAPI OCS API * `DaemonConfig` - configuration of orchestration daemon (e.g. Docker) where ExApps are deployed * `DeployConfig` - additional DaemonConfig options for orchestrator (e.g. network) and ExApps (nextcloud\_url, host, etc.) * `ExAppConfig` - similar to Nextcloud app\_config, but for ExApps configuration * `ExAppPreferences` - similar to Nextcloud app\_preferences, user-specific settings for ExApps * `AppAPIAuth` - AppAPI authentication * `FileActionsMenu` - entry in files actions menu (context menu) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Frequently Asked Questions — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/index.html) * Frequently Asked Questions * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/faq/index.rst) * * * Frequently Asked Questions[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/index.html#frequently-asked-questions "Link to this heading") ============================================================================================================================================================================ This section contains the most common or problematic questions that users or developers may encounter when working with AppAPI. It can be used as pointer to other parts of the documentation, as it usually refers to, or provide a brief answer. Note This section will be updated with time, as new questions arise. If you have a question that is not listed here or the answer is not enough for you, please feel free to ask it by creating an issue in the [AppAPI repository](https://github.com/nextcloud/app_api/issues) . * [Docker Container Registry](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/DockerContainerRegistry.html) * [How to use a private Docker container registry with authentication?](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/DockerContainerRegistry.html#how-to-use-a-private-docker-container-registry-with-authentication) * [Docker Socket Proxy](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/DockerSocketProxy.html) * [Nextcloud AppAPI DSP](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/DockerSocketProxy.html#nextcloud-appapi-dsp) * [Nextcloud AIO](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/DockerSocketProxy.html#nextcloud-aio) * [Other implementations](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/DockerSocketProxy.html#other-implementations) * [GPU support](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/GpuSupport.html) * [How to enable GPU support for the Deploy daemon?](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/GpuSupport.html#how-to-enable-gpu-support-for-the-deploy-daemon) * [How to limit the number of GPUs per ExApp?](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/GpuSupport.html#how-to-limit-the-number-of-gpus-per-exapp) * [Scaling](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/Scaling.html) * [GPUs scaling](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/Scaling.html#gpus-scaling) * [Corporate Proxy - Permanent Settings for PHP CLI](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/BehindCompanyProxy.html) * [Symptoms](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/BehindCompanyProxy.html#symptoms) * [Cause](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/BehindCompanyProxy.html#cause) * [Permanent Solution](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/BehindCompanyProxy.html#permanent-solution) * [Troubleshooting](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/BehindCompanyProxy.html#troubleshooting) * [Contact Support](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/BehindCompanyProxy.html#contact-support) * [Troubleshooting](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/Troubleshooting.html) * [How to troubleshoot networking issues?](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/Troubleshooting.html#how-to-troubleshoot-networking-issues) * [ExApp deployment issues](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/Troubleshooting.html#exapp-deployment-issues) * [Failed to create volume](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/Troubleshooting.html#failed-to-create-volume) * [ExApps management list of apps from App Store is empty](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/faq/Troubleshooting.html#exapps-management-list-of-apps-from-app-store-is-empty) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Setting up dev environment — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/index.html) * Setting up dev environment * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/DevSetup.rst) * * * Setting up dev environment[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/DevSetup.html#setting-up-dev-environment "Link to this heading") =========================================================================================================================================================================== AppAPI development requires a Nextcloud development environment setup. We highly recommend using [Julius Knorr’s Docker setup](https://github.com/juliusknorr/nextcloud-docker-dev) for this. For an alternate environment without using Docker, please refer to the setup instructions in [Getting started](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html) . Suggested IDE: **PhpStorm**, though you can certainly use any IDE of your preference such as **VS Code** or **Vim**. Install AppAPI[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/DevSetup.html#install-appapi "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------- All ExApps require the [AppAPI](https://apps.nextcloud.com/apps/app_api) Nextcloud app as a dependency. As of Nextcloud version 30.0.1, AppAPI is automatically installed by default. If you prefer, you can also build the latest development version of AppAPI from the source code, in which case uninstall the release version of AppAPI and perform the following steps. Clone the latest main branch: > git clone https://github.com/nextcloud/app\_api.git && cd app\_api or clone a specific version by specifying the version tag: > git clone https://github.com/nextcloud/app\_api.git \--branch && cd app\_api where `` is the version you want to install. Then, build frontend assets in development mode: > npm ci && npm run dev Enable AppAPI from the directory where the `occ` command resides: > ./occ app:enable \--force app\_api ### Deploy daemons types[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/DevSetup.html#deploy-daemons-types "Link to this heading") There are two types of Deploy daemons that can be used for development and testing of ExApps: 1. `manual_install`: This type of Deploy daemon is running manually in the host machine. This is useful for ExApp development as you can run your ExApp directly on the host. 2. `docker_install`: This type of Deploy daemon is running in a Docker container. You can register (create) these daemons in the AppAPI admin settings. For the equivalent `occ` command or an explanation of the Deploy daemon parameters, see [DaemonConfig registration](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Deployment.html#occ-daemon-config-registration) . ### Docker Socket Proxy[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/DevSetup.html#docker-socket-proxy "Link to this heading") For development and testing locally, the simplest way is to use the [Nextcloud AppAPI DSP HTTP](https://github.com/nextcloud/docker-socket-proxy?tab=readme-ov-file#httplocal) . In Place of a Conclusion[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/DevSetup.html#in-place-of-a-conclusion "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- There are several make commands available to ease frequent development actions. To see the complete list, execute `make help`. ### Docker remote API[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/DevSetup.html#docker-remote-api "Link to this heading") The Docker Engine remote API can be easily configured via `make dock2port` command. The command will create a docker container to provide remote Docker Engine API. Afterward, register DaemonConfigs in Nextcloud using `make dock-port` command. ### Docker by socket[](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/DevSetup.html#docker-by-socket "Link to this heading") For Docker via socket, use the command `make dock-sock`. This registers DaemonConfigs in Nextcloud for the default socket connection (`/var/run/docker.sock`). Make sure that socket has enough permissions for Nextcloud and webserver user to access it and actually forwarded to the container: ... volumes: ... \- /var/run/docker.sock:/var/run/docker.sock ... ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Security guidelines — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/latest/developer_manual/prologue/index.html) * Security guidelines * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/security.rst) * * * Security guidelines[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#security-guidelines "Link to this heading") ==================================================================================================================================================== This guideline highlights some of the most common security problems and how to prevent them. Please review your app if it contains any of the following security holes. Note **Program defensively**: for instance always check for CSRF or escape strings, even if you do not need it. This prevents future problems where you might miss a change that leads to a security hole. Note All App Framework security features depend on the call of the controller through `OCA\AppFramework\App::main`. If the controller method is executed directly, no security checks are being performed! SQL injection[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#sql-injection "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------- [SQL Injection](https://en.wikipedia.org/wiki/SQL_injection) occurs when SQL query strings are concatenated with variables. To prevent this, always use prepared queries: execute($params); If the App Framework is used, write SQL queries like this in a class that extends the Mapper: execute($sql, $params); Cross site scripting[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#cross-site-scripting "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------ [Cross site scripting](https://en.wikipedia.org/wiki/Cross-site_scripting) happens when user input is passed directly to templates. A potential attacker might be able to inject HTML/JavaScript into the page to steal the users session, log keyboard entries, even perform DDOS attacks on other websites or other malicious actions. Despite the fact that Nextcloud uses Content-Security-Policy to prevent the execution of inline JavaScript code developers are still required to prevent XSS. CSP is just another layer of defense that is not implemented in all web browsers. To prevent XSS in your app you have to sanitize the templates and all JavaScripts which performs a DOM manipulation. ### Templates[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#templates "Link to this heading") Let’s assume you use the following example in your application: to overtake the user account. The same problem occurs when outputting content from the database or any other location that is writable by users. Another attack vector that is often overlooked is XSS in **href** attributes. HTML allows to execute JavaScript in href attributes like this: To prevent XSS in your app, **never use echo, print() or <%=** - use **p()** instead which will sanitize the input. Also **validate URLs to start with the expected protocol** (starts with http for instance)! Note Should you ever require to print something unescaped, double check if it is really needed. If there is no other way (e.g. when including of subtemplates) use print\_unescaped with care. ### JavaScript[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#javascript "Link to this heading") Avoid manipulating the HTML directly via JavaScript, this often leads to XSS since people often forget to sanitize variables: var html \= '

  • ' + username + '
  • "'; If you **really** want to use JavaScript for something like this use escapeHTML to sanitize the variables: var html \= '
  • ' + escapeHTML(username) + '
  • '; An even better way to make your app safer is to use the jQuery built-in function **$.text()** instead of **$.html()**. **DON’T** messageTd.html(username); **DO** messageTd.text(username); It may also be wise to choose a proper JavaScript framework like AngularJS which automatically handles the JavaScript escaping for you. Clickjacking[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#clickjacking "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------- [Clickjacking](https://en.wikipedia.org/wiki/Clickjacking) tricks the user to click into an invisible iframe to perform an arbitrary action (e.g. delete a user account) To prevent such attacks Nextcloud sends the X-Frame-Options header to all template responses. Don’t remove this header if you don’t really need it! This is already built into Nextcloud in `OC_Template`. Code executions / file inclusions[](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#code-executions-file-inclusions "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Code Execution means that an attacker is able to include an arbitrary PHP file. This PHP file runs with all the privileges granted to the normal application and can do an enormous amount of damage. Code executions and file inclusions can be easily prevented by **never** allowing user-input to run through the following functions: * **include()** * **require()** * **require\_once()** * **eval()** * **fopen()** Note Also **never** allow the user to upload files into a folder which is reachable from the URL! **DON’T** = 8.5 for unit testing. PHPUnit documentation: [https://phpunit.de/documentation.html](https://phpunit.de/documentation.html) ### Writing PHP unit tests[](https://docs.nextcloud.com/server/latest/developer_manual/server/unit-testing.html#writing-php-unit-tests "Link to this heading") To get started, do the following: * Create a directory called `tests` in the top level of your application * Create a PHP file in the directory and `require_once` your class which you want to test Then you can simply run the created test with **phpunit**. Note If you use Nextcloud functions in your class under test (i.e., OC::getUser()) you’ll need to bootstrap Nextcloud or use dependency injection. Note You’ll most likely run your tests under a different user than the Web server. This might cause problems with your PHP settings (i.e., open\_basedir) and requires you to adjust your configuration. An example for a simple test would be: `/srv/http/nextcloud/apps/myapp/tests/testaddtwo.php` testMe \= new \\OCA\\Myapp\\TestMe(); } public function testAddTwo(){ $this\->assertEquals(5, $this\->testMe\->addTwo(3)); } } `/srv/http/nextcloud/apps/myapp/lib/testme.php` \[\ // Apps\ \['name' \=> 'Bar#getFoo', 'url' \=> '/foobar', 'verb' \=> 'GET'\],\ \],\ \]; ### Returning data[](https://docs.nextcloud.com/server/latest/developer_manual/server/externalapi.html#returning-data "Link to this heading") Once the API backend has matched your URL, your callable function as defined in **BarController::getFoo** will be executed. The AppFramework will make sure that send parameters are provided to the method based on its declaration. Be sure to extend the `OCP\AppFramework\OCSController` from the AppFramework. Your functions then should returns a `OCP\AppFramework\Http\DataResponse`. The AppFramework will then take care formatting the response properly. ### Exceptions[](https://docs.nextcloud.com/server/latest/developer_manual/server/externalapi.html#exceptions "Link to this heading") To throw an exception to the user in the OCS response. You can throw an `OCP\AppFramework\OCS\OCSException`. You can set the message and code. There are 3 commonly used exceptions already available: * `OCSBadRequestException` * `OCSForbiddenException` * `OCSNotFoundException` ### Authentication & basics[](https://docs.nextcloud.com/server/latest/developer_manual/server/externalapi.html#authentication-basics "Link to this heading") The requests to the OCS endpoint often have to be authenticated. > `curl -u user:password https://example.com/ocs/v2.php/apps/yourapp/foobar` ### Output[](https://docs.nextcloud.com/server/latest/developer_manual/server/externalapi.html#output "Link to this heading") The output defaults to XML. If you want to get JSON append this to the URL: ?format=json Or set the proper Accept header: Accept: application/json Output from the application is wrapped inside a **data** element: **XML**: ok 200 **JSON**: { "ocs": { "meta": { "status": "ok", "statuscode": 200, "message": null }, "data": { // data here } } } ### Statuscodes[](https://docs.nextcloud.com/server/latest/developer_manual/server/externalapi.html#statuscodes "Link to this heading") The statuscode can be any of the following numbers: * **200** - successful * **996** - server error * **401** - not authorized * **404** - not found * **999** - unknown error ### Changing API and backwards compatibility[](https://docs.nextcloud.com/server/latest/developer_manual/server/externalapi.html#changing-api-and-backwards-compatibility "Link to this heading") We aim to keep our API as stable as possible to avoid breaking third-party apps. Before an API is allowed to be removed, it should be marked as deprecated for at least 3 years (9 Nextcloud releases) before it gets removed. Changing the API [should be discussed in a github issue in our server repo](https://github.com/nextcloud/server/issues) . A pull request is most welcome. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # App development — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * App development * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/index.rst) * * * App development[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/index.html#app-development "Link to this heading") ================================================================================================================================================ * [Introduction](https://docs.nextcloud.com/server/latest/developer_manual/app_development/intro.html) * [Create an app](https://docs.nextcloud.com/server/latest/developer_manual/app_development/intro.html#create-an-app) * [Edit an existing app](https://docs.nextcloud.com/server/latest/developer_manual/app_development/intro.html#edit-an-existing-app) * [Enable the app](https://docs.nextcloud.com/server/latest/developer_manual/app_development/intro.html#enable-the-app) * [App architecture](https://docs.nextcloud.com/server/latest/developer_manual/app_development/intro.html#app-architecture) * [Tutorial](https://docs.nextcloud.com/server/latest/developer_manual/app_development/tutorial.html) * [Bootstrapping](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html) * [The Application class](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#the-application-class) * [Bootstrapping process](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#bootstrapping-process) * [App metadata](https://docs.nextcloud.com/server/latest/developer_manual/app_development/info.html) * [Changelog](https://docs.nextcloud.com/server/latest/developer_manual/app_development/info.html#changelog) * [Navigation and pre-app configuration](https://docs.nextcloud.com/server/latest/developer_manual/app_development/init.html) * [Adding a navigation entry](https://docs.nextcloud.com/server/latest/developer_manual/app_development/init.html#adding-a-navigation-entry) * [Initialization events](https://docs.nextcloud.com/server/latest/developer_manual/app_development/init.html#initialization-events) * [Dependency management](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html) * [Composer](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#composer) * [Extending the DAV server](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dav_extension.html) * [Registering a DAV plugin](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dav_extension.html#registering-a-dav-plugin) * [Handling DAV events](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dav_extension.html#handling-dav-events) * [Performance considerations](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dav_extension.html#performance-considerations) * [Translation](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html) * [Translation tool](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#translation-tool) * [Setup of the transifex sync](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#setup-of-the-transifex-sync) * [Manual translation](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#manual-translation) * [Documentation on the translation process](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#documentation-on-the-translation-process) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Navigation and pre-app configuration — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/latest/developer_manual/app_development/index.html) * Navigation and pre-app configuration * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/init.rst) * * * Navigation and pre-app configuration[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/init.html#navigation-and-pre-app-configuration "Link to this heading") ========================================================================================================================================================================================= Adding a navigation entry[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/init.html#adding-a-navigation-entry "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- Navigation entries for apps can be created by adding a navigation section to the `appinfo/info.xml` file, containing the name, order and route the navigation entry should link to. For details on the XML schema check the [app store documentation](https://nextcloudappstore.readthedocs.io/en/latest/developer.html#info-xml) . MyApp myapp.page.index 0 Initialization events[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/init.html#initialization-events "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------- Often apps do not need to load their JavaScript and CSS on every page. For this purpose there are several events emitted that an app can act upon. * `OCA\Files::loadAdditionalScripts` (string): loaded on the files list page * `OCA\Files_Sharing::loadAdditionalScripts` (string): loaded on the public sharing page * `OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth` (string): loaded on the public share authentication page * `OCP\AppFramework\Http\TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS` (constant): loaded when a template response is finished * `OCP\AppFramework\Http\TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS_LOGGEDIN` (constant): loaded when a template response is finished for a logged in user You can subscribe listeners to these events in the [bootstrapping code](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#bootstrapping) of the app. See the [events documentation](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#events) for more details on the event dispatcher and available events. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Bootstrapping — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/latest/developer_manual/app_development/index.html) * Bootstrapping * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/bootstrap.rst) * * * Bootstrapping[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#bootstrapping "Link to this heading") ================================================================================================================================================ Every php process has a relatively short lifespan that lasts as long as the HTTP request or the invocation of the command line program. At the beginning of this lifespan, Nextcloud initializes its services. At the same time, any additional apps might want to register their services to Nextcloud as well. This event is called the _bootstrapping_ and this chapter shall shed some light on how to hook into this with an app. The Application class[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#the-application-class "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- The Application class is the main entry point of an app. This class is optional but highly recommended if your app needs to register any services or run some code for every request. Nextcloud will try to autoload the class from the namespace `\OCA\\AppInfo\Application`, like `\OCA\MyApp\AppInfo\Application`, where _MyApp_ would be the name of your app. The file will therefore have the location `myapp/lib/AppInfo/Application.php`. registerEventListener( BeforeUserDeletedEvent::class, UserDeletedListener::class ); } public function boot(IBootContext $context): void { // ... boot logic goes here ... /\*\* @var IManager $manager \*/ $manager \= $context\->getAppContainer()\->query(IManager::class); $manager\->registerNotifierService(Notifier::class); } } Note that the context objects of the methods `register` and `boot` have different interfaces and thus have different capabilities appropriate for their stage. Bootstrapping process[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#bootstrapping-process "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- To give a better overview of _when_ each of the bootstrapping stages are reached and how they app can interact with them, this section explains the changes done for Nextcloud 20. ### Nextcloud 20 and later[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#nextcloud-20-and-later "Link to this heading") Nextcloud 20 is the first release with the interface `\OCP\AppFramework\Bootstrap\IBootstrap`. This interface can be implemented by your app’s `Application` class to signal that it wants to act on the bootstrapping stages. The major difference between this and the old process is that the bootstrapping is not performed in sequence, but apps register and boot interleaved. This should ensure that an app that `boot`s can rely on all other apps’ registration to be finished. The overall process is as follows: 1. In each installed and enabled app that has an `Application` class that also implements `IBootstrap`, the `register` method will be called. This method receives a context argument via which the app can prime the dependency injection container and register other services lazily, e.g. by calling `$context->registerService(...)`. The emphasis is on **laziness**. At this very early stage of the process lifetime, no other apps nor all of the server components are ready. Therefore the app **must not** try to use anything except the API provided by the context. That shall ensure that all apps can safely run their registration logic before any services are queried (instantiated) from the DI container or related code is run. 2. Nextcloud will load groups of certain apps early, e.g. filesystem or session apps, and other later. 3. Nextcloud will query the app’s `Application` class (again), no matter whether it implements `IBootstrap` or not. 4. Nextcloud will invoke the [boot](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#app-bootstrap-boot) method of every `Application` instance that implements `IBootstrap`. At this stage you may assume that all registrations via `IBootstrap::register` have completed. #### Booting an app[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#booting-an-app "Link to this heading") Any code that should run once for every Nextcloud process goes into the `boot` method of an app’s `Application` class. Use this mechanism carefully as it could have a negative effect on Nextcloud’s overall performance. lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#id3 "Link to this code") getAppContainer()\->query(IFooManager::class); $manager\->registerCustomFoo(MyFooImpl::class); } } The code above fetches a fictional _foo manager_ to register an app class. The boot context object comes with a `injectFn` helper that eases dependency injection inside the `boot` method by injecting arguments of a callable: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#id4 "Link to this code") injectFn(function(IFooManager $manager) { $manager\->registerCustomFoo(MyFooImpl::class); }); } } With the help of `Closure::fromCallable` you can also delegate to other methods that get their arguments injected: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#id5 "Link to this code") injectFn($this\->registerFoo(...)); } protected function registerFoo(IFooManager $manager): void { $manager\->registerCustomFoo(MyFooImpl::class); } } ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Dependency management — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/latest/developer_manual/app_development/index.html) * Dependency management * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/dependency_management.rst) * * * Dependency management[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#dependency-management "Link to this heading") ============================================================================================================================================================================ You can leverage existing software packages to build a Nextcloud app. Composer[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#composer "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- You can add 3rd party php packages with [Composer](https://getcomposer.org/) . Composer will download the specified packages to a directory of your choice, typically to `/vendor`. In order to benefit from Composer’s autoloader, you’ll want to add a `require_once` to the `register` method of your `Application` class in the [bootstrapping](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html#bootstrapping) code of your app. ### Remove unneeded files from packages[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#remove-unneeded-files-from-packages "Link to this heading") It is heavily recommended to remove files that are not required in production from the final packages. This especially, but not exclusively, refers to: * Developer files, e.g. `/Makefile` * CI workflows, e.g. `/.github` * Test assets, e.g. `/tests` * Configuration of development tools, e.g. `/phpunit.xml`, `/psalm.xml` * Git or other version control code, e.g. `/.git` You can check the [Server’s .gitignore](https://github.com/nextcloud/3rdparty/blob/master/.gitignore) file for more inspiration. ### Dependency hell[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#dependency-hell "Link to this heading") Be careful with which packages you add to an app. PHP can not load two version of the same class twice, hence there can be conflicts between Nextcloud Server and an app or between two or more apps if they require the same package. So try to keep the number of production dependencies to a minimum and see [Development tools](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#app-composer-bin-tools) . Alternatively you can use \[composer-bin-plugin\]([https://github.com/bamarni/composer-bin-plugin](https://github.com/bamarni/composer-bin-plugin) ) to avoid dependency conflicts between apps. 1. Install composer-bin-plugin according to their docs. > composer require \--dev bamarni/composer-bin-plugin 2. Install the tools you need in the vendor-bin directory. > composer bin psalm require \--dev psalm/phar > composer bin psalm require \--dev nextcloud/ocp:dev-master 3. Adjust some config (see below) * Add in composer.json: composer.json[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#id2 "Link to this code") { "extra": { "bamarni-bin": { "bin-links": true, "forward-command": true } } } * Add in composer.json: composer.json[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#id3 "Link to this code") { "scripts": { "post-install-cmd": \[\ "\[ $COMPOSER\_DEV\_MODE -eq 0 \] || composer bin all install --ansi"\ \], "post-update-cmd": \[\ "\[ $COMPOSER\_DEV\_MODE -eq 0 \] || composer bin all update --ansi"\ \] } } * Adjust psalm.xml: * Ensure the schemaLocation is correct: psalm.xml[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#id4 "Link to this code") xsi:schemaLocation="https://getpsalm.org/schema/config vendor-bin/psalm/vendor/vimeo/psalm/config.xsd" * Ensure it has something like this: psalm.xml[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#id5 "Link to this code") * Adjust .php-cs-fixer.dist.php .php-cs-fixer.dist.php[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#id6 "Link to this code") require\_once \_\_DIR\_\_ . '/vendor-bin/cs-fixer/vendor/autoload.php'; #### Conflict example[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#conflict-example "Link to this heading") To illustrate the problem imagine app _A_ depends on package _foo_ in version 1, app _B_ depends on package _foo_ in version 2. The package _foo_ had a breaking change to which app _B_ has been adjusted, _A_ uses the old API. Both apps ship a Composer autoloader that autoloads the _foo_ functions and classes. There is a race between the two autoloaders. If _A_’s autoloader is asked to load the class first, then v1 will be used. If _B_’s autoloader loads functions and classes first it will be v2. In some scenarios there might be classes of v1 and v2 when autoloaders are invoked without a defined order. Depending on which functions and classes are loaded, app _A_ might work or break. The same applies to _B_. ### Development tools[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#development-tools "Link to this heading") It is very common for an app to use CLI tools for syntax checks, testing and building. Since many tools depend on common Composer packages like `psr/*` and `symfony/console`, it is likely that apps produce a [dependency hell](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dependency_management.html#app-composer-dependency-hell) on development environments. The dependency hell for CLI tools can be avoided by using the _Composer bin plugin_. It’s a composer plugin that puts development dependencies into sub directorory with a dedicated autoloader. That autoloader is only used if the CLI tool is used. For Nextcloud apps this means two apps can use conflicting versions of one tool. Moreover dependency conflicts between the tools of one app are no longer an issue. Tools known to be problematic that should be moved into bin plugin directories include * `friendsofphp/php-cs-fixer` * `phpunit/phpunit` * `vimeo/psalm` Please see the [package page](https://packagist.org/packages/bamarni/composer-bin-plugin) for up-to-date installation instructions. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Translation — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/latest/developer_manual/app_development/index.html) * Translation * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/translation.rst) * * * Translation[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#translation "Link to this heading") ============================================================================================================================================== Nextcloud’s translation system is powered by [Transifex](https://explore.transifex.com/nextcloud/) . To start translating sign up and enter a group. If your community app should be translated by the [Nextcloud community on Transifex](https://explore.transifex.com/nextcloud/) just follow the setup section below. Translation tool[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#translation-tool "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------- Note The tool-based translation currently only supports repositories hosted on `github.com`. If your app is hosted elsewhere, you can try to follow the [Manual translation](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#manual-translation) instead. The [translation tool](https://github.com/nextcloud/docker-ci/tree/master/translations/translationtool) scrapes the source code for method calls to `t()` or `n()` to extract the strings that should be translated. If you check in minified JS code for example then those method names are also quite common and could cause wrong extractions. For this reason we allow to specify a list of files that the translation tool will not scrape for strings. You simply need to add a file named `.l10nignore` into the root folder of your app and specify the files one per line: \# compiled vue templates js/bruteforcesettings.js Setup of the transifex sync[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#setup-of-the-transifex-sync "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ### Transifex configuration `.tx/config`[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#transifex-configuration-tx-config "Link to this heading") To setup the transifex sync within the Nextcloud community you need to add first the transifex config to your app folder at `.tx/config` (please replace `MYAPP` with your apps id): \[main\] host \= https://www.transifex.com lang\_map \= hu\_HU: hu, nb\_NO: nb, sk\_SK: sk, th\_TH: th, ja\_JP: ja, bg\_BG: bg, cs\_CZ: cs, fi\_FI: fi \[o:nextcloud:p:nextcloud:r:{{APPID}}\] file\_filter \= translationfiles//{{APPID}}.po source\_file \= translationfiles/templates/{{APPID}}.pot source\_lang \= en type \= PO Then create a folder `l10n` and a file `l10n/.gitkeep` to create an empty folder which later holds the translations. ### Branch selection `.tx/backport`[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#branch-selection-tx-backport "Link to this heading") The bot will run every night and only push commits to the following branches branch once there is an update to the translation: * main * master * stableX (X being the recent 3 versions of Nextcloud Server) You can overwrite this list by creating a file `.tx/backport` in your repository with the following content: develop stable That would sync the translations for the branches (`main` and `master` are added automatically): * main * master * develop * stable ### Excluding files `.l10nignore`[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#excluding-files-l10nignore "Link to this heading") Add one more file called `.l10nignore` in root of the repository and the files and folders to ignore for translations. This should be used to exclude files that create false-positive translations, such as: * Compiled JavaScript files `js/` * 3rd-party PHP dependencies `vendor/` * Non-shipped files and documentation `docs/` ### Validate source strings[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#validate-source-strings "Link to this heading") After finishing the setup, you can validate the translation source strings which outlines some common mistakes. Clone the [nextcloud/docker-ci](https://github.com/nextcloud/docker-ci/) repository and afterwards run the following script: bash translations/validateSyncSetup.sh Owner Repository ### Repository permissions[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#repository-permissions "Link to this heading") Now the GitHub account [@nextcloud-bot](https://github.com/nextcloud-bot) needs to get `write` access to your repository. You can invite it from your repository settings: https://github.com///settings/access After sending the invitation, please [open a ticket using the “Request translations” template](https://github.com/nextcloud/docker-ci/issues/new/choose) . Attention In general you should enable the [protected branches feature](https://help.github.com/articles/configuring-protected-branches/) for default and stable branches. If you do that, you need to grant the [@nextcloud-bot](https://github.com/nextcloud-bot) `admin` permissions and allow administrators to bypass the protection. This feature however is only possible for repositories owned by organizations, not in repositories owned by individuals! You can [create your own organization](https://docs.github.com/en/organizations/collaborating-with-groups-in-organizations/creating-a-new-organization-from-scratch) If you need help just [open a ticket with the request](https://github.com/nextcloud/docker-ci/issues/new/choose) and we can also guide you through the steps. Manual translation[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#manual-translation "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------ If Transifex is not the right choice or the app is not accepted for translation, generate the gettext strings by yourself by executing our [translation tool](https://github.com/nextcloud/docker-ci/tree/master/translations/translationtool) in the app folder: cd /srv/http/nextcloud/apps/myapp translationtool.phar create\-pot\-files The translation tool requires `gettext`, installable via: apt\-get install gettext The above tool generates a template that can be used to translate all strings of an app. This template is located in the folder `translationfiles/template/` with the name `myapp.pot`. It can be used by your favored translation tool such as [Poedit](https://poedit.net/) . It then creates a `.po` file. The `.po` file needs to be placed in a folder named like the language code with the app name as filename - for example `translationfiles/es/myapp.po`. After this step the tool needs to be invoked to transfer the po file into our own fileformat that is more easily readable by the server code: translationtool.phar convert\-po\-files Now the following folder structure is available: myapp/l10n |-- es.js |-- es.json myapp/translationfiles |-- es | |-- myapp.po |-- templates |-- myapp.pot You then just need the `.json` and `.js` files for a working localized app. Documentation on the translation process[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#documentation-on-the-translation-process "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The following describes four processes: 1. Process to translate new string ![Process to translate new string](https://docs.nextcloud.com/server/latest/developer_manual/_images/translation_process1.png) 2. Process to correct typo/grammar issue in translated string ![Process to correct typo/grammar issue in translated string](https://docs.nextcloud.com/server/latest/developer_manual/_images/translation_process2.png) 3. Process for making an untranslatable string translatable ![Process for making an untranslatable string translatable](https://docs.nextcloud.com/server/latest/developer_manual/_images/translation_process3.png) 4. Process to correct issue in source string ![Process to correct issue in source string](https://docs.nextcloud.com/server/latest/developer_manual/_images/translation_process4.png) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # HTML/CSS guidelines — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * HTML/CSS guidelines * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/html_css_design/index.rst) * * * HTML/CSS guidelines[](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/index.html#html-css-guidelines "Link to this heading") ======================================================================================================================================================== * [Introduction](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html) * [New button](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#new-button) * [Introduction](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#id1) * [Basic layout](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#basic-layout) * [Rules](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#rules) * [App navigation menu](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#app-navigation-menu) * [Introduction](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#id2) * [Basic layout](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#id3) * [Basic rules](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#basic-rules) * [Utils: menu, counter & buttons](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#utils-menu-counter-buttons) * [Drag and drop](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#drag-and-drop) * [Collapsible entry](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#collapsible-entry) * [Entry bullet](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#entry-bullet) * [Undo entry](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#undo-entry) * [Edit entry](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#edit-entry) * [Pinned entry](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#pinned-entry) * [Various information](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#various-information) * [Settings](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#settings) * [Introduction](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#id4) * [Basic layout](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/navigation.html#id5) * [Main content](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/content.html) * [Rules and information](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/content.html#rules-and-information) * [Content list](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/list.html) * [Introduction](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/list.html#introduction) * [Basic layout](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/list.html#basic-layout) * [Rules and information](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/list.html#rules-and-information) * [Popovermenu in item](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/list.html#popovermenu-in-item) * [Popover menu](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/popovermenu.html) * [What is a popover menu](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/popovermenu.html#what-is-a-popover-menu) * [Basic layout](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/popovermenu.html#basic-layout) * [Technical details](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/popovermenu.html#technical-details) * [Alignment](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/popovermenu.html#alignment) * [HTML elements](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/html.html) * [Progress bar](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/html.html#progress-bar) * [Checkboxes and radios](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/html.html#checkboxes-and-radios) * [Buttons](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/html.html#buttons) * [CSS](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/css.html) * [CSS variables](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/css.html#css-variables) * [CSS classes](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/css.html#css-classes) * [Icons](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/icons.html) * [List of available icons](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/icons.html#list-of-available-icons) * [Svg color api](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/icons.html#svg-color-api) * [Material design icons](https://docs.nextcloud.com/server/latest/developer_manual/html_css_design/icons.html#material-design-icons) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Tutorial — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/latest/developer_manual/app_development/index.html) * Tutorial * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/tutorial.rst) * * * Tutorial[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/tutorial.html#tutorial "Link to this heading") ===================================================================================================================================== To help you get started on Nextcloud app development we have compiled a comprehensive set of tutorials that cover everything from setting up your development environment to developing a full fledged app with database storage. Please head [here](https://cloud.nextcloud.com/s/iyNGp8ryWxc7Efa?path=%2F) to get started. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # How to test … — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/latest/developer_manual/server/index.html) * How to test … * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/how_to/index.rst) * * * How to test …[](https://docs.nextcloud.com/server/latest/developer_manual/how_to/index.html#how-to-test "Link to this heading") ================================================================================================================================= This page should explain how to test given features in Nextcloud. Email sending[](https://docs.nextcloud.com/server/latest/developer_manual/how_to/index.html#email-sending "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------- docker run \-d \-p 1025:1025 \-p 8025:8025 mailhog/mailhog occ config:system:set mail\_smtpmode \--value\=smtp occ config:system:set mail\_smtphost \--value\=127.0.0.1 occ config:system:set mail\_smtpport \--value\=1025 \--type\=integer Then after having Nextcloud send some emails, open [http://127.0.0.1:8025](http://127.0.0.1:8025/) to view them. Redis[](https://docs.nextcloud.com/server/latest/developer_manual/how_to/index.html#redis "Link to this heading") ------------------------------------------------------------------------------------------------------------------- First you need to install the [phpredis extension](https://github.com/phpredis/phpredis) . There is a install document available [inside the repo](https://github.com/phpredis/phpredis/blob/develop/INSTALL.markdown) and many linux distribtutions ship it in their repositories as well. > pecl install redis Redis Cluster[](https://docs.nextcloud.com/server/latest/developer_manual/how_to/index.html#redis-cluster "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------- For a local Redis cluster setup there are some docker script collected in [this repository](https://github.com/Grokzen/docker-redis-cluster) . It boils down to clone the repo and run make up. Then the redis cluster is available at `localhost:7000`. Following `config.php` can be used: 'memcache.distributed' \=> '\\OC\\Memcache\\Redis', 'redis.cluster' \=> \[\ 'seeds' \=> \[ // provide some/all of the cluster servers to bootstrap discovery, port required\ 'localhost:7000',\ \],\ 'timeout' \=> 0.0,\ 'read\_timeout' \=> 0.0,\ 'failover\_mode' \=> \\RedisCluster::FAILOVER\_ERROR,\ \], Primary object store with S3[](https://docs.nextcloud.com/server/latest/developer_manual/how_to/index.html#primary-object-store-with-s3 "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- docker run \-p 9000:9000 minio/minio server /data The edit `config.php` and add the following section: 'objectstore' \=> array ( 'class' \=> 'OC\\\\Files\\\\ObjectStore\\\\S3', 'arguments' \=> array ( 'bucket' \=> 'nextcloud-dev', 'key' \=> 'minioadmin', 'secret' \=> 'minioadmin', 'hostname' \=> 'localhost', 'port' \=> '9000', 'use\_ssl' \=> false, 'use\_path\_style' \=> true, ), ), S3 external storage[](https://docs.nextcloud.com/server/latest/developer_manual/how_to/index.html#s3-external-storage "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------- occ app:enable files\_external docker run \-p 9000:9000 minio/minio server /data Then add an external storage in the web UI using the following configuration: * Authentication type: Access key * Access key: minioadmin * Secret key: minioadmin * Bucket: nextcloud-dev * Hostname: localhost * Port: 9000 * Region: leave empty * Storage class: leave empty * Enable SSL: false * Enable path style: yes SMB external storage[](https://docs.nextcloud.com/server/latest/developer_manual/how_to/index.html#smb-external-storage "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------- SMB external storage can be tested with Docker. The following commands create an SMB server with a public (shared) directory and user home directories for the credentials `smb1:pwd1` and `smb2:pwd2`. occ app:enable files\_external mkdir \-p /tmp/samba/{public,home/{smb1,smb2}} chmod a+rw /tmp/samba/home/smb\* docker run \-it \-p 139:139 \-p 445:445 \\ \-v /tmp/samba/public:/smbpublic \\ \-v /tmp/samba/home:/smbhome \\ dperson/samba \\ \-u "smb1;pwd1" \\ \-u "smb2;pwd2" \\ \-s "public;/smbmount;yes;no;yes" \\ \-s "home;/smbhome/%U;yes;no;no;all;none" Make sure that smbclient is installed on your Nextcloud server and has the following configuration: \# /etc/samba/smb.conf \[global\] client min protocol \= SMB2 client max protocol \= SMB3 hide dot files \= no The setup can be verified with smbclient //127.0.0.1/public \-U smb1 \# Shared storage for all users smbclient //127.0.0.1/home \-U smb1 \--password\=pwd1 \# Home storage SAML setup with onelogin[](https://docs.nextcloud.com/server/latest/developer_manual/how_to/index.html#saml-setup-with-onelogin "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------- * create dev account on onelogin.com * log into onelogin.com * create new app: SAML Test Connector (Advanced) > * go to “Configuration” > > > * Audience: [https://localhost/apps/user\_saml/saml/metadata](https://localhost/apps/user_saml/saml/metadata) > > > > * Recipient: [https://localhost/apps/user\_saml/saml/acs](https://localhost/apps/user_saml/saml/acs) > > > > * ACS (Consumer) URL Validator: [https://localhost/apps/user\_saml/saml/acs](https://localhost/apps/user_saml/saml/acs) > > > > * go to “Parameters” > > > * Add “User.email” -> email (and add to assertion) > > > > * Add “User.FirstName” -> first name (and add to assertion) > > > > * Add “User.LastName” -> last name (and add to assertion) > > > * open Nextcloud SAML settings > * Select SAML > > * Configure it according to [https://portal.nextcloud.com/article/configuring-single-sign-on-10.html](https://portal.nextcloud.com/article/configuring-single-sign-on-10.html) > Collabora without SSL[](https://docs.nextcloud.com/server/latest/developer_manual/how_to/index.html#collabora-without-ssl "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------- **1) Start Collabora in a docker container** docker run \-p 127.0.0.1:9980:9980 \-e 'domain=172.17.0.1' \\ \-e 'username=admin' \-e 'password=487903ffcf4' \\ \-e extra\_params\='--o:ssl.enable=false' \\ \--restart always \--cap\-add MKNOD collabora/code * 172.17.0.1 is localhost, which is default by Docker * get IP of Collabora container: docker inspect –format=’{{ .NetworkSettings.IPAddress }}’ $containerName **2) Configure Nextcloud** * go to your local cloud (e.g. 172.17.0.1/nc) -> Settings -> Collabora * set URL to IP you found out above, e.g: [http://172.17.0.2:9980](http://172.17.0.2:9980/) * check “Disable certificate verification (insecure) **3) Use** * please note that you cannot use it with localhost, but you have to enter a valid IP address of localhost * with this approach you can also use it with mobile clients **4) Troubleshoot** * [http://172.17.0.2:9980/hosting/capabilities](http://172.17.0.2:9980/hosting/capabilities) should give you: {"convert-to":{"available":false},"hasMobileSupport":true,"hasTemplateSaveAs":true,"productName":"Collabora Online Development Edition"} OnlyOffice[](https://docs.nextcloud.com/server/latest/developer_manual/how_to/index.html#onlyoffice "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------- 1. Create self signed cert, should be on a permanent path: mkdir \-p /tmp/oo/certs cd /tmp/oo/certs openssl genrsa \-out onlyoffice.key 4096 openssl req \-new \-key onlyoffice.key \-out onlyoffice.csr openssl x509 \-req \-days 3650 \-in onlyoffice.csr \-signkey onlyoffice.key \-out onlyoffice.crt openssl dhparam \-out dhparam.pem 4096 chmod 400 onlyoffice.key chmod 400 onlyoffice.crt chmod 400 onlyoffice.csr chmod 400 dhparam.pem 2. Start docker, important: do not use certs folder, but parent folder: docker run \--name\=ONLYOFFICEDOCKER \-i \-t \-d \-p 4433:443 \\ \-e JWT\_ENABLED\='true' \-e JWT\_SECRET\='secret' \--restart\=always \\ \-v /tmp/oo/:/var/www/onlyoffice/Data onlyoffice/documentserver 3. Go into docker container: > * docker exec -it ONLYOFFICEDOCKER /bin/bash > > * apt-get update > > * apt-get install vim -y > > * vim /etc/onlyoffice/documentserver/default.json > > * change rejectUnauthorized to false > > > * vim /etc/onlyoffice/documentserver/local.json > > * change token -> inbox -> header to “AuthorizationJWT” > > * change token -> outbox -> header to “AuthorizationJWT” > > > * Add the following to your config.php > > > 'onlyoffice' \=> array ( > 'verify\_peer\_off' \=> true, > 'jwt\_secret' \=> 'secret', > 'jwt\_header' \=> 'AuthorizationJWT' > ), Test with local ip: [https://localhost:4433](https://localhost:4433/) * accept cert warning * verify that “Document Server is running” is shown Test with Nextcloud * download & enable OnlyOffice app * configure: * Document Editing Service address: [https://localhost:4433/](https://localhost:4433/) * Secret key : secret (as above) * Document Editing Service address for internal requests from the server: [https://localhost:4433/](https://localhost:4433/) * Server address for internal requests from the Document Editing Service: [http://192.168.1.95/nc16/](http://192.168.1.95/nc16/) (needs to be real IP address, as localhost points to docker) WebAuthn without SSL[](https://docs.nextcloud.com/server/latest/developer_manual/how_to/index.html#webauthn-without-ssl "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------- [Chrome has the option to test WebAuthn with a fake device](https://developer.chrome.com/docs/devtools/webauthn/) . Browsers support WebAuthn on HTTPS protected sites and localhost domains. Unfortunately this is not supported by the used PHP library where the check for HTTPS needs to be commented for testing on non-HTTPS localhost development environments. diff --git a/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php b/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php index 8400ba9c..49279cc7 100644 --- a/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php +++ b/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php @@ -152,7 +152,7 @@ class AuthenticatorAssertionResponseValidator Assertion::isArray($parsedRelyingPartyId, 'Invalid origin'); if (!in\_array($facetId, $securedRelyingPartyId, true)) { $scheme = $parsedRelyingPartyId\['scheme'\] ?? ''; - Assertion::eq('https', $scheme, 'Invalid scheme. HTTPS required.'); + #Assertion::eq('https', $scheme, 'Invalid scheme. HTTPS required.'); } $clientDataRpId = $parsedRelyingPartyId\['host'\] ?? ''; Assertion::notEmpty($clientDataRpId, 'Invalid origin rpId.'); diff --git a/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php b/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php index f3e5a15d..3927bf23 100644 --- a/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php +++ b/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php @@ -150,7 +150,7 @@ class AuthenticatorAttestationResponseValidator if (!in\_array($facetId, $securedRelyingPartyId, true)) { $scheme = $parsedRelyingPartyId\['scheme'\] ?? ''; - Assertion::eq('https', $scheme, 'Invalid scheme. HTTPS required.'); + #Assertion::eq('https', $scheme, 'Invalid scheme. HTTPS required.'); } /\* @see 7.1.6 \*/ ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Extending the DAV server — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/latest/developer_manual/app_development/index.html) * Extending the DAV server * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/dav_extension.rst) * * * Extending the DAV server[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dav_extension.html#extending-the-dav-server "Link to this heading") ========================================================================================================================================================================== Nextcloud apps can extend the DAV server by registering SabreDAV plugins that hook into different phases of a DAV request. Plugins can add handlers for custom methods and properties, adjust response behavior, and more. See [Writing Plugins - sabre/dav](https://sabre.io/dav/writing-plugins/) for additional possibilities. Registering a DAV plugin[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dav_extension.html#registering-a-dav-plugin "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To register a server plugin in your app, register an event listener for `OCA\DAV\Events\SabrePluginAddEvent` (introduced in Nextcloud 28). In the listener’s handler, add your DAV plugin to the server. For example: MyApplication.php[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dav_extension.html#id1 "Link to this code") class MyApplication extends App implements IBootstrap { public function register(IRegistrationContext $context): void { $context\->registerEventListener(SabrePluginAddEvent::class, MyListener::class); } } MyListener.php[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dav_extension.html#id2 "Link to this code") use OCP\\EventDispatcher\\Event; use OCP\\EventDispatcher\\IEventListener; use OCA\\DAV\\Events\\SabrePluginAddEvent; class MyListener implements IEventListener { public function handle(Event $event): void { if (!$event instanceof SabrePluginAddEvent) { return; } $server \= $event\->getServer(); $server\->addPlugin(new MyDavPlugin()); } } Handling DAV events[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dav_extension.html#handling-dav-events "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- In this example, we register a handler for the `propFind` event and add a custom property that is returned in PROPFIND requests. MyDavPlugin.php[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dav_extension.html#id3 "Link to this code") use Sabre\\DAV\\ServerPlugin; use Sabre\\DAV\\PropFind; class MyDavPlugin extends ServerPlugin { public function initialize(\\Sabre\\DAV\\Server $server): void { // Register your property handler $server\->on('propFind', $this\->handleGetProperties(...)); } private function handleGetProperties(PropFind $propFind, \\Sabre\\DAV\\INode $node): void { // Add a property called "my-property" with the value "custom" $propFind\->handle('{myapplication.example}my-property', fn() \=> 'custom'); } } Performance considerations[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/dav_extension.html#performance-considerations "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ In the example above, if you replace the “custom” value with a database lookup, you introduce a performance issue: a query runs every time the property is loaded. This may not be obvious at first, but it quickly becomes a problem, because a `propFind` event is emitted for every file in a collection to discover its properties. If a collection contains 1,000 children, the code issues 1,000 queries that are likely very similar, differing only by the file identifier. To mitigate this, Nextcloud 32 introduces a new event that signals your app to preload data for a collection and its immediate children. Read more in [WebDAV collection preload events](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/webdav_collection_preload.html#collection-preload) . ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Development environment — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Getting started](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/index.html) * Development environment * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/getting_started/devenv.rst) * * * Development environment[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html#development-environment "Link to this heading") ================================================================================================================================================================= We have a tutorial available on setting up your development environment using docker. You can find the tutorial [here](https://cloud.nextcloud.com/s/iyNGp8ryWxc7Efa?path=%2F) . We recommend you to follow that tutorial. This page describes how to set up your development environment without docker. Please follow the steps on this page to set up your development environment manually. Set up Web server and database[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html#set-up-web-server-and-database "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- First [set up your Web server and database](https://docs.nextcloud.com/server/latest/admin_manual/installation/index.html) (**Section**: Manual Installation - Prerequisites). Get the source[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html#get-the-source "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------- There are two ways to obtain Nextcloud sources: * Using the [stable version](https://docs.nextcloud.com/server/latest/admin_manual/installation/index.html) * Using the development version from [GitHub](https://github.com/nextcloud) which will be explained below. To check out the source from [GitHub](https://github.com/nextcloud) you will need to install Git (see [Setting up Git](https://help.github.com/articles/set-up-git) from the GitHub help) ### Gather information about server setup[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html#gather-information-about-server-setup "Link to this heading") To get started the basic Git repositories need to be cloned into the Web server’s directory. Depending on the distribution this will either be * **/var/www** * **/var/www/html** * **/srv/http** Then identify the user and group the Web server is running as and the Apache user and group for the **chown** command will either be * **http** * **www-data** * **apache** * **wwwrun** ### Check out the code[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html#check-out-the-code "Link to this heading") The following commands are using **/var/www** as the Web server’s directory and **www-data** as user name and group. Make the directory writable so you can install the code as your regular user, and don’t need root privileges: sudo chmod o+rw /var/www Then install Nextcloud at the root of your site from Git: git clone https://github.com/nextcloud/server.git /var/www/ cd /var/www git submodule update \--init If you prefer to install Nextcloud in a sub-folder, replace /var/www with /var/www/. Create the data folder: cd /var/www mkdir data Adjust permissions: cd /var/www sudo chown \-R www\-data:www\-data config data apps sudo chmod o\-rw /var/www Finally, restart the Web server (this might vary depending on your distribution): sudo systemctl restart httpd.service or: sudo systemctl restart apache2.service or: sudo /etc/init.d/apache2 restart Now access the installation at [http://localhost/](http://localhost/) (or the corresponding URL) in your web browser to set up your instance. ### Check out external shipped apps[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html#check-out-external-shipped-apps "Link to this heading") This optional step is especially necessary if you want to test upgrading, as the following apps are required to be present during an upgrade. Install the viewer app: cd /var/www/apps git clone https://github.com/nextcloud/viewer.git Make sure to use a version compatible with the server by checking out the matching tag. You can check the `appinfo/info.xml` of the app to see if its `min-version` field is compatible with the current server. When upgrading the server code you might need to upgrade the app code as well before running `occ upgrade`. Note The same applies to all the apps listed under `alwaysEnabled` in [shipped.json](https://github.com/nextcloud/server/blob/master/core/shipped.json#L49) but most are already present in the server repository. ### Enabling debug mode[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html#enabling-debug-mode "Link to this heading") Note Do not enable this for production! This can create security problems and is only meant for debugging and development! To disable JavaScript and CSS caching, debugging has to be enabled by setting `debug` to `true` in `config/config.php`: true, ... configuration goes here ... ); ### Keep the code up-to-date[](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html#keep-the-code-up-to-date "Link to this heading") If you have more than one repository cloned, it can be time consuming to do the same the action to all repositories one by one. To solve this, you can use the following command template: find . \-maxdepth \-type d \-name .git \-exec sh \-c 'cd "{}"/../ && pwd && ' \\; then, e.g. to pull all changes in all repositories, you only need this: find . \-maxdepth 3 \-type d \-name .git \-exec sh \-c 'cd "{}"/../ && pwd && git pull --rebase' \\; or to prune all merged branches, you would execute this: find . \-maxdepth 3 \-type d \-name .git \-exec sh \-c 'cd "{}"/../ && pwd && git remote prune origin' \\; It is even easier if you create alias from these commands in case you want to avoid retyping those each time you need them. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Clients and Client APIs — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * Clients and Client APIs * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/client_apis/index.rst) * * * Clients and Client APIs[](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/index.html#clients-and-client-apis "Link to this heading") ============================================================================================================================================================ * [General](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/general.html) * [Generic Errors](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/general.html#generic-errors) * [Activity](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/activity-api.html) * [Android](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/android_library/index.html) * [Android Nextcloud client development](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/android_library/index.html#android-nextcloud-client-development) * [Nextcloud Android library](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/android_library/index.html#nextcloud-android-library) * [Files](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/files.html) * [Events](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/files.html#events) * [Router](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/files.html#router) * [Login Flow](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html) * [Opening the webview](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#opening-the-webview) * [Login in the user](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#login-in-the-user) * [Obtaining the login credentials](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#obtaining-the-login-credentials) * [Converting to app passwords](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#converting-to-app-passwords) * [Deleting an app password](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#deleting-an-app-password) * [Login flow v2](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#login-flow-v2) * [Troubleshooting](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/LoginFlow/index.html#troubleshooting) * [OCS API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/index.html) * [OCS OpenAPI tutorial](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-openapi.html) * [OCS APIs overview](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-api-overview.html) * [OCS Share API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-share-api.html) * [OCS Sharee API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-sharee-api.html) * [OCS Status API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-status-api.html) * [OCS Recommendations API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-recommendations-api.html) * [OCS user preferences API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-user-preferences-api.html) * [OCS Translation API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-translation-api.html) * [OCS TextProcessing API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-textprocessing-api.html) * [OCS Text-To-Image API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-text2image-api.html) * [OCS TaskProcessing API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-taskprocessing-api.html) * [OCS Out-of-office API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-out-of-office-api.html) * [OCS FullTextSearch Collection API](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-fulltextsearch-collections-api.html) * [Remote wipe](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/RemoteWipe/index.html) * [Obtaining wipe status](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/RemoteWipe/index.html#obtaining-wipe-status) * [Wiping the actual device](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/RemoteWipe/index.html#wiping-the-actual-device) * [Signalling completion](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/RemoteWipe/index.html#signalling-completion) * [Webdav](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/index.html) * [Basic APIs](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/basic.html) * [Search](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/search.html) * [Trashbin](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/trashbin.html) * [Versions](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/versions.html) * [Chunked file upload](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/chunking.html) * [File bulk upload](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/bulkupload.html) * [Comments](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/WebDAV/comments.html) * [Client Integration](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/ClientIntegration/index.html) * [Supported clients](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/ClientIntegration/index.html#supported-clients) * [Supported server apps](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/ClientIntegration/index.html#supported-server-apps) * [Exposing actions via capability](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/ClientIntegration/index.html#exposing-actions-via-capability) * [Hooks](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/ClientIntegration/index.html#hooks) * [Endpoint](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/ClientIntegration/index.html#endpoint) * [Responses](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/ClientIntegration/index.html#responses) * [Example](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/ClientIntegration/index.html#example) * [Develop your first app with client integration](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/ClientIntegration/index.html#develop-your-first-app-with-client-integration) * [Issues/Bugs](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/ClientIntegration/index.html#issues-bugs) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Introduction — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/latest/developer_manual/app_development/index.html) * Introduction * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/intro.rst) * * * Introduction[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/intro.html#introduction "Link to this heading") ========================================================================================================================================== Create an app[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/intro.html#create-an-app "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------- After [you’ve set up the development environment](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html) change into the Nextcloud apps directory: cd /var/www/nextcloud/apps Then create a skeleton app in the [app store](https://apps.nextcloud.com/developer/apps/generate) . This doesn’t publish anything on the appstore yet, it just gives you a download. Edit an existing app[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/intro.html#edit-an-existing-app "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------- Alternatively, if you would like to contribute to an existing app instead of creating a new one, first [set up the development environment](https://docs.nextcloud.com/server/latest/developer_manual/getting_started/devenv.html) , then create an apps-extra folder in the Nextcloud root directory: cd /var/www/nextcloud/apps\-extra You can then configure Nextcloud to run apps from this directory, by changing your app\_paths system config in your config.php 'apps\_paths' \=> array ( 0 \=> array ( 'path' \=> '/var/www/html/apps', 'url' \=> '/apps', 'writable' \=> false, ), 1 \=> array ( 'path' \=> '/var/www/html/apps-extra', 'url' \=> '/apps-extra', 'writable' \=> false, ), ), Finally, clone the app to which you would like to contribute inside the apps-extra folder. For example: > git clone [https://github.com/nextcloud/cookbook.git](https://github.com/nextcloud/cookbook.git) Enable the app[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/intro.html#enable-the-app "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- The app can now be enabled on the Nextcloud apps page. App architecture[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/intro.html#app-architecture "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- The following directories have now been created: * **appinfo/**: Contains app metadata and configuration * **css/**: Contains the CSS * **img/**: Contains icons and images * **js/**: Contains the JavaScript files * **lib/**: Contains the PHP class files of your app * **src/**: Contains the source code of your vue.js app * **templates/**: Contains the templates * **tests/**: Contains the tests ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # App metadata — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/latest/developer_manual/app_development/index.html) * App metadata * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/info.rst) * * * App metadata[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/info.html#app-metadata "Link to this heading") ========================================================================================================================================= The `appinfo/info.xml` contains metadata about the app. A detailed documentation can be found at the [app store documentation](https://nextcloudappstore.readthedocs.io/en/latest/developer.html#info-xml) . The info.xml is validated using an XML Schema which can be accessed [online](https://apps.nextcloud.com/schema/apps/info.xsd) . A minimum valid **info.xml** would look like this: appinfo/info.xml[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/info.html#id2 "Link to this code") news News An RSS/Atom feed reader An RSS/Atom feed reader 8.8.2 AGPL-3.0-or-later Bernhard Posselt multimedia https://github.com/nextcloud/news/issues A full blown example would look like this (needs to be utf-8 encoded): appinfo/info.xml[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/info.html#id3 "Link to this code") news Nachrichten News An RSS/Atom feed reader # Description\\nAn RSS/Atom feed reader 8.8.2 AGPL-3.0-or-later Bernhard Posselt Alessandro Cosentino Jan-Christoph Borchardt https://github.com/nextcloud/news/wiki#user-documentation https://github.com/nextcloud/news#readme https://github.com/nextcloud/news/wiki#developer-documentation multimedia tools https://github.com/nextcloud/news https://your.forum.com https://github.com/nextcloud/news/issues https://github.com/nextcloud/news https://example.com/1.png https://example.com/2.jpg pgsql sqlite mysql grep ls libxml curl SimpleXML iconv OCA\\DAV\\CardDAV\\Sync\\SyncJob OCA\\DAV\\Migration\\Classification OCA\\DAV\\Migration\\Classification OCA\\DAV\\Migration\\GenerateBirthdays OCA\\DAV\\Migration\\GenerateBirthdays OCA\\DAV\\Migration\\GenerateBirthdays OCA\\AuthF\\TwoFactor\\Provider A\\Php\\Class OCA\\Theming\\Settings\\Admin OCA\\Theming\\Settings\\Section OCA\\Files\\Activity\\Settings\\FavoriteAction OCA\\Files\\Activity\\Settings\\FileChanged OCA\\Files\\Activity\\Settings\\FileCreated OCA\\Files\\Activity\\Settings\\FileDeleted OCA\\Files\\Activity\\Settings\\FileFavorite OCA\\Files\\Activity\\Settings\\FileRestored OCA\\Files\\Activity\\Filter\\FileChanges OCA\\Files\\Activity\\Filter\\Favorites OCA\\Files\\Activity\\FavoriteProvider OCA\\Files\\Activity\\Provider files Files files.view.index 0 app.svg link OCA\\Circles\\Collaboration\\v1\\CollaboratorSearchPlugin The following tags are validated and used in the following way: id * required * must contain only lowercase ASCII characters and underscore * must match the first folder in the archive * will be used to identify the app name * required * must occur at least once with **lang=”en”** or no lang attribute * can be translated by using multiple elements with different **lang** attribute values, language code needs to be set **lang** attribute * will be rendered on the app detail page summary * optional * if not provided the description element’s text will be used * must occur at least once with **lang=”en”** or no lang attribute * can be translated by using multiple elements with different **lang** attribute values, language code needs to be set **lang** attribute * will be rendered on the app list page as short description description * required * must occur at least once with **lang=”en”** or no lang attribute * can contain Markdown * can be translated by using multiple elements with different **lang** attribute values, language code needs to be set **lang** attribute * will be rendered on the app detail page version * required * must be a [semantic version](http://semver.org/) without build metadata, e.g. 9.0.1 or 9.1.0-alpha.1 * [more info on app versioning](https://docs.nextcloud.com/server/latest/developer_manual/app_publishing_maintenance/release_process.html#app-versioning) licence * required * can occur multiple times with different licenses * must contain one of the following licenses (for apps targeting v31 or higher, see the [SPDX License List](https://spdx.org/licenses/) for details): > * **AGPL-3.0-only** > > * **AGPL-3.0-or-later** > > * **Apache-2.0** > > * **GPL-3.0-only** > > * **GPL-3.0-or-later** > > * **MIT** > > * **MPL-2.0** > * (deprecated, for apps targeting v30 or lower) the following shorthand aliases are also used: > * **agpl** (AGPL-3.0) > > * **apache** (Apache-2.0) > > * **gpl3** (GPL-3.0) > > * **mit** (MIT) > > * **mpl** (MPL-2.0) > author * required * can occur multiple times with different authors * can contain a **mail** attribute which must be an email * can contain a **homepage** which must be a URL * will not (yet) be rendered on the App Store * will be provided through the REST API documentation/user * optional * must contain a URL to the user documentation * will be rendered on the app detail page documentation/admin * optional * must contain a URL to the admin documentation * will be rendered on the app detail page documentation/developer * optional * must contain a URL to the developer documentation * will be rendered on the app detail page category * optional * if not provided the category **tools** will be used * must contain one of the following values: > * **customization** > > * **files** > > * **games** > > * **integration** > > * **monitoring** > > * **multimedia** > > * **office** > > * **organization** > > * **security** > > * **social** > > * **tools** > * old categories are migrated: > * **auth** will be converted to **security** > * can occur more than once with different categories website * optional * must contain a URL to the project’s homepage * will be rendered on the app detail page discussion * optional * must contain a URL to the project’s discussion page/forum * will be rendered on the app detail page as the “ask question or discuss” button * if absent, it will default to our forum at [https://help.nextcloud.com/](https://help.nextcloud.com/) bugs * required * must contain a URL to the project’s bug tracker * will be rendered on the app detail page repository * optional * must contain a URL to the project’s repository * can contain a **type** attribute, **git**, **mercurial**, **subversion** and **bzr** are allowed values, defaults to **git** * currently not used screenshot * optional * must contain an HTTPS URL to an image * can contain a **small-thumbnail** attribute which must contain an https url to an image. This image will be used as small preview (e.g. on the app list overview). Keep it small so it renders fast * will be rendered on the app list and detail page in the given order dependencies/php * optional * can contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) * can contain a **min-int-size** attribute, 32 or 64 are allowed as valid values * will be rendered on the app releases page dependencies/database * optional * must contain the database name as text, **sqlite**, **pgsql** and **mysql** are allowed as valid values * can occur multiple times with different databases * can contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) * will be rendered on the app releases page dependencies/command * optional * must contain a linux command as text value * can occur multiple times with different commands * will be rendered on the app releases page dependencies/lib * optional * will be rendered on the app releases page * must contain a required php extension * can occur multiple times with different php extensions * can contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) dependencies/nextcloud * required * must contain a **min-version** attribute (maximum 3 digits separated by dots) * must contain a **max-version** attribute (maximum 3 digits separated by dots) Note Dependencies dependencies/php, dependencies/database and dependencies/lib are checked at installation time (not on update time), hence applications need to stick to the dependencies supported by a major version of Nextcloud the moment an app releases support for that version, i.e. app needs to support the same PHP version-range the supported Nextcloud version supports. background-jobs/job * optional * must contain a php class which is run as background jobs * will not be used, only validated repair-steps/pre-migration/step * optional * must contain a php class which is run before executing database migrations * will not be used, only validated repair-steps/post-migration/step * optional * must contain a php class which is run after executing database migrations * will not be used, only validated repair-steps/live-migration/step * optional * must contain a php class which is run after executing post-migration jobs * will not be used, only validated repair-steps/install/step * optional * must contain a php class which is run after installing the app * will not be used, only validated repair-steps/uninstall/step * optional * must contain a php class which is run after uninstalling the app * will not be used, only validated two-factor-providers/provider * optional * must contain a php class which is registered as two factor auth provider * will not be used, only validated commands/command * optional * must contain a php class which is registered as occ command * will not be used, only validated activity/settings/setting * optional * must contain a php class which implements OCPActivityISetting and is used to add additional settings ui elements to the activity app activity/filters/filter * optional * must contain a php class which implements OCPActivityIFilter and is used to add additional filters to the activity app activity/providers/provider * optional * must contain a php class which implements OCPActivityIProvider and is used to react to events from the activity app settings/admin * optional * must contain a php class which implements OCPSettingsISettings and returns the form to render for the global settings area settings/admin-section * optional * must contain a php class which implements OCPSettingsISection and returns data to render navigation entries in the global settings area navigations * optional * must contain at least one navigation element navigations/navigation * required * must contain a name and route element * denotes a navigation entry * role denotes the visibility, all means everyone can see it, admin means only an admin can see the navigation entry, defaults to all navigations/navigation/id * optional * the app id * you can also create entries for other apps by setting an id other than your app one’s navigations/navigation/name * required * will be displayed below the navigation entry icon * will be translated by the default translation tools navigations/navigation/route * required * name of the route that will be used to generate the link navigations/navigation/icon * optional * name of the icon which is looked up in the app’s **img/** folder * defaults to app.svg navigations/navigation/order * optional * used to sort the navigation entries * a higher order number means that the entry will be ordered further to the bottom navigations/navigation/type * optional * can be either link or settings * link means that the entry is added to the default app menu * settings means that the entry is added to the right-side menu which also contains the personal, admin, users, help and logout entry collaboration * optional * can contain plugins for collaboration search (e.g. supplying share dialog) collaboration/plugins * optional * must contain at least one plugin collaboration/plugins/plugin * required * the PHP class name of the plugin * must contain **type** attribute (currently only _collaboration-search_). The class must implement OCPCollaborationCollaboratorsISearchPlugin. * must contain **share-type** attribute, according to the specific OCPShare constants The following character maximum lengths are enforced: * All description Strings are database text fields and therefore not limited in size * All other Strings have a maximum of 256 characters The following elements are either deprecated or for internal use only and will fail the validation if present: * **standalone** * **default\_enable** * **shipped** * **public** * **remote** * **requiremin** * **requiremax** Changelog[](https://docs.nextcloud.com/server/latest/developer_manual/app_development/info.html#changelog "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------- Apps can provide a changelog. This should be written in the [keep a changelog](https://keepachangelog.com/) . If the apps provide a `CHANGELOG.md` file in the project root, this file will be used to show changes for the released version in the app store and for administrators in the app settings. Moreover, since Nextcloud 29, if the `updatenotification` app is enabled, apps can also provide a changelog for the users. The app will notify users about after the app update if either a `CHANGELOG.language.md` (where `language` is the language code of that user) or a fallback `CHANGELOG.en.md` is available. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Desktop Clients — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * Desktop Clients * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/desktop/index.rst) * * * Desktop Clients[](https://docs.nextcloud.com/server/latest/developer_manual/desktop/index.html#desktop-clients "Link to this heading") ======================================================================================================================================== Available for Windows, macOS, and various Linux distributions, the Nextcloud Desktop Sync client enables you to: * Specify one or more directories on your computer that you want to synchronize to the Nextcloud server. * Always have the latest files synchronized, wherever they are located. This documentation is targeted for developers to build the client on their own. * [Building the Client](https://docs.nextcloud.com/server/latest/developer_manual/desktop/building.html) You can find additional information here: * [User manual](https://docs.nextcloud.com/server/latest/user_manual/en/desktop/index.html) * [Admin manual](https://docs.nextcloud.com/server/latest/admin_manual/desktop/index.html) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Front-end — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Front-end * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/front-end/index.rst) * * * Front-end[](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/index.html#front-end "Link to this heading") ===================================================================================================================================== * [Templates](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/templates.html) * [Including templates](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/templates.html#including-templates) * [Including CSS and JavaScript](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/templates.html#including-css-and-javascript) * [Including images](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/templates.html#including-images) * [JavaScript](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/js.html) * [Sending the CSRF token](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/js.html#sending-the-csrf-token) * [Generating URLs](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/js.html#generating-urls) * [Extending core parts](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/js.html#extending-core-parts) * [Loading initial state](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/js.html#loading-initial-state) * [Keyboard shortcuts](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/js.html#keyboard-shortcuts) * [CSS](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/css.html) * [Theming support](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/theming.html) * [CSS variables](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/theming.html#css-variables) * [JavaScript](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/theming.html#javascript) * [Icons](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/theming.html#icons) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Storage and database — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Storage and database * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/storage/index.rst) * * * Storage and database[](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/index.html#storage-and-database "Link to this heading") ========================================================================================================================================================= * [Migrations](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/migrations.html) * [1\. Migration 1: Schema change](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/migrations.html#migration-1-schema-change) * [2\. Migration 1: Post schema change](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/migrations.html#migration-1-post-schema-change) * [3\. Migration 2: Schema change](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/migrations.html#migration-2-schema-change) * [Construction of migration classes](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/migrations.html#construction-of-migration-classes) * [Migrations and Metadata](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/migrations.html#migrations-and-metadata) * [Console commands](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/migrations.html#console-commands) * [Adding indices](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/migrations.html#adding-indices) * [Replacing indices](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/migrations.html#replacing-indices) * [Database access](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/database.html) * [Transactions](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/database.html#transactions) * [Mappers](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/database.html#mappers) * [Entities](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/database.html#entities) * [Table management tips](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/database.html#table-management-tips) * [Querying the database provider](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/database.html#querying-the-database-provider) * [Supporting more databases](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/database.html#supporting-more-databases) * [Configuration](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/configuration.html) * [System values](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/configuration.html#system-values) * [App values](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/configuration.html#app-values) * [User values](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/configuration.html#user-values) * [Nextcloud filesystem API](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/filesystem.html) * [Node API](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/filesystem.html#node-api) * [AppData](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/appdata.html) * [The simple filesystem](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/appdata.html#the-simple-filesystem) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Middlewares — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Middlewares * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/middlewares.rst) * * * Middlewares[](https://docs.nextcloud.com/server/latest/developer_manual/basics/middlewares.html#middlewares "Link to this heading") ===================================================================================================================================== Middleware is logic that is run before and after each request and is modeled after [Django’s Middleware system](https://docs.djangoproject.com/en/dev/topics/http/middleware/) . It offers the following hooks: * `beforeController`: This is executed before a controller method is being executed. This allows you to plug additional checks or logic before that method, like for instance security checks * `afterException`: This is being run when either the beforeController method or the controller method itself is throwing an exception. The middleware is asked in reverse order to handle the exception and to return a response. If the middleware can’t handle the exception, it throws the exception again * `afterController`: This is being run after a successful controller method call and allows the manipulation of a Response object. The middleware is run in reverse order * `beforeOutput`: This is being run after the response object has been rendered and allows the manipulation of the outputted text. The middleware is run in reverse order ![Middleware flow chart](https://docs.nextcloud.com/server/latest/developer_manual/_images/middleware-flow-horiz.png) To generate your own middleware, simply inherit from the Middleware class and overwrite the methods that should be used. registerMiddleware(CensorMiddleware::class); } public function boot(IBootContext $context): void {} } Global Middlewares[](https://docs.nextcloud.com/server/latest/developer_manual/basics/middlewares.html#global-middlewares "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------- Added in version 26. Registered middleware will only intercept requests of the same app by default. To make a middleware _global_ and trigger for other apps’ middleware, add true as the second argument of the `registerMiddleware` call: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/latest/developer_manual/basics/middlewares.html#id3 "Link to this code") registerMiddleware(MonitoringMiddleware::class, true); } public function boot(IBootContext $context): void {} } Dependency Injection Container Registration[](https://docs.nextcloud.com/server/latest/developer_manual/basics/middlewares.html#dependency-injection-container-registration "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Deprecated since version 20. Middleware can also be added using the **registerMiddleware** method of the container: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/latest/developer_manual/basics/middlewares.html#id4 "Link to this code") getContainer(); // executed in the order that it is registered $container\->registerMiddleware(CensorMiddleware::class); } } Note The order is important! The middleware that is registered first gets run first in the **beforeController** method. For all other hooks, the order is being reversed, meaning: if a middleware is registered first, it gets run last. Parsing annotations[](https://docs.nextcloud.com/server/latest/developer_manual/basics/middlewares.html#parsing-annotations "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it is useful to conditionally execute code before or after a controller method. This can be done by defining custom annotations. An example would be to add a custom authentication method or simply add an additional header to the response. To access the parsed annotations, inject the **ControllerMethodReflector** class: reflector \= $reflector; } /\*\* \* Add custom header if @MyHeader is used \*/ public function afterController($controller, $methodName, Response $response): Response { if($this\->reflector\->hasAnnotation('MyHeader')) { $response\->addHeader('My-Header', 3); } return $response; } } Note An annotation always starts with an uppercase letter ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Routing — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Routing * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/routing.rst) * * * Routing[](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#routing "Link to this heading") ========================================================================================================================= Routes map a URL and a method to a controller method. Routes are defined inside `appinfo/routes.php` by returning them as an array: \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \],\ \]; Added in version 29: You can also use attributes on the Controller method to define routes. They support all the same parameters (except for `name` which is not needed). `FrontpageRoute` has to be used for routes that were in the `routes` section and `ApiRoute` has to be used for routes that were in the `ocs` section. #\[FrontpageRoute(verb: 'GET', url: '/')\] The route array contains the following parts: * **url**: The URL that is matched after _/index.php/apps/myapp_ * **name**: The controller and the method to call; _page#index_ is being mapped to _PageController->index()_, _articles\_api#drop\_latest_ would be mapped to _ArticlesApiController->dropLatest()_. The controller in the example above would be stored in `lib/Controller/PageController.php`. This parameter is not needed for the attributes. * **verb** (Optional, defaults to GET): The HTTP method that should be matched, (e.g. GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH) * **requirements** (Optional): lets you match and extract URLs that have slashes in them (see [Matching subURLs](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#matching-suburls) ) * **postfix** (Optional): lets you define a route id postfix. Since each route name will be transformed to a route id (**page#method** -> **myapp.page.method**) and the route id can only exist once you can use the postfix option to alter the route id creation by adding a string to the route id, e.g., **‘name’ => ‘page#method’, ‘postfix’ => ‘test’** will yield the route id **myapp.page.methodtest**. This makes it possible to add more than one route/URL for a controller method * **defaults** (Optional): If this setting is given, a default value will be assumed for each URL parameter which is not present. The default values are passed in as a key => value pair array OCS routes[](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#ocs-routes "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------- Registering of OCS routes requires to use a [corresponding controller](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#ocscontroller) . Additionally, the route must be configured to be an OCS route in the router. To do so, you use the `ocs` key in the `routes.php` file instead of the key `routes`. The rest of the structure is the same. You can of course have both index.php and OCS routes. \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \],\ 'ocs' \=> \[\ \['name' \=> 'api#data', 'url' \=> '/v1/data', 'verb' \=> 'GET'\],\ \],\ \]; The prefix for OCS routes is `/ocs/v2.php/apps//`. So, the configured URL for the OCS endpoint in the example would be `/ocs/v2.php/apps//v1/data`. Added in version 29: Similar to `FrontpageRoute`, you can use `ApiRoute` as attribute to mark a route in the controller directly. This is equivalent to the configuration in the `routes.php` above. // In class ApiController that is a OCSController #\[ApiRoute(verb: 'GET', url: '/v1/data')\] function data() { /\* ... \*/ } Extracting values from the URL[](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#extracting-values-from-the-url "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- It is possible to extract values from the URL to allow RESTful URL design. To extract a value, you have to wrap it inside curly braces: 'author#show', 'url' \=> '/authors/{id}', 'verb' \=> 'GET'\], // controller/authorcontroller.php class AuthorController { public function show(string $id): Response { // $id is '3' } } The identifier used inside the route is being passed into controller method by reflecting the method parameters. So basically if you want to get the value **{id}** in your method, you need to add **$id** to your method parameters. Matching subURLs[](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#matching-suburls "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it is needed to match more than one URL fragment. An example would be to match a request for all URLs that start with **OPTIONS /index.php/apps/myapp/api**. To do this, use the **requirements** parameter in your route which is an array containing pairs of **‘key’ => ‘regex’**: 'author\_api#cors', 'url' \=> '/api/{path}', 'verb' \=> 'OPTIONS', 'requirements' \=> array('path' \=> '.+')), // controller/authorapicontroller.php class AuthorApiController { public function cors(string $path): Response { // $path will be 'my/route' } } Default values for subURL[](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#default-values-for-suburl "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Apart from matching requirements, a subURL may also have a default value. Say you want to support pagination (a ‘page’ parameter) for your **/posts** subURL that displays posts entries list. You may set a default value for the ‘page’ parameter, that will be used if not already set in the URL. Use the **defaults** parameter in your route which is an array containing pairs of **‘urlparameter’ => ‘defaultvalue’**: 'post#index', 'url' \=> '/post/{page}', 'verb' \=> 'GET', 'defaults' \=> array('page' \=> 1) // this allows same URL as /index.php/myapp/post/1 ), // controller/postcontroller.php class PostController { public function index(int $page \= 1): Response { // $page will be 1 } } Registering resources[](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#registering-resources "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- When dealing with resources, writing routes can become quite repetitive since most of the time routes for the following tasks are needed: * Get all entries * Get one entry by id * Create an entry * Update an entry * Delete an entry To prevent repetition, it’s possible to define resources. The following routes: \[\ \['name' \=> 'author#index', 'url' \=> '/authors', 'verb' \=> 'GET'\],\ \['name' \=> 'author#show', 'url' \=> '/authors/{id}', 'verb' \=> 'GET'\],\ \['name' \=> 'author#create', 'url' \=> '/authors', 'verb' \=> 'POST'\],\ \['name' \=> 'author#update', 'url' \=> '/authors/{id}', 'verb' \=> 'PUT'\],\ \['name' \=> 'author#destroy', 'url' \=> '/authors/{id}', 'verb' \=> 'DELETE'\],\ // your other routes here\ \],\ \]; can be abbreviated by using the **resources** key: \[\ 'author' \=> \['url' \=> '/authors'\],\ \],\ 'routes' \=> \[\ // your other routes here\ \],\ \]; Using the URLGenerator[](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#using-the-urlgenerator "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it is useful to turn a route into a URL to make the code independent from the URL design or to generate a URL for an image in **img/**. Inside the PageController the URL generator can be injected by adding it to the constructor, which will allow to use it to generate a URL for a redirect. For more details on that see the [Dependency injection](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#id2) reference. urlGenerator \= $urlGenerator; } /\*\* \* Redirects to /apps/news/myapp/authors/3 \*/ public function redirect(): RedirectResponse { // route name: author\_api#do\_something // route url: /apps/news/myapp/authors/{id} // # needs to be replaced with a . due to limitations and prefixed // with your app id $route \= 'myapp.author\_api.do\_something'; $parameters \= \['id' \=> 3\]; $url \= $this\->urlGenerator\->linkToRoute($route, $parameters); return new RedirectResponse($url); } } URLGenerator is case sensitive, so **appName** must match **exactly** the name you use in [configuration](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/configuration.html) . If you use a CamelCase name as _myCamelCaseApp_, logger \= $logger; $this\->appName \= $appName; } public function log($message) { $this\->logger\->error($message, \['extra\_context' \=> 'my extra context'\]); } } In cases where you can not [inject](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#id2) a logger into a class, you can use the `\OCP\Log\logger` function to acquire a logger instance. As a first argument you need to pass the app ID. warning('look, no dependency injection'); Admin audit logging[](https://docs.nextcloud.com/server/latest/developer_manual/basics/logging.html#admin-audit-logging "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------- If you want to log things less for system administration but for compliance reasons, e.g. who accessed which file, who changed the password of an item or made it public, the [admin audit log](https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/logging_configuration.html#admin-audit-log) is the correct place. You can easily add a log by simply emitting an `OCP\Log\Audit\CriticalActionPerformedEvent` event: 'My App ID'\] ); $dispatcher\->dispatchTyped($event); ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Basic concepts — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * Basic concepts * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/index.rst) * * * Basic concepts[](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html#basic-concepts "Link to this heading") ===================================================================================================================================== * [Request lifecycle](https://docs.nextcloud.com/server/latest/developer_manual/basics/request_lifecycle.html) * [Front controller](https://docs.nextcloud.com/server/latest/developer_manual/basics/request_lifecycle.html#front-controller) * [Routing](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html) * [OCS routes](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#ocs-routes) * [Extracting values from the URL](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#extracting-values-from-the-url) * [Matching subURLs](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#matching-suburls) * [Default values for subURL](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#default-values-for-suburl) * [Registering resources](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#registering-resources) * [Using the URLGenerator](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html#using-the-urlgenerator) * [Dependency injection](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html) * [Dependency injection](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#id2) * [Controller injection](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#controller-injection) * [Using a container](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#using-a-container) * [How the container works](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#how-the-container-works) * [Use automatic dependency assembly (recommended)](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#use-automatic-dependency-assembly-recommended) * [Which classes should be added](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#which-classes-should-be-added) * [Optional services](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#optional-services) * [Accessing the container from anywhere](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#accessing-the-container-from-anywhere) * [Controllers](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html) * [Connecting a controller and a route](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#connecting-a-controller-and-a-route) * [Getting request parameters](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#getting-request-parameters) * [Responses](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#responses) * [HTML-based Responses](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#html-based-responses) * [Data-based responses](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#data-based-responses) * [Miscellaneous responses](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#miscellaneous-responses) * [Security considerations](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#security-considerations) * [Middlewares](https://docs.nextcloud.com/server/latest/developer_manual/basics/middlewares.html) * [Global Middlewares](https://docs.nextcloud.com/server/latest/developer_manual/basics/middlewares.html#global-middlewares) * [Dependency Injection Container Registration](https://docs.nextcloud.com/server/latest/developer_manual/basics/middlewares.html#dependency-injection-container-registration) * [Parsing annotations](https://docs.nextcloud.com/server/latest/developer_manual/basics/middlewares.html#parsing-annotations) * [Events](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html) * [Overview](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#overview) * [OCP event dispatcher](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-event-dispatcher) * [Hooks](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#hooks) * [Public emitter](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#public-emitter) * [Front-end](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/index.html) * [Templates](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/templates.html) * [JavaScript](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/js.html) * [CSS](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/css.html) * [Theming support](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/theming.html) * [Translations](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html) * [PHP Backend](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#php-backend) * [PHP Templates](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#php-templates) * [JavaScript / TypeScript / Vue](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#javascript-typescript-vue) * [ExApps (Python)](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#exapps-python) * [Guidelines](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#guidelines) * [Adding translations](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#adding-translations) * [Testing translations](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#testing-translations) * [Background jobs (Cron)](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html) * [Types of background jobs](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#types-of-background-jobs) * [Writing a background job](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#writing-a-background-job) * [Registering a background job](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#registering-a-background-job) * [Caching](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html) * [Types of caches](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#types-of-caches) * [In-memory cache](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#in-memory-cache) * [Local cache](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#local-cache) * [Distributed cache](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#distributed-cache) * [Logging](https://docs.nextcloud.com/server/latest/developer_manual/basics/logging.html) * [Admin audit logging](https://docs.nextcloud.com/server/latest/developer_manual/basics/logging.html#admin-audit-logging) * [Settings](https://docs.nextcloud.com/server/latest/developer_manual/basics/setting.html) * [Storage and database](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/index.html) * [Migrations](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/migrations.html) * [Database access](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/database.html) * [Configuration](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/configuration.html) * [Nextcloud filesystem API](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/filesystem.html) * [AppData](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/appdata.html) * [Public share template](https://docs.nextcloud.com/server/latest/developer_manual/basics/public_share_template.html) * [Testing](https://docs.nextcloud.com/server/latest/developer_manual/basics/testing.html) * [PHP](https://docs.nextcloud.com/server/latest/developer_manual/basics/testing.html#php) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Testing — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Testing * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/testing.rst) * * * Testing[](https://docs.nextcloud.com/server/latest/developer_manual/basics/testing.html#testing "Link to this heading") ========================================================================================================================= All PHP classes can be tested with [PHPUnit](https://phpunit.de/) , JavaScript can be tested by using [Karma](http://karma-runner.github.io/) . PHP[](https://docs.nextcloud.com/server/latest/developer_manual/basics/testing.html#php "Link to this heading") ----------------------------------------------------------------------------------------------------------------- The PHP tests go into the **tests/** directory and PHPUnit can be run with: phpunit tests/ When writing your own tests, please ensure that PHPUnit bootstraps from `tests/bootstrap.php`, to set up various environment variables and autoloader registration correctly. Without this, you will see errors as the Nextcloud autoloader security policy prevents access to the tests/ subdirectory. This can be configured in your `phpunit.xml` file as follows: PHP classes should be tested by accessing them from the container to ensure that the container is wired up properly. Services that should be mocked can be replaced directly in the container. A test for the **AuthorStorage** class in [Nextcloud filesystem API](https://docs.nextcloud.com/server/latest/developer_manual/basics/storage/filesystem.html) : storage \= $storage; } public function getContent($id) { // check if file exists and write to it if possible try { $file \= $this\->storage\->getById($id); if($file instanceof \\OCP\\Files\\File) { return $file\->getContent(); } else { throw new StorageException('Can not read from folder'); } } catch(\\OCP\\Files\\NotFoundException $e) { throw new StorageException('File does not exist'); } } } would look like this: container \= $app\->getContainer(); $this\->storage \= $storage \= $this\->getMockBuilder('\\OCP\\Files\\Folder') \->disableOriginalConstructor() \->getMock(); $this\->container\->registerService('RootStorage', function($c) use ($storage) { return $storage; }); } /\*\* \* @expectedException \\OCA\\MyApp\\Storage\\StorageException \*/ public function testFileNotFound() { $this\->storage\->expects($this\->once()) \->method('get') \->with($this\->equalTo(3)) \->will($this\->throwException(new \\OCP\\Files\\NotFoundException())); $this\->container\['AuthorStorage'\]\->getContent(3); } } Make sure to extend the `\Test\TestCase` class with your test and always call the parent methods, when overwriting `setUp()`, `setUpBeforeClass()`, `tearDown()` or `tearDownAfterClass()` method from the TestCase. These methods set up important stuff and clean up the system after the test, so the next test can run without side effects, like remaining files and entries in the file cache, etc. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Caching — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Caching * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/caching.rst) * * * Caching[](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#caching "Link to this heading") ========================================================================================================================= Results of expensive or slow operations can be cached to speed up Nextcloud and its apps. Types of caches[](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#types-of-caches "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------- Nextcloud offers in-memory, local and distributed caches. The caching back-end (APCu, Redis, Memcached) is configurable. For single server setups, admins typically only configure one type of cache. Larger installations can have two types of cache. The Nextcloud API lets you pick a cache type. The following table tries to highlight the main advantages and disadvantages of each type. | | In-memory cache | Local cache | Distributed cache | | --- | --- | --- | --- | | **Latency** | Low | Low | High | | **Data scope** | Same process | Application server | Full cluster | | **Expiration** | End of process | TTL reached | TTL reached | For scalability it should be preferred to use local caches. A local cache has to be populated on each application server, but avoids creating a bottleneck of too much traffic on the distributed cache. A distributed cache is most useful for data that _has to be synchronized_ across the full Nextcloud cluster. In-memory cache[](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#in-memory-cache "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------- The `OCP\Cache\CappedMemoryCache` class is an in-memory cache that can be used like an array: lib/Service/PictureService.php[](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#id1 "Link to this code") cache \= new CappedMemoryCache(64); } public function getPicture(string $url): void { if (isset($this\->cache\[$url\])) { return $this\->cache\[$url\]; } // Fetch picture and serialize result into $picture $this\->cache\[$url\] \= $picture; return $picture; } } A cache instance can also be built by the cache factory. This approach allows mocking the injected factory for finer control during [unit testing](https://docs.nextcloud.com/server/latest/developer_manual/basics/testing.html#testing-php) : lib/Service/PictureService.php[](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#id2 "Link to this code") cacheFactory \= $cacheFactory; } public function getPicture(string $url): void { // Initialize the cache. The instance has to be remembered because // each call to \`createInMemory\` returns a fresh, empty cache. if ($this\->cache \=== null) { $this\->cache \= $this\->cacheFactory\->createInMemory(64); } if (isset($this\->cache\[$url\])) { return $this\->cache\[$url\]; } // Fetch picture and serialize result into $picture $this\->cache\[$url\] \= $picture; return $picture; } } Local cache[](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#local-cache "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------- A local cache instance can be acquired through the `\OCP\ICacheFactory` service. The factory can be injected: lib/Service/PictureService.php[](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#id3 "Link to this code") cacheFactory \= $cacheFactory; } public function getPicture(string $url): void { $cache \= $this\->cacheFactory\->createLocal('my-app-pictures'); $cachedPicture \= $cache\->get($url); if ($cachedPicture !== null) { return $cachedPicture; } // Fetch picture and serialize result into $picture $cache\->set($url, $picture, 6 \* 3600); // Cache result for 6h return $picture; } } Distributed cache[](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#distributed-cache "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------- A distributed cache instance can be acquired through the `\OCP\ICacheFactory` service. The factory can be injected: lib/Service/PictureService.php[](https://docs.nextcloud.com/server/latest/developer_manual/basics/caching.html#id4 "Link to this code") cacheFactory \= $cacheFactory; } public function getPicture(string $url): void { $cache \= $this\->cacheFactory\->createDistributed('my-app-pictures'); $cachedPicture \= $cache\->get($url); if ($cachedPicture !== null) { return $cachedPicture; } // Fetch picture and serialize result into $picture $cache\->set($url, $picture, 6 \* 3600); // Cache result for 6h return $picture; } } ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Public share template — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Public share template * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/public_share_template.rst) * * * Public share template[](https://docs.nextcloud.com/server/latest/developer_manual/basics/public_share_template.html#public-share-template "Link to this heading") =================================================================================================================================================================== It is possible to override the default public share view. This is possible by implementing the `IPublicShareTemplateProvider` interface. registerPublicShareTemplateProvider(MyPublicShareTemplateProvider::class); } } getNode(); return ...; // Whether your provider should be used or not. } public function renderPage(IShare $share, string $token, string $path): TemplateResponse { $shareNode \= $share\->getNode(); $owner \= $this\->userManager\->get($share\->getShareOwner()); $this\->initialState\->provideInitialState('fileId', $shareNode\->getId()); ...; // More initial state that you might need in your view. // OpenGraph Support: http://ogp.me/ Util::addHeader('meta', \['property' \=> "og:title", 'content' \=> $this\->l10n\->t("Encrypted share")\]); Util::addHeader('meta', \['property' \=> "og:description", 'content' \=> $this\->defaults\->getName() . ($this\->defaults\->getSlogan() !== '' ? ' - ' . $this\->defaults\->getSlogan() : '')\]); Util::addHeader('meta', \['property' \=> "og:site\_name", 'content' \=> $this\->defaults\->getName()\]); Util::addHeader('meta', \['property' \=> "og:url", 'content' \=> $this\->urlGenerator\->linkToRouteAbsolute('files\_sharing.sharecontroller.showShare', \['token' \=> $token\])\]); Util::addHeader('meta', \['property' \=> "og:type", 'content' \=> "object"\]); $csp\->addAllowedFrameDomain('\\'self\\''); $response\->setContentSecurityPolicy($csp); $response \= new PublicTemplateResponse(Application::APP\_ID, 'myCustomTemplateFileName', \[\]); $response\->setHeaderTitle($this\->l10n\->t("My custom title")); $csp \= new ContentSecurityPolicy(); return $response; } } ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Background jobs (Cron) — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Background jobs (Cron) * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/backgroundjobs.rst) * * * Background jobs (Cron)[](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#background-jobs-cron "Link to this heading") ============================================================================================================================================================ Often there is a need to run background jobs. For example there are Background jobs in Nextcloud that send out the activity emails. Or expire the trashbin. Types of background jobs[](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#types-of-background-jobs "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ Nextcloud by default offers you two types of background jobs. The `\OCP\BackgroundJob\QueuedJob` and `\OCP\BackgroundJob\TimedJob`. The `QueuedJob` is for one time jobs. This can for example be triggered by inserting a job because an event happened. The `TimedJob` has a method `setInterval` where you can set the time minimum time in seconds between the jobs (from the constructor). This is useful in case you want to have a job that is run at most once a day for example. Of course you can customize this all to your liking by just extending `\OCP\BackgroundJob\Job` Writing a background job[](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#writing-a-background-job "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ Writing a background job is rather straight forward. You write a class and extend your job class of choice. myService \= $service; // Run once an hour $this\->setInterval(3600); } protected function run($arguments) { $this\->myService\->doCron($arguments\['uid'\]); } } As you can see our dependency injection also works just fine for background jobs. The ITimeFactory always needs to be passed to the parent constructor. Since it is required to be set. In this case it is a background job that runs every hour. And we take the `uid` argument to pass on to the service to run the background job. The `run` function is the main thing you need to implement and where all the logic happens. ### Heavy load and time insensitive[](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#heavy-load-and-time-insensitive "Link to this heading") When the background job is a `\OCP\BackgroundJob\TimedJob` and can impact the performance of the instance and is not time sensitive, e.g. clearing old data, running training of AI models or similar things, consider flagging it as time insensitive in the constructor. setInterval(24 \* 3600); // Delay until low-load time $this\->setTimeSensitivity(\\OCP\\BackgroundJob\\IJob::TIME\_INSENSITIVE); This allows the Nextcloud to delay the job until a given nightly time window so the users are not that impacted by the heavy load of the background job. ### Configuring parallelism[](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#configuring-parallelism "Link to this heading") Added in version 27. With resource-heavy background jobs that run for longer than a few minutes, be they `QueuedJob` and `TimedJob` instances, you may want to restrict parallelism to prevent multiple such jobs from clogging up the server’s resources. You can do this with the `setAllowParallelRuns` method of `OCP\BackgroundJob\Job` (`QueuedJob` and `TimedJob` both inherit from this class, so they also have this available). setAllowParallelRuns(false); Registering a background job[](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#registering-a-background-job "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Now that you have written your background job there is of course the small matter of how to make sure the system actually runs your job. In order to do this your job needs to be registered. ### info.xml[](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#info-xml "Link to this heading") You can register your jobs in your info.xml by adding; OCA\\MyApp\\Cron\\SomeTask This will on install/update of the application add the job `OCA\MyApp\Cron\SomeTask`. Of course in this case the arguments passed to your `run` function is just an empty array. ### Registering manually[](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#registering-manually "Link to this heading") In case you want more fine grained control about when a background job is inserted and you want to pass arguments to it you need to manually register your background jobs. You do this by using `\OCP\BackgroundJob\IJobList`. There you can add a job or remove a job. For example you could add or remove a certain job based on some controller: jobList \= $jobList; } public function addJob(string $uid) { $this\->jobList\->add(SomeTask::class, \['uid' \=> $uid\]); } public function removeJob(string $uid) { $this\->jobList\->remove(SomeTask::class, \['uid' \=> $uid\]); } } This provides more fine grained control and you can pass arguments to your background jobs easily. ### Scheduling[](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#scheduling "Link to this heading") A background job can be scheduled to run after a specific time and date. This avoids maintaining a time check inside a background job. Beware that the reliability of the execution time is limited. Systems that do not use system cron may have no active users and therefore no reliable cron trigger at the target time. System cron can also not guarantee that the job is picked up right away if the background job queue is full. The only guarantee you get is that the job is not picked up earlier than the specified time. lib/Service/ShareService.php[](https://docs.nextcloud.com/server/latest/developer_manual/basics/backgroundjobs.html#id1 "Link to this code") jobList \= $jobList; } public function shareWithUser(string $uid, int $expiration) { // create an expiring share $this\->jobList\->scheduleAfter( RevokeShare::class, \['id' \=> $shareId\], $expiration, ); } } ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Translations — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Translations * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/translations.rst) * * * Translations[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#translations "Link to this heading") ======================================================================================================================================== Nextcloud provides mechanisms for internationalization (make an application translatable) and localization (add translations for specific languages). This section provides detailed instructions for both aspects. In order to make your app translatable (internationalization), you should use Nextcloud’s methods for translating strings. They are available for both the server-side (PHP, Templates) as well as for the client-side (JavaScript). PHP Backend[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#php-backend "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------- If localized strings are used in the backend code, simply inject the `\OCP\IL10N` class into your service via type hinting it in the constructor. You will automatically get the language object containing the translations of your app: l\->getLanguageCode(); } public sayHello() { // Simple string return $this\->l\->t('Hello'); } public function getAuthorName($name) { // String using a parameter return $this\->l\->t('Getting author %1$s', \[$name\]); } public function getAuthors($count, $city) { // Translation with plural return $this\->l\->n( '%n author is currently in the city %1$s', // singular string '%n authors are currently in the city %1$s', // plural string $count, // number to decide which plural to use \[$city\] // further parameters are possible ); } } ### Language of other users[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#language-of-other-users "Link to this heading") If you need to get the language of another user, e.g. to send them an email or inside a background job, there are also the `force_language` and `default_language` configuration options to consider. To make this easier, the `OCP\L10N\IFactory` class comes with a `getUserLanguage` method: l10nFactory\->getUserLanguage($user); $l \= $this\->l10nFactory\->get('myapp', $lang); // … } PHP Templates[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#php-templates "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------ In every template the global variable `$l` can be used to translate the strings using its methods `t()` and `n()`: // Simple text string t('Hide')); ?> // Text with a placeholder
    t('Show files of %1$s', \[$user\])); ?>
    // Date string l('date', time())); ?> JavaScript / TypeScript / Vue[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#javascript-typescript-vue "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- There are global functions `t()` and `n()` available for translating strings in javascript code. If your app is build, you can import the translation functions from the [@nextcloud/l10n package](https://github.com/nextcloud-libraries/nextcloud-l10n) . They differ a bit in terms of usage compared to php: * First argument is the appId e.g. `'myapp'` * Placeholders (apart from the count in plurals) use single-mustache brackets with meaning-full descriptors. * The parameter list is an object with the descriptors as key. t('myapp', 'Hello World!'); t('myapp', '{name} is available. Get {linkstart}more information{linkend}', {name: 'Nextcloud 16', linkstart: '
    ', linkend: ''}); n('myapp', 'Import %n calendar into {collection}', 'Import %n calendars into {collection}', selectionLength, {collection: 'Nextcloud'}); ExApps (Python)[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#exapps-python "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------- For ExApps, Python is currently only supported for automated Transifex translations. Alongside the usual `l10n/*.json` and `l10n/*.js` files, translation source files located in `translationfiles//*.po` are also included in the Transifex sync. These `.po` files can be compiled into `.mo` files, which are typically used by the ExApp backend for runtime translations. For more details, see [Translations](https://docs.nextcloud.com/server/latest/developer_manual/exapp_development/tech_details/Translations.html#ex-app-translations-page) . Guidelines[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#guidelines "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------ Please also look through the following hints to improve your strings and make them better translatable by the community and therefore improving the experience for non-english users. ### Dos and Don’ts[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#dos-and-don-ts "Link to this heading") | Bad | Good | Description | | --- | --- | --- | | `´` or `’` | `'` | Use ascii single quote | | `Loading...` | `Loading …` | Use **Unicode triple-dot** character.

    Add a **non-breaking space** before the triple-dot when trimming a sentence instead of a word. | | `Loading …`

    (a general space `U+0020`) | `Loading …`

    (a non-breaking space `U+00A0`) | Only use a **non-breaking space** before the triple-dot (`U+00A0`). | | Don’t | Do not | Using the spelled out version is easier to understand and makes translating easier. | | Won’t | Will not | Using the spelled out version is easier to understand and makes translating easier. | | Can not | Cannot | Using the combined version is easier to understand and makes translating easier. | | id | ID | Full uppercase for shortcutting “identifier” | | Users | Accounts / People | Use **accounts** when you refer to a profile/entity. Use **people** when referring to humans. | | Admin / Administrator | Administration | Refer to administration as a non-human organizational entity

    instead of a single or multiple persons. | | Headline | Headline: | Include colons `:` in the translations as some languages add a space before the colon. | | “ Leading space”

    “Trailing space “ | “No leading space”

    “No trailing space” | Leading or trailing spaces mostly indicate that strings are concatenated.

    For translators it is often helpful to have all the content in a single translation,

    as order and references between words and sentences might get lost otherwise. | | “Error:” $error | “Error: %s” | Instead of concatenating errors or part messages, make them a proper placeholder | ### Correct plurals[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#correct-plurals "Link to this heading") If you use a plural, you **must** also use the `%n` placeholder. The placeholder defines the plural and the word without the number preceding is wrong. If you don’t know/have a number for your translation, e.g. because you don’t know how many items are going to be selected, just use an undefined plural. They exist in every language and have one form. They do not follow the normal plural pattern. PHP Example: // BAD: Plural without count $title \= $l\->n('Import calendar', 'Import calendars', $selectionLength) // BETTER: Plural has count, but disrupting to read and unnecessary information $title \= $l\->n('Import %n calendar', 'Import %n calendars', $selectionLength) // BEST: Simple string with undefined plural not using any number in the string $title \= $l\->t('Import calendars') Opposed to the normal placeholders in javascript, the plural number also uses the `%n` syntax: JS Example: /\* BAD: Plural without count \*/ n('myapp', 'Import calendar', 'Import calendars', selected.length) /\* BETTER: Plural has count, but disrupting to read and unnecessary information \*/ n('myapp', 'Import %n calendar', 'Import %n calendars', selected.length) /\* BEST: Simple string with undefined plural not using any number in the string \*/ t('myapp', 'Import calendars') ### Improving your translations[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#improving-your-translations "Link to this heading") Starting with the following example, improving it step by step: t('Select file from')) . ' '; ?>t('local filesystem'));?>t(' or ')); ?>t('cloud'));?> #### Step 1: String split[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#step-1-string-split "Link to this heading") You shall **never split** sentences and **never concatenate** two translations (e.g. “Enable” and “dark mode” can not be combined to “Enable dark mode”, because languages might have to use different cases)! Translators lose the context and they have no chance to possibly re-arrange words/parts as needed. Translators will translate: * `Select file from` * `local filesystem` * `or` (with leading and trailing whitespace) * `cloud` Translating these individual strings results in `local filesystem` and `cloud` losing case. The two white spaces surrounding `or` will get lost while translating as well. For languages that have a different grammatical order it prevents the translators from reordering the sentence components. So the following code is a bit better, but suffers from another issue: t('Select file from local filesystem or cloud'));?> #### Step 2: HTML Markup[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#step-2-html-markup "Link to this heading") In this case the translators can re-arrange as they like, but have to deal with your markup and can mess it up easily. It is better to **keep the markup out** of your code, so the following translation is even better: t('Select file from %slocal filesystem%s or %scloud%s', \['', '', '', ''\]));?> But there is one last problem with this. #### Step 3: Placeholders[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#step-3-placeholders "Link to this heading") In case the language has to turn things around, your code will still insert the parameters in the given order and they can not re-order them. To prevent this last hurdle simply **use positioned placeholders** like `%1$s`: t('Select file from %1$slocal filesystem%2$s or %3$scloud%4$s', \['', '', '', ''\]));?> This allows translators to have the cloudlink before the browselink in case the language is e.g. right-to-left. ### Provide context hints for translators[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#provide-context-hints-for-translators "Link to this heading") In case some translation strings may be translated wrongly because they have multiple meanings. Especially translations strings that only contain a single word often result in problems. The most famous example in the Nextcloud code base is `Share` which can which can be the verb and action `To share something` or the noun `A share`. The added hints will be shown in the Transifex web-interface: #### PHP[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#php "Link to this heading") #### JavaScript / TypeScript[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#javascript-typescript "Link to this heading") // TRANSLATORS name that is appended to copied files with the same name, will be put in parenthesis and appended with a number if it is the second+ copy var copyNameLocalized \= t('files', 'copy'); #### Vue[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#vue "Link to this heading") This covers vue html templates in vue sfc components. For vue js code, see the javascript section. {{ t('forms', 'Required') }} #### C++ (Qt) / Desktop client[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#c-qt-desktop-client "Link to this heading") //: Example text: "Progress of sync process. Shows the currently synced filename" fileProgressString \= tr("Syncing %1").arg(allFilenames); #### Android[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#android "Link to this heading") Boards #### iOS[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#ios "Link to this heading") /\* The title on the navigation bar of the Scanning screen. \*/ "wescan.scanning.title" \= "Scanning"; Adding translations[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#adding-translations "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------ The steps how to set up translations for an app have been moved to it’s own page in the “App development” chapter: [Translation](https://docs.nextcloud.com/server/latest/developer_manual/app_development/translation.html#translation) Testing translations[](https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#testing-translations "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------- You can use the query parameter `forceLanguage` to force a specific language for a web request (API or frontend). See [Forcing language for a given call](https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-api-overview.html#api-force-language) . ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Dependency injection — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Dependency injection * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/dependency_injection.rst) * * * Dependency injection[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#dependency-injection "Link to this heading") ================================================================================================================================================================ The App Framework assembles the application by using a container based on the software pattern [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) . This makes the code easier to test and thus easier to maintain. If you are unfamiliar with this pattern, watch the following video: * [Google Clean Code Talks](https://www.youtube.com/watch?v=RlfLCWKxHJ0) Dependency injection[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#id2 "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------- Dependency Injection sounds pretty complicated but it just means: Don’t put new dependencies in your constructor or methods but pass them in. So this: use OCP\\IDBConnection; // without dependency injection class AuthorMapper { private IDBConnection $db; public function \_\_construct() { $this\->db \= new Db(); } } would turn into this by using Dependency Injection: use OCP\\IDBConnection; // with dependency injection class AuthorMapper { private IDBConnection $db; public function \_\_construct(IDBConnection $db) { $this\->db \= $db; } } Controller injection[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#controller-injection "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- For controllers it’s possible to also have dependencies injected into methods. lib/Controller/ApiController.php[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#id4 "Link to this code") foo(); } public function bar(BarService $service) { $service\->bar(); } } Using a container[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#using-a-container "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------- Note Please do use automatic dependency injection (see below). For most apps there is no need to register services manually. Passing dependencies into the constructor rather than instantiating them in the constructor has the following drawback: Every line in the source code where **new AuthorMapper** is being used has to be changed, once a new constructor argument is being added to it. The solution for this particular problem is to limit the **new AuthorMapper** to one file, the container. The container contains all the factories for creating these objects and is configured in `lib/AppInfo/Application.php`. Nextcloud 20 and later uses the [PSR-11 standard](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/psr.html#psr11) for the container interface, so working with the container might feel familiar if you’ve worked with other php applications before that also adhere to the convention. To add the app’s classes simply open the `lib/AppInfo/Application.php` and use the **IRegistrationContext::registerService** method: registerService(AuthorController::class, function(ContainerInterface $c): AuthorController { return new AuthorController( $c\->get('appName'), $c\->get(Request::class), $c\->get(AuthorService::class) ); }); /\*\* \* Services \*/ $context\->registerService(AuthorService::class, function(ContainerInterface $c): AuthorService { return new AuthorService( $c\->get(AuthorMapper::class) ); }); /\*\* \* Mappers \*/ $context\->registerService(AuthorMapper::class, function(ContainerInterface $c): AuthorMapper { return new AuthorMapper( $c\->get(IDBConnection::class) ); }); } } How the container works[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#how-the-container-works "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- The container works in the following way: * [A request comes in and is matched against a route](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html) (for the AuthorController in this case) * The matched route queries **AuthorController** service from the container: return new AuthorController( $c->get('appName'), $c->get(Request::class), $c->get(AuthorService::class) ); * The **appName** is queried and returned from the base class * The **Request** is queried and returned from the server container * **AuthorService** is queried: $container->registerService(AuthorService::class, function(ContainerInterface $c): AuthorService { return new AuthorService( $c->get(AuthorMapper::class) ); }); * **AuthorMapper** is queried: $container->registerService(AuthorMappers::class, function(ContainerInterface $c): AuthorMapper { return new AuthorService( $c->get(IDBConnection::class) ); }); * The **database connection** is returned from the server container * Now **AuthorMapper** has all of its dependencies and the object is returned * **AuthorService** gets the **AuthorMapper** and returns the object * **AuthorController** gets the **AuthorService** and finally the controller can be instantiated and the object is returned So basically the container is used as a giant factory to build all the classes that are needed for the application. Because it centralizes all the creation of objects (the **new Class()** lines), it is very easy to add new constructor parameters without breaking existing code: only the **\_\_construct** method and the container line where the **new** is being called need to be changed. Use automatic dependency assembly (recommended)[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#use-automatic-dependency-assembly-recommended "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- In Nextcloud it is possible to build classes and their dependencies without having to explicitly register them on the container, as long as the container can [reflect](https://www.php.net/manual/en/book.reflection.php) the constructor and look up the parameters by their type. This concept is widely known as _auto-wiring_. ### How does auto-wiring work[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#how-does-auto-wiring-work "Link to this heading") Automatic assembly creates new instances of classes just by looking at the class name and its constructor parameters. For each constructor parameter the type or the argument name is used to query the container, e.g.: * **SomeType $type** will use **$container->get(SomeType::class)** * **$variable** will use **$container->get(‘variable’)** If all constructor parameters are resolved, the class will be created, saved as a service and returned. So basically the following is now possible: class \= $class; $this\->appName \= $appName; } } $app \= new \\OCP\\AppFramework\\App('myapp'); $class2 \= $app\->getContainer()\->get(MyTestClass2::class); $class2 instanceof MyTestClass2; // true $class2\->class instanceof MyTestClass; // true $class2\->appName \=== 'myname'; // true $class2 \=== $app\->getContainer()\->get(MyTestClass2::class); // true Note $appName is resolved because the container registered a parameter under the key ‘appName’ which will return the app id. ### How does it affect the request lifecycle[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#how-does-it-affect-the-request-lifecycle "Link to this heading") * A request comes in * All apps’ **routes.php** files are loaded * If a **routes.php** file returns an array, and an **appname/lib/AppInfo/Application.php** exists, include it, create a new instance of **\\OCA\\AppName\\AppInfo\\Application.php** and register the routes on it. That way a container can be used while still benefitting from the new routes behavior * If a **routes.php** file returns an array, but there is no **appname/lib/AppInfo/Application.php**, create a new \\OCP\\AppFramework\\App instance with the app id and register the routes on it * A request is matched for the route, e.g. with the name **page#index** * The appropriate container is being queried for the entry PageController (to keep backwards compatibility) * If the entry does not exist, the container is queried for OCA\\AppName\\Controller\\PageController and if no entry exists, the container tries to create the class by using [reflection](https://www.php.net/manual/en/book.reflection.php) on its constructor parameters ### How does this affect controllers[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#how-does-this-affect-controllers "Link to this heading") The only thing that needs to be done to add a route and a controller method is now: **myapp/appinfo/routes.php** \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \]\]; **myapp/appinfo/lib/Controller/PageController.php** registerParameter('TableName', 'my\_app\_table'); // the interface is called IAuthorMapper and AuthorMapper implements it $context\->registerService(IAuthorMapper::class, function (ContainerInterface $c): AuthorMapper { return $c\->get(AuthorMapper::class); }); // Less verbose alternative $context\->registerServiceAlias(IAuthorMapper::class, AuthorMapper::class); } } ### Predefined core services[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#predefined-core-services "Link to this heading") The following parameter names and type hints can be used to inject core services instead of using **$container->getServer()->getServiceX()** Parameters: * **appName**: The app id * **userId**: The id of the current user * **webRoot**: The path to the Nextcloud installation Aliases: * **AppName**: resolves to `appName` (deprecated) * **Request**: resolves to `\OCP\IRequest` * **ServerContainer**: resolves to `\OCP\IServerContainer` (deprecated) * **UserId**: resolves to `userId` (deprecated) * **WebRoot**: resolves to `webRoot` (deprecated) Types: * `\OCP\IAppConfig` * `\OCP\IAppManager` * `\OCP\IAvatarManager` * `\OCP\Activity\IManager` * `\OCP\ICache` * `\OCP\ICacheFactory` * `\OCP\IConfig` * `\OCP\AppFramework\Utility\IControllerMethodReflector` * `\OCP\Contacts\IManager` * `\OCP\IDateTimeZone` * `\OCP\IDBConnection` * `\OCP\Diagnostics\IEventLogger` * `\OCP\Diagnostics\IQueryLogger` * `\OCP\Files\Config\IMountProviderCollection` * `\OCP\Files\IRootFolder` * `\OCP\IGroupManager` * `\OCP\IL10N` * `\OCP\BackgroundJob\IJobList` * `\OCP\INavigationManager` * `\OCP\IPreview` * `\OCP\IRequest` * `\OCP\AppFramework\Utility\ITimeFactory` * `\OCP\ITagManager` * `\OCP\ITempManager` * `\OCP\Route\IRouter` * `\OCP\ISearch` * `\OCP\Security\ICrypto` * `\OCP\Security\IHasher` * `\OCP\Security\ISecureRandom` * `\OCP\IURLGenerator` * `\OCP\IUserManager` * `\OCP\IUserSession` * `\Psr\Container\ContainerInterface` * `\Psr\Log\LoggerInterface` ### How to enable it[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#how-to-enable-it "Link to this heading") To make use of this new feature, the following things have to be done: * **appinfo/info.xml** requires to provide another field called **namespace** where the namespace of the app is defined. The required namespace is the one which comes after the top level namespace **OCA\\**, e.g.: for **OCA\\MyBeautifulApp\\Some\\OtherClass** the needed namespace would be **MyBeautifulApp** and would be added to the info.xml in the following way: MyBeautifulApp * **appinfo/routes.php**: Instead of creating a new Application class instance, simply return the routes array like: \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \]\]; Note A namespace tag is required because you can not deduce the namespace from the app id Which classes should be added[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#which-classes-should-be-added "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- In general all of the app’s controllers need to be registered inside the container. Then the following question is: What goes into the constructor of the controller? Pass everything into the controller constructor that matches one of the following criteria: * It does I/O (database, write/read to files) * It is a global (e.g. $\_POST, etc. This is in the request class by the way) * The output does not depend on the input variables (also called [impure function](https://en.wikipedia.org/wiki/Pure_function) ), e.g. time, random number generator * It is a service, basically it would make sense to swap it out for a different object What not to inject: * It is pure data and has methods that only act upon it (arrays, data objects) * It is a [pure function](https://en.wikipedia.org/wiki/Pure_function) Optional services[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#optional-services "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------- Added in version 28. If an injected dependency can’t be found or build, an exception is thrown. This can be avoided by using the a nullable type notation for a dependency: namespace OCA\\MyApp\\MyService; use Some\\Service; class MyService { public function \_\_construct(private ?Service $service) { } } If `\Some\Service` exists and can be built, it will be injected. Else `MyService` will receive `null`. Accessing the container from anywhere[](https://docs.nextcloud.com/server/latest/developer_manual/basics/dependency_injection.html#accessing-the-container-from-anywhere "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it can be hard to inject some service inside legacy code, in these cases you can use `OCPServer::get(MyService::class)`. This should only be used as the last resort, as this makes your code more complicated to unit test and is considered an anti-pattern. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Request lifecycle — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Request lifecycle * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/request_lifecycle.rst) * * * Request lifecycle[](https://docs.nextcloud.com/server/latest/developer_manual/basics/request_lifecycle.html#request-lifecycle "Link to this heading") ======================================================================================================================================================= A typical HTTP request consists of the following: * **A URL**: e.g. /index.php/apps/myapp/something * **Request Parameters**: e.g. ?something=true&name=tom * **A Method**: e.g. GET * **Request headers**: e.g. Accept: application/json The following sections will present an overview over how that request is being processed to provide an in depth view over how Nextcloud works. If you are not interested in the internals or don’t want to execute anything before and after your controller, feel free to skip this section and continue directly with defining [your app’s routes](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html) . Front controller[](https://docs.nextcloud.com/server/latest/developer_manual/basics/request_lifecycle.html#front-controller "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- In the beginning, all requests are sent to Nextcloud’s `index.php` which in turn executes `lib/base.php`. This file inspects the HTTP headers, abstracts away differences between different Web servers and initializes the basic classes. Afterwards the basic apps are being loaded in the following order: * Authentication backends * Filesystem * Logging The type of the app is determined by inspecting the app’s [configuration file](https://docs.nextcloud.com/server/latest/developer_manual/app_development/info.html) (`appinfo/info.xml`). Each installed app is being loaded and executed (see [Bootstrap](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html) ). That means that if you want to execute code before a specific app is being run, you can place code in your app’s [Navigation and pre-app configuration](https://docs.nextcloud.com/server/latest/developer_manual/app_development/init.html) file. Afterwards the following steps are performed: * Try to authenticate the user * Load and execute all the remaining apps’ [Navigation and pre-app configuration](https://docs.nextcloud.com/server/latest/developer_manual/app_development/init.html) files * Load and run all the routes in the apps’ `appinfo/routes.php` * Execute the router ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Events — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Events * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/events.rst) * * * Events[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#events "Link to this heading") ====================================================================================================================== Events are used to communicate between different aspects of the Nextcloud eco system. They are used in the Nextcloud server internally, for server-to-apps communication as well as inter-app communication. Overview[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#overview "Link to this heading") -------------------------------------------------------------------------------------------------------------------------- The term “events” is a bit broad in Nextcloud and there are multiple ways of emitting them. * [OCP event dispatcher](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-event-dispatcher) * [Hooks](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#hooks) * [Public Emitter](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#public-emitter) OCP event dispatcher[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-event-dispatcher "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- This mechanism is a versatile and typed approach to events in Nextcloud’s php code. It uses objects rather than just passing primitives or untyped arrays. This should help provide a better developer experience while lowering the risk of unexpected changes in the API that are hard to find after the initial implementation. ### Naming scheme[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#naming-scheme "Link to this heading") The name should reflect the subject and the actions. Suffixing event classes with Event makes it easier to recognize their purpose. For example, if a user is created, a UserCreatedEvent will be emitted. Events are usually emitted _after_ the event has happened. If it’s emitted before, it should be prefixed with Before. Thus BeforeUserCreatedEvent is emitted _before_ the user data is written to the database. Note Although you may choose to name your event classes differently, sticking to the convention will allow Nextcloud developers understand each other’s apps more easily. Note For backwards compatibility with the Symfony class [GenericEvent](https://symfony.com/doc/current/components/event_dispatcher/generic_event.html) , Nextcloud also provides a `\OCP\EventDispatcher\Event` class. With the release of Nextcloud 22 this class has been deprecated. Named and typed event classes should be used instead. ### Writing events[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#writing-events "Link to this heading") As a rule events are dedicated classes extending `\OCP\EventDispatcher\Event`. user \= $user; } public function getUser(): IUser { return $this\->user; } } ### Writing a listener[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#writing-a-listener "Link to this heading") A listener can be a simple callback function (or anything else that is [callable](https://www.php.net/manual/en/language.types.callable.php) , or a dedicated class. #### Listener callbacks[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#listener-callbacks "Link to this heading") You can use simple callback to react on events. They will receive the event object as first and only parameter. You can type-hint the base Event class or the subclass you expect and register for. getContainer()\->query(IEventDispatcher::class); $dispatcher\->addListener(AddEvent::class, function(AddEvent $event) { // ... }); } } Note Type-hinting the actual event class will give you better IDE and static analyzers support. It’s generally safe to assume the dispatcher will not give you any other objects. #### Listener classes[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#listener-classes "Link to this heading") A class that can handle an event will implement the `\OCP\EventDispatcher\IEventListener` interface. Class names should end with Listener. addToCounter(2); } } Note Php parameter type hints are not allowed to be more specific than the type hints on the interface, thus you can’t use AddEvent in the method signature but use an instanceOf instead. In the `Application.php` the event and the listener class are connected. The class is instantiated only when the actual event is fired. getContainer()\->get(IEventDispatcher::class); $dispatcher\->addServiceListener(AddEvent::class, AddTwoListener::class); } } Note The listener is resolved via the DI container, therefore you can add a constructor and type-hint services required for processing the event. ### Available Events[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#available-events "Link to this heading") Here you find an overview of the public events that can be consumed in apps. See their source files for more details. #### `\OCA\DAV\Events\AddressBookCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-addressbookcreatedevent "Link to this heading") Added in version 20. This event is triggered when a user creates a new address-book. #### `\OCA\DAV\Events\AddressBookDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-addressbookdeletedevent "Link to this heading") Added in version 20. This event is triggered when a user deletes an address-book. #### `\OCA\DAV\Events\AddressBookShareUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-addressbookshareupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user shares or unshares an address-book. #### `\OCA\DAV\Events\AddressBookUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-addressbookupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user updates an address-book. #### `\OCA\DAV\Events\CachedCalendarObjectCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-cachedcalendarobjectcreatedevent "Link to this heading") Added in version 20. This event is triggered when a cached calendar object is being created while fetching a calendar-subscription. #### `\OCA\DAV\Events\CachedCalendarObjectDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-cachedcalendarobjectdeletedevent "Link to this heading") Added in version 20. This event is triggered when a cached calendar object is being deleted while fetching a calendar-subscription. #### `\OCA\DAV\Events\CachedCalendarObjectUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-cachedcalendarobjectupdatedevent "Link to this heading") Added in version 20. This event is triggered when a cached calendar object is being updated while fetching a calendar-subscription. #### `\OCA\DAV\Events\CalendarCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-calendarcreatedevent "Link to this heading") Added in version 20. This event is triggered when a user creates a new calendar. #### `\OCA\DAV\Events\CalendarDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-calendardeletedevent "Link to this heading") Added in version 20. This event is triggered when a user deletes a calendar. #### `\OCA\DAV\Events\CalendarObjectCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-calendarobjectcreatedevent "Link to this heading") Added in version 20. This event is triggered when a user creates a calendar-object. #### `\OCA\DAV\Events\CalendarObjectDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-calendarobjectdeletedevent "Link to this heading") Added in version 20. This event is triggered when a user deletes a calendar-object. #### `\OCA\DAV\Events\CalendarObjectUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-calendarobjectupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user updates a calendar-object. #### `\OCA\DAV\Events\CalendarPublishedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-calendarpublishedevent "Link to this heading") Added in version 20. This event is triggered when a user publishes a calendar. #### `\OCA\DAV\Events\CalendarShareUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-calendarshareupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user shares or unshares a calendar. #### `\OCA\DAV\Events\CalendarUnpublishedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-calendarunpublishedevent "Link to this heading") Added in version 20. This event is triggered when a user unpublishes calendar. #### `\OCA\DAV\Events\CalendarUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-calendarupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user updates a calendar. #### `\OCA\DAV\Events\CardCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-cardcreatedevent "Link to this heading") Added in version 20. This event is triggered when a user creates a new card in an address-book. #### `\OCA\DAV\Events\CardDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-carddeletedevent "Link to this heading") Added in version 20. This event is triggered when a user deletes a card in an address-book. #### `\OCA\DAV\Events\CardUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-cardupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user updates a card in an address-book. #### `OCA\DAV\Events\SabrePluginAddEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-sabrepluginaddevent "Link to this heading") Added in version 28. This event is triggered during the setup of the SabreDAV server to allow the registration of additional plugins. #### `\OCA\DAV\Events\SabrePluginAuthInitEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-sabrepluginauthinitevent "Link to this heading") Added in version 20. This event is triggered during the setup of the SabreDAV server to allow the registration of additional authentication backends. #### `\OCA\DAV\Events\SubscriptionCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-subscriptioncreatedevent "Link to this heading") Added in version 20. This event is triggered when a user creates a new calendar-subscription. #### `\OCA\DAV\Events\SubscriptionDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-subscriptiondeletedevent "Link to this heading") Added in version 20. This event is triggered when a user deletes a calendar-subscription. #### `\OCA\DAV\Events\SubscriptionUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-dav-events-subscriptionupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user deletes a calendar-subscription. #### `\OCA\FederatedFileSharing\Events\FederatedShareAddedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-federatedfilesharing-events-federatedshareaddedevent "Link to this heading") Added in version 20. This event is triggered when a federated share is successfully added. #### `\OCA\Files\Event\LoadAdditionalScriptsEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-files-event-loadadditionalscriptsevent "Link to this heading") Added in version 17. This event is triggered when the files app is rendered. It can be used to add additional scripts to the files app. #### `\OCA\Files_Sharing\Event\BeforeTemplateRenderedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-files-sharing-event-beforetemplaterenderedevent "Link to this heading") Added in version 20. Emitted before the rendering step of the public share page happens. The event holds a flag that specifies if it is the authentication page of a public share. #### `\OCA\Files_Trashbin\Events\MoveToTrashEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-files-trashbin-events-movetotrashevent "Link to this heading") Added in version 28. Emitted after a file or folder is moved to the trashbin. #### `\OCA\Settings\Events\BeforeTemplateRenderedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-settings-events-beforetemplaterenderedevent "Link to this heading") Added in version 20. This event is triggered right before the user management template is rendered. #### `\OCA\User_LDAP\Events\GroupBackendRegistered`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-user-ldap-events-groupbackendregistered "Link to this heading") Added in version 20. This event is triggered right after the LDAP group backend is registered. #### `\OCA\User_LDAP\Events\UserBackendRegistered`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-user-ldap-events-userbackendregistered "Link to this heading") Added in version 20. This event is triggered right after the LDAP user backend is registered. #### `\OCA\Viewer\Event\LoadViewer`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#oca-viewer-event-loadviewer "Link to this heading") Added in version 17. This event is triggered whenever the viewer is loaded and extensions should be loaded. #### `OCP\Accounts\UserUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-accounts-userupdatedevent "Link to this heading") Added in version 28. This event is triggered when the account data of a user was updated. #### `OCP\App\Events\AppDisableEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-app-events-appdisableevent "Link to this heading") Added in version 27. This event is triggered when an app is disabled. #### `OCP\App\Events\AppEnableEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-app-events-appenableevent "Link to this heading") Added in version 27. This event is triggered when an app is enabled. #### `OCP\App\Events\AppUpdateEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-app-events-appupdateevent "Link to this heading") Added in version 27. This event is triggered when an app is updated. #### `OCP\App\ManagerEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-app-managerevent "Link to this heading") Added in version 9. Class ManagerEvent #### `OCP\AppFramework\Http\Events\BeforeLoginTemplateRenderedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-appframework-http-events-beforelogintemplaterenderedevent "Link to this heading") Added in version 28. Emitted before the rendering step of the login TemplateResponse. #### `OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-appframework-http-events-beforetemplaterenderedevent "Link to this heading") Added in version 20. Emitted before the rendering step of each TemplateResponse. The event holds a flag that specifies if an user is logged in. #### `OCP\Authentication\Events\AnyLoginFailedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-authentication-events-anyloginfailedevent "Link to this heading") Added in version 26. Emitted when the authentication fails #### `OCP\Authentication\Events\LoginFailedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-authentication-events-loginfailedevent "Link to this heading") Added in version 19. Emitted when the authentication fails, but only if the login name can be associated with an existing user. #### `OCP\Authentication\Events\TokenInvalidatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-authentication-events-tokeninvalidatedevent "Link to this heading") Added in version 32. Emitted when an authentication token is invalidated. #### `OCP\Authentication\TwoFactorAuth\RegistryEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-authentication-twofactorauth-registryevent "Link to this heading") Added in version 15. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengeFailed`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderchallengefailed "Link to this heading") Added in version 28. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengePassed`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderchallengepassed "Link to this heading") Added in version 28. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderDisabled`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderdisabled "Link to this heading") Added in version 20. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserDisabled`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderforuserdisabled "Link to this heading") Added in version 22. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserEnabled`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderforuserenabled "Link to this heading") Added in version 22. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserRegistered`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderforuserregistered "Link to this heading") Added in version 28. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserUnregistered`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderforuserunregistered "Link to this heading") Added in version 28. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderUserDeleted`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorprovideruserdeleted "Link to this heading") Added in version 28. #### `OCP\BeforeSabrePubliclyLoadedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-beforesabrepubliclyloadedevent "Link to this heading") Added in version 26. Dispatched before Sabre is loaded when accessing public webdav endpoints This can be used to inject a Sabre plugin for example #### `OCP\Calendar\Events\CalendarObjectCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-calendar-events-calendarobjectcreatedevent "Link to this heading") Added in version 32. #### `OCP\Calendar\Events\CalendarObjectDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-calendar-events-calendarobjectdeletedevent "Link to this heading") Added in version 32. #### `OCP\Calendar\Events\CalendarObjectMovedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-calendar-events-calendarobjectmovedevent "Link to this heading") Added in version 32. #### `OCP\Calendar\Events\CalendarObjectMovedToTrashEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-calendar-events-calendarobjectmovedtotrashevent "Link to this heading") Added in version 32. #### `OCP\Calendar\Events\CalendarObjectRestoredEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-calendar-events-calendarobjectrestoredevent "Link to this heading") Added in version 32. #### `OCP\Calendar\Events\CalendarObjectUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-calendar-events-calendarobjectupdatedevent "Link to this heading") Added in version 32. #### `OCP\Collaboration\AutoComplete\AutoCompleteEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-collaboration-autocomplete-autocompleteevent "Link to this heading") Added in version 16. #### `OCP\Collaboration\AutoComplete\AutoCompleteFilterEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-collaboration-autocomplete-autocompletefilterevent "Link to this heading") Added in version 28. #### `OCP\Collaboration\Reference\RenderReferenceEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-collaboration-reference-renderreferenceevent "Link to this heading") Added in version 25. Event emitted when apps might render references like link previews or smart picker widgets. This can be used to inject scripts for extending that. Further details can be found in the [Reference providers](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/reference.html#reference-providers) deep dive. #### `OCP\Collaboration\Resources\LoadAdditionalScriptsEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-collaboration-resources-loadadditionalscriptsevent "Link to this heading") Added in version 25. This event is used by apps to register their own frontend scripts for integrating projects in their app. Apps also need to dispatch the event in order to load scripts during page load #### `OCP\Comments\CommentsEntityEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-comments-commentsentityevent "Link to this heading") Added in version 9.1. Changed in version 28.0.0: Dispatched as a typed event Class CommentsEntityEvent #### `OCP\Comments\CommentsEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-comments-commentsevent "Link to this heading") Added in version 9. Class CommentsEvent #### `OCP\Config\BeforePreferenceDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-config-beforepreferencedeletedevent "Link to this heading") Added in version 25. #### `OCP\Config\BeforePreferenceSetEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-config-beforepreferencesetevent "Link to this heading") Added in version 25. #### `OCP\Console\ConsoleEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-console-consoleevent "Link to this heading") Added in version 9. Class ConsoleEvent #### `OCP\Contacts\Events\ContactInteractedWithEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-contacts-events-contactinteractedwithevent "Link to this heading") Added in version 19. An event that allows apps to notify other components about an interaction between two users. This can be used to build better recommendations and suggestions in user interfaces. Emitters should add at least one identifier (uid, email, federated cloud ID) of the recipient of the interaction. #### `OCP\DB\Events\AddMissingColumnsEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-db-events-addmissingcolumnsevent "Link to this heading") Added in version 28. Event to allow apps to register information about missing database columns This event will be dispatched for checking on the admin settings and when running occ db:add-missing-columns which will then create those columns #### `OCP\DB\Events\AddMissingIndicesEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-db-events-addmissingindicesevent "Link to this heading") Added in version 28. Event to allow apps to register information about missing database indices This event will be dispatched for checking on the admin settings and when running occ db:add-missing-indices which will then create those indices #### `OCP\DB\Events\AddMissingPrimaryKeyEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-db-events-addmissingprimarykeyevent "Link to this heading") Added in version 28. Event to allow apps to register information about missing database primary keys This event will be dispatched for checking on the admin settings and when running occ db:add-missing-primary-keys which will then create those keys #### `OCP\DirectEditing\RegisterDirectEditorEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-directediting-registerdirecteditorevent "Link to this heading") Added in version 18. Event to allow to register the direct editor. #### `OCP\EventDispatcher\GenericEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-eventdispatcher-genericevent "Link to this heading") Added in version 18. Class GenericEvent convenience re-implementation of SymfonyComponentGenericEvent against OCPEventDispatcherEvent #### `OCP\Federation\Events\TrustedServerRemovedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-federation-events-trustedserverremovedevent "Link to this heading") Added in version 25. #### `OCP\Files\Cache\AbstractCacheEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-cache-abstractcacheevent "Link to this heading") Added in version 22. #### `OCP\Files\Cache\CacheEntryInsertedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-cache-cacheentryinsertedevent "Link to this heading") Added in version 21. Event for when an existing entry in the cache gets inserted #### `OCP\Files\Cache\CacheEntryRemovedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-cache-cacheentryremovedevent "Link to this heading") Added in version 21. Event for when an existing entry in the cache gets removed #### `OCP\Files\Cache\CacheEntryUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-cache-cacheentryupdatedevent "Link to this heading") Added in version 21. Event for when an existing entry in the cache gets updated #### `OCP\Files\Cache\CacheInsertEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-cache-cacheinsertevent "Link to this heading") Added in version 16. Event for when a new entry gets added to the cache #### `OCP\Files\Cache\CacheUpdateEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-cache-cacheupdateevent "Link to this heading") Added in version 16. Event for when an existing entry in the cache gets updated #### `OCP\Files\Config\Event\UserMountAddedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-config-event-usermountaddedevent "Link to this heading") Added in version 31. Event emitted when a user mount was added. #### `OCP\Files\Config\Event\UserMountRemovedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-config-event-usermountremovedevent "Link to this heading") Added in version 31. Event emitted when a user mount was removed. #### `OCP\Files\Config\Event\UserMountUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-config-event-usermountupdatedevent "Link to this heading") Added in version 31. Event emitted when a user mount was moved. #### `OCP\Files\Events\BeforeDirectFileDownloadEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-beforedirectfiledownloadevent "Link to this heading") Added in version 25. This event is triggered when a user tries to download a file directly. #### `OCP\Files\Events\BeforeFileScannedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-beforefilescannedevent "Link to this heading") Added in version 18. #### `OCP\Files\Events\BeforeFileSystemSetupEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-beforefilesystemsetupevent "Link to this heading") Added in version 31. Event triggered before the file system is setup #### `OCP\Files\Events\BeforeFolderScannedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-beforefolderscannedevent "Link to this heading") Added in version 18. #### `OCP\Files\Events\BeforeZipCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-beforezipcreatedevent "Link to this heading") Added in version 25. This event is triggered before a archive is created when a user requested downloading a folder or multiple files. By setting successful to false the tar creation can be aborted and the download denied. #### `OCP\Files\Events\FileCacheUpdated`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-filecacheupdated "Link to this heading") Added in version 18. #### `OCP\Files\Events\FileScannedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-filescannedevent "Link to this heading") Added in version 18. #### `OCP\Files\Events\FolderScannedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-folderscannedevent "Link to this heading") Added in version 18. #### `OCP\Files\Events\InvalidateMountCacheEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-invalidatemountcacheevent "Link to this heading") Added in version 24. Used to notify the filesystem setup manager that the available mounts for a user have changed #### `OCP\Files\Events\Node\BeforeNodeCopiedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-beforenodecopiedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\BeforeNodeCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-beforenodecreatedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\BeforeNodeDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-beforenodedeletedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\BeforeNodeReadEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-beforenodereadevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\BeforeNodeRenamedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-beforenoderenamedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\BeforeNodeTouchedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-beforenodetouchedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\BeforeNodeWrittenEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-beforenodewrittenevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\FilesystemTornDownEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-filesystemtorndownevent "Link to this heading") Added in version 24. Event fired after the filesystem has been torn down #### `OCP\Files\Events\Node\NodeCopiedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-nodecopiedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\NodeCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-nodecreatedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\NodeDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-nodedeletedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\NodeRenamedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-noderenamedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\NodeTouchedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-nodetouchedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\NodeWrittenEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-node-nodewrittenevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\NodeAddedToCache`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-nodeaddedtocache "Link to this heading") Added in version 18. #### `OCP\Files\Events\NodeAddedToFavorite`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-nodeaddedtofavorite "Link to this heading") Added in version 28. #### `OCP\Files\Events\NodeRemovedFromCache`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-noderemovedfromcache "Link to this heading") Added in version 18. #### `OCP\Files\Events\NodeRemovedFromFavorite`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-events-noderemovedfromfavorite "Link to this heading") Added in version 28. #### `OCP\Files\ObjectStore\Events\BucketCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-objectstore-events-bucketcreatedevent "Link to this heading") Added in version 33. #### `OCP\Files\Template\BeforeGetTemplatesEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-template-beforegettemplatesevent "Link to this heading") Added in version 30. #### `OCP\Files\Template\FileCreatedFromTemplateEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-template-filecreatedfromtemplateevent "Link to this heading") Added in version 21. #### `OCP\Files\Template\RegisterTemplateCreatorEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-files-template-registertemplatecreatorevent "Link to this heading") Added in version 30. #### `OCP\FilesMetadata\Event\MetadataBackgroundEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-filesmetadata-event-metadatabackgroundevent "Link to this heading") Added in version 28. MetadataBackgroundEvent is an event similar to MetadataLiveEvent but dispatched on a background thread instead of live thread. Meaning there is no limit to the time required for the generation of your metadata. #### `OCP\FilesMetadata\Event\MetadataLiveEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-filesmetadata-event-metadataliveevent "Link to this heading") Added in version 28. MetadataLiveEvent is an event initiated when a file is created or updated. The app contains the Node related to the created/updated file, and a FilesMetadata that already contains the currently known metadata. Setting new metadata, or modifying already existing metadata with different value, will trigger the save of the metadata in the database. #### `OCP\FilesMetadata\Event\MetadataNamedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-filesmetadata-event-metadatanamedevent "Link to this heading") Added in version 28. MetadataNamedEvent is an event similar to MetadataBackgroundEvent completed with a target name, used to limit the refresh of metadata only listeners capable of filtering themselves out. Meaning that when using this event, your app must implement a filter on the event’s registered name returned by getName() This event is mostly triggered when a registered name is added to the files scan i.e. ./occ files:scan –generate-metadata \[name\] #### `OCP\Group\Events\BeforeGroupChangedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-group-events-beforegroupchangedevent "Link to this heading") Added in version 26. #### `OCP\Group\Events\BeforeGroupCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-group-events-beforegroupcreatedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\BeforeGroupDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-group-events-beforegroupdeletedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\BeforeUserAddedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-group-events-beforeuseraddedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\BeforeUserRemovedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-group-events-beforeuserremovedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\GroupChangedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-group-events-groupchangedevent "Link to this heading") Added in version 26. #### `OCP\Group\Events\GroupCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-group-events-groupcreatedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\GroupDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-group-events-groupdeletedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\SubAdminAddedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-group-events-subadminaddedevent "Link to this heading") Added in version 21. #### `OCP\Group\Events\SubAdminRemovedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-group-events-subadminremovedevent "Link to this heading") Added in version 21. #### `OCP\Group\Events\UserAddedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-group-events-useraddedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\UserRemovedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-group-events-userremovedevent "Link to this heading") Added in version 18. #### `OCP\Log\Audit\CriticalActionPerformedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-log-audit-criticalactionperformedevent "Link to this heading") Added in version 22. Emitted when the admin\_audit app should log an entry #### `OCP\Log\BeforeMessageLoggedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-log-beforemessageloggedevent "Link to this heading") Added in version 28. Even for when a log item is being logged #### `OCP\Mail\Events\BeforeMessageSent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-mail-events-beforemessagesent "Link to this heading") Added in version 19. Emitted before a system mail is sent. It can be used to alter the message. #### `OCP\Navigation\Events\LoadAdditionalEntriesEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-navigation-events-loadadditionalentriesevent "Link to this heading") Added in version 31. #### `OCP\OCM\Events\ResourceTypeRegisterEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-ocm-events-resourcetyperegisterevent "Link to this heading") Added in version 28. Use this event to register additional OCM resources before the API returns them in the OCM provider list and capability #### `OCP\Preview\BeforePreviewFetchedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-preview-beforepreviewfetchedevent "Link to this heading") Added in version 25.0.1. Changed in version 28.0.0: the constructor arguments `$width`, `$height`, `$crop` and `$mode` are no longer nullable. Changed in version 31.0.0: the constructor arguments `$mimeType` was added Emitted before a file preview is being fetched. It can be used to block preview rendering by throwing a `OCP\Files\NotFoundException` #### `OCP\Profile\BeforeTemplateRenderedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-profile-beforetemplaterenderedevent "Link to this heading") Added in version 25. Emitted before the rendering step of the public profile page happens. #### `OCP\SabrePluginEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-sabrepluginevent "Link to this heading") Added in version 8.2. #### `OCP\Security\CSP\AddContentSecurityPolicyEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-security-csp-addcontentsecuritypolicyevent "Link to this heading") Added in version 17. Allows to inject something into the default content policy. This is for example useful when you’re injecting Javascript code into a view belonging to another controller and cannot modify its Content-Security-Policy itself. Note that the adjustment is only applied to applications that use AppFramework controllers. WARNING: Using this API incorrectly may make the instance more insecure. Do think twice before adding whitelisting resources. Please do also note that it is not possible to use the disallowXYZ functions. #### `OCP\Security\Events\GenerateSecurePasswordEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-security-events-generatesecurepasswordevent "Link to this heading") Added in version 18. Event to request a secure password to be generated. Since Nextcloud 31 this event also provides a `getContext` method allowing to apply different rules for different password context like account passwords or share passwords. #### `OCP\Security\Events\ValidatePasswordPolicyEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-security-events-validatepasswordpolicyevent "Link to this heading") Added in version 18. This event can be emitted to request a validation of a password. If a password policy app is installed and the password is invalid, an OCPHintException will be thrown. Since Nextcloud 31 this event also provides a `getContext` method allowing to apply different rules for different password context like account passwords or share passwords. #### `OCP\Security\FeaturePolicy\AddFeaturePolicyEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-security-featurepolicy-addfeaturepolicyevent "Link to this heading") Added in version 17. Event that allows to register a feature policy header to a request. #### `OCP\Settings\Events\DeclarativeSettingsGetValueEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-settings-events-declarativesettingsgetvalueevent "Link to this heading") Added in version 29. #### `OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-settings-events-declarativesettingsregisterformevent "Link to this heading") Added in version 29. #### `OCP\Settings\Events\DeclarativeSettingsSetValueEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-settings-events-declarativesettingssetvalueevent "Link to this heading") Added in version 29. #### `OCP\Share\Events\BeforeShareCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-share-events-beforesharecreatedevent "Link to this heading") Added in version 28. #### `OCP\Share\Events\BeforeShareDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-share-events-beforesharedeletedevent "Link to this heading") Added in version 28. #### `OCP\Share\Events\ShareAcceptedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-share-events-shareacceptedevent "Link to this heading") Added in version 28. #### `OCP\Share\Events\ShareCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-share-events-sharecreatedevent "Link to this heading") Added in version 18. #### `OCP\Share\Events\ShareDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-share-events-sharedeletedevent "Link to this heading") Added in version 21. #### `OCP\Share\Events\ShareDeletedFromSelfEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-share-events-sharedeletedfromselfevent "Link to this heading") Added in version 28. #### `OCP\Share\Events\VerifyMountPointEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-share-events-verifymountpointevent "Link to this heading") Added in version 19. #### `OCP\SpeechToText\Events\TranscriptionFailedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-speechtotext-events-transcriptionfailedevent "Link to this heading") Added in version 27. This Event is emitted if a transcription of a media file using a Speech-To-Text provider failed #### `OCP\SpeechToText\Events\TranscriptionSuccessfulEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-speechtotext-events-transcriptionsuccessfulevent "Link to this heading") Added in version 27. This Event is emitted when a transcription of a media file happened successfully #### `OCP\SystemTag\ManagerEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-systemtag-managerevent "Link to this heading") Added in version 9. Class ManagerEvent #### `OCP\SystemTag\MapperEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-systemtag-mapperevent "Link to this heading") Added in version 9. Class MapperEvent #### `OCP\SystemTag\SystemTagsEntityEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-systemtag-systemtagsentityevent "Link to this heading") Added in version 9.1. Changed in version 28.0.0: Dispatched as a typed event Class SystemTagsEntityEvent #### `OCP\TaskProcessing\Events\GetTaskProcessingProvidersEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-taskprocessing-events-gettaskprocessingprovidersevent "Link to this heading") Added in version 32. Event dispatched by the server to collect Task Processing Providers and custom Task Types from listeners (like AppAPI). Listeners should add their providers and task types using the addProvider() and addTaskType() methods. #### `OCP\TaskProcessing\Events\TaskFailedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-taskprocessing-events-taskfailedevent "Link to this heading") Added in version 30. #### `OCP\TaskProcessing\Events\TaskSuccessfulEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-taskprocessing-events-tasksuccessfulevent "Link to this heading") Added in version 30. #### `OCP\TextProcessing\Events\TaskFailedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-textprocessing-events-taskfailedevent "Link to this heading") Added in version 27.1. #### `OCP\TextProcessing\Events\TaskSuccessfulEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-textprocessing-events-tasksuccessfulevent "Link to this heading") Added in version 27.1. #### `OCP\TextToImage\Events\TaskFailedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-texttoimage-events-taskfailedevent "Link to this heading") Added in version 28. #### `OCP\TextToImage\Events\TaskSuccessfulEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-texttoimage-events-tasksuccessfulevent "Link to this heading") Added in version 28. #### `OCP\User\Events\BeforePasswordUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-beforepasswordupdatedevent "Link to this heading") Added in version 18. Emitted before the user password is updated. #### `OCP\User\Events\BeforeUserCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-beforeusercreatedevent "Link to this heading") Added in version 18. Emitted before a new user is created on the back-end. #### `OCP\User\Events\BeforeUserDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-beforeuserdeletedevent "Link to this heading") Added in version 18. #### `OCP\User\Events\BeforeUserIdUnassignedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-beforeuseridunassignedevent "Link to this heading") Added in version 31. Emitted before removing the mapping between an external user and an internal userid #### `OCP\User\Events\BeforeUserLoggedInEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-beforeuserloggedinevent "Link to this heading") Added in version 18. #### `OCP\User\Events\BeforeUserLoggedInWithCookieEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-beforeuserloggedinwithcookieevent "Link to this heading") Added in version 18. Emitted before a user is logged in via remember-me cookies. #### `OCP\User\Events\BeforeUserLoggedOutEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-beforeuserloggedoutevent "Link to this heading") Added in version 18. Emitted before a user is logged out. #### `OCP\User\Events\OutOfOfficeChangedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-outofofficechangedevent "Link to this heading") Added in version 28. Emitted when a user’s out-of-office period has changed #### `OCP\User\Events\OutOfOfficeClearedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-outofofficeclearedevent "Link to this heading") Added in version 28. Emitted when a user’s out-of-office period is cleared #### `OCP\User\Events\OutOfOfficeEndedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-outofofficeendedevent "Link to this heading") Added in version 28. Emitted when a user’s out-of-office period ended #### `OCP\User\Events\OutOfOfficeScheduledEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-outofofficescheduledevent "Link to this heading") Added in version 28. Emitted when a user’s out-of-office period is scheduled #### `OCP\User\Events\OutOfOfficeStartedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-outofofficestartedevent "Link to this heading") Added in version 28. Emitted when a user’s out-of-office period started #### `OCP\User\Events\PasswordUpdatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-passwordupdatedevent "Link to this heading") Added in version 18. Emitted when the user password has been updated. #### `OCP\User\Events\PostLoginEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-postloginevent "Link to this heading") Added in version 18. #### `OCP\User\Events\UserChangedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-userchangedevent "Link to this heading") Added in version 18. #### `OCP\User\Events\UserCreatedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-usercreatedevent "Link to this heading") Added in version 18. Emitted when a new user has been created on the back-end. #### `OCP\User\Events\UserDeletedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-userdeletedevent "Link to this heading") Added in version 18. #### `OCP\User\Events\UserFirstTimeLoggedInEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-userfirsttimeloggedinevent "Link to this heading") Added in version 28. #### `OCP\User\Events\UserIdAssignedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-useridassignedevent "Link to this heading") Added in version 31. Emitted by backends (like user\_ldap) when a user created externally is mapped for the first time and assigned a userid #### `OCP\User\Events\UserIdUnassignedEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-useridunassignedevent "Link to this heading") Added in version 31. Emitted after removing the mapping between an external user and an internal userid #### `OCP\User\Events\UserLiveStatusEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-userlivestatusevent "Link to this heading") Added in version 20. #### `OCP\User\Events\UserLoggedInEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-userloggedinevent "Link to this heading") Added in version 18. #### `OCP\User\Events\UserLoggedInWithCookieEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-userloggedinwithcookieevent "Link to this heading") Added in version 18. Emitted when a user has been successfully logged in via remember-me cookies. #### `OCP\User\Events\UserLoggedOutEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-events-userloggedoutevent "Link to this heading") Added in version 18. Emitted when a user has been logged out successfully. #### `OCP\User\GetQuotaEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-user-getquotaevent "Link to this heading") Added in version 20. Event to allow apps to #### `OCP\WorkflowEngine\Events\LoadSettingsScriptsEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-workflowengine-events-loadsettingsscriptsevent "Link to this heading") Added in version 20. Emitted when the workflow engine settings page is loaded. #### `OCP\WorkflowEngine\Events\RegisterChecksEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-workflowengine-events-registerchecksevent "Link to this heading") Added in version 18. #### `OCP\WorkflowEngine\Events\RegisterEntitiesEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-workflowengine-events-registerentitiesevent "Link to this heading") Added in version 18. #### `OCP\WorkflowEngine\Events\RegisterOperationsEvent`[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-workflowengine-events-registeroperationsevent "Link to this heading") Added in version 18. Hooks[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#hooks "Link to this heading") -------------------------------------------------------------------------------------------------------------------- Deprecated since version 18: Use the [OCP event dispatcher](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-event-dispatcher) instead. Hooks are used to execute code before or after an event has occurred. This is for instance useful to run cleanup code after users, groups or files have been deleted. Hooks should be registered in the [Bootstrapping process](https://docs.nextcloud.com/server/latest/developer_manual/app_development/bootstrap.html) . ### Available hooks[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#available-hooks "Link to this heading") The scope is the first parameter that is passed to the **listen** method, the second parameter is the method and the third one the callback that should be executed once the hook is being called, e.g.: listen('\\OC\\User', 'preDelete', $callback); Hooks can also be removed by using the **removeListener** method on the object: removeListener(null, null, $callback); The following hooks are available: ### Session[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#session "Link to this heading") Injectable from the ServerContainer with the `\OCP\IUserSession` service. Hooks available in scope **\\OC\\User**: * **preSetPassword** (\\OC\\User\\User $user, string $password, string $recoverPassword) * **postSetPassword** (\\OC\\User\\User $user, string $password, string $recoverPassword) * **changeUser** (\\OC\\User\\User $user, string $feature, string $value) * **preDelete** (\\OC\\User\\User $user) * **postDelete** (\\OC\\User\\User $user) * **preCreateUser** (string $uid, string $password) * **postCreateUser** (\\OC\\User\\User $user) * **preLogin** (string $user, string $password) * **postLogin** (\\OC\\User\\User $user, string $password) * **logout** () ### UserManager[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#usermanager "Link to this heading") Injectable from the ServerContainer with the `\OCP\IUserManager` service. Hooks available in scope **\\OC\\User**: * **preSetPassword** (\\OC\\User\\User $user, string $password, string $recoverPassword) * **postSetPassword** (\\OC\\User\\User $user, string $password, string $recoverPassword) * **preDelete** (\\OC\\User\\User $user) * **postDelete** (\\OC\\User\\User $user) * **preCreateUser** (string $uid, string $password) * **postCreateUser** (\\OC\\User\\User $user, string $password) ### GroupManager[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#groupmanager "Link to this heading") Hooks available in scope **\\OC\\Group**: * **preAddUser** (\\OC\\Group\\Group $group, \\OC\\User\\User $user) * **postAddUser** (\\OC\\Group\\Group $group, \\OC\\User\\User $user) * **preRemoveUser** (\\OC\\Group\\Group $group, \\OC\\User\\User $user) * **postRemoveUser** (\\OC\\Group\\Group $group, \\OC\\User\\User $user) * **preDelete** (\\OC\\Group\\Group $group) * **postDelete** (\\OC\\Group\\Group $group) * **preCreate** (string $groupId) * **postCreate** (\\OC\\Group\\Group $group) ### Filesystem root[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#filesystem-root "Link to this heading") Injectable from the ServerContainer by calling the method **getRootFolder()**, **getUserFolder()** or **getAppFolder()**. To enable these events for your app you should add the following to your info.xml file: Filesystem hooks available in scope **\\OC\\Files**: * **preWrite** (\\OCP\\Files\\Node $node) * **postWrite** (\\OCP\\Files\\Node $node) * **preCreate** (\\OCP\\Files\\Node $node) * **postCreate** (\\OCP\\Files\\Node $node) * **preDelete** (\\OCP\\Files\\Node $node) * **postDelete** (\\OCP\\Files\\Node $node) * **preTouch** (\\OCP\\Files\\Node $node, int $mtime) * **postTouch** (\\OCP\\Files\\Node $node) * **preCopy** (\\OCP\\Files\\Node $source, \\OCP\\Files\\Node $target) * **postCopy** (\\OCP\\Files\\Node $source, \\OCP\\Files\\Node $target) * **preRename** (\\OCP\\Files\\Node $source, \\OCP\\Files\\Node $target) * **postRename** (\\OCP\\Files\\Node $source, \\OCP\\Files\\Node $target) ### Filesystem scanner[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#filesystem-scanner "Link to this heading") Filesystem scanner hooks available in scope **\\OC\\Files\\Utils\\Scanner**: * **scanFile** (string $absolutePath) * **scanFolder** (string $absolutePath) * **postScanFile** (string $absolutePath) * **postScanFolder** (string $absolutePath) Public emitter[](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#public-emitter "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------- Deprecated since version 18: Use the [OCP event dispatcher](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html#ocp-event-dispatcher) instead. tbd ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [32](https://docs.nextcloud.com/server/32/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) --- # Controllers — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/latest/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/latest/developer_manual/basics/index.html) * Controllers * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/controllers.rst) * * * Controllers[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#controllers "Link to this heading") ===================================================================================================================================== Controllers are used to connect [routes](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html) with app logic. Think of it as callbacks that are executed once a request has come in. Controllers are defined inside the **lib/Controller/** directory. To create a controller, simply extend the Controller class and create a method that should be executed on a request: $id = 3 // $doMore = false // $value = 3.5 } } The following types will be cast: * **bool** or **boolean** * **float** * **int** or **integer** ### JSON parameters[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#json-parameters "Link to this heading") It is possible to pass JSON using a POST, PUT or PATCH request. To do that the **Content-Type** header has to be set to **application/json**. The JSON is being parsed as an array and the first level keys will be used to pass in the arguments, e.g.: POST /index.php/apps/myapp/authors Content\-Type: application/json { "name": "test", "number": 3, "publisher": true, "customFields": { "mail": "test@example.com", "address": "Somewhere" } } "test@example.com", "address" => "Somewhere") } } ### Reading headers, files, cookies and environment variables[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#reading-headers-files-cookies-and-environment-variables "Link to this heading") Headers, files, cookies and environment variables can be accessed directly from the request object: request\->getHeader('Content-Type'); // $\_SERVER\['HTTP\_CONTENT\_TYPE'\] $cookie \= $this\->request\->getCookie('myCookie'); // $\_COOKIES\['myCookie'\] $file \= $this\->request\->getUploadedFile('myfile'); // $\_FILES\['myfile'\] $env \= $this\->request\->getEnv('SOME\_VAR'); // $\_ENV\['SOME\_VAR'\] } } Why should those values be accessed from the request object and not from the global array like $\_FILES? Simple: [because it’s bad practice](http://c2.com/cgi/wiki?GlobalVariablesAreBad) and will make testing harder. ### Reading and writing session variables[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#reading-and-writing-session-variables "Link to this heading") To set, get or modify session variables, the ISession object has to be injected into the controller. Nextcloud will read existing session data at the beginning of the request lifecycle and close the session afterwards. This means that in order to write to the session, the session has to be opened first. This is done implicitly when calling the set method, but would close immediately afterwards. To prevent this, the session has to be explicitly opened by calling the reopen method. Alternatively, you can use the `#[UseSession]` attribute to automatically open and close the session for you. use OCP\\AppFramework\\Controller; use OCP\\AppFramework\\Http\\Attribute\\UseSession; use OCP\\AppFramework\\Http\\Response; class PageController extends Controller { #\[UseSession\] public function writeASessionVariable(): Response { // ... } } Note The `#[UseSession]` was added in Nextcloud 26 and requires PHP 8.0 or later. If your app targets older releases and PHP 7.x then use the deprecated `@UseSession` annotation. /\*\* \* @UseSession \*/ public function writeASessionVariable(): Response { // .... } In case the session may be read and written by concurrent requests of your application, keeping the session open during your controller method execution may be required to ensure that the session is locked and no other request can write to the session at the same time. When reopening the session, the session data will also get updated with the latest changes from other requests. Using the annotation will keep the session lock for the whole duration of the controller method execution. For additional information on how session locking works in PHP see the article about [PHP Session Locking: How To Prevent Sessions Blocking in PHP requests](https://ma.ttias.be/php-session-locking-prevent-sessions-blocking-in-requests/) . Then session variables can be accessed like this: Note The session is closed automatically for writing, unless you add the `#[UseSession]` attribute! session \= $session; } #\[UseSession\] public function writeASessionVariable(): Response { // read a session variable $value \= $this\->session\['value'\]; // write a session variable $this\->session\['value'\] \= 'new value'; } } ### Setting cookies[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#setting-cookies "Link to this heading") Cookies can be set or modified directly on the response class: addCookie('foo', 'bar'); $response\->addCookie('bar', 'foo', new DateTime('2015-01-01 00:00')); return $response; } /\*\* \* Invalidates the cookie "foo" \* Invalidates the cookie "bar" and "bazinga" \*/ public function invalidateCookie(): TemplateResponse { $response \= new TemplateResponse(...); $response\->invalidateCookie('foo'); $response\->invalidateCookies(array('bar', 'bazinga')); return $response; } } Responses[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#responses "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------- Similar to how every controller receives a request object, every controller method has to return a Response. This can be in the form of a Response subclass or in the form of a value that can be handled by a registered responder. There are different kinds of responses available, like HTML-based responses, data responses, or other. The app decides of which kind the response is, by returning an appropriate `Response` object in the corresponding controller method. The following sections give an overview over the various kinds and how to implement them. HTML-based Responses[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#html-based-responses "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------- HTML pages are typically served using template responses. This is typically used as a starting point to load the website. This code linked by the template is by default encapsulated by the server to provide some common styling (e.g. the header row). The code then uses JavaScript to load further components (see [Frontend building in Vue](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/js.html#applicationjs) ) and the actual data. This section only focuses on the actual HTML content, not the data to fill into the dynamic pages. ### Templates[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#templates "Link to this heading") A [template](https://docs.nextcloud.com/server/latest/developer_manual/basics/front-end/templates.html) can be rendered by returning a TemplateResponse. A TemplateResponse takes the following parameters: * **appName**: tells the template engine in which app the template should be located * **templateName**: the name of the template inside the templates/ folder without the .php extension * **parameters**: optional array parameters that are available in the template through $\_, e.g.: array('key' \=> 'something') can be accessed through: $\_\['key'\] * **renderAs**: defaults to _user_, tells Nextcloud if it should include it in the web interface, or in case _blank_ is passed solely render the template 'hi'); return new TemplateResponse($this\->appName, $templateName, $parameters); } } Showing a template is the only exception to the rule to [not disable CSRF checks](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#csrf-introduction) : The user might type the URL directly (or use a browser bookmark or similar) to navigate to a HTML template. Therefore, usage of the `#[NoCSRFRequired]` attribute (see [below](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#controller-authentication) ) is acceptable in this context. ### Public page templates[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#public-page-templates "Link to this heading") For public pages, that are rendered to users who are not logged in to the Nextcloud instance, a `OCP\\AppFramework\\Http\\Template\\PublicTemplateResponse` should be used, to load the correct base template. It also allows adding an optional set of actions that will be shown in the top right corner of the public page. appName, 'main', \[\]); $template\->setHeaderTitle('Public page'); $template\->setHeaderDetails('some details'); $template\->setHeaderActions(\[\ new SimpleMenuAction('download', 'Label 1', 'icon-css-class1', 'link-url', 0),\ new SimpleMenuAction('share', 'Label 2', 'icon-css-class2', 'link-url', 10),\ \]); return $template; } } The header title and subtitle will be rendered in the header, next to the logo. The action with the highest priority (lowest number) will be used as the primary action, others will shown in the popover menu on demand. A `OCP\\AppFramework\\Http\\Template\\SimpleMenuAction` will be a link with an icon added to the menu. App developers can implement their own types of menu renderings by adding a custom class implementing the `OCP\\AppFramework\\Http\\Template\\IMenuAction` interface. As the public template is also some HTML template, the same argumentation as for [regular templates](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#controller-template) regarding the CSRF checks hold true: The usage of `#[NoCSRFRequired]` for public pages is considered acceptable for some pages: Each page that the user should be able to directly access (by typing/pastig the URL in the browser or clicking on a link in a mail) should have this attribute set. For multi-page forms in the second and later stages, this should **not** be set as the user should follow the series of pages. Data-based responses[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#data-based-responses "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------- In contrast to the HTML template responses, the data responses return some user-data in packed form. There are different encodings thinkable like JSON, XML, or other formats. The main point is that the data is requested by the browser using JavaScript on behalf of the shown website. The user only indirectly requested the data by user interaction with the frontend. ### OCS[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#ocs "Link to this heading") In order to simplify exchange of data between the Nextcloud backend and any client (be it the web frontend or whatever else), the OCS API has been introduced. Here, JSON and XML responders have been prepared and are installed without additional effort. Note The usage of OCS is closely related to the usage of [REST APIs](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/rest_apis.html) . Unless you have a clear use-case, it is advised to use OCS over pure REST. A more detailed description can be found in [Relation of REST and OCS](https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/rest_apis.html#ocs-vs-rest) . To use OCS in your API you can use the **OCP\\AppFramework\\OCSController** base class and return your data in the form of a **DataResponse** in the following way: \[\ \[\ 'name' \=> 'Share#getShares',\ 'url' \=> '/api/v1/shares',\ 'verb' \=> 'GET',\ \],\ \],\ \]; Now your method will be reachable via `/ocs/v2.php/apps//api/v1/shares` Added in version 29: You can use the attribute `ApiRoute` as described in [Routing](https://docs.nextcloud.com/server/latest/developer_manual/basics/routing.html) instead of the entry in `appinfo/routes.php` as an alternative. ### JSON[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#json "Link to this heading") Warning The usage of standard controller to access content data like JSON (no HTML) is considered legacy. Better use [OCS](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#ocscontroller) for this type of requests. Returning JSON is simple, just pass an array to a JSONResponse: 'hi'); return new JSONResponse($params); } } Because returning JSON is such a common task, there’s even a shorter way to do this: 'hi'); } } Why does this work? Because the dispatcher sees that the controller did not return a subclass of a Response and asks the controller to turn the value into a Response. That’s where responders come in. Deprecated since version 30: Usage of “index.php”-controllers for data transmission should be avoided. Use OCS instead. ### Handling errors[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#handling-errors "Link to this heading") Sometimes a request should fail, for instance if an author with id 1 is requested but does not exist. In that case use an appropriate [HTTP error code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error) to signal the client that an error occurred. Each response subclass has access to the **setStatus** method which lets you set an HTTP status code. To return a JSONResponse signaling that the author with id 1 has not been found, use the following code: registerResponder('xml', function($value) { if ($value instanceof DataResponse) { return new XMLResponse( $value\->getData(), $value\->getStatus(), $value\->getHeaders() ); } else { return new XMLResponse($value); } }); return array('test' \=> 'hi'); } } Note The above example would only return XML if the **format** parameter was _xml_. If you want to return an XMLResponse regardless of the format parameter, extend the Response class and return a new instance of it from the controller method instead. Because returning values works fine in case of a success but not in case of failure that requires a custom HTTP error code, you can always wrap the value in a **DataResponse**. This works for both normal responses and error responses. 'not found!'), Http::STATUS\_NOT\_FOUND); } } } Miscellaneous responses[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#miscellaneous-responses "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Some special responses are available as well. These are discussed here. ### Redirects[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#redirects "Link to this heading") A redirect can be achieved by returning a RedirectResponse: addHeader('Content-Type', 'application/xml'); $this\->xml \= $xml; } public function render(): string { $root \= new SimpleXMLElement(''); array\_walk\_recursive($this\->xml, array ($root, 'addChild')); return $xml\->asXML(); } } ### Streamed and lazily rendered responses[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#streamed-and-lazily-rendered-responses "Link to this heading") By default all responses are rendered at once and sent as a string through middleware. In certain cases this is not a desirable behavior, for instance if you want to stream a file in order to save memory. To do that use the now available **OCP\\AppFramework\\Http\\StreamResponse** class: index()` method should not check the CSRF token because it has not yet been sent to the client and because of that can’t work. To turn off checks the following _Attributes_ can be added before the controller: * `#[NoAdminRequired]`: Also users that are not admins can access the page * `#[PublicPage]`: Everyone can access the page without having to log in * `#[NoTwoFactorRequired]`: A user can access the page before the two-factor challenge has been passed (use this wisely and only in two-factor auth apps, e.g. to allow setup during login) * `#[NoCSRFRequired]`: Don’t check the CSRF token (use this wisely since you might create a security hole; to understand what it does see [CSRF in the security section](https://docs.nextcloud.com/server/latest/developer_manual/prologue/security.html#cross-site-request-forgery) ) Note The attributes are only available in Nextcloud 27 or later. In older versions annotations with the same names exist: * `@NoAdminRequired` instead of `#[NoAdminRequired]` * `` @PublicPage` `` instead of `#[PublicPage]` * `` @NoTwoFactorRequired` `` instead of `#[NoTwoFactorRequired]` * `` @NoCSRFRequired` `` instead of `#[NoCSRFRequired]` In the following some examples of configurations are given. #### Showing an HTML page by the user[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#showing-an-html-page-by-the-user "Link to this heading") A typical app needs an `index.html` page to show all content within. This page should be visible by all users in the instance. Therefore, you need to loosen the restriction from admins only (`#[NoAdminRequired]`). Additionally, as the user might not have a CSRF checker cookie set yet, the CSRF checks should be disabled (which is fine as this is a template response). appName, 'main'); } } If the page should only be visible to the admin, you can keep the restrictive default by omitting the attribute `#[NoAdminRequired]`. #### Getting data from the backend using AJAX requests[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#getting-data-from-the-backend-using-ajax-requests "Link to this heading") Data for the frontend needs to be made available from the backend. Here, OCS is the suggested way to go. Here is the example from [OCS controllers](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#ocscontroller) : auth->isSuccessful here is just an // example. if (!$this\->auth\->isSuccessful()) { $templateResponse\->throttle(); } return $templateResponse; } } A controller can also have multiple factors to brute force against. In this case you can specify multiple attributes and then in the throttle you specify the action which was violated. This is especially useful when a secret, in the sample below token, could be guessed on multiple endpoints e.g. a share token on the API level, preview endpoint, frontend controller, etc. while another secret (password), is specific to this one controller method. shareManager\->getByToken($token)) { $templateResponse\->throttle(\['action' \=> 'token'\]); } // … if (!$share\->verifyPassword($password)) { $templateResponse\->throttle(\['action' \=> 'password'\]); } return $templateResponse; } } ### Modifying the content security policy[](https://docs.nextcloud.com/server/latest/developer_manual/basics/controllers.html#modifying-the-content-security-policy "Link to this heading") By default Nextcloud disables all resources which are not served on the same domain, forbids cross domain requests and disables inline CSS and JavaScript by setting a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Introducing_Content_Security_Policy) . However if an app relies on third-party media or other features which are forbidden by the current policy the policy can be relaxed. Note Double check your content and edge cases before you relax the policy! Also read the [documentation provided by MDN](https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Introducing_Content_Security_Policy) To relax the policy pass an instance of the ContentSecurityPolicy class to your response. The methods on the class can be chained. The following methods turn off security features by passing in **true** as the **$isAllowed** parameter * **allowInlineScript** (bool $isAllowed) * **allowInlineStyle** (bool $isAllowed) * **allowEvalScript** (bool $isAllowed) * **useStrictDynamic** (bool $isAllowed) Trust all scripts that are loaded by a trusted script, see ‘script-src’ and ‘strict-dynamic’ * **useStrictDynamicOnScripts** (bool $isAllowed) Trust all scripts that are loaded by a trusted script which was loaded using a ` to overtake the user account. The same problem occurs when outputting content from the database or any other location that is writable by users. Another attack vector that is often overlooked is XSS in **href** attributes. HTML allows to execute JavaScript in href attributes like this: To prevent XSS in your app, **never use echo, print() or <%=** - use **p()** instead which will sanitize the input. Also **validate URLs to start with the expected protocol** (starts with http for instance)! Note Should you ever require to print something unescaped, double check if it is really needed. If there is no other way (e.g. when including of subtemplates) use print\_unescaped with care. ### JavaScript[](https://docs.nextcloud.com/server/31/developer_manual/prologue/security.html#javascript "Link to this heading") Avoid manipulating the HTML directly via JavaScript, this often leads to XSS since people often forget to sanitize variables: var html \= '
  • ' + username + '
  • "'; If you **really** want to use JavaScript for something like this use escapeHTML to sanitize the variables: var html \= '
  • ' + escapeHTML(username) + '
  • '; An even better way to make your app safer is to use the jQuery built-in function **$.text()** instead of **$.html()**. **DON’T** messageTd.html(username); **DO** messageTd.text(username); It may also be wise to choose a proper JavaScript framework like AngularJS which automatically handles the JavaScript escaping for you. Clickjacking[](https://docs.nextcloud.com/server/31/developer_manual/prologue/security.html#clickjacking "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------- [Clickjacking](https://en.wikipedia.org/wiki/Clickjacking) tricks the user to click into an invisible iframe to perform an arbitrary action (e.g. delete a user account) To prevent such attacks Nextcloud sends the X-Frame-Options header to all template responses. Don’t remove this header if you don’t really need it! This is already built into Nextcloud in `OC_Template`. Code executions / file inclusions[](https://docs.nextcloud.com/server/31/developer_manual/prologue/security.html#code-executions-file-inclusions "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Execution means that an attacker is able to include an arbitrary PHP file. This PHP file runs with all the privileges granted to the normal application and can do an enormous amount of damage. Code executions and file inclusions can be easily prevented by **never** allowing user-input to run through the following functions: * **include()** * **require()** * **require\_once()** * **eval()** * **fopen()** Note Also **never** allow the user to upload files into a folder which is reachable from the URL! **DON’T** ) * End of Lines : Unix style (LF / ‘n’) only * No global variables or functions * Code should be tested, ideally with unit and integration tests. * When you `git pull`, always `git pull --rebase` to avoid generating extra commits like: _merged main into main_ The most part of Nextcloud is written in PHP, Typescript / JavaScript, so we have some more fine grained coding standards for those languages: * [PHP coding standards](https://docs.nextcloud.com/server/31/developer_manual/getting_started/coding_standards/php.html) * [JavaScript and Typescript](https://docs.nextcloud.com/server/31/developer_manual/getting_started/coding_standards/javascript.html) * [CSS and HTML coding standards](https://docs.nextcloud.com/server/31/developer_manual/getting_started/coding_standards/html_css.html) License headers[](https://docs.nextcloud.com/server/31/developer_manual/getting_started/coding_standards/index.html#license-headers "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Nextcloud is licensed under the [GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl) . From 16 June 2016, we switched to “GNU Affero General Public License v3.0 or later” for better long-term maintainability. If you create a new file please use this header: /\*\* \* SPDX-FileCopyrightText: \[year\] \[your name\] \[\] \* SPDX-License-Identifier: AGPL-3.0-or-later \*/ The year should then be the creation time and the email address is optional. If you edit an existing file please, please keep the existing license header as it is and just add your copyright notice, if you consider your changes substantial enough to claim copyright. In order to do so there are two options: * If a generic header is already present, please just add yourself to the AUTHORS.md file * If no generic header is present, you can add yourself with a copyright line as described above. As a rule of thumb, this is the case if you contributed more than seven lines of code. An example of a generic license header where adding yourself to the AUTHORS.md file is preferred please see the example below /\*\* \* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors \* SPDX-License-Identifier: AGPL-3.0-or-later \*/ The Nextcloud GmbH part only applies to employees of the company not to contributors. For more, general information on SPDX headers and their usage for reuse-compliance, please see * [REUSE](https://reuse.software/) * [SPDX](https://spdx.dev/) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # HTML/CSS guidelines — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * HTML/CSS guidelines * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/html_css_design/index.rst) * * * HTML/CSS guidelines[](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/index.html#html-css-guidelines "Link to this heading") ==================================================================================================================================================== * [Introduction](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html) * [New button](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#new-button) * [Introduction](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#id1) * [Basic layout](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#basic-layout) * [Rules](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#rules) * [App navigation menu](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#app-navigation-menu) * [Introduction](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#id2) * [Basic layout](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#id3) * [Basic rules](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#basic-rules) * [Utils: menu, counter & buttons](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#utils-menu-counter-buttons) * [Drag and drop](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#drag-and-drop) * [Collapsible entry](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#collapsible-entry) * [Entry bullet](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#entry-bullet) * [Undo entry](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#undo-entry) * [Edit entry](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#edit-entry) * [Pinned entry](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#pinned-entry) * [Various information](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#various-information) * [Settings](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#settings) * [Introduction](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#id4) * [Basic layout](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/navigation.html#id5) * [Main content](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/content.html) * [Rules and information](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/content.html#rules-and-information) * [Content list](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/list.html) * [Introduction](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/list.html#introduction) * [Basic layout](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/list.html#basic-layout) * [Rules and information](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/list.html#rules-and-information) * [Popovermenu in item](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/list.html#popovermenu-in-item) * [Popover menu](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/popovermenu.html) * [What is a popover menu](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/popovermenu.html#what-is-a-popover-menu) * [Basic layout](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/popovermenu.html#basic-layout) * [Technical details](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/popovermenu.html#technical-details) * [Alignment](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/popovermenu.html#alignment) * [HTML elements](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/html.html) * [Progress bar](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/html.html#progress-bar) * [Checkboxes and radios](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/html.html#checkboxes-and-radios) * [Buttons](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/html.html#buttons) * [CSS](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/css.html) * [CSS variables](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/css.html#css-variables) * [CSS classes](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/css.html#css-classes) * [Icons](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/icons.html) * [List of available icons](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/icons.html#list-of-available-icons) * [Svg color api](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/icons.html#svg-color-api) * [Material design icons](https://docs.nextcloud.com/server/32/developer_manual/html_css_design/icons.html#material-design-icons) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # HTML/CSS guidelines — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * HTML/CSS guidelines * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/html_css_design/index.rst) * * * HTML/CSS guidelines[](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/index.html#html-css-guidelines "Link to this heading") ======================================================================================================================================================== * [Introduction](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html) * [New button](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#new-button) * [Introduction](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#id1) * [Basic layout](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#basic-layout) * [Rules](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#rules) * [App navigation menu](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#app-navigation-menu) * [Introduction](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#id2) * [Basic layout](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#id3) * [Basic rules](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#basic-rules) * [Utils: menu, counter & buttons](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#utils-menu-counter-buttons) * [Drag and drop](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#drag-and-drop) * [Collapsible entry](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#collapsible-entry) * [Entry bullet](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#entry-bullet) * [Undo entry](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#undo-entry) * [Edit entry](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#edit-entry) * [Pinned entry](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#pinned-entry) * [Various information](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#various-information) * [Settings](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#settings) * [Introduction](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#id4) * [Basic layout](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/navigation.html#id5) * [Main content](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/content.html) * [Rules and information](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/content.html#rules-and-information) * [Content list](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/list.html) * [Introduction](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/list.html#introduction) * [Basic layout](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/list.html#basic-layout) * [Rules and information](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/list.html#rules-and-information) * [Popovermenu in item](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/list.html#popovermenu-in-item) * [Popover menu](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/popovermenu.html) * [What is a popover menu](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/popovermenu.html#what-is-a-popover-menu) * [Basic layout](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/popovermenu.html#basic-layout) * [Technical details](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/popovermenu.html#technical-details) * [Alignment](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/popovermenu.html#alignment) * [HTML elements](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/html.html) * [Progress bar](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/html.html#progress-bar) * [Checkboxes and radios](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/html.html#checkboxes-and-radios) * [Buttons](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/html.html#buttons) * [CSS](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/css.html) * [CSS variables](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/css.html#css-variables) * [CSS classes](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/css.html#css-classes) * [Icons](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/icons.html) * [List of available icons](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/icons.html#list-of-available-icons) * [Svg color api](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/icons.html#svg-color-api) * [Material design icons](https://docs.nextcloud.com/server/stable/developer_manual/html_css_design/icons.html#material-design-icons) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Code of conduct — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/32/developer_manual/prologue/index.html) * Code of conduct * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/code-of-conduct.rst) * * * Code of conduct[](https://docs.nextcloud.com/server/32/developer_manual/prologue/code-of-conduct.html#code-of-conduct "Link to this heading") =============================================================================================================================================== We want the Nextcloud community to be a fun and productive environment for everyone. For that reason, we ask all contributors and participants to familiarize themselves with our [Code of Conduct](https://nextcloud.com/code-of-conduct) . ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Help and communication — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/32/developer_manual/prologue/index.html) * Help and communication * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/help_communication.rst) * * * Help and communication[](https://docs.nextcloud.com/server/32/developer_manual/prologue/help_communication.html#help-and-communication "Link to this heading") ================================================================================================================================================================ Forums[](https://docs.nextcloud.com/server/32/developer_manual/prologue/help_communication.html#forums "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------- Communicate via our [forums](https://help.nextcloud.com/) . Maintainers[](https://docs.nextcloud.com/server/32/developer_manual/prologue/help_communication.html#maintainers "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------ * [Contact](https://nextcloud.com/contact/) a maintainer of a certain app or division ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Help and communication — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/stable/developer_manual/prologue/index.html) * Help and communication * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/help_communication.rst) * * * Help and communication[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/help_communication.html#help-and-communication "Link to this heading") ==================================================================================================================================================================== Forums[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/help_communication.html#forums "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------ Communicate via our [forums](https://help.nextcloud.com/) . Maintainers[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/help_communication.html#maintainers "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- * [Contact](https://nextcloud.com/contact/) a maintainer of a certain app or division ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Bugtracker — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/32/developer_manual/prologue/index.html) * Bugtracker * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/bugtracker/index.rst) * * * Bugtracker[](https://docs.nextcloud.com/server/32/developer_manual/prologue/bugtracker/index.html#bugtracker "Link to this heading") ====================================================================================================================================== Thank you for helping Nextcloud by reporting bugs. Before submitting an issue, please read [Issue submission guidelines](https://github.com/nextcloud/server/blob/master/.github/CONTRIBUTING.md#submitting-issues) first. * If the issue is with the Nextcloud server, report it to the [Server repository](https://github.com/nextcloud/server/issues) * If the issue is with the Nextcloud desktop client, report it to the [Desktop repository](https://github.com/nextcloud/desktop/issues) * If the issue is with the Nextcloud Android client, report it to the [Android repository](https://github.com/nextcloud/android/issues) * If the issue is with the Nextcloud iOS client, report it to the [iOS repository](https://github.com/nextcloud/ios/issues) * If the issue is with a Nextcloud app, report it to where that app is developed. See [App Store](https://apps.nextcloud.com/) page for related links. * If the app is listed in our [main GitHub organization](https://github.com/nextcloud) report it to the correct sub repository ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Bugtracker — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/stable/developer_manual/prologue/index.html) * Bugtracker * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/bugtracker/index.rst) * * * Bugtracker[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/bugtracker/index.html#bugtracker "Link to this heading") ========================================================================================================================================== Thank you for helping Nextcloud by reporting bugs. Before submitting an issue, please read [Issue submission guidelines](https://github.com/nextcloud/server/blob/master/.github/CONTRIBUTING.md#submitting-issues) first. * If the issue is with the Nextcloud server, report it to the [Server repository](https://github.com/nextcloud/server/issues) * If the issue is with the Nextcloud desktop client, report it to the [Desktop repository](https://github.com/nextcloud/desktop/issues) * If the issue is with the Nextcloud Android client, report it to the [Android repository](https://github.com/nextcloud/android/issues) * If the issue is with the Nextcloud iOS client, report it to the [iOS repository](https://github.com/nextcloud/ios/issues) * If the issue is with a Nextcloud app, report it to where that app is developed. See [App Store](https://apps.nextcloud.com/) page for related links. * If the app is listed in our [main GitHub organization](https://github.com/nextcloud) report it to the correct sub repository ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Development process — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Getting started](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/index.html) * Development process * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/getting_started/development_process.rst) * * * Development process[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/development_process.html#development-process "Link to this heading") ====================================================================================================================================================================== This page gives an overview of how Nextcloud code is developed. Source Code Version Control[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/development_process.html#source-code-version-control "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nextcloud uses [git](https://git-scm.com/) to manage revisions of the code. Software components have their own repositories. ### Branch Names[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/development_process.html#branch-names "Link to this heading") Default branches of Nextcloud and its app repositories are named `main` or `master`. Additionally, there are _stable branches_ whenever a major version of Nextcloud is released. Those are named `stableX`, where X refers to the version. For Nextcloud 25, for example, the stable branch is named `stable25`. Target Branches for Contributions[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/development_process.html#target-branches-for-contributions "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Any changes made to the source code go into the default branch of a repository through a [pull request](https://docs.github.com/en/pull-requests) . \# Switch to the default branch and update it git checkout main git pull origin main \# Create the new feature branch git checkout \-b feature/foo-bar \# Add and commit the changes git add file1 file2 git commit \--signoff \-m 'Add foo bar' \# Push the new commit to the remote repository and open a pull request git push origin feature/foo-bar ### Bugfixes[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/development_process.html#bugfixes "Link to this heading") If a contribution fixes a bug that also affects older Nextcloud or app releases, it may qualify for a _backport_. Backporting a fix means applying the change on an older version of the code. Git calls this operation _cherry picking_. #### Automatic Backport[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/development_process.html#automatic-backport "Link to this heading") In many cases the cherry pick results in a clean apply of the patch and git is able to resolve any small conflicts. In those cases it’s easiest to let the [backport bot](https://github.com/nextcloud/backportbot) do the backport. See the [bot usage](https://github.com/nextcloud/backportbot#usage) for its commands. #### Manual Backport[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/development_process.html#manual-backport "Link to this heading") More complex changes may require the developer to do the backport manually. This can be done as follows: \# Switch to the target branch and update it git checkout stable25 git pull origin stable25 \# Create the new backport branch git checkout \-b fix/foo-stable25 \# Cherry pick the change from the commit sha1 of the change against the default branch \# This might cause conflicts. Resolve them. git cherry-pick abc123 \# Push the cherry pick commit to the remote repository and open a pull request git push origin fix/foo-stable25 ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Desktop Clients — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * Desktop Clients * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/desktop/index.rst) * * * Desktop Clients[](https://docs.nextcloud.com/server/stable/developer_manual/desktop/index.html#desktop-clients "Link to this heading") ======================================================================================================================================== Available for Windows, macOS, and various Linux distributions, the Nextcloud Desktop Sync client enables you to: * Specify one or more directories on your computer that you want to synchronize to the Nextcloud server. * Always have the latest files synchronized, wherever they are located. This documentation is targeted for developers to build the client on their own. * [Building the Client](https://docs.nextcloud.com/server/stable/developer_manual/desktop/building.html) You can find additional information here: * [User manual](https://docs.nextcloud.com/server/32/user_manual/en/desktop/index.html) * [Admin manual](https://docs.nextcloud.com/server/32/admin_manual/desktop/index.html) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Desktop Clients — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * Desktop Clients * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/desktop/index.rst) * * * Desktop Clients[](https://docs.nextcloud.com/server/32/developer_manual/desktop/index.html#desktop-clients "Link to this heading") ==================================================================================================================================== Available for Windows, macOS, and various Linux distributions, the Nextcloud Desktop Sync client enables you to: * Specify one or more directories on your computer that you want to synchronize to the Nextcloud server. * Always have the latest files synchronized, wherever they are located. This documentation is targeted for developers to build the client on their own. * [Building the Client](https://docs.nextcloud.com/server/32/developer_manual/desktop/building.html) You can find additional information here: * [User manual](https://docs.nextcloud.com/server/32/user_manual/en/desktop/index.html) * [Admin manual](https://docs.nextcloud.com/server/32/admin_manual/desktop/index.html) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Clients and Client APIs — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * Clients and Client APIs * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/client_apis/index.rst) * * * Clients and Client APIs[](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/index.html#clients-and-client-apis "Link to this heading") ============================================================================================================================================================ * [General](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/general.html) * [Generic Errors](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/general.html#generic-errors) * [Activity](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/activity-api.html) * [Android](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/android_library/index.html) * [Android Nextcloud client development](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/android_library/index.html#android-nextcloud-client-development) * [Nextcloud Android library](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/android_library/index.html#nextcloud-android-library) * [Files](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/files.html) * [Events](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/files.html#events) * [Router](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/files.html#router) * [Login Flow](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/LoginFlow/index.html) * [Opening the webview](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/LoginFlow/index.html#opening-the-webview) * [Login in the user](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/LoginFlow/index.html#login-in-the-user) * [Obtaining the login credentials](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/LoginFlow/index.html#obtaining-the-login-credentials) * [Converting to app passwords](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/LoginFlow/index.html#converting-to-app-passwords) * [Deleting an app password](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/LoginFlow/index.html#deleting-an-app-password) * [Login flow v2](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/LoginFlow/index.html#login-flow-v2) * [Troubleshooting](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/LoginFlow/index.html#troubleshooting) * [OCS API](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/index.html) * [OCS OpenAPI tutorial](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-openapi.html) * [OCS APIs overview](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-api-overview.html) * [OCS Share API](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-share-api.html) * [OCS Sharee API](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-sharee-api.html) * [OCS Status API](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-status-api.html) * [OCS Recommendations API](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-recommendations-api.html) * [OCS user preferences API](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-user-preferences-api.html) * [OCS Translation API](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-translation-api.html) * [OCS TextProcessing API](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-textprocessing-api.html) * [OCS Text-To-Image API](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-text2image-api.html) * [OCS TaskProcessing API](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-taskprocessing-api.html) * [OCS Out-of-office API](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-out-of-office-api.html) * [OCS FullTextSearch Collection API](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/OCS/ocs-fulltextsearch-collections-api.html) * [Remote wipe](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/RemoteWipe/index.html) * [Obtaining wipe status](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/RemoteWipe/index.html#obtaining-wipe-status) * [Wiping the actual device](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/RemoteWipe/index.html#wiping-the-actual-device) * [Signalling completion](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/RemoteWipe/index.html#signalling-completion) * [Webdav](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/WebDAV/index.html) * [Basic APIs](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/WebDAV/basic.html) * [Search](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/WebDAV/search.html) * [Trashbin](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/WebDAV/trashbin.html) * [Versions](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/WebDAV/versions.html) * [Chunked file upload](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/WebDAV/chunking.html) * [File bulk upload](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/WebDAV/bulkupload.html) * [Comments](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/WebDAV/comments.html) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Clients and Client APIs — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * Clients and Client APIs * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/client_apis/index.rst) * * * Clients and Client APIs[](https://docs.nextcloud.com/server/32/developer_manual/client_apis/index.html#clients-and-client-apis "Link to this heading") ======================================================================================================================================================== * [General](https://docs.nextcloud.com/server/32/developer_manual/client_apis/general.html) * [Generic Errors](https://docs.nextcloud.com/server/32/developer_manual/client_apis/general.html#generic-errors) * [Activity](https://docs.nextcloud.com/server/32/developer_manual/client_apis/activity-api.html) * [Android](https://docs.nextcloud.com/server/32/developer_manual/client_apis/android_library/index.html) * [Android Nextcloud client development](https://docs.nextcloud.com/server/32/developer_manual/client_apis/android_library/index.html#android-nextcloud-client-development) * [Nextcloud Android library](https://docs.nextcloud.com/server/32/developer_manual/client_apis/android_library/index.html#nextcloud-android-library) * [Files](https://docs.nextcloud.com/server/32/developer_manual/client_apis/files.html) * [Events](https://docs.nextcloud.com/server/32/developer_manual/client_apis/files.html#events) * [Router](https://docs.nextcloud.com/server/32/developer_manual/client_apis/files.html#router) * [Login Flow](https://docs.nextcloud.com/server/32/developer_manual/client_apis/LoginFlow/index.html) * [Opening the webview](https://docs.nextcloud.com/server/32/developer_manual/client_apis/LoginFlow/index.html#opening-the-webview) * [Login in the user](https://docs.nextcloud.com/server/32/developer_manual/client_apis/LoginFlow/index.html#login-in-the-user) * [Obtaining the login credentials](https://docs.nextcloud.com/server/32/developer_manual/client_apis/LoginFlow/index.html#obtaining-the-login-credentials) * [Converting to app passwords](https://docs.nextcloud.com/server/32/developer_manual/client_apis/LoginFlow/index.html#converting-to-app-passwords) * [Deleting an app password](https://docs.nextcloud.com/server/32/developer_manual/client_apis/LoginFlow/index.html#deleting-an-app-password) * [Login flow v2](https://docs.nextcloud.com/server/32/developer_manual/client_apis/LoginFlow/index.html#login-flow-v2) * [Troubleshooting](https://docs.nextcloud.com/server/32/developer_manual/client_apis/LoginFlow/index.html#troubleshooting) * [OCS API](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/index.html) * [OCS OpenAPI tutorial](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-openapi.html) * [OCS APIs overview](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-api-overview.html) * [OCS Share API](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-share-api.html) * [OCS Sharee API](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-sharee-api.html) * [OCS Status API](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-status-api.html) * [OCS Recommendations API](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-recommendations-api.html) * [OCS user preferences API](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-user-preferences-api.html) * [OCS Translation API](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-translation-api.html) * [OCS TextProcessing API](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-textprocessing-api.html) * [OCS Text-To-Image API](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-text2image-api.html) * [OCS TaskProcessing API](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-taskprocessing-api.html) * [OCS Out-of-office API](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-out-of-office-api.html) * [OCS FullTextSearch Collection API](https://docs.nextcloud.com/server/32/developer_manual/client_apis/OCS/ocs-fulltextsearch-collections-api.html) * [Remote wipe](https://docs.nextcloud.com/server/32/developer_manual/client_apis/RemoteWipe/index.html) * [Obtaining wipe status](https://docs.nextcloud.com/server/32/developer_manual/client_apis/RemoteWipe/index.html#obtaining-wipe-status) * [Wiping the actual device](https://docs.nextcloud.com/server/32/developer_manual/client_apis/RemoteWipe/index.html#wiping-the-actual-device) * [Signalling completion](https://docs.nextcloud.com/server/32/developer_manual/client_apis/RemoteWipe/index.html#signalling-completion) * [Webdav](https://docs.nextcloud.com/server/32/developer_manual/client_apis/WebDAV/index.html) * [Basic APIs](https://docs.nextcloud.com/server/32/developer_manual/client_apis/WebDAV/basic.html) * [Search](https://docs.nextcloud.com/server/32/developer_manual/client_apis/WebDAV/search.html) * [Trashbin](https://docs.nextcloud.com/server/32/developer_manual/client_apis/WebDAV/trashbin.html) * [Versions](https://docs.nextcloud.com/server/32/developer_manual/client_apis/WebDAV/versions.html) * [Chunked file upload](https://docs.nextcloud.com/server/32/developer_manual/client_apis/WebDAV/chunking.html) * [File bulk upload](https://docs.nextcloud.com/server/32/developer_manual/client_apis/WebDAV/bulkupload.html) * [Comments](https://docs.nextcloud.com/server/32/developer_manual/client_apis/WebDAV/comments.html) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Development process — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [Getting started](https://docs.nextcloud.com/server/32/developer_manual/getting_started/index.html) * Development process * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/getting_started/development_process.rst) * * * Development process[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/development_process.html#development-process "Link to this heading") ================================================================================================================================================================== This page gives an overview of how Nextcloud code is developed. Source Code Version Control[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/development_process.html#source-code-version-control "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nextcloud uses [git](https://git-scm.com/) to manage revisions of the code. Software components have their own repositories. ### Branch Names[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/development_process.html#branch-names "Link to this heading") Default branches of Nextcloud and its app repositories are named `main` or `master`. Additionally, there are _stable branches_ whenever a major version of Nextcloud is released. Those are named `stableX`, where X refers to the version. For Nextcloud 25, for example, the stable branch is named `stable25`. Target Branches for Contributions[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/development_process.html#target-branches-for-contributions "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Any changes made to the source code go into the default branch of a repository through a [pull request](https://docs.github.com/en/pull-requests) . \# Switch to the default branch and update it git checkout main git pull origin main \# Create the new feature branch git checkout \-b feature/foo-bar \# Add and commit the changes git add file1 file2 git commit \--signoff \-m 'Add foo bar' \# Push the new commit to the remote repository and open a pull request git push origin feature/foo-bar ### Bugfixes[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/development_process.html#bugfixes "Link to this heading") If a contribution fixes a bug that also affects older Nextcloud or app releases, it may qualify for a _backport_. Backporting a fix means applying the change on an older version of the code. Git calls this operation _cherry picking_. #### Automatic Backport[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/development_process.html#automatic-backport "Link to this heading") In many cases the cherry pick results in a clean apply of the patch and git is able to resolve any small conflicts. In those cases it’s easiest to let the [backport bot](https://github.com/nextcloud/backportbot) do the backport. See the [bot usage](https://github.com/nextcloud/backportbot#usage) for its commands. #### Manual Backport[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/development_process.html#manual-backport "Link to this heading") More complex changes may require the developer to do the backport manually. This can be done as follows: \# Switch to the target branch and update it git checkout stable25 git pull origin stable25 \# Create the new backport branch git checkout \-b fix/foo-stable25 \# Cherry pick the change from the commit sha1 of the change against the default branch \# This might cause conflicts. Resolve them. git cherry-pick abc123 \# Push the cherry pick commit to the remote repository and open a pull request git push origin fix/foo-stable25 ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Security guidelines — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/stable/developer_manual/prologue/index.html) * Security guidelines * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/security.rst) * * * Security guidelines[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/security.html#security-guidelines "Link to this heading") ==================================================================================================================================================== This guideline highlights some of the most common security problems and how to prevent them. Please review your app if it contains any of the following security holes. Note **Program defensively**: for instance always check for CSRF or escape strings, even if you do not need it. This prevents future problems where you might miss a change that leads to a security hole. Note All App Framework security features depend on the call of the controller through `OCA\AppFramework\App::main`. If the controller method is executed directly, no security checks are being performed! SQL injection[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/security.html#sql-injection "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------- [SQL Injection](https://en.wikipedia.org/wiki/SQL_injection) occurs when SQL query strings are concatenated with variables. To prevent this, always use prepared queries: execute($params); If the App Framework is used, write SQL queries like this in a class that extends the Mapper: execute($sql, $params); Cross site scripting[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/security.html#cross-site-scripting "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------ [Cross site scripting](https://en.wikipedia.org/wiki/Cross-site_scripting) happens when user input is passed directly to templates. A potential attacker might be able to inject HTML/JavaScript into the page to steal the users session, log keyboard entries, even perform DDOS attacks on other websites or other malicious actions. Despite the fact that Nextcloud uses Content-Security-Policy to prevent the execution of inline JavaScript code developers are still required to prevent XSS. CSP is just another layer of defense that is not implemented in all web browsers. To prevent XSS in your app you have to sanitize the templates and all JavaScripts which performs a DOM manipulation. ### Templates[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/security.html#templates "Link to this heading") Let’s assume you use the following example in your application: to overtake the user account. The same problem occurs when outputting content from the database or any other location that is writable by users. Another attack vector that is often overlooked is XSS in **href** attributes. HTML allows to execute JavaScript in href attributes like this:
    To prevent XSS in your app, **never use echo, print() or <%=** - use **p()** instead which will sanitize the input. Also **validate URLs to start with the expected protocol** (starts with http for instance)! Note Should you ever require to print something unescaped, double check if it is really needed. If there is no other way (e.g. when including of subtemplates) use print\_unescaped with care. ### JavaScript[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/security.html#javascript "Link to this heading") Avoid manipulating the HTML directly via JavaScript, this often leads to XSS since people often forget to sanitize variables: var html \= '
  • ' + username + '
  • "'; If you **really** want to use JavaScript for something like this use escapeHTML to sanitize the variables: var html \= '
  • ' + escapeHTML(username) + '
  • '; An even better way to make your app safer is to use the jQuery built-in function **$.text()** instead of **$.html()**. **DON’T** messageTd.html(username); **DO** messageTd.text(username); It may also be wise to choose a proper JavaScript framework like AngularJS which automatically handles the JavaScript escaping for you. Clickjacking[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/security.html#clickjacking "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------- [Clickjacking](https://en.wikipedia.org/wiki/Clickjacking) tricks the user to click into an invisible iframe to perform an arbitrary action (e.g. delete a user account) To prevent such attacks Nextcloud sends the X-Frame-Options header to all template responses. Don’t remove this header if you don’t really need it! This is already built into Nextcloud in `OC_Template`. Code executions / file inclusions[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/security.html#code-executions-file-inclusions "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Code Execution means that an attacker is able to include an arbitrary PHP file. This PHP file runs with all the privileges granted to the normal application and can do an enormous amount of damage. Code executions and file inclusions can be easily prevented by **never** allowing user-input to run through the following functions: * **include()** * **require()** * **require\_once()** * **eval()** * **fopen()** Note Also **never** allow the user to upload files into a folder which is reachable from the URL! **DON’T** This means the development of your pull request cannot be considered done if you introduced changes (additions, removals or modifications) that affect app developers that you did not document. 2. A change that affects app developers, has to be reported and documented by the author of the pull request in the [App Upgrade guide](https://docs.nextcloud.com/server/32/developer_manual/app_publishing_maintenance/app_upgrade_guide/index.html#app-upgrade-guide) section. > The requirements for this documentation are: > > * It should be written so that app developers understand how to work around the change for their app in a tutorial format > > * The steps should be explicitly written, so the documentation shall not rely upon links to external resources for the steps. While it is encouraged to add an external links as additional reference, it is a hard requirement that the documentation is readable and actionable without browsing to this link. > > * The change author’s name should be added to the section so readers can reach out to the author if they have questions or if something is unclear. > > * Timeline: the documentation is required to be handed in when finalizing the pull request and should be merged timely close to the actual change. > Other documentation requirements[](https://docs.nextcloud.com/server/32/developer_manual/prologue/compatibility_app_ecosystem.html#other-documentation-requirements "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A change that affects administrators who upgrade their Nextcloud should be documented in the release notes section of the admin documentation of that release. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Compatibility with the app ecosystem — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/stable/developer_manual/prologue/index.html) * Compatibility with the app ecosystem * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/compatibility_app_ecosystem.rst) * * * Compatibility with the app ecosystem[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/compatibility_app_ecosystem.html#compatibility-with-the-app-ecosystem "Link to this heading") ========================================================================================================================================================================================================= The Nextcloud app ecosystem consists of hundreds of apps and app maintainers. The development process may require changes that affect apps in this ecosystem. These changes may either be a change in standards or best practises, yet in more extreme cases the changes may also be breaking apps. While developers are expected to aim for limiting the number of changes that break apps, this cannot always be avoided or is not always reasonable to do to maintain an up-to-date technology stack. Informing app developers about any change that affect them is therefore key to a thriving ecosystem. This page describes the three procedures to document changes that are relevant to app developers. Documentation procedures of changes that affect app developers[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/compatibility_app_ecosystem.html#documentation-procedures-of-changes-that-affect-app-developers "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- There are three procedures in place to facilitate communication to app developers about changes that affect them: 1. The definition of **Done** of a pull request includes documentation. > This means the development of your pull request cannot be considered done if you introduced changes (additions, removals or modifications) that affect app developers that you did not document. 2. A change that affects app developers, has to be reported and documented by the author of the pull request in the [App Upgrade guide](https://docs.nextcloud.com/server/stable/developer_manual/app_publishing_maintenance/app_upgrade_guide/index.html#app-upgrade-guide) section. > The requirements for this documentation are: > > * It should be written so that app developers understand how to work around the change for their app in a tutorial format > > * The steps should be explicitly written, so the documentation shall not rely upon links to external resources for the steps. While it is encouraged to add an external links as additional reference, it is a hard requirement that the documentation is readable and actionable without browsing to this link. > > * The change author’s name should be added to the section so readers can reach out to the author if they have questions or if something is unclear. > > * Timeline: the documentation is required to be handed in when finalizing the pull request and should be merged timely close to the actual change. > Other documentation requirements[](https://docs.nextcloud.com/server/stable/developer_manual/prologue/compatibility_app_ecosystem.html#other-documentation-requirements "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A change that affects administrators who upgrade their Nextcloud should be documented in the release notes section of the admin documentation of that release. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Coding style & general guidelines — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Getting started](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/index.html) * Coding style & general guidelines * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/getting_started/coding_standards/index.rst) * * * Coding style & general guidelines[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/coding_standards/index.html#coding-style-general-guidelines "Link to this heading") =================================================================================================================================================================================================== General[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/coding_standards/index.html#general "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------- * Ideally, discuss your plans on the [forums](https://help.nextcloud.com/) to see if others want to work with you on it * We use [GitHub](https://github.com/nextcloud) , please get an account there and clone the repositories you want to work on * Fixes go directly to the main branch, nevertheless they need to be tested thoroughly. * New features are always developed in a branch and only merged to the main branch once they are fully done. * Software should work. We only put features into the main branch when they are complete. It’s better to not have a feature instead of having one that works poorly. * It is best to start working based on an issue - create one if there is none. You describe what you want to do, ask feedback on the direction you take it and take it from there. * When you are finished, use the merge request function on GitHub to create a pull request. The other developers will look at it and give you feedback. You can signify that your PR is ready for review by adding the label “3. to review” to it. See [the code review page for more information](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/prologue/bugtracker/codereviews.html) * It is key to keep changes separate and small. The bigger and more hairy a PR grows, the harder it is to get it in. So split things up where you can in smaller changes - if you need a small improvement like a API addition for a big feature addition, get it in first rather than adding it to the big piece of work! * Decisions are made by consensus. We strive for making the best technical decisions and as nobody can know everything, we collaborate. That means a first negative comment might not be the final word, neither is positive feedback an immediate GO. Nextcloud is built out of modular pieces (apps) and maintainers have a strong influence. In case of disagreement we consult other seasoned contributors. Labels[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/coding_standards/index.html#labels "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------- We assign labels to issues and pull requests to make it easy to find them and to signal what needs to be done. Some of these are assigned by the developers, others by QA, bug triagers, project lead or maintainers and so on. It is not desired that users/reporters of bugs assign labels themselves, unless they are developers/contributors to Nextcloud. The most important labels and their meaning: * Tags showing the state of the issue or PR, numbered 0-4: * `0. to triage` - issue or feature request needs to get triaged and approved for development * `1. to develop` - ready to start development on this * `2. developing` - development in progress * `3. to review` - ready for review * `4. to release` - reviewed PR that awaits unfreeze of a branch to get merged or has pending CI jobs * `needs info` - this issue needs further information from the reporter, see [Nextcloud bug triaging](https://docs.nextcloud.com/server/stable/developer_manual/prologue/bugtracker/triaging.html) . This tag is typically combined with `0. to triage` to signal a bug report is not confirmed yet or a feature request has not been approved. * `needs review` - this issue needs further investigation from the Nextcloud team, see [Nextcloud bug triaging](https://docs.nextcloud.com/server/stable/developer_manual/prologue/bugtracker/triaging.html) . * Tags showing the type of issue or PR * `bug` - this issue is a bug * `enhancement` - this issue is a feature request/idea for improvement of Nextcloud * `technical debt` - this issue or PR is about [technical debt](https://en.wikipedia.org/wiki/Technical_debt) * `overview` - this issue is a summary of a global effort, usually referencing other issues * Tags that classify an issue or PR * `high`, `medium` and `low` – signify how important the bug is. * `regression` - something that worked in a previous release but is now not working as expected or missing. * `feature: *`, e.g. `feature: dav` – these tags group tickets of specific feature or subsystems. * `design` - this needs help from the design team or is a design-related issue/pull request * `good first issue` - these are issues which are relatively easy to solve and ideal for people who want to learn how to code in Nextcloud * `backport-request` - the pull requests also needs to be applied to older Nextcloud versions. This tag is typically assigned by automation. User interface[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/coding_standards/index.html#user-interface "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------- * Software should get out of the way. Do things automatically instead of offering configuration options. * Software should be easy to use. Show only the most important elements. Secondary elements only on hover or via Advanced function. * User data is sacred. Provide undo instead of asking for confirmation - [which might be dismissed](http://www.alistapart.com/articles/neveruseawarning/) * The state of the application should be clear. If something loads, provide feedback. * Do not adapt broken concepts (for example design of desktop apps) just for the sake of consistency. We aim to provide a better interface, so let’s find out how to do that! * Regularly reset your installation to see how the first-run experience is like. And improve it. * Ideally do [usability testing](http://jancborchardt.net/usability-in-free-software) to know how people use the software. * For further UX principles, read [Alex Faaborg from Mozilla](http://uxmag.com/articles/quantifying-usability) . Coding standards[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/coding_standards/index.html#coding-standards "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Maximum line-length of 80 characters * Use tabs to indent * A tab is 4 spaces wide * Opening braces of blocks are on the same line as the definition * Quotes: ‘ for everything, “ for HTML attributes (

    ) * End of Lines : Unix style (LF / ‘n’) only * No global variables or functions * Code should be tested, ideally with unit and integration tests. * When you `git pull`, always `git pull --rebase` to avoid generating extra commits like: _merged main into main_ The most part of Nextcloud is written in PHP, Typescript / JavaScript, so we have some more fine grained coding standards for those languages: * [PHP coding standards](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/coding_standards/php.html) * [JavaScript and Typescript](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/coding_standards/javascript.html) * [CSS and HTML coding standards](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/coding_standards/html_css.html) License headers[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/coding_standards/index.html#license-headers "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- Nextcloud is licensed under the [GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl) . From 16 June 2016, we switched to “GNU Affero General Public License v3.0 or later” for better long-term maintainability. If you create a new file please use this header: /\*\* \* SPDX-FileCopyrightText: \[year\] \[your name\] \[\] \* SPDX-License-Identifier: AGPL-3.0-or-later \*/ The year should then be the creation time and the email address is optional. If you edit an existing file please, please keep the existing license header as it is and just add your copyright notice, if you consider your changes substantial enough to claim copyright. In order to do so there are two options: * If a generic header is already present, please just add yourself to the AUTHORS.md file * If no generic header is present, you can add yourself with a copyright line as described above. As a rule of thumb, this is the case if you contributed more than seven lines of code. An example of a generic license header where adding yourself to the AUTHORS.md file is preferred please see the example below /\*\* \* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors \* SPDX-License-Identifier: AGPL-3.0-or-later \*/ The Nextcloud GmbH part only applies to employees of the company not to contributors. For more, general information on SPDX headers and their usage for reuse-compliance, please see * [REUSE](https://reuse.software/) * [SPDX](https://spdx.dev/) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Development environment — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Getting started](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/index.html) * Development environment * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/getting_started/devenv.rst) * * * Development environment[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/devenv.html#development-environment "Link to this heading") ================================================================================================================================================================= We have a tutorial available on setting up your development environment using docker. You can find the tutorial [here](https://cloud.nextcloud.com/s/iyNGp8ryWxc7Efa?path=%2F) . We recommend you to follow that tutorial. This page describes how to set up your development environment without docker. Please follow the steps on this page to set up your development environment manually. Set up Web server and database[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/devenv.html#set-up-web-server-and-database "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- First [set up your Web server and database](https://docs.nextcloud.com/server/32/admin_manual/installation/index.html) (**Section**: Manual Installation - Prerequisites). Get the source[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/devenv.html#get-the-source "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------- There are two ways to obtain Nextcloud sources: * Using the [stable version](https://docs.nextcloud.com/server/32/admin_manual/installation/index.html) * Using the development version from [GitHub](https://github.com/nextcloud) which will be explained below. To check out the source from [GitHub](https://github.com/nextcloud) you will need to install Git (see [Setting up Git](https://help.github.com/articles/set-up-git) from the GitHub help) ### Gather information about server setup[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/devenv.html#gather-information-about-server-setup "Link to this heading") To get started the basic Git repositories need to be cloned into the Web server’s directory. Depending on the distribution this will either be * **/var/www** * **/var/www/html** * **/srv/http** Then identify the user and group the Web server is running as and the Apache user and group for the **chown** command will either be * **http** * **www-data** * **apache** * **wwwrun** ### Check out the code[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/devenv.html#check-out-the-code "Link to this heading") The following commands are using **/var/www** as the Web server’s directory and **www-data** as user name and group. Make the directory writable so you can install the code as your regular user, and don’t need root privileges: sudo chmod o+rw /var/www Then install Nextcloud at the root of your site from Git: git clone https://github.com/nextcloud/server.git /var/www/ cd /var/www git submodule update \--init If you prefer to install Nextcloud in a sub-folder, replace /var/www with /var/www/. Create the data folder: cd /var/www mkdir data Adjust permissions: cd /var/www sudo chown \-R www\-data:www\-data config data apps sudo chmod o\-rw /var/www Finally, restart the Web server (this might vary depending on your distribution): sudo systemctl restart httpd.service or: sudo systemctl restart apache2.service or: sudo /etc/init.d/apache2 restart Now access the installation at [http://localhost/](http://localhost/) (or the corresponding URL) in your web browser to set up your instance. ### Check out external shipped apps[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/devenv.html#check-out-external-shipped-apps "Link to this heading") This optional step is especially necessary if you want to test upgrading, as the following apps are required to be present during an upgrade. Install the viewer app: cd /var/www/apps git clone https://github.com/nextcloud/viewer.git Make sure to use a version compatible with the server by checking out the matching tag. You can check the `appinfo/info.xml` of the app to see if its `min-version` field is compatible with the current server. When upgrading the server code you might need to upgrade the app code as well before running `occ upgrade`. Note The same applies to all the apps listed under `alwaysEnabled` in [shipped.json](https://github.com/nextcloud/server/blob/master/core/shipped.json#L49) but most are already present in the server repository. ### Enabling debug mode[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/devenv.html#enabling-debug-mode "Link to this heading") Note Do not enable this for production! This can create security problems and is only meant for debugging and development! To disable JavaScript and CSS caching, debugging has to be enabled by setting `debug` to `true` in `config/config.php`: true, ... configuration goes here ... ); ### Keep the code up-to-date[](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/devenv.html#keep-the-code-up-to-date "Link to this heading") If you have more than one repository cloned, it can be time consuming to do the same the action to all repositories one by one. To solve this, you can use the following command template: find . \-maxdepth \-type d \-name .git \-exec sh \-c 'cd "{}"/../ && pwd && ' \\; then, e.g. to pull all changes in all repositories, you only need this: find . \-maxdepth 3 \-type d \-name .git \-exec sh \-c 'cd "{}"/../ && pwd && git pull --rebase' \\; or to prune all merged branches, you would execute this: find . \-maxdepth 3 \-type d \-name .git \-exec sh \-c 'cd "{}"/../ && pwd && git remote prune origin' \\; It is even easier if you create alias from these commands in case you want to avoid retyping those each time you need them. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Security guidelines — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [Prologue](https://docs.nextcloud.com/server/32/developer_manual/prologue/index.html) * Security guidelines * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/prologue/security.rst) * * * Security guidelines[](https://docs.nextcloud.com/server/32/developer_manual/prologue/security.html#security-guidelines "Link to this heading") ================================================================================================================================================ This guideline highlights some of the most common security problems and how to prevent them. Please review your app if it contains any of the following security holes. Note **Program defensively**: for instance always check for CSRF or escape strings, even if you do not need it. This prevents future problems where you might miss a change that leads to a security hole. Note All App Framework security features depend on the call of the controller through `OCA\AppFramework\App::main`. If the controller method is executed directly, no security checks are being performed! SQL injection[](https://docs.nextcloud.com/server/32/developer_manual/prologue/security.html#sql-injection "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------ [SQL Injection](https://en.wikipedia.org/wiki/SQL_injection) occurs when SQL query strings are concatenated with variables. To prevent this, always use prepared queries: execute($params); If the App Framework is used, write SQL queries like this in a class that extends the Mapper: execute($sql, $params); Cross site scripting[](https://docs.nextcloud.com/server/32/developer_manual/prologue/security.html#cross-site-scripting "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- [Cross site scripting](https://en.wikipedia.org/wiki/Cross-site_scripting) happens when user input is passed directly to templates. A potential attacker might be able to inject HTML/JavaScript into the page to steal the users session, log keyboard entries, even perform DDOS attacks on other websites or other malicious actions. Despite the fact that Nextcloud uses Content-Security-Policy to prevent the execution of inline JavaScript code developers are still required to prevent XSS. CSP is just another layer of defense that is not implemented in all web browsers. To prevent XSS in your app you have to sanitize the templates and all JavaScripts which performs a DOM manipulation. ### Templates[](https://docs.nextcloud.com/server/32/developer_manual/prologue/security.html#templates "Link to this heading") Let’s assume you use the following example in your application: to overtake the user account. The same problem occurs when outputting content from the database or any other location that is writable by users. Another attack vector that is often overlooked is XSS in **href** attributes. HTML allows to execute JavaScript in href attributes like this: To prevent XSS in your app, **never use echo, print() or <%=** - use **p()** instead which will sanitize the input. Also **validate URLs to start with the expected protocol** (starts with http for instance)! Note Should you ever require to print something unescaped, double check if it is really needed. If there is no other way (e.g. when including of subtemplates) use print\_unescaped with care. ### JavaScript[](https://docs.nextcloud.com/server/32/developer_manual/prologue/security.html#javascript "Link to this heading") Avoid manipulating the HTML directly via JavaScript, this often leads to XSS since people often forget to sanitize variables: var html \= '

  • ' + username + '
  • "'; If you **really** want to use JavaScript for something like this use escapeHTML to sanitize the variables: var html \= '
  • ' + escapeHTML(username) + '
  • '; An even better way to make your app safer is to use the jQuery built-in function **$.text()** instead of **$.html()**. **DON’T** messageTd.html(username); **DO** messageTd.text(username); It may also be wise to choose a proper JavaScript framework like AngularJS which automatically handles the JavaScript escaping for you. Clickjacking[](https://docs.nextcloud.com/server/32/developer_manual/prologue/security.html#clickjacking "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------- [Clickjacking](https://en.wikipedia.org/wiki/Clickjacking) tricks the user to click into an invisible iframe to perform an arbitrary action (e.g. delete a user account) To prevent such attacks Nextcloud sends the X-Frame-Options header to all template responses. Don’t remove this header if you don’t really need it! This is already built into Nextcloud in `OC_Template`. Code executions / file inclusions[](https://docs.nextcloud.com/server/32/developer_manual/prologue/security.html#code-executions-file-inclusions "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Code Execution means that an attacker is able to include an arbitrary PHP file. This PHP file runs with all the privileges granted to the normal application and can do an enormous amount of damage. Code executions and file inclusions can be easily prevented by **never** allowing user-input to run through the following functions: * **include()** * **require()** * **require\_once()** * **eval()** * **fopen()** Note Also **never** allow the user to upload files into a folder which is reachable from the URL! **DON’T** ) * End of Lines : Unix style (LF / ‘n’) only * No global variables or functions * Code should be tested, ideally with unit and integration tests. * When you `git pull`, always `git pull --rebase` to avoid generating extra commits like: _merged main into main_ The most part of Nextcloud is written in PHP, Typescript / JavaScript, so we have some more fine grained coding standards for those languages: * [PHP coding standards](https://docs.nextcloud.com/server/32/developer_manual/getting_started/coding_standards/php.html) * [JavaScript and Typescript](https://docs.nextcloud.com/server/32/developer_manual/getting_started/coding_standards/javascript.html) * [CSS and HTML coding standards](https://docs.nextcloud.com/server/32/developer_manual/getting_started/coding_standards/html_css.html) License headers[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/coding_standards/index.html#license-headers "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Nextcloud is licensed under the [GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl) . From 16 June 2016, we switched to “GNU Affero General Public License v3.0 or later” for better long-term maintainability. If you create a new file please use this header: /\*\* \* SPDX-FileCopyrightText: \[year\] \[your name\] \[\] \* SPDX-License-Identifier: AGPL-3.0-or-later \*/ The year should then be the creation time and the email address is optional. If you edit an existing file please, please keep the existing license header as it is and just add your copyright notice, if you consider your changes substantial enough to claim copyright. In order to do so there are two options: * If a generic header is already present, please just add yourself to the AUTHORS.md file * If no generic header is present, you can add yourself with a copyright line as described above. As a rule of thumb, this is the case if you contributed more than seven lines of code. An example of a generic license header where adding yourself to the AUTHORS.md file is preferred please see the example below /\*\* \* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors \* SPDX-License-Identifier: AGPL-3.0-or-later \*/ The Nextcloud GmbH part only applies to employees of the company not to contributors. For more, general information on SPDX headers and their usage for reuse-compliance, please see * [REUSE](https://reuse.software/) * [SPDX](https://spdx.dev/) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Development environment — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Getting started](https://docs.nextcloud.com/server/31/developer_manual/getting_started/index.html) * Development environment * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/getting_started/devenv.rst) * * * Development environment[](https://docs.nextcloud.com/server/31/developer_manual/getting_started/devenv.html#development-environment "Link to this heading") ============================================================================================================================================================= We have a tutorial available on setting up your development environment using docker. You can find the tutorial [here](https://cloud.nextcloud.com/s/iyNGp8ryWxc7Efa?path=%2F) . We recommend you to follow that tutorial. This page describes how to set up your development environment without docker. Please follow the steps on this page to set up your development environment manually. Set up Web server and database[](https://docs.nextcloud.com/server/31/developer_manual/getting_started/devenv.html#set-up-web-server-and-database "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- First [set up your Web server and database](https://docs.nextcloud.com/server/31/admin_manual/installation/index.html) (**Section**: Manual Installation - Prerequisites). Get the source[](https://docs.nextcloud.com/server/31/developer_manual/getting_started/devenv.html#get-the-source "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------- There are two ways to obtain Nextcloud sources: * Using the [stable version](https://docs.nextcloud.com/server/31/admin_manual/installation/index.html) * Using the development version from [GitHub](https://github.com/nextcloud) which will be explained below. To check out the source from [GitHub](https://github.com/nextcloud) you will need to install Git (see [Setting up Git](https://help.github.com/articles/set-up-git) from the GitHub help) ### Gather information about server setup[](https://docs.nextcloud.com/server/31/developer_manual/getting_started/devenv.html#gather-information-about-server-setup "Link to this heading") To get started the basic Git repositories need to be cloned into the Web server’s directory. Depending on the distribution this will either be * **/var/www** * **/var/www/html** * **/srv/http** Then identify the user and group the Web server is running as and the Apache user and group for the **chown** command will either be * **http** * **www-data** * **apache** * **wwwrun** ### Check out the code[](https://docs.nextcloud.com/server/31/developer_manual/getting_started/devenv.html#check-out-the-code "Link to this heading") The following commands are using **/var/www** as the Web server’s directory and **www-data** as user name and group. Make the directory writable so you can install the code as your regular user, and don’t need root privileges: sudo chmod o+rw /var/www Then install Nextcloud at the root of your site from Git: git clone https://github.com/nextcloud/server.git /var/www/ cd /var/www git submodule update \--init If you prefer to install Nextcloud in a sub-folder, replace /var/www with /var/www/. Create the data folder: cd /var/www mkdir data Adjust permissions: cd /var/www sudo chown \-R www\-data:www\-data config data apps sudo chmod o\-rw /var/www Finally, restart the Web server (this might vary depending on your distribution): sudo systemctl restart httpd.service or: sudo systemctl restart apache2.service or: sudo /etc/init.d/apache2 restart Now access the installation at [http://localhost/](http://localhost/) (or the corresponding URL) in your web browser to set up your instance. ### Check out external shipped apps[](https://docs.nextcloud.com/server/31/developer_manual/getting_started/devenv.html#check-out-external-shipped-apps "Link to this heading") This optional step is especially necessary if you want to test upgrading, as the following apps are required to be present during an upgrade. Install the viewer app: cd /var/www/apps git clone https://github.com/nextcloud/viewer.git Make sure to use a version compatible with the server by checking out the matching tag. You can check the `appinfo/info.xml` of the app to see if its `min-version` field is compatible with the current server. When upgrading the server code you might need to upgrade the app code as well before running `occ upgrade`. Note The same applies to all the apps listed under `alwaysEnabled` in [shipped.json](https://github.com/nextcloud/server/blob/master/core/shipped.json#L49) but most are already present in the server repository. ### Enabling debug mode[](https://docs.nextcloud.com/server/31/developer_manual/getting_started/devenv.html#enabling-debug-mode "Link to this heading") Note Do not enable this for production! This can create security problems and is only meant for debugging and development! To disable JavaScript and CSS caching, debugging has to be enabled by setting `debug` to `true` in `config/config.php`: true, ... configuration goes here ... ); ### Keep the code up-to-date[](https://docs.nextcloud.com/server/31/developer_manual/getting_started/devenv.html#keep-the-code-up-to-date "Link to this heading") If you have more than one repository cloned, it can be time consuming to do the same the action to all repositories one by one. To solve this, you can use the following command template: find . \-maxdepth \-type d \-name .git \-exec sh \-c 'cd "{}"/../ && pwd && ' \\; then, e.g. to pull all changes in all repositories, you only need this: find . \-maxdepth 3 \-type d \-name .git \-exec sh \-c 'cd "{}"/../ && pwd && git pull --rebase' \\; or to prune all merged branches, you would execute this: find . \-maxdepth 3 \-type d \-name .git \-exec sh \-c 'cd "{}"/../ && pwd && git remote prune origin' \\; It is even easier if you create alias from these commands in case you want to avoid retyping those each time you need them. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Development environment — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [Getting started](https://docs.nextcloud.com/server/32/developer_manual/getting_started/index.html) * Development environment * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/getting_started/devenv.rst) * * * Development environment[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/devenv.html#development-environment "Link to this heading") ============================================================================================================================================================= We have a tutorial available on setting up your development environment using docker. You can find the tutorial [here](https://cloud.nextcloud.com/s/iyNGp8ryWxc7Efa?path=%2F) . We recommend you to follow that tutorial. This page describes how to set up your development environment without docker. Please follow the steps on this page to set up your development environment manually. Set up Web server and database[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/devenv.html#set-up-web-server-and-database "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- First [set up your Web server and database](https://docs.nextcloud.com/server/32/admin_manual/installation/index.html) (**Section**: Manual Installation - Prerequisites). Get the source[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/devenv.html#get-the-source "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------- There are two ways to obtain Nextcloud sources: * Using the [stable version](https://docs.nextcloud.com/server/32/admin_manual/installation/index.html) * Using the development version from [GitHub](https://github.com/nextcloud) which will be explained below. To check out the source from [GitHub](https://github.com/nextcloud) you will need to install Git (see [Setting up Git](https://help.github.com/articles/set-up-git) from the GitHub help) ### Gather information about server setup[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/devenv.html#gather-information-about-server-setup "Link to this heading") To get started the basic Git repositories need to be cloned into the Web server’s directory. Depending on the distribution this will either be * **/var/www** * **/var/www/html** * **/srv/http** Then identify the user and group the Web server is running as and the Apache user and group for the **chown** command will either be * **http** * **www-data** * **apache** * **wwwrun** ### Check out the code[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/devenv.html#check-out-the-code "Link to this heading") The following commands are using **/var/www** as the Web server’s directory and **www-data** as user name and group. Make the directory writable so you can install the code as your regular user, and don’t need root privileges: sudo chmod o+rw /var/www Then install Nextcloud at the root of your site from Git: git clone https://github.com/nextcloud/server.git /var/www/ cd /var/www git submodule update \--init If you prefer to install Nextcloud in a sub-folder, replace /var/www with /var/www/. Create the data folder: cd /var/www mkdir data Adjust permissions: cd /var/www sudo chown \-R www\-data:www\-data config data apps sudo chmod o\-rw /var/www Finally, restart the Web server (this might vary depending on your distribution): sudo systemctl restart httpd.service or: sudo systemctl restart apache2.service or: sudo /etc/init.d/apache2 restart Now access the installation at [http://localhost/](http://localhost/) (or the corresponding URL) in your web browser to set up your instance. ### Check out external shipped apps[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/devenv.html#check-out-external-shipped-apps "Link to this heading") This optional step is especially necessary if you want to test upgrading, as the following apps are required to be present during an upgrade. Install the viewer app: cd /var/www/apps git clone https://github.com/nextcloud/viewer.git Make sure to use a version compatible with the server by checking out the matching tag. You can check the `appinfo/info.xml` of the app to see if its `min-version` field is compatible with the current server. When upgrading the server code you might need to upgrade the app code as well before running `occ upgrade`. Note The same applies to all the apps listed under `alwaysEnabled` in [shipped.json](https://github.com/nextcloud/server/blob/master/core/shipped.json#L49) but most are already present in the server repository. ### Enabling debug mode[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/devenv.html#enabling-debug-mode "Link to this heading") Note Do not enable this for production! This can create security problems and is only meant for debugging and development! To disable JavaScript and CSS caching, debugging has to be enabled by setting `debug` to `true` in `config/config.php`: true, ... configuration goes here ... ); ### Keep the code up-to-date[](https://docs.nextcloud.com/server/32/developer_manual/getting_started/devenv.html#keep-the-code-up-to-date "Link to this heading") If you have more than one repository cloned, it can be time consuming to do the same the action to all repositories one by one. To solve this, you can use the following command template: find . \-maxdepth \-type d \-name .git \-exec sh \-c 'cd "{}"/../ && pwd && ' \\; then, e.g. to pull all changes in all repositories, you only need this: find . \-maxdepth 3 \-type d \-name .git \-exec sh \-c 'cd "{}"/../ && pwd && git pull --rebase' \\; or to prune all merged branches, you would execute this: find . \-maxdepth 3 \-type d \-name .git \-exec sh \-c 'cd "{}"/../ && pwd && git remote prune origin' \\; It is even easier if you create alias from these commands in case you want to avoid retyping those each time you need them. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Routing — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/31/developer_manual/basics/index.html) * Routing * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/routing.rst) * * * Routing[](https://docs.nextcloud.com/server/31/developer_manual/basics/routing.html#routing "Link to this heading") ===================================================================================================================== Routes map a URL and a method to a controller method. Routes are defined inside `appinfo/routes.php` by returning them as an array: \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \],\ \]; Added in version 29. You can also use attributes on the Controller method to define routes. They support all the same parameters (except for `name` which is not needed). `FrontpageRoute` has to be used for routes that were in the `routes` section and `ApiRoute` has to be used for routes that were in the `ocs` section. #\[FrontpageRoute(verb: 'GET', url: '/')\] #\[ApiRoute(verb: 'GET', url: '/')\] The route array contains the following parts: * **url**: The URL that is matched after _/index.php/apps/myapp_ * **name**: The controller and the method to call; _page#index_ is being mapped to _PageController->index()_, _articles\_api#drop\_latest_ would be mapped to _ArticlesApiController->dropLatest()_. The controller in the example above would be stored in `lib/Controller/PageController.php`. This parameter is not needed for the attributes. * **verb** (Optional, defaults to GET): The HTTP method that should be matched, (e.g. GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH) * **requirements** (Optional): lets you match and extract URLs that have slashes in them (see [Matching subURLs](https://docs.nextcloud.com/server/31/developer_manual/basics/routing.html#matching-suburls) ) * **postfix** (Optional): lets you define a route id postfix. Since each route name will be transformed to a route id (**page#method** -> **myapp.page.method**) and the route id can only exist once you can use the postfix option to alter the route id creation by adding a string to the route id, e.g., **‘name’ => ‘page#method’, ‘postfix’ => ‘test’** will yield the route id **myapp.page.methodtest**. This makes it possible to add more than one route/URL for a controller method * **defaults** (Optional): If this setting is given, a default value will be assumed for each URL parameter which is not present. The default values are passed in as a key => value pair array Extracting values from the URL[](https://docs.nextcloud.com/server/31/developer_manual/basics/routing.html#extracting-values-from-the-url "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- It is possible to extract values from the URL to allow RESTful URL design. To extract a value, you have to wrap it inside curly braces: 'author#show', 'url' \=> '/authors/{id}', 'verb' \=> 'GET'\], // controller/authorcontroller.php class AuthorController { public function show(string $id): Response { // $id is '3' } } The identifier used inside the route is being passed into controller method by reflecting the method parameters. So basically if you want to get the value **{id}** in your method, you need to add **$id** to your method parameters. Matching subURLs[](https://docs.nextcloud.com/server/31/developer_manual/basics/routing.html#matching-suburls "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------- Sometimes it is needed to match more than one URL fragment. An example would be to match a request for all URLs that start with **OPTIONS /index.php/apps/myapp/api**. To do this, use the **requirements** parameter in your route which is an array containing pairs of **‘key’ => ‘regex’**: 'author\_api#cors', 'url' \=> '/api/{path}', 'verb' \=> 'OPTIONS', 'requirements' \=> array('path' \=> '.+')), // controller/authorapicontroller.php class AuthorApiController { public function cors(string $path): Response { // $path will be 'my/route' } } Default values for subURL[](https://docs.nextcloud.com/server/31/developer_manual/basics/routing.html#default-values-for-suburl "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------- Apart from matching requirements, a subURL may also have a default value. Say you want to support pagination (a ‘page’ parameter) for your **/posts** subURL that displays posts entries list. You may set a default value for the ‘page’ parameter, that will be used if not already set in the URL. Use the **defaults** parameter in your route which is an array containing pairs of **‘urlparameter’ => ‘defaultvalue’**: 'post#index', 'url' \=> '/post/{page}', 'verb' \=> 'GET', 'defaults' \=> array('page' \=> 1) // this allows same URL as /index.php/myapp/post/1 ), // controller/postcontroller.php class PostController { public function index(int $page \= 1): Response { // $page will be 1 } } Registering resources[](https://docs.nextcloud.com/server/31/developer_manual/basics/routing.html#registering-resources "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------- When dealing with resources, writing routes can become quite repetitive since most of the time routes for the following tasks are needed: * Get all entries * Get one entry by id * Create an entry * Update an entry * Delete an entry To prevent repetition, it’s possible to define resources. The following routes: \[\ \['name' \=> 'author#index', 'url' \=> '/authors', 'verb' \=> 'GET'\],\ \['name' \=> 'author#show', 'url' \=> '/authors/{id}', 'verb' \=> 'GET'\],\ \['name' \=> 'author#create', 'url' \=> '/authors', 'verb' \=> 'POST'\],\ \['name' \=> 'author#update', 'url' \=> '/authors/{id}', 'verb' \=> 'PUT'\],\ \['name' \=> 'author#destroy', 'url' \=> '/authors/{id}', 'verb' \=> 'DELETE'\],\ // your other routes here\ \],\ \]; can be abbreviated by using the **resources** key: \[\ 'author' \=> \['url' \=> '/authors'\],\ \],\ 'routes' \=> \[\ // your other routes here\ \],\ \]; Using the URLGenerator[](https://docs.nextcloud.com/server/31/developer_manual/basics/routing.html#using-the-urlgenerator "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it is useful to turn a route into a URL to make the code independent from the URL design or to generate a URL for an image in **img/**. Inside the PageController the URL generator can be injected by adding it to the constructor, which will allow to use it to generate a URL for a redirect. For more details on that see the [Dependency injection](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#id2) reference. urlGenerator \= $urlGenerator; } /\*\* \* Redirects to /apps/news/myapp/authors/3 \*/ public function redirect(): RedirectResponse { // route name: author\_api#do\_something // route url: /apps/news/myapp/authors/{id} // # needs to be replaced with a . due to limitations and prefixed // with your app id $route \= 'myapp.author\_api.do\_something'; $parameters \= \['id' \=> 3\]; $url \= $this\->urlGenerator\->linkToRoute($route, $parameters); return new RedirectResponse($url); } } URLGenerator is case sensitive, so **appName** must match **exactly** the name you use in [configuration](https://docs.nextcloud.com/server/31/developer_manual/basics/storage/configuration.html) . If you use a CamelCase name as _myCamelCaseApp_, registerMiddleware(CensorMiddleware::class); } public function boot(IBootContext $context): void {} } Global Middlewares[](https://docs.nextcloud.com/server/31/developer_manual/basics/middlewares.html#global-middlewares "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------- Added in version 26. Registered middleware will only intercept requests of the same app by default. To make a middleware _global_ and trigger for other apps’ middleware, add true as the second argument of the `registerMiddleware` call: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/31/developer_manual/basics/middlewares.html#id3 "Link to this code") registerMiddleware(MonitoringMiddleware::class, true); } public function boot(IBootContext $context): void {} } Dependency Injection Container Registration[](https://docs.nextcloud.com/server/31/developer_manual/basics/middlewares.html#dependency-injection-container-registration "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Deprecated since version 20. Middleware can also be added using the **registerMiddleware** method of the container: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/31/developer_manual/basics/middlewares.html#id4 "Link to this code") getContainer(); // executed in the order that it is registered $container\->registerMiddleware(CensorMiddleware::class); } } Note The order is important! The middleware that is registered first gets run first in the **beforeController** method. For all other hooks, the order is being reversed, meaning: if a middleware is registered first, it gets run last. Parsing annotations[](https://docs.nextcloud.com/server/31/developer_manual/basics/middlewares.html#parsing-annotations "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it is useful to conditionally execute code before or after a controller method. This can be done by defining custom annotations. An example would be to add a custom authentication method or simply add an additional header to the response. To access the parsed annotations, inject the **ControllerMethodReflector** class: reflector \= $reflector; } /\*\* \* Add custom header if @MyHeader is used \*/ public function afterController($controller, $methodName, Response $response): Response { if($this\->reflector\->hasAnnotation('MyHeader')) { $response\->addHeader('My-Header', 3); } return $response; } } Note An annotation always starts with an uppercase letter ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Introduction — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/index.html) * Introduction * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/Introduction.rst) * * * Introduction[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/Introduction.html#introduction "Link to this heading") =============================================================================================================================================== **ExApps** (short for “External Apps”) are Nextcloud apps that are developed in another programming language (outside of PHP) using the AppAPI OCS API. [AppAPI](https://apps.nextcloud.com/apps/app_api) is a project introduced by Nextcloud to revolutionize the process of application development within the Nextcloud ecosystem. Overview[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/Introduction.html#overview "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------- The main tasks of the AppAPI ecosystem are: > * Providing a reliable and fast method for authenticating applications > > * Supporting various application deployment options > > * Offering a clear and straightforward application administration interface > > * Ensuring a reliable implementation of all the necessary missing APIs for applications > > * Supplying clear, understandable documentation and support on how to implement libraries in other programming languages for writing next-gen applications for Nextcloud > The system should support the expansion and integration of new deployment methods, avoiding any tight coupling with a specific deployment type. Applications should be capable of indicating the deployment methods they can accommodate. Given the evolving landscape of new technologies and the potential emergence of more intricate or simplified deployment options, the system is architected to seamlessly embrace the integration of novel deployment modes. If you have any questions or corrections regarding the documentation, we would be glad to address them in discussions, incorporate corrections through pull requests, and handle complex problems through issues. Glossary[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/Introduction.html#glossary "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------- AppAPI brings out the following terms frequently used in the code: * `ExApp` (External App) - the app on another (from PHP) programming language, which uses AppAPI OCS API * `DaemonConfig` - configuration of orchestration daemon (e.g. Docker) where ExApps are deployed * `DeployConfig` - additional DaemonConfig options for orchestrator (e.g. network) and ExApps (nextcloud\_url, host, etc.) * `ExAppConfig` - similar to Nextcloud app\_config, but for ExApps configuration * `ExAppPreferences` - similar to Nextcloud app\_preferences, user-specific settings for ExApps * `AppAPIAuth` - AppAPI authentication * `FileActionsMenu` - entry in files actions menu (context menu) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Navigation and pre-app configuration — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/31/developer_manual/app_development/index.html) * Navigation and pre-app configuration * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/init.rst) * * * Navigation and pre-app configuration[](https://docs.nextcloud.com/server/31/developer_manual/app_development/init.html#navigation-and-pre-app-configuration "Link to this heading") ===================================================================================================================================================================================== Adding a navigation entry[](https://docs.nextcloud.com/server/31/developer_manual/app_development/init.html#adding-a-navigation-entry "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------- Navigation entries for apps can be created by adding a navigation section to the `appinfo/info.xml` file, containing the name, order and route the navigation entry should link to. For details on the XML schema check the [app store documentation](https://nextcloudappstore.readthedocs.io/en/latest/developer.html#info-xml) . MyApp myapp.page.index 0 Initialization events[](https://docs.nextcloud.com/server/31/developer_manual/app_development/init.html#initialization-events "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------- Often apps do not need to load their JavaScript and CSS on every page. For this purpose there are several events emitted that an app can act upon. * `OCA\Files::loadAdditionalScripts` (string): loaded on the files list page * `OCA\Files_Sharing::loadAdditionalScripts` (string): loaded on the public sharing page * `OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth` (string): loaded on the public share authentication page * `OCP\AppFramework\Http\TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS` (constant): loaded when a template response is finished * `OCP\AppFramework\Http\TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS_LOGGEDIN` (constant): loaded when a template response is finished for a logged in user You can subscribe listeners to these events in the [bootstrapping code](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#bootstrapping) of the app. See the [events documentation](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#events) for more details on the event dispatcher and available events. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Tutorial — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/31/developer_manual/app_development/index.html) * Tutorial * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/tutorial.rst) * * * Tutorial[](https://docs.nextcloud.com/server/31/developer_manual/app_development/tutorial.html#tutorial "Link to this heading") ================================================================================================================================= To help you get started on Nextcloud app development we have compiled a comprehensive set of tutorials that cover everything from setting up your development environment to developing a full fledged app with database storage. Please head [here](https://cloud.nextcloud.com/s/iyNGp8ryWxc7Efa?path=%2F) to get started. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Front-end — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/31/developer_manual/basics/index.html) * Front-end * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/front-end/index.rst) * * * Front-end[](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/index.html#front-end "Link to this heading") ================================================================================================================================= * [Templates](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/templates.html) * [Including templates](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/templates.html#including-templates) * [Including CSS and JavaScript](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/templates.html#including-css-and-javascript) * [Including images](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/templates.html#including-images) * [JavaScript](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/js.html) * [Sending the CSRF token](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/js.html#sending-the-csrf-token) * [Generating URLs](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/js.html#generating-urls) * [Extending core parts](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/js.html#extending-core-parts) * [Loading initial state](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/js.html#loading-initial-state) * [Keyboard shortcuts](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/js.html#keyboard-shortcuts) * [CSS](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/css.html) * [Theming support](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/theming.html) * [CSS variables](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/theming.html#css-variables) * [JavaScript](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/theming.html#javascript) * [Icons](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/theming.html#icons) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Dependency injection — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/31/developer_manual/basics/index.html) * Dependency injection * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/dependency_injection.rst) * * * Dependency injection[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#dependency-injection "Link to this heading") ============================================================================================================================================================ The App Framework assembles the application by using a container based on the software pattern [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) . This makes the code easier to test and thus easier to maintain. If you are unfamiliar with this pattern, watch the following video: * [Google Clean Code Talks](https://www.youtube.com/watch?v=RlfLCWKxHJ0) Dependency injection[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#id2 "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------- Dependency Injection sounds pretty complicated but it just means: Don’t put new dependencies in your constructor or methods but pass them in. So this: use OCP\\IDBConnection; // without dependency injection class AuthorMapper { private IDBConnection $db; public function \_\_construct() { $this\->db \= new Db(); } } would turn into this by using Dependency Injection: use OCP\\IDBConnection; // with dependency injection class AuthorMapper { private IDBConnection $db; public function \_\_construct(IDBConnection $db) { $this\->db \= $db; } } Controller injection[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#controller-injection "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------ For controllers it’s possible to also have dependencies injected into methods. lib/Controller/ApiController.php[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#id4 "Link to this code") foo(); } public function bar(BarService $service) { $service\->bar(); } } Using a container[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#using-a-container "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------ Note Please do use automatic dependency injection (see below). For most apps there is no need to register services manually. Passing dependencies into the constructor rather than instantiating them in the constructor has the following drawback: Every line in the source code where **new AuthorMapper** is being used has to be changed, once a new constructor argument is being added to it. The solution for this particular problem is to limit the **new AuthorMapper** to one file, the container. The container contains all the factories for creating these objects and is configured in `lib/AppInfo/Application.php`. Nextcloud 20 and later uses the [PSR-11 standard](https://docs.nextcloud.com/server/31/developer_manual/digging_deeper/psr.html#psr11) for the container interface, so working with the container might feel familiar if you’ve worked with other php applications before that also adhere to the convention. To add the app’s classes simply open the `lib/AppInfo/Application.php` and use the **IRegistrationContext::registerService** method: registerService(AuthorController::class, function(ContainerInterface $c): AuthorController { return new AuthorController( $c\->get('appName'), $c\->get(Request::class), $c\->get(AuthorService::class) ); }); /\*\* \* Services \*/ $context\->registerService(AuthorService::class, function(ContainerInterface $c): AuthorService { return new AuthorService( $c\->get(AuthorMapper::class) ); }); /\*\* \* Mappers \*/ $context\->registerService(AuthorMapper::class, function(ContainerInterface $c): AuthorMapper { return new AuthorMapper( $c\->get(IDBConnection::class) ); }); } } How the container works[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#how-the-container-works "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ The container works in the following way: * [A request comes in and is matched against a route](https://docs.nextcloud.com/server/31/developer_manual/basics/routing.html) (for the AuthorController in this case) * The matched route queries **AuthorController** service from the container: return new AuthorController( $c->get('appName'), $c->get(Request::class), $c->get(AuthorService::class) ); * The **appName** is queried and returned from the base class * The **Request** is queried and returned from the server container * **AuthorService** is queried: $container->registerService(AuthorService::class, function(ContainerInterface $c): AuthorService { return new AuthorService( $c->get(AuthorMapper::class) ); }); * **AuthorMapper** is queried: $container->registerService(AuthorMappers::class, function(ContainerInterface $c): AuthorMapper { return new AuthorService( $c->get(IDBConnection::class) ); }); * The **database connection** is returned from the server container * Now **AuthorMapper** has all of its dependencies and the object is returned * **AuthorService** gets the **AuthorMapper** and returns the object * **AuthorController** gets the **AuthorService** and finally the controller can be instantiated and the object is returned So basically the container is used as a giant factory to build all the classes that are needed for the application. Because it centralizes all the creation of objects (the **new Class()** lines), it is very easy to add new constructor parameters without breaking existing code: only the **\_\_construct** method and the container line where the **new** is being called need to be changed. Use automatic dependency assembly (recommended)[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#use-automatic-dependency-assembly-recommended "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- In Nextcloud it is possible to build classes and their dependencies without having to explicitly register them on the container, as long as the container can [reflect](https://www.php.net/manual/en/book.reflection.php) the constructor and look up the parameters by their type. This concept is widely known as _auto-wiring_. ### How does auto-wiring work[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#how-does-auto-wiring-work "Link to this heading") Automatic assembly creates new instances of classes just by looking at the class name and its constructor parameters. For each constructor parameter the type or the argument name is used to query the container, e.g.: * **SomeType $type** will use **$container->get(SomeType::class)** * **$variable** will use **$container->get(‘variable’)** If all constructor parameters are resolved, the class will be created, saved as a service and returned. So basically the following is now possible: class \= $class; $this\->appName \= $appName; } } $app \= new \\OCP\\AppFramework\\App('myapp'); $class2 \= $app\->getContainer()\->get(MyTestClass2::class); $class2 instanceof MyTestClass2; // true $class2\->class instanceof MyTestClass; // true $class2\->appName \=== 'myname'; // true $class2 \=== $app\->getContainer()\->get(MyTestClass2::class); // true Note $appName is resolved because the container registered a parameter under the key ‘appName’ which will return the app id. ### How does it affect the request lifecycle[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#how-does-it-affect-the-request-lifecycle "Link to this heading") * A request comes in * All apps’ **routes.php** files are loaded * If a **routes.php** file returns an array, and an **appname/lib/AppInfo/Application.php** exists, include it, create a new instance of **\\OCA\\AppName\\AppInfo\\Application.php** and register the routes on it. That way a container can be used while still benefitting from the new routes behavior * If a **routes.php** file returns an array, but there is no **appname/lib/AppInfo/Application.php**, create a new \\OCP\\AppFramework\\App instance with the app id and register the routes on it * A request is matched for the route, e.g. with the name **page#index** * The appropriate container is being queried for the entry PageController (to keep backwards compatibility) * If the entry does not exist, the container is queried for OCA\\AppName\\Controller\\PageController and if no entry exists, the container tries to create the class by using [reflection](https://www.php.net/manual/en/book.reflection.php) on its constructor parameters ### How does this affect controllers[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#how-does-this-affect-controllers "Link to this heading") The only thing that needs to be done to add a route and a controller method is now: **myapp/appinfo/routes.php** \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \]\]; **myapp/appinfo/lib/Controller/PageController.php** registerParameter('TableName', 'my\_app\_table'); // the interface is called IAuthorMapper and AuthorMapper implements it $context\->registerService(IAuthorMapper::class, function (ContainerInterface $c): AuthorMapper { return $c\->get(AuthorMapper::class); }); // Less verbose alternative $context\->registerServiceAlias(IAuthorMapper::class, AuthorMapper::class); } } ### Predefined core services[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#predefined-core-services "Link to this heading") The following parameter names and type hints can be used to inject core services instead of using **$container->getServer()->getServiceX()** Parameters: * **appName**: The app id * **userId**: The id of the current user * **webRoot**: The path to the Nextcloud installation Aliases: * **AppName**: resolves to `appName` (deprecated) * **Request**: resolves to `\OCP\IRequest` * **ServerContainer**: resolves to `\OCP\IServerContainer` (deprecated) * **UserId**: resolves to `userId` (deprecated) * **WebRoot**: resolves to `webRoot` (deprecated) Types: * `\OCP\IAppConfig` * `\OCP\IAppManager` * `\OCP\IAvatarManager` * `\OCP\Activity\IManager` * `\OCP\ICache` * `\OCP\ICacheFactory` * `\OCP\IConfig` * `\OCP\AppFramework\Utility\IControllerMethodReflector` * `\OCP\Contacts\IManager` * `\OCP\IDateTimeZone` * `\OCP\IDBConnection` * `\OCP\Diagnostics\IEventLogger` * `\OCP\Diagnostics\IQueryLogger` * `\OCP\Files\Config\IMountProviderCollection` * `\OCP\Files\IRootFolder` * `\OCP\IGroupManager` * `\OCP\IL10N` * `\OCP\BackgroundJob\IJobList` * `\OCP\INavigationManager` * `\OCP\IPreview` * `\OCP\IRequest` * `\OCP\AppFramework\Utility\ITimeFactory` * `\OCP\ITagManager` * `\OCP\ITempManager` * `\OCP\Route\IRouter` * `\OCP\ISearch` * `\OCP\Security\ICrypto` * `\OCP\Security\IHasher` * `\OCP\Security\ISecureRandom` * `\OCP\IURLGenerator` * `\OCP\IUserManager` * `\OCP\IUserSession` * `\Psr\Container\ContainerInterface` * `\Psr\Log\LoggerInterface` ### How to enable it[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#how-to-enable-it "Link to this heading") To make use of this new feature, the following things have to be done: * **appinfo/info.xml** requires to provide another field called **namespace** where the namespace of the app is defined. The required namespace is the one which comes after the top level namespace **OCA\\**, e.g.: for **OCA\\MyBeautifulApp\\Some\\OtherClass** the needed namespace would be **MyBeautifulApp** and would be added to the info.xml in the following way: MyBeautifulApp * **appinfo/routes.php**: Instead of creating a new Application class instance, simply return the routes array like: \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \]\]; Note A namespace tag is required because you can not deduce the namespace from the app id Which classes should be added[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#which-classes-should-be-added "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ In general all of the app’s controllers need to be registered inside the container. Then the following question is: What goes into the constructor of the controller? Pass everything into the controller constructor that matches one of the following criteria: * It does I/O (database, write/read to files) * It is a global (e.g. $\_POST, etc. This is in the request class by the way) * The output does not depend on the input variables (also called [impure function](https://en.wikipedia.org/wiki/Pure_function) ), e.g. time, random number generator * It is a service, basically it would make sense to swap it out for a different object What not to inject: * It is pure data and has methods that only act upon it (arrays, data objects) * It is a [pure function](https://en.wikipedia.org/wiki/Pure_function) Optional services[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#optional-services "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------ Added in version 28. If an injected dependency can’t be found or build, an exception is thrown. This can be avoided by using the a nullable type notation for a dependency: namespace OCA\\MyApp\\MyService; use Some\\Service; class MyService { public function \_\_construct(private ?Service $service) { } } If `\Some\Service` exists and can be built, it will be injected. Else `MyService` will receive `null`. Accessing the container from anywhere[](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#accessing-the-container-from-anywhere "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it can be hard to inject some service inside legacy code, in these cases you can use `OCPServer::get(MyService::class)`. This should only be used as the last resort, as this makes your code more complicated to unit test and is considered an anti-pattern. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Introduction — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/31/developer_manual/app_development/index.html) * Introduction * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/intro.rst) * * * Introduction[](https://docs.nextcloud.com/server/31/developer_manual/app_development/intro.html#introduction "Link to this heading") ====================================================================================================================================== Create an app[](https://docs.nextcloud.com/server/31/developer_manual/app_development/intro.html#create-an-app "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------- After [you’ve set up the development environment](https://docs.nextcloud.com/server/31/developer_manual/getting_started/devenv.html) change into the Nextcloud apps directory: cd /var/www/nextcloud/apps Then create a skeleton app in the [app store](https://apps.nextcloud.com/developer/apps/generate) . This doesn’t publish anything on the appstore yet, it just gives you a download. Edit an existing app[](https://docs.nextcloud.com/server/31/developer_manual/app_development/intro.html#edit-an-existing-app "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------ Alternatively, if you would like to contribute to an existing app instead of creating a new one, first [set up the development environment](https://docs.nextcloud.com/server/31/developer_manual/getting_started/devenv.html) , then create an apps-extra folder in the Nextcloud root directory: cd /var/www/nextcloud/apps\-extra You can then configure Nextcloud to run apps from this directory, by changing your app\_paths system config in your config.php 'apps\_paths' \=> array ( 0 \=> array ( 'path' \=> '/var/www/html/apps', 'url' \=> '/apps', 'writable' \=> false, ), 1 \=> array ( 'path' \=> '/var/www/html/apps-extra', 'url' \=> '/apps-extra', 'writable' \=> false, ), ), Finally, clone the app to which you would like to contribute inside the apps-extra folder. For example: > git clone [https://github.com/nextcloud/cookbook.git](https://github.com/nextcloud/cookbook.git) Enable the app[](https://docs.nextcloud.com/server/31/developer_manual/app_development/intro.html#enable-the-app "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------ The app can now be enabled on the Nextcloud apps page. App architecture[](https://docs.nextcloud.com/server/31/developer_manual/app_development/intro.html#app-architecture "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- The following directories have now been created: * **appinfo/**: Contains app metadata and configuration * **css/**: Contains the CSS * **img/**: Contains icons and images * **js/**: Contains the JavaScript files * **lib/**: Contains the PHP class files of your app * **src/**: Contains the source code of your vue.js app * **templates/**: Contains the templates * **tests/**: Contains the tests ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Bootstrapping — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/31/developer_manual/app_development/index.html) * Bootstrapping * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/bootstrap.rst) * * * Bootstrapping[](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#bootstrapping "Link to this heading") ============================================================================================================================================ Every php process has a relatively short lifespan that lasts as long as the HTTP request or the invocation of the command line program. At the beginning of this lifespan, Nextcloud initializes its services. At the same time, any additional apps might want to register their services to Nextcloud as well. This event is called the _bootstrapping_ and this chapter shall shed some light on how to hook into this with an app. The Application class[](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#the-application-class "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------ The Application class is the main entry point of an app. This class is optional but highly recommended if your app needs to register any services or run some code for every request. Nextcloud will try to autoload the class from the namespace `\OCA\\AppInfo\Application`, like `\OCA\MyApp\AppInfo\Application`, where _MyApp_ would be the name of your app. The file will therefore have the location `myapp/lib/AppInfo/Application.php`. registerEventListener( BeforeUserDeletedEvent::class, UserDeletedListener::class ); } public function boot(IBootContext $context): void { // ... boot logic goes here ... /\*\* @var IManager $manager \*/ $manager \= $context\->getAppContainer()\->query(IManager::class); $manager\->registerNotifierService(Notifier::class); } } Note that the context objects of the methods `register` and `boot` have different interfaces and thus have different capabilities appropriate for their stage. Bootstrapping process[](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#bootstrapping-process "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------ To give a better overview of _when_ each of the bootstrapping stages are reached and how they app can interact with them, this section explains the changes done for Nextcloud 20. ### Nextcloud 20 and later[](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#nextcloud-20-and-later "Link to this heading") Nextcloud 20 is the first release with the interface `\OCP\AppFramework\Bootstrap\IBootstrap`. This interface can be implemented by your app’s `Application` class to signal that it wants to act on the bootstrapping stages. The major difference between this and the old process is that the bootstrapping is not performed in sequence, but apps register and boot interleaved. This should ensure that an app that `boot`s can rely on all other apps’ registration to be finished. The overall process is as follows: 1. In each installed and enabled app that has an `Application` class that also implements `IBootstrap`, the `register` method will be called. This method receives a context argument via which the app can prime the dependency injection container and register other services lazily, e.g. by calling `$context->registerService(...)`. The emphasis is on **laziness**. At this very early stage of the process lifetime, no other apps nor all of the server components are ready. Therefore the app **must not** try to use anything except the API provided by the context. That shall ensure that all apps can safely run their registration logic before any services are queried (instantiated) from the DI container or related code is run. 2. Nextcloud will load groups of certain apps early, e.g. filesystem or session apps, and other later. For that purpose, their optional [app.php (deprecated)](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#app-php) will be included. As `app.php` is deprecated, apps should try not to rely on this step. 3. Nextcloud will query the app’s `Application` class (again), no matter whether it implements `IBootstrap` or not. 4. Nextcloud will invoke the [boot](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#app-bootstrap-boot) method of every `Application` instance that implements `IBootstrap`. At this stage you may assume that all registrations via `IBootstrap::register` have completed. #### Booting an app[](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#booting-an-app "Link to this heading") Any code that should run once for every Nextcloud process goes into the `boot` method of an app’s `Application` class. Use this mechanism carefully as it could have a negative effect on Nextcloud’s overall performance. lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#id3 "Link to this code") getAppContainer()\->query(IFooManager::class); $manager\->registerCustomFoo(MyFooImpl::class); } } The code above fetches a fictional _foo manager_ to register an app class. The boot context object comes with a `injectFn` helper that eases dependency injection inside the `boot` method by injecting arguments of a callable: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#id4 "Link to this code") injectFn(function(IFooManager $manager) { $manager\->registerCustomFoo(MyFooImpl::class); }); } } With the help of `Closure::fromCallable` you can also delegate to other methods that get their arguments injected: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#id5 "Link to this code") injectFn(Closure::fromCallable(\[$this, 'registerFoo'\])); } protected function registerFoo(IFooManager $manager): void { $manager\->registerCustomFoo(MyFooImpl::class); } } ### Nextcloud 19 and older[](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#nextcloud-19-and-older "Link to this heading") Nextcloud will load groups of certain apps early, like filesystem or session apps, and other later. For this their optional [app.php (deprecated)](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#app-php) will be included. The `Application` class is only queried for some requests, so there is no guarantee that it’s constructor will be invoked. app.php (deprecated)[](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#app-php-deprecated "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------- Nextcloud will `require_once` every installed and enabled app’s `appinfo/app.php` file if it exists. The app can use this file to run registrations of autoloaders, services, event listeners and similar. To leverage the advantages of object-oriented programming, it’s recommended to put the logic into an [Application](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#application-php) class and query an instance like appinfo/app.php[](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#id6 "Link to this code") query(\\OCA\\MyApp\\AppInfo\\Application::class); ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Dependency management — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/31/developer_manual/app_development/index.html) * Dependency management * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/dependency_management.rst) * * * Dependency management[](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#dependency-management "Link to this heading") ======================================================================================================================================================================== You can leverage existing software packages to build a Nextcloud app. Composer[](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#composer "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- You can add 3rd party php packages with [Composer](https://getcomposer.org/) . Composer will download the specified packages to a directory of your choice, typically to `/vendor`. In order to benefit from Composer’s autoloader, you’ll want to add a `require_once` to the `register` method of your `Application` class in the [bootstrapping](https://docs.nextcloud.com/server/31/developer_manual/app_development/bootstrap.html#bootstrapping) code of your app. ### Remove unneeded files from packages[](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#remove-unneeded-files-from-packages "Link to this heading") It is heavily recommended to remove files that are not required in production from the final packages. This especially, but not exclusively, refers to: * Developer files, e.g. `/Makefile` * CI workflows, e.g. `/.github` * Test assets, e.g. `/tests` * Configuration of development tools, e.g. `/phpunit.xml`, `/psalm.xml` * Git or other version control code, e.g. `/.git` You can check the [Server’s .gitignore](https://github.com/nextcloud/3rdparty/blob/master/.gitignore) file for more inspiration. ### Dependency hell[](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#dependency-hell "Link to this heading") Be careful with which packages you add to an app. PHP can not load two version of the same class twice, hence there can be conflicts between Nextcloud Server and an app or between two or more apps if they require the same package. So try to keep the number of production dependencies to a minimum and see [Development tools](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#app-composer-bin-tools) . Alternatively you can use \[composer-bin-plugin\]([https://github.com/bamarni/composer-bin-plugin](https://github.com/bamarni/composer-bin-plugin) ) to avoid dependency conflicts between apps. 1. Install composer-bin-plugin according to their docs. > composer require \--dev bamarni/composer-bin-plugin 2. Install the tools you need in the vendor-bin directory. > composer bin psalm require \--dev psalm/phar > composer bin psalm require \--dev nextcloud/ocp:dev-master 3. Adjust some config (see below) * Add in composer.json: composer.json[](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#id2 "Link to this code") { "extra": { "bamarni-bin": { "bin-links": true, "forward-command": true } } } * Add in composer.json: composer.json[](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#id3 "Link to this code") { "scripts": { "post-install-cmd": \[\ "\[ $COMPOSER\_DEV\_MODE -eq 0 \] || composer bin all install --ansi"\ \], "post-update-cmd": \[\ "\[ $COMPOSER\_DEV\_MODE -eq 0 \] || composer bin all update --ansi"\ \] } } * Adjust psalm.xml: * Ensure the schemaLocation is correct: psalm.xml[](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#id4 "Link to this code") xsi:schemaLocation="https://getpsalm.org/schema/config vendor-bin/psalm/vendor/vimeo/psalm/config.xsd" * Ensure it has something like this: psalm.xml[](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#id5 "Link to this code") * Adjust .php-cs-fixer.dist.php .php-cs-fixer.dist.php[](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#id6 "Link to this code") require\_once \_\_DIR\_\_ . '/vendor-bin/cs-fixer/vendor/autoload.php'; #### Conflict example[](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#conflict-example "Link to this heading") To illustrate the problem imagine app _A_ depends on package _foo_ in version 1, app _B_ depends on package _foo_ in version 2. The package _foo_ had a breaking change to which app _B_ has been adjusted, _A_ uses the old API. Both apps ship a Composer autoloader that autoloads the _foo_ functions and classes. There is a race between the two autoloaders. If _A_’s autoloader is asked to load the class first, then v1 will be used. If _B_’s autoloader loads functions and classes first it will be v2. In some scenarios there might be classes of v1 and v2 when autoloaders are invoked without a defined order. Depending on which functions and classes are loaded, app _A_ might work or break. The same applies to _B_. ### Development tools[](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#development-tools "Link to this heading") It is very common for an app to use CLI tools for syntax checks, testing and building. Since many tools depend on common Composer packages like `psr/*` and `symfony/console`, it is likely that apps produce a [dependency hell](https://docs.nextcloud.com/server/31/developer_manual/app_development/dependency_management.html#app-composer-dependency-hell) on development environments. The dependency hell for CLI tools can be avoided by using the _Composer bin plugin_. It’s a composer plugin that puts development dependencies into sub directorory with a dedicated autoloader. That autoloader is only used if the CLI tool is used. For Nextcloud apps this means two apps can use conflicting versions of one tool. Moreover dependency conflicts between the tools of one app are no longer an issue. Tools known to be problematic that should be moved into bin plugin directories include * `friendsofphp/php-cs-fixer` * `phpunit/phpunit` * `vimeo/psalm` Please see the [package page](https://packagist.org/packages/bamarni/composer-bin-plugin) for up-to-date installation instructions. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Development overview — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/index.html) * Development overview * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/development_overview/index.rst) * * * Development overview[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/index.html#development-overview "Link to this heading") ============================================================================================================================================================================= This section contains the most common information for ExApp developers, grouped from other parts of documentation. * [ExApp development](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html) * [0\. Setting up the development environment](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#setting-up-the-development-environment) * [1\. Starting from template](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#starting-from-template) * [3\. Development](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#development) * [4\. Packaging](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#packaging) * [5\. AppStore publishing](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#appstore-publishing) * [6\. Testing](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#testing) * [ExApp overview](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppOverview.html) * [ExApp structure](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppOverview.html#exapp-structure) * [Backend](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppOverview.html#backend) * [Frontend](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppOverview.html#frontend) * [L10n translations](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppOverview.html#l10n-translations) * [Makefile](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppOverview.html#makefile) * [ExApp lifecycle](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppLifecycle.html) * [ExApp lifecycle methods](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#exapp-lifecycle-methods) * [ExApp lifecycle scheme](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#exapp-lifecycle-scheme) * [Nextcloud-side ExApp lifecycle methods](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#nextcloud-side-exapp-lifecycle-methods) * [AppAPI Authentication](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#appapi-authentication) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Technical details — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/index.html) * Technical details * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/tech_details/index.rst) * * * Technical details[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/index.html#technical-details "Link to this heading") =============================================================================================================================================================== * [App Installation Flow](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/InstallationFlow.html) * [Image Pulling (Docker)](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/InstallationFlow.html#image-pulling-docker) * [Heartbeat](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/InstallationFlow.html#heartbeat) * [Init](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/InstallationFlow.html#init) * [Enabled](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/InstallationFlow.html#enabled) * [Deployment](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Deployment.html) * [Overview](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Deployment.html#overview) * [DaemonConfig registration](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Deployment.html#daemonconfig-registration) * [ExApp registration](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Deployment.html#exapp-registration) * [Application installation scheme](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Deployment.html#application-installation-scheme) * [ExApp info.xml schema](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Deployment.html#exapp-info-xml-schema) * [Authentication](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Authentication.html) * [Authentication flow](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Authentication.html#authentication-flow) * [Authentication headers](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Authentication.html#authentication-headers) * [AppAPIAuth](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Authentication.html#appapiauth) * [AppAPI session keys](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Authentication.html#appapi-session-keys) * [Translations](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Translations.html) * [Front-end](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Translations.html#front-end) * [Back-end](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Translations.html#back-end) * [Manual install](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Translations.html#manual-install) * [Docker install](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Translations.html#docker-install) * [Translation tool](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Translations.html#translation-tool) * [AppAPI Nextcloud APIs](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/index.html) * [Logging](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/logging.html) * [AppConfig](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/appconfig.html) * [Preferences](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/preferences.html) * [ExApp](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/exapp.html) * [Routes](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/routes.html) * [Miscellaneous OCS APIs](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/utils.html) * [File Actions Menu](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/fileactionsmenu.html) * [Top Menu Entry](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/topmenu.html) * [Declarative Settings](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/settings.html) * [Notifications](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/notifications.html) * [Events Listener](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/events_listener.html) * [OCC Command](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/occ_command.html) * [Talk bots](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/talkbots.html) * [Other OCS APIs](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/api/other_ocs.html) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Frequently Asked Questions — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/index.html) * Frequently Asked Questions * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/faq/index.rst) * * * Frequently Asked Questions[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/index.html#frequently-asked-questions "Link to this heading") ======================================================================================================================================================================== This section contains the most common or problematic questions that users or developers may encounter when working with AppAPI. It can be used as pointer to other parts of the documentation, as it usually refers to, or provide a brief answer. Note This section will be updated with time, as new questions arise. If you have a question that is not listed here or the answer is not enough for you, please feel free to ask it by creating an issue in the [AppAPI repository](https://github.com/nextcloud/app_api/issues) . * [Docker Container Registry](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/DockerContainerRegistry.html) * [How to use a private Docker container registry with authentication?](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/DockerContainerRegistry.html#how-to-use-a-private-docker-container-registry-with-authentication) * [Docker Socket Proxy](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/DockerSocketProxy.html) * [Nextcloud AppAPI DSP](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/DockerSocketProxy.html#nextcloud-appapi-dsp) * [Nextcloud AIO](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/DockerSocketProxy.html#nextcloud-aio) * [Other implementations](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/DockerSocketProxy.html#other-implementations) * [GPU support](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/GpuSupport.html) * [How to enable GPU support for the Deploy daemon?](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/GpuSupport.html#how-to-enable-gpu-support-for-the-deploy-daemon) * [How to limit the number of GPUs per ExApp?](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/GpuSupport.html#how-to-limit-the-number-of-gpus-per-exapp) * [Scaling](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/Scaling.html) * [GPUs scaling](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/Scaling.html#gpus-scaling) * [Corporate Proxy - Permanent Settings for PHP CLI](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/BehindCompanyProxy.html) * [Symptoms](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/BehindCompanyProxy.html#symptoms) * [Cause](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/BehindCompanyProxy.html#cause) * [Permanent Solution](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/BehindCompanyProxy.html#permanent-solution) * [Troubleshooting](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/BehindCompanyProxy.html#troubleshooting) * [Contact Support](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/BehindCompanyProxy.html#contact-support) * [Troubleshooting](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/Troubleshooting.html) * [How to troubleshoot networking issues?](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/Troubleshooting.html#how-to-troubleshoot-networking-issues) * [ExApp deployment issues](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/Troubleshooting.html#exapp-deployment-issues) * [Failed to create volume](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/Troubleshooting.html#failed-to-create-volume) * [ExApps management list of apps from App Store is empty](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/faq/Troubleshooting.html#exapps-management-list-of-apps-from-app-store-is-empty) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Routing — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/stable/developer_manual/basics/index.html) * Routing * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/routing.rst) * * * Routing[](https://docs.nextcloud.com/server/stable/developer_manual/basics/routing.html#routing "Link to this heading") ========================================================================================================================= Routes map a URL and a method to a controller method. Routes are defined inside `appinfo/routes.php` by returning them as an array: \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \],\ \]; Added in version 29: You can also use attributes on the Controller method to define routes. They support all the same parameters (except for `name` which is not needed). `FrontpageRoute` has to be used for routes that were in the `routes` section and `ApiRoute` has to be used for routes that were in the `ocs` section. #\[FrontpageRoute(verb: 'GET', url: '/')\] The route array contains the following parts: * **url**: The URL that is matched after _/index.php/apps/myapp_ * **name**: The controller and the method to call; _page#index_ is being mapped to _PageController->index()_, _articles\_api#drop\_latest_ would be mapped to _ArticlesApiController->dropLatest()_. The controller in the example above would be stored in `lib/Controller/PageController.php`. This parameter is not needed for the attributes. * **verb** (Optional, defaults to GET): The HTTP method that should be matched, (e.g. GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH) * **requirements** (Optional): lets you match and extract URLs that have slashes in them (see [Matching subURLs](https://docs.nextcloud.com/server/stable/developer_manual/basics/routing.html#matching-suburls) ) * **postfix** (Optional): lets you define a route id postfix. Since each route name will be transformed to a route id (**page#method** -> **myapp.page.method**) and the route id can only exist once you can use the postfix option to alter the route id creation by adding a string to the route id, e.g., **‘name’ => ‘page#method’, ‘postfix’ => ‘test’** will yield the route id **myapp.page.methodtest**. This makes it possible to add more than one route/URL for a controller method * **defaults** (Optional): If this setting is given, a default value will be assumed for each URL parameter which is not present. The default values are passed in as a key => value pair array OCS routes[](https://docs.nextcloud.com/server/stable/developer_manual/basics/routing.html#ocs-routes "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------- Registering of OCS routes requires to use a [corresponding controller](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#ocscontroller) . Additionally, the route must be configured to be an OCS route in the router. To do so, you use the `ocs` key in the `routes.php` file instead of the key `routes`. The rest of the structure is the same. You can of course have both index.php and OCS routes. \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \],\ 'ocs' \=> \[\ \['name' \=> 'api#data', 'url' \=> '/v1/data', 'verb' \=> 'GET'\],\ \],\ \]; The prefix for OCS routes is `/ocs/v2.php/apps//`. So, the configured URL for the OCS endpoint in the example would be `/ocs/v2.php/apps//v1/data`. Added in version 29: Similar to `FrontpageRoute`, you can use `ApiRoute` as attribute to mark a route in the controller directly. This is equivalent to the configuration in the `routes.php` above. // In class ApiController that is a OCSController #\[ApiRoute(verb: 'GET', url: '/v1/data')\] function data() { /\* ... \*/ } Extracting values from the URL[](https://docs.nextcloud.com/server/stable/developer_manual/basics/routing.html#extracting-values-from-the-url "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- It is possible to extract values from the URL to allow RESTful URL design. To extract a value, you have to wrap it inside curly braces: 'author#show', 'url' \=> '/authors/{id}', 'verb' \=> 'GET'\], // controller/authorcontroller.php class AuthorController { public function show(string $id): Response { // $id is '3' } } The identifier used inside the route is being passed into controller method by reflecting the method parameters. So basically if you want to get the value **{id}** in your method, you need to add **$id** to your method parameters. Matching subURLs[](https://docs.nextcloud.com/server/stable/developer_manual/basics/routing.html#matching-suburls "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it is needed to match more than one URL fragment. An example would be to match a request for all URLs that start with **OPTIONS /index.php/apps/myapp/api**. To do this, use the **requirements** parameter in your route which is an array containing pairs of **‘key’ => ‘regex’**: 'author\_api#cors', 'url' \=> '/api/{path}', 'verb' \=> 'OPTIONS', 'requirements' \=> array('path' \=> '.+')), // controller/authorapicontroller.php class AuthorApiController { public function cors(string $path): Response { // $path will be 'my/route' } } Default values for subURL[](https://docs.nextcloud.com/server/stable/developer_manual/basics/routing.html#default-values-for-suburl "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Apart from matching requirements, a subURL may also have a default value. Say you want to support pagination (a ‘page’ parameter) for your **/posts** subURL that displays posts entries list. You may set a default value for the ‘page’ parameter, that will be used if not already set in the URL. Use the **defaults** parameter in your route which is an array containing pairs of **‘urlparameter’ => ‘defaultvalue’**: 'post#index', 'url' \=> '/post/{page}', 'verb' \=> 'GET', 'defaults' \=> array('page' \=> 1) // this allows same URL as /index.php/myapp/post/1 ), // controller/postcontroller.php class PostController { public function index(int $page \= 1): Response { // $page will be 1 } } Registering resources[](https://docs.nextcloud.com/server/stable/developer_manual/basics/routing.html#registering-resources "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- When dealing with resources, writing routes can become quite repetitive since most of the time routes for the following tasks are needed: * Get all entries * Get one entry by id * Create an entry * Update an entry * Delete an entry To prevent repetition, it’s possible to define resources. The following routes: \[\ \['name' \=> 'author#index', 'url' \=> '/authors', 'verb' \=> 'GET'\],\ \['name' \=> 'author#show', 'url' \=> '/authors/{id}', 'verb' \=> 'GET'\],\ \['name' \=> 'author#create', 'url' \=> '/authors', 'verb' \=> 'POST'\],\ \['name' \=> 'author#update', 'url' \=> '/authors/{id}', 'verb' \=> 'PUT'\],\ \['name' \=> 'author#destroy', 'url' \=> '/authors/{id}', 'verb' \=> 'DELETE'\],\ // your other routes here\ \],\ \]; can be abbreviated by using the **resources** key: \[\ 'author' \=> \['url' \=> '/authors'\],\ \],\ 'routes' \=> \[\ // your other routes here\ \],\ \]; Using the URLGenerator[](https://docs.nextcloud.com/server/stable/developer_manual/basics/routing.html#using-the-urlgenerator "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it is useful to turn a route into a URL to make the code independent from the URL design or to generate a URL for an image in **img/**. Inside the PageController the URL generator can be injected by adding it to the constructor, which will allow to use it to generate a URL for a redirect. For more details on that see the [Dependency injection](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#id2) reference. urlGenerator \= $urlGenerator; } /\*\* \* Redirects to /apps/news/myapp/authors/3 \*/ public function redirect(): RedirectResponse { // route name: author\_api#do\_something // route url: /apps/news/myapp/authors/{id} // # needs to be replaced with a . due to limitations and prefixed // with your app id $route \= 'myapp.author\_api.do\_something'; $parameters \= \['id' \=> 3\]; $url \= $this\->urlGenerator\->linkToRoute($route, $parameters); return new RedirectResponse($url); } } URLGenerator is case sensitive, so **appName** must match **exactly** the name you use in [configuration](https://docs.nextcloud.com/server/stable/developer_manual/basics/storage/configuration.html) . If you use a CamelCase name as _myCamelCaseApp_, \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \],\ \]; Added in version 29: You can also use attributes on the Controller method to define routes. They support all the same parameters (except for `name` which is not needed). `FrontpageRoute` has to be used for routes that were in the `routes` section and `ApiRoute` has to be used for routes that were in the `ocs` section. #\[FrontpageRoute(verb: 'GET', url: '/')\] The route array contains the following parts: * **url**: The URL that is matched after _/index.php/apps/myapp_ * **name**: The controller and the method to call; _page#index_ is being mapped to _PageController->index()_, _articles\_api#drop\_latest_ would be mapped to _ArticlesApiController->dropLatest()_. The controller in the example above would be stored in `lib/Controller/PageController.php`. This parameter is not needed for the attributes. * **verb** (Optional, defaults to GET): The HTTP method that should be matched, (e.g. GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH) * **requirements** (Optional): lets you match and extract URLs that have slashes in them (see [Matching subURLs](https://docs.nextcloud.com/server/32/developer_manual/basics/routing.html#matching-suburls) ) * **postfix** (Optional): lets you define a route id postfix. Since each route name will be transformed to a route id (**page#method** -> **myapp.page.method**) and the route id can only exist once you can use the postfix option to alter the route id creation by adding a string to the route id, e.g., **‘name’ => ‘page#method’, ‘postfix’ => ‘test’** will yield the route id **myapp.page.methodtest**. This makes it possible to add more than one route/URL for a controller method * **defaults** (Optional): If this setting is given, a default value will be assumed for each URL parameter which is not present. The default values are passed in as a key => value pair array OCS routes[](https://docs.nextcloud.com/server/32/developer_manual/basics/routing.html#ocs-routes "Link to this heading") --------------------------------------------------------------------------------------------------------------------------- Registering of OCS routes requires to use a [corresponding controller](https://docs.nextcloud.com/server/32/developer_manual/basics/controllers.html#ocscontroller) . Additionally, the route must be configured to be an OCS route in the router. To do so, you use the `ocs` key in the `routes.php` file instead of the key `routes`. The rest of the structure is the same. You can of course have both index.php and OCS routes. \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \],\ 'ocs' \=> \[\ \['name' \=> 'api#data', 'url' \=> '/v1/data', 'verb' \=> 'GET'\],\ \],\ \]; The prefix for OCS routes is `/ocs/v2.php/apps//`. So, the configured URL for the OCS endpoint in the example would be `/ocs/v2.php/apps//v1/data`. Added in version 29: Similar to `FrontpageRoute`, you can use `ApiRoute` as attribute to mark a route in the controller directly. This is equivalent to the configuration in the `routes.php` above. // In class ApiController that is a OCSController #\[ApiRoute(verb: 'GET', url: '/v1/data')\] function data() { /\* ... \*/ } Extracting values from the URL[](https://docs.nextcloud.com/server/32/developer_manual/basics/routing.html#extracting-values-from-the-url "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- It is possible to extract values from the URL to allow RESTful URL design. To extract a value, you have to wrap it inside curly braces: 'author#show', 'url' \=> '/authors/{id}', 'verb' \=> 'GET'\], // controller/authorcontroller.php class AuthorController { public function show(string $id): Response { // $id is '3' } } The identifier used inside the route is being passed into controller method by reflecting the method parameters. So basically if you want to get the value **{id}** in your method, you need to add **$id** to your method parameters. Matching subURLs[](https://docs.nextcloud.com/server/32/developer_manual/basics/routing.html#matching-suburls "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------- Sometimes it is needed to match more than one URL fragment. An example would be to match a request for all URLs that start with **OPTIONS /index.php/apps/myapp/api**. To do this, use the **requirements** parameter in your route which is an array containing pairs of **‘key’ => ‘regex’**: 'author\_api#cors', 'url' \=> '/api/{path}', 'verb' \=> 'OPTIONS', 'requirements' \=> array('path' \=> '.+')), // controller/authorapicontroller.php class AuthorApiController { public function cors(string $path): Response { // $path will be 'my/route' } } Default values for subURL[](https://docs.nextcloud.com/server/32/developer_manual/basics/routing.html#default-values-for-suburl "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------- Apart from matching requirements, a subURL may also have a default value. Say you want to support pagination (a ‘page’ parameter) for your **/posts** subURL that displays posts entries list. You may set a default value for the ‘page’ parameter, that will be used if not already set in the URL. Use the **defaults** parameter in your route which is an array containing pairs of **‘urlparameter’ => ‘defaultvalue’**: 'post#index', 'url' \=> '/post/{page}', 'verb' \=> 'GET', 'defaults' \=> array('page' \=> 1) // this allows same URL as /index.php/myapp/post/1 ), // controller/postcontroller.php class PostController { public function index(int $page \= 1): Response { // $page will be 1 } } Registering resources[](https://docs.nextcloud.com/server/32/developer_manual/basics/routing.html#registering-resources "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------- When dealing with resources, writing routes can become quite repetitive since most of the time routes for the following tasks are needed: * Get all entries * Get one entry by id * Create an entry * Update an entry * Delete an entry To prevent repetition, it’s possible to define resources. The following routes: \[\ \['name' \=> 'author#index', 'url' \=> '/authors', 'verb' \=> 'GET'\],\ \['name' \=> 'author#show', 'url' \=> '/authors/{id}', 'verb' \=> 'GET'\],\ \['name' \=> 'author#create', 'url' \=> '/authors', 'verb' \=> 'POST'\],\ \['name' \=> 'author#update', 'url' \=> '/authors/{id}', 'verb' \=> 'PUT'\],\ \['name' \=> 'author#destroy', 'url' \=> '/authors/{id}', 'verb' \=> 'DELETE'\],\ // your other routes here\ \],\ \]; can be abbreviated by using the **resources** key: \[\ 'author' \=> \['url' \=> '/authors'\],\ \],\ 'routes' \=> \[\ // your other routes here\ \],\ \]; Using the URLGenerator[](https://docs.nextcloud.com/server/32/developer_manual/basics/routing.html#using-the-urlgenerator "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it is useful to turn a route into a URL to make the code independent from the URL design or to generate a URL for an image in **img/**. Inside the PageController the URL generator can be injected by adding it to the constructor, which will allow to use it to generate a URL for a redirect. For more details on that see the [Dependency injection](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#id2) reference. urlGenerator \= $urlGenerator; } /\*\* \* Redirects to /apps/news/myapp/authors/3 \*/ public function redirect(): RedirectResponse { // route name: author\_api#do\_something // route url: /apps/news/myapp/authors/{id} // # needs to be replaced with a . due to limitations and prefixed // with your app id $route \= 'myapp.author\_api.do\_something'; $parameters \= \['id' \=> 3\]; $url \= $this\->urlGenerator\->linkToRoute($route, $parameters); return new RedirectResponse($url); } } URLGenerator is case sensitive, so **appName** must match **exactly** the name you use in [configuration](https://docs.nextcloud.com/server/32/developer_manual/basics/storage/configuration.html) . If you use a CamelCase name as _myCamelCaseApp_, news News An RSS/Atom feed reader An RSS/Atom feed reader 8.8.2 AGPL-3.0-or-later Bernhard Posselt multimedia https://github.com/nextcloud/news/issues A full blown example would look like this (needs to be utf-8 encoded): appinfo/info.xml[](https://docs.nextcloud.com/server/31/developer_manual/app_development/info.html#id3 "Link to this code") news Nachrichten News An RSS/Atom feed reader # Description\\nAn RSS/Atom feed reader 8.8.2 AGPL-3.0-or-later Bernhard Posselt Alessandro Cosentino Jan-Christoph Borchardt https://github.com/nextcloud/news/wiki#user-documentation https://github.com/nextcloud/news#readme https://github.com/nextcloud/news/wiki#developer-documentation multimedia tools https://github.com/nextcloud/news https://your.forum.com https://github.com/nextcloud/news/issues https://github.com/nextcloud/news https://example.com/1.png https://example.com/2.jpg pgsql sqlite mysql grep ls libxml curl SimpleXML iconv OCA\\DAV\\CardDAV\\Sync\\SyncJob OCA\\DAV\\Migration\\Classification OCA\\DAV\\Migration\\Classification OCA\\DAV\\Migration\\GenerateBirthdays OCA\\DAV\\Migration\\GenerateBirthdays OCA\\DAV\\Migration\\GenerateBirthdays OCA\\AuthF\\TwoFactor\\Provider A\\Php\\Class OCA\\Theming\\Settings\\Admin OCA\\Theming\\Settings\\Section OCA\\Files\\Activity\\Settings\\FavoriteAction OCA\\Files\\Activity\\Settings\\FileChanged OCA\\Files\\Activity\\Settings\\FileCreated OCA\\Files\\Activity\\Settings\\FileDeleted OCA\\Files\\Activity\\Settings\\FileFavorite OCA\\Files\\Activity\\Settings\\FileRestored OCA\\Files\\Activity\\Filter\\FileChanges OCA\\Files\\Activity\\Filter\\Favorites OCA\\Files\\Activity\\FavoriteProvider OCA\\Files\\Activity\\Provider files Files files.view.index 0 app.svg link OCA\\Circles\\Collaboration\\v1\\CollaboratorSearchPlugin The following tags are validated and used in the following way: id * required * must contain only lowercase ASCII characters and underscore * must match the first folder in the archive * will be used to identify the app name * required * must occur at least once with **lang=”en”** or no lang attribute * can be translated by using multiple elements with different **lang** attribute values, language code needs to be set **lang** attribute * will be rendered on the app detail page summary * optional * if not provided the description element’s text will be used * must occur at least once with **lang=”en”** or no lang attribute * can be translated by using multiple elements with different **lang** attribute values, language code needs to be set **lang** attribute * will be rendered on the app list page as short description description * required * must occur at least once with **lang=”en”** or no lang attribute * can contain Markdown * can be translated by using multiple elements with different **lang** attribute values, language code needs to be set **lang** attribute * will be rendered on the app detail page version * required * must be a [semantic version](http://semver.org/) without build metadata, e.g. 9.0.1 or 9.1.0-alpha.1 * [more info on app versioning](https://docs.nextcloud.com/server/31/developer_manual/app_publishing_maintenance/release_process.html#app-versioning) licence * required * can occur multiple times with different licenses * must contain one of the following licenses (for apps targeting v31 or higher, see the [SPDX License List](https://spdx.org/licenses/) for details): > * **AGPL-3.0-only** > > * **AGPL-3.0-or-later** > > * **Apache-2.0** > > * **GPL-3.0-only** > > * **GPL-3.0-or-later** > > * **MIT** > > * **MPL-2.0** > * (deprecated, for apps targeting v30 or lower) the following shorthand aliases are also used: > * **agpl** (AGPL-3.0) > > * **apache** (Apache-2.0) > > * **gpl3** (GPL-3.0) > > * **mit** (MIT) > > * **mpl** (MPL-2.0) > author * required * can occur multiple times with different authors * can contain a **mail** attribute which must be an email * can contain a **homepage** which must be a URL * will not (yet) be rendered on the App Store * will be provided through the REST API documentation/user * optional * must contain a URL to the user documentation * will be rendered on the app detail page documentation/admin * optional * must contain a URL to the admin documentation * will be rendered on the app detail page documentation/developer * optional * must contain a URL to the developer documentation * will be rendered on the app detail page category * optional * if not provided the category **tools** will be used * must contain one of the following values: > * **customization** > > * **files** > > * **games** > > * **integration** > > * **monitoring** > > * **multimedia** > > * **office** > > * **organization** > > * **security** > > * **social** > > * **tools** > * old categories are migrated: > * **auth** will be converted to **security** > * can occur more than once with different categories website * optional * must contain a URL to the project’s homepage * will be rendered on the app detail page discussion * optional * must contain a URL to the project’s discussion page/forum * will be rendered on the app detail page as the “ask question or discuss” button * if absent, it will default to our forum at [https://help.nextcloud.com/](https://help.nextcloud.com/) bugs * required * must contain a URL to the project’s bug tracker * will be rendered on the app detail page repository * optional * must contain a URL to the project’s repository * can contain a **type** attribute, **git**, **mercurial**, **subversion** and **bzr** are allowed values, defaults to **git** * currently not used screenshot * optional * must contain an HTTPS URL to an image * can contain a **small-thumbnail** attribute which must contain an https url to an image. This image will be used as small preview (e.g. on the app list overview). Keep it small so it renders fast * will be rendered on the app list and detail page in the given order dependencies/php * optional * can contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) * can contain a **min-int-size** attribute, 32 or 64 are allowed as valid values * will be rendered on the app releases page dependencies/database * optional * must contain the database name as text, **sqlite**, **pgsql** and **mysql** are allowed as valid values * can occur multiple times with different databases * can contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) * will be rendered on the app releases page dependencies/command * optional * must contain a linux command as text value * can occur multiple times with different commands * will be rendered on the app releases page dependencies/lib * optional * will be rendered on the app releases page * must contain a required php extension * can occur multiple times with different php extensions * can contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) dependencies/nextcloud * required on Nextcloud 11 or higher * if absent white-listed owncloud versions will be taken from the owncloud element (see below) * must contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) Note Dependencies dependencies/php, dependencies/database and dependencies/lib are checked at installation time (not on update time), hence applications need to stick to the dependencies supported by a major version of Nextcloud the moment an app releases support for that version, i.e. app needs to support the same PHP version-range the supported Nextcloud version supports. background-jobs/job * optional * must contain a php class which is run as background jobs * will not be used, only validated repair-steps/pre-migration/step * optional * must contain a php class which is run before executing database migrations * will not be used, only validated repair-steps/post-migration/step * optional * must contain a php class which is run after executing database migrations * will not be used, only validated repair-steps/live-migration/step * optional * must contain a php class which is run after executing post-migration jobs * will not be used, only validated repair-steps/install/step * optional * must contain a php class which is run after installing the app * will not be used, only validated repair-steps/uninstall/step * optional * must contain a php class which is run after uninstalling the app * will not be used, only validated two-factor-providers/provider * optional * must contain a php class which is registered as two factor auth provider * will not be used, only validated commands/command * optional * must contain a php class which is registered as occ command * will not be used, only validated activity/settings/setting * optional * must contain a php class which implements OCPActivityISetting and is used to add additional settings ui elements to the activity app activity/filters/filter * optional * must contain a php class which implements OCPActivityIFilter and is used to add additional filters to the activity app activity/providers/provider * optional * must contain a php class which implements OCPActivityIProvider and is used to react to events from the activity app settings/admin * optional * must contain a php class which implements OCPSettingsISettings and returns the form to render for the global settings area settings/admin-section * optional * must contain a php class which implements OCPSettingsISection and returns data to render navigation entries in the global settings area navigations * optional * must contain at least one navigation element navigations/navigation * required * must contain a name and route element * denotes a navigation entry * role denotes the visibility, all means everyone can see it, admin means only an admin can see the navigation entry, defaults to all navigations/navigation/id * optional * the app id * you can also create entries for other apps by setting an id other than your app one’s navigations/navigation/name * required * will be displayed below the navigation entry icon * will be translated by the default translation tools navigations/navigation/route * required * name of the route that will be used to generate the link navigations/navigation/icon * optional * name of the icon which is looked up in the app’s **img/** folder * defaults to app.svg navigations/navigation/order * optional * used to sort the navigation entries * a higher order number means that the entry will be ordered further to the bottom navigations/navigation/type * optional * can be either link or settings * link means that the entry is added to the default app menu * settings means that the entry is added to the right-side menu which also contains the personal, admin, users, help and logout entry collaboration * optional * can contain plugins for collaboration search (e.g. supplying share dialog) collaboration/plugins * optional * must contain at least one plugin collaboration/plugins/plugin * required * the PHP class name of the plugin * must contain **type** attribute (currently only _collaboration-search_). The class must implement OCPCollaborationCollaboratorsISearchPlugin. * must contain **share-type** attribute, according to the specific OCPShare constants The following character maximum lengths are enforced: * All description Strings are database text fields and therefore not limited in size * All other Strings have a maximum of 256 characters The following elements are either deprecated or for internal use only and will fail the validation if present: * **standalone** * **default\_enable** * **shipped** * **public** * **remote** * **requiremin** * **requiremax** Changelog[](https://docs.nextcloud.com/server/31/developer_manual/app_development/info.html#changelog "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------- Apps can provide a changelog. This should be written in the [keep a changelog](https://keepachangelog.com/) . If the apps provide a `CHANGELOG.md` file in the project root, this file will be used to show changes for the released version in the app store and for administrators in the app settings. Moreover, since Nextcloud 29, if the `updatenotification` app is enabled, apps can also provide a changelog for the users. The app will notify users about after the app update if either a `CHANGELOG.language.md` (where `language` is the language code of that user) or a fallback `CHANGELOG.en.md` is available. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Introduction — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/index.html) * Introduction * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/Introduction.rst) * * * Introduction[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/Introduction.html#introduction "Link to this heading") =================================================================================================================================================== **ExApps** (short for “External Apps”) are Nextcloud apps that are developed in another programming language (outside of PHP) using the AppAPI OCS API. [AppAPI](https://apps.nextcloud.com/apps/app_api) is a project introduced by Nextcloud to revolutionize the process of application development within the Nextcloud ecosystem. Overview[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/Introduction.html#overview "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------- The main tasks of the AppAPI ecosystem are: > * Providing a reliable and fast method for authenticating applications > > * Supporting various application deployment options > > * Offering a clear and straightforward application administration interface > > * Ensuring a reliable implementation of all the necessary missing APIs for applications > > * Supplying clear, understandable documentation and support on how to implement libraries in other programming languages for writing next-gen applications for Nextcloud > The system should support the expansion and integration of new deployment methods, avoiding any tight coupling with a specific deployment type. Applications should be capable of indicating the deployment methods they can accommodate. Given the evolving landscape of new technologies and the potential emergence of more intricate or simplified deployment options, the system is architected to seamlessly embrace the integration of novel deployment modes. If you have any questions or corrections regarding the documentation, we would be glad to address them in discussions, incorporate corrections through pull requests, and handle complex problems through issues. Glossary[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/Introduction.html#glossary "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------- AppAPI brings out the following terms frequently used in the code: * `ExApp` (External App) - the app on another (from PHP) programming language, which uses AppAPI OCS API * `DaemonConfig` - configuration of orchestration daemon (e.g. Docker) where ExApps are deployed * `DeployConfig` - additional DaemonConfig options for orchestrator (e.g. network) and ExApps (nextcloud\_url, host, etc.) * `ExAppConfig` - similar to Nextcloud app\_config, but for ExApps configuration * `ExAppPreferences` - similar to Nextcloud app\_preferences, user-specific settings for ExApps * `AppAPIAuth` - AppAPI authentication * `FileActionsMenu` - entry in files actions menu (context menu) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Setting up dev environment — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/index.html) * Setting up dev environment * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/DevSetup.rst) * * * Setting up dev environment[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/DevSetup.html#setting-up-dev-environment "Link to this heading") ======================================================================================================================================================================= AppAPI development requires a Nextcloud development environment setup. We highly recommend using [Julius Knorr’s Docker setup](https://github.com/juliusknorr/nextcloud-docker-dev) for this. For an alternate environment without using Docker, please refer to the setup instructions in [Getting started](https://docs.nextcloud.com/server/31/developer_manual/getting_started/devenv.html) . Suggested IDE: **PhpStorm**, though you can certainly use any IDE of your preference such as **VS Code** or **Vim**. Install AppAPI[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/DevSetup.html#install-appapi "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------- All ExApps require the [AppAPI](https://apps.nextcloud.com/apps/app_api) Nextcloud app as a dependency. As of Nextcloud version 30.0.1, AppAPI is automatically installed by default. If you prefer, you can also build the latest development version of AppAPI from the source code, in which case uninstall the release version of AppAPI and perform the following steps. Clone the latest main branch: > git clone https://github.com/nextcloud/app\_api.git && cd app\_api or clone a specific version by specifying the version tag: > git clone https://github.com/nextcloud/app\_api.git \--branch && cd app\_api where `` is the version you want to install. Then, build frontend assets in development mode: > npm ci && npm run dev Enable AppAPI from the directory where the `occ` command resides: > ./occ app:enable \--force app\_api ### Deploy daemons types[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/DevSetup.html#deploy-daemons-types "Link to this heading") There are two types of Deploy daemons that can be used for development and testing of ExApps: 1. `manual_install`: This type of Deploy daemon is running manually in the host machine. This is useful for ExApp development as you can run your ExApp directly on the host. 2. `docker_install`: This type of Deploy daemon is running in a Docker container. You can register (create) these daemons in the AppAPI admin settings. For the equivalent `occ` command or an explanation of the Deploy daemon parameters, see [DaemonConfig registration](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/tech_details/Deployment.html#occ-daemon-config-registration) . ### Docker Socket Proxy[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/DevSetup.html#docker-socket-proxy "Link to this heading") For development and testing locally, the simplest way is to use the [Nextcloud AppAPI DSP HTTP](https://github.com/nextcloud/docker-socket-proxy?tab=readme-ov-file#httplocal) . In Place of a Conclusion[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/DevSetup.html#in-place-of-a-conclusion "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- There are several make commands available to ease frequent development actions. To see the complete list, execute `make help`. ### Docker remote API[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/DevSetup.html#docker-remote-api "Link to this heading") The Docker Engine remote API can be easily configured via `make dock2port` command. The command will create a docker container to provide remote Docker Engine API. Afterward, register DaemonConfigs in Nextcloud using `make dock-port` command. ### Docker by socket[](https://docs.nextcloud.com/server/31/developer_manual/exapp_development/DevSetup.html#docker-by-socket "Link to this heading") For Docker via socket, use the command `make dock-sock`. This registers DaemonConfigs in Nextcloud for the default socket connection (`/var/run/docker.sock`). Make sure that socket has enough permissions for Nextcloud and webserver user to access it and actually forwarded to the container: ... volumes: ... \- /var/run/docker.sock:/var/run/docker.sock ... ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Translation setup — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/31/developer_manual/app_development/index.html) * Translation setup * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/translation_setup.rst) * * * Translation setup[](https://docs.nextcloud.com/server/31/developer_manual/app_development/translation_setup.html#translation-setup "Link to this heading") ============================================================================================================================================================ Nextcloud’s translation system is powered by [Transifex](https://explore.transifex.com/nextcloud/) . To start translating sign up and enter a group. If your community app should be translated by the [Nextcloud community on Transifex](https://explore.transifex.com/nextcloud/) just follow the setup section below. Translation tool[](https://docs.nextcloud.com/server/31/developer_manual/app_development/translation_setup.html#translation-tool "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------- Note The tool-based translation currently only supports repositories hosted on `github.com`. If your app is hosted elsewhere, you can try to follow the [Manual translation](https://docs.nextcloud.com/server/31/developer_manual/app_development/translation_setup.html#manual-translation) instead. The [translation tool](https://github.com/nextcloud/docker-ci/tree/master/translations/translationtool) scrapes the source code for method calls to `t()` or `n()` to extract the strings that should be translated. If you check in minified JS code for example then those method names are also quite common and could cause wrong extractions. For this reason we allow to specify a list of files that the translation tool will not scrape for strings. You simply need to add a file named `.l10nignore` into the root folder of your app and specify the files one per line: \# compiled vue templates js/bruteforcesettings.js Setup of the transifex sync[](https://docs.nextcloud.com/server/31/developer_manual/app_development/translation_setup.html#setup-of-the-transifex-sync "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### Transifex configuration `.tx/config`[](https://docs.nextcloud.com/server/31/developer_manual/app_development/translation_setup.html#transifex-configuration-tx-config "Link to this heading") To setup the transifex sync within the Nextcloud community you need to add first the transifex config to your app folder at `.tx/config` (please replace `MYAPP` with your apps id): \[main\] host \= https://www.transifex.com lang\_map \= hu\_HU: hu, nb\_NO: nb, sk\_SK: sk, th\_TH: th, ja\_JP: ja, bg\_BG: bg, cs\_CZ: cs, fi\_FI: fi \[o:nextcloud:p:nextcloud:r:{{APPID}}\] file\_filter \= translationfiles//{{APPID}}.po source\_file \= translationfiles/templates/{{APPID}}.pot source\_lang \= en type \= PO Then create a folder `l10n` and a file `l10n/.gitkeep` to create an empty folder which later holds the translations. ### Branch selection `.tx/backport`[](https://docs.nextcloud.com/server/31/developer_manual/app_development/translation_setup.html#branch-selection-tx-backport "Link to this heading") The bot will run every night and only push commits to the following branches branch once there is an update to the translation: * main * master * stableX (X being the recent 3 versions of Nextcloud Server) You can overwrite this list by creating a file `.tx/backport` in your repository with the following content: develop stable That would sync the translations for the branches (`main` and `master` are added automatically): * main * master * develop * stable ### Excluding files `.l10nignore`[](https://docs.nextcloud.com/server/31/developer_manual/app_development/translation_setup.html#excluding-files-l10nignore "Link to this heading") Add one more file called `.l10nignore` in root of the repository and the files and folders to ignore for translations. This should be used to exclude files that create false-positive translations, such as: * Compiled JavaScript files `js/` * 3rd-party PHP dependencies `vendor/` * Non-shipped files and documentation `docs/` ### Validate source strings[](https://docs.nextcloud.com/server/31/developer_manual/app_development/translation_setup.html#validate-source-strings "Link to this heading") After finishing the setup, you can validate the translation source strings which outlines some common mistakes. Clone the [nextcloud/docker-ci](https://github.com/nextcloud/docker-ci/) repository and afterwards run the following script: bash translations/validateSyncSetup.sh Owner Repository ### Repository permissions[](https://docs.nextcloud.com/server/31/developer_manual/app_development/translation_setup.html#repository-permissions "Link to this heading") Now the GitHub account [@nextcloud-bot](https://github.com/nextcloud-bot) needs to get `write` access to your repository. You can invite it from your repository settings: https://github.com///settings/access After sending the invitation, please [open a ticket using the “Request translations” template](https://github.com/nextcloud/docker-ci/issues/new/choose) . Attention In general you should enable the [protected branches feature](https://help.github.com/articles/configuring-protected-branches/) for default and stable branches. If you do that, you need to grant the [@nextcloud-bot](https://github.com/nextcloud-bot) `admin` permissions and allow administrators to bypass the protection. This feature however is only possible for repositories owned by organizations, not in repositories owned by individuals! You can [create your own organization](https://docs.github.com/en/organizations/collaborating-with-groups-in-organizations/creating-a-new-organization-from-scratch) If you need help just [open a ticket with the request](https://github.com/nextcloud/docker-ci/issues/new/choose) and we can also guide you through the steps. Manual translation[](https://docs.nextcloud.com/server/31/developer_manual/app_development/translation_setup.html#manual-translation "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------- If Transifex is not the right choice or the app is not accepted for translation, generate the gettext strings by yourself by executing our [translation tool](https://github.com/nextcloud/docker-ci/tree/master/translations/translationtool) in the app folder: cd /srv/http/nextcloud/apps/myapp translationtool.phar create\-pot\-files The translation tool requires `gettext`, installable via: apt\-get install gettext The above tool generates a template that can be used to translate all strings of an app. This template is located in the folder `translationfiles/template/` with the name `myapp.pot`. It can be used by your favored translation tool such as [Poedit](https://poedit.net/) . It then creates a `.po` file. The `.po` file needs to be placed in a folder named like the language code with the app name as filename - for example `translationfiles/es/myapp.po`. After this step the tool needs to be invoked to transfer the po file into our own fileformat that is more easily readable by the server code: translationtool.phar convert\-po\-files Now the following folder structure is available: myapp/l10n |-- es.js |-- es.json myapp/translationfiles |-- es | |-- myapp.po |-- templates |-- myapp.pot You then just need the `.json` and `.js` files for a working localized app. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Introduction — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/index.html) * Introduction * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/Introduction.rst) * * * Introduction[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/Introduction.html#introduction "Link to this heading") =============================================================================================================================================== **ExApps** (short for “External Apps”) are Nextcloud apps that are developed in another programming language (outside of PHP) using the AppAPI OCS API. [AppAPI](https://apps.nextcloud.com/apps/app_api) is a project introduced by Nextcloud to revolutionize the process of application development within the Nextcloud ecosystem. Overview[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/Introduction.html#overview "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------- The main tasks of the AppAPI ecosystem are: > * Providing a reliable and fast method for authenticating applications > > * Supporting various application deployment options > > * Offering a clear and straightforward application administration interface > > * Ensuring a reliable implementation of all the necessary missing APIs for applications > > * Supplying clear, understandable documentation and support on how to implement libraries in other programming languages for writing next-gen applications for Nextcloud > The system should support the expansion and integration of new deployment methods, avoiding any tight coupling with a specific deployment type. Applications should be capable of indicating the deployment methods they can accommodate. Given the evolving landscape of new technologies and the potential emergence of more intricate or simplified deployment options, the system is architected to seamlessly embrace the integration of novel deployment modes. If you have any questions or corrections regarding the documentation, we would be glad to address them in discussions, incorporate corrections through pull requests, and handle complex problems through issues. Glossary[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/Introduction.html#glossary "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------- AppAPI brings out the following terms frequently used in the code: * `ExApp` (External App) - the app on another (from PHP) programming language, which uses AppAPI OCS API * `DaemonConfig` - configuration of orchestration daemon (e.g. Docker) where ExApps are deployed * `DeployConfig` - additional DaemonConfig options for orchestrator (e.g. network) and ExApps (nextcloud\_url, host, etc.) * `ExAppConfig` - similar to Nextcloud app\_config, but for ExApps configuration * `ExAppPreferences` - similar to Nextcloud app\_preferences, user-specific settings for ExApps * `AppAPIAuth` - AppAPI authentication * `FileActionsMenu` - entry in files actions menu (context menu) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Middlewares — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/stable/developer_manual/basics/index.html) * Middlewares * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/middlewares.rst) * * * Middlewares[](https://docs.nextcloud.com/server/stable/developer_manual/basics/middlewares.html#middlewares "Link to this heading") ===================================================================================================================================== Middleware is logic that is run before and after each request and is modeled after [Django’s Middleware system](https://docs.djangoproject.com/en/dev/topics/http/middleware/) . It offers the following hooks: * `beforeController`: This is executed before a controller method is being executed. This allows you to plug additional checks or logic before that method, like for instance security checks * `afterException`: This is being run when either the beforeController method or the controller method itself is throwing an exception. The middleware is asked in reverse order to handle the exception and to return a response. If the middleware can’t handle the exception, it throws the exception again * `afterController`: This is being run after a successful controller method call and allows the manipulation of a Response object. The middleware is run in reverse order * `beforeOutput`: This is being run after the response object has been rendered and allows the manipulation of the outputted text. The middleware is run in reverse order ![Middleware flow chart](https://docs.nextcloud.com/server/stable/developer_manual/_images/middleware-flow-horiz.png) To generate your own middleware, simply inherit from the Middleware class and overwrite the methods that should be used. registerMiddleware(CensorMiddleware::class); } public function boot(IBootContext $context): void {} } Global Middlewares[](https://docs.nextcloud.com/server/stable/developer_manual/basics/middlewares.html#global-middlewares "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------- Added in version 26. Registered middleware will only intercept requests of the same app by default. To make a middleware _global_ and trigger for other apps’ middleware, add true as the second argument of the `registerMiddleware` call: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/stable/developer_manual/basics/middlewares.html#id3 "Link to this code") registerMiddleware(MonitoringMiddleware::class, true); } public function boot(IBootContext $context): void {} } Dependency Injection Container Registration[](https://docs.nextcloud.com/server/stable/developer_manual/basics/middlewares.html#dependency-injection-container-registration "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Deprecated since version 20. Middleware can also be added using the **registerMiddleware** method of the container: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/stable/developer_manual/basics/middlewares.html#id4 "Link to this code") getContainer(); // executed in the order that it is registered $container\->registerMiddleware(CensorMiddleware::class); } } Note The order is important! The middleware that is registered first gets run first in the **beforeController** method. For all other hooks, the order is being reversed, meaning: if a middleware is registered first, it gets run last. Parsing annotations[](https://docs.nextcloud.com/server/stable/developer_manual/basics/middlewares.html#parsing-annotations "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it is useful to conditionally execute code before or after a controller method. This can be done by defining custom annotations. An example would be to add a custom authentication method or simply add an additional header to the response. To access the parsed annotations, inject the **ControllerMethodReflector** class: reflector \= $reflector; } /\*\* \* Add custom header if @MyHeader is used \*/ public function afterController($controller, $methodName, Response $response): Response { if($this\->reflector\->hasAnnotation('MyHeader')) { $response\->addHeader('My-Header', 3); } return $response; } } Note An annotation always starts with an uppercase letter ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Tutorial — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/32/developer_manual/app_development/index.html) * Tutorial * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/tutorial.rst) * * * Tutorial[](https://docs.nextcloud.com/server/32/developer_manual/app_development/tutorial.html#tutorial "Link to this heading") ================================================================================================================================= To help you get started on Nextcloud app development we have compiled a comprehensive set of tutorials that cover everything from setting up your development environment to developing a full fledged app with database storage. Please head [here](https://cloud.nextcloud.com/s/iyNGp8ryWxc7Efa?path=%2F) to get started. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Technical details — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/index.html) * Technical details * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/tech_details/index.rst) * * * Technical details[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/index.html#technical-details "Link to this heading") =================================================================================================================================================================== * [App Installation Flow](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/InstallationFlow.html) * [Image Pulling (Docker)](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/InstallationFlow.html#image-pulling-docker) * [Heartbeat](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/InstallationFlow.html#heartbeat) * [Init](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/InstallationFlow.html#init) * [Enabled](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/InstallationFlow.html#enabled) * [Deployment](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Deployment.html) * [Overview](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Deployment.html#overview) * [DaemonConfig registration](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Deployment.html#daemonconfig-registration) * [ExApp registration](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Deployment.html#exapp-registration) * [Application installation scheme](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Deployment.html#application-installation-scheme) * [ExApp info.xml schema](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Deployment.html#exapp-info-xml-schema) * [Authentication](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Authentication.html) * [Authentication flow](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Authentication.html#authentication-flow) * [Authentication headers](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Authentication.html#authentication-headers) * [AppAPIAuth](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Authentication.html#appapiauth) * [AppAPI session keys](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Authentication.html#appapi-session-keys) * [Translations](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Translations.html) * [Front-end](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Translations.html#front-end) * [Back-end](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Translations.html#back-end) * [Manual translations](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Translations.html#manual-translations) * [Manual install](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Translations.html#manual-install) * [Docker install](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Translations.html#docker-install) * [Translation tool](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Translations.html#translation-tool) * [AppAPI Nextcloud APIs](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/index.html) * [Logging](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/logging.html) * [AppConfig](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/appconfig.html) * [Preferences](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/preferences.html) * [ExApp](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/exapp.html) * [Routes](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/routes.html) * [Miscellaneous OCS APIs](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/utils.html) * [File Actions Menu](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/fileactionsmenu.html) * [Top Menu Entry](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/topmenu.html) * [Declarative Settings](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/settings.html) * [Notifications](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/notifications.html) * [Events Listener](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/events_listener.html) * [OCC Command](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/occ_command.html) * [Talk bots](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/talkbots.html) * [Other OCS APIs](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/api/other_ocs.html) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Development overview — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/index.html) * Development overview * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/development_overview/index.rst) * * * Development overview[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/index.html#development-overview "Link to this heading") ================================================================================================================================================================================= This section contains the most common information for ExApp developers, grouped from other parts of documentation. * [ExApp development](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html) * [0\. Setting up the development environment](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#setting-up-the-development-environment) * [1\. Starting from template](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#starting-from-template) * [3\. Development](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#development) * [4\. Packaging](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#packaging) * [5\. AppStore publishing](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#appstore-publishing) * [6\. Testing](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#testing) * [ExApp overview](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppOverview.html) * [ExApp structure](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppOverview.html#exapp-structure) * [Backend](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppOverview.html#backend) * [Frontend](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppOverview.html#frontend) * [L10n translations](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppOverview.html#l10n-translations) * [Makefile](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppOverview.html#makefile) * [ExApp lifecycle](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppLifecycle.html) * [ExApp lifecycle methods](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#exapp-lifecycle-methods) * [ExApp lifecycle scheme](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#exapp-lifecycle-scheme) * [Nextcloud-side ExApp lifecycle methods](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#nextcloud-side-exapp-lifecycle-methods) * [AppAPI Authentication](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#appapi-authentication) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Development overview — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/index.html) * Development overview * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/development_overview/index.rst) * * * Development overview[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/index.html#development-overview "Link to this heading") ============================================================================================================================================================================= This section contains the most common information for ExApp developers, grouped from other parts of documentation. * [ExApp development](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html) * [0\. Setting up the development environment](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#setting-up-the-development-environment) * [1\. Starting from template](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#starting-from-template) * [3\. Development](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#development) * [4\. Packaging](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#packaging) * [5\. AppStore publishing](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#appstore-publishing) * [6\. Testing](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppDevelopmentSteps.html#testing) * [ExApp overview](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppOverview.html) * [ExApp structure](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppOverview.html#exapp-structure) * [Backend](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppOverview.html#backend) * [Frontend](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppOverview.html#frontend) * [L10n translations](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppOverview.html#l10n-translations) * [Makefile](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppOverview.html#makefile) * [ExApp lifecycle](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppLifecycle.html) * [ExApp lifecycle methods](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#exapp-lifecycle-methods) * [ExApp lifecycle scheme](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#exapp-lifecycle-scheme) * [Nextcloud-side ExApp lifecycle methods](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#nextcloud-side-exapp-lifecycle-methods) * [AppAPI Authentication](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/development_overview/ExAppLifecycle.html#appapi-authentication) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Frequently Asked Questions — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/index.html) * Frequently Asked Questions * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/faq/index.rst) * * * Frequently Asked Questions[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/index.html#frequently-asked-questions "Link to this heading") ============================================================================================================================================================================ This section contains the most common or problematic questions that users or developers may encounter when working with AppAPI. It can be used as pointer to other parts of the documentation, as it usually refers to, or provide a brief answer. Note This section will be updated with time, as new questions arise. If you have a question that is not listed here or the answer is not enough for you, please feel free to ask it by creating an issue in the [AppAPI repository](https://github.com/nextcloud/app_api/issues) . * [Docker Container Registry](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/DockerContainerRegistry.html) * [How to use a private Docker container registry with authentication?](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/DockerContainerRegistry.html#how-to-use-a-private-docker-container-registry-with-authentication) * [Docker Socket Proxy](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/DockerSocketProxy.html) * [Nextcloud AppAPI DSP](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/DockerSocketProxy.html#nextcloud-appapi-dsp) * [Nextcloud AIO](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/DockerSocketProxy.html#nextcloud-aio) * [Other implementations](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/DockerSocketProxy.html#other-implementations) * [GPU support](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/GpuSupport.html) * [How to enable GPU support for the Deploy daemon?](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/GpuSupport.html#how-to-enable-gpu-support-for-the-deploy-daemon) * [How to limit the number of GPUs per ExApp?](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/GpuSupport.html#how-to-limit-the-number-of-gpus-per-exapp) * [Scaling](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/Scaling.html) * [GPUs scaling](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/Scaling.html#gpus-scaling) * [Corporate Proxy - Permanent Settings for PHP CLI](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/BehindCompanyProxy.html) * [Symptoms](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/BehindCompanyProxy.html#symptoms) * [Cause](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/BehindCompanyProxy.html#cause) * [Permanent Solution](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/BehindCompanyProxy.html#permanent-solution) * [Troubleshooting](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/BehindCompanyProxy.html#troubleshooting) * [Contact Support](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/BehindCompanyProxy.html#contact-support) * [Troubleshooting](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/Troubleshooting.html) * [How to troubleshoot networking issues?](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/Troubleshooting.html#how-to-troubleshoot-networking-issues) * [ExApp deployment issues](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/Troubleshooting.html#exapp-deployment-issues) * [Failed to create volume](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/Troubleshooting.html#failed-to-create-volume) * [ExApps management list of apps from App Store is empty](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/faq/Troubleshooting.html#exapps-management-list-of-apps-from-app-store-is-empty) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Frequently Asked Questions — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/index.html) * Frequently Asked Questions * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/faq/index.rst) * * * Frequently Asked Questions[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/index.html#frequently-asked-questions "Link to this heading") ======================================================================================================================================================================== This section contains the most common or problematic questions that users or developers may encounter when working with AppAPI. It can be used as pointer to other parts of the documentation, as it usually refers to, or provide a brief answer. Note This section will be updated with time, as new questions arise. If you have a question that is not listed here or the answer is not enough for you, please feel free to ask it by creating an issue in the [AppAPI repository](https://github.com/nextcloud/app_api/issues) . * [Docker Container Registry](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/DockerContainerRegistry.html) * [How to use a private Docker container registry with authentication?](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/DockerContainerRegistry.html#how-to-use-a-private-docker-container-registry-with-authentication) * [Docker Socket Proxy](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/DockerSocketProxy.html) * [Nextcloud AppAPI DSP](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/DockerSocketProxy.html#nextcloud-appapi-dsp) * [Nextcloud AIO](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/DockerSocketProxy.html#nextcloud-aio) * [Other implementations](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/DockerSocketProxy.html#other-implementations) * [GPU support](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/GpuSupport.html) * [How to enable GPU support for the Deploy daemon?](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/GpuSupport.html#how-to-enable-gpu-support-for-the-deploy-daemon) * [How to limit the number of GPUs per ExApp?](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/GpuSupport.html#how-to-limit-the-number-of-gpus-per-exapp) * [Scaling](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/Scaling.html) * [GPUs scaling](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/Scaling.html#gpus-scaling) * [Corporate Proxy - Permanent Settings for PHP CLI](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/BehindCompanyProxy.html) * [Symptoms](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/BehindCompanyProxy.html#symptoms) * [Cause](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/BehindCompanyProxy.html#cause) * [Permanent Solution](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/BehindCompanyProxy.html#permanent-solution) * [Troubleshooting](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/BehindCompanyProxy.html#troubleshooting) * [Contact Support](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/BehindCompanyProxy.html#contact-support) * [Troubleshooting](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/Troubleshooting.html) * [How to troubleshoot networking issues?](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/Troubleshooting.html#how-to-troubleshoot-networking-issues) * [ExApp deployment issues](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/Troubleshooting.html#exapp-deployment-issues) * [Failed to create volume](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/Troubleshooting.html#failed-to-create-volume) * [ExApps management list of apps from App Store is empty](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/faq/Troubleshooting.html#exapps-management-list-of-apps-from-app-store-is-empty) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Technical details — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/index.html) * Technical details * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/tech_details/index.rst) * * * Technical details[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/index.html#technical-details "Link to this heading") =============================================================================================================================================================== * [App Installation Flow](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/InstallationFlow.html) * [Image Pulling (Docker)](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/InstallationFlow.html#image-pulling-docker) * [Heartbeat](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/InstallationFlow.html#heartbeat) * [Init](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/InstallationFlow.html#init) * [Enabled](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/InstallationFlow.html#enabled) * [Deployment](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Deployment.html) * [Overview](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Deployment.html#overview) * [DaemonConfig registration](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Deployment.html#daemonconfig-registration) * [ExApp registration](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Deployment.html#exapp-registration) * [Application installation scheme](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Deployment.html#application-installation-scheme) * [ExApp info.xml schema](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Deployment.html#exapp-info-xml-schema) * [Authentication](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Authentication.html) * [Authentication flow](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Authentication.html#authentication-flow) * [Authentication headers](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Authentication.html#authentication-headers) * [AppAPIAuth](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Authentication.html#appapiauth) * [AppAPI session keys](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Authentication.html#appapi-session-keys) * [Translations](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Translations.html) * [Front-end](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Translations.html#front-end) * [Back-end](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Translations.html#back-end) * [Manual translations](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Translations.html#manual-translations) * [Manual install](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Translations.html#manual-install) * [Docker install](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Translations.html#docker-install) * [Translation tool](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Translations.html#translation-tool) * [AppAPI Nextcloud APIs](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/index.html) * [Logging](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/logging.html) * [AppConfig](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/appconfig.html) * [Preferences](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/preferences.html) * [ExApp](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/exapp.html) * [Routes](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/routes.html) * [Miscellaneous OCS APIs](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/utils.html) * [File Actions Menu](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/fileactionsmenu.html) * [Top Menu Entry](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/topmenu.html) * [Declarative Settings](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/settings.html) * [Notifications](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/notifications.html) * [Events Listener](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/events_listener.html) * [OCC Command](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/occ_command.html) * [Talk bots](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/talkbots.html) * [Other OCS APIs](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/api/other_ocs.html) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Dependency injection — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/stable/developer_manual/basics/index.html) * Dependency injection * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/dependency_injection.rst) * * * Dependency injection[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#dependency-injection "Link to this heading") ================================================================================================================================================================ The App Framework assembles the application by using a container based on the software pattern [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) . This makes the code easier to test and thus easier to maintain. If you are unfamiliar with this pattern, watch the following video: * [Google Clean Code Talks](https://www.youtube.com/watch?v=RlfLCWKxHJ0) Dependency injection[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#id2 "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------- Dependency Injection sounds pretty complicated but it just means: Don’t put new dependencies in your constructor or methods but pass them in. So this: use OCP\\IDBConnection; // without dependency injection class AuthorMapper { private IDBConnection $db; public function \_\_construct() { $this\->db \= new Db(); } } would turn into this by using Dependency Injection: use OCP\\IDBConnection; // with dependency injection class AuthorMapper { private IDBConnection $db; public function \_\_construct(IDBConnection $db) { $this\->db \= $db; } } Controller injection[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#controller-injection "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- For controllers it’s possible to also have dependencies injected into methods. lib/Controller/ApiController.php[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#id4 "Link to this code") foo(); } public function bar(BarService $service) { $service\->bar(); } } Using a container[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#using-a-container "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------- Note Please do use automatic dependency injection (see below). For most apps there is no need to register services manually. Passing dependencies into the constructor rather than instantiating them in the constructor has the following drawback: Every line in the source code where **new AuthorMapper** is being used has to be changed, once a new constructor argument is being added to it. The solution for this particular problem is to limit the **new AuthorMapper** to one file, the container. The container contains all the factories for creating these objects and is configured in `lib/AppInfo/Application.php`. Nextcloud 20 and later uses the [PSR-11 standard](https://docs.nextcloud.com/server/stable/developer_manual/digging_deeper/psr.html#psr11) for the container interface, so working with the container might feel familiar if you’ve worked with other php applications before that also adhere to the convention. To add the app’s classes simply open the `lib/AppInfo/Application.php` and use the **IRegistrationContext::registerService** method: registerService(AuthorController::class, function(ContainerInterface $c): AuthorController { return new AuthorController( $c\->get('appName'), $c\->get(Request::class), $c\->get(AuthorService::class) ); }); /\*\* \* Services \*/ $context\->registerService(AuthorService::class, function(ContainerInterface $c): AuthorService { return new AuthorService( $c\->get(AuthorMapper::class) ); }); /\*\* \* Mappers \*/ $context\->registerService(AuthorMapper::class, function(ContainerInterface $c): AuthorMapper { return new AuthorMapper( $c\->get(IDBConnection::class) ); }); } } How the container works[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#how-the-container-works "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- The container works in the following way: * [A request comes in and is matched against a route](https://docs.nextcloud.com/server/stable/developer_manual/basics/routing.html) (for the AuthorController in this case) * The matched route queries **AuthorController** service from the container: return new AuthorController( $c->get('appName'), $c->get(Request::class), $c->get(AuthorService::class) ); * The **appName** is queried and returned from the base class * The **Request** is queried and returned from the server container * **AuthorService** is queried: $container->registerService(AuthorService::class, function(ContainerInterface $c): AuthorService { return new AuthorService( $c->get(AuthorMapper::class) ); }); * **AuthorMapper** is queried: $container->registerService(AuthorMappers::class, function(ContainerInterface $c): AuthorMapper { return new AuthorService( $c->get(IDBConnection::class) ); }); * The **database connection** is returned from the server container * Now **AuthorMapper** has all of its dependencies and the object is returned * **AuthorService** gets the **AuthorMapper** and returns the object * **AuthorController** gets the **AuthorService** and finally the controller can be instantiated and the object is returned So basically the container is used as a giant factory to build all the classes that are needed for the application. Because it centralizes all the creation of objects (the **new Class()** lines), it is very easy to add new constructor parameters without breaking existing code: only the **\_\_construct** method and the container line where the **new** is being called need to be changed. Use automatic dependency assembly (recommended)[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#use-automatic-dependency-assembly-recommended "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- In Nextcloud it is possible to build classes and their dependencies without having to explicitly register them on the container, as long as the container can [reflect](https://www.php.net/manual/en/book.reflection.php) the constructor and look up the parameters by their type. This concept is widely known as _auto-wiring_. ### How does auto-wiring work[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#how-does-auto-wiring-work "Link to this heading") Automatic assembly creates new instances of classes just by looking at the class name and its constructor parameters. For each constructor parameter the type or the argument name is used to query the container, e.g.: * **SomeType $type** will use **$container->get(SomeType::class)** * **$variable** will use **$container->get(‘variable’)** If all constructor parameters are resolved, the class will be created, saved as a service and returned. So basically the following is now possible: class \= $class; $this\->appName \= $appName; } } $app \= new \\OCP\\AppFramework\\App('myapp'); $class2 \= $app\->getContainer()\->get(MyTestClass2::class); $class2 instanceof MyTestClass2; // true $class2\->class instanceof MyTestClass; // true $class2\->appName \=== 'myname'; // true $class2 \=== $app\->getContainer()\->get(MyTestClass2::class); // true Note $appName is resolved because the container registered a parameter under the key ‘appName’ which will return the app id. ### How does it affect the request lifecycle[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#how-does-it-affect-the-request-lifecycle "Link to this heading") * A request comes in * All apps’ **routes.php** files are loaded * If a **routes.php** file returns an array, and an **appname/lib/AppInfo/Application.php** exists, include it, create a new instance of **\\OCA\\AppName\\AppInfo\\Application.php** and register the routes on it. That way a container can be used while still benefitting from the new routes behavior * If a **routes.php** file returns an array, but there is no **appname/lib/AppInfo/Application.php**, create a new \\OCP\\AppFramework\\App instance with the app id and register the routes on it * A request is matched for the route, e.g. with the name **page#index** * The appropriate container is being queried for the entry PageController (to keep backwards compatibility) * If the entry does not exist, the container is queried for OCA\\AppName\\Controller\\PageController and if no entry exists, the container tries to create the class by using [reflection](https://www.php.net/manual/en/book.reflection.php) on its constructor parameters ### How does this affect controllers[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#how-does-this-affect-controllers "Link to this heading") The only thing that needs to be done to add a route and a controller method is now: **myapp/appinfo/routes.php** \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \]\]; **myapp/appinfo/lib/Controller/PageController.php** registerParameter('TableName', 'my\_app\_table'); // the interface is called IAuthorMapper and AuthorMapper implements it $context\->registerService(IAuthorMapper::class, function (ContainerInterface $c): AuthorMapper { return $c\->get(AuthorMapper::class); }); // Less verbose alternative $context\->registerServiceAlias(IAuthorMapper::class, AuthorMapper::class); } } ### Predefined core services[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#predefined-core-services "Link to this heading") The following parameter names and type hints can be used to inject core services instead of using **$container->getServer()->getServiceX()** Parameters: * **appName**: The app id * **userId**: The id of the current user * **webRoot**: The path to the Nextcloud installation Aliases: * **AppName**: resolves to `appName` (deprecated) * **Request**: resolves to `\OCP\IRequest` * **ServerContainer**: resolves to `\OCP\IServerContainer` (deprecated) * **UserId**: resolves to `userId` (deprecated) * **WebRoot**: resolves to `webRoot` (deprecated) Types: * `\OCP\IAppConfig` * `\OCP\IAppManager` * `\OCP\IAvatarManager` * `\OCP\Activity\IManager` * `\OCP\ICache` * `\OCP\ICacheFactory` * `\OCP\IConfig` * `\OCP\AppFramework\Utility\IControllerMethodReflector` * `\OCP\Contacts\IManager` * `\OCP\IDateTimeZone` * `\OCP\IDBConnection` * `\OCP\Diagnostics\IEventLogger` * `\OCP\Diagnostics\IQueryLogger` * `\OCP\Files\Config\IMountProviderCollection` * `\OCP\Files\IRootFolder` * `\OCP\IGroupManager` * `\OCP\IL10N` * `\OCP\BackgroundJob\IJobList` * `\OCP\INavigationManager` * `\OCP\IPreview` * `\OCP\IRequest` * `\OCP\AppFramework\Utility\ITimeFactory` * `\OCP\ITagManager` * `\OCP\ITempManager` * `\OCP\Route\IRouter` * `\OCP\ISearch` * `\OCP\Security\ICrypto` * `\OCP\Security\IHasher` * `\OCP\Security\ISecureRandom` * `\OCP\IURLGenerator` * `\OCP\IUserManager` * `\OCP\IUserSession` * `\Psr\Container\ContainerInterface` * `\Psr\Log\LoggerInterface` ### How to enable it[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#how-to-enable-it "Link to this heading") To make use of this new feature, the following things have to be done: * **appinfo/info.xml** requires to provide another field called **namespace** where the namespace of the app is defined. The required namespace is the one which comes after the top level namespace **OCA\\**, e.g.: for **OCA\\MyBeautifulApp\\Some\\OtherClass** the needed namespace would be **MyBeautifulApp** and would be added to the info.xml in the following way: MyBeautifulApp * **appinfo/routes.php**: Instead of creating a new Application class instance, simply return the routes array like: \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \]\]; Note A namespace tag is required because you can not deduce the namespace from the app id Which classes should be added[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#which-classes-should-be-added "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- In general all of the app’s controllers need to be registered inside the container. Then the following question is: What goes into the constructor of the controller? Pass everything into the controller constructor that matches one of the following criteria: * It does I/O (database, write/read to files) * It is a global (e.g. $\_POST, etc. This is in the request class by the way) * The output does not depend on the input variables (also called [impure function](https://en.wikipedia.org/wiki/Pure_function) ), e.g. time, random number generator * It is a service, basically it would make sense to swap it out for a different object What not to inject: * It is pure data and has methods that only act upon it (arrays, data objects) * It is a [pure function](https://en.wikipedia.org/wiki/Pure_function) Optional services[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#optional-services "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------- Added in version 28. If an injected dependency can’t be found or build, an exception is thrown. This can be avoided by using the a nullable type notation for a dependency: namespace OCA\\MyApp\\MyService; use Some\\Service; class MyService { public function \_\_construct(private ?Service $service) { } } If `\Some\Service` exists and can be built, it will be injected. Else `MyService` will receive `null`. Accessing the container from anywhere[](https://docs.nextcloud.com/server/stable/developer_manual/basics/dependency_injection.html#accessing-the-container-from-anywhere "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it can be hard to inject some service inside legacy code, in these cases you can use `OCPServer::get(MyService::class)`. This should only be used as the last resort, as this makes your code more complicated to unit test and is considered an anti-pattern. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Background jobs (Cron) — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/31/developer_manual/basics/index.html) * Background jobs (Cron) * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/backgroundjobs.rst) * * * Background jobs (Cron)[](https://docs.nextcloud.com/server/31/developer_manual/basics/backgroundjobs.html#background-jobs-cron "Link to this heading") ======================================================================================================================================================== Often there is a need to run background jobs. For example there are Background jobs in Nextcloud that send out the activity emails. Or expire the trashbin. Types of background jobs[](https://docs.nextcloud.com/server/31/developer_manual/basics/backgroundjobs.html#types-of-background-jobs "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------- Nextcloud by default offers you two types of background jobs. The `\OCP\BackgroundJob\QueuedJob` and `\OCP\BackgroundJob\TimedJob`. The `QueuedJob` is for one time jobs. This can for example be triggered by inserting a job because an event happened. The `TimedJob` has a method `setInterval` where you can set the time minimum time in seconds between the jobs (from the constructor). This is useful in case you want to have a job that is run at most once a day for example. Of course you can customize this all to your liking by just extending `\OCP\BackgroundJob\Job` Writing a background job[](https://docs.nextcloud.com/server/31/developer_manual/basics/backgroundjobs.html#writing-a-background-job "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------- Writing a background job is rather straight forward. You write a class and extend your job class of choice. myService \= $service; // Run once an hour $this\->setInterval(3600); } protected function run($arguments) { $this\->myService\->doCron($arguments\['uid'\]); } } As you can see our dependency injection also works just fine for background jobs. The ITimeFactory always needs to be passed to the parent constructor. Since it is required to be set. In this case it is a background job that runs every hour. And we take the `uid` argument to pass on to the service to run the background job. The `run` function is the main thing you need to implement and where all the logic happens. ### Heavy load and time insensitive[](https://docs.nextcloud.com/server/31/developer_manual/basics/backgroundjobs.html#heavy-load-and-time-insensitive "Link to this heading") When the background job is a `\OCP\BackgroundJob\TimedJob` and can impact the performance of the instance and is not time sensitive, e.g. clearing old data, running training of AI models or similar things, consider flagging it as time insensitive in the constructor. setInterval(24 \* 3600); // Delay until low-load time $this\->setTimeSensitivity(\\OCP\\BackgroundJob\\IJob::TIME\_INSENSITIVE); This allows the Nextcloud to delay the job until a given nightly time window so the users are not that impacted by the heavy load of the background job. ### Configuring parallelism[](https://docs.nextcloud.com/server/31/developer_manual/basics/backgroundjobs.html#configuring-parallelism "Link to this heading") Added in version 27. With resource-heavy background jobs that run for longer than a few minutes, be they `QueuedJob` and `TimedJob` instances, you may want to restrict parallelism to prevent multiple such jobs from clogging up the server’s resources. You can do this with the `setAllowParallelRuns` method of `OCP\BackgroundJob\Job` (`QueuedJob` and `TimedJob` both inherit from this class, so they also have this available). setAllowParallelRuns(false); Registering a background job[](https://docs.nextcloud.com/server/31/developer_manual/basics/backgroundjobs.html#registering-a-background-job "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- Now that you have written your background job there is of course the small matter of how to make sure the system actually runs your job. In order to do this your job needs to be registered. ### info.xml[](https://docs.nextcloud.com/server/31/developer_manual/basics/backgroundjobs.html#info-xml "Link to this heading") You can register your jobs in your info.xml by adding; OCA\\MyApp\\Cron\\SomeTask This will on install/update of the application add the job `OCA\MyApp\Cron\SomeTask`. Of course in this case the arguments passed to your `run` function is just an empty array. ### Registering manually[](https://docs.nextcloud.com/server/31/developer_manual/basics/backgroundjobs.html#registering-manually "Link to this heading") In case you want more fine grained control about when a background job is inserted and you want to pass arguments to it you need to manually register your background jobs. You do this by using `\OCP\BackgroundJob\IJobList`. There you can add a job or remove a job. For example you could add or remove a certain job based on some controller: jobList \= $jobList; } public function addJob(string $uid) { $this\->jobList\->add(SomeTask::class, \['uid' \=> $uid\]); } public function removeJob(string $uid) { $this\->jobList\->remove(SomeTask::class, \['uid' \=> $uid\]); } } This provides more fine grained control and you can pass arguments to your background jobs easily. ### Scheduling[](https://docs.nextcloud.com/server/31/developer_manual/basics/backgroundjobs.html#scheduling "Link to this heading") A background job can be scheduled to run after a specific time and date. This avoids maintaining a time check inside a background job. Beware that the reliability of the execution time is limited. Systems that do not use system cron may have no active users and therefore no reliable cron trigger at the target time. System cron can also not guarantee that the job is picked up right away if the background job queue is full. The only guarantee you get is that the job is not picked up earlier than the specified time. lib/Service/ShareService.php[](https://docs.nextcloud.com/server/31/developer_manual/basics/backgroundjobs.html#id1 "Link to this code") jobList \= $jobList; } public function shareWithUser(string $uid, int $expiration) { // create an expiring share $this\->jobList\->scheduleAfter( RevokeShare::class, \['id' \=> $shareId\], $expiration, ); } } ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Translations — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/31/developer_manual/basics/index.html) * Translations * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/translations.rst) * * * Translations[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#translations "Link to this heading") ==================================================================================================================================== Nextcloud provides mechanisms for internationalization (make an application translatable) and localization (add translations for specific languages). This section provides detailed instructions for both aspects. In order to make your app translatable (internationalization), you should use Nextcloud’s methods for translating strings. They are available for both the server-side (PHP, Templates) as well as for the client-side (JavaScript). PHP Backend[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#php-backend "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------- If localized strings are used in the backend code, simply inject the `\OCP\IL10N` class into your service via type hinting it in the constructor. You will automatically get the language object containing the translations of your app: l\->getLanguageCode(); } public sayHello() { // Simple string return $this\->l\->t('Hello'); } public function getAuthorName($name) { // String using a parameter return $this\->l\->t('Getting author %1$s', \[$name\]); } public function getAuthors($count, $city) { // Translation with plural return $this\->l\->n( '%n author is currently in the city %1$s', // singular string '%n authors are currently in the city %1$s', // plural string $count, // number to decide which plural to use \[$city\] // further parameters are possible ); } } ### Language of other users[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#language-of-other-users "Link to this heading") If you need to get the language of another user, e.g. to send them an email or inside a background job, there are also the `force_language` and `default_language` configuration options to consider. To make this easier, the `OCP\L10N\IFactory` class comes with a `getUserLanguage` method: l10nFactory\->getUserLanguage($user); $l \= $this\->l10nFactory\->get('myapp', $lang); // … } PHP Templates[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#php-templates "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------- In every template the global variable `$l` can be used to translate the strings using its methods `t()` and `n()`: // Simple text string t('Hide')); ?> // Text with a placeholder
    t('Show files of %1$s', \[$user\])); ?>
    // Date string l('date', time())); ?> JavaScript / TypeScript / Vue[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#javascript-typescript-vue "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ There are global functions `t()` and `n()` available for translating strings in javascript code. If your app is build, you can import the translation functions from the [@nextcloud/l10n package](https://github.com/nextcloud-libraries/nextcloud-l10n) . They differ a bit in terms of usage compared to php: * First argument is the appId e.g. `'myapp'` * Placeholders (apart from the count in plurals) use single-mustache brackets with meaning-full descriptors. * The parameter list is an object with the descriptors as key. t('myapp', 'Hello World!'); t('myapp', '{name} is available. Get {linkstart}more information{linkend}', {name: 'Nextcloud 16', linkstart: '
    ', linkend: ''}); n('myapp', 'Import %n calendar into {collection}', 'Import %n calendars into {collection}', selectionLength, {collection: 'Nextcloud'}); Guidelines[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#guidelines "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------- Please also look through the following hints to improve your strings and make them better translatable by the community and therefore improving the experience for non-english users. ### Dos and Don’ts[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#dos-and-don-ts "Link to this heading") | Bad | Good | Description | | --- | --- | --- | | `´` or `’` | `'` | Use ascii single quote | | `Loading...` | `Loading …` | Use unicode triple-dot character.

    Add a space before the triple-dot when trimming a sentence instead of a word. | | Don’t | Do not | Using the spelled out version is easier to understand and makes translating easier. | | Won’t | Will not | Using the spelled out version is easier to understand and makes translating easier. | | Can not | Cannot | Using the combined version is easier to understand and makes translating easier. | | id | ID | Full uppercase for shortcutting “identifier” | | Users | Accounts / People | Use **accounts** when you refer to a profile/entity. Use **people** when referring to humans. | | Admin / Administrator | Administration | Refer to administration as a non-human organizational entity

    instead of a single or multiple persons. | | Headline | Headline: | Include colons `:` in the translations as some languages add a space before the colon. | | “ Leading space”

    “Trailing space “ | “No leading space”

    “No trailing space” | Leading or trailing spaces mostly indicate that strings are concatenated.

    For translators it is often helpful to have all the content in a single translation,

    as order and references between words and sentences might get lost otherwise. | | “Error:” $error | “Error: %s” | Instead of concatenating errors or part messages, make them a proper placeholder | ### Correct plurals[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#correct-plurals "Link to this heading") If you use a plural, you **must** also use the `%n` placeholder. The placeholder defines the plural and the word without the number preceding is wrong. If you don’t know/have a number for your translation, e.g. because you don’t know how many items are going to be selected, just use an undefined plural. They exist in every language and have one form. They do not follow the normal plural pattern. PHP Example: // BAD: Plural without count $title \= $l\->n('Import calendar', 'Import calendars', $selectionLength) // BETTER: Plural has count, but disrupting to read and unnecessary information $title \= $l\->n('Import %n calendar', 'Import %n calendars', $selectionLength) // BEST: Simple string with undefined plural not using any number in the string $title \= $l\->t('Import calendars') Opposed to the normal placeholders in javascript, the plural number also uses the `%n` syntax: JS Example: /\* BAD: Plural without count \*/ n('myapp', 'Import calendar', 'Import calendars', selected.length) /\* BETTER: Plural has count, but disrupting to read and unnecessary information \*/ n('myapp', 'Import %n calendar', 'Import %n calendars', selected.length) /\* BEST: Simple string with undefined plural not using any number in the string \*/ t('myapp', 'Import calendars') ### Improving your translations[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#improving-your-translations "Link to this heading") Starting with the following example, improving it step by step: t('Select file from')) . ' '; ?>t('local filesystem'));?>t(' or ')); ?>t('cloud'));?> #### Step 1: String split[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#step-1-string-split "Link to this heading") You shall **never split** sentences and **never concatenate** two translations (e.g. “Enable” and “dark mode” can not be combined to “Enable dark mode”, because languages might have to use different cases)! Translators lose the context and they have no chance to possibly re-arrange words/parts as needed. Translators will translate: * `Select file from` * `local filesystem` * `or` (with leading and trailing whitespace) * `cloud` Translating these individual strings results in `local filesystem` and `cloud` losing case. The two white spaces surrounding `or` will get lost while translating as well. For languages that have a different grammatical order it prevents the translators from reordering the sentence components. So the following code is a bit better, but suffers from another issue: t('Select file from local filesystem or cloud'));?> #### Step 2: HTML Markup[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#step-2-html-markup "Link to this heading") In this case the translators can re-arrange as they like, but have to deal with your markup and can mess it up easily. It is better to **keep the markup out** of your code, so the following translation is even better: t('Select file from %slocal filesystem%s or %scloud%s', \['', '', '', ''\]));?> But there is one last problem with this. #### Step 3: Placeholders[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#step-3-placeholders "Link to this heading") In case the language has to turn things around, your code will still insert the parameters in the given order and they can not re-order them. To prevent this last hurdle simply **use positioned placeholders** like `%1$s`: t('Select file from %1$slocal filesystem%2$s or %3$scloud%4$s', \['', '', '', ''\]));?> This allows translators to have the cloudlink before the browselink in case the language is e.g. right-to-left. ### Provide context hints for translators[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#provide-context-hints-for-translators "Link to this heading") In case some translation strings may be translated wrongly because they have multiple meanings. Especially translations strings that only contain a single word often result in problems. The most famous example in the Nextcloud code base is `Share` which can which can be the verb and action `To share something` or the noun `A share`. The added hints will be shown in the Transifex web-interface: #### PHP[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#php "Link to this heading")
    • t('Add new file')); ?>
    #### JavaScript / TypeScript[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#javascript-typescript "Link to this heading") // TRANSLATORS name that is appended to copied files with the same name, will be put in parenthesis and appended with a number if it is the second+ copy var copyNameLocalized \= t('files', 'copy'); #### Vue[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#vue "Link to this heading") This covers vue html templates in vue sfc components. For vue js code, see the javascript section. {{ t('forms', 'Required') }} #### C++ (Qt) / Desktop client[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#c-qt-desktop-client "Link to this heading") //: Example text: "Progress of sync process. Shows the currently synced filename" fileProgressString \= tr("Syncing %1").arg(allFilenames); #### Android[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#android "Link to this heading") Boards #### iOS[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#ios "Link to this heading") /\* The title on the navigation bar of the Scanning screen. \*/ "wescan.scanning.title" \= "Scanning"; Adding translations[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#adding-translations "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- The steps how to set up translations for an app have been moved to it’s own page in the “App development” chapter: [Translation setup](https://docs.nextcloud.com/server/31/developer_manual/app_development/translation_setup.html#translation-setup) Testing translations[](https://docs.nextcloud.com/server/31/developer_manual/basics/translations.html#testing-translations "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------- You can use the query parameter `forceLanguage` to force a specific language for a web request (API or frontend). See [Forcing language for a given call](https://docs.nextcloud.com/server/31/developer_manual/client_apis/OCS/ocs-api-overview.html#api-force-language) . ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Bootstrapping — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/stable/developer_manual/app_development/index.html) * Bootstrapping * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/bootstrap.rst) * * * Bootstrapping[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/bootstrap.html#bootstrapping "Link to this heading") ================================================================================================================================================ Every php process has a relatively short lifespan that lasts as long as the HTTP request or the invocation of the command line program. At the beginning of this lifespan, Nextcloud initializes its services. At the same time, any additional apps might want to register their services to Nextcloud as well. This event is called the _bootstrapping_ and this chapter shall shed some light on how to hook into this with an app. The Application class[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/bootstrap.html#the-application-class "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- The Application class is the main entry point of an app. This class is optional but highly recommended if your app needs to register any services or run some code for every request. Nextcloud will try to autoload the class from the namespace `\OCA\\AppInfo\Application`, like `\OCA\MyApp\AppInfo\Application`, where _MyApp_ would be the name of your app. The file will therefore have the location `myapp/lib/AppInfo/Application.php`. registerEventListener( BeforeUserDeletedEvent::class, UserDeletedListener::class ); } public function boot(IBootContext $context): void { // ... boot logic goes here ... /\*\* @var IManager $manager \*/ $manager \= $context\->getAppContainer()\->query(IManager::class); $manager\->registerNotifierService(Notifier::class); } } Note that the context objects of the methods `register` and `boot` have different interfaces and thus have different capabilities appropriate for their stage. Bootstrapping process[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/bootstrap.html#bootstrapping-process "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- To give a better overview of _when_ each of the bootstrapping stages are reached and how they app can interact with them, this section explains the changes done for Nextcloud 20. ### Nextcloud 20 and later[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/bootstrap.html#nextcloud-20-and-later "Link to this heading") Nextcloud 20 is the first release with the interface `\OCP\AppFramework\Bootstrap\IBootstrap`. This interface can be implemented by your app’s `Application` class to signal that it wants to act on the bootstrapping stages. The major difference between this and the old process is that the bootstrapping is not performed in sequence, but apps register and boot interleaved. This should ensure that an app that `boot`s can rely on all other apps’ registration to be finished. The overall process is as follows: 1. In each installed and enabled app that has an `Application` class that also implements `IBootstrap`, the `register` method will be called. This method receives a context argument via which the app can prime the dependency injection container and register other services lazily, e.g. by calling `$context->registerService(...)`. The emphasis is on **laziness**. At this very early stage of the process lifetime, no other apps nor all of the server components are ready. Therefore the app **must not** try to use anything except the API provided by the context. That shall ensure that all apps can safely run their registration logic before any services are queried (instantiated) from the DI container or related code is run. 2. Nextcloud will load groups of certain apps early, e.g. filesystem or session apps, and other later. 3. Nextcloud will query the app’s `Application` class (again), no matter whether it implements `IBootstrap` or not. 4. Nextcloud will invoke the [boot](https://docs.nextcloud.com/server/stable/developer_manual/app_development/bootstrap.html#app-bootstrap-boot) method of every `Application` instance that implements `IBootstrap`. At this stage you may assume that all registrations via `IBootstrap::register` have completed. #### Booting an app[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/bootstrap.html#booting-an-app "Link to this heading") Any code that should run once for every Nextcloud process goes into the `boot` method of an app’s `Application` class. Use this mechanism carefully as it could have a negative effect on Nextcloud’s overall performance. lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/bootstrap.html#id3 "Link to this code") getAppContainer()\->query(IFooManager::class); $manager\->registerCustomFoo(MyFooImpl::class); } } The code above fetches a fictional _foo manager_ to register an app class. The boot context object comes with a `injectFn` helper that eases dependency injection inside the `boot` method by injecting arguments of a callable: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/bootstrap.html#id4 "Link to this code") injectFn(function(IFooManager $manager) { $manager\->registerCustomFoo(MyFooImpl::class); }); } } With the help of `Closure::fromCallable` you can also delegate to other methods that get their arguments injected: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/bootstrap.html#id5 "Link to this code") injectFn($this\->registerFoo(...)); } protected function registerFoo(IFooManager $manager): void { $manager\->registerCustomFoo(MyFooImpl::class); } } ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Front-end — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/stable/developer_manual/basics/index.html) * Front-end * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/front-end/index.rst) * * * Front-end[](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/index.html#front-end "Link to this heading") ===================================================================================================================================== * [Templates](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/templates.html) * [Including templates](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/templates.html#including-templates) * [Including CSS and JavaScript](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/templates.html#including-css-and-javascript) * [Including images](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/templates.html#including-images) * [JavaScript](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/js.html) * [Sending the CSRF token](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/js.html#sending-the-csrf-token) * [Generating URLs](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/js.html#generating-urls) * [Extending core parts](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/js.html#extending-core-parts) * [Loading initial state](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/js.html#loading-initial-state) * [Keyboard shortcuts](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/js.html#keyboard-shortcuts) * [CSS](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/css.html) * [Theming support](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/theming.html) * [CSS variables](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/theming.html#css-variables) * [JavaScript](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/theming.html#javascript) * [Icons](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/theming.html#icons) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Controllers — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/31/developer_manual/basics/index.html) * Controllers * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/controllers.rst) * * * Controllers[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#controllers "Link to this heading") ================================================================================================================================= Controllers are used to connect [routes](https://docs.nextcloud.com/server/31/developer_manual/basics/routing.html) with app logic. Think of it as callbacks that are executed once a request has come in. Controllers are defined inside the **lib/Controller/** directory. To create a controller, simply extend the Controller class and create a method that should be executed on a request: $id = 3 // $doMore = false // $value = 3.5 } } The following types will be cast: * **bool** or **boolean** * **float** * **int** or **integer** ### JSON parameters[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#json-parameters "Link to this heading") It is possible to pass JSON using a POST, PUT or PATCH request. To do that the **Content-Type** header has to be set to **application/json**. The JSON is being parsed as an array and the first level keys will be used to pass in the arguments, e.g.: POST /index.php/apps/myapp/authors Content\-Type: application/json { "name": "test", "number": 3, "publisher": true, "customFields": { "mail": "test@example.com", "address": "Somewhere" } } "test@example.com", "address" => "Somewhere") } } ### Reading headers, files, cookies and environment variables[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#reading-headers-files-cookies-and-environment-variables "Link to this heading") Headers, files, cookies and environment variables can be accessed directly from the request object: request\->getHeader('Content-Type'); // $\_SERVER\['HTTP\_CONTENT\_TYPE'\] $cookie \= $this\->request\->getCookie('myCookie'); // $\_COOKIES\['myCookie'\] $file \= $this\->request\->getUploadedFile('myfile'); // $\_FILES\['myfile'\] $env \= $this\->request\->getEnv('SOME\_VAR'); // $\_ENV\['SOME\_VAR'\] } } Why should those values be accessed from the request object and not from the global array like $\_FILES? Simple: [because it’s bad practice](http://c2.com/cgi/wiki?GlobalVariablesAreBad) and will make testing harder. ### Reading and writing session variables[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#reading-and-writing-session-variables "Link to this heading") To set, get or modify session variables, the ISession object has to be injected into the controller. Nextcloud will read existing session data at the beginning of the request lifecycle and close the session afterwards. This means that in order to write to the session, the session has to be opened first. This is done implicitly when calling the set method, but would close immediately afterwards. To prevent this, the session has to be explicitly opened by calling the reopen method. Alternatively, you can use the `#[UseSession]` attribute to automatically open and close the session for you. use OCP\\AppFramework\\Controller; use OCP\\AppFramework\\Http\\Attribute\\UseSession; use OCP\\AppFramework\\Http\\Response; class PageController extends Controller { #\[UseSession\] public function writeASessionVariable(): Response { // ... } } Note The `#[UseSession]` was added in Nextcloud 26 and requires PHP 8.0 or later. If your app targets older releases and PHP 7.x then use the deprecated `@UseSession` annotation. /\*\* \* @UseSession \*/ public function writeASessionVariable(): Response { // .... } In case the session may be read and written by concurrent requests of your application, keeping the session open during your controller method execution may be required to ensure that the session is locked and no other request can write to the session at the same time. When reopening the session, the session data will also get updated with the latest changes from other requests. Using the annotation will keep the session lock for the whole duration of the controller method execution. For additional information on how session locking works in PHP see the article about [PHP Session Locking: How To Prevent Sessions Blocking in PHP requests](https://ma.ttias.be/php-session-locking-prevent-sessions-blocking-in-requests/) . Then session variables can be accessed like this: Note The session is closed automatically for writing, unless you add the `#[UseSession]` attribute! session \= $session; } #\[UseSession\] public function writeASessionVariable(): Response { // read a session variable $value \= $this\->session\['value'\]; // write a session variable $this\->session\['value'\] \= 'new value'; } } ### Setting cookies[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#setting-cookies "Link to this heading") Cookies can be set or modified directly on the response class: addCookie('foo', 'bar'); $response\->addCookie('bar', 'foo', new DateTime('2015-01-01 00:00')); return $response; } /\*\* \* Invalidates the cookie "foo" \* Invalidates the cookie "bar" and "bazinga" \*/ public function invalidateCookie(): TemplateResponse { $response \= new TemplateResponse(...); $response\->invalidateCookie('foo'); $response\->invalidateCookies(array('bar', 'bazinga')); return $response; } } Responses[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#responses "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------- Similar to how every controller receives a request object, every controller method has to return a Response. This can be in the form of a Response subclass or in the form of a value that can be handled by a registered responder. ### JSON[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#json "Link to this heading") Returning JSON is simple, just pass an array to a JSONResponse: 'hi'); return new JSONResponse($params); } } Because returning JSON is such a common task, there’s even a shorter way to do this: 'hi'); } } Why does this work? Because the dispatcher sees that the controller did not return a subclass of a Response and asks the controller to turn the value into a Response. That’s where responders come in. ### Responders[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#responders "Link to this heading") Responders are short functions that take a value and return a response. They are used to return different kinds of responses based on a **format** parameter which is supplied by the client. Think of an API that is able to return both XML and JSON depending on if you call the URL with: ?format=xml or: ?format=json The appropriate responder is being chosen by the following criteria: * First the dispatcher checks the Request if there is a **format** parameter, e.g.: ?format=xml or: /index.php/apps/myapp/authors.{format} * If there is none, take the **Accept** header, use the first mimetype and cut off _application/_. In the following example the format would be _xml_: Accept: application/xml, application/json * If there is no Accept header or the responder does not exist, format defaults to **json**. By default there is only a responder for JSON but more can be added easily: registerResponder('xml', function($value) { if ($value instanceof DataResponse) { return new XMLResponse( $value\->getData(), $value\->getStatus(), $value\->getHeaders() ); } else { return new XMLResponse($value); } }); return array('test' \=> 'hi'); } } Note The above example would only return XML if the **format** parameter was _xml_. If you want to return an XMLResponse regardless of the format parameter, extend the Response class and return a new instance of it from the controller method instead. Because returning values works fine in case of a success but not in case of failure that requires a custom HTTP error code, you can always wrap the value in a **DataResponse**. This works for both normal responses and error responses. 'not found!'), Http::STATUS\_NOT\_FOUND); } } } ### Templates[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#templates "Link to this heading") A [template](https://docs.nextcloud.com/server/31/developer_manual/basics/front-end/templates.html) can be rendered by returning a TemplateResponse. A TemplateResponse takes the following parameters: * **appName**: tells the template engine in which app the template should be located * **templateName**: the name of the template inside the templates/ folder without the .php extension * **parameters**: optional array parameters that are available in the template through $\_, e.g.: array('key' \=> 'something') can be accessed through: $\_\['key'\] * **renderAs**: defaults to _user_, tells Nextcloud if it should include it in the web interface, or in case _blank_ is passed solely render the template 'hi'); return new TemplateResponse($this\->appName, $templateName, $parameters); } } ### Public page templates[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#public-page-templates "Link to this heading") For public pages, that are rendered to users who are not logged in to the Nextcloud instance, a `OCP\\AppFramework\\Http\\Template\\PublicTemplateResponse` should be used, to load the correct base template. It also allows adding an optional set of actions that will be shown in the top right corner of the public page. appName, 'main', \[\]); $template\->setHeaderTitle('Public page'); $template\->setHeaderDetails('some details'); $template\->setHeaderActions(\[\ new SimpleMenuAction('download', 'Label 1', 'icon-css-class1', 'link-url', 0),\ new SimpleMenuAction('share', 'Label 2', 'icon-css-class2', 'link-url', 10),\ \]); return $template; } } The header title and subtitle will be rendered in the header, next to the logo. The action with the highest priority (lowest number) will be used as the primary action, others will shown in the popover menu on demand. A `OCP\\AppFramework\\Http\\Template\\SimpleMenuAction` will be a link with an icon added to the menu. App developers can implement their own types of menu renderings by adding a custom class implementing the `OCP\\AppFramework\\Http\\Template\\IMenuAction` interface. ### Redirects[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#redirects "Link to this heading") A redirect can be achieved by returning a RedirectResponse: addHeader('Content-Type', 'application/xml'); $this\->xml \= $xml; } public function render(): string { $root \= new SimpleXMLElement(''); array\_walk\_recursive($this\->xml, array ($root, 'addChild')); return $xml\->asXML(); } } ### Streamed and lazily rendered responses[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#streamed-and-lazily-rendered-responses "Link to this heading") By default all responses are rendered at once and sent as a string through middleware. In certain cases this is not a desirable behavior, for instance if you want to stream a file in order to save memory. To do that use the now available **OCP\\AppFramework\\Http\\StreamResponse** class: ` tag, see ‘script-src-elem’ **(enabled by default)** Note `useStrictDynamicOnScripts` is enabled by default to allow module javascript to load its dependencies using `import` since Nextcloud 28. You can disable this by passing **false** as the parameter. The following methods whitelist domains by passing in a domain or \* for any domain: * **addAllowedScriptDomain** (string $domain) * **addAllowedStyleDomain** (string $domain) * **addAllowedFontDomain** (string $domain) * **addAllowedImageDomain** (string $domain) * **addAllowedConnectDomain** (string $domain) * **addAllowedMediaDomain** (string $domain) * **addAllowedObjectDomain** (string $domain) * **addAllowedFrameDomain** (string $domain) * **addAllowedChildSrcDomain** (string $domain) The following policy for instance allows images, audio and videos from other domains: addAllowedImageDomain('\*'); \->addAllowedMediaDomain('\*'); $response\->setContentSecurityPolicy($csp); } } ### OCS[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#ocs "Link to this heading") Note This is purely for compatibility reasons. If you are planning to offer an external API, go for a [REST APIs](https://docs.nextcloud.com/server/31/developer_manual/digging_deeper/rest_apis.html) instead. In order to ease migration from OCS API routes to the App Framework, an additional controller and response have been added. To migrate your API you can use the **OCP\\AppFramework\\OCSController** base class and return your data in the form of a DataResponse in the following way: \[\ \[\ 'name' \=> 'Share#getShares',\ 'url' \=> '/api/v1/shares',\ 'verb' \=> 'GET',\ \],\ \],\ \]; Now your method will be reachable via `/ocs/v2.php/apps//api/v1/shares` ### Handling errors[](https://docs.nextcloud.com/server/31/developer_manual/basics/controllers.html#handling-errors "Link to this heading") Sometimes a request should fail, for instance if an author with id 1 is requested but does not exist. In that case use an appropriate [HTTP error code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error) to signal the client that an error occurred. Each response subclass has access to the **setStatus** method which lets you set an HTTP status code. To return a JSONResponse signaling that the author with id 1 has not been found, use the following code: index() method should not check the CSRF token because it has not yet been sent to the client and because of that can’t work. To turn off checks the following _Attributes_ can be added before the controller: * `#[NoAdminRequired]`: Also users that are not admins can access the page * `#[PublicPage]`: Everyone can access the page without having to log in * `#[NoTwoFactorRequired]`: A user can access the page before the two-factor challenge has been passed (use this wisely and only in two-factor auth apps, e.g. to allow setup during login) * `#[NoCSRFRequired]`: Don’t check the CSRF token (use this wisely since you might create a security hole; to understand what it does see [CSRF in the security section](https://docs.nextcloud.com/server/31/developer_manual/prologue/security.html#cross-site-request-forgery) ) Note The attributes are only available in Nextcloud 27 or later. In older versions annotations with the same names exist: * `@NoAdminRequired` instead of `#[NoAdminRequired]` * `` @PublicPage` `` instead of `#[PublicPage]` * `` @NoTwoFactorRequired` `` instead of `#[NoTwoFactorRequired]` * `` @NoCSRFRequired` `` instead of `#[NoCSRFRequired]` A controller method that turns off all checks would look like this: auth->isSuccessful here is just an // example. if (!$this\->auth\->isSuccessful()) { $templateResponse\->throttle(); } return $templateResponse; } } A controller can also have multiple factors to brute force against. In this case you can specify multiple attributes and then in the throttle you specify the action which was violated. This is especially useful when a secret, in the sample below token, could be guessed on multiple endpoints e.g. a share token on the API level, preview endpoint, frontend controller, etc. while another secret (password), is specific to this one controller method. shareManager\->getByToken($token)) { $templateResponse\->throttle(\['action' \=> 'token'\]); } // … if (!$share\->verifyPassword($password)) { $templateResponse\->throttle(\['action' \=> 'password'\]); } return $templateResponse; } } ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Tutorial — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/stable/developer_manual/app_development/index.html) * Tutorial * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/tutorial.rst) * * * Tutorial[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/tutorial.html#tutorial "Link to this heading") ===================================================================================================================================== To help you get started on Nextcloud app development we have compiled a comprehensive set of tutorials that cover everything from setting up your development environment to developing a full fledged app with database storage. Please head [here](https://cloud.nextcloud.com/s/iyNGp8ryWxc7Efa?path=%2F) to get started. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Front-end code — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/31/developer_manual/server/index.html) * Front-end code * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/server/code-front-end.rst) * * * Front-end code[](https://docs.nextcloud.com/server/31/developer_manual/server/code-front-end.html#front-end-code "Link to this heading") ========================================================================================================================================== Building Vue components and scripts[](https://docs.nextcloud.com/server/31/developer_manual/server/code-front-end.html#building-vue-components-and-scripts "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ We are moving more and more toward using Vue.js in the front-end, starting with Settings. For building the code on changes, use these terminal commands in the root folder: \# install dependencies npm install \# build for development npm run dev \# build for development and watch edits npm run watch \# build for production with minification npm run build Building styles[](https://docs.nextcloud.com/server/31/developer_manual/server/code-front-end.html#building-styles "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------- Styles are written in SCSS and compiled to css. \# install dependencies make dev-setup \# compile style sheets npm run sass \# compile style sheets and watch edits npm run sass:watch Committing changes[](https://docs.nextcloud.com/server/31/developer_manual/server/code-front-end.html#committing-changes "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- **When making changes, also commit the compiled files!** We still use Handlebars templates in some places in Files and Settings. We will replace these step-by-step with Vue.js, but in the meantime, you need to compile them separately. If you don’t have Handlebars installed yet, you can do it with this terminal command: sudo npm install -g handlebars Then inside the root folder of your local Nextcloud development installation, run this command in the terminal every time you changed a `.handlebars` file to compile it: ./build/compile-handlebars-templates.sh Before checking in JS changes, make sure to also build for production: make build-js-production Then add the compiled files for committing. To save some time, to only rebuild for a specific app, use the following and replace the module with the app name: MODULE=user\_status make build-js-production Please note that if you used `make build-js` or `make watch-js` before, you’ll notice that a lot of files were marked as changed, so might need to clear the workspace first. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Nextcloud Assistant — Nextcloud latest Administration Manual latest documentation * [](https://docs.nextcloud.com/server/latest/admin_manual/contents.html) * [Artificial Intelligence](https://docs.nextcloud.com/server/latest/admin_manual/ai/index.html) * Nextcloud Assistant * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/admin_manual/ai/app_assistant.rst) * * * Nextcloud Assistant[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#nextcloud-assistant "Link to this heading") =============================================================================================================================================== Nextcloud assistant is the primary graphical user interface for interacting with artificial intelligence features in Nextcloud. It offers the graphical user interface for the unified AI Task processing API offering features like summarizing text, generating headlines, asking arbitrary questions, transcription of media files, image generation and it integrates with the context\_chat app to offer in-context answers about your own data stored in Nextcloud. The assistant app also offers a chat interface to interact with the chosen language model. Nextcloud can provide customer support upon request, please talk to your account manager for the possibilities. Find the user documentation here: [https://github.com/nextcloud/assistant/tree/main/docs/user](https://github.com/nextcloud/assistant/tree/main/docs/user) Installation[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#installation "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------- You can install the _assistant_ app via the “Apps” page in Nextcloud, or by executing sudo \-E \-u www\-data php occ app:enable assistant App store[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#app-store "Link to this heading") --------------------------------------------------------------------------------------------------------------------------- You can also find the app in our app store, where you can write a review: [https://apps.nextcloud.com/apps/assistant](https://apps.nextcloud.com/apps/assistant) Repository[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#repository "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------- You can find the app’s code repository on GitHub where you can report bugs and contribute fixes and features: [https://github.com/nextcloud/assistant](https://github.com/nextcloud/assistant) Nextcloud customers should file bugs directly with our Customer Support. Related apps[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#related-apps "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------- Artificial intelligence at Nextcloud is built in a modular way, allowing you to choose from a variety of solutions for your needs. In order to make use of the various features of the Assistant you will need additional apps that act as backends to provide the actual implementation of the AI functionality. In the Nextcloud administration settings under “Artificial intelligence” you can select which AI backend app to use for which tasks. Note that some of the backend apps are only community maintained, while others are available for Customer support upon request. The AI admin settings will show all types of Assistant Tasks that are implemented by all your installed apps. Task types can be disabled in the AI admin settings so they are not available for the Assistant or other apps even if they are implemented. All implemented Task types are enabled by default. **Note**: At Nextcloud we focus on creating on-premise AI apps that run fully self-hosted on your own servers in order to preserve your privacy and data sovereignty. However, you can also offload these resource-heavy tasks to an [“AI as a Service” provider](https://docs.nextcloud.com/server/latest/admin_manual/ai/ai_as_a_service.html#ai-ai-as-a-service) . **Note**: When using our on-premise AI apps, make sure you have a GPU with enough VRAM that fits all the features you need. For each app documented here you will find its hardware requirements. ### Machine translation[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#machine-translation "Link to this heading") In order to make use of machine translation features in the assistant, you will need an app that provides a translation backend: \* [translate2 (ExApp)](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_translate2.html#ai-app-translate2) - Runs open source AI translation models locally on your own server hardware (Customer support available upon request) \* _integration\_deepl_ - Integrates with the deepl API to provide translation functionality from Deepl.com servers (Only community supported) ### Speech-To-Text[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#speech-to-text "Link to this heading") In order to make use of Speech-to-Text, you will need an app that provides a Speech-To-Text backend: * [stt\_whisper2](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_stt_whisper2.html#ai-app-stt-whisper2) - Runs open source AI Speech-To-Text models on your own server hardware (Customer support available upon request) * [OpenAI and LocalAI integration (via OpenAI API)](https://apps.nextcloud.com/apps/integration_openai) - Integrates with the OpenAI API to provide AI functionality from OpenAI servers (Customer support available upon request; see [AI as a Service](https://docs.nextcloud.com/server/latest/admin_manual/ai/ai_as_a_service.html#ai-ai-as-a-service) ) ### Text processing[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#text-processing "Link to this heading") In order to make use of text processing features in the assistant, you will need an app that provides a Text processing backend: * [llm2](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_llm2.html#ai-app-llm2) - Runs open source AI language models locally on your own server hardware (Customer support available upon request) * * [OpenAI and LocalAI integration (via OpenAI API)](https://apps.nextcloud.com/apps/integration_openai) - Integrates with the OpenAI API to provide AI functionality from OpenAI servers (Customer support available upon request; see [AI as a Service](https://docs.nextcloud.com/server/latest/admin_manual/ai/ai_as_a_service.html#ai-ai-as-a-service) ) * _integration\_watsonx_ - Integrates with the IBM watsonx.ai API to provide AI functionality from IBM Cloud servers (Customer support available upon request; see [AI as a Service](https://docs.nextcloud.com/server/latest/admin_manual/ai/ai_as_a_service.html#ai-ai-as-a-service) ) These apps currently implement the following Assistant Tasks: * _Generate text_ (Tested with OpenAI GPT-3.5 and Llama 3.1 8B) * _Summarize_ (Tested with OpenAI GPT-3.5 and Llama 3.1 8B) * _Generate headline_ (Tested with OpenAI GPT-3.5 and Llama 3.1 8B) * _Extract topics_ (Tested with OpenAI GPT-3.5 and Llama 3.1 8B) * _Context write_ (Tested with OpenAI GPT-3.5 and Llama 3.1 8B) * _Reformulate text_ (Tested with OpenAI GPT-3.5 and Llama 3.1 8B) These tasks may work with other models, but we can give no guarantees. ### Text-To-Image[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#text-to-image "Link to this heading") In order to make use of Text-To-Image features, you will need an app that provides an image generation backend: * [tex2image\_stablediffusion2](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_text2image_stablediffusion2.html#ai-app-text2image-stablediffusion2) (Customer support available upon request) * * [OpenAI and LocalAI integration (via OpenAI API)](https://apps.nextcloud.com/apps/integration_openai) - Integrates with the OpenAI API to provide AI functionality from OpenAI servers (Customer support available upon request; see [AI as a Service](https://docs.nextcloud.com/server/latest/admin_manual/ai/ai_as_a_service.html#ai-ai-as-a-service) ) * _integration\_replicate_ - Integrates with the replicate API to provide AI functionality from replicate servers (see [AI as a Service](https://docs.nextcloud.com/server/latest/admin_manual/ai/ai_as_a_service.html#ai-ai-as-a-service) ) ### Context Chat[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#context-chat "Link to this heading") In order to make use of our special Context Chat feature, offering insights about your own documents and data stored in Nextcloud, you will need the following apps: * [context\_chat + context\_chat\_backend](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_context_chat.html#ai-app-context-chat) - (Customer support available upon request) You will also need a text processing provider as specified above (ie. llm2, integration\_openai or integration\_watsonx). ### Chat[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#chat "Link to this heading") In order to make use of our “Chat with AI” feature you will need any one of the following apps: * [llm2](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_llm2.html#ai-app-llm2) - Runs open source AI language models locally on your own server hardware (Customer support available upon request) * * [OpenAI and LocalAI integration (via OpenAI API)](https://apps.nextcloud.com/apps/integration_openai) - Integrates with the OpenAI API to provide AI functionality from OpenAI servers (Customer support available upon request; see [AI as a Service](https://docs.nextcloud.com/server/latest/admin_manual/ai/ai_as_a_service.html#ai-ai-as-a-service) ) ### Voice Chat[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#voice-chat "Link to this heading") In order to make use of our “Audio chat” feature which allows you to interact with the assistant Chat via your Voice and Ears as if in a real conversation, you will need any of the following set of apps: * Either * [OpenAI and LocalAI integration (via OpenAI API)](https://apps.nextcloud.com/apps/integration_openai) - Integrates with the OpenAI API to provide AI functionality from OpenAI servers (Customer support available upon request; see [AI as a Service](https://docs.nextcloud.com/server/latest/admin_manual/ai/ai_as_a_service.html#ai-ai-as-a-service) ) * Or * [llm2](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_llm2.html#ai-app-llm2) - Runs open source AI language models locally on your own server hardware (Customer support available upon request) * [stt\_whisper2](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_stt_whisper2.html#ai-app-stt-whisper2) - Runs open source AI Speech-To-Text models on your own server hardware (Customer support available upon request) * [text2speech\_kokoro](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_text2speech_kokoro.html#ai-app-text2speech-kokoro) - Runs open source AI Text-To-Speech models on your own server hardware (Customer support available upon request) ### Context Agent[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#context-agent "Link to this heading") In order to make use of our AI agent feature, offering the execution of actions on behalf of the user based on the AI chat, you will need the following apps: * [context\_agent](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_context_agent.html#ai-app-context-agent) - (Customer support available upon request) You will also need a text processing provider as specified above (ie. _llm2_ or _integration\_openai_). ### Text-To-Speech[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#text-to-speech "Link to this heading") In order to make use of Text-To-Speech, you will need an app that provides a Text-To-Speech backend, which is one of the following: * [OpenAI and LocalAI integration (via OpenAI API)](https://apps.nextcloud.com/apps/integration_openai) - Integrates with the OpenAI API to provide AI functionality from OpenAI servers (Customer support available upon request; see [AI as a Service](https://docs.nextcloud.com/server/latest/admin_manual/ai/ai_as_a_service.html#ai-ai-as-a-service) ) * [text2speech\_kokoro](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_text2speech_kokoro.html#ai-app-text2speech-kokoro) - Runs open source AI Text-To-Speech models on your own server hardware (Customer support available upon request) Configuration[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#configuration "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------- The Assistant admin settings can be found under the “Artificial intelligence” section. You can disable the assistant top menu entry there. You can also disable the AI-related smart pickers. The occ commands to change the options are listed below. ### Assistant configuration[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#assistant-configuration "Link to this heading") 1. Top-right Assistant occ config:app:set assistant assistant\_enabled \--value\=1 \--type\=string To enable/disable the assistant button from the top-right corner for all the users. 2. AI text generation smart picker occ config:app:set assistant free\_prompt\_picker\_enabled \--value\=1 \--type\=string To enable/disable the AI text generation smart picker for all the users. 3. Text-to-image smart picker occ config:app:set assistant text\_to\_image\_picker\_enabled \--value\=1 \--type\=string To enable/disable the text-to-image smart picker for all the users. 4. Speech-to-text smart picker occ config:app:set assistant speech\_to\_text\_picker\_enabled \--value\=1 \--type\=string To enable/disable the speech-to-text smart picker for all the users. ### Task processing[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#task-processing "Link to this heading") 1. List Tasks occ taskprocessing:task:list lists all task processing tasks. 2. Get Task occ taskprocessing:task:get $TASK\_ID shows all information for a specific task. 3. Enable or disable a Task type occ taskprocessing:task-type:set-enabled $TASK\_TYPE\_ID 1 Set 1 to enable and 0 to disable an implemented task type. 4. Get Task statistics occ taskprocessing:task:stats shows statistics for all task processing Tasks. 5. Clean-up old tasks occ taskprocessing:task:cleanup delete tasks that are older than this number of seconds, defaults to 4 months. ### Image storage[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#image-storage "Link to this heading") Days until generated images are deleted if they are not viewed. occ config:app:set assistant max\_image\_generation\_idle\_time \--value\=90 \--type\=integer ### Chat with AI[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#chat-with-ai "Link to this heading") 1. Chat User Instructions for Chat Completions occ config:app:set assistant chat\_user\_instructions \--value\="hello world" The user instructions that are prepended before the chat messages for the AI model to understand the context of the block of text. This is a good place not only to instruct the AI model to be polite and kind but also to for example answer all the queries in a particular language or better yet, follow the user’s language. The sky is the limit. **Note**: The default instructions are optimized to work well across a variety of language models, but may not be optimal for the specific model you choose. Specifically, the model may be tempted to mention the user’s name a bit too often and may mention the user’s language in an unusual manner. 2. Chat User Instructions for Title Generation occ config:app:set assistant chat\_user\_instructions\_title \--value\="hello title" This field is appended to the block of chat messages, i.e. attached after the messages. It is done this way to allow it to be used even with text completion models which could have the instructions as “The title for the above conversation could be "”. 3. Last N messages to consider for chat completions occ config:app:set assistant chat\_last\_n\_messages \--value\=10 The number of latest messages to consider for generating the next message. This does not include the user instructions, which is always considered in addition to this. This value should be adjusted in case you are hitting the token limit in your conversations too often. The AI text generation provider should ideally handle the max token limit case. ### Improve AI task pickup speed[](https://docs.nextcloud.com/server/latest/admin_manual/ai/app_assistant.html#improve-ai-task-pickup-speed "Link to this heading") See [the relevant section in AI Overview](https://docs.nextcloud.com/server/latest/admin_manual/ai/overview.html#ai-overview-improve-ai-task-pickup-speed) for more information. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/admin_manual) [stable](https://docs.nextcloud.com/server/stable/admin_manual) [32](https://docs.nextcloud.com/server/32/admin_manual) [31](https://docs.nextcloud.com/server/31/admin_manual) --- # Request lifecycle — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/stable/developer_manual/basics/index.html) * Request lifecycle * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/request_lifecycle.rst) * * * Request lifecycle[](https://docs.nextcloud.com/server/stable/developer_manual/basics/request_lifecycle.html#request-lifecycle "Link to this heading") ======================================================================================================================================================= A typical HTTP request consists of the following: * **A URL**: e.g. /index.php/apps/myapp/something * **Request Parameters**: e.g. ?something=true&name=tom * **A Method**: e.g. GET * **Request headers**: e.g. Accept: application/json The following sections will present an overview over how that request is being processed to provide an in depth view over how Nextcloud works. If you are not interested in the internals or don’t want to execute anything before and after your controller, feel free to skip this section and continue directly with defining [your app’s routes](https://docs.nextcloud.com/server/stable/developer_manual/basics/routing.html) . Front controller[](https://docs.nextcloud.com/server/stable/developer_manual/basics/request_lifecycle.html#front-controller "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- In the beginning, all requests are sent to Nextcloud’s `index.php` which in turn executes `lib/base.php`. This file inspects the HTTP headers, abstracts away differences between different Web servers and initializes the basic classes. Afterwards the basic apps are being loaded in the following order: * Authentication backends * Filesystem * Logging The type of the app is determined by inspecting the app’s [configuration file](https://docs.nextcloud.com/server/stable/developer_manual/app_development/info.html) (`appinfo/info.xml`). Each installed app is being loaded and executed (see [Bootstrap](https://docs.nextcloud.com/server/stable/developer_manual/app_development/bootstrap.html) ). That means that if you want to execute code before a specific app is being run, you can place code in your app’s [Navigation and pre-app configuration](https://docs.nextcloud.com/server/stable/developer_manual/app_development/init.html) file. Afterwards the following steps are performed: * Try to authenticate the user * Load and execute all the remaining apps’ [Navigation and pre-app configuration](https://docs.nextcloud.com/server/stable/developer_manual/app_development/init.html) files * Load and run all the routes in the apps’ `appinfo/routes.php` * Execute the router ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Request lifecycle — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/32/developer_manual/basics/index.html) * Request lifecycle * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/request_lifecycle.rst) * * * Request lifecycle[](https://docs.nextcloud.com/server/32/developer_manual/basics/request_lifecycle.html#request-lifecycle "Link to this heading") =================================================================================================================================================== A typical HTTP request consists of the following: * **A URL**: e.g. /index.php/apps/myapp/something * **Request Parameters**: e.g. ?something=true&name=tom * **A Method**: e.g. GET * **Request headers**: e.g. Accept: application/json The following sections will present an overview over how that request is being processed to provide an in depth view over how Nextcloud works. If you are not interested in the internals or don’t want to execute anything before and after your controller, feel free to skip this section and continue directly with defining [your app’s routes](https://docs.nextcloud.com/server/32/developer_manual/basics/routing.html) . Front controller[](https://docs.nextcloud.com/server/32/developer_manual/basics/request_lifecycle.html#front-controller "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------- In the beginning, all requests are sent to Nextcloud’s `index.php` which in turn executes `lib/base.php`. This file inspects the HTTP headers, abstracts away differences between different Web servers and initializes the basic classes. Afterwards the basic apps are being loaded in the following order: * Authentication backends * Filesystem * Logging The type of the app is determined by inspecting the app’s [configuration file](https://docs.nextcloud.com/server/32/developer_manual/app_development/info.html) (`appinfo/info.xml`). Each installed app is being loaded and executed (see [Bootstrap](https://docs.nextcloud.com/server/32/developer_manual/app_development/bootstrap.html) ). That means that if you want to execute code before a specific app is being run, you can place code in your app’s [Navigation and pre-app configuration](https://docs.nextcloud.com/server/32/developer_manual/app_development/init.html) file. Afterwards the following steps are performed: * Try to authenticate the user * Load and execute all the remaining apps’ [Navigation and pre-app configuration](https://docs.nextcloud.com/server/32/developer_manual/app_development/init.html) files * Load and run all the routes in the apps’ `appinfo/routes.php` * Execute the router ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Middlewares — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/32/developer_manual/basics/index.html) * Middlewares * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/middlewares.rst) * * * Middlewares[](https://docs.nextcloud.com/server/32/developer_manual/basics/middlewares.html#middlewares "Link to this heading") ================================================================================================================================= Middleware is logic that is run before and after each request and is modeled after [Django’s Middleware system](https://docs.djangoproject.com/en/dev/topics/http/middleware/) . It offers the following hooks: * `beforeController`: This is executed before a controller method is being executed. This allows you to plug additional checks or logic before that method, like for instance security checks * `afterException`: This is being run when either the beforeController method or the controller method itself is throwing an exception. The middleware is asked in reverse order to handle the exception and to return a response. If the middleware can’t handle the exception, it throws the exception again * `afterController`: This is being run after a successful controller method call and allows the manipulation of a Response object. The middleware is run in reverse order * `beforeOutput`: This is being run after the response object has been rendered and allows the manipulation of the outputted text. The middleware is run in reverse order ![Middleware flow chart](https://docs.nextcloud.com/server/32/developer_manual/_images/middleware-flow-horiz.png) To generate your own middleware, simply inherit from the Middleware class and overwrite the methods that should be used. registerMiddleware(CensorMiddleware::class); } public function boot(IBootContext $context): void {} } Global Middlewares[](https://docs.nextcloud.com/server/32/developer_manual/basics/middlewares.html#global-middlewares "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------- Added in version 26. Registered middleware will only intercept requests of the same app by default. To make a middleware _global_ and trigger for other apps’ middleware, add true as the second argument of the `registerMiddleware` call: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/32/developer_manual/basics/middlewares.html#id3 "Link to this code") registerMiddleware(MonitoringMiddleware::class, true); } public function boot(IBootContext $context): void {} } Dependency Injection Container Registration[](https://docs.nextcloud.com/server/32/developer_manual/basics/middlewares.html#dependency-injection-container-registration "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Deprecated since version 20. Middleware can also be added using the **registerMiddleware** method of the container: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/32/developer_manual/basics/middlewares.html#id4 "Link to this code") getContainer(); // executed in the order that it is registered $container\->registerMiddleware(CensorMiddleware::class); } } Note The order is important! The middleware that is registered first gets run first in the **beforeController** method. For all other hooks, the order is being reversed, meaning: if a middleware is registered first, it gets run last. Parsing annotations[](https://docs.nextcloud.com/server/32/developer_manual/basics/middlewares.html#parsing-annotations "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it is useful to conditionally execute code before or after a controller method. This can be done by defining custom annotations. An example would be to add a custom authentication method or simply add an additional header to the response. To access the parsed annotations, inject the **ControllerMethodReflector** class: reflector \= $reflector; } /\*\* \* Add custom header if @MyHeader is used \*/ public function afterController($controller, $methodName, Response $response): Response { if($this\->reflector\->hasAnnotation('MyHeader')) { $response\->addHeader('My-Header', 3); } return $response; } } Note An annotation always starts with an uppercase letter ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Caching — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/31/developer_manual/basics/index.html) * Caching * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/caching.rst) * * * Caching[](https://docs.nextcloud.com/server/31/developer_manual/basics/caching.html#caching "Link to this heading") ===================================================================================================================== Results of expensive or slow operations can be cached to speed up Nextcloud and its apps. Types of caches[](https://docs.nextcloud.com/server/31/developer_manual/basics/caching.html#types-of-caches "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------- Nextcloud offers in-memory, local and distributed caches. The caching back-end (APCu, Redis, Memcached) is configurable. For single server setups, admins typically only configure one type of cache. Larger installations can have two types of cache. The Nextcloud API lets you pick a cache type. The following table tries to highlight the main advantages and disadvantages of each type. | | In-memory cache | Local cache | Distributed cache | | --- | --- | --- | --- | | **Latency** | Low | Low | High | | **Data scope** | Same process | Application server | Full cluster | | **Expiration** | End of process | TTL reached | TTL reached | For scalability it should be preferred to use local caches. A local cache has to be populated on each application server, but avoids creating a bottleneck of too much traffic on the distributed cache. A distributed cache is most useful for data that _has to be synchronized_ across the full Nextcloud cluster. In-memory cache[](https://docs.nextcloud.com/server/31/developer_manual/basics/caching.html#in-memory-cache "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------- The `OCP\Cache\CappedMemoryCache` class is an in-memory cache that can be used like an array: lib/Service/PictureService.php[](https://docs.nextcloud.com/server/31/developer_manual/basics/caching.html#id1 "Link to this code") cache \= new CappedMemoryCache(64); } public function getPicture(string $url): void { if (isset($this\->cache\[$url\])) { return $this\->cache\[$url\]; } // Fetch picture and serialize result into $picture $this\->cache\[$url\] \= $picture; return $picture; } } A cache instance can also be built by the cache factory. This approach allows mocking the injected factory for finer control during [unit testing](https://docs.nextcloud.com/server/31/developer_manual/basics/testing.html#testing-php) : lib/Service/PictureService.php[](https://docs.nextcloud.com/server/31/developer_manual/basics/caching.html#id2 "Link to this code") cacheFactory \= $cacheFactory; } public function getPicture(string $url): void { // Initialize the cache. The instance has to be remembered because // each call to \`createInMemory\` returns a fresh, empty cache. if ($this\->cache \=== null) { $this\->cache \= $this\->cacheFactory\->createInMemory(64); } if (isset($this\->cache\[$url\])) { return $this\->cache\[$url\]; } // Fetch picture and serialize result into $picture $this\->cache\[$url\] \= $picture; return $picture; } } Local cache[](https://docs.nextcloud.com/server/31/developer_manual/basics/caching.html#local-cache "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------- A local cache instance can be acquired through the `\OCP\ICacheFactory` service. The factory can be injected: lib/Service/PictureService.php[](https://docs.nextcloud.com/server/31/developer_manual/basics/caching.html#id3 "Link to this code") cacheFactory \= $cacheFactory; } public function getPicture(string $url): void { $cache \= $this\->cacheFactory\->createLocal('my-app-pictures'); $cachedPicture \= $cache\->get($url); if ($cachedPicture !== null) { return $cachedPicture; } // Fetch picture and serialize result into $picture $cache\->set($url, $picture, 6 \* 3600); // Cache result for 6h return $picture; } } Distributed cache[](https://docs.nextcloud.com/server/31/developer_manual/basics/caching.html#distributed-cache "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------- A distributed cache instance can be acquired through the `\OCP\ICacheFactory` service. The factory can be injected: lib/Service/PictureService.php[](https://docs.nextcloud.com/server/31/developer_manual/basics/caching.html#id4 "Link to this code") cacheFactory \= $cacheFactory; } public function getPicture(string $url): void { $cache \= $this\->cacheFactory\->createDistributed('my-app-pictures'); $cachedPicture \= $cache\->get($url); if ($cachedPicture !== null) { return $cachedPicture; } // Fetch picture and serialize result into $picture $cache\->set($url, $picture, 6 \* 3600); // Cache result for 6h return $picture; } } ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Introduction — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/stable/developer_manual/app_development/index.html) * Introduction * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/intro.rst) * * * Introduction[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/intro.html#introduction "Link to this heading") ========================================================================================================================================== Create an app[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/intro.html#create-an-app "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------- After [you’ve set up the development environment](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/devenv.html) change into the Nextcloud apps directory: cd /var/www/nextcloud/apps Then create a skeleton app in the [app store](https://apps.nextcloud.com/developer/apps/generate) . This doesn’t publish anything on the appstore yet, it just gives you a download. Edit an existing app[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/intro.html#edit-an-existing-app "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------- Alternatively, if you would like to contribute to an existing app instead of creating a new one, first [set up the development environment](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/devenv.html) , then create an apps-extra folder in the Nextcloud root directory: cd /var/www/nextcloud/apps\-extra You can then configure Nextcloud to run apps from this directory, by changing your app\_paths system config in your config.php 'apps\_paths' \=> array ( 0 \=> array ( 'path' \=> '/var/www/html/apps', 'url' \=> '/apps', 'writable' \=> false, ), 1 \=> array ( 'path' \=> '/var/www/html/apps-extra', 'url' \=> '/apps-extra', 'writable' \=> false, ), ), Finally, clone the app to which you would like to contribute inside the apps-extra folder. For example: > git clone [https://github.com/nextcloud/cookbook.git](https://github.com/nextcloud/cookbook.git) Enable the app[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/intro.html#enable-the-app "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- The app can now be enabled on the Nextcloud apps page. App architecture[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/intro.html#app-architecture "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- The following directories have now been created: * **appinfo/**: Contains app metadata and configuration * **css/**: Contains the CSS * **img/**: Contains icons and images * **js/**: Contains the JavaScript files * **lib/**: Contains the PHP class files of your app * **src/**: Contains the source code of your vue.js app * **templates/**: Contains the templates * **tests/**: Contains the tests ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Bootstrapping — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/32/developer_manual/app_development/index.html) * Bootstrapping * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/bootstrap.rst) * * * Bootstrapping[](https://docs.nextcloud.com/server/32/developer_manual/app_development/bootstrap.html#bootstrapping "Link to this heading") ============================================================================================================================================ Every php process has a relatively short lifespan that lasts as long as the HTTP request or the invocation of the command line program. At the beginning of this lifespan, Nextcloud initializes its services. At the same time, any additional apps might want to register their services to Nextcloud as well. This event is called the _bootstrapping_ and this chapter shall shed some light on how to hook into this with an app. The Application class[](https://docs.nextcloud.com/server/32/developer_manual/app_development/bootstrap.html#the-application-class "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------ The Application class is the main entry point of an app. This class is optional but highly recommended if your app needs to register any services or run some code for every request. Nextcloud will try to autoload the class from the namespace `\OCA\\AppInfo\Application`, like `\OCA\MyApp\AppInfo\Application`, where _MyApp_ would be the name of your app. The file will therefore have the location `myapp/lib/AppInfo/Application.php`. registerEventListener( BeforeUserDeletedEvent::class, UserDeletedListener::class ); } public function boot(IBootContext $context): void { // ... boot logic goes here ... /\*\* @var IManager $manager \*/ $manager \= $context\->getAppContainer()\->query(IManager::class); $manager\->registerNotifierService(Notifier::class); } } Note that the context objects of the methods `register` and `boot` have different interfaces and thus have different capabilities appropriate for their stage. Bootstrapping process[](https://docs.nextcloud.com/server/32/developer_manual/app_development/bootstrap.html#bootstrapping-process "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------ To give a better overview of _when_ each of the bootstrapping stages are reached and how they app can interact with them, this section explains the changes done for Nextcloud 20. ### Nextcloud 20 and later[](https://docs.nextcloud.com/server/32/developer_manual/app_development/bootstrap.html#nextcloud-20-and-later "Link to this heading") Nextcloud 20 is the first release with the interface `\OCP\AppFramework\Bootstrap\IBootstrap`. This interface can be implemented by your app’s `Application` class to signal that it wants to act on the bootstrapping stages. The major difference between this and the old process is that the bootstrapping is not performed in sequence, but apps register and boot interleaved. This should ensure that an app that `boot`s can rely on all other apps’ registration to be finished. The overall process is as follows: 1. In each installed and enabled app that has an `Application` class that also implements `IBootstrap`, the `register` method will be called. This method receives a context argument via which the app can prime the dependency injection container and register other services lazily, e.g. by calling `$context->registerService(...)`. The emphasis is on **laziness**. At this very early stage of the process lifetime, no other apps nor all of the server components are ready. Therefore the app **must not** try to use anything except the API provided by the context. That shall ensure that all apps can safely run their registration logic before any services are queried (instantiated) from the DI container or related code is run. 2. Nextcloud will load groups of certain apps early, e.g. filesystem or session apps, and other later. 3. Nextcloud will query the app’s `Application` class (again), no matter whether it implements `IBootstrap` or not. 4. Nextcloud will invoke the [boot](https://docs.nextcloud.com/server/32/developer_manual/app_development/bootstrap.html#app-bootstrap-boot) method of every `Application` instance that implements `IBootstrap`. At this stage you may assume that all registrations via `IBootstrap::register` have completed. #### Booting an app[](https://docs.nextcloud.com/server/32/developer_manual/app_development/bootstrap.html#booting-an-app "Link to this heading") Any code that should run once for every Nextcloud process goes into the `boot` method of an app’s `Application` class. Use this mechanism carefully as it could have a negative effect on Nextcloud’s overall performance. lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/32/developer_manual/app_development/bootstrap.html#id3 "Link to this code") getAppContainer()\->query(IFooManager::class); $manager\->registerCustomFoo(MyFooImpl::class); } } The code above fetches a fictional _foo manager_ to register an app class. The boot context object comes with a `injectFn` helper that eases dependency injection inside the `boot` method by injecting arguments of a callable: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/32/developer_manual/app_development/bootstrap.html#id4 "Link to this code") injectFn(function(IFooManager $manager) { $manager\->registerCustomFoo(MyFooImpl::class); }); } } With the help of `Closure::fromCallable` you can also delegate to other methods that get their arguments injected: lib/AppInfo/Application.php[](https://docs.nextcloud.com/server/32/developer_manual/app_development/bootstrap.html#id5 "Link to this code") injectFn($this\->registerFoo(...)); } protected function registerFoo(IFooManager $manager): void { $manager\->registerCustomFoo(MyFooImpl::class); } } ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Setting up dev environment — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/index.html) * Setting up dev environment * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/DevSetup.rst) * * * Setting up dev environment[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/DevSetup.html#setting-up-dev-environment "Link to this heading") =========================================================================================================================================================================== AppAPI development requires a Nextcloud development environment setup. We highly recommend using [Julius Knorr’s Docker setup](https://github.com/juliusknorr/nextcloud-docker-dev) for this. For an alternate environment without using Docker, please refer to the setup instructions in [Getting started](https://docs.nextcloud.com/server/stable/developer_manual/getting_started/devenv.html) . Suggested IDE: **PhpStorm**, though you can certainly use any IDE of your preference such as **VS Code** or **Vim**. Install AppAPI[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/DevSetup.html#install-appapi "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------- All ExApps require the [AppAPI](https://apps.nextcloud.com/apps/app_api) Nextcloud app as a dependency. As of Nextcloud version 30.0.1, AppAPI is automatically installed by default. If you prefer, you can also build the latest development version of AppAPI from the source code, in which case uninstall the release version of AppAPI and perform the following steps. Clone the latest main branch: > git clone https://github.com/nextcloud/app\_api.git && cd app\_api or clone a specific version by specifying the version tag: > git clone https://github.com/nextcloud/app\_api.git \--branch && cd app\_api where `` is the version you want to install. Then, build frontend assets in development mode: > npm ci && npm run dev Enable AppAPI from the directory where the `occ` command resides: > ./occ app:enable \--force app\_api ### Deploy daemons types[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/DevSetup.html#deploy-daemons-types "Link to this heading") There are two types of Deploy daemons that can be used for development and testing of ExApps: 1. `manual_install`: This type of Deploy daemon is running manually in the host machine. This is useful for ExApp development as you can run your ExApp directly on the host. 2. `docker_install`: This type of Deploy daemon is running in a Docker container. You can register (create) these daemons in the AppAPI admin settings. For the equivalent `occ` command or an explanation of the Deploy daemon parameters, see [DaemonConfig registration](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/tech_details/Deployment.html#occ-daemon-config-registration) . ### Docker Socket Proxy[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/DevSetup.html#docker-socket-proxy "Link to this heading") For development and testing locally, the simplest way is to use the [Nextcloud AppAPI DSP HTTP](https://github.com/nextcloud/docker-socket-proxy?tab=readme-ov-file#httplocal) . In Place of a Conclusion[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/DevSetup.html#in-place-of-a-conclusion "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- There are several make commands available to ease frequent development actions. To see the complete list, execute `make help`. ### Docker remote API[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/DevSetup.html#docker-remote-api "Link to this heading") The Docker Engine remote API can be easily configured via `make dock2port` command. The command will create a docker container to provide remote Docker Engine API. Afterward, register DaemonConfigs in Nextcloud using `make dock-port` command. ### Docker by socket[](https://docs.nextcloud.com/server/stable/developer_manual/exapp_development/DevSetup.html#docker-by-socket "Link to this heading") For Docker via socket, use the command `make dock-sock`. This registers DaemonConfigs in Nextcloud for the default socket connection (`/var/run/docker.sock`). Make sure that socket has enough permissions for Nextcloud and webserver user to access it and actually forwarded to the container: ... volumes: ... \- /var/run/docker.sock:/var/run/docker.sock ... ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Static analysis — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/31/developer_manual/server/index.html) * Static analysis * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/server/static-analysis.rst) * * * Static analysis[](https://docs.nextcloud.com/server/31/developer_manual/server/static-analysis.html#static-analysis "Link to this heading") ============================================================================================================================================= PHP static analysis[](https://docs.nextcloud.com/server/31/developer_manual/server/static-analysis.html#php-static-analysis "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- In the server repository psalm is used for static analysis of the PHP code. ### Required PHP extensions[](https://docs.nextcloud.com/server/31/developer_manual/server/static-analysis.html#required-php-extensions "Link to this heading") The following PHP extensions are required to be installed and enabled to make psalm work: * acpu * curl * ftp * gd * iconv * imagick * json * ldap * libxml * mbstring * openssl * pdo * simplexml * sysvsem * xmlreader * zip Some of these are for optional features, but are still required to validate the code. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Setting up dev environment — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [ExApp development](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/index.html) * Setting up dev environment * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/exapp_development/DevSetup.rst) * * * Setting up dev environment[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/DevSetup.html#setting-up-dev-environment "Link to this heading") ======================================================================================================================================================================= AppAPI development requires a Nextcloud development environment setup. We highly recommend using [Julius Knorr’s Docker setup](https://github.com/juliusknorr/nextcloud-docker-dev) for this. For an alternate environment without using Docker, please refer to the setup instructions in [Getting started](https://docs.nextcloud.com/server/32/developer_manual/getting_started/devenv.html) . Suggested IDE: **PhpStorm**, though you can certainly use any IDE of your preference such as **VS Code** or **Vim**. Install AppAPI[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/DevSetup.html#install-appapi "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------- All ExApps require the [AppAPI](https://apps.nextcloud.com/apps/app_api) Nextcloud app as a dependency. As of Nextcloud version 30.0.1, AppAPI is automatically installed by default. If you prefer, you can also build the latest development version of AppAPI from the source code, in which case uninstall the release version of AppAPI and perform the following steps. Clone the latest main branch: > git clone https://github.com/nextcloud/app\_api.git && cd app\_api or clone a specific version by specifying the version tag: > git clone https://github.com/nextcloud/app\_api.git \--branch && cd app\_api where `` is the version you want to install. Then, build frontend assets in development mode: > npm ci && npm run dev Enable AppAPI from the directory where the `occ` command resides: > ./occ app:enable \--force app\_api ### Deploy daemons types[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/DevSetup.html#deploy-daemons-types "Link to this heading") There are two types of Deploy daemons that can be used for development and testing of ExApps: 1. `manual_install`: This type of Deploy daemon is running manually in the host machine. This is useful for ExApp development as you can run your ExApp directly on the host. 2. `docker_install`: This type of Deploy daemon is running in a Docker container. You can register (create) these daemons in the AppAPI admin settings. For the equivalent `occ` command or an explanation of the Deploy daemon parameters, see [DaemonConfig registration](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/tech_details/Deployment.html#occ-daemon-config-registration) . ### Docker Socket Proxy[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/DevSetup.html#docker-socket-proxy "Link to this heading") For development and testing locally, the simplest way is to use the [Nextcloud AppAPI DSP HTTP](https://github.com/nextcloud/docker-socket-proxy?tab=readme-ov-file#httplocal) . In Place of a Conclusion[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/DevSetup.html#in-place-of-a-conclusion "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- There are several make commands available to ease frequent development actions. To see the complete list, execute `make help`. ### Docker remote API[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/DevSetup.html#docker-remote-api "Link to this heading") The Docker Engine remote API can be easily configured via `make dock2port` command. The command will create a docker container to provide remote Docker Engine API. Afterward, register DaemonConfigs in Nextcloud using `make dock-port` command. ### Docker by socket[](https://docs.nextcloud.com/server/32/developer_manual/exapp_development/DevSetup.html#docker-by-socket "Link to this heading") For Docker via socket, use the command `make dock-sock`. This registers DaemonConfigs in Nextcloud for the default socket connection (`/var/run/docker.sock`). Make sure that socket has enough permissions for Nextcloud and webserver user to access it and actually forwarded to the container: ... volumes: ... \- /var/run/docker.sock:/var/run/docker.sock ... ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Back-end code — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/31/developer_manual/server/index.html) * Back-end code * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/server/code-back-end.rst) * * * Back-end code[](https://docs.nextcloud.com/server/31/developer_manual/server/code-back-end.html#back-end-code "Link to this heading") ======================================================================================================================================= When changing back-end PHP code, in general, no additional steps are needed before checking in. However, if new files were created, you will need to run the following command to update the autoloader files: build/autoloaderchecker.sh After that, please also include the autoloader file changes in your commits. Compatibility documentation[](https://docs.nextcloud.com/server/31/developer_manual/server/code-back-end.html#compatibility-documentation "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- * New APIs (interfaces, constants, methods, classes, traits, enums) added to the public namespace `OCP` have to be annotated with a `@since X.Y.Z` attribute of the version it was added in. * When it is backported the version should be adjusted to the X.Y.Z of the stable version it was backported in only in that stable branch. The master branch should still contain the newest Major version shipping the API. * Once an API was shipped, unless it is marked as experimental, it has to be deprecated in similar fashion using `@deprecated X.Y.Z` for 3 years (9 Nextcloud releases) before it can be removed. Deprecations have to be clearly documented in the [App upgrade guide](https://docs.nextcloud.com/server/31/developer_manual/app_publishing_maintenance/app_upgrade_guide/index.html#app-upgrade-guide) for the upcoming Major version. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Dependency injection — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/32/developer_manual/basics/index.html) * Dependency injection * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/dependency_injection.rst) * * * Dependency injection[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#dependency-injection "Link to this heading") ============================================================================================================================================================ The App Framework assembles the application by using a container based on the software pattern [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) . This makes the code easier to test and thus easier to maintain. If you are unfamiliar with this pattern, watch the following video: * [Google Clean Code Talks](https://www.youtube.com/watch?v=RlfLCWKxHJ0) Dependency injection[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#id2 "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------- Dependency Injection sounds pretty complicated but it just means: Don’t put new dependencies in your constructor or methods but pass them in. So this: use OCP\\IDBConnection; // without dependency injection class AuthorMapper { private IDBConnection $db; public function \_\_construct() { $this\->db \= new Db(); } } would turn into this by using Dependency Injection: use OCP\\IDBConnection; // with dependency injection class AuthorMapper { private IDBConnection $db; public function \_\_construct(IDBConnection $db) { $this\->db \= $db; } } Controller injection[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#controller-injection "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------ For controllers it’s possible to also have dependencies injected into methods. lib/Controller/ApiController.php[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#id4 "Link to this code") foo(); } public function bar(BarService $service) { $service\->bar(); } } Using a container[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#using-a-container "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------ Note Please do use automatic dependency injection (see below). For most apps there is no need to register services manually. Passing dependencies into the constructor rather than instantiating them in the constructor has the following drawback: Every line in the source code where **new AuthorMapper** is being used has to be changed, once a new constructor argument is being added to it. The solution for this particular problem is to limit the **new AuthorMapper** to one file, the container. The container contains all the factories for creating these objects and is configured in `lib/AppInfo/Application.php`. Nextcloud 20 and later uses the [PSR-11 standard](https://docs.nextcloud.com/server/32/developer_manual/digging_deeper/psr.html#psr11) for the container interface, so working with the container might feel familiar if you’ve worked with other php applications before that also adhere to the convention. To add the app’s classes simply open the `lib/AppInfo/Application.php` and use the **IRegistrationContext::registerService** method: registerService(AuthorController::class, function(ContainerInterface $c): AuthorController { return new AuthorController( $c\->get('appName'), $c\->get(Request::class), $c\->get(AuthorService::class) ); }); /\*\* \* Services \*/ $context\->registerService(AuthorService::class, function(ContainerInterface $c): AuthorService { return new AuthorService( $c\->get(AuthorMapper::class) ); }); /\*\* \* Mappers \*/ $context\->registerService(AuthorMapper::class, function(ContainerInterface $c): AuthorMapper { return new AuthorMapper( $c\->get(IDBConnection::class) ); }); } } How the container works[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#how-the-container-works "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ The container works in the following way: * [A request comes in and is matched against a route](https://docs.nextcloud.com/server/32/developer_manual/basics/routing.html) (for the AuthorController in this case) * The matched route queries **AuthorController** service from the container: return new AuthorController( $c->get('appName'), $c->get(Request::class), $c->get(AuthorService::class) ); * The **appName** is queried and returned from the base class * The **Request** is queried and returned from the server container * **AuthorService** is queried: $container->registerService(AuthorService::class, function(ContainerInterface $c): AuthorService { return new AuthorService( $c->get(AuthorMapper::class) ); }); * **AuthorMapper** is queried: $container->registerService(AuthorMappers::class, function(ContainerInterface $c): AuthorMapper { return new AuthorService( $c->get(IDBConnection::class) ); }); * The **database connection** is returned from the server container * Now **AuthorMapper** has all of its dependencies and the object is returned * **AuthorService** gets the **AuthorMapper** and returns the object * **AuthorController** gets the **AuthorService** and finally the controller can be instantiated and the object is returned So basically the container is used as a giant factory to build all the classes that are needed for the application. Because it centralizes all the creation of objects (the **new Class()** lines), it is very easy to add new constructor parameters without breaking existing code: only the **\_\_construct** method and the container line where the **new** is being called need to be changed. Use automatic dependency assembly (recommended)[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#use-automatic-dependency-assembly-recommended "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- In Nextcloud it is possible to build classes and their dependencies without having to explicitly register them on the container, as long as the container can [reflect](https://www.php.net/manual/en/book.reflection.php) the constructor and look up the parameters by their type. This concept is widely known as _auto-wiring_. ### How does auto-wiring work[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#how-does-auto-wiring-work "Link to this heading") Automatic assembly creates new instances of classes just by looking at the class name and its constructor parameters. For each constructor parameter the type or the argument name is used to query the container, e.g.: * **SomeType $type** will use **$container->get(SomeType::class)** * **$variable** will use **$container->get(‘variable’)** If all constructor parameters are resolved, the class will be created, saved as a service and returned. So basically the following is now possible: class \= $class; $this\->appName \= $appName; } } $app \= new \\OCP\\AppFramework\\App('myapp'); $class2 \= $app\->getContainer()\->get(MyTestClass2::class); $class2 instanceof MyTestClass2; // true $class2\->class instanceof MyTestClass; // true $class2\->appName \=== 'myname'; // true $class2 \=== $app\->getContainer()\->get(MyTestClass2::class); // true Note $appName is resolved because the container registered a parameter under the key ‘appName’ which will return the app id. ### How does it affect the request lifecycle[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#how-does-it-affect-the-request-lifecycle "Link to this heading") * A request comes in * All apps’ **routes.php** files are loaded * If a **routes.php** file returns an array, and an **appname/lib/AppInfo/Application.php** exists, include it, create a new instance of **\\OCA\\AppName\\AppInfo\\Application.php** and register the routes on it. That way a container can be used while still benefitting from the new routes behavior * If a **routes.php** file returns an array, but there is no **appname/lib/AppInfo/Application.php**, create a new \\OCP\\AppFramework\\App instance with the app id and register the routes on it * A request is matched for the route, e.g. with the name **page#index** * The appropriate container is being queried for the entry PageController (to keep backwards compatibility) * If the entry does not exist, the container is queried for OCA\\AppName\\Controller\\PageController and if no entry exists, the container tries to create the class by using [reflection](https://www.php.net/manual/en/book.reflection.php) on its constructor parameters ### How does this affect controllers[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#how-does-this-affect-controllers "Link to this heading") The only thing that needs to be done to add a route and a controller method is now: **myapp/appinfo/routes.php** \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \]\]; **myapp/appinfo/lib/Controller/PageController.php** registerParameter('TableName', 'my\_app\_table'); // the interface is called IAuthorMapper and AuthorMapper implements it $context\->registerService(IAuthorMapper::class, function (ContainerInterface $c): AuthorMapper { return $c\->get(AuthorMapper::class); }); // Less verbose alternative $context\->registerServiceAlias(IAuthorMapper::class, AuthorMapper::class); } } ### Predefined core services[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#predefined-core-services "Link to this heading") The following parameter names and type hints can be used to inject core services instead of using **$container->getServer()->getServiceX()** Parameters: * **appName**: The app id * **userId**: The id of the current user * **webRoot**: The path to the Nextcloud installation Aliases: * **AppName**: resolves to `appName` (deprecated) * **Request**: resolves to `\OCP\IRequest` * **ServerContainer**: resolves to `\OCP\IServerContainer` (deprecated) * **UserId**: resolves to `userId` (deprecated) * **WebRoot**: resolves to `webRoot` (deprecated) Types: * `\OCP\IAppConfig` * `\OCP\IAppManager` * `\OCP\IAvatarManager` * `\OCP\Activity\IManager` * `\OCP\ICache` * `\OCP\ICacheFactory` * `\OCP\IConfig` * `\OCP\AppFramework\Utility\IControllerMethodReflector` * `\OCP\Contacts\IManager` * `\OCP\IDateTimeZone` * `\OCP\IDBConnection` * `\OCP\Diagnostics\IEventLogger` * `\OCP\Diagnostics\IQueryLogger` * `\OCP\Files\Config\IMountProviderCollection` * `\OCP\Files\IRootFolder` * `\OCP\IGroupManager` * `\OCP\IL10N` * `\OCP\BackgroundJob\IJobList` * `\OCP\INavigationManager` * `\OCP\IPreview` * `\OCP\IRequest` * `\OCP\AppFramework\Utility\ITimeFactory` * `\OCP\ITagManager` * `\OCP\ITempManager` * `\OCP\Route\IRouter` * `\OCP\ISearch` * `\OCP\Security\ICrypto` * `\OCP\Security\IHasher` * `\OCP\Security\ISecureRandom` * `\OCP\IURLGenerator` * `\OCP\IUserManager` * `\OCP\IUserSession` * `\Psr\Container\ContainerInterface` * `\Psr\Log\LoggerInterface` ### How to enable it[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#how-to-enable-it "Link to this heading") To make use of this new feature, the following things have to be done: * **appinfo/info.xml** requires to provide another field called **namespace** where the namespace of the app is defined. The required namespace is the one which comes after the top level namespace **OCA\\**, e.g.: for **OCA\\MyBeautifulApp\\Some\\OtherClass** the needed namespace would be **MyBeautifulApp** and would be added to the info.xml in the following way: MyBeautifulApp * **appinfo/routes.php**: Instead of creating a new Application class instance, simply return the routes array like: \[\ \['name' \=> 'page#index', 'url' \=> '/', 'verb' \=> 'GET'\],\ \]\]; Note A namespace tag is required because you can not deduce the namespace from the app id Which classes should be added[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#which-classes-should-be-added "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ In general all of the app’s controllers need to be registered inside the container. Then the following question is: What goes into the constructor of the controller? Pass everything into the controller constructor that matches one of the following criteria: * It does I/O (database, write/read to files) * It is a global (e.g. $\_POST, etc. This is in the request class by the way) * The output does not depend on the input variables (also called [impure function](https://en.wikipedia.org/wiki/Pure_function) ), e.g. time, random number generator * It is a service, basically it would make sense to swap it out for a different object What not to inject: * It is pure data and has methods that only act upon it (arrays, data objects) * It is a [pure function](https://en.wikipedia.org/wiki/Pure_function) Optional services[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#optional-services "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------ Added in version 28. If an injected dependency can’t be found or build, an exception is thrown. This can be avoided by using the a nullable type notation for a dependency: namespace OCA\\MyApp\\MyService; use Some\\Service; class MyService { public function \_\_construct(private ?Service $service) { } } If `\Some\Service` exists and can be built, it will be injected. Else `MyService` will receive `null`. Accessing the container from anywhere[](https://docs.nextcloud.com/server/32/developer_manual/basics/dependency_injection.html#accessing-the-container-from-anywhere "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Sometimes it can be hard to inject some service inside legacy code, in these cases you can use `OCPServer::get(MyService::class)`. This should only be used as the last resort, as this makes your code more complicated to unit test and is considered an anti-pattern. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Navigation and pre-app configuration — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/stable/developer_manual/app_development/index.html) * Navigation and pre-app configuration * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/init.rst) * * * Navigation and pre-app configuration[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/init.html#navigation-and-pre-app-configuration "Link to this heading") ========================================================================================================================================================================================= Adding a navigation entry[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/init.html#adding-a-navigation-entry "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- Navigation entries for apps can be created by adding a navigation section to the `appinfo/info.xml` file, containing the name, order and route the navigation entry should link to. For details on the XML schema check the [app store documentation](https://nextcloudappstore.readthedocs.io/en/latest/developer.html#info-xml) . MyApp myapp.page.index 0 Initialization events[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/init.html#initialization-events "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------- Often apps do not need to load their JavaScript and CSS on every page. For this purpose there are several events emitted that an app can act upon. * `OCA\Files::loadAdditionalScripts` (string): loaded on the files list page * `OCA\Files_Sharing::loadAdditionalScripts` (string): loaded on the public sharing page * `OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth` (string): loaded on the public share authentication page * `OCP\AppFramework\Http\TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS` (constant): loaded when a template response is finished * `OCP\AppFramework\Http\TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS_LOGGEDIN` (constant): loaded when a template response is finished for a logged in user You can subscribe listeners to these events in the [bootstrapping code](https://docs.nextcloud.com/server/stable/developer_manual/app_development/bootstrap.html#bootstrapping) of the app. See the [events documentation](https://docs.nextcloud.com/server/stable/developer_manual/basics/events.html#events) for more details on the event dispatcher and available events. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Nextcloud architecture — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/31/developer_manual/server/index.html) * Nextcloud architecture * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/server/architecture/index.rst) * * * Nextcloud architecture[](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/index.html#nextcloud-architecture "Link to this heading") ============================================================================================================================================================== * [Nextcloud filesystem API](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html) * [High level overview](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#high-level-overview) * [Filesystem layer](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#filesystem-layer) * [Storage layer](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#storage-layer) * [Storage/Cache wrappers](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#storage-cache-wrappers) * [Code Map](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#code-map) * [AppData](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#appdata) * [Cache](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#cache) * [Mount](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#mount) * [Node](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#node) * [ObjectStorage](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#objectstorage) * [SimpleFS](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#simplefs) * [Storage](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#storage) * [Streams](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#streams) * [Type](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#type) * [View.php](https://docs.nextcloud.com/server/31/developer_manual/server/architecture/files.html#view-php) ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # External API — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/31/developer_manual/server/index.html) * External API * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/server/externalapi.rst) * * * External API[](https://docs.nextcloud.com/server/31/developer_manual/server/externalapi.html#external-api "Link to this heading") =================================================================================================================================== Introduction[](https://docs.nextcloud.com/server/31/developer_manual/server/externalapi.html#introduction "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------- The external API inside Nextcloud allows third party developers to access data provided by Nextcloud apps. Nextcloud follows the [Open Collaboration Services specification](https://open-collaboration-services.org/) . Usage[](https://docs.nextcloud.com/server/31/developer_manual/server/externalapi.html#usage "Link to this heading") --------------------------------------------------------------------------------------------------------------------- ### Registering methods[](https://docs.nextcloud.com/server/31/developer_manual/server/externalapi.html#registering-methods "Link to this heading") Methods are registered inside the `appinfo/routes.php` by returning an array holding the endpoint meta data. \[\ // Apps\ \['name' \=> 'Bar#getFoo', 'url' \=> '/foobar', 'verb' \=> 'GET'\],\ \],\ \]; ### Returning data[](https://docs.nextcloud.com/server/31/developer_manual/server/externalapi.html#returning-data "Link to this heading") Once the API backend has matched your URL, your callable function as defined in **BarController::getFoo** will be executed. The AppFramework will make sure that send parameters are provided to the method based on its declaration. Be sure to extend the `OCP\AppFramework\OCSController` from the AppFramework. Your functions then should returns a `OCP\AppFramework\Http\DataResponse`. The AppFramework will then take care formatting the response properly. ### Exceptions[](https://docs.nextcloud.com/server/31/developer_manual/server/externalapi.html#exceptions "Link to this heading") To throw an exception to the user in the OCS response. You can throw an `OCP\AppFramework\OCS\OCSException`. You can set the message and code. There are 3 commonly used exceptions already available: * `OCSBadRequestException` * `OCSForbiddenException` * `OCSNotFoundException` ### Authentication & basics[](https://docs.nextcloud.com/server/31/developer_manual/server/externalapi.html#authentication-basics "Link to this heading") The requests to the OCS endpoint often have to be authenticated. > `curl -u user:password https://example.com/ocs/v2.php/apps/yourapp/foobar` ### Output[](https://docs.nextcloud.com/server/31/developer_manual/server/externalapi.html#output "Link to this heading") The output defaults to XML. If you want to get JSON append this to the URL: ?format=json Or set the proper Accept header: Accept: application/json Output from the application is wrapped inside a **data** element: **XML**: ok 200 **JSON**: { "ocs": { "meta": { "status": "ok", "statuscode": 200, "message": null }, "data": { // data here } } } ### Statuscodes[](https://docs.nextcloud.com/server/31/developer_manual/server/externalapi.html#statuscodes "Link to this heading") The statuscode can be any of the following numbers: * **200** - successful * **996** - server error * **401** - not authorized * **404** - not found * **999** - unknown error ### Changing API and backwards compatibility[](https://docs.nextcloud.com/server/31/developer_manual/server/externalapi.html#changing-api-and-backwards-compatibility "Link to this heading") We aim to keep our API as stable as possible to avoid breaking third-party apps. Before an API is allowed to be removed, it should be marked as deprecated for at least 3 years (9 Nextcloud releases) before it gets removed. Changing the API [should be discussed in a github issue in our server repo](https://github.com/nextcloud/server/issues) . A pull request is most welcome. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Unit-Testing — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/31/developer_manual/server/index.html) * Unit-Testing * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/server/unit-testing.rst) * * * Unit-Testing[](https://docs.nextcloud.com/server/31/developer_manual/server/unit-testing.html#unit-testing "Link to this heading") ==================================================================================================================================== PHP unit testing[](https://docs.nextcloud.com/server/31/developer_manual/server/unit-testing.html#php-unit-testing "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------- ### Getting PHPUnit[](https://docs.nextcloud.com/server/31/developer_manual/server/unit-testing.html#getting-phpunit "Link to this heading") Nextcloud uses PHPUnit >= 8.5 for unit testing. PHPUnit documentation: [https://phpunit.de/documentation.html](https://phpunit.de/documentation.html) ### Writing PHP unit tests[](https://docs.nextcloud.com/server/31/developer_manual/server/unit-testing.html#writing-php-unit-tests "Link to this heading") To get started, do the following: * Create a directory called `tests` in the top level of your application * Create a PHP file in the directory and `require_once` your class which you want to test Then you can simply run the created test with **phpunit**. Note If you use Nextcloud functions in your class under test (i.e., OC::getUser()) you’ll need to bootstrap Nextcloud or use dependency injection. Note You’ll most likely run your tests under a different user than the Web server. This might cause problems with your PHP settings (i.e., open\_basedir) and requires you to adjust your configuration. An example for a simple test would be: `/srv/http/nextcloud/apps/myapp/tests/testaddtwo.php` testMe \= new \\OCA\\Myapp\\TestMe(); } public function testAddTwo(){ $this\->assertEquals(5, $this\->testMe\->addTwo(3)); } } `/srv/http/nextcloud/apps/myapp/lib/testme.php` array ( 0 \=> array ( 'path' \=> '/var/www/html/apps', 'url' \=> '/apps', 'writable' \=> false, ), 1 \=> array ( 'path' \=> '/var/www/html/apps-extra', 'url' \=> '/apps-extra', 'writable' \=> false, ), ), Finally, clone the app to which you would like to contribute inside the apps-extra folder. For example: > git clone [https://github.com/nextcloud/cookbook.git](https://github.com/nextcloud/cookbook.git) Enable the app[](https://docs.nextcloud.com/server/32/developer_manual/app_development/intro.html#enable-the-app "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------ The app can now be enabled on the Nextcloud apps page. App architecture[](https://docs.nextcloud.com/server/32/developer_manual/app_development/intro.html#app-architecture "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- The following directories have now been created: * **appinfo/**: Contains app metadata and configuration * **css/**: Contains the CSS * **img/**: Contains icons and images * **js/**: Contains the JavaScript files * **lib/**: Contains the PHP class files of your app * **src/**: Contains the source code of your vue.js app * **templates/**: Contains the templates * **tests/**: Contains the tests ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Navigation and pre-app configuration — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/32/developer_manual/app_development/index.html) * Navigation and pre-app configuration * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/init.rst) * * * Navigation and pre-app configuration[](https://docs.nextcloud.com/server/32/developer_manual/app_development/init.html#navigation-and-pre-app-configuration "Link to this heading") ===================================================================================================================================================================================== Adding a navigation entry[](https://docs.nextcloud.com/server/32/developer_manual/app_development/init.html#adding-a-navigation-entry "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------- Navigation entries for apps can be created by adding a navigation section to the `appinfo/info.xml` file, containing the name, order and route the navigation entry should link to. For details on the XML schema check the [app store documentation](https://nextcloudappstore.readthedocs.io/en/latest/developer.html#info-xml) . MyApp myapp.page.index 0 Initialization events[](https://docs.nextcloud.com/server/32/developer_manual/app_development/init.html#initialization-events "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------- Often apps do not need to load their JavaScript and CSS on every page. For this purpose there are several events emitted that an app can act upon. * `OCA\Files::loadAdditionalScripts` (string): loaded on the files list page * `OCA\Files_Sharing::loadAdditionalScripts` (string): loaded on the public sharing page * `OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth` (string): loaded on the public share authentication page * `OCP\AppFramework\Http\TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS` (constant): loaded when a template response is finished * `OCP\AppFramework\Http\TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS_LOGGEDIN` (constant): loaded when a template response is finished for a logged in user You can subscribe listeners to these events in the [bootstrapping code](https://docs.nextcloud.com/server/32/developer_manual/app_development/bootstrap.html#bootstrapping) of the app. See the [events documentation](https://docs.nextcloud.com/server/32/developer_manual/basics/events.html#events) for more details on the event dispatcher and available events. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Logging — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/31/developer_manual/basics/index.html) * Logging * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/logging.rst) * * * Logging[](https://docs.nextcloud.com/server/31/developer_manual/basics/logging.html#logging "Link to this heading") ===================================================================================================================== The logger is present by default in the container. The app that is logging is set automatically. Nextcloud uses a [PSR3](https://docs.nextcloud.com/server/31/developer_manual/digging_deeper/psr.html#psr3) logger. The logger can be used in the following way: logger \= $logger; $this\->appName \= $appName; } public function log($message) { $this\->logger\->error($message, \['extra\_context' \=> 'my extra context'\]); } } In cases where you can not [inject](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#id2) a logger into a class, you can use the `\OCP\Log\logger` function to acquire a logger instance. As a first argument you need to pass the app ID. warning('look, no dependency injection'); Admin audit logging[](https://docs.nextcloud.com/server/31/developer_manual/basics/logging.html#admin-audit-logging "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------- If you want to log things less for system administration but for compliance reasons, e.g. who accessed which file, who changed the password of an item or made it public, the [admin audit log](https://docs.nextcloud.com/server/31/admin_manual/configuration_server/logging_configuration.html#admin-audit-log) is the correct place. You can easily add a log by simply emitting an `OCP\Log\Audit\CriticalActionPerformedEvent` event: 'My App ID'\] ); $dispatcher\->dispatchTyped($event); ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Dependency management — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/stable/developer_manual/app_development/index.html) * Dependency management * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/dependency_management.rst) * * * Dependency management[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#dependency-management "Link to this heading") ============================================================================================================================================================================ You can leverage existing software packages to build a Nextcloud app. Composer[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#composer "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- You can add 3rd party php packages with [Composer](https://getcomposer.org/) . Composer will download the specified packages to a directory of your choice, typically to `/vendor`. In order to benefit from Composer’s autoloader, you’ll want to add a `require_once` to the `register` method of your `Application` class in the [bootstrapping](https://docs.nextcloud.com/server/stable/developer_manual/app_development/bootstrap.html#bootstrapping) code of your app. ### Remove unneeded files from packages[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#remove-unneeded-files-from-packages "Link to this heading") It is heavily recommended to remove files that are not required in production from the final packages. This especially, but not exclusively, refers to: * Developer files, e.g. `/Makefile` * CI workflows, e.g. `/.github` * Test assets, e.g. `/tests` * Configuration of development tools, e.g. `/phpunit.xml`, `/psalm.xml` * Git or other version control code, e.g. `/.git` You can check the [Server’s .gitignore](https://github.com/nextcloud/3rdparty/blob/master/.gitignore) file for more inspiration. ### Dependency hell[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#dependency-hell "Link to this heading") Be careful with which packages you add to an app. PHP can not load two version of the same class twice, hence there can be conflicts between Nextcloud Server and an app or between two or more apps if they require the same package. So try to keep the number of production dependencies to a minimum and see [Development tools](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#app-composer-bin-tools) . Alternatively you can use \[composer-bin-plugin\]([https://github.com/bamarni/composer-bin-plugin](https://github.com/bamarni/composer-bin-plugin) ) to avoid dependency conflicts between apps. 1. Install composer-bin-plugin according to their docs. > composer require \--dev bamarni/composer-bin-plugin 2. Install the tools you need in the vendor-bin directory. > composer bin psalm require \--dev psalm/phar > composer bin psalm require \--dev nextcloud/ocp:dev-master 3. Adjust some config (see below) * Add in composer.json: composer.json[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#id2 "Link to this code") { "extra": { "bamarni-bin": { "bin-links": true, "forward-command": true } } } * Add in composer.json: composer.json[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#id3 "Link to this code") { "scripts": { "post-install-cmd": \[\ "\[ $COMPOSER\_DEV\_MODE -eq 0 \] || composer bin all install --ansi"\ \], "post-update-cmd": \[\ "\[ $COMPOSER\_DEV\_MODE -eq 0 \] || composer bin all update --ansi"\ \] } } * Adjust psalm.xml: * Ensure the schemaLocation is correct: psalm.xml[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#id4 "Link to this code") xsi:schemaLocation="https://getpsalm.org/schema/config vendor-bin/psalm/vendor/vimeo/psalm/config.xsd" * Ensure it has something like this: psalm.xml[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#id5 "Link to this code") * Adjust .php-cs-fixer.dist.php .php-cs-fixer.dist.php[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#id6 "Link to this code") require\_once \_\_DIR\_\_ . '/vendor-bin/cs-fixer/vendor/autoload.php'; #### Conflict example[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#conflict-example "Link to this heading") To illustrate the problem imagine app _A_ depends on package _foo_ in version 1, app _B_ depends on package _foo_ in version 2. The package _foo_ had a breaking change to which app _B_ has been adjusted, _A_ uses the old API. Both apps ship a Composer autoloader that autoloads the _foo_ functions and classes. There is a race between the two autoloaders. If _A_’s autoloader is asked to load the class first, then v1 will be used. If _B_’s autoloader loads functions and classes first it will be v2. In some scenarios there might be classes of v1 and v2 when autoloaders are invoked without a defined order. Depending on which functions and classes are loaded, app _A_ might work or break. The same applies to _B_. ### Development tools[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#development-tools "Link to this heading") It is very common for an app to use CLI tools for syntax checks, testing and building. Since many tools depend on common Composer packages like `psr/*` and `symfony/console`, it is likely that apps produce a [dependency hell](https://docs.nextcloud.com/server/stable/developer_manual/app_development/dependency_management.html#app-composer-dependency-hell) on development environments. The dependency hell for CLI tools can be avoided by using the _Composer bin plugin_. It’s a composer plugin that puts development dependencies into sub directorory with a dedicated autoloader. That autoloader is only used if the CLI tool is used. For Nextcloud apps this means two apps can use conflicting versions of one tool. Moreover dependency conflicts between the tools of one app are no longer an issue. Tools known to be problematic that should be moved into bin plugin directories include * `friendsofphp/php-cs-fixer` * `phpunit/phpunit` * `vimeo/psalm` Please see the [package page](https://packagist.org/packages/bamarni/composer-bin-plugin) for up-to-date installation instructions. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # App metadata — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/32/developer_manual/app_development/index.html) * App metadata * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/info.rst) * * * App metadata[](https://docs.nextcloud.com/server/32/developer_manual/app_development/info.html#app-metadata "Link to this heading") ===================================================================================================================================== The `appinfo/info.xml` contains metadata about the app. A detailed documentation can be found at the [app store documentation](https://nextcloudappstore.readthedocs.io/en/latest/developer.html#info-xml) . The info.xml is validated using an XML Schema which can be accessed [online](https://apps.nextcloud.com/schema/apps/info.xsd) . A minimum valid **info.xml** would look like this: appinfo/info.xml[](https://docs.nextcloud.com/server/32/developer_manual/app_development/info.html#id2 "Link to this code") news News An RSS/Atom feed reader An RSS/Atom feed reader 8.8.2 AGPL-3.0-or-later Bernhard Posselt multimedia https://github.com/nextcloud/news/issues A full blown example would look like this (needs to be utf-8 encoded): appinfo/info.xml[](https://docs.nextcloud.com/server/32/developer_manual/app_development/info.html#id3 "Link to this code") news Nachrichten News An RSS/Atom feed reader # Description\\nAn RSS/Atom feed reader 8.8.2 AGPL-3.0-or-later Bernhard Posselt Alessandro Cosentino Jan-Christoph Borchardt https://github.com/nextcloud/news/wiki#user-documentation https://github.com/nextcloud/news#readme https://github.com/nextcloud/news/wiki#developer-documentation multimedia tools https://github.com/nextcloud/news https://your.forum.com https://github.com/nextcloud/news/issues https://github.com/nextcloud/news https://example.com/1.png https://example.com/2.jpg pgsql sqlite mysql grep ls libxml curl SimpleXML iconv OCA\\DAV\\CardDAV\\Sync\\SyncJob OCA\\DAV\\Migration\\Classification OCA\\DAV\\Migration\\Classification OCA\\DAV\\Migration\\GenerateBirthdays OCA\\DAV\\Migration\\GenerateBirthdays OCA\\DAV\\Migration\\GenerateBirthdays OCA\\AuthF\\TwoFactor\\Provider A\\Php\\Class OCA\\Theming\\Settings\\Admin OCA\\Theming\\Settings\\Section OCA\\Files\\Activity\\Settings\\FavoriteAction OCA\\Files\\Activity\\Settings\\FileChanged OCA\\Files\\Activity\\Settings\\FileCreated OCA\\Files\\Activity\\Settings\\FileDeleted OCA\\Files\\Activity\\Settings\\FileFavorite OCA\\Files\\Activity\\Settings\\FileRestored OCA\\Files\\Activity\\Filter\\FileChanges OCA\\Files\\Activity\\Filter\\Favorites OCA\\Files\\Activity\\FavoriteProvider OCA\\Files\\Activity\\Provider files Files files.view.index 0 app.svg link OCA\\Circles\\Collaboration\\v1\\CollaboratorSearchPlugin The following tags are validated and used in the following way: id * required * must contain only lowercase ASCII characters and underscore * must match the first folder in the archive * will be used to identify the app name * required * must occur at least once with **lang=”en”** or no lang attribute * can be translated by using multiple elements with different **lang** attribute values, language code needs to be set **lang** attribute * will be rendered on the app detail page summary * optional * if not provided the description element’s text will be used * must occur at least once with **lang=”en”** or no lang attribute * can be translated by using multiple elements with different **lang** attribute values, language code needs to be set **lang** attribute * will be rendered on the app list page as short description description * required * must occur at least once with **lang=”en”** or no lang attribute * can contain Markdown * can be translated by using multiple elements with different **lang** attribute values, language code needs to be set **lang** attribute * will be rendered on the app detail page version * required * must be a [semantic version](http://semver.org/) without build metadata, e.g. 9.0.1 or 9.1.0-alpha.1 * [more info on app versioning](https://docs.nextcloud.com/server/32/developer_manual/app_publishing_maintenance/release_process.html#app-versioning) licence * required * can occur multiple times with different licenses * must contain one of the following licenses (for apps targeting v31 or higher, see the [SPDX License List](https://spdx.org/licenses/) for details): > * **AGPL-3.0-only** > > * **AGPL-3.0-or-later** > > * **Apache-2.0** > > * **GPL-3.0-only** > > * **GPL-3.0-or-later** > > * **MIT** > > * **MPL-2.0** > * (deprecated, for apps targeting v30 or lower) the following shorthand aliases are also used: > * **agpl** (AGPL-3.0) > > * **apache** (Apache-2.0) > > * **gpl3** (GPL-3.0) > > * **mit** (MIT) > > * **mpl** (MPL-2.0) > author * required * can occur multiple times with different authors * can contain a **mail** attribute which must be an email * can contain a **homepage** which must be a URL * will not (yet) be rendered on the App Store * will be provided through the REST API documentation/user * optional * must contain a URL to the user documentation * will be rendered on the app detail page documentation/admin * optional * must contain a URL to the admin documentation * will be rendered on the app detail page documentation/developer * optional * must contain a URL to the developer documentation * will be rendered on the app detail page category * optional * if not provided the category **tools** will be used * must contain one of the following values: > * **customization** > > * **files** > > * **games** > > * **integration** > > * **monitoring** > > * **multimedia** > > * **office** > > * **organization** > > * **security** > > * **social** > > * **tools** > * old categories are migrated: > * **auth** will be converted to **security** > * can occur more than once with different categories website * optional * must contain a URL to the project’s homepage * will be rendered on the app detail page discussion * optional * must contain a URL to the project’s discussion page/forum * will be rendered on the app detail page as the “ask question or discuss” button * if absent, it will default to our forum at [https://help.nextcloud.com/](https://help.nextcloud.com/) bugs * required * must contain a URL to the project’s bug tracker * will be rendered on the app detail page repository * optional * must contain a URL to the project’s repository * can contain a **type** attribute, **git**, **mercurial**, **subversion** and **bzr** are allowed values, defaults to **git** * currently not used screenshot * optional * must contain an HTTPS URL to an image * can contain a **small-thumbnail** attribute which must contain an https url to an image. This image will be used as small preview (e.g. on the app list overview). Keep it small so it renders fast * will be rendered on the app list and detail page in the given order dependencies/php * optional * can contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) * can contain a **min-int-size** attribute, 32 or 64 are allowed as valid values * will be rendered on the app releases page dependencies/database * optional * must contain the database name as text, **sqlite**, **pgsql** and **mysql** are allowed as valid values * can occur multiple times with different databases * can contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) * will be rendered on the app releases page dependencies/command * optional * must contain a linux command as text value * can occur multiple times with different commands * will be rendered on the app releases page dependencies/lib * optional * will be rendered on the app releases page * must contain a required php extension * can occur multiple times with different php extensions * can contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) dependencies/nextcloud * required * must contain a **min-version** attribute (maximum 3 digits separated by dots) * must contain a **max-version** attribute (maximum 3 digits separated by dots) Note Dependencies dependencies/php, dependencies/database and dependencies/lib are checked at installation time (not on update time), hence applications need to stick to the dependencies supported by a major version of Nextcloud the moment an app releases support for that version, i.e. app needs to support the same PHP version-range the supported Nextcloud version supports. background-jobs/job * optional * must contain a php class which is run as background jobs * will not be used, only validated repair-steps/pre-migration/step * optional * must contain a php class which is run before executing database migrations * will not be used, only validated repair-steps/post-migration/step * optional * must contain a php class which is run after executing database migrations * will not be used, only validated repair-steps/live-migration/step * optional * must contain a php class which is run after executing post-migration jobs * will not be used, only validated repair-steps/install/step * optional * must contain a php class which is run after installing the app * will not be used, only validated repair-steps/uninstall/step * optional * must contain a php class which is run after uninstalling the app * will not be used, only validated two-factor-providers/provider * optional * must contain a php class which is registered as two factor auth provider * will not be used, only validated commands/command * optional * must contain a php class which is registered as occ command * will not be used, only validated activity/settings/setting * optional * must contain a php class which implements OCPActivityISetting and is used to add additional settings ui elements to the activity app activity/filters/filter * optional * must contain a php class which implements OCPActivityIFilter and is used to add additional filters to the activity app activity/providers/provider * optional * must contain a php class which implements OCPActivityIProvider and is used to react to events from the activity app settings/admin * optional * must contain a php class which implements OCPSettingsISettings and returns the form to render for the global settings area settings/admin-section * optional * must contain a php class which implements OCPSettingsISection and returns data to render navigation entries in the global settings area navigations * optional * must contain at least one navigation element navigations/navigation * required * must contain a name and route element * denotes a navigation entry * role denotes the visibility, all means everyone can see it, admin means only an admin can see the navigation entry, defaults to all navigations/navigation/id * optional * the app id * you can also create entries for other apps by setting an id other than your app one’s navigations/navigation/name * required * will be displayed below the navigation entry icon * will be translated by the default translation tools navigations/navigation/route * required * name of the route that will be used to generate the link navigations/navigation/icon * optional * name of the icon which is looked up in the app’s **img/** folder * defaults to app.svg navigations/navigation/order * optional * used to sort the navigation entries * a higher order number means that the entry will be ordered further to the bottom navigations/navigation/type * optional * can be either link or settings * link means that the entry is added to the default app menu * settings means that the entry is added to the right-side menu which also contains the personal, admin, users, help and logout entry collaboration * optional * can contain plugins for collaboration search (e.g. supplying share dialog) collaboration/plugins * optional * must contain at least one plugin collaboration/plugins/plugin * required * the PHP class name of the plugin * must contain **type** attribute (currently only _collaboration-search_). The class must implement OCPCollaborationCollaboratorsISearchPlugin. * must contain **share-type** attribute, according to the specific OCPShare constants The following character maximum lengths are enforced: * All description Strings are database text fields and therefore not limited in size * All other Strings have a maximum of 256 characters The following elements are either deprecated or for internal use only and will fail the validation if present: * **standalone** * **default\_enable** * **shipped** * **public** * **remote** * **requiremin** * **requiremax** Changelog[](https://docs.nextcloud.com/server/32/developer_manual/app_development/info.html#changelog "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------- Apps can provide a changelog. This should be written in the [keep a changelog](https://keepachangelog.com/) . If the apps provide a `CHANGELOG.md` file in the project root, this file will be used to show changes for the released version in the app store and for administrators in the app settings. Moreover, since Nextcloud 29, if the `updatenotification` app is enabled, apps can also provide a changelog for the users. The app will notify users about after the app update if either a `CHANGELOG.language.md` (where `language` is the language code of that user) or a fallback `CHANGELOG.en.md` is available. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # App metadata — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [App development](https://docs.nextcloud.com/server/stable/developer_manual/app_development/index.html) * App metadata * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/app_development/info.rst) * * * App metadata[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/info.html#app-metadata "Link to this heading") ========================================================================================================================================= The `appinfo/info.xml` contains metadata about the app. A detailed documentation can be found at the [app store documentation](https://nextcloudappstore.readthedocs.io/en/latest/developer.html#info-xml) . The info.xml is validated using an XML Schema which can be accessed [online](https://apps.nextcloud.com/schema/apps/info.xsd) . A minimum valid **info.xml** would look like this: appinfo/info.xml[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/info.html#id2 "Link to this code") news News An RSS/Atom feed reader An RSS/Atom feed reader 8.8.2 AGPL-3.0-or-later Bernhard Posselt multimedia https://github.com/nextcloud/news/issues A full blown example would look like this (needs to be utf-8 encoded): appinfo/info.xml[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/info.html#id3 "Link to this code") news Nachrichten News An RSS/Atom feed reader # Description\\nAn RSS/Atom feed reader 8.8.2 AGPL-3.0-or-later Bernhard Posselt Alessandro Cosentino Jan-Christoph Borchardt https://github.com/nextcloud/news/wiki#user-documentation https://github.com/nextcloud/news#readme https://github.com/nextcloud/news/wiki#developer-documentation multimedia tools https://github.com/nextcloud/news https://your.forum.com https://github.com/nextcloud/news/issues https://github.com/nextcloud/news https://example.com/1.png https://example.com/2.jpg pgsql sqlite mysql grep ls libxml curl SimpleXML iconv OCA\\DAV\\CardDAV\\Sync\\SyncJob OCA\\DAV\\Migration\\Classification OCA\\DAV\\Migration\\Classification OCA\\DAV\\Migration\\GenerateBirthdays OCA\\DAV\\Migration\\GenerateBirthdays OCA\\DAV\\Migration\\GenerateBirthdays OCA\\AuthF\\TwoFactor\\Provider A\\Php\\Class OCA\\Theming\\Settings\\Admin OCA\\Theming\\Settings\\Section OCA\\Files\\Activity\\Settings\\FavoriteAction OCA\\Files\\Activity\\Settings\\FileChanged OCA\\Files\\Activity\\Settings\\FileCreated OCA\\Files\\Activity\\Settings\\FileDeleted OCA\\Files\\Activity\\Settings\\FileFavorite OCA\\Files\\Activity\\Settings\\FileRestored OCA\\Files\\Activity\\Filter\\FileChanges OCA\\Files\\Activity\\Filter\\Favorites OCA\\Files\\Activity\\FavoriteProvider OCA\\Files\\Activity\\Provider files Files files.view.index 0 app.svg link OCA\\Circles\\Collaboration\\v1\\CollaboratorSearchPlugin The following tags are validated and used in the following way: id * required * must contain only lowercase ASCII characters and underscore * must match the first folder in the archive * will be used to identify the app name * required * must occur at least once with **lang=”en”** or no lang attribute * can be translated by using multiple elements with different **lang** attribute values, language code needs to be set **lang** attribute * will be rendered on the app detail page summary * optional * if not provided the description element’s text will be used * must occur at least once with **lang=”en”** or no lang attribute * can be translated by using multiple elements with different **lang** attribute values, language code needs to be set **lang** attribute * will be rendered on the app list page as short description description * required * must occur at least once with **lang=”en”** or no lang attribute * can contain Markdown * can be translated by using multiple elements with different **lang** attribute values, language code needs to be set **lang** attribute * will be rendered on the app detail page version * required * must be a [semantic version](http://semver.org/) without build metadata, e.g. 9.0.1 or 9.1.0-alpha.1 * [more info on app versioning](https://docs.nextcloud.com/server/stable/developer_manual/app_publishing_maintenance/release_process.html#app-versioning) licence * required * can occur multiple times with different licenses * must contain one of the following licenses (for apps targeting v31 or higher, see the [SPDX License List](https://spdx.org/licenses/) for details): > * **AGPL-3.0-only** > > * **AGPL-3.0-or-later** > > * **Apache-2.0** > > * **GPL-3.0-only** > > * **GPL-3.0-or-later** > > * **MIT** > > * **MPL-2.0** > * (deprecated, for apps targeting v30 or lower) the following shorthand aliases are also used: > * **agpl** (AGPL-3.0) > > * **apache** (Apache-2.0) > > * **gpl3** (GPL-3.0) > > * **mit** (MIT) > > * **mpl** (MPL-2.0) > author * required * can occur multiple times with different authors * can contain a **mail** attribute which must be an email * can contain a **homepage** which must be a URL * will not (yet) be rendered on the App Store * will be provided through the REST API documentation/user * optional * must contain a URL to the user documentation * will be rendered on the app detail page documentation/admin * optional * must contain a URL to the admin documentation * will be rendered on the app detail page documentation/developer * optional * must contain a URL to the developer documentation * will be rendered on the app detail page category * optional * if not provided the category **tools** will be used * must contain one of the following values: > * **customization** > > * **files** > > * **games** > > * **integration** > > * **monitoring** > > * **multimedia** > > * **office** > > * **organization** > > * **security** > > * **social** > > * **tools** > * old categories are migrated: > * **auth** will be converted to **security** > * can occur more than once with different categories website * optional * must contain a URL to the project’s homepage * will be rendered on the app detail page discussion * optional * must contain a URL to the project’s discussion page/forum * will be rendered on the app detail page as the “ask question or discuss” button * if absent, it will default to our forum at [https://help.nextcloud.com/](https://help.nextcloud.com/) bugs * required * must contain a URL to the project’s bug tracker * will be rendered on the app detail page repository * optional * must contain a URL to the project’s repository * can contain a **type** attribute, **git**, **mercurial**, **subversion** and **bzr** are allowed values, defaults to **git** * currently not used screenshot * optional * must contain an HTTPS URL to an image * can contain a **small-thumbnail** attribute which must contain an https url to an image. This image will be used as small preview (e.g. on the app list overview). Keep it small so it renders fast * will be rendered on the app list and detail page in the given order dependencies/php * optional * can contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) * can contain a **min-int-size** attribute, 32 or 64 are allowed as valid values * will be rendered on the app releases page dependencies/database * optional * must contain the database name as text, **sqlite**, **pgsql** and **mysql** are allowed as valid values * can occur multiple times with different databases * can contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) * will be rendered on the app releases page dependencies/command * optional * must contain a linux command as text value * can occur multiple times with different commands * will be rendered on the app releases page dependencies/lib * optional * will be rendered on the app releases page * must contain a required php extension * can occur multiple times with different php extensions * can contain a **min-version** attribute (maximum 3 digits separated by dots) * can contain a **max-version** attribute (maximum 3 digits separated by dots) dependencies/nextcloud * required * must contain a **min-version** attribute (maximum 3 digits separated by dots) * must contain a **max-version** attribute (maximum 3 digits separated by dots) Note Dependencies dependencies/php, dependencies/database and dependencies/lib are checked at installation time (not on update time), hence applications need to stick to the dependencies supported by a major version of Nextcloud the moment an app releases support for that version, i.e. app needs to support the same PHP version-range the supported Nextcloud version supports. background-jobs/job * optional * must contain a php class which is run as background jobs * will not be used, only validated repair-steps/pre-migration/step * optional * must contain a php class which is run before executing database migrations * will not be used, only validated repair-steps/post-migration/step * optional * must contain a php class which is run after executing database migrations * will not be used, only validated repair-steps/live-migration/step * optional * must contain a php class which is run after executing post-migration jobs * will not be used, only validated repair-steps/install/step * optional * must contain a php class which is run after installing the app * will not be used, only validated repair-steps/uninstall/step * optional * must contain a php class which is run after uninstalling the app * will not be used, only validated two-factor-providers/provider * optional * must contain a php class which is registered as two factor auth provider * will not be used, only validated commands/command * optional * must contain a php class which is registered as occ command * will not be used, only validated activity/settings/setting * optional * must contain a php class which implements OCPActivityISetting and is used to add additional settings ui elements to the activity app activity/filters/filter * optional * must contain a php class which implements OCPActivityIFilter and is used to add additional filters to the activity app activity/providers/provider * optional * must contain a php class which implements OCPActivityIProvider and is used to react to events from the activity app settings/admin * optional * must contain a php class which implements OCPSettingsISettings and returns the form to render for the global settings area settings/admin-section * optional * must contain a php class which implements OCPSettingsISection and returns data to render navigation entries in the global settings area navigations * optional * must contain at least one navigation element navigations/navigation * required * must contain a name and route element * denotes a navigation entry * role denotes the visibility, all means everyone can see it, admin means only an admin can see the navigation entry, defaults to all navigations/navigation/id * optional * the app id * you can also create entries for other apps by setting an id other than your app one’s navigations/navigation/name * required * will be displayed below the navigation entry icon * will be translated by the default translation tools navigations/navigation/route * required * name of the route that will be used to generate the link navigations/navigation/icon * optional * name of the icon which is looked up in the app’s **img/** folder * defaults to app.svg navigations/navigation/order * optional * used to sort the navigation entries * a higher order number means that the entry will be ordered further to the bottom navigations/navigation/type * optional * can be either link or settings * link means that the entry is added to the default app menu * settings means that the entry is added to the right-side menu which also contains the personal, admin, users, help and logout entry collaboration * optional * can contain plugins for collaboration search (e.g. supplying share dialog) collaboration/plugins * optional * must contain at least one plugin collaboration/plugins/plugin * required * the PHP class name of the plugin * must contain **type** attribute (currently only _collaboration-search_). The class must implement OCPCollaborationCollaboratorsISearchPlugin. * must contain **share-type** attribute, according to the specific OCPShare constants The following character maximum lengths are enforced: * All description Strings are database text fields and therefore not limited in size * All other Strings have a maximum of 256 characters The following elements are either deprecated or for internal use only and will fail the validation if present: * **standalone** * **default\_enable** * **shipped** * **public** * **remote** * **requiremin** * **requiremax** Changelog[](https://docs.nextcloud.com/server/stable/developer_manual/app_development/info.html#changelog "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------- Apps can provide a changelog. This should be written in the [keep a changelog](https://keepachangelog.com/) . If the apps provide a `CHANGELOG.md` file in the project root, this file will be used to show changes for the released version in the app store and for administrators in the app settings. Moreover, since Nextcloud 29, if the `updatenotification` app is enabled, apps can also provide a changelog for the users. The app will notify users about after the app update if either a `CHANGELOG.language.md` (where `language` is the language code of that user) or a fallback `CHANGELOG.en.md` is available. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Front-end code — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/32/developer_manual/server/index.html) * Front-end code * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/server/code-front-end.rst) * * * Front-end code[](https://docs.nextcloud.com/server/32/developer_manual/server/code-front-end.html#front-end-code "Link to this heading") ========================================================================================================================================== Building Vue components and scripts[](https://docs.nextcloud.com/server/32/developer_manual/server/code-front-end.html#building-vue-components-and-scripts "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ We are moving more and more toward using Vue.js in the front-end, starting with Settings. For building the code on changes, use these terminal commands in the root folder: \# install dependencies npm install \# build for development npm run dev \# build for development and watch edits npm run watch \# build for production with minification npm run build Building styles[](https://docs.nextcloud.com/server/32/developer_manual/server/code-front-end.html#building-styles "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------- Styles are written in SCSS and compiled to css. \# install dependencies make dev-setup \# compile style sheets npm run sass \# compile style sheets and watch edits npm run sass:watch Committing changes[](https://docs.nextcloud.com/server/32/developer_manual/server/code-front-end.html#committing-changes "Link to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- **When making changes, also commit the compiled files!** We still use Handlebars templates in some places in Files and Settings. We will replace these step-by-step with Vue.js, but in the meantime, you need to compile them separately. If you don’t have Handlebars installed yet, you can do it with this terminal command: sudo npm install -g handlebars Then inside the root folder of your local Nextcloud development installation, run this command in the terminal every time you changed a `.handlebars` file to compile it: ./build/compile-handlebars-templates.sh Before checking in JS changes, make sure to also build for production: make build-js-production Then add the compiled files for committing. To save some time, to only rebuild for a specific app, use the following and replace the module with the app name: MODULE=user\_status make build-js-production Please note that if you used `make build-js` or `make watch-js` before, you’ll notice that a lot of files were marked as changed, so might need to clear the workspace first. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Back-end code — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/stable/developer_manual/server/index.html) * Back-end code * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/server/code-back-end.rst) * * * Back-end code[](https://docs.nextcloud.com/server/stable/developer_manual/server/code-back-end.html#back-end-code "Link to this heading") =========================================================================================================================================== When changing back-end PHP code, in general, no additional steps are needed before checking in. However, if new files were created, you will need to run the following command to update the autoloader files: build/autoloaderchecker.sh After that, please also include the autoloader file changes in your commits. Compatibility documentation[](https://docs.nextcloud.com/server/stable/developer_manual/server/code-back-end.html#compatibility-documentation "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- * New APIs (interfaces, constants, methods, classes, traits, enums) added to the public namespace `OCP` have to be annotated with a `@since X.Y.Z` attribute of the version it was added in. * When it is backported the version should be adjusted to the X.Y.Z of the stable version it was backported in only in that stable branch. The master branch should still contain the newest Major version shipping the API. * Once an API was shipped, unless it is marked as experimental, it has to be deprecated in similar fashion using `@deprecated X.Y.Z` for 3 years (9 Nextcloud releases) before it can be removed. Deprecations have to be clearly documented in the [App upgrade guide](https://docs.nextcloud.com/server/stable/developer_manual/app_publishing_maintenance/app_upgrade_guide/index.html#app-upgrade-guide) for the upcoming Major version. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Front-end code — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/stable/developer_manual/server/index.html) * Front-end code * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/server/code-front-end.rst) * * * Front-end code[](https://docs.nextcloud.com/server/stable/developer_manual/server/code-front-end.html#front-end-code "Link to this heading") ============================================================================================================================================== Building Vue components and scripts[](https://docs.nextcloud.com/server/stable/developer_manual/server/code-front-end.html#building-vue-components-and-scripts "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- We are moving more and more toward using Vue.js in the front-end, starting with Settings. For building the code on changes, use these terminal commands in the root folder: \# install dependencies npm install \# build for development npm run dev \# build for development and watch edits npm run watch \# build for production with minification npm run build Building styles[](https://docs.nextcloud.com/server/stable/developer_manual/server/code-front-end.html#building-styles "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------ Styles are written in SCSS and compiled to css. \# install dependencies make dev-setup \# compile style sheets npm run sass \# compile style sheets and watch edits npm run sass:watch Committing changes[](https://docs.nextcloud.com/server/stable/developer_manual/server/code-front-end.html#committing-changes "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------ **When making changes, also commit the compiled files!** We still use Handlebars templates in some places in Files and Settings. We will replace these step-by-step with Vue.js, but in the meantime, you need to compile them separately. If you don’t have Handlebars installed yet, you can do it with this terminal command: sudo npm install -g handlebars Then inside the root folder of your local Nextcloud development installation, run this command in the terminal every time you changed a `.handlebars` file to compile it: ./build/compile-handlebars-templates.sh Before checking in JS changes, make sure to also build for production: make build-js-production Then add the compiled files for committing. To save some time, to only rebuild for a specific app, use the following and replace the module with the app name: MODULE=user\_status make build-js-production Please note that if you used `make build-js` or `make watch-js` before, you’ll notice that a lot of files were marked as changed, so might need to clear the workspace first. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # How to test … — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/31/developer_manual/server/index.html) * How to test … * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/how_to/index.rst) * * * How to test …[](https://docs.nextcloud.com/server/31/developer_manual/how_to/index.html#how-to-test "Link to this heading") ============================================================================================================================= This page should explain how to test given features in Nextcloud. Email sending[](https://docs.nextcloud.com/server/31/developer_manual/how_to/index.html#email-sending "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------- docker run \-d \-p 1025:1025 \-p 8025:8025 mailhog/mailhog occ config:system:set mail\_smtpmode \--value\=smtp occ config:system:set mail\_smtphost \--value\=127.0.0.1 occ config:system:set mail\_smtpport \--value\=1025 \--type\=integer Then after having Nextcloud send some emails, open [http://127.0.0.1:8025](http://127.0.0.1:8025/) to view them. Redis[](https://docs.nextcloud.com/server/31/developer_manual/how_to/index.html#redis "Link to this heading") --------------------------------------------------------------------------------------------------------------- First you need to install the [phpredis extension](https://github.com/phpredis/phpredis) . There is a install document available [inside the repo](https://github.com/phpredis/phpredis/blob/develop/INSTALL.markdown) and many linux distribtutions ship it in their repositories as well. > pecl install redis Redis Cluster[](https://docs.nextcloud.com/server/31/developer_manual/how_to/index.html#redis-cluster "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------- For a local Redis cluster setup there are some docker script collected in [this repository](https://github.com/Grokzen/docker-redis-cluster) . It boils down to clone the repo and run make up. Then the redis cluster is available at `localhost:7000`. Following `config.php` can be used: 'memcache.distributed' \=> '\\OC\\Memcache\\Redis', 'redis.cluster' \=> \[\ 'seeds' \=> \[ // provide some/all of the cluster servers to bootstrap discovery, port required\ 'localhost:7000',\ \],\ 'timeout' \=> 0.0,\ 'read\_timeout' \=> 0.0,\ 'failover\_mode' \=> \\RedisCluster::FAILOVER\_ERROR,\ \], Primary object store with S3[](https://docs.nextcloud.com/server/31/developer_manual/how_to/index.html#primary-object-store-with-s3 "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------- docker run \-p 9000:9000 minio/minio server /data The edit `config.php` and add the following section: 'objectstore' \=> array ( 'class' \=> 'OC\\\\Files\\\\ObjectStore\\\\S3', 'arguments' \=> array ( 'bucket' \=> 'nextcloud-dev', 'key' \=> 'minioadmin', 'secret' \=> 'minioadmin', 'hostname' \=> 'localhost', 'port' \=> '9000', 'use\_ssl' \=> false, 'use\_path\_style' \=> true, ), ), S3 external storage[](https://docs.nextcloud.com/server/31/developer_manual/how_to/index.html#s3-external-storage "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------- occ app:enable files\_external docker run \-p 9000:9000 minio/minio server /data Then add an external storage in the web UI using the following configuration: * Authentication type: Access key * Access key: minioadmin * Secret key: minioadmin * Bucket: nextcloud-dev * Hostname: localhost * Port: 9000 * Region: leave empty * Storage class: leave empty * Enable SSL: false * Enable path style: yes SMB external storage[](https://docs.nextcloud.com/server/31/developer_manual/how_to/index.html#smb-external-storage "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------- SMB external storage can be tested with Docker. The following commands create an SMB server with a public (shared) directory and user home directories for the credentials `smb1:pwd1` and `smb2:pwd2`. occ app:enable files\_external mkdir \-p /tmp/samba/{public,home/{smb1,smb2}} chmod a+rw /tmp/samba/home/smb\* docker run \-it \-p 139:139 \-p 445:445 \\ \-v /tmp/samba/public:/smbpublic \\ \-v /tmp/samba/home:/smbhome \\ dperson/samba \\ \-u "smb1;pwd1" \\ \-u "smb2;pwd2" \\ \-s "public;/smbmount;yes;no;yes" \\ \-s "home;/smbhome/%U;yes;no;no;all;none" Make sure that smbclient is installed on your Nextcloud server and has the following configuration: \# /etc/samba/smb.conf \[global\] client min protocol \= SMB2 client max protocol \= SMB3 hide dot files \= no The setup can be verified with smbclient //127.0.0.1/public \-U smb1 \# Shared storage for all users smbclient //127.0.0.1/home \-U smb1 \--password\=pwd1 \# Home storage SAML setup with onelogin[](https://docs.nextcloud.com/server/31/developer_manual/how_to/index.html#saml-setup-with-onelogin "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- * create dev account on onelogin.com * log into onelogin.com * create new app: SAML Test Connector (Advanced) > * go to “Configuration” > > > * Audience: [https://localhost/apps/user\_saml/saml/metadata](https://localhost/apps/user_saml/saml/metadata) > > > > * Recipient: [https://localhost/apps/user\_saml/saml/acs](https://localhost/apps/user_saml/saml/acs) > > > > * ACS (Consumer) URL Validator: [https://localhost/apps/user\_saml/saml/acs](https://localhost/apps/user_saml/saml/acs) > > > > * go to “Parameters” > > > * Add “User.email” -> email (and add to assertion) > > > > * Add “User.FirstName” -> first name (and add to assertion) > > > > * Add “User.LastName” -> last name (and add to assertion) > > > * open Nextcloud SAML settings > * Select SAML > > * Configure it according to [https://portal.nextcloud.com/article/configuring-single-sign-on-10.html](https://portal.nextcloud.com/article/configuring-single-sign-on-10.html) > Collabora without SSL[](https://docs.nextcloud.com/server/31/developer_manual/how_to/index.html#collabora-without-ssl "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------- **1) Start Collabora in a docker container** docker run \-p 127.0.0.1:9980:9980 \-e 'domain=172.17.0.1' \\ \-e 'username=admin' \-e 'password=487903ffcf4' \\ \-e extra\_params\='--o:ssl.enable=false' \\ \--restart always \--cap\-add MKNOD collabora/code * 172.17.0.1 is localhost, which is default by Docker * get IP of Collabora container: docker inspect –format=’{{ .NetworkSettings.IPAddress }}’ $containerName **2) Configure Nextcloud** * go to your local cloud (e.g. 172.17.0.1/nc) -> Settings -> Collabora * set URL to IP you found out above, e.g: [http://172.17.0.2:9980](http://172.17.0.2:9980/) * check “Disable certificate verification (insecure) **3) Use** * please note that you cannot use it with localhost, but you have to enter a valid IP address of localhost * with this approach you can also use it with mobile clients **4) Troubleshoot** * [http://172.17.0.2:9980/hosting/capabilities](http://172.17.0.2:9980/hosting/capabilities) should give you: {"convert-to":{"available":false},"hasMobileSupport":true,"hasTemplateSaveAs":true,"productName":"Collabora Online Development Edition"} OnlyOffice[](https://docs.nextcloud.com/server/31/developer_manual/how_to/index.html#onlyoffice "Link to this heading") ------------------------------------------------------------------------------------------------------------------------- 1. Create self signed cert, should be on a permanent path: mkdir \-p /tmp/oo/certs cd /tmp/oo/certs openssl genrsa \-out onlyoffice.key 4096 openssl req \-new \-key onlyoffice.key \-out onlyoffice.csr openssl x509 \-req \-days 3650 \-in onlyoffice.csr \-signkey onlyoffice.key \-out onlyoffice.crt openssl dhparam \-out dhparam.pem 4096 chmod 400 onlyoffice.key chmod 400 onlyoffice.crt chmod 400 onlyoffice.csr chmod 400 dhparam.pem 2. Start docker, important: do not use certs folder, but parent folder: docker run \--name\=ONLYOFFICEDOCKER \-i \-t \-d \-p 4433:443 \\ \-e JWT\_ENABLED\='true' \-e JWT\_SECRET\='secret' \--restart\=always \\ \-v /tmp/oo/:/var/www/onlyoffice/Data onlyoffice/documentserver 3. Go into docker container: > * docker exec -it ONLYOFFICEDOCKER /bin/bash > > * apt-get update > > * apt-get install vim -y > > * vim /etc/onlyoffice/documentserver/default.json > > * change rejectUnauthorized to false > > > * vim /etc/onlyoffice/documentserver/local.json > > * change token -> inbox -> header to “AuthorizationJWT” > > * change token -> outbox -> header to “AuthorizationJWT” > > > * Add the following to your config.php > > > 'onlyoffice' \=> array ( > 'verify\_peer\_off' \=> true, > 'jwt\_secret' \=> 'secret', > 'jwt\_header' \=> 'AuthorizationJWT' > ), Test with local ip: [https://localhost:4433](https://localhost:4433/) * accept cert warning * verify that “Document Server is running” is shown Test with Nextcloud * download & enable OnlyOffice app * configure: * Document Editing Service address: [https://localhost:4433/](https://localhost:4433/) * Secret key : secret (as above) * Document Editing Service address for internal requests from the server: [https://localhost:4433/](https://localhost:4433/) * Server address for internal requests from the Document Editing Service: [http://192.168.1.95/nc16/](http://192.168.1.95/nc16/) (needs to be real IP address, as localhost points to docker) WebAuthn without SSL[](https://docs.nextcloud.com/server/31/developer_manual/how_to/index.html#webauthn-without-ssl "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------- [Chrome has the option to test WebAuthn with a fake device](https://developer.chrome.com/docs/devtools/webauthn/) . Browsers support WebAuthn on HTTPS protected sites and localhost domains. Unfortunately this is not supported by the used PHP library where the check for HTTPS needs to be commented for testing on non-HTTPS localhost development environments. diff --git a/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php b/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php index 8400ba9c..49279cc7 100644 --- a/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php +++ b/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAssertionResponseValidator.php @@ -152,7 +152,7 @@ class AuthenticatorAssertionResponseValidator Assertion::isArray($parsedRelyingPartyId, 'Invalid origin'); if (!in\_array($facetId, $securedRelyingPartyId, true)) { $scheme = $parsedRelyingPartyId\['scheme'\] ?? ''; - Assertion::eq('https', $scheme, 'Invalid scheme. HTTPS required.'); + #Assertion::eq('https', $scheme, 'Invalid scheme. HTTPS required.'); } $clientDataRpId = $parsedRelyingPartyId\['host'\] ?? ''; Assertion::notEmpty($clientDataRpId, 'Invalid origin rpId.'); diff --git a/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php b/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php index f3e5a15d..3927bf23 100644 --- a/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php +++ b/3rdparty/web-auth/webauthn-lib/src/AuthenticatorAttestationResponseValidator.php @@ -150,7 +150,7 @@ class AuthenticatorAttestationResponseValidator if (!in\_array($facetId, $securedRelyingPartyId, true)) { $scheme = $parsedRelyingPartyId\['scheme'\] ?? ''; - Assertion::eq('https', $scheme, 'Invalid scheme. HTTPS required.'); + #Assertion::eq('https', $scheme, 'Invalid scheme. HTTPS required.'); } /\* @see 7.1.6 \*/ ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Static analysis — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/32/developer_manual/server/index.html) * Static analysis * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/server/static-analysis.rst) * * * Static analysis[](https://docs.nextcloud.com/server/32/developer_manual/server/static-analysis.html#static-analysis "Link to this heading") ============================================================================================================================================= PHP static analysis[](https://docs.nextcloud.com/server/32/developer_manual/server/static-analysis.html#php-static-analysis "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- In the server repository psalm is used for static analysis of the PHP code. ### Required PHP extensions[](https://docs.nextcloud.com/server/32/developer_manual/server/static-analysis.html#required-php-extensions "Link to this heading") The following PHP extensions are required to be installed and enabled to make psalm work: * acpu * curl * ftp * gd * iconv * imagick * json * ldap * libxml * mbstring * openssl * pdo * simplexml * sysvsem * xmlreader * zip Some of these are for optional features, but are still required to validate the code. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Static analysis — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/stable/developer_manual/server/index.html) * Static analysis * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/server/static-analysis.rst) * * * Static analysis[](https://docs.nextcloud.com/server/stable/developer_manual/server/static-analysis.html#static-analysis "Link to this heading") ================================================================================================================================================= PHP static analysis[](https://docs.nextcloud.com/server/stable/developer_manual/server/static-analysis.html#php-static-analysis "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------- In the server repository psalm is used for static analysis of the PHP code. ### Required PHP extensions[](https://docs.nextcloud.com/server/stable/developer_manual/server/static-analysis.html#required-php-extensions "Link to this heading") The following PHP extensions are required to be installed and enabled to make psalm work: * acpu * curl * ftp * gd * iconv * imagick * json * ldap * libxml * mbstring * openssl * pdo * simplexml * sysvsem * xmlreader * zip Some of these are for optional features, but are still required to validate the code. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Back-end code — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/32/developer_manual/index.html) * [Server development](https://docs.nextcloud.com/server/32/developer_manual/server/index.html) * Back-end code * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/server/code-back-end.rst) * * * Back-end code[](https://docs.nextcloud.com/server/32/developer_manual/server/code-back-end.html#back-end-code "Link to this heading") ======================================================================================================================================= When changing back-end PHP code, in general, no additional steps are needed before checking in. However, if new files were created, you will need to run the following command to update the autoloader files: build/autoloaderchecker.sh After that, please also include the autoloader file changes in your commits. Compatibility documentation[](https://docs.nextcloud.com/server/32/developer_manual/server/code-back-end.html#compatibility-documentation "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- * New APIs (interfaces, constants, methods, classes, traits, enums) added to the public namespace `OCP` have to be annotated with a `@since X.Y.Z` attribute of the version it was added in. * When it is backported the version should be adjusted to the X.Y.Z of the stable version it was backported in only in that stable branch. The master branch should still contain the newest Major version shipping the API. * Once an API was shipped, unless it is marked as experimental, it has to be deprecated in similar fashion using `@deprecated X.Y.Z` for 3 years (9 Nextcloud releases) before it can be removed. Deprecations have to be clearly documented in the [App upgrade guide](https://docs.nextcloud.com/server/32/developer_manual/app_publishing_maintenance/app_upgrade_guide/index.html#app-upgrade-guide) for the upcoming Major version. ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [31](https://docs.nextcloud.com/server/31/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) --- # Events — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/31/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/31/developer_manual/basics/index.html) * Events * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/events.rst) * * * Events[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#events "Link to this heading") ================================================================================================================== Events are used to communicate between different aspects of the Nextcloud eco system. They are used in the Nextcloud server internally, for server-to-apps communication as well as inter-app communication. Overview[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#overview "Link to this heading") ---------------------------------------------------------------------------------------------------------------------- The term “events” is a bit broad in Nextcloud and there are multiple ways of emitting them. * [OCP event dispatcher](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-event-dispatcher) * [Hooks](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#hooks) * [Public Emitter](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#public-emitter) OCP event dispatcher[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-event-dispatcher "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- This mechanism is a versatile and typed approach to events in Nextcloud’s php code. It uses objects rather than just passing primitives or untyped arrays. This should help provide a better developer experience while lowering the risk of unexpected changes in the API that are hard to find after the initial implementation. ### Naming scheme[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#naming-scheme "Link to this heading") The name should reflect the subject and the actions. Suffixing event classes with Event makes it easier to recognize their purpose. For example, if a user is created, a UserCreatedEvent will be emitted. Events are usually emitted _after_ the event has happened. If it’s emitted before, it should be prefixed with Before. Thus BeforeUserCreatedEvent is emitted _before_ the user data is written to the database. Note Although you may choose to name your event classes differently, sticking to the convention will allow Nextcloud developers understand each other’s apps more easily. Note For backwards compatibility with the Symfony class [GenericEvent](https://symfony.com/doc/current/components/event_dispatcher/generic_event.html) , Nextcloud also provides a `\OCP\EventDispatcher\Event` class. With the release of Nextcloud 22 this class has been deprecated. Named and typed event classes should be used instead. ### Writing events[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#writing-events "Link to this heading") As a rule events are dedicated classes extending `\OCP\EventDispatcher\Event`. user \= $user; } public function getUser(): IUser { return $this\->user; } } ### Writing a listener[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#writing-a-listener "Link to this heading") A listener can be a simple callback function (or anything else that is [callable](https://www.php.net/manual/en/language.types.callable.php) , or a dedicated class. #### Listener callbacks[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#listener-callbacks "Link to this heading") You can use simple callback to react on events. They will receive the event object as first and only parameter. You can type-hint the base Event class or the subclass you expect and register for. getContainer()\->query(IEventDispatcher::class); $dispatcher\->addListener(AddEvent::class, function(AddEvent $event) { // ... }); } } Note Type-hinting the actual event class will give you better IDE and static analyzers support. It’s generally safe to assume the dispatcher will not give you any other objects. #### Listener classes[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#listener-classes "Link to this heading") A class that can handle an event will implement the `\OCP\EventDispatcher\IEventListener` interface. Class names should end with Listener. addToCounter(2); } } Note Php parameter type hints are not allowed to be more specific than the type hints on the interface, thus you can’t use AddEvent in the method signature but use an instanceOf instead. In the `Application.php` the event and the listener class are connected. The class is instantiated only when the actual event is fired. getContainer()\->get(IEventDispatcher::class); $dispatcher\->addServiceListener(AddEvent::class, AddTwoListener::class); } } Note The listener is resolved via the DI container, therefore you can add a constructor and type-hint services required for processing the event. ### Available Events[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#available-events "Link to this heading") Here you find an overview of the public events that can be consumed in apps. See their source files for more details. #### `\OCA\DAV\Events\AddressBookCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-addressbookcreatedevent "Link to this heading") Added in version 20. This event is triggered when a user creates a new address-book. #### `\OCA\DAV\Events\AddressBookDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-addressbookdeletedevent "Link to this heading") Added in version 20. This event is triggered when a user deletes an address-book. #### `\OCA\DAV\Events\AddressBookShareUpdatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-addressbookshareupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user shares or unshares an address-book. #### `\OCA\DAV\Events\AddressBookUpdatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-addressbookupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user updates an address-book. #### `\OCA\DAV\Events\CachedCalendarObjectCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-cachedcalendarobjectcreatedevent "Link to this heading") Added in version 20. This event is triggered when a cached calendar object is being created while fetching a calendar-subscription. #### `\OCA\DAV\Events\CachedCalendarObjectDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-cachedcalendarobjectdeletedevent "Link to this heading") Added in version 20. This event is triggered when a cached calendar object is being deleted while fetching a calendar-subscription. #### `\OCA\DAV\Events\CachedCalendarObjectUpdatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-cachedcalendarobjectupdatedevent "Link to this heading") Added in version 20. This event is triggered when a cached calendar object is being updated while fetching a calendar-subscription. #### `\OCA\DAV\Events\CalendarCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-calendarcreatedevent "Link to this heading") Added in version 20. This event is triggered when a user creates a new calendar. #### `\OCA\DAV\Events\CalendarDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-calendardeletedevent "Link to this heading") Added in version 20. This event is triggered when a user deletes a calendar. #### `\OCA\DAV\Events\CalendarObjectCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-calendarobjectcreatedevent "Link to this heading") Added in version 20. This event is triggered when a user creates a calendar-object. #### `\OCA\DAV\Events\CalendarObjectDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-calendarobjectdeletedevent "Link to this heading") Added in version 20. This event is triggered when a user deletes a calendar-object. #### `\OCA\DAV\Events\CalendarObjectUpdatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-calendarobjectupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user updates a calendar-object. #### `\OCA\DAV\Events\CalendarPublishedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-calendarpublishedevent "Link to this heading") Added in version 20. This event is triggered when a user publishes a calendar. #### `\OCA\DAV\Events\CalendarShareUpdatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-calendarshareupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user shares or unshares a calendar. #### `\OCA\DAV\Events\CalendarUnpublishedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-calendarunpublishedevent "Link to this heading") Added in version 20. This event is triggered when a user unpublishes calendar. #### `\OCA\DAV\Events\CalendarUpdatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-calendarupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user updates a calendar. #### `\OCA\DAV\Events\CardCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-cardcreatedevent "Link to this heading") Added in version 20. This event is triggered when a user creates a new card in an address-book. #### `\OCA\DAV\Events\CardDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-carddeletedevent "Link to this heading") Added in version 20. This event is triggered when a user deletes a card in an address-book. #### `\OCA\DAV\Events\CardUpdatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-cardupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user updates a card in an address-book. #### `OCA\DAV\Events\SabrePluginAddEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-sabrepluginaddevent "Link to this heading") Added in version 28. This event is triggered during the setup of the SabreDAV server to allow the registration of additional plugins. #### `\OCA\DAV\Events\SabrePluginAuthInitEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-sabrepluginauthinitevent "Link to this heading") Added in version 20. This event is triggered during the setup of the SabreDAV server to allow the registration of additional authentication backends. #### `\OCA\DAV\Events\SubscriptionCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-subscriptioncreatedevent "Link to this heading") Added in version 20. This event is triggered when a user creates a new calendar-subscription. #### `\OCA\DAV\Events\SubscriptionDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-subscriptiondeletedevent "Link to this heading") Added in version 20. This event is triggered when a user deletes a calendar-subscription. #### `\OCA\DAV\Events\SubscriptionUpdatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-dav-events-subscriptionupdatedevent "Link to this heading") Added in version 20. This event is triggered when a user deletes a calendar-subscription. #### `\OCA\FederatedFileSharing\Events\FederatedShareAddedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-federatedfilesharing-events-federatedshareaddedevent "Link to this heading") Added in version 20. This event is triggered when a federated share is successfully added. #### `\OCA\Files\Event\LoadAdditionalScriptsEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-files-event-loadadditionalscriptsevent "Link to this heading") Added in version 17. This event is triggered when the files app is rendered. It can be used to add additional scripts to the files app. #### `\OCA\Files_Sharing\Event\BeforeTemplateRenderedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-files-sharing-event-beforetemplaterenderedevent "Link to this heading") Added in version 20. Emitted before the rendering step of the public share page happens. The event holds a flag that specifies if it is the authentication page of a public share. #### `\OCA\Files_Trashbin\Events\MoveToTrashEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-files-trashbin-events-movetotrashevent "Link to this heading") Added in version 28. Emitted after a file or folder is moved to the trashbin. #### `\OCA\Settings\Events\BeforeTemplateRenderedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-settings-events-beforetemplaterenderedevent "Link to this heading") Added in version 20. This event is triggered right before the user management template is rendered. #### `\OCA\User_LDAP\Events\GroupBackendRegistered`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-user-ldap-events-groupbackendregistered "Link to this heading") Added in version 20. This event is triggered right after the LDAP group backend is registered. #### `\OCA\User_LDAP\Events\UserBackendRegistered`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-user-ldap-events-userbackendregistered "Link to this heading") Added in version 20. This event is triggered right after the LDAP user backend is registered. #### `\OCA\Viewer\Event\LoadViewer`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#oca-viewer-event-loadviewer "Link to this heading") Added in version 17. This event is triggered whenever the viewer is loaded and extensions should be loaded. #### `OCP\Accounts\UserUpdatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-accounts-userupdatedevent "Link to this heading") Added in version 28. This event is triggered when the account data of a user was updated. #### `OCP\App\Events\AppDisableEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-app-events-appdisableevent "Link to this heading") Added in version 27. This event is triggered when an app is disabled. #### `OCP\App\Events\AppEnableEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-app-events-appenableevent "Link to this heading") Added in version 27. This event is triggered when an app is enabled. #### `OCP\App\Events\AppUpdateEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-app-events-appupdateevent "Link to this heading") Added in version 27. This event is triggered when an app is updated. #### `OCP\App\ManagerEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-app-managerevent "Link to this heading") Added in version 9. Class ManagerEvent #### `OCP\AppFramework\Http\Events\BeforeLoginTemplateRenderedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-appframework-http-events-beforelogintemplaterenderedevent "Link to this heading") Added in version 28. Emitted before the rendering step of the login TemplateResponse. #### `OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-appframework-http-events-beforetemplaterenderedevent "Link to this heading") Added in version 20. Emitted before the rendering step of each TemplateResponse. The event holds a flag that specifies if an user is logged in. #### `OCP\Authentication\Events\AnyLoginFailedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-authentication-events-anyloginfailedevent "Link to this heading") Added in version 26. Emitted when the authentication fails #### `OCP\Authentication\Events\LoginFailedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-authentication-events-loginfailedevent "Link to this heading") Added in version 19. Emitted when the authentication fails, but only if the login name can be associated with an existing user. #### `OCP\Authentication\TwoFactorAuth\RegistryEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-authentication-twofactorauth-registryevent "Link to this heading") Added in version 15. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengeFailed`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderchallengefailed "Link to this heading") Added in version 28. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengePassed`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderchallengepassed "Link to this heading") Added in version 28. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderDisabled`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderdisabled "Link to this heading") Added in version 20. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserDisabled`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderforuserdisabled "Link to this heading") Added in version 22. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserEnabled`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderforuserenabled "Link to this heading") Added in version 22. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserRegistered`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderforuserregistered "Link to this heading") Added in version 28. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserUnregistered`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorproviderforuserunregistered "Link to this heading") Added in version 28. #### `OCP\Authentication\TwoFactorAuth\TwoFactorProviderUserDeleted`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-authentication-twofactorauth-twofactorprovideruserdeleted "Link to this heading") Added in version 28. #### `OCP\BeforeSabrePubliclyLoadedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-beforesabrepubliclyloadedevent "Link to this heading") Added in version 26. Dispatched before Sabre is loaded when accessing public webdav endpoints This can be used to inject a Sabre plugin for example #### `OCP\Collaboration\AutoComplete\AutoCompleteEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-collaboration-autocomplete-autocompleteevent "Link to this heading") Added in version 16. #### `OCP\Collaboration\AutoComplete\AutoCompleteFilterEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-collaboration-autocomplete-autocompletefilterevent "Link to this heading") Added in version 28. #### `OCP\Collaboration\Reference\RenderReferenceEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-collaboration-reference-renderreferenceevent "Link to this heading") Added in version 25. Event emitted when apps might render references like link previews or smart picker widgets. This can be used to inject scripts for extending that. Further details can be found in the [Reference providers](https://docs.nextcloud.com/server/31/developer_manual/digging_deeper/reference.html#reference-providers) deep dive. #### `OCP\Collaboration\Resources\LoadAdditionalScriptsEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-collaboration-resources-loadadditionalscriptsevent "Link to this heading") Added in version 25. This event is used by apps to register their own frontend scripts for integrating projects in their app. Apps also need to dispatch the event in order to load scripts during page load #### `OCP\Comments\CommentsEntityEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-comments-commentsentityevent "Link to this heading") Added in version 9.1. Changed in version 28.0.0: Dispatched as a typed event Class CommentsEntityEvent #### `OCP\Comments\CommentsEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-comments-commentsevent "Link to this heading") Added in version 9. Class CommentsEvent #### `OCP\Config\BeforePreferenceDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-config-beforepreferencedeletedevent "Link to this heading") Added in version 25. #### `OCP\Config\BeforePreferenceSetEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-config-beforepreferencesetevent "Link to this heading") Added in version 25. #### `OCP\Console\ConsoleEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-console-consoleevent "Link to this heading") Added in version 9. Class ConsoleEvent #### `OCP\Contacts\Events\ContactInteractedWithEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-contacts-events-contactinteractedwithevent "Link to this heading") Added in version 19. An event that allows apps to notify other components about an interaction between two users. This can be used to build better recommendations and suggestions in user interfaces. Emitters should add at least one identifier (uid, email, federated cloud ID) of the recipient of the interaction. #### `OCP\DB\Events\AddMissingColumnsEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-db-events-addmissingcolumnsevent "Link to this heading") Added in version 28. Event to allow apps to register information about missing database columns This event will be dispatched for checking on the admin settings and when running occ db:add-missing-columns which will then create those columns #### `OCP\DB\Events\AddMissingIndicesEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-db-events-addmissingindicesevent "Link to this heading") Added in version 28. Event to allow apps to register information about missing database indices This event will be dispatched for checking on the admin settings and when running occ db:add-missing-indices which will then create those indices #### `OCP\DB\Events\AddMissingPrimaryKeyEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-db-events-addmissingprimarykeyevent "Link to this heading") Added in version 28. Event to allow apps to register information about missing database primary keys This event will be dispatched for checking on the admin settings and when running occ db:add-missing-primary-keys which will then create those keys #### `OCP\DirectEditing\RegisterDirectEditorEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-directediting-registerdirecteditorevent "Link to this heading") Added in version 18. Event to allow to register the direct editor. #### `OCP\EventDispatcher\GenericEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-eventdispatcher-genericevent "Link to this heading") Added in version 18. Class GenericEvent convenience reimplementation of SymfonyComponentGenericEvent against OCPEventDispatcherEvent #### `OCP\Federation\Events\TrustedServerRemovedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-federation-events-trustedserverremovedevent "Link to this heading") Added in version 25. #### `OCP\Files\Cache\AbstractCacheEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-cache-abstractcacheevent "Link to this heading") Added in version 22. #### `OCP\Files\Cache\CacheEntryInsertedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-cache-cacheentryinsertedevent "Link to this heading") Added in version 21. Event for when an existing entry in the cache gets inserted #### `OCP\Files\Cache\CacheEntryRemovedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-cache-cacheentryremovedevent "Link to this heading") Added in version 21. Event for when an existing entry in the cache gets removed #### `OCP\Files\Cache\CacheEntryUpdatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-cache-cacheentryupdatedevent "Link to this heading") Added in version 21. Event for when an existing entry in the cache gets updated #### `OCP\Files\Cache\CacheInsertEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-cache-cacheinsertevent "Link to this heading") Added in version 16. Event for when a new entry gets added to the cache #### `OCP\Files\Cache\CacheUpdateEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-cache-cacheupdateevent "Link to this heading") Added in version 16. Event for when an existing entry in the cache gets updated #### `OCP\Files\Events\BeforeDirectFileDownloadEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-beforedirectfiledownloadevent "Link to this heading") Added in version 25. This event is triggered when a user tries to download a file directly. #### `OCP\Files\Events\BeforeFileScannedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-beforefilescannedevent "Link to this heading") Added in version 18. #### `OCP\Files\Events\BeforeFolderScannedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-beforefolderscannedevent "Link to this heading") Added in version 18. #### `OCP\Files\Events\BeforeZipCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-beforezipcreatedevent "Link to this heading") Added in version 25. #### `OCP\Files\Events\FileCacheUpdated`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-filecacheupdated "Link to this heading") Added in version 18. #### `OCP\Files\Events\FileScannedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-filescannedevent "Link to this heading") Added in version 18. #### `OCP\Files\Events\FolderScannedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-folderscannedevent "Link to this heading") Added in version 18. #### `OCP\Files\Events\InvalidateMountCacheEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-invalidatemountcacheevent "Link to this heading") Added in version 24. Used to notify the filesystem setup manager that the available mounts for a user have changed #### `OCP\Files\Events\Node\BeforeNodeCopiedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-beforenodecopiedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\BeforeNodeCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-beforenodecreatedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\BeforeNodeDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-beforenodedeletedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\BeforeNodeReadEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-beforenodereadevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\BeforeNodeRenamedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-beforenoderenamedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\BeforeNodeTouchedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-beforenodetouchedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\BeforeNodeWrittenEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-beforenodewrittenevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\FilesystemTornDownEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-filesystemtorndownevent "Link to this heading") Added in version 24. Event fired after the filesystem has been torn down #### `OCP\Files\Events\Node\NodeCopiedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-nodecopiedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\NodeCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-nodecreatedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\NodeDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-nodedeletedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\NodeRenamedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-noderenamedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\NodeTouchedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-nodetouchedevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\Node\NodeWrittenEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-node-nodewrittenevent "Link to this heading") Added in version 20. #### `OCP\Files\Events\NodeAddedToCache`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-nodeaddedtocache "Link to this heading") Added in version 18. #### `OCP\Files\Events\NodeAddedToFavorite`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-nodeaddedtofavorite "Link to this heading") Added in version 28. #### `OCP\Files\Events\NodeRemovedFromCache`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-noderemovedfromcache "Link to this heading") Added in version 18. #### `OCP\Files\Events\NodeRemovedFromFavorite`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-events-noderemovedfromfavorite "Link to this heading") Added in version 28. #### `OCP\Files\Template\BeforeGetTemplatesEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-template-beforegettemplatesevent "Link to this heading") Added in version 30. #### `OCP\Files\Template\FileCreatedFromTemplateEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-template-filecreatedfromtemplateevent "Link to this heading") Added in version 21. #### `OCP\Files\Template\RegisterTemplateCreatorEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-files-template-registertemplatecreatorevent "Link to this heading") Added in version 30. #### `OCP\FilesMetadata\Event\MetadataBackgroundEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-filesmetadata-event-metadatabackgroundevent "Link to this heading") Added in version 28. MetadataBackgroundEvent is an event similar to MetadataLiveEvent but dispatched on a background thread instead of live thread. Meaning there is no limit to the time required for the generation of your metadata. #### `OCP\FilesMetadata\Event\MetadataLiveEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-filesmetadata-event-metadataliveevent "Link to this heading") Added in version 28. MetadataLiveEvent is an event initiated when a file is created or updated. The app contains the Node related to the created/updated file, and a FilesMetadata that already contains the currently known metadata. Setting new metadata, or modifying already existing metadata with different value, will trigger the save of the metadata in the database. #### `OCP\FilesMetadata\Event\MetadataNamedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-filesmetadata-event-metadatanamedevent "Link to this heading") Added in version 28. MetadataNamedEvent is an event similar to MetadataBackgroundEvent completed with a target name, used to limit the refresh of metadata only listeners capable of filtering themselves out. Meaning that when using this event, your app must implement a filter on the event’s registered name returned by getName() This event is mostly triggered when a registered name is added to the files scan i.e. ./occ files:scan –generate-metadata \[name\] #### `OCP\Group\Events\BeforeGroupChangedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-group-events-beforegroupchangedevent "Link to this heading") Added in version 26. #### `OCP\Group\Events\BeforeGroupCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-group-events-beforegroupcreatedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\BeforeGroupDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-group-events-beforegroupdeletedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\BeforeUserAddedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-group-events-beforeuseraddedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\BeforeUserRemovedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-group-events-beforeuserremovedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\GroupChangedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-group-events-groupchangedevent "Link to this heading") Added in version 26. #### `OCP\Group\Events\GroupCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-group-events-groupcreatedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\GroupDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-group-events-groupdeletedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\SubAdminAddedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-group-events-subadminaddedevent "Link to this heading") Added in version 21. #### `OCP\Group\Events\SubAdminRemovedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-group-events-subadminremovedevent "Link to this heading") Added in version 21. #### `OCP\Group\Events\UserAddedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-group-events-useraddedevent "Link to this heading") Added in version 18. #### `OCP\Group\Events\UserRemovedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-group-events-userremovedevent "Link to this heading") Added in version 18. #### `OCP\Log\Audit\CriticalActionPerformedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-log-audit-criticalactionperformedevent "Link to this heading") Added in version 22. Emitted when the admin\_audit app should log an entry #### `OCP\Log\BeforeMessageLoggedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-log-beforemessageloggedevent "Link to this heading") Added in version 28. Even for when a log item is being logged #### `OCP\Mail\Events\BeforeMessageSent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-mail-events-beforemessagesent "Link to this heading") Added in version 19. Emitted before a system mail is sent. It can be used to alter the message. #### `OCP\OCM\Events\ResourceTypeRegisterEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-ocm-events-resourcetyperegisterevent "Link to this heading") Added in version 28. Use this event to register additional OCM resources before the API returns them in the OCM provider list and capability #### `OCP\Preview\BeforePreviewFetchedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-preview-beforepreviewfetchedevent "Link to this heading") Added in version 25.0.1. Changed in version 28.0.0: the constructor arguments `$width`, `$height`, `$crop` and `$mode` are no longer nullable. Emitted before a file preview is being fetched. It can be used to block preview rendering by throwing a `OCP\Files\NotFoundException` #### `OCP\Profile\BeforeTemplateRenderedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-profile-beforetemplaterenderedevent "Link to this heading") Added in version 25. Emitted before the rendering step of the public profile page happens. #### `OCP\SabrePluginEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-sabrepluginevent "Link to this heading") Added in version 8.2. #### `OCP\Security\CSP\AddContentSecurityPolicyEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-security-csp-addcontentsecuritypolicyevent "Link to this heading") Added in version 17. Allows to inject something into the default content policy. This is for example useful when you’re injecting Javascript code into a view belonging to another controller and cannot modify its Content-Security-Policy itself. Note that the adjustment is only applied to applications that use AppFramework controllers. WARNING: Using this API incorrectly may make the instance more insecure. Do think twice before adding whitelisting resources. Please do also note that it is not possible to use the disallowXYZ functions. #### `OCP\Security\Events\GenerateSecurePasswordEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-security-events-generatesecurepasswordevent "Link to this heading") Added in version 18. Event to request a secure password to be generated. Since Nextcloud 31 this event also provides a `getContext` method allowing to apply different rules for different password context like account passwords or share passwords. #### `OCP\Security\Events\ValidatePasswordPolicyEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-security-events-validatepasswordpolicyevent "Link to this heading") Added in version 18. This event can be emitted to request a validation of a password. If a password policy app is installed and the password is invalid, an OCPHintException will be thrown. Since Nextcloud 31 this event also provides a `getContext` method allowing to apply different rules for different password context like account passwords or share passwords. #### `OCP\Security\FeaturePolicy\AddFeaturePolicyEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-security-featurepolicy-addfeaturepolicyevent "Link to this heading") Added in version 17. Event that allows to register a feature policy header to a request. #### `OCP\Settings\Events\DeclarativeSettingsGetValueEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-settings-events-declarativesettingsgetvalueevent "Link to this heading") Added in version 29. #### `OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-settings-events-declarativesettingsregisterformevent "Link to this heading") Added in version 29. #### `OCP\Settings\Events\DeclarativeSettingsSetValueEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-settings-events-declarativesettingssetvalueevent "Link to this heading") Added in version 29. #### `OCP\Share\Events\BeforeShareCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-share-events-beforesharecreatedevent "Link to this heading") Added in version 28. #### `OCP\Share\Events\BeforeShareDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-share-events-beforesharedeletedevent "Link to this heading") Added in version 28. #### `OCP\Share\Events\ShareAcceptedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-share-events-shareacceptedevent "Link to this heading") Added in version 28. #### `OCP\Share\Events\ShareCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-share-events-sharecreatedevent "Link to this heading") Added in version 18. #### `OCP\Share\Events\ShareDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-share-events-sharedeletedevent "Link to this heading") Added in version 21. #### `OCP\Share\Events\ShareDeletedFromSelfEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-share-events-sharedeletedfromselfevent "Link to this heading") Added in version 28. #### `OCP\Share\Events\VerifyMountPointEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-share-events-verifymountpointevent "Link to this heading") Added in version 19. #### `OCP\SpeechToText\Events\TranscriptionFailedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-speechtotext-events-transcriptionfailedevent "Link to this heading") Added in version 27. This Event is emitted if a transcription of a media file using a Speech-To-Text provider failed #### `OCP\SpeechToText\Events\TranscriptionSuccessfulEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-speechtotext-events-transcriptionsuccessfulevent "Link to this heading") Added in version 27. This Event is emitted when a transcription of a media file happened successfully #### `OCP\SystemTag\ManagerEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-systemtag-managerevent "Link to this heading") Added in version 9. Class ManagerEvent #### `OCP\SystemTag\MapperEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-systemtag-mapperevent "Link to this heading") Added in version 9. Class MapperEvent #### `OCP\SystemTag\SystemTagsEntityEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-systemtag-systemtagsentityevent "Link to this heading") Added in version 9.1. Changed in version 28.0.0: Dispatched as a typed event Class SystemTagsEntityEvent #### `OCP\TaskProcessing\Events\TaskFailedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-taskprocessing-events-taskfailedevent "Link to this heading") Added in version 30. #### `OCP\TaskProcessing\Events\TaskSuccessfulEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-taskprocessing-events-tasksuccessfulevent "Link to this heading") Added in version 30. #### `OCP\TextProcessing\Events\TaskFailedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-textprocessing-events-taskfailedevent "Link to this heading") Added in version 27.1. #### `OCP\TextProcessing\Events\TaskSuccessfulEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-textprocessing-events-tasksuccessfulevent "Link to this heading") Added in version 27.1. #### `OCP\TextToImage\Events\TaskFailedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-texttoimage-events-taskfailedevent "Link to this heading") Added in version 28. #### `OCP\TextToImage\Events\TaskSuccessfulEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-texttoimage-events-tasksuccessfulevent "Link to this heading") Added in version 28. #### `OCP\User\Events\BeforePasswordUpdatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-beforepasswordupdatedevent "Link to this heading") Added in version 18. Emitted before the user password is updated. #### `OCP\User\Events\BeforeUserCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-beforeusercreatedevent "Link to this heading") Added in version 18. Emitted before a new user is created on the back-end. #### `OCP\User\Events\BeforeUserDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-beforeuserdeletedevent "Link to this heading") Added in version 18. #### `OCP\User\Events\BeforeUserLoggedInEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-beforeuserloggedinevent "Link to this heading") Added in version 18. #### `OCP\User\Events\BeforeUserLoggedInWithCookieEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-beforeuserloggedinwithcookieevent "Link to this heading") Added in version 18. Emitted before a user is logged in via remember-me cookies. #### `OCP\User\Events\BeforeUserLoggedOutEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-beforeuserloggedoutevent "Link to this heading") Added in version 18. Emitted before a user is logged out. #### `OCP\User\Events\OutOfOfficeChangedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-outofofficechangedevent "Link to this heading") Added in version 28. Emitted when a user’s out-of-office period has changed #### `OCP\User\Events\OutOfOfficeClearedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-outofofficeclearedevent "Link to this heading") Added in version 28. Emitted when a user’s out-of-office period is cleared #### `OCP\User\Events\OutOfOfficeEndedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-outofofficeendedevent "Link to this heading") Added in version 28. Emitted when a user’s out-of-office period ended #### `OCP\User\Events\OutOfOfficeScheduledEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-outofofficescheduledevent "Link to this heading") Added in version 28. Emitted when a user’s out-of-office period is scheduled #### `OCP\User\Events\OutOfOfficeStartedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-outofofficestartedevent "Link to this heading") Added in version 28. Emitted when a user’s out-of-office period started #### `OCP\User\Events\PasswordUpdatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-passwordupdatedevent "Link to this heading") Added in version 18. Emitted when the user password has been updated. #### `OCP\User\Events\PostLoginEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-postloginevent "Link to this heading") Added in version 18. #### `OCP\User\Events\UserChangedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-userchangedevent "Link to this heading") Added in version 18. #### `OCP\User\Events\UserCreatedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-usercreatedevent "Link to this heading") Added in version 18. Emitted when a new user has been created on the back-end. #### `OCP\User\Events\UserDeletedEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-userdeletedevent "Link to this heading") Added in version 18. #### `OCP\User\Events\UserFirstTimeLoggedInEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-userfirsttimeloggedinevent "Link to this heading") Added in version 28. #### `OCP\User\Events\UserLiveStatusEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-userlivestatusevent "Link to this heading") Added in version 20. #### `OCP\User\Events\UserLoggedInEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-userloggedinevent "Link to this heading") Added in version 18. #### `OCP\User\Events\UserLoggedInWithCookieEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-userloggedinwithcookieevent "Link to this heading") Added in version 18. Emitted when a user has been successfully logged in via remember-me cookies. #### `OCP\User\Events\UserLoggedOutEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-events-userloggedoutevent "Link to this heading") Added in version 18. Emitted when a user has been logged out successfully. #### `OCP\User\GetQuotaEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-user-getquotaevent "Link to this heading") Added in version 20. Event to allow apps to #### `OCP\WorkflowEngine\Events\LoadSettingsScriptsEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-workflowengine-events-loadsettingsscriptsevent "Link to this heading") Added in version 20. Emitted when the workflow engine settings page is loaded. #### `OCP\WorkflowEngine\Events\RegisterChecksEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-workflowengine-events-registerchecksevent "Link to this heading") Added in version 18. #### `OCP\WorkflowEngine\Events\RegisterEntitiesEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-workflowengine-events-registerentitiesevent "Link to this heading") Added in version 18. #### `OCP\WorkflowEngine\Events\RegisterOperationsEvent`[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-workflowengine-events-registeroperationsevent "Link to this heading") Added in version 18. Hooks[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#hooks "Link to this heading") ---------------------------------------------------------------------------------------------------------------- Deprecated since version 18: Use the [OCP event dispatcher](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-event-dispatcher) instead. Hooks are used to execute code before or after an event has occurred. This is for instance useful to run cleanup code after users, groups or files have been deleted. Hooks should be registered in the [app.php](https://docs.nextcloud.com/server/31/developer_manual/app_development/init.html) : getContainer()\->query('UserHooks')\->register(); The hook logic should be in a separate class that is being registered in the [App constructor](https://docs.nextcloud.com/server/31/developer_manual/basics/dependency_injection.html#using-a-container) : getContainer(); /\*\* \* Controllers \*/ $container\->registerService('UserHooks', function($c) { return new UserHooks( $c\->get(\\OCP\\IUserManager::class) ); }); } } userManager \= $userManager; } public function register() { $callback \= function($user) { // your code that executes before $user is deleted }; $this\->userManager\->listen('\\OC\\User', 'preDelete', $callback); } } ### Available hooks[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#available-hooks "Link to this heading") The scope is the first parameter that is passed to the **listen** method, the second parameter is the method and the third one the callback that should be executed once the hook is being called, e.g.: listen('\\OC\\User', 'preDelete', $callback); Hooks can also be removed by using the **removeListener** method on the object: removeListener(null, null, $callback); The following hooks are available: ### Session[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#session "Link to this heading") Injectable from the ServerContainer with the `\OCP\IUserSession` service. Hooks available in scope **\\OC\\User**: * **preSetPassword** (\\OC\\User\\User $user, string $password, string $recoverPassword) * **postSetPassword** (\\OC\\User\\User $user, string $password, string $recoverPassword) * **changeUser** (\\OC\\User\\User $user, string $feature, string $value) * **preDelete** (\\OC\\User\\User $user) * **postDelete** (\\OC\\User\\User $user) * **preCreateUser** (string $uid, string $password) * **postCreateUser** (\\OC\\User\\User $user) * **preLogin** (string $user, string $password) * **postLogin** (\\OC\\User\\User $user, string $password) * **logout** () ### UserManager[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#usermanager "Link to this heading") Injectable from the ServerContainer with the `\OCP\IUserManager` service. Hooks available in scope **\\OC\\User**: * **preSetPassword** (\\OC\\User\\User $user, string $password, string $recoverPassword) * **postSetPassword** (\\OC\\User\\User $user, string $password, string $recoverPassword) * **preDelete** (\\OC\\User\\User $user) * **postDelete** (\\OC\\User\\User $user) * **preCreateUser** (string $uid, string $password) * **postCreateUser** (\\OC\\User\\User $user, string $password) ### GroupManager[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#groupmanager "Link to this heading") Hooks available in scope **\\OC\\Group**: * **preAddUser** (\\OC\\Group\\Group $group, \\OC\\User\\User $user) * **postAddUser** (\\OC\\Group\\Group $group, \\OC\\User\\User $user) * **preRemoveUser** (\\OC\\Group\\Group $group, \\OC\\User\\User $user) * **postRemoveUser** (\\OC\\Group\\Group $group, \\OC\\User\\User $user) * **preDelete** (\\OC\\Group\\Group $group) * **postDelete** (\\OC\\Group\\Group $group) * **preCreate** (string $groupId) * **postCreate** (\\OC\\Group\\Group $group) ### Filesystem root[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#filesystem-root "Link to this heading") Injectable from the ServerContainer by calling the method **getRootFolder()**, **getUserFolder()** or **getAppFolder()**. To enable these events for your app you should add the following to your info.xml file: Filesystem hooks available in scope **\\OC\\Files**: * **preWrite** (\\OCP\\Files\\Node $node) * **postWrite** (\\OCP\\Files\\Node $node) * **preCreate** (\\OCP\\Files\\Node $node) * **postCreate** (\\OCP\\Files\\Node $node) * **preDelete** (\\OCP\\Files\\Node $node) * **postDelete** (\\OCP\\Files\\Node $node) * **preTouch** (\\OCP\\Files\\Node $node, int $mtime) * **postTouch** (\\OCP\\Files\\Node $node) * **preCopy** (\\OCP\\Files\\Node $source, \\OCP\\Files\\Node $target) * **postCopy** (\\OCP\\Files\\Node $source, \\OCP\\Files\\Node $target) * **preRename** (\\OCP\\Files\\Node $source, \\OCP\\Files\\Node $target) * **postRename** (\\OCP\\Files\\Node $source, \\OCP\\Files\\Node $target) ### Filesystem scanner[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#filesystem-scanner "Link to this heading") Filesystem scanner hooks available in scope **\\OC\\Files\\Utils\\Scanner**: * **scanFile** (string $absolutePath) * **scanFolder** (string $absolutePath) * **postScanFile** (string $absolutePath) * **postScanFolder** (string $absolutePath) Public emitter[](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#public-emitter "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------- Deprecated since version 18: Use the [OCP event dispatcher](https://docs.nextcloud.com/server/31/developer_manual/basics/events.html#ocp-event-dispatcher) instead. tbd ☁️ latest ☁️ Versions [latest](https://docs.nextcloud.com/server/latest/developer_manual) [stable](https://docs.nextcloud.com/server/stable/developer_manual) [30](https://docs.nextcloud.com/server/30/developer_manual) [29](https://docs.nextcloud.com/server/29/developer_manual) [28](https://docs.nextcloud.com/server/28/developer_manual) --- # Controllers — Nextcloud latest Developer Manual latest documentation * [](https://docs.nextcloud.com/server/stable/developer_manual/index.html) * [Basic concepts](https://docs.nextcloud.com/server/stable/developer_manual/basics/index.html) * Controllers * [Edit on GitHub](https://github.com/nextcloud/documentation/edit/master/developer_manual/basics/controllers.rst) * * * Controllers[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#controllers "Link to this heading") ===================================================================================================================================== Controllers are used to connect [routes](https://docs.nextcloud.com/server/stable/developer_manual/basics/routing.html) with app logic. Think of it as callbacks that are executed once a request has come in. Controllers are defined inside the **lib/Controller/** directory. To create a controller, simply extend the Controller class and create a method that should be executed on a request: $id = 3 // $doMore = false // $value = 3.5 } } The following types will be cast: * **bool** or **boolean** * **float** * **int** or **integer** ### JSON parameters[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#json-parameters "Link to this heading") It is possible to pass JSON using a POST, PUT or PATCH request. To do that the **Content-Type** header has to be set to **application/json**. The JSON is being parsed as an array and the first level keys will be used to pass in the arguments, e.g.: POST /index.php/apps/myapp/authors Content\-Type: application/json { "name": "test", "number": 3, "publisher": true, "customFields": { "mail": "test@example.com", "address": "Somewhere" } } "test@example.com", "address" => "Somewhere") } } ### Reading headers, files, cookies and environment variables[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#reading-headers-files-cookies-and-environment-variables "Link to this heading") Headers, files, cookies and environment variables can be accessed directly from the request object: request\->getHeader('Content-Type'); // $\_SERVER\['HTTP\_CONTENT\_TYPE'\] $cookie \= $this\->request\->getCookie('myCookie'); // $\_COOKIES\['myCookie'\] $file \= $this\->request\->getUploadedFile('myfile'); // $\_FILES\['myfile'\] $env \= $this\->request\->getEnv('SOME\_VAR'); // $\_ENV\['SOME\_VAR'\] } } Why should those values be accessed from the request object and not from the global array like $\_FILES? Simple: [because it’s bad practice](http://c2.com/cgi/wiki?GlobalVariablesAreBad) and will make testing harder. ### Reading and writing session variables[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#reading-and-writing-session-variables "Link to this heading") To set, get or modify session variables, the ISession object has to be injected into the controller. Nextcloud will read existing session data at the beginning of the request lifecycle and close the session afterwards. This means that in order to write to the session, the session has to be opened first. This is done implicitly when calling the set method, but would close immediately afterwards. To prevent this, the session has to be explicitly opened by calling the reopen method. Alternatively, you can use the `#[UseSession]` attribute to automatically open and close the session for you. use OCP\\AppFramework\\Controller; use OCP\\AppFramework\\Http\\Attribute\\UseSession; use OCP\\AppFramework\\Http\\Response; class PageController extends Controller { #\[UseSession\] public function writeASessionVariable(): Response { // ... } } Note The `#[UseSession]` was added in Nextcloud 26 and requires PHP 8.0 or later. If your app targets older releases and PHP 7.x then use the deprecated `@UseSession` annotation. /\*\* \* @UseSession \*/ public function writeASessionVariable(): Response { // .... } In case the session may be read and written by concurrent requests of your application, keeping the session open during your controller method execution may be required to ensure that the session is locked and no other request can write to the session at the same time. When reopening the session, the session data will also get updated with the latest changes from other requests. Using the annotation will keep the session lock for the whole duration of the controller method execution. For additional information on how session locking works in PHP see the article about [PHP Session Locking: How To Prevent Sessions Blocking in PHP requests](https://ma.ttias.be/php-session-locking-prevent-sessions-blocking-in-requests/) . Then session variables can be accessed like this: Note The session is closed automatically for writing, unless you add the `#[UseSession]` attribute! session \= $session; } #\[UseSession\] public function writeASessionVariable(): Response { // read a session variable $value \= $this\->session\['value'\]; // write a session variable $this\->session\['value'\] \= 'new value'; } } ### Setting cookies[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#setting-cookies "Link to this heading") Cookies can be set or modified directly on the response class: addCookie('foo', 'bar'); $response\->addCookie('bar', 'foo', new DateTime('2015-01-01 00:00')); return $response; } /\*\* \* Invalidates the cookie "foo" \* Invalidates the cookie "bar" and "bazinga" \*/ public function invalidateCookie(): TemplateResponse { $response \= new TemplateResponse(...); $response\->invalidateCookie('foo'); $response\->invalidateCookies(array('bar', 'bazinga')); return $response; } } Responses[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#responses "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------- Similar to how every controller receives a request object, every controller method has to return a Response. This can be in the form of a Response subclass or in the form of a value that can be handled by a registered responder. There are different kinds of responses available, like HTML-based responses, data responses, or other. The app decides of which kind the response is, by returning an appropriate `Response` object in the corresponding controller method. The following sections give an overview over the various kinds and how to implement them. HTML-based Responses[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#html-based-responses "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------- HTML pages are typically served using template responses. This is typically used as a starting point to load the website. This code linked by the template is by default encapsulated by the server to provide some common styling (e.g. the header row). The code then uses JavaScript to load further components (see [Frontend building in Vue](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/js.html#applicationjs) ) and the actual data. This section only focuses on the actual HTML content, not the data to fill into the dynamic pages. ### Templates[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#templates "Link to this heading") A [template](https://docs.nextcloud.com/server/stable/developer_manual/basics/front-end/templates.html) can be rendered by returning a TemplateResponse. A TemplateResponse takes the following parameters: * **appName**: tells the template engine in which app the template should be located * **templateName**: the name of the template inside the templates/ folder without the .php extension * **parameters**: optional array parameters that are available in the template through $\_, e.g.: array('key' \=> 'something') can be accessed through: $\_\['key'\] * **renderAs**: defaults to _user_, tells Nextcloud if it should include it in the web interface, or in case _blank_ is passed solely render the template 'hi'); return new TemplateResponse($this\->appName, $templateName, $parameters); } } ### Public page templates[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#public-page-templates "Link to this heading") For public pages, that are rendered to users who are not logged in to the Nextcloud instance, a `OCP\\AppFramework\\Http\\Template\\PublicTemplateResponse` should be used, to load the correct base template. It also allows adding an optional set of actions that will be shown in the top right corner of the public page. appName, 'main', \[\]); $template\->setHeaderTitle('Public page'); $template\->setHeaderDetails('some details'); $template\->setHeaderActions(\[\ new SimpleMenuAction('download', 'Label 1', 'icon-css-class1', 'link-url', 0),\ new SimpleMenuAction('share', 'Label 2', 'icon-css-class2', 'link-url', 10),\ \]); return $template; } } The header title and subtitle will be rendered in the header, next to the logo. The action with the highest priority (lowest number) will be used as the primary action, others will shown in the popover menu on demand. A `OCP\\AppFramework\\Http\\Template\\SimpleMenuAction` will be a link with an icon added to the menu. App developers can implement their own types of menu renderings by adding a custom class implementing the `OCP\\AppFramework\\Http\\Template\\IMenuAction` interface. Data-based responses[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#data-based-responses "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------- In contrast to the HTML template responses, the data responses return some user-data in packed form. There are different encodings thinkable like JSON, XML, or other formats. The main point is that the data is requested by the browser using JavaScript on behalf of the shown website. The user only indirectly requested the data by user interaction with the frontend. ### OCS[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#ocs "Link to this heading") Note This is purely for compatibility reasons. If you are planning to offer an external API, go for a [REST APIs](https://docs.nextcloud.com/server/stable/developer_manual/digging_deeper/rest_apis.html#rest-apis) instead. In order to simplify exchange of data between the Nextcloud backend and any client (be it the web frontend or whatever else), the OCS API has been introduced. To use OCS in your API you can use the **OCP\\AppFramework\\OCSController** base class and return your data in the form of a **DataResponse** in the following way: \[\ \[\ 'name' \=> 'Share#getShares',\ 'url' \=> '/api/v1/shares',\ 'verb' \=> 'GET',\ \],\ \],\ \]; Now your method will be reachable via `/ocs/v2.php/apps//api/v1/shares` Added in version 29: You can use the attribute `ApiRoute` as described in [Routing](https://docs.nextcloud.com/server/stable/developer_manual/basics/routing.html) instead of the entry in `appinfo/routes.php` as an alternative. ### JSON[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#json "Link to this heading") Returning JSON is simple, just pass an array to a JSONResponse: 'hi'); return new JSONResponse($params); } } Because returning JSON is such a common task, there’s even a shorter way to do this: 'hi'); } } Why does this work? Because the dispatcher sees that the controller did not return a subclass of a Response and asks the controller to turn the value into a Response. That’s where responders come in. ### Handling errors[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#handling-errors "Link to this heading") Sometimes a request should fail, for instance if an author with id 1 is requested but does not exist. In that case use an appropriate [HTTP error code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_Client_Error) to signal the client that an error occurred. Each response subclass has access to the **setStatus** method which lets you set an HTTP status code. To return a JSONResponse signaling that the author with id 1 has not been found, use the following code: registerResponder('xml', function($value) { if ($value instanceof DataResponse) { return new XMLResponse( $value\->getData(), $value\->getStatus(), $value\->getHeaders() ); } else { return new XMLResponse($value); } }); return array('test' \=> 'hi'); } } Note The above example would only return XML if the **format** parameter was _xml_. If you want to return an XMLResponse regardless of the format parameter, extend the Response class and return a new instance of it from the controller method instead. Because returning values works fine in case of a success but not in case of failure that requires a custom HTTP error code, you can always wrap the value in a **DataResponse**. This works for both normal responses and error responses. 'not found!'), Http::STATUS\_NOT\_FOUND); } } } Miscellaneous responses[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#miscellaneous-responses "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Some special responses are available as well. These are discussed here. ### Redirects[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#redirects "Link to this heading") A redirect can be achieved by returning a RedirectResponse: addHeader('Content-Type', 'application/xml'); $this\->xml \= $xml; } public function render(): string { $root \= new SimpleXMLElement(''); array\_walk\_recursive($this\->xml, array ($root, 'addChild')); return $xml\->asXML(); } } ### Streamed and lazily rendered responses[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#streamed-and-lazily-rendered-responses "Link to this heading") By default all responses are rendered at once and sent as a string through middleware. In certain cases this is not a desirable behavior, for instance if you want to stream a file in order to save memory. To do that use the now available **OCP\\AppFramework\\Http\\StreamResponse** class: index()` method should not check the CSRF token because it has not yet been sent to the client and because of that can’t work. To turn off checks the following _Attributes_ can be added before the controller: * `#[NoAdminRequired]`: Also users that are not admins can access the page * `#[PublicPage]`: Everyone can access the page without having to log in * `#[NoTwoFactorRequired]`: A user can access the page before the two-factor challenge has been passed (use this wisely and only in two-factor auth apps, e.g. to allow setup during login) * `#[NoCSRFRequired]`: Don’t check the CSRF token (use this wisely since you might create a security hole; to understand what it does see [CSRF in the security section](https://docs.nextcloud.com/server/stable/developer_manual/prologue/security.html#cross-site-request-forgery) ) Note The attributes are only available in Nextcloud 27 or later. In older versions annotations with the same names exist: * `@NoAdminRequired` instead of `#[NoAdminRequired]` * `` @PublicPage` `` instead of `#[PublicPage]` * `` @NoTwoFactorRequired` `` instead of `#[NoTwoFactorRequired]` * `` @NoCSRFRequired` `` instead of `#[NoCSRFRequired]` In the following some examples of configurations are given. #### Showing an HTML page by the user[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#showing-an-html-page-by-the-user "Link to this heading") A typical app needs an `index.html` page to show all content within. This page should be visible by all users in the instance. Therefore, you need to loosen the restriction from admins only (`#[NoAdminRequired]`). Additionally, as the user might not have a CSRF checker cookie set yet, the CSRF checks should be disabled (which is fine as this is a template response). appName, 'main'); } } If the page should only be visible to the admin, you can keep the restrictive default by omitting the attribute `#[NoAdminRequired]`. #### Getting data from the backend using AJAX requests[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#getting-data-from-the-backend-using-ajax-requests "Link to this heading") Data for the frontend needs to be made available from the backend. Here, OCS is the suggested way to go. Here is the example from [OCS controllers](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#ocscontroller) : auth->isSuccessful here is just an // example. if (!$this\->auth\->isSuccessful()) { $templateResponse\->throttle(); } return $templateResponse; } } A controller can also have multiple factors to brute force against. In this case you can specify multiple attributes and then in the throttle you specify the action which was violated. This is especially useful when a secret, in the sample below token, could be guessed on multiple endpoints e.g. a share token on the API level, preview endpoint, frontend controller, etc. while another secret (password), is specific to this one controller method. shareManager\->getByToken($token)) { $templateResponse\->throttle(\['action' \=> 'token'\]); } // … if (!$share\->verifyPassword($password)) { $templateResponse\->throttle(\['action' \=> 'password'\]); } return $templateResponse; } } ### Modifying the content security policy[](https://docs.nextcloud.com/server/stable/developer_manual/basics/controllers.html#modifying-the-content-security-policy "Link to this heading") By default Nextcloud disables all resources which are not served on the same domain, forbids cross domain requests and disables inline CSS and JavaScript by setting a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Introducing_Content_Security_Policy) . However if an app relies on third-party media or other features which are forbidden by the current policy the policy can be relaxed. Note Double check your content and edge cases before you relax the policy! Also read the [documentation provided by MDN](https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Introducing_Content_Security_Policy) To relax the policy pass an instance of the ContentSecurityPolicy class to your response. The methods on the class can be chained. The following methods turn off security features by passing in **true** as the **$isAllowed** parameter * **allowInlineScript** (bool $isAllowed) * **allowInlineStyle** (bool $isAllowed) * **allowEvalScript** (bool $isAllowed) * **useStrictDynamic** (bool $isAllowed) Trust all scripts that are loaded by a trusted script, see ‘script-src’ and ‘strict-dynamic’ * **useStrictDynamicOnScripts** (bool $isAllowed) Trust all scripts that are loaded by a trusted script which was loaded using a `