aboutsummaryrefslogtreecommitdiffstats
path: root/apps/testing
diff options
context:
space:
mode:
Diffstat (limited to 'apps/testing')
-rw-r--r--apps/testing/.noopenapi0
-rw-r--r--apps/testing/appinfo/info.xml9
-rw-r--r--apps/testing/appinfo/routes.php25
-rw-r--r--apps/testing/clean_opcode_cache.php22
-rw-r--r--apps/testing/composer/composer/ClassLoader.php108
-rw-r--r--apps/testing/composer/composer/InstalledVersions.php17
-rw-r--r--apps/testing/composer/composer/autoload_classmap.php17
-rw-r--r--apps/testing/composer/composer/autoload_static.php17
-rw-r--r--apps/testing/composer/composer/installed.php4
-rw-r--r--apps/testing/img/app.svg2
-rw-r--r--apps/testing/img/logo.pngbin0 -> 3571 bytes
-rw-r--r--apps/testing/lib/AlternativeHomeUserBackend.php29
-rw-r--r--apps/testing/lib/AppInfo/Application.php72
-rw-r--r--apps/testing/lib/Controller/ConfigController.php35
-rw-r--r--apps/testing/lib/Controller/LockingController.php62
-rw-r--r--apps/testing/lib/Controller/RateLimitTestController.php44
-rw-r--r--apps/testing/lib/Conversion/ConversionProvider.php47
-rw-r--r--apps/testing/lib/HiddenGroupBackend.php44
-rw-r--r--apps/testing/lib/Listener/GetDeclarativeSettingsValueListener.php37
-rw-r--r--apps/testing/lib/Listener/RegisterDeclarativeSettingsListener.php71
-rw-r--r--apps/testing/lib/Listener/SetDeclarativeSettingsValueListener.php37
-rw-r--r--apps/testing/lib/Locking/FakeDBLockingProvider.php29
-rw-r--r--apps/testing/lib/Migration/Version30000Date20240102030405.php41
-rw-r--r--apps/testing/lib/Provider/FakeText2ImageProvider.php33
-rw-r--r--apps/testing/lib/Provider/FakeTextProcessingProvider.php39
-rw-r--r--apps/testing/lib/Provider/FakeTextProcessingProviderSync.php45
-rw-r--r--apps/testing/lib/Provider/FakeTranslationProvider.php29
-rw-r--r--apps/testing/lib/Settings/DeclarativeSettingsForm.php205
-rw-r--r--apps/testing/lib/TaskProcessing/FakeContextWriteProvider.php130
-rw-r--r--apps/testing/lib/TaskProcessing/FakeTextToImageProvider.php108
-rw-r--r--apps/testing/lib/TaskProcessing/FakeTextToTextProvider.php122
-rw-r--r--apps/testing/lib/TaskProcessing/FakeTextToTextSummaryProvider.php122
-rw-r--r--apps/testing/lib/TaskProcessing/FakeTranscribeProvider.php88
-rw-r--r--apps/testing/lib/TaskProcessing/FakeTranslateProvider.php154
34 files changed, 1569 insertions, 275 deletions
diff --git a/apps/testing/.noopenapi b/apps/testing/.noopenapi
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/apps/testing/.noopenapi
diff --git a/apps/testing/appinfo/info.xml b/apps/testing/appinfo/info.xml
index 2fd528b9015..66614f35c8c 100644
--- a/apps/testing/appinfo/info.xml
+++ b/apps/testing/appinfo/info.xml
@@ -1,11 +1,16 @@
<?xml version="1.0"?>
+<!--
+ - SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-FileCopyrightText: 2015 owncloud, Inc.
+ - SPDX-License-Identifier: AGPL-3.0-only
+-->
<info xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
<id>testing</id>
<name>QA testing</name>
<summary>This app is only for testing! It is dangerous to have it enabled in a live instance</summary>
<description>This app is only for testing! It is dangerous to have it enabled in a live instance</description>
- <version>1.16.0</version>
+ <version>1.22.0</version>
<licence>agpl</licence>
<author>Joas Schilling</author>
<types>
@@ -14,6 +19,6 @@
<category>monitoring</category>
<bugs>https://github.com/nextcloud/server/issues</bugs>
<dependencies>
- <nextcloud min-version="26" max-version="26"/>
+ <nextcloud min-version="32" max-version="32"/>
</dependencies>
</info>
diff --git a/apps/testing/appinfo/routes.php b/apps/testing/appinfo/routes.php
index 1ab36a4e826..862f63ef4c2 100644
--- a/apps/testing/appinfo/routes.php
+++ b/apps/testing/appinfo/routes.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2015-2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
return [
'routes' => [
diff --git a/apps/testing/clean_opcode_cache.php b/apps/testing/clean_opcode_cache.php
index c43340d1b2c..acfeece7e15 100644
--- a/apps/testing/clean_opcode_cache.php
+++ b/apps/testing/clean_opcode_cache.php
@@ -1,23 +1,7 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
opcache_reset();
diff --git a/apps/testing/composer/composer/ClassLoader.php b/apps/testing/composer/composer/ClassLoader.php
index fd56bd7d840..7824d8f7eaf 100644
--- a/apps/testing/composer/composer/ClassLoader.php
+++ b/apps/testing/composer/composer/ClassLoader.php
@@ -45,35 +45,34 @@ class ClassLoader
/** @var \Closure(string):void */
private static $includeFile;
- /** @var ?string */
+ /** @var string|null */
private $vendorDir;
// PSR-4
/**
- * @var array[]
- * @psalm-var array<string, array<string, int>>
+ * @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
- * @var array[]
- * @psalm-var array<string, array<int, string>>
+ * @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array();
/**
- * @var array[]
- * @psalm-var array<string, string>
+ * @var list<string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
- * @var array[]
- * @psalm-var array<string, array<string, string[]>>
+ * List of PSR-0 prefixes
+ *
+ * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
+ *
+ * @var array<string, array<string, list<string>>>
*/
private $prefixesPsr0 = array();
/**
- * @var array[]
- * @psalm-var array<string, string>
+ * @var list<string>
*/
private $fallbackDirsPsr0 = array();
@@ -81,8 +80,7 @@ class ClassLoader
private $useIncludePath = false;
/**
- * @var string[]
- * @psalm-var array<string, string>
+ * @var array<string, string>
*/
private $classMap = array();
@@ -90,21 +88,20 @@ class ClassLoader
private $classMapAuthoritative = false;
/**
- * @var bool[]
- * @psalm-var array<string, bool>
+ * @var array<string, bool>
*/
private $missingClasses = array();
- /** @var ?string */
+ /** @var string|null */
private $apcuPrefix;
/**
- * @var self[]
+ * @var array<string, self>
*/
private static $registeredLoaders = array();
/**
- * @param ?string $vendorDir
+ * @param string|null $vendorDir
*/
public function __construct($vendorDir = null)
{
@@ -113,7 +110,7 @@ class ClassLoader
}
/**
- * @return string[]
+ * @return array<string, list<string>>
*/
public function getPrefixes()
{
@@ -125,8 +122,7 @@ class ClassLoader
}
/**
- * @return array[]
- * @psalm-return array<string, array<int, string>>
+ * @return array<string, list<string>>
*/
public function getPrefixesPsr4()
{
@@ -134,8 +130,7 @@ class ClassLoader
}
/**
- * @return array[]
- * @psalm-return array<string, string>
+ * @return list<string>
*/
public function getFallbackDirs()
{
@@ -143,8 +138,7 @@ class ClassLoader
}
/**
- * @return array[]
- * @psalm-return array<string, string>
+ * @return list<string>
*/
public function getFallbackDirsPsr4()
{
@@ -152,8 +146,7 @@ class ClassLoader
}
/**
- * @return string[] Array of classname => path
- * @psalm-return array<string, string>
+ * @return array<string, string> Array of classname => path
*/
public function getClassMap()
{
@@ -161,8 +154,7 @@ class ClassLoader
}
/**
- * @param string[] $classMap Class to filename map
- * @psalm-param array<string, string> $classMap
+ * @param array<string, string> $classMap Class to filename map
*
* @return void
*/
@@ -179,24 +171,25 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
- * @param string $prefix The prefix
- * @param string[]|string $paths The PSR-0 root directories
- * @param bool $prepend Whether to prepend the directories
+ * @param string $prefix The prefix
+ * @param list<string>|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
+ $paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
- (array) $paths,
+ $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
- (array) $paths
+ $paths
);
}
@@ -205,19 +198,19 @@ class ClassLoader
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
- $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+ $this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
- (array) $paths,
+ $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
- (array) $paths
+ $paths
);
}
}
@@ -226,9 +219,9 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
- * @param string $prefix The prefix/namespace, with trailing '\\'
- * @param string[]|string $paths The PSR-4 base directories
- * @param bool $prepend Whether to prepend the directories
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param list<string>|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
@@ -236,17 +229,18 @@ class ClassLoader
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
+ $paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
- (array) $paths,
+ $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
- (array) $paths
+ $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
@@ -256,18 +250,18 @@ class ClassLoader
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
- $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ $this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
- (array) $paths,
+ $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
- (array) $paths
+ $paths
);
}
}
@@ -276,8 +270,8 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
- * @param string $prefix The prefix
- * @param string[]|string $paths The PSR-0 base directories
+ * @param string $prefix The prefix
+ * @param list<string>|string $paths The PSR-0 base directories
*
* @return void
*/
@@ -294,8 +288,8 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
- * @param string $prefix The prefix/namespace, with trailing '\\'
- * @param string[]|string $paths The PSR-4 base directories
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param list<string>|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
@@ -429,7 +423,8 @@ class ClassLoader
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
- (self::$includeFile)($file);
+ $includeFile = self::$includeFile;
+ $includeFile($file);
return true;
}
@@ -480,9 +475,9 @@ class ClassLoader
}
/**
- * Returns the currently registered loaders indexed by their corresponding vendor directories.
+ * Returns the currently registered loaders keyed by their corresponding vendor directories.
*
- * @return self[]
+ * @return array<string, self>
*/
public static function getRegisteredLoaders()
{
@@ -560,7 +555,10 @@ class ClassLoader
return false;
}
- private static function initializeIncludeClosure(): void
+ /**
+ * @return void
+ */
+ private static function initializeIncludeClosure()
{
if (self::$includeFile !== null) {
return;
@@ -574,8 +572,8 @@ class ClassLoader
* @param string $file
* @return void
*/
- self::$includeFile = static function($file) {
+ self::$includeFile = \Closure::bind(static function($file) {
include $file;
- };
+ }, null, null);
}
}
diff --git a/apps/testing/composer/composer/InstalledVersions.php b/apps/testing/composer/composer/InstalledVersions.php
index c6b54af7ba2..51e734a774b 100644
--- a/apps/testing/composer/composer/InstalledVersions.php
+++ b/apps/testing/composer/composer/InstalledVersions.php
@@ -98,7 +98,7 @@ class InstalledVersions
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
- return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
+ return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
}
}
@@ -119,7 +119,7 @@ class InstalledVersions
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
- $constraint = $parser->parseConstraints($constraint);
+ $constraint = $parser->parseConstraints((string) $constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
@@ -328,7 +328,9 @@ class InstalledVersions
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
- $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
+ /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
+ $required = require $vendorDir.'/composer/installed.php';
+ $installed[] = self::$installedByVendor[$vendorDir] = $required;
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
@@ -340,12 +342,17 @@ class InstalledVersions
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
- self::$installed = require __DIR__ . '/installed.php';
+ /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
+ $required = require __DIR__ . '/installed.php';
+ self::$installed = $required;
} else {
self::$installed = array();
}
}
- $installed[] = self::$installed;
+
+ if (self::$installed !== array()) {
+ $installed[] = self::$installed;
+ }
return $installed;
}
diff --git a/apps/testing/composer/composer/autoload_classmap.php b/apps/testing/composer/composer/autoload_classmap.php
index c4688abedf4..9be96aaf617 100644
--- a/apps/testing/composer/composer/autoload_classmap.php
+++ b/apps/testing/composer/composer/autoload_classmap.php
@@ -12,5 +12,22 @@ return array(
'OCA\\Testing\\Controller\\ConfigController' => $baseDir . '/../lib/Controller/ConfigController.php',
'OCA\\Testing\\Controller\\LockingController' => $baseDir . '/../lib/Controller/LockingController.php',
'OCA\\Testing\\Controller\\RateLimitTestController' => $baseDir . '/../lib/Controller/RateLimitTestController.php',
+ 'OCA\\Testing\\Conversion\\ConversionProvider' => $baseDir . '/../lib/Conversion/ConversionProvider.php',
+ 'OCA\\Testing\\HiddenGroupBackend' => $baseDir . '/../lib/HiddenGroupBackend.php',
+ 'OCA\\Testing\\Listener\\GetDeclarativeSettingsValueListener' => $baseDir . '/../lib/Listener/GetDeclarativeSettingsValueListener.php',
+ 'OCA\\Testing\\Listener\\RegisterDeclarativeSettingsListener' => $baseDir . '/../lib/Listener/RegisterDeclarativeSettingsListener.php',
+ 'OCA\\Testing\\Listener\\SetDeclarativeSettingsValueListener' => $baseDir . '/../lib/Listener/SetDeclarativeSettingsValueListener.php',
'OCA\\Testing\\Locking\\FakeDBLockingProvider' => $baseDir . '/../lib/Locking/FakeDBLockingProvider.php',
+ 'OCA\\Testing\\Migration\\Version30000Date20240102030405' => $baseDir . '/../lib/Migration/Version30000Date20240102030405.php',
+ 'OCA\\Testing\\Provider\\FakeText2ImageProvider' => $baseDir . '/../lib/Provider/FakeText2ImageProvider.php',
+ 'OCA\\Testing\\Provider\\FakeTextProcessingProvider' => $baseDir . '/../lib/Provider/FakeTextProcessingProvider.php',
+ 'OCA\\Testing\\Provider\\FakeTextProcessingProviderSync' => $baseDir . '/../lib/Provider/FakeTextProcessingProviderSync.php',
+ 'OCA\\Testing\\Provider\\FakeTranslationProvider' => $baseDir . '/../lib/Provider/FakeTranslationProvider.php',
+ 'OCA\\Testing\\Settings\\DeclarativeSettingsForm' => $baseDir . '/../lib/Settings/DeclarativeSettingsForm.php',
+ 'OCA\\Testing\\TaskProcessing\\FakeContextWriteProvider' => $baseDir . '/../lib/TaskProcessing/FakeContextWriteProvider.php',
+ 'OCA\\Testing\\TaskProcessing\\FakeTextToImageProvider' => $baseDir . '/../lib/TaskProcessing/FakeTextToImageProvider.php',
+ 'OCA\\Testing\\TaskProcessing\\FakeTextToTextProvider' => $baseDir . '/../lib/TaskProcessing/FakeTextToTextProvider.php',
+ 'OCA\\Testing\\TaskProcessing\\FakeTextToTextSummaryProvider' => $baseDir . '/../lib/TaskProcessing/FakeTextToTextSummaryProvider.php',
+ 'OCA\\Testing\\TaskProcessing\\FakeTranscribeProvider' => $baseDir . '/../lib/TaskProcessing/FakeTranscribeProvider.php',
+ 'OCA\\Testing\\TaskProcessing\\FakeTranslateProvider' => $baseDir . '/../lib/TaskProcessing/FakeTranslateProvider.php',
);
diff --git a/apps/testing/composer/composer/autoload_static.php b/apps/testing/composer/composer/autoload_static.php
index 15b46171838..bd557c37f6b 100644
--- a/apps/testing/composer/composer/autoload_static.php
+++ b/apps/testing/composer/composer/autoload_static.php
@@ -27,7 +27,24 @@ class ComposerStaticInitTesting
'OCA\\Testing\\Controller\\ConfigController' => __DIR__ . '/..' . '/../lib/Controller/ConfigController.php',
'OCA\\Testing\\Controller\\LockingController' => __DIR__ . '/..' . '/../lib/Controller/LockingController.php',
'OCA\\Testing\\Controller\\RateLimitTestController' => __DIR__ . '/..' . '/../lib/Controller/RateLimitTestController.php',
+ 'OCA\\Testing\\Conversion\\ConversionProvider' => __DIR__ . '/..' . '/../lib/Conversion/ConversionProvider.php',
+ 'OCA\\Testing\\HiddenGroupBackend' => __DIR__ . '/..' . '/../lib/HiddenGroupBackend.php',
+ 'OCA\\Testing\\Listener\\GetDeclarativeSettingsValueListener' => __DIR__ . '/..' . '/../lib/Listener/GetDeclarativeSettingsValueListener.php',
+ 'OCA\\Testing\\Listener\\RegisterDeclarativeSettingsListener' => __DIR__ . '/..' . '/../lib/Listener/RegisterDeclarativeSettingsListener.php',
+ 'OCA\\Testing\\Listener\\SetDeclarativeSettingsValueListener' => __DIR__ . '/..' . '/../lib/Listener/SetDeclarativeSettingsValueListener.php',
'OCA\\Testing\\Locking\\FakeDBLockingProvider' => __DIR__ . '/..' . '/../lib/Locking/FakeDBLockingProvider.php',
+ 'OCA\\Testing\\Migration\\Version30000Date20240102030405' => __DIR__ . '/..' . '/../lib/Migration/Version30000Date20240102030405.php',
+ 'OCA\\Testing\\Provider\\FakeText2ImageProvider' => __DIR__ . '/..' . '/../lib/Provider/FakeText2ImageProvider.php',
+ 'OCA\\Testing\\Provider\\FakeTextProcessingProvider' => __DIR__ . '/..' . '/../lib/Provider/FakeTextProcessingProvider.php',
+ 'OCA\\Testing\\Provider\\FakeTextProcessingProviderSync' => __DIR__ . '/..' . '/../lib/Provider/FakeTextProcessingProviderSync.php',
+ 'OCA\\Testing\\Provider\\FakeTranslationProvider' => __DIR__ . '/..' . '/../lib/Provider/FakeTranslationProvider.php',
+ 'OCA\\Testing\\Settings\\DeclarativeSettingsForm' => __DIR__ . '/..' . '/../lib/Settings/DeclarativeSettingsForm.php',
+ 'OCA\\Testing\\TaskProcessing\\FakeContextWriteProvider' => __DIR__ . '/..' . '/../lib/TaskProcessing/FakeContextWriteProvider.php',
+ 'OCA\\Testing\\TaskProcessing\\FakeTextToImageProvider' => __DIR__ . '/..' . '/../lib/TaskProcessing/FakeTextToImageProvider.php',
+ 'OCA\\Testing\\TaskProcessing\\FakeTextToTextProvider' => __DIR__ . '/..' . '/../lib/TaskProcessing/FakeTextToTextProvider.php',
+ 'OCA\\Testing\\TaskProcessing\\FakeTextToTextSummaryProvider' => __DIR__ . '/..' . '/../lib/TaskProcessing/FakeTextToTextSummaryProvider.php',
+ 'OCA\\Testing\\TaskProcessing\\FakeTranscribeProvider' => __DIR__ . '/..' . '/../lib/TaskProcessing/FakeTranscribeProvider.php',
+ 'OCA\\Testing\\TaskProcessing\\FakeTranslateProvider' => __DIR__ . '/..' . '/../lib/TaskProcessing/FakeTranslateProvider.php',
);
public static function getInitializer(ClassLoader $loader)
diff --git a/apps/testing/composer/composer/installed.php b/apps/testing/composer/composer/installed.php
index a1f6a8636b4..d2b87e1bdfd 100644
--- a/apps/testing/composer/composer/installed.php
+++ b/apps/testing/composer/composer/installed.php
@@ -3,7 +3,7 @@
'name' => '__root__',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
- 'reference' => 'd51429a47232bbf46a2be832ecfa711f102da802',
+ 'reference' => '4ff660ca2e0baa02440ba07296ed7e75fa544c0e',
'type' => 'library',
'install_path' => __DIR__ . '/../',
'aliases' => array(),
@@ -13,7 +13,7 @@
'__root__' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
- 'reference' => 'd51429a47232bbf46a2be832ecfa711f102da802',
+ 'reference' => '4ff660ca2e0baa02440ba07296ed7e75fa544c0e',
'type' => 'library',
'install_path' => __DIR__ . '/../',
'aliases' => array(),
diff --git a/apps/testing/img/app.svg b/apps/testing/img/app.svg
index 7ef7f086921..078e67202b6 100644
--- a/apps/testing/img/app.svg
+++ b/apps/testing/img/app.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" version="1" viewBox="0 0 32 32"><path d="M13.733 0a.915.915 0 0 0-.933.934V3.6c-1.182.304-2.243.794-3.267 1.4L7.6 3.068a.93.93 0 0 0-1.334 0l-3.2 3.2a.93.93 0 0 0 0 1.334L5 9.535c-.607 1.024-1.097 2.085-1.4 3.267H.933a.915.915 0 0 0-.933.934v4.533c0 .53.403.934.933.934H3.6c.303 1.182.793 2.243 1.4 3.267l-1.934 1.935a.93.93 0 0 0 0 1.333l3.2 3.2a.93.93 0 0 0 1.333 0L9.532 27c1.024.61 2.085 1.097 3.266 1.4v2.667c0 .53.402.933.932.933h4.534c.53 0 .933-.403.933-.935V28.4c1.18-.305 2.24-.795 3.265-1.4L24.4 28.93a.93.93 0 0 0 1.332 0l3.2-3.2a.93.93 0 0 0 0-1.333L27 22.465c.607-1.024 1.096-2.085 1.4-3.266h2.665a.915.915 0 0 0 .935-.933v-4.534a.915.915 0 0 0-.934-.933H28.4c-.304-1.182-.792-2.243-1.4-3.267L28.932 7.6a.93.93 0 0 0 0-1.334l-3.2-3.2a.93.93 0 0 0-1.333 0L22.465 5c-1.024-.607-2.084-1.097-3.266-1.4V.933A.915.915 0 0 0 18.267 0zM16 8.87A7.134 7.134 0 0 1 23.13 16 7.134 7.134 0 0 1 16 23.133c-3.936 0-7.13-3.196-7.13-7.132S12.063 8.87 16 8.87z" display="block" fill="#fff"/></svg> \ No newline at end of file
+<svg viewBox="0 0 32 32" height="32" width="32" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"><path d="m9.25 22-.4-3.2a3.697 3.697 0 0 1-.612-.3 8.336 8.336 0 0 1-.563-.375L4.7 19.375l-2.75-4.75 2.575-1.95a2.342 2.342 0 0 1-.025-.338v-.674c0-.109.008-.221.025-.338L1.95 9.375l2.75-4.75 2.975 1.25c.183-.133.375-.258.575-.375.2-.117.4-.217.6-.3l.4-3.2h5.5l.4 3.2c.217.083.421.183.613.3.191.117.379.242.562.375l2.975-1.25 2.75 4.75-2.575 1.95c.017.117.025.229.025.338v.674c0 .109-.017.221-.05.338l2.575 1.95-2.75 4.75-2.95-1.25a6.928 6.928 0 0 1-.575.375c-.2.117-.4.217-.6.3l-.4 3.2h-5.5Zm2.8-6.5c.967 0 1.792-.342 2.475-1.025A3.373 3.373 0 0 0 15.55 12c0-.967-.342-1.792-1.025-2.475A3.373 3.373 0 0 0 12.05 8.5c-.983 0-1.812.342-2.487 1.025A3.393 3.393 0 0 0 8.55 12c0 .967.338 1.792 1.013 2.475.675.683 1.504 1.025 2.487 1.025Z" style="fill:#fff;fill-rule:nonzero" transform="matrix(1.59204 0 0 1.6 -3.104 -3.2)"/></svg> \ No newline at end of file
diff --git a/apps/testing/img/logo.png b/apps/testing/img/logo.png
new file mode 100644
index 00000000000..df32e1c7eab
--- /dev/null
+++ b/apps/testing/img/logo.png
Binary files differ
diff --git a/apps/testing/lib/AlternativeHomeUserBackend.php b/apps/testing/lib/AlternativeHomeUserBackend.php
index b6d39cf6b99..0524ebe110d 100644
--- a/apps/testing/lib/AlternativeHomeUserBackend.php
+++ b/apps/testing/lib/AlternativeHomeUserBackend.php
@@ -1,26 +1,15 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud GmbH.
- *
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016 ownCloud GmbH.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Testing;
+use OC\User\Database;
+use OCP\IConfig;
+use OCP\Server;
+
/**
* Alternative home user backend.
*
@@ -33,7 +22,7 @@ namespace OCA\Testing;
* ],
* ]
*/
-class AlternativeHomeUserBackend extends \OC\User\Database {
+class AlternativeHomeUserBackend extends Database {
public function __construct() {
parent::__construct();
}
@@ -48,7 +37,7 @@ class AlternativeHomeUserBackend extends \OC\User\Database {
if ($uid !== 'admin') {
$uid = md5($uid);
}
- return \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $uid;
+ return Server::get(IConfig::class)->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $uid;
}
return false;
diff --git a/apps/testing/lib/AppInfo/Application.php b/apps/testing/lib/AppInfo/Application.php
index 4bf4b5cb470..2add318f327 100644
--- a/apps/testing/lib/AppInfo/Application.php
+++ b/apps/testing/lib/AppInfo/Application.php
@@ -1,52 +1,78 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud GmbH
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Testing\AppInfo;
use OCA\Testing\AlternativeHomeUserBackend;
+use OCA\Testing\Conversion\ConversionProvider;
+use OCA\Testing\HiddenGroupBackend;
+use OCA\Testing\Listener\GetDeclarativeSettingsValueListener;
+use OCA\Testing\Listener\RegisterDeclarativeSettingsListener;
+use OCA\Testing\Listener\SetDeclarativeSettingsValueListener;
+use OCA\Testing\Provider\FakeText2ImageProvider;
+use OCA\Testing\Provider\FakeTextProcessingProvider;
+use OCA\Testing\Provider\FakeTextProcessingProviderSync;
+use OCA\Testing\Provider\FakeTranslationProvider;
+use OCA\Testing\Settings\DeclarativeSettingsForm;
+use OCA\Testing\TaskProcessing\FakeContextWriteProvider;
+use OCA\Testing\TaskProcessing\FakeTextToImageProvider;
+use OCA\Testing\TaskProcessing\FakeTextToTextProvider;
+use OCA\Testing\TaskProcessing\FakeTextToTextSummaryProvider;
+use OCA\Testing\TaskProcessing\FakeTranscribeProvider;
+use OCA\Testing\TaskProcessing\FakeTranslateProvider;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
+use OCP\IGroupManager;
+use OCP\Settings\Events\DeclarativeSettingsGetValueEvent;
+use OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent;
+use OCP\Settings\Events\DeclarativeSettingsSetValueEvent;
class Application extends App implements IBootstrap {
+ public const APP_ID = 'testing';
+
public function __construct(array $urlParams = []) {
- parent::__construct('testing', $urlParams);
+ parent::__construct(self::APP_ID, $urlParams);
}
public function register(IRegistrationContext $context): void {
+ $context->registerTranslationProvider(FakeTranslationProvider::class);
+ $context->registerTextProcessingProvider(FakeTextProcessingProvider::class);
+ $context->registerTextProcessingProvider(FakeTextProcessingProviderSync::class);
+ $context->registerTextToImageProvider(FakeText2ImageProvider::class);
+
+ $context->registerTaskProcessingProvider(FakeTextToTextProvider::class);
+ $context->registerTaskProcessingProvider(FakeTextToTextSummaryProvider::class);
+ $context->registerTaskProcessingProvider(FakeTextToImageProvider::class);
+ $context->registerTaskProcessingProvider(FakeTranslateProvider::class);
+ $context->registerTaskProcessingProvider(FakeTranscribeProvider::class);
+ $context->registerTaskProcessingProvider(FakeContextWriteProvider::class);
+
+ $context->registerFileConversionProvider(ConversionProvider::class);
+
+ $context->registerDeclarativeSettings(DeclarativeSettingsForm::class);
+ $context->registerEventListener(DeclarativeSettingsRegisterFormEvent::class, RegisterDeclarativeSettingsListener::class);
+ $context->registerEventListener(DeclarativeSettingsGetValueEvent::class, GetDeclarativeSettingsValueListener::class);
+ $context->registerEventListener(DeclarativeSettingsSetValueEvent::class, SetDeclarativeSettingsValueListener::class);
}
public function boot(IBootContext $context): void {
$server = $context->getServerContainer();
$config = $server->getConfig();
- if ($config->getAppValue('testing', 'enable_alt_user_backend', 'no') === 'yes') {
+ if ($config->getAppValue(self::APP_ID, 'enable_alt_user_backend', 'no') === 'yes') {
$userManager = $server->getUserManager();
// replace all user backends with this one
$userManager->clearBackends();
$userManager->registerBackend($context->getAppContainer()->get(AlternativeHomeUserBackend::class));
}
+
+ $groupManager = $server->get(IGroupManager::class);
+ $groupManager->addBackend($server->get(HiddenGroupBackend::class));
}
}
diff --git a/apps/testing/lib/Controller/ConfigController.php b/apps/testing/lib/Controller/ConfigController.php
index 76f1e1a1ee1..1b38666e51c 100644
--- a/apps/testing/lib/Controller/ConfigController.php
+++ b/apps/testing/lib/Controller/ConfigController.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Testing\Controller;
@@ -29,19 +14,17 @@ use OCP\IRequest;
class ConfigController extends OCSController {
- /** @var IConfig */
- private $config;
-
/**
* @param string $appName
* @param IRequest $request
* @param IConfig $config
*/
- public function __construct($appName,
- IRequest $request,
- IConfig $config) {
+ public function __construct(
+ $appName,
+ IRequest $request,
+ private IConfig $config,
+ ) {
parent::__construct($appName, $request);
- $this->config = $config;
}
/**
diff --git a/apps/testing/lib/Controller/LockingController.php b/apps/testing/lib/Controller/LockingController.php
index c01ad218c84..edc66d012ee 100644
--- a/apps/testing/lib/Controller/LockingController.php
+++ b/apps/testing/lib/Controller/LockingController.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Testing\Controller;
@@ -39,21 +24,6 @@ use OCP\Lock\LockedException;
class LockingController extends OCSController {
- /** @var ILockingProvider */
- protected $lockingProvider;
-
- /** @var FakeDBLockingProvider */
- protected $fakeDBLockingProvider;
-
- /** @var IDBConnection */
- protected $connection;
-
- /** @var IConfig */
- protected $config;
-
- /** @var IRootFolder */
- protected $rootFolder;
-
/**
* @param string $appName
* @param IRequest $request
@@ -63,20 +33,16 @@ class LockingController extends OCSController {
* @param IConfig $config
* @param IRootFolder $rootFolder
*/
- public function __construct($appName,
- IRequest $request,
- ILockingProvider $lockingProvider,
- FakeDBLockingProvider $fakeDBLockingProvider,
- IDBConnection $connection,
- IConfig $config,
- IRootFolder $rootFolder) {
+ public function __construct(
+ $appName,
+ IRequest $request,
+ protected ILockingProvider $lockingProvider,
+ protected FakeDBLockingProvider $fakeDBLockingProvider,
+ protected IDBConnection $connection,
+ protected IConfig $config,
+ protected IRootFolder $rootFolder,
+ ) {
parent::__construct($appName, $request);
-
- $this->lockingProvider = $lockingProvider;
- $this->fakeDBLockingProvider = $fakeDBLockingProvider;
- $this->connection = $connection;
- $this->config = $config;
- $this->rootFolder = $rootFolder;
}
/**
@@ -199,7 +165,7 @@ class LockingController extends OCSController {
throw new OCSException('', Http::STATUS_LOCKED);
}
- public function releaseAll(int $type = null): DataResponse {
+ public function releaseAll(?int $type = null): DataResponse {
$lockingProvider = $this->getLockingProvider();
foreach ($this->config->getAppKeys('testing') as $lock) {
diff --git a/apps/testing/lib/Controller/RateLimitTestController.php b/apps/testing/lib/Controller/RateLimitTestController.php
index d9a8fde5c0d..d3700b69858 100644
--- a/apps/testing/lib/Controller/RateLimitTestController.php
+++ b/apps/testing/lib/Controller/RateLimitTestController.php
@@ -1,52 +1,36 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch>
- *
- * @author Lukas Reschke <lukas@statuscode.ch>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Testing\Controller;
use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\Attribute\AnonRateLimit;
+use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
+use OCP\AppFramework\Http\Attribute\PublicPage;
+use OCP\AppFramework\Http\Attribute\UserRateLimit;
use OCP\AppFramework\Http\JSONResponse;
class RateLimitTestController extends Controller {
/**
- * @PublicPage
- * @NoCSRFRequired
- *
- * @UserRateThrottle(limit=5, period=100)
- * @AnonRateThrottle(limit=1, period=100)
- *
* @return JSONResponse
*/
+ #[PublicPage]
+ #[NoCSRFRequired]
+ #[UserRateLimit(limit: 5, period: 100)]
+ #[AnonRateLimit(limit: 1, period: 100)]
public function userAndAnonProtected() {
return new JSONResponse();
}
/**
- * @PublicPage
- * @NoCSRFRequired
- *
- * @AnonRateThrottle(limit=1, period=10)
- *
* @return JSONResponse
*/
+ #[PublicPage]
+ #[NoCSRFRequired]
+ #[AnonRateLimit(limit: 1, period: 10)]
public function onlyAnonProtected() {
return new JSONResponse();
}
diff --git a/apps/testing/lib/Conversion/ConversionProvider.php b/apps/testing/lib/Conversion/ConversionProvider.php
new file mode 100644
index 00000000000..b8d93428694
--- /dev/null
+++ b/apps/testing/lib/Conversion/ConversionProvider.php
@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Testing\Conversion;
+
+use OCP\Files\Conversion\ConversionMimeProvider;
+use OCP\Files\Conversion\IConversionProvider;
+use OCP\Files\File;
+use OCP\IL10N;
+
+class ConversionProvider implements IConversionProvider {
+ public function __construct(
+ private IL10N $l10n,
+ ) {
+ }
+
+ public function getSupportedMimeTypes(): array {
+ return [
+ new ConversionMimeProvider('image/jpeg', 'image/png', 'png', $this->l10n->t('Image (.png)')),
+ new ConversionMimeProvider('image/jpeg', 'image/gif', 'gif', $this->l10n->t('Image (.gif)')),
+ ];
+ }
+
+ public function convertFile(File $file, string $targetMimeType): mixed {
+ $image = imagecreatefromstring($file->getContent());
+ imagepalettetotruecolor($image);
+
+ // Start output buffering
+ ob_start();
+
+ // Convert the image to the target format
+ if ($targetMimeType === 'image/gif') {
+ imagegif($image);
+ } else {
+ imagepng($image);
+ }
+
+ // End and return the output buffer
+ return ob_get_clean();
+ }
+}
diff --git a/apps/testing/lib/HiddenGroupBackend.php b/apps/testing/lib/HiddenGroupBackend.php
new file mode 100644
index 00000000000..96ead46c06e
--- /dev/null
+++ b/apps/testing/lib/HiddenGroupBackend.php
@@ -0,0 +1,44 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Testing;
+
+use OCP\Group\Backend\ABackend;
+use OCP\Group\Backend\IHideFromCollaborationBackend;
+
+class HiddenGroupBackend extends ABackend implements IHideFromCollaborationBackend {
+ public function __construct(
+ private string $groupName = 'hidden_group',
+ ) {
+ }
+
+ public function inGroup($uid, $gid): bool {
+ return false;
+ }
+
+ public function getUserGroups($uid): array {
+ return [];
+ }
+
+ public function getGroups($search = '', $limit = -1, $offset = 0): array {
+ return $offset === 0 ? [$this->groupName] : [];
+ }
+
+ public function groupExists($gid): bool {
+ return $gid === $this->groupName;
+ }
+
+ public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0): array {
+ return [];
+ }
+
+ public function hideGroup(string $groupId): bool {
+ return true;
+ }
+}
diff --git a/apps/testing/lib/Listener/GetDeclarativeSettingsValueListener.php b/apps/testing/lib/Listener/GetDeclarativeSettingsValueListener.php
new file mode 100644
index 00000000000..0df58168007
--- /dev/null
+++ b/apps/testing/lib/Listener/GetDeclarativeSettingsValueListener.php
@@ -0,0 +1,37 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Testing\Listener;
+
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\IConfig;
+use OCP\Settings\Events\DeclarativeSettingsGetValueEvent;
+
+/**
+ * @template-implements IEventListener<DeclarativeSettingsGetValueEvent>
+ */
+class GetDeclarativeSettingsValueListener implements IEventListener {
+
+ public function __construct(
+ private IConfig $config,
+ ) {
+ }
+
+ public function handle(Event $event): void {
+ if (!$event instanceof DeclarativeSettingsGetValueEvent) {
+ return;
+ }
+
+ if ($event->getApp() !== 'testing') {
+ return;
+ }
+
+ $value = $this->config->getUserValue($event->getUser()->getUID(), $event->getApp(), $event->getFieldId());
+ $event->setValue($value);
+ }
+}
diff --git a/apps/testing/lib/Listener/RegisterDeclarativeSettingsListener.php b/apps/testing/lib/Listener/RegisterDeclarativeSettingsListener.php
new file mode 100644
index 00000000000..aab39b78d76
--- /dev/null
+++ b/apps/testing/lib/Listener/RegisterDeclarativeSettingsListener.php
@@ -0,0 +1,71 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Testing\Listener;
+
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\Settings\DeclarativeSettingsTypes;
+use OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent;
+
+/**
+ * @template-implements IEventListener<DeclarativeSettingsRegisterFormEvent>
+ */
+class RegisterDeclarativeSettingsListener implements IEventListener {
+
+ public function __construct() {
+ }
+
+ public function handle(Event $event): void {
+ if (!($event instanceof DeclarativeSettingsRegisterFormEvent)) {
+ // Unrelated
+ return;
+ }
+
+ $event->registerSchema('testing', [
+ 'id' => 'test_declarative_form_event',
+ 'priority' => 20,
+ 'section_type' => DeclarativeSettingsTypes::SECTION_TYPE_ADMIN,
+ 'section_id' => 'additional',
+ 'storage_type' => DeclarativeSettingsTypes::STORAGE_TYPE_INTERNAL,
+ 'title' => 'Test declarative settings event', // NcSettingsSection name
+ 'description' => 'This form is registered via the RegisterDeclarativeSettingsFormEvent', // NcSettingsSection description
+ 'fields' => [
+ [
+ 'id' => 'event_field_1',
+ 'title' => 'Why is 42 this answer to all questions?',
+ 'description' => 'Hint: It\'s not',
+ 'type' => DeclarativeSettingsTypes::TEXT,
+ 'placeholder' => 'Enter your answer',
+ 'default' => 'Because it is',
+ ],
+ [
+ 'id' => 'feature_rating',
+ 'title' => 'How would you rate this feature?',
+ 'description' => 'Your vote is not anonymous',
+ 'type' => DeclarativeSettingsTypes::RADIO, // radio, radio-button (NcCheckboxRadioSwitch button-variant)
+ 'label' => 'Select single toggle',
+ 'default' => '3',
+ 'options' => [
+ [
+ 'name' => 'Awesome', // NcCheckboxRadioSwitch display name
+ 'value' => '1' // NcCheckboxRadioSwitch value
+ ],
+ [
+ 'name' => 'Very awesome',
+ 'value' => '2'
+ ],
+ [
+ 'name' => 'Super awesome',
+ 'value' => '3'
+ ],
+ ],
+ ],
+ ],
+ ]);
+ }
+}
diff --git a/apps/testing/lib/Listener/SetDeclarativeSettingsValueListener.php b/apps/testing/lib/Listener/SetDeclarativeSettingsValueListener.php
new file mode 100644
index 00000000000..0058e7df43e
--- /dev/null
+++ b/apps/testing/lib/Listener/SetDeclarativeSettingsValueListener.php
@@ -0,0 +1,37 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Testing\Listener;
+
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\IConfig;
+use OCP\Settings\Events\DeclarativeSettingsSetValueEvent;
+
+/**
+ * @template-implements IEventListener<DeclarativeSettingsSetValueEvent>
+ */
+class SetDeclarativeSettingsValueListener implements IEventListener {
+
+ public function __construct(
+ private IConfig $config,
+ ) {
+ }
+
+ public function handle(Event $event): void {
+ if (!$event instanceof DeclarativeSettingsSetValueEvent) {
+ return;
+ }
+
+ if ($event->getApp() !== 'testing') {
+ return;
+ }
+
+ error_log('Testing app wants to store ' . $event->getValue() . ' for field ' . $event->getFieldId() . ' for user ' . $event->getUser()->getUID());
+ $this->config->setUserValue($event->getUser()->getUID(), $event->getApp(), $event->getFieldId(), $event->getValue());
+ }
+}
diff --git a/apps/testing/lib/Locking/FakeDBLockingProvider.php b/apps/testing/lib/Locking/FakeDBLockingProvider.php
index 2556ba29a64..f77bacc7a63 100644
--- a/apps/testing/lib/Locking/FakeDBLockingProvider.php
+++ b/apps/testing/lib/Locking/FakeDBLockingProvider.php
@@ -1,32 +1,15 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Testing\Locking;
+use OC\Lock\DBLockingProvider;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IDBConnection;
-use Psr\Log\LoggerInterface;
-use OC\Lock\DBLockingProvider;
class FakeDBLockingProvider extends DBLockingProvider {
// Lock for 10 hours just to be sure
@@ -39,7 +22,7 @@ class FakeDBLockingProvider extends DBLockingProvider {
public function __construct(
IDBConnection $connection,
- ITimeFactory $timeFactory
+ ITimeFactory $timeFactory,
) {
parent::__construct($connection, $timeFactory);
$this->db = $connection;
diff --git a/apps/testing/lib/Migration/Version30000Date20240102030405.php b/apps/testing/lib/Migration/Version30000Date20240102030405.php
new file mode 100644
index 00000000000..e7b6bdcd618
--- /dev/null
+++ b/apps/testing/lib/Migration/Version30000Date20240102030405.php
@@ -0,0 +1,41 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Testing\Migration;
+
+use Closure;
+use OCP\Migration\Attributes\AddColumn;
+use OCP\Migration\Attributes\AddIndex;
+use OCP\Migration\Attributes\ColumnType;
+use OCP\Migration\Attributes\CreateTable;
+use OCP\Migration\Attributes\DropColumn;
+use OCP\Migration\Attributes\DropIndex;
+use OCP\Migration\Attributes\DropTable;
+use OCP\Migration\Attributes\IndexType;
+use OCP\Migration\Attributes\ModifyColumn;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+
+#[DropTable(table: 'old_table')]
+#[CreateTable(table: 'new_table', description: 'Table is used to store things, but also to get more things', notes: ['this is a notice', 'and another one, if really needed'])]
+#[AddColumn(table: 'my_table')]
+#[AddColumn(table: 'my_table', name: 'another_field')]
+#[AddColumn(table: 'other_table', name: 'last_one', type: ColumnType::DATE)]
+#[AddIndex(table: 'my_table')]
+#[AddIndex(table: 'my_table', type: IndexType::PRIMARY)]
+#[DropColumn(table: 'other_table')]
+#[DropColumn(table: 'other_table', name: 'old_column', description: 'field is not used anymore and replaced by \'last_one\'')]
+#[DropIndex(table: 'other_table')]
+#[ModifyColumn(table: 'other_table')]
+#[ModifyColumn(table: 'other_table', name: 'this_field')]
+#[ModifyColumn(table: 'other_table', name: 'this_field', type: ColumnType::BIGINT)]
+class Version30000Date20240102030405 extends SimpleMigrationStep {
+ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
+ return null;
+ }
+}
diff --git a/apps/testing/lib/Provider/FakeText2ImageProvider.php b/apps/testing/lib/Provider/FakeText2ImageProvider.php
new file mode 100644
index 00000000000..6b607f23347
--- /dev/null
+++ b/apps/testing/lib/Provider/FakeText2ImageProvider.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Testing\Provider;
+
+use OCP\TextToImage\IProvider;
+
+class FakeText2ImageProvider implements IProvider {
+
+ public function getName(): string {
+ return 'Fake Text2Image provider';
+ }
+
+ public function generate(string $prompt, array $resources): void {
+ foreach ($resources as $resource) {
+ $read = fopen(__DIR__ . '/../../img/logo.png', 'r');
+ stream_copy_to_stream($read, $resource);
+ fclose($read);
+ }
+ }
+
+ public function getExpectedRuntime(): int {
+ return 1;
+ }
+
+ public function getId(): string {
+ return 'testing-fake-text2image-provider';
+ }
+}
diff --git a/apps/testing/lib/Provider/FakeTextProcessingProvider.php b/apps/testing/lib/Provider/FakeTextProcessingProvider.php
new file mode 100644
index 00000000000..d3b16c55c67
--- /dev/null
+++ b/apps/testing/lib/Provider/FakeTextProcessingProvider.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Testing\Provider;
+
+use OCP\TextProcessing\FreePromptTaskType;
+use OCP\TextProcessing\IProvider;
+use OCP\TextProcessing\ITaskType;
+
+/** @template-implements IProvider<FreePromptTaskType|ITaskType> */
+class FakeTextProcessingProvider implements IProvider {
+
+ public function getName(): string {
+ return 'Fake text processing provider (asynchronous)';
+ }
+
+ public function process(string $prompt): string {
+ return $this->mb_strrev($prompt) . ' (done with FakeTextProcessingProvider)';
+ }
+
+ public function getTaskType(): string {
+ return FreePromptTaskType::class;
+ }
+
+ /**
+ * Reverse a miltibyte string.
+ *
+ * @param string $string The string to be reversed.
+ * @return string The reversed string
+ */
+ private function mb_strrev(string $string): string {
+ $chars = mb_str_split($string, 1);
+ return implode('', array_reverse($chars));
+ }
+}
diff --git a/apps/testing/lib/Provider/FakeTextProcessingProviderSync.php b/apps/testing/lib/Provider/FakeTextProcessingProviderSync.php
new file mode 100644
index 00000000000..ea822199109
--- /dev/null
+++ b/apps/testing/lib/Provider/FakeTextProcessingProviderSync.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Testing\Provider;
+
+use OCP\TextProcessing\FreePromptTaskType;
+use OCP\TextProcessing\IProviderWithExpectedRuntime;
+use OCP\TextProcessing\ITaskType;
+
+/**
+ * @template-implements IProviderWithExpectedRuntime<FreePromptTaskType|ITaskType>
+ */
+class FakeTextProcessingProviderSync implements IProviderWithExpectedRuntime {
+
+ public function getName(): string {
+ return 'Fake text processing provider (synchronous)';
+ }
+
+ public function process(string $prompt): string {
+ return $this->mb_strrev($prompt) . ' (done with FakeTextProcessingProviderSync)';
+ }
+
+ public function getTaskType(): string {
+ return FreePromptTaskType::class;
+ }
+
+ public function getExpectedRuntime(): int {
+ return 1;
+ }
+
+ /**
+ * Reverse a miltibyte string.
+ *
+ * @param string $string The string to be reversed.
+ * @return string The reversed string
+ */
+ private function mb_strrev(string $string): string {
+ $chars = mb_str_split($string, 1);
+ return implode('', array_reverse($chars));
+ }
+}
diff --git a/apps/testing/lib/Provider/FakeTranslationProvider.php b/apps/testing/lib/Provider/FakeTranslationProvider.php
new file mode 100644
index 00000000000..cc2d13db646
--- /dev/null
+++ b/apps/testing/lib/Provider/FakeTranslationProvider.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Testing\Provider;
+
+use OCP\Translation\ITranslationProvider;
+use OCP\Translation\LanguageTuple;
+
+class FakeTranslationProvider implements ITranslationProvider {
+
+ public function getName(): string {
+ return 'Fake translation';
+ }
+
+ public function getAvailableLanguages(): array {
+ return [
+ new LanguageTuple('de', 'German', 'en', 'English'),
+ new LanguageTuple('en', 'English', 'de', 'German'),
+ ];
+ }
+
+ public function translate(?string $fromLanguage, string $toLanguage, string $text): string {
+ return strrev($text);
+ }
+}
diff --git a/apps/testing/lib/Settings/DeclarativeSettingsForm.php b/apps/testing/lib/Settings/DeclarativeSettingsForm.php
new file mode 100644
index 00000000000..55e44cbcbea
--- /dev/null
+++ b/apps/testing/lib/Settings/DeclarativeSettingsForm.php
@@ -0,0 +1,205 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Testing\Settings;
+
+use OCP\Settings\DeclarativeSettingsTypes;
+use OCP\Settings\IDeclarativeSettingsForm;
+
+class DeclarativeSettingsForm implements IDeclarativeSettingsForm {
+ public function getSchema(): array {
+ return [
+ 'id' => 'test_declarative_form',
+ 'priority' => 10,
+ 'section_type' => DeclarativeSettingsTypes::SECTION_TYPE_ADMIN, // admin, personal
+ 'section_id' => 'additional',
+ 'storage_type' => DeclarativeSettingsTypes::STORAGE_TYPE_INTERNAL, // external, internal (handled by core to store in appconfig and preferences)
+ 'title' => 'Test declarative settings class', // NcSettingsSection name
+ 'description' => 'This form is registered with a DeclarativeSettingsForm class', // NcSettingsSection description
+ 'doc_url' => '', // NcSettingsSection doc_url for documentation or help page, empty string if not needed
+ 'fields' => [
+ [
+ 'id' => 'test_ex_app_field_7', // configkey
+ 'title' => 'Multi-selection', // name or label
+ 'description' => 'Select some option setting', // hint
+ 'type' => DeclarativeSettingsTypes::MULTI_SELECT, // select, radio, multi-select
+ 'options' => ['foo', 'bar', 'baz'], // simple options for select, radio, multi-select
+ 'placeholder' => 'Select some multiple options', // input placeholder
+ 'default' => ['foo', 'bar'],
+ ],
+ [
+ 'id' => 'some_real_setting',
+ 'title' => 'Choose init status check background job interval',
+ 'description' => 'How often AppAPI should check for initialization status',
+ 'type' => DeclarativeSettingsTypes::RADIO, // radio (NcCheckboxRadioSwitch type radio)
+ 'placeholder' => 'Choose init status check background job interval',
+ 'default' => '40m',
+ 'options' => [
+ [
+ 'name' => 'Each 40 minutes', // NcCheckboxRadioSwitch display name
+ 'value' => '40m' // NcCheckboxRadioSwitch value
+ ],
+ [
+ 'name' => 'Each 60 minutes',
+ 'value' => '60m'
+ ],
+ [
+ 'name' => 'Each 120 minutes',
+ 'value' => '120m'
+ ],
+ [
+ 'name' => 'Each day',
+ 'value' => 60 * 24 . 'm'
+ ],
+ ],
+ ],
+ [
+ 'id' => 'test_ex_app_field_1', // configkey
+ 'title' => 'Default text field', // label
+ 'description' => 'Set some simple text setting', // hint
+ 'type' => DeclarativeSettingsTypes::TEXT, // text, password, email, tel, url, number
+ 'placeholder' => 'Enter text setting', // placeholder
+ 'default' => 'foo',
+ ],
+ [
+ 'id' => 'test_ex_app_field_1_1',
+ 'title' => 'Email field',
+ 'description' => 'Set email config',
+ 'type' => DeclarativeSettingsTypes::EMAIL,
+ 'placeholder' => 'Enter email',
+ 'default' => '',
+ ],
+ [
+ 'id' => 'test_ex_app_field_1_2',
+ 'title' => 'Tel field',
+ 'description' => 'Set tel config',
+ 'type' => DeclarativeSettingsTypes::TEL,
+ 'placeholder' => 'Enter your tel',
+ 'default' => '',
+ ],
+ [
+ 'id' => 'test_ex_app_field_1_3',
+ 'title' => 'Url (website) field',
+ 'description' => 'Set url config',
+ 'type' => 'url',
+ 'placeholder' => 'Enter url',
+ 'default' => '',
+ ],
+ [
+ 'id' => 'test_ex_app_field_1_4',
+ 'title' => 'Number field',
+ 'description' => 'Set number config',
+ 'type' => DeclarativeSettingsTypes::NUMBER,
+ 'placeholder' => 'Enter number value',
+ 'default' => 0,
+ ],
+ [
+ 'id' => 'test_ex_app_field_2',
+ 'title' => 'Password',
+ 'description' => 'Set some secure value setting',
+ 'type' => 'password',
+ 'placeholder' => 'Set secure value',
+ 'default' => '',
+ ],
+ [
+ 'id' => 'test_ex_app_field_3',
+ 'title' => 'Selection',
+ 'description' => 'Select some option setting',
+ 'type' => DeclarativeSettingsTypes::SELECT, // select, radio, multi-select
+ 'options' => ['foo', 'bar', 'baz'],
+ 'placeholder' => 'Select some option setting',
+ 'default' => 'foo',
+ ],
+ [
+ 'id' => 'test_ex_app_field_4',
+ 'title' => 'Toggle something',
+ 'description' => 'Select checkbox option setting',
+ 'type' => DeclarativeSettingsTypes::CHECKBOX, // checkbox, multiple-checkbox
+ 'label' => 'Verify something if enabled',
+ 'default' => false,
+ ],
+ [
+ 'id' => 'test_ex_app_field_5',
+ 'title' => 'Multiple checkbox toggles, describing one setting, checked options are saved as an JSON object {foo: true, bar: false}',
+ 'description' => 'Select checkbox option setting',
+ 'type' => DeclarativeSettingsTypes::MULTI_CHECKBOX, // checkbox, multi-checkbox
+ 'default' => ['foo' => true, 'bar' => true, 'baz' => true],
+ 'options' => [
+ [
+ 'name' => 'Foo',
+ 'value' => 'foo', // multiple-checkbox configkey
+ ],
+ [
+ 'name' => 'Bar',
+ 'value' => 'bar',
+ ],
+ [
+ 'name' => 'Baz',
+ 'value' => 'baz',
+ ],
+ [
+ 'name' => 'Qux',
+ 'value' => 'qux',
+ ],
+ ],
+ ],
+ [
+ 'id' => 'test_ex_app_field_6',
+ 'title' => 'Radio toggles, describing one setting like single select',
+ 'description' => 'Select radio option setting',
+ 'type' => DeclarativeSettingsTypes::RADIO, // radio (NcCheckboxRadioSwitch type radio)
+ 'label' => 'Select single toggle',
+ 'default' => 'foo',
+ 'options' => [
+ [
+ 'name' => 'First radio', // NcCheckboxRadioSwitch display name
+ 'value' => 'foo' // NcCheckboxRadioSwitch value
+ ],
+ [
+ 'name' => 'Second radio',
+ 'value' => 'bar'
+ ],
+ [
+ 'name' => 'Third radio',
+ 'value' => 'baz'
+ ],
+ ],
+ ],
+ [
+ 'id' => 'test_sensitive_field',
+ 'title' => 'Sensitive text field',
+ 'description' => 'Set some secure value setting that is stored encrypted',
+ 'type' => DeclarativeSettingsTypes::TEXT,
+ 'label' => 'Sensitive field',
+ 'placeholder' => 'Set secure value',
+ 'default' => '',
+ 'sensitive' => true, // only for TEXT, PASSWORD types
+ ],
+ [
+ 'id' => 'test_sensitive_field_2',
+ 'title' => 'Sensitive password field',
+ 'description' => 'Set some password setting that is stored encrypted',
+ 'type' => DeclarativeSettingsTypes::PASSWORD,
+ 'label' => 'Sensitive field',
+ 'placeholder' => 'Set secure value',
+ 'default' => '',
+ 'sensitive' => true, // only for TEXT, PASSWORD types
+ ],
+ [
+ 'id' => 'test_non_sensitive_field',
+ 'title' => 'Password field',
+ 'description' => 'Set some password setting',
+ 'type' => DeclarativeSettingsTypes::PASSWORD,
+ 'label' => 'Password field',
+ 'placeholder' => 'Set secure value',
+ 'default' => '',
+ 'sensitive' => false,
+ ],
+ ],
+ ];
+ }
+}
diff --git a/apps/testing/lib/TaskProcessing/FakeContextWriteProvider.php b/apps/testing/lib/TaskProcessing/FakeContextWriteProvider.php
new file mode 100644
index 00000000000..9a5574f5147
--- /dev/null
+++ b/apps/testing/lib/TaskProcessing/FakeContextWriteProvider.php
@@ -0,0 +1,130 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+declare(strict_types=1);
+
+namespace OCA\Testing\TaskProcessing;
+
+use OCA\Testing\AppInfo\Application;
+use OCP\AppFramework\Services\IAppConfig;
+use OCP\TaskProcessing\EShapeType;
+use OCP\TaskProcessing\Exception\ProcessingException;
+use OCP\TaskProcessing\ISynchronousProvider;
+use OCP\TaskProcessing\ShapeDescriptor;
+use OCP\TaskProcessing\ShapeEnumValue;
+use OCP\TaskProcessing\TaskTypes\ContextWrite;
+use RuntimeException;
+
+class FakeContextWriteProvider implements ISynchronousProvider {
+
+ public function __construct(
+ protected IAppConfig $appConfig,
+ ) {
+ }
+
+ public function getId(): string {
+ return Application::APP_ID . '-contextwrite';
+ }
+
+ public function getName(): string {
+ return 'Fake context write task processing provider';
+ }
+
+ public function getTaskTypeId(): string {
+ return ContextWrite::ID;
+ }
+
+ public function getExpectedRuntime(): int {
+ return 1;
+ }
+
+ public function getInputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getInputShapeDefaults(): array {
+ return [];
+ }
+
+ public function getOptionalInputShape(): array {
+ return [
+ 'max_tokens' => new ShapeDescriptor(
+ 'Maximum output words',
+ 'The maximum number of words/tokens that can be generated in the completion.',
+ EShapeType::Number
+ ),
+ 'model' => new ShapeDescriptor(
+ 'Model',
+ 'The model used to generate the completion',
+ EShapeType::Enum
+ ),
+ ];
+ }
+
+ public function getOptionalInputShapeEnumValues(): array {
+ return [
+ 'model' => [
+ new ShapeEnumValue('Model 1', 'model_1'),
+ new ShapeEnumValue('Model 2', 'model_2'),
+ new ShapeEnumValue('Model 3', 'model_3'),
+ ],
+ ];
+ }
+
+ public function getOptionalInputShapeDefaults(): array {
+ return [
+ 'max_tokens' => 4321,
+ 'model' => 'model_2',
+ ];
+ }
+
+ public function getOutputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getOptionalOutputShape(): array {
+ return [];
+ }
+
+ public function getOptionalOutputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function process(?string $userId, array $input, callable $reportProgress): array {
+ if ($this->appConfig->getAppValueBool('fail-' . $this->getId())) {
+ throw new ProcessingException('Failing as set by AppConfig');
+ }
+
+ if (
+ !isset($input['style_input']) || !is_string($input['style_input'])
+ || !isset($input['source_input']) || !is_string($input['source_input'])
+ ) {
+ throw new RuntimeException('Invalid inputs');
+ }
+ $writingStyle = $input['style_input'];
+ $sourceMaterial = $input['source_input'];
+
+ if (isset($input['model']) && is_string($input['model'])) {
+ $model = $input['model'];
+ } else {
+ $model = 'unknown model';
+ }
+
+ $maxTokens = null;
+ if (isset($input['max_tokens']) && is_int($input['max_tokens'])) {
+ $maxTokens = $input['max_tokens'];
+ }
+
+ $fakeResult = 'This is a fake result: '
+ . "\n\n- Style input: " . $writingStyle
+ . "\n- Source input: " . $sourceMaterial
+ . "\n- Model: " . $model
+ . "\n- Maximum number of words: " . $maxTokens;
+
+ return ['output' => $fakeResult];
+ }
+}
diff --git a/apps/testing/lib/TaskProcessing/FakeTextToImageProvider.php b/apps/testing/lib/TaskProcessing/FakeTextToImageProvider.php
new file mode 100644
index 00000000000..455d6c0b518
--- /dev/null
+++ b/apps/testing/lib/TaskProcessing/FakeTextToImageProvider.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+declare(strict_types=1);
+
+namespace OCA\Testing\TaskProcessing;
+
+use OCA\Testing\AppInfo\Application;
+use OCP\AppFramework\Services\IAppConfig;
+use OCP\TaskProcessing\EShapeType;
+use OCP\TaskProcessing\Exception\ProcessingException;
+use OCP\TaskProcessing\ISynchronousProvider;
+use OCP\TaskProcessing\ShapeDescriptor;
+use OCP\TaskProcessing\TaskTypes\TextToImage;
+use RuntimeException;
+
+class FakeTextToImageProvider implements ISynchronousProvider {
+
+ public function __construct(
+ protected IAppConfig $appConfig,
+ ) {
+ }
+
+ public function getId(): string {
+ return Application::APP_ID . '-text2image';
+ }
+
+ public function getName(): string {
+ return 'Fake text2image task processing provider';
+ }
+
+ public function getTaskTypeId(): string {
+ return TextToImage::ID;
+ }
+
+ public function getExpectedRuntime(): int {
+ return 1;
+ }
+
+ public function getInputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getInputShapeDefaults(): array {
+ return [
+ 'numberOfImages' => 1,
+ ];
+ }
+
+ public function getOptionalInputShape(): array {
+ return [
+ 'size' => new ShapeDescriptor(
+ 'Size',
+ 'Optional. The size of the generated images. Must be in 256x256 format.',
+ EShapeType::Text
+ ),
+ ];
+ }
+
+ public function getOptionalInputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getOptionalInputShapeDefaults(): array {
+ return [];
+ }
+
+ public function getOutputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getOptionalOutputShape(): array {
+ return [];
+ }
+
+ public function getOptionalOutputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function process(?string $userId, array $input, callable $reportProgress): array {
+ if ($this->appConfig->getAppValueBool('fail-' . $this->getId())) {
+ throw new ProcessingException('Failing as set by AppConfig');
+ }
+
+ if (!isset($input['input']) || !is_string($input['input'])) {
+ throw new RuntimeException('Invalid prompt');
+ }
+ $prompt = $input['input'];
+
+ $nbImages = 1;
+ if (isset($input['numberOfImages']) && is_int($input['numberOfImages'])) {
+ $nbImages = $input['numberOfImages'];
+ }
+
+ $fakeContent = file_get_contents(__DIR__ . '/../../img/logo.png');
+
+ $output = ['images' => []];
+ foreach (range(1, $nbImages) as $i) {
+ $output['images'][] = $fakeContent;
+ }
+ /** @var array<string, list<numeric|string>|numeric|string> $output */
+ return $output;
+ }
+}
diff --git a/apps/testing/lib/TaskProcessing/FakeTextToTextProvider.php b/apps/testing/lib/TaskProcessing/FakeTextToTextProvider.php
new file mode 100644
index 00000000000..5012823024e
--- /dev/null
+++ b/apps/testing/lib/TaskProcessing/FakeTextToTextProvider.php
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+declare(strict_types=1);
+
+namespace OCA\Testing\TaskProcessing;
+
+use OCA\Testing\AppInfo\Application;
+use OCP\AppFramework\Services\IAppConfig;
+use OCP\TaskProcessing\EShapeType;
+use OCP\TaskProcessing\Exception\ProcessingException;
+use OCP\TaskProcessing\ISynchronousProvider;
+use OCP\TaskProcessing\ShapeDescriptor;
+use OCP\TaskProcessing\ShapeEnumValue;
+use OCP\TaskProcessing\TaskTypes\TextToText;
+use RuntimeException;
+
+class FakeTextToTextProvider implements ISynchronousProvider {
+
+ public function __construct(
+ protected IAppConfig $appConfig,
+ ) {
+ }
+
+ public function getId(): string {
+ return Application::APP_ID . '-text2text';
+ }
+
+ public function getName(): string {
+ return 'Fake text2text task processing provider';
+ }
+
+ public function getTaskTypeId(): string {
+ return TextToText::ID;
+ }
+
+ public function getExpectedRuntime(): int {
+ return 1;
+ }
+
+ public function getInputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getInputShapeDefaults(): array {
+ return [];
+ }
+
+ public function getOptionalInputShape(): array {
+ return [
+ 'max_tokens' => new ShapeDescriptor(
+ 'Maximum output words',
+ 'The maximum number of words/tokens that can be generated in the completion.',
+ EShapeType::Number
+ ),
+ 'model' => new ShapeDescriptor(
+ 'Model',
+ 'The model used to generate the completion',
+ EShapeType::Enum
+ ),
+ ];
+ }
+
+ public function getOptionalInputShapeEnumValues(): array {
+ return [
+ 'model' => [
+ new ShapeEnumValue('Model 1', 'model_1'),
+ new ShapeEnumValue('Model 2', 'model_2'),
+ new ShapeEnumValue('Model 3', 'model_3'),
+ ],
+ ];
+ }
+
+ public function getOptionalInputShapeDefaults(): array {
+ return [
+ 'max_tokens' => 1234,
+ 'model' => 'model_2',
+ ];
+ }
+
+ public function getOptionalOutputShape(): array {
+ return [];
+ }
+
+ public function getOutputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getOptionalOutputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function process(?string $userId, array $input, callable $reportProgress): array {
+ if ($this->appConfig->getAppValueBool('fail-' . $this->getId())) {
+ throw new ProcessingException('Failing as set by AppConfig');
+ }
+
+ if (isset($input['model']) && is_string($input['model'])) {
+ $model = $input['model'];
+ } else {
+ $model = 'unknown model';
+ }
+
+ if (!isset($input['input']) || !is_string($input['input'])) {
+ throw new RuntimeException('Invalid prompt');
+ }
+ $prompt = $input['input'];
+
+ $maxTokens = null;
+ if (isset($input['max_tokens']) && is_int($input['max_tokens'])) {
+ $maxTokens = $input['max_tokens'];
+ }
+
+ return [
+ 'output' => 'This is a fake result: ' . "\n\n- Prompt: " . $prompt . "\n- Model: " . $model . "\n- Maximum number of words: " . $maxTokens,
+ ];
+ }
+}
diff --git a/apps/testing/lib/TaskProcessing/FakeTextToTextSummaryProvider.php b/apps/testing/lib/TaskProcessing/FakeTextToTextSummaryProvider.php
new file mode 100644
index 00000000000..58816d8a0df
--- /dev/null
+++ b/apps/testing/lib/TaskProcessing/FakeTextToTextSummaryProvider.php
@@ -0,0 +1,122 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+
+namespace OCA\Testing\TaskProcessing;
+
+use OCA\Testing\AppInfo\Application;
+use OCP\AppFramework\Services\IAppConfig;
+use OCP\TaskProcessing\EShapeType;
+use OCP\TaskProcessing\Exception\ProcessingException;
+use OCP\TaskProcessing\ISynchronousProvider;
+use OCP\TaskProcessing\ShapeDescriptor;
+use OCP\TaskProcessing\ShapeEnumValue;
+use OCP\TaskProcessing\TaskTypes\TextToTextSummary;
+use RuntimeException;
+
+class FakeTextToTextSummaryProvider implements ISynchronousProvider {
+
+ public function __construct(
+ protected IAppConfig $appConfig,
+ ) {
+ }
+
+ public function getId(): string {
+ return Application::APP_ID . '-text2text-summary';
+ }
+
+ public function getName(): string {
+ return 'Fake text2text summary task processing provider';
+ }
+
+ public function getTaskTypeId(): string {
+ return TextToTextSummary::ID;
+ }
+
+ public function getExpectedRuntime(): int {
+ return 1;
+ }
+
+ public function getInputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getInputShapeDefaults(): array {
+ return [];
+ }
+
+ public function getOptionalInputShape(): array {
+ return [
+ 'max_tokens' => new ShapeDescriptor(
+ 'Maximum output words',
+ 'The maximum number of words/tokens that can be generated in the completion.',
+ EShapeType::Number
+ ),
+ 'model' => new ShapeDescriptor(
+ 'Model',
+ 'The model used to generate the completion',
+ EShapeType::Enum
+ ),
+ ];
+ }
+
+ public function getOptionalInputShapeEnumValues(): array {
+ return [
+ 'model' => [
+ new ShapeEnumValue('Model 1', 'model_1'),
+ new ShapeEnumValue('Model 2', 'model_2'),
+ new ShapeEnumValue('Model 3', 'model_3'),
+ ],
+ ];
+ }
+
+ public function getOptionalInputShapeDefaults(): array {
+ return [
+ 'max_tokens' => 1234,
+ 'model' => 'model_2',
+ ];
+ }
+
+ public function getOptionalOutputShape(): array {
+ return [];
+ }
+
+ public function getOutputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getOptionalOutputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function process(?string $userId, array $input, callable $reportProgress): array {
+ if ($this->appConfig->getAppValueBool('fail-' . $this->getId())) {
+ throw new ProcessingException('Failing as set by AppConfig');
+ }
+
+ if (isset($input['model']) && is_string($input['model'])) {
+ $model = $input['model'];
+ } else {
+ $model = 'unknown model';
+ }
+
+ if (!isset($input['input']) || !is_string($input['input'])) {
+ throw new RuntimeException('Invalid prompt');
+ }
+ $prompt = $input['input'];
+
+ $maxTokens = null;
+ if (isset($input['max_tokens']) && is_int($input['max_tokens'])) {
+ $maxTokens = $input['max_tokens'];
+ }
+
+ return [
+ 'output' => 'This is a fake summary: ',// . "\n\n- Prompt: " . $prompt . "\n- Model: " . $model . "\n- Maximum number of words: " . $maxTokens,
+ ];
+ }
+}
diff --git a/apps/testing/lib/TaskProcessing/FakeTranscribeProvider.php b/apps/testing/lib/TaskProcessing/FakeTranscribeProvider.php
new file mode 100644
index 00000000000..4827a07037a
--- /dev/null
+++ b/apps/testing/lib/TaskProcessing/FakeTranscribeProvider.php
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+declare(strict_types=1);
+
+namespace OCA\Testing\TaskProcessing;
+
+use OCA\Testing\AppInfo\Application;
+use OCP\AppFramework\Services\IAppConfig;
+use OCP\Files\File;
+use OCP\TaskProcessing\Exception\ProcessingException;
+use OCP\TaskProcessing\ISynchronousProvider;
+use OCP\TaskProcessing\TaskTypes\AudioToText;
+use RuntimeException;
+
+class FakeTranscribeProvider implements ISynchronousProvider {
+
+ public function __construct(
+ protected IAppConfig $appConfig,
+ ) {
+ }
+
+ public function getId(): string {
+ return Application::APP_ID . '-audio2text';
+ }
+
+ public function getName(): string {
+ return 'Fake audio2text task processing provider';
+ }
+
+ public function getTaskTypeId(): string {
+ return AudioToText::ID;
+ }
+
+ public function getExpectedRuntime(): int {
+ return 1;
+ }
+
+ public function getInputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getInputShapeDefaults(): array {
+ return [];
+ }
+
+ public function getOptionalInputShape(): array {
+ return [];
+ }
+
+ public function getOptionalInputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getOptionalInputShapeDefaults(): array {
+ return [];
+ }
+
+ public function getOutputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getOptionalOutputShape(): array {
+ return [];
+ }
+
+ public function getOptionalOutputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function process(?string $userId, array $input, callable $reportProgress): array {
+ if (!isset($input['input']) || !$input['input'] instanceof File || !$input['input']->isReadable()) {
+ throw new RuntimeException('Invalid input file');
+ }
+ if ($this->appConfig->getAppValueBool('fail-' . $this->getId())) {
+ throw new ProcessingException('Failing as set by AppConfig');
+ }
+
+ $inputFile = $input['input'];
+ $transcription = 'Fake transcription result';
+
+ return ['output' => $transcription];
+ }
+}
diff --git a/apps/testing/lib/TaskProcessing/FakeTranslateProvider.php b/apps/testing/lib/TaskProcessing/FakeTranslateProvider.php
new file mode 100644
index 00000000000..22be8e83049
--- /dev/null
+++ b/apps/testing/lib/TaskProcessing/FakeTranslateProvider.php
@@ -0,0 +1,154 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+declare(strict_types=1);
+
+namespace OCA\Testing\TaskProcessing;
+
+use OCA\Testing\AppInfo\Application;
+use OCP\AppFramework\Services\IAppConfig;
+use OCP\L10N\IFactory;
+use OCP\TaskProcessing\EShapeType;
+use OCP\TaskProcessing\Exception\ProcessingException;
+use OCP\TaskProcessing\ISynchronousProvider;
+use OCP\TaskProcessing\ShapeDescriptor;
+use OCP\TaskProcessing\ShapeEnumValue;
+use OCP\TaskProcessing\TaskTypes\TextToTextTranslate;
+use RuntimeException;
+
+class FakeTranslateProvider implements ISynchronousProvider {
+
+ public function __construct(
+ private IFactory $l10nFactory,
+ protected IAppConfig $appConfig,
+ ) {
+ }
+
+ public function getId(): string {
+ return Application::APP_ID . '-translate';
+ }
+
+ public function getName(): string {
+ return 'Fake translate task processing provider';
+ }
+
+ public function getTaskTypeId(): string {
+ return TextToTextTranslate::ID;
+ }
+
+ public function getExpectedRuntime(): int {
+ return 1;
+ }
+
+ public function getInputShapeEnumValues(): array {
+ $coreL = $this->l10nFactory->getLanguages();
+ $languages = array_merge($coreL['commonLanguages'], $coreL['otherLanguages']);
+ $languageEnumValues = array_map(static function (array $language) {
+ return new ShapeEnumValue($language['name'], $language['code']);
+ }, $languages);
+ $detectLanguageEnumValue = new ShapeEnumValue('Detect language', 'detect_language');
+ return [
+ 'origin_language' => array_merge([$detectLanguageEnumValue], $languageEnumValues),
+ 'target_language' => $languageEnumValues,
+ ];
+ }
+
+ public function getInputShapeDefaults(): array {
+ return [
+ 'origin_language' => 'detect_language',
+ ];
+ }
+
+ public function getOptionalInputShape(): array {
+ return [
+ 'max_tokens' => new ShapeDescriptor(
+ 'Maximum output words',
+ 'The maximum number of words/tokens that can be generated in the completion.',
+ EShapeType::Number
+ ),
+ 'model' => new ShapeDescriptor(
+ 'Model',
+ 'The model used to generate the completion',
+ EShapeType::Enum
+ ),
+ ];
+ }
+
+ public function getOptionalInputShapeEnumValues(): array {
+ return [
+ 'model' => [
+ new ShapeEnumValue('Model 1', 'model_1'),
+ new ShapeEnumValue('Model 2', 'model_2'),
+ new ShapeEnumValue('Model 3', 'model_3'),
+ ],
+ ];
+ }
+
+ public function getOptionalInputShapeDefaults(): array {
+ return [
+ 'max_tokens' => 200,
+ 'model' => 'model_3',
+ ];
+ }
+
+ public function getOptionalOutputShape(): array {
+ return [];
+ }
+
+ public function getOutputShapeEnumValues(): array {
+ return [];
+ }
+
+ public function getOptionalOutputShapeEnumValues(): array {
+ return [];
+ }
+
+ private function getCoreLanguagesByCode(): array {
+ $coreL = $this->l10nFactory->getLanguages();
+ $coreLanguages = array_reduce(array_merge($coreL['commonLanguages'], $coreL['otherLanguages']), function ($carry, $val) {
+ $carry[$val['code']] = $val['name'];
+ return $carry;
+ });
+ return $coreLanguages;
+ }
+
+ public function process(?string $userId, array $input, callable $reportProgress): array {
+ if ($this->appConfig->getAppValueBool('fail-' . $this->getId())) {
+ throw new ProcessingException('Failing as set by AppConfig');
+ }
+
+ if (isset($input['model']) && is_string($input['model'])) {
+ $model = $input['model'];
+ } else {
+ $model = 'model_3';
+ }
+
+ if (!isset($input['input']) || !is_string($input['input'])) {
+ throw new RuntimeException('Invalid input text');
+ }
+ $inputText = $input['input'];
+
+ $maxTokens = null;
+ if (isset($input['max_tokens']) && is_int($input['max_tokens'])) {
+ $maxTokens = $input['max_tokens'];
+ }
+
+ $coreLanguages = $this->getCoreLanguagesByCode();
+
+ $toLanguage = $coreLanguages[$input['target_language']] ?? $input['target_language'];
+ if ($input['origin_language'] !== 'detect_language') {
+ $fromLanguage = $coreLanguages[$input['origin_language']] ?? $input['origin_language'];
+ $prompt = 'Fake translation from ' . $fromLanguage . ' to ' . $toLanguage . ': ' . $inputText;
+ } else {
+ $prompt = 'Fake Translation to ' . $toLanguage . ': ' . $inputText;
+ }
+
+ $fakeResult = $prompt . "\n\nModel: " . $model . "\nMax tokens: " . $maxTokens;
+
+ return ['output' => $fakeResult];
+ }
+}