diff options
Diffstat (limited to 'build')
137 files changed, 10464 insertions, 6571 deletions
diff --git a/build/.htaccess b/build/.htaccess index 853aed187d3..07984663791 100644 --- a/build/.htaccess +++ b/build/.htaccess @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2015 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only # line below if for Apache 2.4 <ifModule mod_authz_core.c> Require all denied diff --git a/build/WebpackSPDXPlugin.js b/build/WebpackSPDXPlugin.js new file mode 100644 index 00000000000..eeb338c032c --- /dev/null +++ b/build/WebpackSPDXPlugin.js @@ -0,0 +1,221 @@ +'use strict' + +/** + * Party inspired by https://github.com/FormidableLabs/webpack-stats-plugin + * + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT + */ + +const { constants } = require('node:fs') +const fs = require('node:fs/promises') +const path = require('node:path') +const webpack = require('webpack') + +class WebpackSPDXPlugin { + + #options + + /** + * @param {object} opts Parameters + * @param {Record<string, string>} opts.override Override licenses for packages + */ + constructor(opts = {}) { + this.#options = { override: {}, ...opts } + } + + apply(compiler) { + compiler.hooks.thisCompilation.tap('spdx-plugin', (compilation) => { + // `processAssets` is one of the last hooks before frozen assets. + // We choose `PROCESS_ASSETS_STAGE_REPORT` which is the last possible + // stage after which to emit. + compilation.hooks.processAssets.tapPromise( + { + name: 'spdx-plugin', + stage: compilation.constructor.PROCESS_ASSETS_STAGE_REPORT, + }, + () => this.emitLicenses(compilation), + ) + }) + } + + /** + * Find the nearest package.json + * @param {string} dir Directory to start checking + */ + async #findPackage(dir) { + if (!dir || dir === '/' || dir === '.') { + return null + } + + const packageJson = `${dir}/package.json` + try { + await fs.access(packageJson, constants.F_OK) + } catch (e) { + return await this.#findPackage(path.dirname(dir)) + } + + const { private: isPrivatePacket, name } = JSON.parse(await fs.readFile(packageJson)) + // "private" is set in internal package.json which should not be resolved but the parent package.json + // Same if no name is set in package.json + if (isPrivatePacket === true || !name) { + return (await this.#findPackage(path.dirname(dir))) ?? packageJson + } + return packageJson + } + + /** + * Emit licenses found in compilation to '.license' files + * @param {webpack.Compilation} compilation Webpack compilation object + * @param {*} callback Callback for old webpack versions + */ + async emitLicenses(compilation, callback) { + const logger = compilation.getLogger('spdx-plugin') + // cache the node packages + const packageInformation = new Map() + + const warnings = new Set() + /** @type {Map<string, Set<webpack.Chunk>>} */ + const sourceMap = new Map() + + for (const chunk of compilation.chunks) { + for (const file of chunk.files) { + if (sourceMap.has(file)) { + sourceMap.get(file).add(chunk) + } else { + sourceMap.set(file, new Set([chunk])) + } + } + } + + for (const [asset, chunks] of sourceMap.entries()) { + /** @type {Set<webpack.Module>} */ + const modules = new Set() + /** + * @param {webpack.Module} module + */ + const addModule = (module) => { + if (module && !modules.has(module)) { + modules.add(module) + for (const dep of module.dependencies) { + addModule(compilation.moduleGraph.getModule(dep)) + } + } + } + chunks.forEach((chunk) => chunk.getModules().forEach(addModule)) + + const sources = [...modules].map((module) => module.identifier()) + .map((source) => { + const skipped = [ + 'delegated', + 'external', + 'container entry', + 'ignored', + 'remote', + 'data:', + ] + // Webpack sources that we can not infer license information or that is not included (external modules) + if (skipped.some((prefix) => source.startsWith(prefix))) { + return '' + } + // Internal webpack sources + if (source.startsWith('webpack/runtime')) { + return require.resolve('webpack') + } + // Handle webpack loaders + if (source.includes('!')) { + return source.split('!').at(-1) + } + if (source.includes('|')) { + return source + .split('|') + .filter((s) => s.startsWith(path.sep)) + .at(0) + } + return source + }) + .filter((s) => !!s) + .map((s) => s.split('?', 2)[0]) + + // Skip assets without modules, these are emitted by webpack plugins + if (sources.length === 0) { + logger.warn(`Skipping ${asset} because it does not contain any source information`) + continue + } + + /** packages used by the current asset + * @type {Set<string>} + */ + const packages = new Set() + + // packages is the list of packages used by the asset + for (const sourcePath of sources) { + const pkg = await this.#findPackage(path.dirname(sourcePath)) + if (!pkg) { + logger.warn(`No package for source found (${sourcePath})`) + continue + } + + if (!packageInformation.has(pkg)) { + // Get the information from the package + const { author: packageAuthor, name, version, license: packageLicense, licenses } = JSON.parse(await fs.readFile(pkg)) + // Handle legacy packages + let license = !packageLicense && licenses + ? licenses.map((entry) => entry.type ?? entry).join(' OR ') + : packageLicense + if (license?.includes(' ') && !license?.startsWith('(')) { + license = `(${license})` + } + // Handle both object style and string style author + const author = typeof packageAuthor === 'object' + ? `${packageAuthor.name}` + (packageAuthor.mail ? ` <${packageAuthor.mail}>` : '') + : packageAuthor ?? `${name} developers` + + packageInformation.set(pkg, { + version, + // Fallback to directory name if name is not set + name: name ?? path.basename(path.dirname(pkg)), + author, + license, + }) + } + packages.add(pkg) + } + + let output = 'This file is generated from multiple sources. Included packages:\n' + const authors = new Set() + const licenses = new Set() + for (const packageName of [...packages].sort()) { + const pkg = packageInformation.get(packageName) + const license = this.#options.override[pkg.name] ?? pkg.license + // Emit warning if not already done + if (!license && !warnings.has(pkg.name)) { + logger.warn(`Missing license information for package ${pkg.name}, you should add it to the 'override' option.`) + warnings.add(pkg.name) + } + licenses.add(license || 'unknown') + authors.add(pkg.author) + output += `- ${pkg.name}\n\t- version: ${pkg.version}\n\t- license: ${license}\n` + } + output = `\n\n${output}` + for (const author of [...authors].sort()) { + output = `SPDX-FileCopyrightText: ${author}\n${output}` + } + for (const license of [...licenses].sort()) { + output = `SPDX-License-Identifier: ${license}\n${output}` + } + + compilation.emitAsset( + asset.split('?', 2)[0] + '.license', + new webpack.sources.RawSource(output), + ) + } + + if (callback) { + return callback() + } + } + +} + +module.exports = WebpackSPDXPlugin diff --git a/build/autoloaderchecker.sh b/build/autoloaderchecker.sh index 09bcff0b853..75db26f07ce 100755 --- a/build/autoloaderchecker.sh +++ b/build/autoloaderchecker.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash +# SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + COMPOSER_COMMAND="php composer.phar" if [ -e "composer.phar" ] @@ -31,6 +34,13 @@ echo echo "Regenerating main autoloader" $COMPOSER_COMMAND dump-autoload -d $REPODIR +FOUND_COMPOSER_BIN=$(grep --recursive --fixed-strings 'Bamarni\\Composer\\Bin' $REPODIR/lib/composer/composer/) +if [ -n "$FOUND_COMPOSER_BIN" ]; then + echo "The main autoloader contains the composer bin plugin" + echo "Run composer again with --no-dev and commit the result" + exit 1 +fi + for app in ${REPODIR}/apps/*; do if git check-ignore ${app} -q ; then echo @@ -42,6 +52,7 @@ for app in ${REPODIR}/apps/*; do echo "Regenerating composer files for ${app}" $COMPOSER_COMMAND i --no-dev -d ${app}/composer || exit 1 $COMPOSER_COMMAND dump-autoload -d ${app}/composer || exit 1 + git checkout ${app}/composer/composer/installed.php fi done diff --git a/build/build.xml b/build/build.xml index c8c5c4efffc..a44eca134d5 100644 --- a/build/build.xml +++ b/build/build.xml @@ -1,4 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- + - SPDX-FileCopyrightText: 2014 ownCloud, Inc. + - SPDX-License-Identifier: AGPL-3.0-or-later +--> <project name="ownCloud" default="build"> <!-- the target 'build' can be used by developers for command line builds --> diff --git a/build/buildjsdocs.sh b/build/buildjsdocs.sh deleted file mode 100755 index dd2af210277..00000000000 --- a/build/buildjsdocs.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash -# -# ownCloud -# -# Run JS tests -# -# @author Vincent Petry -# @copyright 2014 Vincent Petry <pvince81@owncloud.com> -# -NPM="$(which npm 2>/dev/null)" -OUTPUT_DIR="jsdocs" - -JS_FILES="../core/js/*.js ../core/js/**/*.js ../apps/*/js/*.js" - -if test -z "$NPM" -then - echo 'Node JS >= 0.8 is required to build the documentation' >&2 - exit 1 -fi - -# update/install test packages -$NPM install --prefix . --link jsdoc || exit 3 - -JSDOC_BIN="$(which jsdoc 2>/dev/null)" - -# If not installed globally, try local version -if test -z "$JSDOC_BIN" -then - JSDOC_BIN="./node_modules/jsdoc/jsdoc.js" -fi - -if test -z "$JSDOC_BIN" -then - echo 'jsdoc executable not found' >&2 - exit 2 -fi - -mkdir -p "$OUTPUT_DIR" - -NODE_PATH="./node_modules" $JSDOC_BIN -d "$OUTPUT_DIR" $JS_FILES - diff --git a/build/ca-bundle-etag.txt b/build/ca-bundle-etag.txt index 554025be5d9..8e3dbc7afa6 100644 --- a/build/ca-bundle-etag.txt +++ b/build/ca-bundle-etag.txt @@ -1 +1 @@ -"38116-6136426be7e2c" +"37a4f-63c22676aec9e" diff --git a/build/ca-bundle-etag.txt.license b/build/ca-bundle-etag.txt.license new file mode 100644 index 00000000000..39ee0d6eacc --- /dev/null +++ b/build/ca-bundle-etag.txt.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors +SPDX-License-Identifier: AGPL-3.0-or-later
\ No newline at end of file diff --git a/build/compile-handlebars-templates.sh b/build/compile-handlebars-templates.sh index 6a9397de3fa..57633e8a234 100755 --- a/build/compile-handlebars-templates.sh +++ b/build/compile-handlebars-templates.sh @@ -1,21 +1,15 @@ #!/usr/bin/env bash - +# +# SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +# REPODIR=`git rev-parse --show-toplevel` cd $REPODIR -# Comments files plugin -node node_modules/handlebars/bin/handlebars -n OCA.Comments.Templates apps/comments/src/templates -f apps/comments/src/templates.js - # Settings node node_modules/handlebars/bin/handlebars -n OC.Settings.Templates apps/settings/js/templates -f apps/settings/js/templates.js -# Files app -node node_modules/handlebars/bin/handlebars -n OCA.Files.Templates apps/files/js/templates -f apps/files/js/templates.js - -# Sharing -node node_modules/handlebars/bin/handlebars -n OCA.Sharing.Templates apps/files_sharing/js/templates -f apps/files_sharing/js/templates.js - # Files external node node_modules/handlebars/bin/handlebars -n OCA.Files_External.Templates apps/files_external/js/templates -f apps/files_external/js/templates.js @@ -26,6 +20,5 @@ if [[ $(git diff --name-only) ]]; then exit 1 fi - echo "All up to date! Carry on :D" exit 0 diff --git a/build/files-checker.php b/build/files-checker.php index ceb3367485c..08d9acf2fd8 100644 --- a/build/files-checker.php +++ b/build/files-checker.php @@ -1,33 +1,21 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2017 Morris Jobke <hey@morrisjobke.de> - * - * @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 */ $expectedFiles = [ '.', '..', '.devcontainer', - '.drone.yml', '.editorconfig', + '.envrc', '.eslintignore', '.eslintrc.js', '.git', + '.git-blame-ignore-revs', '.gitattributes', '.github', '.gitignore', @@ -39,7 +27,6 @@ $expectedFiles = [ '.npmignore', '.php-cs-fixer.dist.php', '.pre-commit-config.yaml', - '.scrutinizer.yml', '.tag', '.tx', '.user.ini', @@ -54,6 +41,7 @@ $expectedFiles = [ 'DESIGN.md', 'Makefile', 'README.md', + 'REUSE.toml', 'SECURITY.md', 'apps', 'autotest-checkers.sh', @@ -74,15 +62,19 @@ $expectedFiles = [ 'cypress.d.ts', 'cypress', 'dist', + 'flake.lock', + 'flake.nix', 'index.html', 'index.php', - 'jest.config.ts', 'lib', + 'LICENSES', 'occ', 'ocs', 'ocs-provider', + 'openapi.json', 'package-lock.json', 'package.json', + 'psalm-ncu.xml', 'psalm-ocp.xml', 'psalm.xml', 'public.php', @@ -90,11 +82,13 @@ $expectedFiles = [ 'resources', 'robots.txt', 'status.php', + 'stylelint.config.js', 'tests', 'themes', 'tsconfig.json', 'vendor-bin', 'version.php', + 'vitest.config.mts', 'webpack.common.js', 'webpack.config.js', 'webpack.modules.js', diff --git a/build/gen-coverage-badge.php b/build/gen-coverage-badge.php index 0164951fc1c..602ab83b281 100644 --- a/build/gen-coverage-badge.php +++ b/build/gen-coverage-badge.php @@ -1,26 +1,13 @@ <?php + /** - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @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: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ if (!isset($argv[1])) { - echo "Clover file is missing" . PHP_EOL; + echo 'Clover file is missing' . PHP_EOL; exit; } @@ -54,6 +41,6 @@ try { file_put_contents('coverage.svg', $content); } catch (Exception $ex) { echo $ex->getMessage() . PHP_EOL; - $content = file_get_contents("https://img.shields.io/badge/coverage-ERROR-red.svg"); + $content = file_get_contents('https://img.shields.io/badge/coverage-ERROR-red.svg'); file_put_contents('coverage.svg', $content); } diff --git a/build/htaccess-checker.php b/build/htaccess-checker.php index 950735463c9..963b3edb34b 100644 --- a/build/htaccess-checker.php +++ b/build/htaccess-checker.php @@ -1,24 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 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: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ /** diff --git a/build/image-optimization.sh b/build/image-optimization.sh index 5556dbdf31c..ddb213ea5bb 100755 --- a/build/image-optimization.sh +++ b/build/image-optimization.sh @@ -1,5 +1,8 @@ #!/usr/bin/env bash - +# +# SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +# set -e OPTIPNG=$(which optipng) diff --git a/build/integration/.gitignore b/build/integration/.gitignore index 18b981bf7ed..f181a23b4c0 100644 --- a/build/integration/.gitignore +++ b/build/integration/.gitignore @@ -1,3 +1,4 @@ +# SPDX-FileCopyrightText: 2015 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only vendor output -composer.lock diff --git a/build/integration/capabilities_features/capabilities.feature b/build/integration/capabilities_features/capabilities.feature index 500ea0297a6..2c664e24e1e 100644 --- a/build/integration/capabilities_features/capabilities.feature +++ b/build/integration/capabilities_features/capabilities.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2015-2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: capabilities Background: Given using api version "1" diff --git a/build/integration/collaboration_features/autocomplete.feature b/build/integration/collaboration_features/autocomplete.feature index 7329db79e29..7efc646f08d 100644 --- a/build/integration/collaboration_features/autocomplete.feature +++ b/build/integration/collaboration_features/autocomplete.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: autocomplete Background: Given using api version "2" diff --git a/build/integration/collaboration_features/user_status.feature b/build/integration/collaboration_features/user_status.feature index 759d6e31795..f620b50a416 100644 --- a/build/integration/collaboration_features/user_status.feature +++ b/build/integration/collaboration_features/user_status.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: user_status Background: Given using api version "2" diff --git a/build/integration/comments_features/comments-search.feature b/build/integration/comments_features/comments-search.feature deleted file mode 100644 index a1d116ee3f4..00000000000 --- a/build/integration/comments_features/comments-search.feature +++ /dev/null @@ -1,271 +0,0 @@ -Feature: comments-search - - Scenario: Search my own comment on a file belonging to myself - Given user "user0" exists - And User "user0" uploads file "data/textfile.txt" to "/myFileToComment.txt" - And "user0" posts a comment with content "My first comment" on the file named "/myFileToComment.txt" it should return "201" - When Logging in using web as "user0" - And searching for "first" in app "files" - Then the list of search results has "1" results - And search result "0" contains - | type | comment | - | comment | My first comment | - | authorId | user0 | - | authorName | user0 | - | path | myFileToComment.txt | - | fileName | myFileToComment.txt | - | name | My first comment | - - Scenario: Search my own comment on a file shared by someone with me - Given user "user0" exists - And user "user1" exists - And User "user1" uploads file "data/textfile.txt" to "/sharedFileToComment.txt" - And as "user1" creating a share with - | path | sharedFileToComment.txt | - | shareWith | user0 | - | shareType | 0 | - And user "user0" accepts last share - And "user0" posts a comment with content "My first comment" on the file named "/sharedFileToComment.txt" it should return "201" - When Logging in using web as "user0" - And searching for "first" in app "files" - Then the list of search results has "1" results - And search result "0" contains - | type | comment | - | comment | My first comment | - | authorId | user0 | - | authorName | user0 | - | path | sharedFileToComment.txt | - | fileName | sharedFileToComment.txt | - | name | My first comment | - - Scenario: Search other user's comment on a file shared by me - Given user "user0" exists - And user "user1" exists - And User "user0" uploads file "data/textfile.txt" to "/mySharedFileToComment.txt" - And as "user0" creating a share with - | path | mySharedFileToComment.txt | - | shareWith | user1 | - | shareType | 0 | - And user "user1" accepts last share - And "user1" posts a comment with content "Other's first comment" on the file named "/mySharedFileToComment.txt" it should return "201" - When Logging in using web as "user0" - And searching for "first" in app "files" - Then the list of search results has "1" results - And search result "0" contains - | type | comment | - | comment | Other's first comment | - | authorId | user1 | - | authorName | user1 | - | path | mySharedFileToComment.txt | - | fileName | mySharedFileToComment.txt | - | name | Other's first comment | - - Scenario: Search other user's comment on a file shared by someone with me - Given user "user0" exists - And user "user1" exists - And User "user1" uploads file "data/textfile.txt" to "/sharedFileToComment.txt" - And as "user1" creating a share with - | path | sharedFileToComment.txt | - | shareWith | user0 | - | shareType | 0 | - And user "user0" accepts last share - And "user1" posts a comment with content "Other's first comment" on the file named "/sharedFileToComment.txt" it should return "201" - When Logging in using web as "user0" - And searching for "first" in app "files" - Then the list of search results has "1" results - And search result "0" contains - | type | comment | - | comment | Other's first comment | - | authorId | user1 | - | authorName | user1 | - | path | sharedFileToComment.txt | - | fileName | sharedFileToComment.txt | - | name | Other's first comment | - - Scenario: Search several comments on a file belonging to myself - Given user "user0" exists - And User "user0" uploads file "data/textfile.txt" to "/myFileToComment.txt" - And "user0" posts a comment with content "My first comment to be found" on the file named "/myFileToComment.txt" it should return "201" - And "user0" posts a comment with content "The second comment should not be found" on the file named "/myFileToComment.txt" it should return "201" - And "user0" posts a comment with content "My third comment to be found" on the file named "/myFileToComment.txt" it should return "201" - When Logging in using web as "user0" - And searching for "comment to be found" in app "files" - Then the list of search results has "2" results - And search result "0" contains - | type | comment | - | comment | My third comment to be found | - | authorId | user0 | - | authorName | user0 | - | path | myFileToComment.txt | - | fileName | myFileToComment.txt | - | name | My third comment to be found | - And search result "1" contains - | type | comment | - | comment | My first comment to be found | - | authorId | user0 | - | authorName | user0 | - | path | myFileToComment.txt | - | fileName | myFileToComment.txt | - | name | My first comment to be found | - - Scenario: Search comment with a large message ellipsized on the right - Given user "user0" exists - And User "user0" uploads file "data/textfile.txt" to "/myFileToComment.txt" - And "user0" posts a comment with content "A very verbose message that is meant to be used to test the ellipsized message returned when searching for long comments" on the file named "/myFileToComment.txt" it should return "201" - When Logging in using web as "user0" - And searching for "verbose" in app "files" - Then the list of search results has "1" results - And search result "0" contains - | type | comment | - | comment | A very verbose message that is meant to… | - | authorId | user0 | - | authorName | user0 | - | path | myFileToComment.txt | - | fileName | myFileToComment.txt | - | name | A very verbose message that is meant to be used to test the ellipsized message returned when searching for long comments | - - Scenario: Search comment with a large message ellipsized on the left - Given user "user0" exists - And User "user0" uploads file "data/textfile.txt" to "/myFileToComment.txt" - And "user0" posts a comment with content "A very verbose message that is meant to be used to test the ellipsized message returned when searching for long comments" on the file named "/myFileToComment.txt" it should return "201" - When Logging in using web as "user0" - And searching for "searching" in app "files" - Then the list of search results has "1" results - And search result "0" contains - | type | comment | - | comment | …ed message returned when searching for long comments | - | authorId | user0 | - | authorName | user0 | - | path | myFileToComment.txt | - | fileName | myFileToComment.txt | - | name | A very verbose message that is meant to be used to test the ellipsized message returned when searching for long comments | - - Scenario: Search comment with a large message ellipsized on both ends - Given user "user0" exists - And User "user0" uploads file "data/textfile.txt" to "/myFileToComment.txt" - And "user0" posts a comment with content "A very verbose message that is meant to be used to test the ellipsized message returned when searching for long comments" on the file named "/myFileToComment.txt" it should return "201" - When Logging in using web as "user0" - And searching for "ellipsized" in app "files" - Then the list of search results has "1" results - And search result "0" contains - | type | comment | - | comment | …t to be used to test the ellipsized message returned when se… | - | authorId | user0 | - | authorName | user0 | - | path | myFileToComment.txt | - | fileName | myFileToComment.txt | - | name | A very verbose message that is meant to be used to test the ellipsized message returned when searching for long comments | - - Scenario: Search comment on a file in a subfolder - Given user "user0" exists - And user "user0" created a folder "/subfolder" - And User "user0" uploads file "data/textfile.txt" to "/subfolder/myFileToComment.txt" - And "user0" posts a comment with content "My first comment" on the file named "/subfolder/myFileToComment.txt" it should return "201" - When Logging in using web as "user0" - And searching for "first" in app "files" - Then the list of search results has "1" results - And search result "0" contains - | type | comment | - | comment | My first comment | - | authorId | user0 | - | authorName | user0 | - | path | subfolder/myFileToComment.txt | - | fileName | myFileToComment.txt | - | name | My first comment | - - Scenario: Search several comments - Given user "user0" exists - And user "user1" exists - And User "user0" uploads file "data/textfile.txt" to "/myFileToComment.txt" - And User "user0" uploads file "data/textfile.txt" to "/mySharedFileToComment.txt" - And as "user0" creating a share with - | path | mySharedFileToComment.txt | - | shareWith | user1 | - | shareType | 0 | - And user "user1" accepts last share - And User "user1" uploads file "data/textfile.txt" to "/sharedFileToComment.txt" - And as "user1" creating a share with - | path | sharedFileToComment.txt | - | shareWith | user0 | - | shareType | 0 | - And user "user0" accepts last share - And "user0" posts a comment with content "My first comment to be found" on the file named "/myFileToComment.txt" it should return "201" - And "user0" posts a comment with content "The second comment should not be found" on the file named "/myFileToComment.txt" it should return "201" - And "user0" posts a comment with content "My first comment to be found" on the file named "/mySharedFileToComment.txt" it should return "201" - And "user1" posts a comment with content "Other's first comment that should not be found" on the file named "/mySharedFileToComment.txt" it should return "201" - And "user1" posts a comment with content "Other's second comment to be found" on the file named "/mySharedFileToComment.txt" it should return "201" - And "user0" posts a comment with content "My first comment that should not be found" on the file named "/sharedFileToComment.txt" it should return "201" - And "user1" posts a comment with content "Other's first comment to be found" on the file named "/sharedFileToComment.txt" it should return "201" - And "user0" posts a comment with content "My second comment to be found that happens to be more verbose than the others and thus should be ellipsized" on the file named "/sharedFileToComment.txt" it should return "201" - And "user0" posts a comment with content "My third comment to be found" on the file named "/myFileToComment.txt" it should return "201" - When Logging in using web as "user0" - And searching for "comment to be found" in app "files" - Then the list of search results has "6" results - And search result "0" contains - | type | comment | - | comment | My third comment to be found | - | authorId | user0 | - | authorName | user0 | - | path | myFileToComment.txt | - | fileName | myFileToComment.txt | - | name | My third comment to be found | - And search result "1" contains - | type | comment | - | comment | My second comment to be found that happens to be more … | - | authorId | user0 | - | authorName | user0 | - | path | sharedFileToComment.txt | - | fileName | sharedFileToComment.txt | - | name | My second comment to be found that happens to be more verbose than the others and thus should be ellipsized | - And search result "2" contains - | type | comment | - | comment | Other's first comment to be found | - | authorId | user1 | - | authorName | user1 | - | path | sharedFileToComment.txt | - | fileName | sharedFileToComment.txt | - | name | Other's first comment to be found | - And search result "3" contains - | type | comment | - | comment | Other's second comment to be found | - | authorId | user1 | - | authorName | user1 | - | path | mySharedFileToComment.txt | - | fileName | mySharedFileToComment.txt | - | name | Other's second comment to be found | - And search result "4" contains - | type | comment | - | comment | My first comment to be found | - | authorId | user0 | - | authorName | user0 | - | path | mySharedFileToComment.txt | - | fileName | mySharedFileToComment.txt | - | name | My first comment to be found | - And search result "5" contains - | type | comment | - | comment | My first comment to be found | - | authorId | user0 | - | authorName | user0 | - | path | myFileToComment.txt | - | fileName | myFileToComment.txt | - | name | My first comment to be found | - - Scenario: Search comment with a query that also matches a file name - Given user "user0" exists - And User "user0" uploads file "data/textfile.txt" to "/myFileToComment.txt" - And "user0" posts a comment with content "A comment in myFileToComment.txt" on the file named "/myFileToComment.txt" it should return "201" - When Logging in using web as "user0" - And searching for "myFileToComment" in app "files" - Then the list of search results has "2" results - And search result "0" contains - | type | file | - | path | /myFileToComment.txt | - | name | myFileToComment.txt | - And search result "1" contains - | type | comment | - | comment | A comment in myFileToComment.txt | - | authorId | user0 | - | authorName | user0 | - | path | myFileToComment.txt | - | fileName | myFileToComment.txt | - | name | A comment in myFileToComment.txt | diff --git a/build/integration/comments_features/comments.feature b/build/integration/comments_features/comments.feature index 0f3a4cc75cf..33eb154b147 100644 --- a/build/integration/comments_features/comments.feature +++ b/build/integration/comments_features/comments.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: comments Scenario: Creating a comment on a file belonging to myself Given user "user0" exists diff --git a/build/integration/composer.json b/build/integration/composer.json index 7ab9da29e4a..98e093a7e69 100644 --- a/build/integration/composer.json +++ b/build/integration/composer.json @@ -1,16 +1,16 @@ { "config": { "platform": { - "php": "8.0.2" + "php": "8.1" }, "sort-packages": true }, "require-dev": { - "behat/behat": "^3.14", + "behat/behat": "^3.15", "dms/phpunit-arraysubset-asserts": "^0.5", - "guzzlehttp/guzzle": "^7.8", + "guzzlehttp/guzzle": "^7.9", "phpunit/phpunit": "^9.6", - "sabre/dav": "^4.6", - "symfony/event-dispatcher": "^5.4" + "sabre/dav": "^4.7", + "symfony/event-dispatcher": "^6.4" } } diff --git a/build/integration/composer.lock b/build/integration/composer.lock index b9ab218baeb..cc8427c78eb 100644 --- a/build/integration/composer.lock +++ b/build/integration/composer.lock @@ -4,42 +4,46 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a1099632419635a7a22336e2ccf1c8db", + "content-hash": "922eb11ee2ecd8426779897121fad75d", "packages": [], "packages-dev": [ { "name": "behat/behat", - "version": "v3.14.0", + "version": "v3.23.0", "source": { "type": "git", "url": "https://github.com/Behat/Behat.git", - "reference": "2a3832d9cb853a794af3a576f9e524ae460f3340" + "reference": "c465af8756adaaa6d962c3176a0a6c594361809b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Behat/zipball/2a3832d9cb853a794af3a576f9e524ae460f3340", - "reference": "2a3832d9cb853a794af3a576f9e524ae460f3340", + "url": "https://api.github.com/repos/Behat/Behat/zipball/c465af8756adaaa6d962c3176a0a6c594361809b", + "reference": "c465af8756adaaa6d962c3176a0a6c594361809b", "shasum": "" }, "require": { - "behat/gherkin": "^4.9.0", - "behat/transliterator": "^1.2", + "behat/gherkin": "^4.12.0", + "composer-runtime-api": "^2.2", + "composer/xdebug-handler": "^1.4 || ^2.0 || ^3.0", "ext-mbstring": "*", - "php": "^7.2 || ^8.0", + "nikic/php-parser": "^4.19.2 || ^5.2", + "php": "8.1.* || 8.2.* || 8.3.* || 8.4.* ", "psr/container": "^1.0 || ^2.0", - "symfony/config": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "symfony/console": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "symfony/dependency-injection": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "symfony/event-dispatcher": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "symfony/translation": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "symfony/yaml": "^4.4 || ^5.0 || ^6.0 || ^7.0" + "symfony/config": "^5.4 || ^6.4 || ^7.0", + "symfony/console": "^5.4 || ^6.4 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0", + "symfony/translation": "^5.4 || ^6.4 || ^7.0", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0" }, "require-dev": { - "herrera-io/box": "~1.6.1", - "phpspec/prophecy": "^1.15", - "phpunit/phpunit": "^8.5 || ^9.0", - "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "vimeo/psalm": "^4.8" + "friendsofphp/php-cs-fixer": "^3.68", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^9.6", + "rector/rector": "^2.0", + "sebastian/diff": "^4.0", + "symfony/polyfill-php84": "^1.31", + "symfony/process": "^5.4 || ^6.4 || ^7.0" }, "suggest": { "ext-dom": "Needed to output test results in JUnit format." @@ -58,7 +62,9 @@ "Behat\\Hook\\": "src/Behat/Hook/", "Behat\\Step\\": "src/Behat/Step/", "Behat\\Behat\\": "src/Behat/Behat/", - "Behat\\Testwork\\": "src/Behat/Testwork/" + "Behat\\Config\\": "src/Behat/Config/", + "Behat\\Testwork\\": "src/Behat/Testwork/", + "Behat\\Transformation\\": "src/Behat/Transformation/" } }, "notification-url": "https://packagist.org/downloads/", @@ -73,7 +79,7 @@ } ], "description": "Scenario-oriented BDD framework for PHP", - "homepage": "http://behat.org/", + "homepage": "https://behat.org/", "keywords": [ "Agile", "BDD", @@ -90,31 +96,37 @@ ], "support": { "issues": "https://github.com/Behat/Behat/issues", - "source": "https://github.com/Behat/Behat/tree/v3.14.0" + "source": "https://github.com/Behat/Behat/tree/v3.23.0" }, - "time": "2023-12-09T13:55:02+00:00" + "time": "2025-07-15T16:58:54+00:00" }, { "name": "behat/gherkin", - "version": "v4.9.0", + "version": "v4.14.0", "source": { "type": "git", "url": "https://github.com/Behat/Gherkin.git", - "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4" + "reference": "34c9b59c59355a7b4c53b9f041c8dbd1c8acc3b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Gherkin/zipball/0bc8d1e30e96183e4f36db9dc79caead300beff4", - "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/34c9b59c59355a7b4c53b9f041c8dbd1c8acc3b4", + "reference": "34c9b59c59355a7b4c53b9f041c8dbd1c8acc3b4", "shasum": "" }, "require": { - "php": "~7.2|~8.0" + "composer-runtime-api": "^2.2", + "php": "8.1.* || 8.2.* || 8.3.* || 8.4.*" }, "require-dev": { - "cucumber/cucumber": "dev-gherkin-22.0.0", - "phpunit/phpunit": "~8|~9", - "symfony/yaml": "~3|~4|~5" + "cucumber/gherkin-monorepo": "dev-gherkin-v32.1.1", + "friendsofphp/php-cs-fixer": "^3.65", + "mikey179/vfsstream": "^1.6", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^2", + "phpstan/phpstan-phpunit": "^2", + "phpunit/phpunit": "^10.5", + "symfony/yaml": "^5.4 || ^6.4 || ^7.0" }, "suggest": { "symfony/yaml": "If you want to parse features, represented in YAML files" @@ -126,8 +138,8 @@ } }, "autoload": { - "psr-0": { - "Behat\\Gherkin": "src/" + "psr-4": { + "Behat\\Gherkin\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -138,11 +150,11 @@ { "name": "Konstantin Kudryashov", "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "homepage": "https://everzet.com" } ], "description": "Gherkin DSL parser for PHP", - "homepage": "http://behat.org/", + "homepage": "https://behat.org/", "keywords": [ "BDD", "Behat", @@ -153,58 +165,154 @@ ], "support": { "issues": "https://github.com/Behat/Gherkin/issues", - "source": "https://github.com/Behat/Gherkin/tree/v4.9.0" + "source": "https://github.com/Behat/Gherkin/tree/v4.14.0" }, - "time": "2021-10-12T13:05:09+00:00" + "time": "2025-05-23T15:06:40+00:00" }, { - "name": "behat/transliterator", - "version": "v1.5.0", + "name": "composer/pcre", + "version": "3.3.2", "source": { "type": "git", - "url": "https://github.com/Behat/Transliterator.git", - "reference": "baac5873bac3749887d28ab68e2f74db3a4408af" + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Transliterator/zipball/baac5873bac3749887d28ab68e2f74db3a4408af", - "reference": "baac5873bac3749887d28ab68e2f74db3a4408af", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", "shasum": "" }, "require": { - "php": ">=7.2" + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" }, "require-dev": { - "chuyskywalker/rolling-curl": "^3.1", - "php-yaoi/php-yaoi": "^1.0", - "phpunit/phpunit": "^8.5.25 || ^9.5.19" + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" }, "type": "library", "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, "branch-alias": { - "dev-master": "1.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { "psr-4": { - "Behat\\Transliterator\\": "src/Behat/Transliterator" + "Composer\\Pcre\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Artistic-1.0" + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } ], - "description": "String transliterator", + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", "keywords": [ - "i18n", - "slug", - "transliterator" + "PCRE", + "preg", + "regex", + "regular expression" ], "support": { - "issues": "https://github.com/Behat/Transliterator/issues", - "source": "https://github.com/Behat/Transliterator/tree/v1.5.0" + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" }, - "time": "2022-03-30T09:27:43+00:00" + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-12T16:29:46+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-05-06T16:37:16+00:00" }, { "name": "dms/phpunit-arraysubset-asserts", @@ -252,30 +360,30 @@ }, { "name": "doctrine/instantiator", - "version": "1.5.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^11", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -302,7 +410,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -318,26 +426,26 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:15:36+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.8.1", + "version": "7.9.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", - "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.1", - "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -348,9 +456,9 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "guzzle/client-integration-tests": "3.0.2", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -428,7 +536,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + "source": "https://github.com/guzzle/guzzle/tree/7.9.3" }, "funding": [ { @@ -444,20 +552,20 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:35:24+00:00" + "time": "2025-03-27T13:37:11+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.0.2", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", - "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", "shasum": "" }, "require": { @@ -465,7 +573,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.36 || ^9.6.15" + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "type": "library", "extra": { @@ -511,7 +619,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.2" + "source": "https://github.com/guzzle/promises/tree/2.2.0" }, "funding": [ { @@ -527,20 +635,20 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:19:20+00:00" + "time": "2025-03-27T13:27:01+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.6.2", + "version": "2.7.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", - "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", "shasum": "" }, "require": { @@ -555,8 +663,8 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.36 || ^9.6.15" + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -627,7 +735,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.2" + "source": "https://github.com/guzzle/psr7/tree/2.7.1" }, "funding": [ { @@ -643,20 +751,20 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:05:35+00:00" + "time": "2025-03-27T12:30:47+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { @@ -664,11 +772,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -694,7 +803,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { @@ -702,20 +811,20 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-06-12T14:39:25+00:00" }, { "name": "nikic/php-parser", - "version": "v5.0.2", + "version": "v5.5.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", "shasum": "" }, "require": { @@ -726,7 +835,7 @@ }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -758,9 +867,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" }, - "time": "2024-03-05T20:51:40+00:00" + "time": "2025-05-31T08:24:38+00:00" }, { "name": "phar-io/manifest", @@ -882,35 +991,35 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.31", + "version": "9.2.32", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.18 || ^5.0", + "nikic/php-parser": "^4.19.1 || ^5.1.0", "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.6" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -919,7 +1028,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "9.2.x-dev" } }, "autoload": { @@ -948,7 +1057,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" }, "funding": [ { @@ -956,7 +1065,7 @@ "type": "github" } ], - "time": "2024-03-02T06:37:42+00:00" + "time": "2024-08-22T04:23:01+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1201,45 +1310,45 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.18", + "version": "9.6.21", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "32c2c2d6580b1d8ab3c10b1e9e4dc263cc69bb04" + "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/32c2c2d6580b1d8ab3c10b1e9e4dc263cc69bb04", - "reference": "32c2c2d6580b1d8ab3c10b1e9e4dc263cc69bb04", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", + "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1 || ^2", + "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-code-coverage": "^9.2.32", + "phpunit/php-file-iterator": "^3.0.6", "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", "sebastian/version": "^3.0.2" }, "suggest": { @@ -1284,7 +1393,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.18" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.21" }, "funding": [ { @@ -1300,7 +1409,7 @@ "type": "tidelift" } ], - "time": "2024-03-21T12:07:32+00:00" + "time": "2024-09-19T10:50:18+00:00" }, { "name": "psr/container", @@ -1459,20 +1568,20 @@ }, { "name": "psr/http-factory", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=7.0.0", + "php": ">=7.1", "psr/http-message": "^1.0 || ^2.0" }, "type": "library", @@ -1496,7 +1605,7 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -1508,9 +1617,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2023-04-10T20:10:41+00:00" + "time": "2024-04-15T12:06:14+00:00" }, { "name": "psr/http-message", @@ -1567,16 +1676,16 @@ }, { "name": "psr/log", - "version": "3.0.0", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { @@ -1611,9 +1720,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2021-07-14T16:46:02+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "ralouphie/getallheaders", @@ -1661,16 +1770,16 @@ }, { "name": "sabre/dav", - "version": "4.6.0", + "version": "4.7.0", "source": { "type": "git", "url": "https://github.com/sabre-io/dav.git", - "reference": "554145304b4a026477d130928d16e626939b0b2a" + "reference": "074373bcd689a30bcf5aaa6bbb20a3395964ce7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/dav/zipball/554145304b4a026477d130928d16e626939b0b2a", - "reference": "554145304b4a026477d130928d16e626939b0b2a", + "url": "https://api.github.com/repos/sabre-io/dav/zipball/074373bcd689a30bcf5aaa6bbb20a3395964ce7a", + "reference": "074373bcd689a30bcf5aaa6bbb20a3395964ce7a", "shasum": "" }, "require": { @@ -1740,29 +1849,29 @@ "issues": "https://github.com/sabre-io/dav/issues", "source": "https://github.com/fruux/sabre-dav" }, - "time": "2023-12-11T13:01:23+00:00" + "time": "2024-10-29T11:46:02+00:00" }, { "name": "sabre/event", - "version": "5.1.4", + "version": "5.1.7", "source": { "type": "git", "url": "https://github.com/sabre-io/event.git", - "reference": "d7da22897125d34d7eddf7977758191c06a74497" + "reference": "86d57e305c272898ba3c28e9bd3d65d5464587c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/event/zipball/d7da22897125d34d7eddf7977758191c06a74497", - "reference": "d7da22897125d34d7eddf7977758191c06a74497", + "url": "https://api.github.com/repos/sabre-io/event/zipball/86d57e305c272898ba3c28e9bd3d65d5464587c2", + "reference": "86d57e305c272898ba3c28e9bd3d65d5464587c2", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "~2.17.1", + "friendsofphp/php-cs-fixer": "~2.17.1||^3.63", "phpstan/phpstan": "^0.12", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.0" + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6" }, "type": "library", "autoload": { @@ -1806,20 +1915,20 @@ "issues": "https://github.com/sabre-io/event/issues", "source": "https://github.com/fruux/sabre-event" }, - "time": "2021-11-04T06:51:17+00:00" + "time": "2024-08-27T11:23:05+00:00" }, { "name": "sabre/http", - "version": "5.1.10", + "version": "5.1.12", "source": { "type": "git", "url": "https://github.com/sabre-io/http.git", - "reference": "f9f3d1fba8916fa2f4ec25636c4fedc26cb94e02" + "reference": "dedff73f3995578bc942fa4c8484190cac14f139" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/http/zipball/f9f3d1fba8916fa2f4ec25636c4fedc26cb94e02", - "reference": "f9f3d1fba8916fa2f4ec25636c4fedc26cb94e02", + "url": "https://api.github.com/repos/sabre-io/http/zipball/dedff73f3995578bc942fa4c8484190cac14f139", + "reference": "dedff73f3995578bc942fa4c8484190cac14f139", "shasum": "" }, "require": { @@ -1831,9 +1940,9 @@ "sabre/uri": "^2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "~2.17.1", + "friendsofphp/php-cs-fixer": "~2.17.1||^3.63", "phpstan/phpstan": "^0.12", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.0" + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6" }, "suggest": { "ext-curl": " to make http requests with the Client class" @@ -1869,31 +1978,31 @@ "issues": "https://github.com/sabre-io/http/issues", "source": "https://github.com/fruux/sabre-http" }, - "time": "2023-08-18T01:55:28+00:00" + "time": "2024-08-27T16:07:41+00:00" }, { "name": "sabre/uri", - "version": "2.3.3", + "version": "2.3.4", "source": { "type": "git", "url": "https://github.com/sabre-io/uri.git", - "reference": "7e0e7dfd0b7e14346a27eabd66e843a6e7f1812b" + "reference": "b76524c22de90d80ca73143680a8e77b1266c291" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/uri/zipball/7e0e7dfd0b7e14346a27eabd66e843a6e7f1812b", - "reference": "7e0e7dfd0b7e14346a27eabd66e843a6e7f1812b", + "url": "https://api.github.com/repos/sabre-io/uri/zipball/b76524c22de90d80ca73143680a8e77b1266c291", + "reference": "b76524c22de90d80ca73143680a8e77b1266c291", "shasum": "" }, "require": { "php": "^7.4 || ^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.17", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^1.10", - "phpstan/phpstan-phpunit": "^1.3", - "phpstan/phpstan-strict-rules": "^1.5", + "friendsofphp/php-cs-fixer": "^3.63", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^1.12", + "phpstan/phpstan-phpunit": "^1.4", + "phpstan/phpstan-strict-rules": "^1.6", "phpunit/phpunit": "^9.6" }, "type": "library", @@ -1929,20 +2038,20 @@ "issues": "https://github.com/sabre-io/uri/issues", "source": "https://github.com/fruux/sabre-uri" }, - "time": "2023-06-09T06:54:04+00:00" + "time": "2024-08-27T12:18:16+00:00" }, { "name": "sabre/vobject", - "version": "4.5.4", + "version": "4.5.6", "source": { "type": "git", "url": "https://github.com/sabre-io/vobject.git", - "reference": "a6d53a3e5bec85ed3dd78868b7de0f5b4e12f772" + "reference": "900266bb3bd448a9f7f41f82344ad0aba237cb27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/vobject/zipball/a6d53a3e5bec85ed3dd78868b7de0f5b4e12f772", - "reference": "a6d53a3e5bec85ed3dd78868b7de0f5b4e12f772", + "url": "https://api.github.com/repos/sabre-io/vobject/zipball/900266bb3bd448a9f7f41f82344ad0aba237cb27", + "reference": "900266bb3bd448a9f7f41f82344ad0aba237cb27", "shasum": "" }, "require": { @@ -1952,9 +2061,9 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "~2.17.1", - "phpstan/phpstan": "^0.12", + "phpstan/phpstan": "^0.12 || ^1.11", "phpunit/php-invoker": "^2.0 || ^3.1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.0" + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6" }, "suggest": { "hoa/bench": "If you would like to run the benchmark scripts" @@ -2033,20 +2142,20 @@ "issues": "https://github.com/sabre-io/vobject/issues", "source": "https://github.com/fruux/sabre-vobject" }, - "time": "2023-11-09T12:54:37+00:00" + "time": "2024-10-14T11:53:54+00:00" }, { "name": "sabre/xml", - "version": "2.2.6", + "version": "2.2.11", "source": { "type": "git", "url": "https://github.com/sabre-io/xml.git", - "reference": "9cde7cdab1e50893cc83b037b40cd47bfde42a2b" + "reference": "01a7927842abf3e10df3d9c2d9b0cc9d813a3fcc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/xml/zipball/9cde7cdab1e50893cc83b037b40cd47bfde42a2b", - "reference": "9cde7cdab1e50893cc83b037b40cd47bfde42a2b", + "url": "https://api.github.com/repos/sabre-io/xml/zipball/01a7927842abf3e10df3d9c2d9b0cc9d813a3fcc", + "reference": "01a7927842abf3e10df3d9c2d9b0cc9d813a3fcc", "shasum": "" }, "require": { @@ -2058,9 +2167,9 @@ "sabre/uri": ">=1.0,<3.0.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "~2.17.1", + "friendsofphp/php-cs-fixer": "~2.17.1||3.63.2", "phpstan/phpstan": "^0.12", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.0" + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6" }, "type": "library", "autoload": { @@ -2102,7 +2211,7 @@ "issues": "https://github.com/sabre-io/xml/issues", "source": "https://github.com/fruux/sabre-xml" }, - "time": "2023-06-28T12:56:05+00:00" + "time": "2024-09-06T07:37:46+00:00" }, { "name": "sebastian/cli-parser", @@ -3069,37 +3178,34 @@ }, { "name": "symfony/config", - "version": "v6.0.19", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "db4fc45c24e0c3e2198e68ada9d7f90daa1f97e3" + "reference": "af5917a3b1571f54689e56677a3f06440d2fe4c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/db4fc45c24e0c3e2198e68ada9d7f90daa1f97e3", - "reference": "db4fc45c24e0c3e2198e68ada9d7f90daa1f97e3", + "url": "https://api.github.com/repos/symfony/config/zipball/af5917a3b1571f54689e56677a3f06440d2fe4c7", + "reference": "af5917a3b1571f54689e56677a3f06440d2fe4c7", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/filesystem": "^5.4|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php81": "^1.22" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/filesystem": "^5.4|^6.0|^7.0", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { - "symfony/finder": "<4.4" + "symfony/finder": "<5.4", + "symfony/service-contracts": "<2.5" }, "require-dev": { - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/messenger": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -3127,7 +3233,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v6.0.19" + "source": "https://github.com/symfony/config/tree/v6.4.22" }, "funding": [ { @@ -3143,27 +3249,28 @@ "type": "tidelift" } ], - "time": "2023-01-09T04:36:00+00:00" + "time": "2025-05-14T06:00:01+00:00" }, { "name": "symfony/console", - "version": "v6.0.19", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed" + "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c3ebc83d031b71c39da318ca8b7a07ecc67507ed", - "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed", + "url": "https://api.github.com/repos/symfony/console/zipball/9056771b8eca08d026cd3280deeec3cfd99c4d93", + "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.4|^6.0" + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.0" }, "conflict": { "symfony/dependency-injection": "<5.4", @@ -3177,18 +3284,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -3217,12 +3322,12 @@ "homepage": "https://symfony.com", "keywords": [ "cli", - "command line", + "command-line", "console", "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.0.19" + "source": "https://github.com/symfony/console/tree/v6.4.23" }, "funding": [ { @@ -3238,34 +3343,34 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2025-06-27T19:37:22+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.0.20", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "359806e1adebd1c43e18e5ea22acd14bef7fcf8c" + "reference": "0d9f24f3de0a83573fce5c9ed025d6306c6e166b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/359806e1adebd1c43e18e5ea22acd14bef7fcf8c", - "reference": "359806e1adebd1c43e18e5ea22acd14bef7fcf8c", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/0d9f24f3de0a83573fce5c9ed025d6306c6e166b", + "reference": "0d9f24f3de0a83573fce5c9ed025d6306c6e166b", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php81": "^1.22", - "symfony/service-contracts": "^1.1.6|^2.0|^3.0" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/service-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4.20|^7.2.5" }, "conflict": { "ext-psr": "<1.1|>=2", - "symfony/config": "<5.4", + "symfony/config": "<6.1", "symfony/finder": "<5.4", - "symfony/proxy-manager-bridge": "<5.4", + "symfony/proxy-manager-bridge": "<6.3", "symfony/yaml": "<5.4" }, "provide": { @@ -3273,16 +3378,9 @@ "symfony/service-implementation": "1.1|2.0|3.0" }, "require-dev": { - "symfony/config": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" + "symfony/config": "^6.1|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -3310,7 +3408,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.0.20" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.23" }, "funding": [ { @@ -3326,33 +3424,33 @@ "type": "tidelift" } ], - "time": "2023-01-30T15:41:07+00:00" + "time": "2025-06-23T06:49:06+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.0.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", - "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -3377,7 +3475,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -3393,48 +3491,43 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.4.34", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "e3bca343efeb613f843c254e7718ef17c9bdf7a3" + "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e3bca343efeb613f843c254e7718ef17c9bdf7a3", - "reference": "e3bca343efeb613f843c254e7718ef17c9bdf7a3", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", + "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<4.4" + "symfony/dependency-injection": "<5.4", + "symfony/service-contracts": "<2.5" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" + "symfony/event-dispatcher-implementation": "2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -3462,7 +3555,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.34" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.13" }, "funding": [ { @@ -3478,37 +3571,34 @@ "type": "tidelift" } ], - "time": "2023-12-27T21:12:56+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.0.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7bc61cc2db649b4637d331240c5346dcc7708051" + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7bc61cc2db649b4637d331240c5346dcc7708051", - "reference": "7bc61cc2db649b4637d331240c5346dcc7708051", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -3541,7 +3631,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" }, "funding": [ { @@ -3557,27 +3647,30 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/filesystem", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "3d49eec03fda1f0fc19b7349fbbe55ebc1004214" + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/3d49eec03fda1f0fc19b7349fbbe55ebc1004214", - "reference": "3d49eec03fda1f0fc19b7349fbbe55ebc1004214", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4856c9cf585d5a0313d8d35afd681a526f038dd3", + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, + "require-dev": { + "symfony/process": "^5.4|^6.4|^7.0" + }, "type": "library", "autoload": { "psr-4": { @@ -3604,7 +3697,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.0.19" + "source": "https://github.com/symfony/filesystem/tree/v6.4.13" }, "funding": [ { @@ -3620,24 +3713,24 @@ "type": "tidelift" } ], - "time": "2023-01-20T17:44:14+00:00" + "time": "2024-10-25T15:07:50+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.28.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -3647,12 +3740,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3686,7 +3776,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" }, "funding": [ { @@ -3702,36 +3792,33 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3767,7 +3854,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" }, "funding": [ { @@ -3783,36 +3870,33 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3851,7 +3935,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" }, "funding": [ { @@ -3867,24 +3951,25 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-iconv": "*", + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -3894,12 +3979,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3934,169 +4016,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-28T09:04:16+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-php81", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -4112,46 +4032,47 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.0.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d78d39c1599bd1188b8e26bb341da52c3c6d8a66", - "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { - "php": ">=8.0.2", - "psr/container": "^2.0" + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4178,7 +4099,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -4194,37 +4115,38 @@ "type": "tidelift" } ], - "time": "2022-05-30T19:17:58+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { "name": "symfony/string", - "version": "v6.0.19", + "version": "v6.4.21", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a" + "reference": "73e2c6966a5aef1d4892873ed5322245295370c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/d9e72497367c23e08bf94176d2be45b00a9d232a", - "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a", + "url": "https://api.github.com/repos/symfony/string/zipball/73e2c6966a5aef1d4892873ed5322245295370c6", + "reference": "73e2c6966a5aef1d4892873ed5322245295370c6", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/translation-contracts": "^2.0|^3.0", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -4263,7 +4185,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.0.19" + "source": "https://github.com/symfony/string/tree/v6.4.21" }, "funding": [ { @@ -4279,32 +4201,35 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2025-04-18T15:23:29+00:00" }, { "name": "symfony/translation", - "version": "v6.0.19", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f" + "reference": "de8afa521e04a5220e9e58a1dc99971ab7cac643" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", - "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", + "url": "https://api.github.com/repos/symfony/translation/zipball/de8afa521e04a5220e9e58a1dc99971ab7cac643", + "reference": "de8afa521e04a5220e9e58a1dc99971ab7cac643", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.3|^3.0" + "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { "symfony/config": "<5.4", "symfony/console": "<5.4", "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", "symfony/twig-bundle": "<5.4", "symfony/yaml": "<5.4" }, @@ -4312,22 +4237,19 @@ "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { + "nikic/php-parser": "^4.18|^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2.0|^3.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/intl": "^5.4|^6.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/service-contracts": "^1.1.2|^2|^3", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "psr/log-implementation": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -4358,7 +4280,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.0.19" + "source": "https://github.com/symfony/translation/tree/v6.4.23" }, "funding": [ { @@ -4374,42 +4296,42 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2025-06-26T21:24:02+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.0.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282" + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/acbfbb274e730e5a0236f619b6168d9dedb3e282", - "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", "shasum": "" }, "require": { - "php": ">=8.0.2" - }, - "suggest": { - "symfony/translation-implementation": "" + "php": ">=8.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Translation\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4436,7 +4358,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" }, "funding": [ { @@ -4452,34 +4374,109 @@ "type": "tidelift" } ], - "time": "2022-06-27T17:10:44+00:00" + "time": "2024-09-27T08:32:26+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v6.4.22", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "f28cf841f5654955c9f88ceaf4b9dc29571988a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/f28cf841f5654955c9f88ceaf4b9dc29571988a9", + "reference": "f28cf841f5654955c9f88ceaf4b9dc29571988a9", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "require-dev": { + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "lazy-loading", + "proxy", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v6.4.22" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-05-14T13:00:13+00:00" }, { "name": "symfony/yaml", - "version": "v6.0.19", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "deec3a812a0305a50db8ae689b183f43d915c884" + "reference": "93e29e0deb5f1b2e360adfb389a20d25eb81a27b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/deec3a812a0305a50db8ae689b183f43d915c884", - "reference": "deec3a812a0305a50db8ae689b183f43d915c884", + "url": "https://api.github.com/repos/symfony/yaml/zipball/93e29e0deb5f1b2e360adfb389a20d25eb81a27b", + "reference": "93e29e0deb5f1b2e360adfb389a20d25eb81a27b", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8" }, "conflict": { "symfony/console": "<5.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "symfony/console": "^5.4|^6.0|^7.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -4510,7 +4507,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.0.19" + "source": "https://github.com/symfony/yaml/tree/v6.4.23" }, "funding": [ { @@ -4526,7 +4523,7 @@ "type": "tidelift" } ], - "time": "2023-01-11T11:50:03+00:00" + "time": "2025-06-03T06:46:12+00:00" }, { "name": "theseer/tokenizer", @@ -4581,13 +4578,13 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], + "platform": {}, + "platform-dev": {}, "platform-overrides": { - "php": "8.0.2" + "php": "8.1" }, "plugin-api-version": "2.6.0" } diff --git a/build/integration/config/behat.yml b/build/integration/config/behat.yml index 8401b841cdd..0a3fe4fd823 100644 --- a/build/integration/config/behat.yml +++ b/build/integration/config/behat.yml @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2015-2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only default: autoload: '': "%paths.base%/../features/bootstrap" @@ -13,7 +16,7 @@ default: - "%paths.base%/../features" contexts: - FeatureContext: - baseUrl: http://localhost:8080/ocs/ + baseUrl: http://localhost:8080/ocs/ admin: - admin - admin @@ -36,7 +39,7 @@ default: - "%paths.base%/../comments_features" contexts: - FeatureContext: - baseUrl: http://localhost:8080/ocs/ + baseUrl: http://localhost:8080/ocs/ admin: - admin - admin @@ -58,8 +61,8 @@ default: paths: - "%paths.base%/../dav_features" contexts: - - FeatureContext: - baseUrl: http://localhost:8080/ocs/ + - DavFeatureContext: + baseUrl: http://localhost:8080/ocs/ admin: - admin - admin @@ -77,12 +80,14 @@ default: - CommandLineContext: baseUrl: http://localhost:8080 ocPath: ../../ + - PrincipalPropertySearchContext: + baseUrl: http://localhost:8080 federation: paths: - "%paths.base%/../federation_features" contexts: - FederationContext: - baseUrl: http://localhost:8080/ocs/ + baseUrl: http://localhost:8080/ocs/ admin: - admin - admin @@ -92,7 +97,7 @@ default: - "%paths.base%/../files_features" contexts: - FeatureContext: - baseUrl: http://localhost:8080/ocs/ + baseUrl: http://localhost:8080/ocs/ admin: - admin - admin @@ -110,12 +115,28 @@ default: - CommandLineContext: baseUrl: http://localhost:8080 ocPath: ../../ + - MetadataContext: + baseUrl: http://localhost:8080 + admin: + - admin + - admin + regular_user_password: 123456 + files_conversion: + paths: + - "%paths.base%/../file_conversions" + contexts: + - ConversionsContext: + baseUrl: http://localhost:8080 + admin: + - admin + - admin + regular_user_password: 123456 capabilities: paths: - "%paths.base%/../capabilities_features" contexts: - CapabilitiesContext: - baseUrl: http://localhost:8080/ocs/ + baseUrl: http://localhost:8080/ocs/ admin: - admin - admin @@ -125,7 +146,7 @@ default: - "%paths.base%/../collaboration_features" contexts: - CollaborationContext: - baseUrl: http://localhost:8080/ocs/ + baseUrl: http://localhost:8080/ocs/ admin: - admin - admin @@ -135,7 +156,7 @@ default: - "%paths.base%/../sharees_features" contexts: - ShareesContext: - baseUrl: http://localhost:8080/ocs/ + baseUrl: http://localhost:8080/ocs/ admin: - admin - admin @@ -145,7 +166,7 @@ default: - "%paths.base%/../sharing_features" contexts: - SharingContext: - baseUrl: http://localhost:8080/ocs/ + baseUrl: http://localhost:8080/ocs/ admin: - admin - admin @@ -156,7 +177,7 @@ default: - "%paths.base%/../videoverification_features" contexts: - SharingContext: - baseUrl: http://localhost:8080/ocs/ + baseUrl: http://localhost:8080/ocs/ admin: - admin - admin @@ -167,7 +188,7 @@ default: - "%paths.base%/../setup_features" contexts: - SetupContext: - baseUrl: http://localhost:8080/ocs/ + baseUrl: http://localhost:8080/ocs/ admin: - admin - admin @@ -217,10 +238,41 @@ default: - "%paths.base%/../remoteapi_features" contexts: - FeatureContext: - baseUrl: http://localhost:8080/ocs/ + baseUrl: http://localhost:8080/ocs/ admin: - admin - admin regular_user_password: 123456 - RemoteContext: - remote: http://localhost:8080 + remote: http://localhost:8080 + + ratelimiting: + paths: + - "%paths.base%/../ratelimiting_features" + contexts: + - RateLimitingContext: + baseUrl: http://localhost:8080 + admin: + - admin + - admin + regular_user_password: 123456 + routing: + paths: + - "%paths.base%/../routing_features" + contexts: + - RoutingContext: + baseUrl: http://localhost:8080 + admin: + - admin + - admin + regular_user_password: 123456 + theming: + paths: + - "%paths.base%/../theming_features" + contexts: + - FeatureContext: + baseUrl: http://localhost:8080 + admin: + - admin + - admin + regular_user_password: 123456 diff --git a/build/integration/data/bjoern.vcf.license b/build/integration/data/bjoern.vcf.license new file mode 100644 index 00000000000..314119db8d2 --- /dev/null +++ b/build/integration/data/bjoern.vcf.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors +SPDX-License-Identifier: AGPL-3.0-or-later
\ No newline at end of file diff --git a/build/integration/data/clouds.jpg b/build/integration/data/clouds.jpg Binary files differnew file mode 100644 index 00000000000..2433b140766 --- /dev/null +++ b/build/integration/data/clouds.jpg diff --git a/build/integration/data/clouds.jpg.license b/build/integration/data/clouds.jpg.license new file mode 100644 index 00000000000..d7c54c39d02 --- /dev/null +++ b/build/integration/data/clouds.jpg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: 2019 CHUTTERSNAP <https://unsplash.com/@chuttersnap> <https://unsplash.com/photos/blue-clouds-under-white-sky-9AqIdzEc9pY>" +SPDX-License-Identifier: LicenseRef-Unsplash diff --git a/build/integration/data/coloured-pattern-non-square.png.license b/build/integration/data/coloured-pattern-non-square.png.license new file mode 100644 index 00000000000..39ee0d6eacc --- /dev/null +++ b/build/integration/data/coloured-pattern-non-square.png.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors +SPDX-License-Identifier: AGPL-3.0-or-later
\ No newline at end of file diff --git a/build/integration/data/green-square-256.png.license b/build/integration/data/green-square-256.png.license new file mode 100644 index 00000000000..3811666d42a --- /dev/null +++ b/build/integration/data/green-square-256.png.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors +SPDX-License-Identifier: AGPL-3.0-or-later
\ No newline at end of file diff --git a/build/integration/data/textfile.txt.license b/build/integration/data/textfile.txt.license new file mode 100644 index 00000000000..f7804ddc385 --- /dev/null +++ b/build/integration/data/textfile.txt.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: 2015 ownCloud, Inc. +SPDX-License-Identifier: AGPL-3.0-only
\ No newline at end of file diff --git a/build/integration/dav_features/caldav.feature b/build/integration/dav_features/caldav.feature index f7baf76d4bc..f324f720bbd 100644 --- a/build/integration/dav_features/caldav.feature +++ b/build/integration/dav_features/caldav.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: caldav Scenario: Accessing a not existing calendar of another user Given user "user0" exists @@ -85,3 +87,8 @@ Feature: caldav When "user0" requests principal "users/user0" on the endpoint "/remote.php/dav/principals/" Then The CalDAV response should be multi status And The CalDAV response should contain a property "{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL" with a href value "/remote.php/dav/calendars/user0/MyCalendar2/" + + Scenario: Should create default calendar on first login + Given user "first-login" exists + When "first-login" requests calendar "first-login/personal" on the endpoint "/remote.php/dav/calendars/" + Then The CalDAV HTTP status code should be "207" diff --git a/build/integration/dav_features/carddav.feature b/build/integration/dav_features/carddav.feature index 9c9df6ddd94..35e85639817 100644 --- a/build/integration/dav_features/carddav.feature +++ b/build/integration/dav_features/carddav.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: carddav Scenario: Accessing a not existing addressbook of another user Given user "user0" exists @@ -47,7 +49,6 @@ Feature: carddav |X-Frame-Options|SAMEORIGIN| |X-Permitted-Cross-Domain-Policies|none| |X-Robots-Tag|noindex, nofollow| - |X-XSS-Protection|1; mode=block| Scenario: Exporting the picture of ones own contact Given "admin" creates an addressbook named "MyAddressbook" with statuscode "201" @@ -61,7 +62,6 @@ Feature: carddav |X-Frame-Options|SAMEORIGIN| |X-Permitted-Cross-Domain-Policies|none| |X-Robots-Tag|noindex, nofollow| - |X-XSS-Protection|1; mode=block| Scenario: Create addressbook request for non-existing addressbook of another user Given user "user0" exists @@ -77,3 +77,7 @@ Feature: carddav Then The CardDAV HTTP status code should be "404" And The CardDAV exception is "Sabre\DAV\Exception\NotFound" And The CardDAV error message is "File not found: admin in 'addressbooks'" + + Scenario: Should create default addressbook on first login + Given user "first-login" exists + Then "first-login" requests addressbook "first-login/contacts" with statuscode "207" on the endpoint "/remote.php/dav/addressbooks/users/" diff --git a/build/integration/dav_features/dav-v2-public.feature b/build/integration/dav_features/dav-v2-public.feature new file mode 100644 index 00000000000..a1ff85dc77b --- /dev/null +++ b/build/integration/dav_features/dav-v2-public.feature @@ -0,0 +1,78 @@ +# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +Feature: dav-v2-public + Background: + Given using api version "1" + + Scenario: See note to recipient in public shares + Given using new dav path + And As an "admin" + And user "user0" exists + And user "user1" exists + And As an "user1" + And user "user1" created a folder "/testshare" + And as "user1" creating a share with + | path | testshare | + | shareType | 3 | + | permissions | 1 | + | note | Hello | + And As an "user0" + Given using new public dav path + When Requesting share note on dav endpoint + Then the single response should contain a property "{http://nextcloud.org/ns}note" with value "Hello" + + Scenario: Downloading a file from public share with Ajax header + Given using new dav path + And As an "admin" + And user "user0" exists + And user "user1" exists + And As an "user1" + And user "user1" created a folder "/testshare" + When User "user1" uploads file "data/green-square-256.png" to "/testshare/image.png" + And as "user1" creating a share with + | path | testshare | + | shareType | 3 | + | permissions | 1 | + And As an "user0" + Given using new public dav path + When Downloading public file "/image.png" + Then the downloaded file has the content of "/testshare/image.png" from "user1" data + + # Test that downloading files work to ensure e.g. the viewer works or files can be downloaded + Scenario: Downloading a file from public share without Ajax header and disabled s2s share + Given using new dav path + And As an "admin" + And user "user0" exists + And user "user1" exists + And As an "user1" + And user "user1" created a folder "/testshare" + When User "user1" uploads file "data/green-square-256.png" to "/testshare/image.png" + And as "user1" creating a share with + | path | testshare | + | shareType | 3 | + | permissions | 1 | + And As an "user0" + Given parameter "outgoing_server2server_share_enabled" of app "files_sharing" is set to "no" + Given using new public dav path + When Downloading public file "/image.png" without ajax header + Then the downloaded file has the content of "/testshare/image.png" from "user1" data + + Scenario: Download a folder + Given using new dav path + And As an "admin" + And user "user0" exists + And user "user0" created a folder "/testshare" + And user "user0" created a folder "/testshare/testFolder" + When User "user0" uploads file "data/textfile.txt" to "/testshare/testFolder/text.txt" + When User "user0" uploads file "data/green-square-256.png" to "/testshare/testFolder/image.png" + And as "user0" creating a share with + | path | testshare | + | shareType | 3 | + | permissions | 1 | + And As an "user1" + Given using new public dav path + When Downloading public folder "testFolder" + Then the downloaded file is a zip file + Then the downloaded zip file contains a folder named "testFolder/" + And the downloaded zip file contains a file named "testFolder/text.txt" with the contents of "/testshare/testFolder/text.txt" from "user0" data + And the downloaded zip file contains a file named "testFolder/image.png" with the contents of "/testshare/testFolder/image.png" from "user0" data diff --git a/build/integration/dav_features/dav-v2.feature b/build/integration/dav_features/dav-v2.feature index a3ac59578e9..dbd2295497f 100644 --- a/build/integration/dav_features/dav-v2.feature +++ b/build/integration/dav_features/dav-v2.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + Feature: dav-v2 Background: Given using api version "1" @@ -9,6 +12,16 @@ Feature: dav-v2 When User "user0" moves file "/textfile0.txt" to "/FOLDER/textfile0.txt" Then the HTTP status code should be "201" + Scenario: Moving and overwriting it's parent + Given using new dav path + And As an "admin" + And user "user0" exists + And As an "user0" + And user "user0" created a folder "/test" + And user "user0" created a folder "/test/test" + When User "user0" moves file "/test/test" to "/test" + Then the HTTP status code should be "403" + Scenario: download a file with range using new endpoint Given using new dav path And As an "admin" @@ -28,7 +41,6 @@ Feature: dav-v2 |X-Frame-Options|SAMEORIGIN| |X-Permitted-Cross-Domain-Policies|none| |X-Robots-Tag|noindex, nofollow| - |X-XSS-Protection|1; mode=block| And Downloaded content should start with "Welcome to your Nextcloud account!" Scenario: Doing a GET with a web login should work without CSRF token on the new backend @@ -43,6 +55,20 @@ Feature: dav-v2 Then Downloaded content should start with "Welcome to your Nextcloud account!" Then the HTTP status code should be "200" + Scenario: Download a folder + Given using new dav path + And As an "admin" + And user "user0" exists + And user "user0" created a folder "/testFolder" + When User "user0" uploads file "data/textfile.txt" to "/testFolder/text.txt" + When User "user0" uploads file "data/green-square-256.png" to "/testFolder/image.png" + And As an "user0" + When Downloading folder "/testFolder" + Then the downloaded file is a zip file + Then the downloaded zip file contains a folder named "testFolder/" + And the downloaded zip file contains a file named "testFolder/text.txt" with the contents of "/testFolder/text.txt" from "user0" data + And the downloaded zip file contains a file named "testFolder/image.png" with the contents of "/testFolder/image.png" from "user0" data + Scenario: Doing a PROPFIND with a web login should not work without CSRF token on the new backend Given Logging in using web as "admin" When Sending a "PROPFIND" to "/remote.php/dav/files/admin/welcome.txt" without requesttoken @@ -76,32 +102,61 @@ Feature: dav-v2 | shareType | 0 | | permissions | 31 | | shareWith | user0 | - And user "user0" accepts last share + And user "user0" accepts last share And As an "user0" When User "user0" uploads file "data/textfile.txt" to "/testquota/asdf.txt" Then the HTTP status code should be "201" + Scenario: Uploading a file with very long filename + Given using new dav path + And As an "admin" + And user "user0" exists + And user "user0" has a quota of "10 MB" + And As an "user0" + When User "user0" uploads file "data/textfile.txt" to "/long-filename-with-250-characters-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.txt" + Then the HTTP status code should be "201" + + Scenario: Uploading a file with a too long filename + Given using new dav path + And As an "admin" + And user "user0" exists + And user "user0" has a quota of "10 MB" + And As an "user0" + When User "user0" uploads file "data/textfile.txt" to "/long-filename-with-251-characters-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.txt" + Then the HTTP status code should be "400" + Scenario: Create a search query on image Given using new dav path And As an "admin" - And user "user0" exists - And As an "user0" - When User "user0" uploads file "data/textfile.txt" to "/testquota/asdf.txt" - Then Image search should work - And the response should be empty - When User "user0" uploads file "data/green-square-256.png" to "/image.png" + And user "user0" exists + And As an "user0" + When User "user0" uploads file "data/textfile.txt" to "/testquota/asdf.txt" + Then Image search should work + And the response should be empty + When User "user0" uploads file "data/green-square-256.png" to "/image.png" Then Image search should work - And the single response should contain a property "{DAV:}getcontenttype" with value "image/png" - - Scenario: Create a search query on favorite - Given using new dav path - And As an "admin" - And user "user0" exists - And As an "user0" - When User "user0" uploads file "data/green-square-256.png" to "/fav_image.png" - Then Favorite search should work - And the response should be empty - When user "user0" favorites element "/fav_image.png" - Then Favorite search should work - And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "1" + And the single response should contain a property "{DAV:}getcontenttype" with value "image/png" + Scenario: Create a search query on favorite + Given using new dav path + And As an "admin" + And user "user0" exists + And As an "user0" + When User "user0" uploads file "data/green-square-256.png" to "/fav_image.png" + Then Favorite search should work + And the response should be empty + When user "user0" favorites element "/fav_image.png" + Then Favorite search should work + And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "1" + + Scenario: Create a search query on favorite + Given using new dav path + And As an "admin" + And user "user0" exists + And As an "user0" + When User "user0" uploads file "data/green-square-256.png" to "/fav_image.png" + Then Favorite search should work + And the response should be empty + When user "user0" favorites element "/fav_image.png" + Then Favorite search should work + And the single response should contain a property "{http://owncloud.org/ns}favorite" with value "1" diff --git a/build/integration/dav_features/principal-property-search.feature b/build/integration/dav_features/principal-property-search.feature new file mode 100644 index 00000000000..b2195489263 --- /dev/null +++ b/build/integration/dav_features/principal-property-search.feature @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +Feature: principal-property-search + Background: + Given user "user0" exists + Given As an "admin" + Given invoking occ with "app:enable --force testing" + + Scenario: Find a principal by a given displayname + When searching for a principal matching "user0" + Then The search HTTP status code should be "207" + And The search response should contain "<d:href>/remote.php/dav/principals/users/user0/</d:href>" diff --git a/build/integration/dav_features/webdav-related.feature b/build/integration/dav_features/webdav-related.feature index 28a0cad619b..12fd3d44c4f 100644 --- a/build/integration/dav_features/webdav-related.feature +++ b/build/integration/dav_features/webdav-related.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: webdav-related Background: Given using api version "1" @@ -36,6 +38,43 @@ Feature: webdav-related Then the HTTP status code should be "204" And Downloaded content when downloading file "/textfile0.txt" with range "bytes=0-6" should be "Welcome" + Scenario: Moving and overwriting it's parent + Given using old dav path + And As an "admin" + And user "user0" exists + And As an "user0" + And user "user0" created a folder "/test" + And user "user0" created a folder "/test/test" + When User "user0" moves file "/test/test" to "/test" + Then the HTTP status code should be "403" + + Scenario: Moving a file from shared folder to root folder + Given using old dav path + And user "user0" exists + And user "user1" exists + And user "user0" created a folder "/testshare" + And User "user0" copies file "/welcome.txt" to "/testshare/welcome.txt" + And as "user0" creating a share with + | path | testshare | + | shareType | 0 | + | shareWith | user1 | + When User "user1" moves file "/testshare/welcome.txt" to "/movedwelcome.txt" + Then As an "user1" + And Downloaded content when downloading file "/movedwelcome.txt" with range "bytes=0-6" should be "Welcome" + + Scenario: Moving a file from root folder to shared folder + Given using old dav path + And user "user0" exists + And user "user1" exists + And user "user0" created a folder "/testshare" + And as "user0" creating a share with + | path | testshare | + | shareType | 0 | + | shareWith | user1 | + When User "user1" moves file "/welcome.txt" to "/testshare/movedwelcome.txt" + Then As an "user1" + And Downloaded content when downloading file "/testshare/movedwelcome.txt" with range "bytes=0-6" should be "Welcome" + Scenario: Moving a file to a folder with no permissions Given using old dav path And As an "admin" @@ -252,7 +291,6 @@ Feature: webdav-related |X-Frame-Options|SAMEORIGIN| |X-Permitted-Cross-Domain-Policies|none| |X-Robots-Tag|noindex, nofollow| - |X-XSS-Protection|1; mode=block| And Downloaded content should start with "Welcome to your Nextcloud account!" Scenario: Doing a GET with a web login should work without CSRF token on the old backend @@ -277,33 +315,6 @@ Feature: webdav-related When Sending a "PROPFIND" to "/remote.php/webdav/welcome.txt" with requesttoken Then the HTTP status code should be "207" - Scenario: Upload chunked file asc - Given user "user0" exists - And user "user0" uploads chunk file "1" of "3" with "AAAAA" to "/myChunkedFile.txt" - And user "user0" uploads chunk file "2" of "3" with "BBBBB" to "/myChunkedFile.txt" - And user "user0" uploads chunk file "3" of "3" with "CCCCC" to "/myChunkedFile.txt" - When As an "user0" - And Downloading file "/myChunkedFile.txt" - Then Downloaded content should be "AAAAABBBBBCCCCC" - - Scenario: Upload chunked file desc - Given user "user0" exists - And user "user0" uploads chunk file "3" of "3" with "CCCCC" to "/myChunkedFile.txt" - And user "user0" uploads chunk file "2" of "3" with "BBBBB" to "/myChunkedFile.txt" - And user "user0" uploads chunk file "1" of "3" with "AAAAA" to "/myChunkedFile.txt" - When As an "user0" - And Downloading file "/myChunkedFile.txt" - Then Downloaded content should be "AAAAABBBBBCCCCC" - - Scenario: Upload chunked file random - Given user "user0" exists - And user "user0" uploads chunk file "2" of "3" with "BBBBB" to "/myChunkedFile.txt" - And user "user0" uploads chunk file "3" of "3" with "CCCCC" to "/myChunkedFile.txt" - And user "user0" uploads chunk file "1" of "3" with "AAAAA" to "/myChunkedFile.txt" - When As an "user0" - And Downloading file "/myChunkedFile.txt" - Then Downloaded content should be "AAAAABBBBBCCCCC" - Scenario: A file that is not shared does not have a share-types property Given user "user0" exists And user "user0" created a folder "/test" @@ -694,7 +705,7 @@ Feature: webdav-related And user "user0" uploads new chunk v2 file "2" to id "chunking-random" And user "user0" uploads new chunk v2 file "4" to id "chunking-random" And user "user0" moves new chunk v2 file with id "chunking-random" - Then the upload should fail on object storage + Then the upload should fail on object storage @s3-multipart Scenario: Upload chunked file with special characters with new chunking v2 diff --git a/build/integration/features/auth.feature b/build/integration/features/auth.feature index 679b2465659..f9c8b7d0e46 100644 --- a/build/integration/features/auth.feature +++ b/build/integration/features/auth.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: auth Background: diff --git a/build/integration/features/avatar.feature b/build/integration/features/avatar.feature index 06135a25693..4c8c37fb98c 100644 --- a/build/integration/features/avatar.feature +++ b/build/integration/features/avatar.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: avatar Background: diff --git a/build/integration/features/bootstrap/Activity.php b/build/integration/features/bootstrap/Activity.php new file mode 100644 index 00000000000..4172776304d --- /dev/null +++ b/build/integration/features/bootstrap/Activity.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +use Behat\Gherkin\Node\TableNode; +use PHPUnit\Framework\Assert; + +trait Activity { + use BasicStructure; + + /** + * @Then last activity should be + * @param TableNode $activity + */ + public function lastActivityIs(TableNode $activity): void { + $this->sendRequestForJSON('GET', '/apps/activity/api/v2/activity'); + $this->theHTTPStatusCodeShouldBe('200'); + $data = json_decode($this->response->getBody()->getContents(), true); + $activities = $data['ocs']['data']; + /* Sort by id */ + uasort($activities, fn ($a, $b) => $a['activity_id'] <=> $b['activity_id']); + $lastActivity = array_pop($activities); + foreach ($activity->getRowsHash() as $key => $value) { + Assert::assertEquals($value, $lastActivity[$key]); + } + } +} diff --git a/build/integration/features/bootstrap/AppConfiguration.php b/build/integration/features/bootstrap/AppConfiguration.php index 740a8b169a6..e8580ed537b 100644 --- a/build/integration/features/bootstrap/AppConfiguration.php +++ b/build/integration/features/bootstrap/AppConfiguration.php @@ -1,29 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Sergio Bertolin <sbertolin@solidgear.es> - * - * @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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Behat\Hook\Scope\AfterScenarioScope; use Behat\Behat\Hook\Scope\BeforeScenarioScope; diff --git a/build/integration/features/bootstrap/Auth.php b/build/integration/features/bootstrap/Auth.php index 8ce72e73b82..aeaade85383 100644 --- a/build/integration/features/bootstrap/Auth.php +++ b/build/integration/features/bootstrap/Auth.php @@ -1,29 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2016 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Kesselberg <mail@danielkesselberg.de> - * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Phil Davis <phil.davis@inf.org> - * @author Robin Appelman <robin@icewind.nl> - * - * @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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ use GuzzleHttp\Client; use GuzzleHttp\Cookie\CookieJar; @@ -224,7 +204,8 @@ trait Auth { * @param bool $remember */ public function aNewBrowserSessionIsStarted($remember = false) { - $loginUrl = substr($this->baseUrl, 0, -5) . '/login'; + $baseUrl = substr($this->baseUrl, 0, -5); + $loginUrl = $baseUrl . '/login'; // Request a new session and extract CSRF token $client = new Client(); $response = $client->get($loginUrl, [ @@ -243,6 +224,9 @@ trait Auth { 'requesttoken' => $this->requestToken, ], 'cookies' => $this->cookieJar, + 'headers' => [ + 'Origin' => $baseUrl, + ], ] ); $this->extracRequestTokenFromResponse($response); diff --git a/build/integration/features/bootstrap/Avatar.php b/build/integration/features/bootstrap/Avatar.php index 6b8e5d88092..beebf1c024a 100644 --- a/build/integration/features/bootstrap/Avatar.php +++ b/build/integration/features/bootstrap/Avatar.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2020, Daniel Calviño Sánchez (danxuliu@gmail.com) - * - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * - * @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: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Gherkin\Node\TableNode; use PHPUnit\Framework\Assert; @@ -26,7 +10,7 @@ use PHPUnit\Framework\Assert; require __DIR__ . '/../../vendor/autoload.php'; trait Avatar { - /** @var string **/ + /** @var string * */ private $lastAvatar; /** @AfterScenario **/ @@ -257,10 +241,10 @@ trait Avatar { } private function isSameColor(array $firstColor, array $secondColor, int $allowedDelta = 1) { - if ($this->isSameColorComponent($firstColor['red'], $secondColor['red'], $allowedDelta) && - $this->isSameColorComponent($firstColor['green'], $secondColor['green'], $allowedDelta) && - $this->isSameColorComponent($firstColor['blue'], $secondColor['blue'], $allowedDelta) && - $this->isSameColorComponent($firstColor['alpha'], $secondColor['alpha'], $allowedDelta)) { + if ($this->isSameColorComponent($firstColor['red'], $secondColor['red'], $allowedDelta) + && $this->isSameColorComponent($firstColor['green'], $secondColor['green'], $allowedDelta) + && $this->isSameColorComponent($firstColor['blue'], $secondColor['blue'], $allowedDelta) + && $this->isSameColorComponent($firstColor['alpha'], $secondColor['alpha'], $allowedDelta)) { return true; } @@ -268,8 +252,8 @@ trait Avatar { } private function isSameColorComponent(int $firstColorComponent, int $secondColorComponent, int $allowedDelta) { - if ($firstColorComponent >= ($secondColorComponent - $allowedDelta) && - $firstColorComponent <= ($secondColorComponent + $allowedDelta)) { + if ($firstColorComponent >= ($secondColorComponent - $allowedDelta) + && $firstColorComponent <= ($secondColorComponent + $allowedDelta)) { return true; } diff --git a/build/integration/features/bootstrap/BasicStructure.php b/build/integration/features/bootstrap/BasicStructure.php index e12a40ac6b4..59a4312913e 100644 --- a/build/integration/features/bootstrap/BasicStructure.php +++ b/build/integration/features/bootstrap/BasicStructure.php @@ -1,40 +1,15 @@ <?php + /** - * @copyright Copyright (c) 2016 Sergio Bertolin <sbertolin@solidgear.es> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Sergio Bertolin <sbertolin@solidgear.es> - * @author Sergio Bertolín <sbertolin@solidgear.es> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Gherkin\Node\TableNode; use GuzzleHttp\Client; use GuzzleHttp\Cookie\CookieJar; use GuzzleHttp\Exception\ClientException; +use GuzzleHttp\Exception\ServerException; use PHPUnit\Framework\Assert; use Psr\Http\Message\ResponseInterface; @@ -45,6 +20,7 @@ trait BasicStructure { use Avatar; use Download; use Mail; + use Theming; /** @var string */ private $currentUser = ''; @@ -147,7 +123,11 @@ trait BasicStructure { * @return string */ public function getOCSResponse($response) { - return simplexml_load_string($response->getBody())->meta[0]->statuscode; + $body = simplexml_load_string((string)$response->getBody()); + if ($body === false) { + throw new \RuntimeException('Could not parse OCS response, body is not valid XML'); + } + return $body->meta[0]->statuscode; } /** @@ -197,6 +177,8 @@ trait BasicStructure { $this->response = $client->request($verb, $fullUrl, $options); } catch (ClientException $ex) { $this->response = $ex->getResponse(); + } catch (ServerException $ex) { + $this->response = $ex->getResponse(); } } @@ -212,8 +194,8 @@ trait BasicStructure { $options = []; if ($this->currentUser === 'admin') { $options['auth'] = ['admin', 'admin']; - } elseif (strpos($this->currentUser, 'guest') !== 0) { - $options['auth'] = [$this->currentUser, self::TEST_PASSWORD]; + } elseif (strpos($this->currentUser, 'anonymous') !== 0) { + $options['auth'] = [$this->currentUser, $this->regularUser]; } if ($body instanceof TableNode) { $fd = $body->getRowsHash(); @@ -306,7 +288,8 @@ trait BasicStructure { * @param string $user */ public function loggingInUsingWebAs($user) { - $loginUrl = substr($this->baseUrl, 0, -5) . '/index.php/login'; + $baseUrl = substr($this->baseUrl, 0, -5); + $loginUrl = $baseUrl . '/index.php/login'; // Request a new session and extract CSRF token $client = new Client(); $response = $client->get( @@ -329,6 +312,9 @@ trait BasicStructure { 'requesttoken' => $this->requestToken, ], 'cookies' => $this->cookieJar, + 'headers' => [ + 'Origin' => $baseUrl, + ], ] ); $this->extracRequestTokenFromResponse($response); @@ -354,7 +340,7 @@ trait BasicStructure { $fd = $body->getRowsHash(); $options['form_params'] = $fd; } elseif ($body) { - $options = array_merge($options, $body); + $options = array_merge_recursive($options, $body); } $client = new Client(); @@ -442,14 +428,14 @@ trait BasicStructure { } public function createFileSpecificSize($name, $size) { - $file = fopen("work/" . "$name", 'w'); + $file = fopen('work/' . "$name", 'w'); fseek($file, $size - 1, SEEK_CUR); fwrite($file, 'a'); // write a dummy char at SIZE position fclose($file); } public function createFileWithText($name, $text) { - $file = fopen("work/" . "$name", 'w'); + $file = fopen('work/' . "$name", 'w'); fwrite($file, $text); fclose($file); } @@ -485,19 +471,19 @@ trait BasicStructure { */ public static function addFilesToSkeleton() { for ($i = 0; $i < 5; $i++) { - file_put_contents("../../core/skeleton/" . "textfile" . "$i" . ".txt", "Nextcloud test text file\n"); + file_put_contents('../../core/skeleton/' . 'textfile' . "$i" . '.txt', "Nextcloud test text file\n"); } - if (!file_exists("../../core/skeleton/FOLDER")) { - mkdir("../../core/skeleton/FOLDER", 0777, true); + if (!file_exists('../../core/skeleton/FOLDER')) { + mkdir('../../core/skeleton/FOLDER', 0777, true); } - if (!file_exists("../../core/skeleton/PARENT")) { - mkdir("../../core/skeleton/PARENT", 0777, true); + if (!file_exists('../../core/skeleton/PARENT')) { + mkdir('../../core/skeleton/PARENT', 0777, true); } - file_put_contents("../../core/skeleton/PARENT/" . "parent.txt", "Nextcloud test text file\n"); - if (!file_exists("../../core/skeleton/PARENT/CHILD")) { - mkdir("../../core/skeleton/PARENT/CHILD", 0777, true); + file_put_contents('../../core/skeleton/PARENT/' . 'parent.txt', "Nextcloud test text file\n"); + if (!file_exists('../../core/skeleton/PARENT/CHILD')) { + mkdir('../../core/skeleton/PARENT/CHILD', 0777, true); } - file_put_contents("../../core/skeleton/PARENT/CHILD/" . "child.txt", "Nextcloud test text file\n"); + file_put_contents('../../core/skeleton/PARENT/CHILD/' . 'child.txt', "Nextcloud test text file\n"); } /** @@ -505,18 +491,18 @@ trait BasicStructure { */ public static function removeFilesFromSkeleton() { for ($i = 0; $i < 5; $i++) { - self::removeFile("../../core/skeleton/", "textfile" . "$i" . ".txt"); + self::removeFile('../../core/skeleton/', 'textfile' . "$i" . '.txt'); } - if (is_dir("../../core/skeleton/FOLDER")) { - rmdir("../../core/skeleton/FOLDER"); + if (is_dir('../../core/skeleton/FOLDER')) { + rmdir('../../core/skeleton/FOLDER'); } - self::removeFile("../../core/skeleton/PARENT/CHILD/", "child.txt"); - if (is_dir("../../core/skeleton/PARENT/CHILD")) { - rmdir("../../core/skeleton/PARENT/CHILD"); + self::removeFile('../../core/skeleton/PARENT/CHILD/', 'child.txt'); + if (is_dir('../../core/skeleton/PARENT/CHILD')) { + rmdir('../../core/skeleton/PARENT/CHILD'); } - self::removeFile("../../core/skeleton/PARENT/", "parent.txt"); - if (is_dir("../../core/skeleton/PARENT")) { - rmdir("../../core/skeleton/PARENT"); + self::removeFile('../../core/skeleton/PARENT/', 'parent.txt'); + if (is_dir('../../core/skeleton/PARENT')) { + rmdir('../../core/skeleton/PARENT'); } } @@ -524,7 +510,7 @@ trait BasicStructure { * @BeforeScenario @local_storage */ public static function removeFilesFromLocalStorageBefore() { - $dir = "./work/local_storage/"; + $dir = './work/local_storage/'; $di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS); $ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST); foreach ($ri as $file) { @@ -536,7 +522,7 @@ trait BasicStructure { * @AfterScenario @local_storage */ public static function removeFilesFromLocalStorageAfter() { - $dir = "./work/local_storage/"; + $dir = './work/local_storage/'; $di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS); $ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST); foreach ($ri as $file) { diff --git a/build/integration/features/bootstrap/CalDavContext.php b/build/integration/features/bootstrap/CalDavContext.php index 7f986542d25..459c35089fa 100644 --- a/build/integration/features/bootstrap/CalDavContext.php +++ b/build/integration/features/bootstrap/CalDavContext.php @@ -1,29 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Phil Davis <phil.davis@inf.org> - * @author Robin Appelman <robin@icewind.nl> - * @author Richard Steinmetz <richard@steinmetz.cloud> - * - * @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-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ require __DIR__ . '/../../vendor/autoload.php'; @@ -32,7 +12,7 @@ use GuzzleHttp\Exception\GuzzleException; use Psr\Http\Message\ResponseInterface; class CalDavContext implements \Behat\Behat\Context\Context { - /** @var string */ + /** @var string */ private $baseUrl; /** @var Client */ private $client; @@ -62,7 +42,7 @@ class CalDavContext implements \Behat\Behat\Context\Context { /** @AfterScenario */ public function afterScenario() { - $davUrl = $this->baseUrl. '/remote.php/dav/calendars/admin/MyCalendar'; + $davUrl = $this->baseUrl . '/remote.php/dav/calendars/admin/MyCalendar'; try { $this->client->delete( $davUrl, @@ -287,7 +267,7 @@ class CalDavContext implements \Behat\Behat\Context\Context { * @param string $name */ public function createsACalendarNamed($user, $name) { - $davUrl = $this->baseUrl . '/remote.php/dav/calendars/'.$user.'/'.$name; + $davUrl = $this->baseUrl . '/remote.php/dav/calendars/' . $user . '/' . $name; $password = ($user === 'admin') ? 'admin' : '123456'; $this->response = $this->client->request( @@ -310,7 +290,7 @@ class CalDavContext implements \Behat\Behat\Context\Context { * @param string $name */ public function publiclySharesTheCalendarNamed($user, $name) { - $davUrl = $this->baseUrl . '/remote.php/dav/calendars/'.$user.'/'.$name; + $davUrl = $this->baseUrl . '/remote.php/dav/calendars/' . $user . '/' . $name; $password = ($user === 'admin') ? 'admin' : '123456'; $this->response = $this->client->request( diff --git a/build/integration/features/bootstrap/CapabilitiesContext.php b/build/integration/features/bootstrap/CapabilitiesContext.php index 4fdfb3e41b0..7d09ab6ddcf 100644 --- a/build/integration/features/bootstrap/CapabilitiesContext.php +++ b/build/integration/features/bootstrap/CapabilitiesContext.php @@ -1,30 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2016 Sergio Bertolin <sbertolin@solidgear.es> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Sergio Bertolin <sbertolin@solidgear.es> - * - * @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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Behat\Context\Context; use Behat\Behat\Context\SnippetAcceptingContext; @@ -44,7 +23,9 @@ class CapabilitiesContext implements Context, SnippetAcceptingContext { * @param \Behat\Gherkin\Node\TableNode|null $formData */ public function checkCapabilitiesResponse(\Behat\Gherkin\Node\TableNode $formData) { - $capabilitiesXML = simplexml_load_string($this->response->getBody())->data->capabilities; + $capabilitiesXML = simplexml_load_string($this->response->getBody()); + Assert::assertNotFalse($capabilitiesXML, 'Failed to fetch capabilities'); + $capabilitiesXML = $capabilitiesXML->data->capabilities; foreach ($formData->getHash() as $row) { $path_to_element = explode('@@@', $row['path_to_element']); @@ -54,9 +35,9 @@ class CapabilitiesContext implements Context, SnippetAcceptingContext { } $answeredValue = (string)$answeredValue; Assert::assertEquals( - $row['value'] === "EMPTY" ? '' : $row['value'], + $row['value'] === 'EMPTY' ? '' : $row['value'], $answeredValue, - "Failed field " . $row['capability'] . " " . $row['path_to_element'] + 'Failed field ' . $row['capability'] . ' ' . $row['path_to_element'] ); } } diff --git a/build/integration/features/bootstrap/CardDavContext.php b/build/integration/features/bootstrap/CardDavContext.php index 80d96215eba..733c98dca02 100644 --- a/build/integration/features/bootstrap/CardDavContext.php +++ b/build/integration/features/bootstrap/CardDavContext.php @@ -1,27 +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 Phil Davis <phil.davis@inf.org> - * @author Robin Appelman <robin@icewind.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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ require __DIR__ . '/../../vendor/autoload.php'; @@ -30,7 +12,7 @@ use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Message\ResponseInterface; class CardDavContext implements \Behat\Behat\Context\Context { - /** @var string */ + /** @var string */ private $baseUrl; /** @var Client */ private $client; @@ -129,7 +111,7 @@ class CardDavContext implements \Behat\Behat\Context\Context { * @throws \Exception */ public function createsAnAddressbookNamedWithStatuscode($user, $addressBook, $statusCode) { - $davUrl = $this->baseUrl . '/remote.php/dav/addressbooks/users/'.$user.'/'.$addressBook; + $davUrl = $this->baseUrl . '/remote.php/dav/addressbooks/users/' . $user . '/' . $addressBook; $password = ($user === 'admin') ? 'admin' : '123456'; $this->response = $this->client->request( @@ -142,7 +124,7 @@ class CardDavContext implements \Behat\Behat\Context\Context { <d:prop> <d:resourcetype> <d:collection />,<card:addressbook /> - </d:resourcetype>,<d:displayname>'.$addressBook.'</d:displayname> + </d:resourcetype>,<d:displayname>' . $addressBook . '</d:displayname> </d:prop> </d:set> </d:mkcol>', @@ -209,7 +191,7 @@ class CardDavContext implements \Behat\Behat\Context\Context { * @Given :user uploads the contact :fileName to the addressbook :addressbook */ public function uploadsTheContactToTheAddressbook($user, $fileName, $addressBook) { - $davUrl = $this->baseUrl . '/remote.php/dav/addressbooks/users/'.$user.'/'.$addressBook . '/' . $fileName; + $davUrl = $this->baseUrl . '/remote.php/dav/addressbooks/users/' . $user . '/' . $addressBook . '/' . $fileName; $password = ($user === 'admin') ? 'admin' : '123456'; $this->response = $this->client->request( @@ -242,7 +224,7 @@ class CardDavContext implements \Behat\Behat\Context\Context { * @When Exporting the picture of contact :fileName from addressbook :addressBook as user :user */ public function whenExportingThePictureOfContactFromAddressbookAsUser($fileName, $addressBook, $user) { - $davUrl = $this->baseUrl . '/remote.php/dav/addressbooks/users/'.$user.'/'.$addressBook . '/' . $fileName . '?photo=true'; + $davUrl = $this->baseUrl . '/remote.php/dav/addressbooks/users/' . $user . '/' . $addressBook . '/' . $fileName . '?photo=true'; $password = ($user === 'admin') ? 'admin' : '123456'; try { @@ -268,7 +250,7 @@ class CardDavContext implements \Behat\Behat\Context\Context { * @When Downloading the contact :fileName from addressbook :addressBook as user :user */ public function whenDownloadingTheContactFromAddressbookAsUser($fileName, $addressBook, $user) { - $davUrl = $this->baseUrl . '/remote.php/dav/addressbooks/users/'.$user.'/'.$addressBook . '/' . $fileName; + $davUrl = $this->baseUrl . '/remote.php/dav/addressbooks/users/' . $user . '/' . $addressBook . '/' . $fileName; $password = ($user === 'admin') ? 'admin' : '123456'; try { diff --git a/build/integration/features/bootstrap/ChecksumsContext.php b/build/integration/features/bootstrap/ChecksumsContext.php index ae44fcb1503..c8abf91127e 100644 --- a/build/integration/features/bootstrap/ChecksumsContext.php +++ b/build/integration/features/bootstrap/ChecksumsContext.php @@ -1,28 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Phil Davis <phil.davis@inf.org> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ require __DIR__ . '/../../vendor/autoload.php'; @@ -30,7 +11,7 @@ use GuzzleHttp\Client; use GuzzleHttp\Message\ResponseInterface; class ChecksumsContext implements \Behat\Behat\Context\Context { - /** @var string */ + /** @var string */ private $baseUrl; /** @var Client */ private $client; @@ -107,7 +88,7 @@ class ChecksumsContext implements \Behat\Behat\Context\Context { */ public function theWebdavResponseShouldHaveAStatusCode($statusCode) { if ((int)$statusCode !== $this->response->getStatusCode()) { - throw new \Exception("Expected $statusCode, got ".$this->response->getStatusCode()); + throw new \Exception("Expected $statusCode, got " . $this->response->getStatusCode()); } } @@ -151,7 +132,7 @@ class ChecksumsContext implements \Behat\Behat\Context\Context { $checksums = $parsed[0]['value'][1]['value'][0]['value'][0]; if ($checksums['value'][0]['value'] !== $checksum) { - throw new \Exception("Expected $checksum, got ".$checksums['value'][0]['value']); + throw new \Exception("Expected $checksum, got " . $checksums['value'][0]['value']); } } @@ -179,7 +160,7 @@ class ChecksumsContext implements \Behat\Behat\Context\Context { */ public function theHeaderChecksumShouldMatch($checksum) { if ($this->response->getHeader('OC-Checksum')[0] !== $checksum) { - throw new \Exception("Expected $checksum, got ".$this->response->getHeader('OC-Checksum')[0]); + throw new \Exception("Expected $checksum, got " . $this->response->getHeader('OC-Checksum')[0]); } } @@ -219,7 +200,7 @@ class ChecksumsContext implements \Behat\Behat\Context\Context { $status = $parsed[0]['value'][1]['value'][1]['value']; if ($status !== 'HTTP/1.1 404 Not Found') { - throw new \Exception("Expected 'HTTP/1.1 404 Not Found', got ".$status); + throw new \Exception("Expected 'HTTP/1.1 404 Not Found', got " . $status); } } @@ -228,34 +209,7 @@ class ChecksumsContext implements \Behat\Behat\Context\Context { */ public function theOcChecksumHeaderShouldNotBeThere() { if ($this->response->hasHeader('OC-Checksum')) { - throw new \Exception("Expected no checksum header but got ".$this->response->getHeader('OC-Checksum')[0]); + throw new \Exception('Expected no checksum header but got ' . $this->response->getHeader('OC-Checksum')[0]); } } - - /** - * @Given user :user uploads chunk file :num of :total with :data to :destination with checksum :checksum - * @param string $user - * @param int $num - * @param int $total - * @param string $data - * @param string $destination - * @param string $checksum - */ - public function userUploadsChunkFileOfWithToWithChecksum($user, $num, $total, $data, $destination, $checksum) { - $num -= 1; - $this->response = $this->client->put( - $this->baseUrl . '/remote.php/webdav' . $destination . '-chunking-42-'.$total.'-'.$num, - [ - 'auth' => [ - $user, - $this->getPasswordForUser($user) - ], - 'body' => $data, - 'headers' => [ - 'OC-Checksum' => $checksum, - 'OC-Chunked' => '1', - ] - ] - ); - } } diff --git a/build/integration/features/bootstrap/CollaborationContext.php b/build/integration/features/bootstrap/CollaborationContext.php index 00fcbd09b26..27fa1795c5d 100644 --- a/build/integration/features/bootstrap/CollaborationContext.php +++ b/build/integration/features/bootstrap/CollaborationContext.php @@ -3,25 +3,8 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2021, Joas Schilling <coding@schilljs.com> - * - * @author Joas Schilling <coding@schilljs.com> - * - * @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: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Behat\Context\Context; use Behat\Gherkin\Node\TableNode; @@ -88,7 +71,7 @@ class CollaborationContext implements Context { try { $destination = '/users/admin/myaddressbook'; $data = '<x0:mkcol xmlns:x0="DAV:"><x0:set><x0:prop><x0:resourcetype><x0:collection/><x4:addressbook xmlns:x4="urn:ietf:params:xml:ns:carddav"/></x0:resourcetype><x0:displayname>myaddressbook</x0:displayname></x0:prop></x0:set></x0:mkcol>'; - $this->response = $this->makeDavRequest($this->currentUser, "MKCOL", $destination, ['Content-Type' => 'application/xml'], $data, "addressbooks"); + $this->response = $this->makeDavRequest($this->currentUser, 'MKCOL', $destination, ['Content-Type' => 'application/xml'], $data, 'addressbooks'); } catch (\GuzzleHttp\Exception\ServerException $e) { // 5xx responses cause a server exception $this->response = $e->getResponse(); @@ -110,7 +93,7 @@ EMAIL;TYPE=HOME:user@example.com REV;VALUE=DATE-AND-OR-TIME:20211130T140111Z END:VCARD EOF; - $this->response = $this->makeDavRequest($this->currentUser, "PUT", $destination, [], $data, "addressbooks"); + $this->response = $this->makeDavRequest($this->currentUser, 'PUT', $destination, [], $data, 'addressbooks'); } catch (\GuzzleHttp\Exception\ServerException $e) { // 5xx responses cause a server exception $this->response = $e->getResponse(); diff --git a/build/integration/features/bootstrap/CommandLine.php b/build/integration/features/bootstrap/CommandLine.php index cba254551e0..924d723daa6 100644 --- a/build/integration/features/bootstrap/CommandLine.php +++ b/build/integration/features/bootstrap/CommandLine.php @@ -1,27 +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 Robin Appelman <robin@icewind.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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ use PHPUnit\Framework\Assert; diff --git a/build/integration/features/bootstrap/CommandLineContext.php b/build/integration/features/bootstrap/CommandLineContext.php index 8f9cfc7b45a..e7764356270 100644 --- a/build/integration/features/bootstrap/CommandLineContext.php +++ b/build/integration/features/bootstrap/CommandLineContext.php @@ -1,31 +1,13 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Stefan Weil <sw@weilnetz.de> - * @author Sujith H <sharidasan@owncloud.com> - * @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-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ require __DIR__ . '/../../vendor/autoload.php'; +use Behat\Behat\Context\Exception\ContextNotFoundException; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use PHPUnit\Framework\Assert; @@ -61,8 +43,12 @@ class CommandLineContext implements \Behat\Behat\Context\Context { /** @BeforeScenario */ public function gatherContexts(BeforeScenarioScope $scope) { $environment = $scope->getEnvironment(); - // this should really be "WebDavContext" ... - $this->featureContext = $environment->getContext('FeatureContext'); + // this should really be "WebDavContext" + try { + $this->featureContext = $environment->getContext('FeatureContext'); + } catch (ContextNotFoundException) { + $this->featureContext = $environment->getContext('DavFeatureContext'); + } } private function findLastTransferFolderForUser($sourceUser, $targetUser) { @@ -71,7 +57,7 @@ class CommandLineContext implements \Behat\Behat\Context\Context { foreach ($results as $path => $data) { $path = rawurldecode($path); $parts = explode(' ', $path); - if (basename($parts[0]) !== 'transferred') { + if (basename($parts[0]) !== 'Transferred') { continue; } if (isset($parts[2]) && $parts[2] === $sourceUser) { @@ -124,19 +110,6 @@ class CommandLineContext implements \Behat\Behat\Context\Context { } /** - * @When /^transferring ownership of path "([^"]+)" from "([^"]+)" to "([^"]+)" with received shares$/ - */ - public function transferringOwnershipPathWithIncomingShares($path, $user1, $user2) { - $path = '--path=' . $path; - if ($this->runOcc(['files:transfer-ownership', $path, $user1, $user2, '--transfer-incoming-shares=1']) === 0) { - $this->lastTransferPath = $this->findLastTransferFolderForUser($user1, $user2); - } else { - // failure - $this->lastTransferPath = null; - } - } - - /** * @When /^using received transfer folder of "([^"]+)" as dav path$/ */ public function usingTransferFolderAsDavPath($user) { diff --git a/build/integration/features/bootstrap/CommentsContext.php b/build/integration/features/bootstrap/CommentsContext.php index 0eddf972bc1..53001b1c204 100644 --- a/build/integration/features/bootstrap/CommentsContext.php +++ b/build/integration/features/bootstrap/CommentsContext.php @@ -1,28 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Julius Härtl <jus@bitgrid.net> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Robin Appelman <robin@icewind.nl> - * @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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ require __DIR__ . '/../../vendor/autoload.php'; @@ -49,8 +30,6 @@ class CommentsContext implements \Behat\Behat\Context\Context { } } - - /** * get a named entry from response instead of picking a random entry from values * @@ -158,7 +137,7 @@ class CommentsContext implements \Behat\Behat\Context\Context { } if ($res->getStatusCode() !== (int)$statusCode) { - throw new \Exception("Response status code was not $statusCode (" . $res->getStatusCode() . ")"); + throw new \Exception("Response status code was not $statusCode (" . $res->getStatusCode() . ')'); } } @@ -200,13 +179,13 @@ class CommentsContext implements \Behat\Behat\Context\Context { } if ($res->getStatusCode() !== (int)$statusCode) { - throw new \Exception("Response status code was not $statusCode (" . $res->getStatusCode() . ")"); + throw new \Exception("Response status code was not $statusCode (" . $res->getStatusCode() . ')'); } if ($res->getStatusCode() === 207) { $service = new Sabre\Xml\Service(); $this->response = $service->parse($res->getBody()->getContents()); - $this->commentId = (int) ($this->getValueFromNamedEntries('{DAV:}response {DAV:}propstat {DAV:}prop {http://owncloud.org/ns}id', $this->response ?? []) ?? 0); + $this->commentId = (int)($this->getValueFromNamedEntries('{DAV:}response {DAV:}propstat {DAV:}prop {http://owncloud.org/ns}id', $this->response ?? []) ?? 0); } } @@ -258,7 +237,7 @@ class CommentsContext implements \Behat\Behat\Context\Context { } if ($res->getStatusCode() !== (int)$statusCode) { - throw new \Exception("Response status code was not $statusCode (" . $res->getStatusCode() . ")"); + throw new \Exception("Response status code was not $statusCode (" . $res->getStatusCode() . ')'); } } @@ -295,7 +274,7 @@ class CommentsContext implements \Behat\Behat\Context\Context { $count = count($this->response); } if ($count !== (int)$number) { - throw new \Exception("Found more comments than $number (" . $count . ")"); + throw new \Exception("Found more comments than $number (" . $count . ')'); } } @@ -325,7 +304,7 @@ class CommentsContext implements \Behat\Behat\Context\Context { } if ($res->getStatusCode() !== (int)$statusCode) { - throw new \Exception("Response status code was not $statusCode (" . $res->getStatusCode() . ")"); + throw new \Exception("Response status code was not $statusCode (" . $res->getStatusCode() . ')'); } } } diff --git a/build/integration/features/bootstrap/ContactsMenu.php b/build/integration/features/bootstrap/ContactsMenu.php index 0506d827a39..f6bf6b9422b 100644 --- a/build/integration/features/bootstrap/ContactsMenu.php +++ b/build/integration/features/bootstrap/ContactsMenu.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2021 Daniel Calviño Sánchez <danxuliu@gmail.com> - * - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * - * @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: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ use PHPUnit\Framework\Assert; diff --git a/build/integration/features/bootstrap/ConversionsContext.php b/build/integration/features/bootstrap/ConversionsContext.php new file mode 100644 index 00000000000..ccd14c460f8 --- /dev/null +++ b/build/integration/features/bootstrap/ConversionsContext.php @@ -0,0 +1,60 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +require __DIR__ . '/../../vendor/autoload.php'; + +use Behat\Behat\Context\Context; +use Behat\Behat\Context\SnippetAcceptingContext; +use Behat\Gherkin\Node\TableNode; + +class ConversionsContext implements Context, SnippetAcceptingContext { + use AppConfiguration; + use BasicStructure; + use WebDav; + + /** @BeforeScenario */ + public function setUpScenario() { + $this->asAn('admin'); + $this->setStatusTestingApp(true); + } + + /** @AfterScenario */ + public function tearDownScenario() { + $this->asAn('admin'); + $this->setStatusTestingApp(false); + } + + protected function resetAppConfigs() { + } + + /** + * @When /^user "([^"]*)" converts file "([^"]*)" to "([^"]*)"$/ + */ + public function userConvertsTheSavedFileId(string $user, string $path, string $mime) { + $this->userConvertsTheSavedFileIdTo($user, $path, $mime, null); + } + + /** + * @When /^user "([^"]*)" converts file "([^"]*)" to "([^"]*)" and saves it to "([^"]*)"$/ + */ + public function userConvertsTheSavedFileIdTo(string $user, string $path, string $mime, ?string $destination) { + try { + $fileId = $this->getFileIdForPath($user, $path); + } catch (Exception $e) { + // return a fake value to keep going and be able to test the error + $fileId = 0; + } + + $data = [['fileId', $fileId], ['targetMimeType', $mime]]; + if ($destination !== null) { + $data[] = ['destination', $destination]; + } + + $this->asAn($user); + $this->sendingToWith('post', '/apps/files/api/v1/convert', new TableNode($data)); + } +} diff --git a/build/integration/features/bootstrap/DavFeatureContext.php b/build/integration/features/bootstrap/DavFeatureContext.php new file mode 100644 index 00000000000..ec6085cff98 --- /dev/null +++ b/build/integration/features/bootstrap/DavFeatureContext.php @@ -0,0 +1,24 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +use Behat\Behat\Context\Context; +use Behat\Behat\Context\SnippetAcceptingContext; + +require __DIR__ . '/../../vendor/autoload.php'; + +class DavFeatureContext implements Context, SnippetAcceptingContext { + use AppConfiguration; + use ContactsMenu; + use ExternalStorage; + use Search; + use WebDav; + use Trashbin; + + protected function resetAppConfigs() { + $this->deleteServerConfig('files_sharing', 'outgoing_server2server_share_enabled'); + } +} diff --git a/build/integration/features/bootstrap/Download.php b/build/integration/features/bootstrap/Download.php index e5e6dc64853..549a033346e 100644 --- a/build/integration/features/bootstrap/Download.php +++ b/build/integration/features/bootstrap/Download.php @@ -1,32 +1,16 @@ <?php + /** - * @copyright Copyright (c) 2018, Daniel Calviño Sánchez (danxuliu@gmail.com) - * - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @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: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ use PHPUnit\Framework\Assert; +use Psr\Http\Message\StreamInterface; require __DIR__ . '/../../vendor/autoload.php'; trait Download { - /** @var string **/ + /** @var string * */ private $downloadedFile; /** @AfterScenario **/ @@ -38,16 +22,16 @@ trait Download { * @When user :user downloads zip file for entries :entries in folder :folder */ public function userDownloadsZipFileForEntriesInFolder($user, $entries, $folder) { + $folder = trim($folder, '/'); $this->asAn($user); - $this->sendingToDirectUrl('GET', "/index.php/apps/files/ajax/download.php?dir=" . $folder . "&files=[" . $entries . "]"); + $this->sendingToDirectUrl('GET', "/remote.php/dav/files/$user/$folder?accept=zip&files=[" . $entries . ']'); $this->theHTTPStatusCodeShouldBe('200'); - - $this->getDownloadedFile(); } private function getDownloadedFile() { $this->downloadedFile = ''; + /** @var StreamInterface */ $body = $this->response->getBody(); while (!$body->eof()) { $this->downloadedFile .= $body->read(8192); @@ -56,14 +40,28 @@ trait Download { } /** + * @Then the downloaded file is a zip file + */ + public function theDownloadedFileIsAZipFile() { + $this->getDownloadedFile(); + + Assert::assertTrue( + strpos($this->downloadedFile, "\x50\x4B\x01\x02") !== false, + 'File does not contain the central directory file header' + ); + } + + /** * @Then the downloaded zip file is a zip32 file */ public function theDownloadedZipFileIsAZip32File() { + $this->theDownloadedFileIsAZipFile(); + // assertNotContains is not used to prevent the whole file from being // printed in case of error. Assert::assertTrue( strpos($this->downloadedFile, "\x50\x4B\x06\x06") === false, - "File contains the zip64 end of central dir signature" + 'File contains the zip64 end of central dir signature' ); } @@ -71,11 +69,13 @@ trait Download { * @Then the downloaded zip file is a zip64 file */ public function theDownloadedZipFileIsAZip64File() { + $this->theDownloadedFileIsAZipFile(); + // assertNotContains is not used to prevent the whole file from being // printed in case of error. Assert::assertTrue( strpos($this->downloadedFile, "\x50\x4B\x06\x06") !== false, - "File does not contain the zip64 end of central dir signature" + 'File does not contain the zip64 end of central dir signature' ); } @@ -95,7 +95,7 @@ trait Download { // in case of error and to be able to get the extra field length. Assert::assertEquals( 1, preg_match($fileHeaderRegExp, $this->downloadedFile, $matches), - "Local header for file did not appear once in zip file" + 'Local header for file did not appear once in zip file' ); $extraFieldLength = unpack('vextraFieldLength', $matches[1])['extraFieldLength']; @@ -115,7 +115,7 @@ trait Download { // in case of error. Assert::assertEquals( 1, preg_match($fileHeaderAndContentRegExp, $this->downloadedFile), - "Local header and contents for file did not appear once in zip file" + 'Local header and contents for file did not appear once in zip file' ); } @@ -135,7 +135,21 @@ trait Download { // in case of error. Assert::assertEquals( 1, preg_match($folderHeaderRegExp, $this->downloadedFile), - "Local header for folder did not appear once in zip file" + 'Local header for folder did not appear once in zip file' + ); + } + + /** + * @Then the downloaded file has the content of :sourceFilename from :user data + */ + public function theDownloadedFileHasContentOfUserFile($sourceFilename, $user) { + $this->getDownloadedFile(); + $expectedFileContents = file_get_contents($this->getDataDirectory() . "/$user/files" . $sourceFilename); + + // prevent the whole file from being printed in case of error. + Assert::assertEquals( + 0, strcmp($expectedFileContents, $this->downloadedFile), + 'Downloaded file content does not match local file content' ); } } diff --git a/build/integration/features/bootstrap/ExternalStorage.php b/build/integration/features/bootstrap/ExternalStorage.php new file mode 100644 index 00000000000..8fe2653a026 --- /dev/null +++ b/build/integration/features/bootstrap/ExternalStorage.php @@ -0,0 +1,123 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +use Behat\Gherkin\Node\TableNode; +use PHPUnit\Framework\Assert; + +require __DIR__ . '/../../vendor/autoload.php'; + +trait ExternalStorage { + private array $storageIds = []; + + private array $lastExternalStorageData; + + /** + * @AfterScenario + **/ + public function deleteCreatedStorages(): void { + foreach ($this->storageIds as $storageId) { + $this->deleteStorage($storageId); + } + $this->storageIds = []; + } + + private function deleteStorage(string $storageId): void { + // Based on "runOcc" from CommandLine trait + $args = ['files_external:delete', '--yes', $storageId]; + $args = array_map(function ($arg) { + return escapeshellarg($arg); + }, $args); + $args[] = '--no-ansi --no-warnings'; + $args = implode(' ', $args); + + $descriptor = [ + 0 => ['pipe', 'r'], + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ]; + $process = proc_open('php console.php ' . $args, $descriptor, $pipes, $ocPath = '../..'); + $lastStdOut = stream_get_contents($pipes[1]); + proc_close($process); + } + + /** + * @When logged in user creates external global storage + * + * @param TableNode $fields + */ + public function loggedInUserCreatesExternalGlobalStorage(TableNode $fields): void { + $this->sendJsonWithRequestTokenAndBasicAuth('POST', '/index.php/apps/files_external/globalstorages', $fields); + $this->theHTTPStatusCodeShouldBe('201'); + + $this->lastExternalStorageData = json_decode($this->response->getBody(), $asAssociativeArray = true); + + $this->storageIds[] = $this->lastExternalStorageData['id']; + } + + /** + * @When logged in user updates last external userglobal storage + * + * @param TableNode $fields + */ + public function loggedInUserUpdatesLastExternalUserglobalStorage(TableNode $fields): void { + $this->sendJsonWithRequestTokenAndBasicAuth('PUT', '/index.php/apps/files_external/userglobalstorages/' . $this->lastExternalStorageData['id'], $fields); + $this->theHTTPStatusCodeShouldBe('200'); + + $this->lastExternalStorageData = json_decode($this->response->getBody(), $asAssociativeArray = true); + } + + /** + * @Then fields of last external storage match with + * + * @param TableNode $fields + */ + public function fieldsOfLastExternalStorageMatchWith(TableNode $fields): void { + foreach ($fields->getRowsHash() as $expectedField => $expectedValue) { + if (!array_key_exists($expectedField, $this->lastExternalStorageData)) { + Assert::fail("$expectedField was not found in response"); + } + + Assert::assertEquals($expectedValue, $this->lastExternalStorageData[$expectedField], "Field '$expectedField' does not match ({$this->lastExternalStorageData[$expectedField]})"); + } + } + + private function sendJsonWithRequestToken(string $method, string $url, TableNode $fields): void { + $isFirstField = true; + $fieldsAsJsonString = '{'; + foreach ($fields->getRowsHash() as $key => $value) { + $fieldsAsJsonString .= ($isFirstField ? '' : ',') . '"' . $key . '":' . $value; + $isFirstField = false; + } + $fieldsAsJsonString .= '}'; + + $body = [ + 'headers' => [ + 'Content-Type' => 'application/json', + ], + 'body' => $fieldsAsJsonString, + ]; + $this->sendingAToWithRequesttoken($method, $url, $body); + } + + private function sendJsonWithRequestTokenAndBasicAuth(string $method, string $url, TableNode $fields): void { + $isFirstField = true; + $fieldsAsJsonString = '{'; + foreach ($fields->getRowsHash() as $key => $value) { + $fieldsAsJsonString .= ($isFirstField ? '' : ',') . '"' . $key . '":' . $value; + $isFirstField = false; + } + $fieldsAsJsonString .= '}'; + + $body = [ + 'headers' => [ + 'Content-Type' => 'application/json', + 'Authorization' => 'Basic ' . base64_encode('admin:admin'), + ], + 'body' => $fieldsAsJsonString, + ]; + $this->sendingAToWithRequesttoken($method, $url, $body); + } +} diff --git a/build/integration/features/bootstrap/FakeSMTPHelper.php b/build/integration/features/bootstrap/FakeSMTPHelper.php index 9d3b5979114..32387869edd 100644 --- a/build/integration/features/bootstrap/FakeSMTPHelper.php +++ b/build/integration/features/bootstrap/FakeSMTPHelper.php @@ -1,25 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2016 Daniel Calviño Sánchez <danxuliu@gmail.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * - * @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: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ // Code below modified from https://github.com/axllent/fake-smtp/blob/f0856f8a0df6f4ca5a573cf31428c09ebc5b9ea3/fakeSMTP.php, // which is under the MIT license (https://github.com/axllent/fake-smtp/blob/f0856f8a0df6f4ca5a573cf31428c09ebc5b9ea3/LICENSE) @@ -52,7 +35,7 @@ class fakeSMTP { $hasValidTo = false; $receivingData = false; $header = true; - $this->reply('220 '.$this->serverHello); + $this->reply('220 ' . $this->serverHello); $this->mail['ipaddress'] = $this->detectIP(); while ($data = fgets($this->fd)) { $data = preg_replace('@\r\n@', "\n", $data); @@ -78,7 +61,7 @@ class fakeSMTP { $this->reply('250 2.1.5 Ok'); $hasValidTo = true; } else { - $this->reply('501 5.1.3 Bad recipient address syntax '.$match[1]); + $this->reply('501 5.1.3 Bad recipient address syntax ' . $match[1]); } } } elseif (!$receivingData && preg_match('/^RSET$/i', trim($data))) { @@ -88,7 +71,7 @@ class fakeSMTP { } elseif (!$receivingData && preg_match('/^NOOP$/i', trim($data))) { $this->reply('250 2.0.0 Ok'); } elseif (!$receivingData && preg_match('/^VRFY (.*)/i', trim($data), $match)) { - $this->reply('250 2.0.0 '.$match[1]); + $this->reply('250 2.0.0 ' . $match[1]); } elseif (!$receivingData && preg_match('/^DATA/i', trim($data))) { if (!$hasValidTo) { $this->reply('503 5.5.1 Error: need RCPT command'); @@ -97,7 +80,7 @@ class fakeSMTP { $receivingData = true; } } elseif (!$receivingData && preg_match('/^(HELO|EHLO)/i', $data)) { - $this->reply('250 HELO '.$this->mail['ipaddress']); + $this->reply('250 HELO ' . $this->mail['ipaddress']); } elseif (!$receivingData && preg_match('/^QUIT/i', trim($data))) { break; } elseif (!$receivingData) { @@ -106,7 +89,7 @@ class fakeSMTP { } elseif ($receivingData && $data == ".\n") { /* Email Received, now let's look at it */ $receivingData = false; - $this->reply('250 2.0.0 Ok: queued as '.$this->generateRandom(10)); + $this->reply('250 2.0.0 Ok: queued as ' . $this->generateRandom(10)); $splitmail = explode("\n\n", $this->mail['rawEmail'], 2); if (count($splitmail) == 2) { $this->mail['emailHeaders'] = $splitmail[0]; @@ -127,14 +110,14 @@ class fakeSMTP { } } /* Say good bye */ - $this->reply('221 2.0.0 Bye '.$this->mail['ipaddress']); + $this->reply('221 2.0.0 Bye ' . $this->mail['ipaddress']); fclose($this->fd); } public function log($s) { if ($this->logFile) { - file_put_contents($this->logFile, trim($s)."\n", FILE_APPEND); + file_put_contents($this->logFile, trim($s) . "\n", FILE_APPEND); } } diff --git a/build/integration/features/bootstrap/FeatureContext.php b/build/integration/features/bootstrap/FeatureContext.php index a3a600d6625..ab37556f931 100644 --- a/build/integration/features/bootstrap/FeatureContext.php +++ b/build/integration/features/bootstrap/FeatureContext.php @@ -1,40 +1,29 @@ <?php + /** - * @copyright Copyright (c) 2016 Thomas Müller <thomas.mueller@tmit.eu> - * - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Joas Schilling <coding@schilljs.com> - * @author Sergio Bertolin <sbertolin@solidgear.es> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Behat\Context\Context; use Behat\Behat\Context\SnippetAcceptingContext; require __DIR__ . '/../../vendor/autoload.php'; - /** * Features context. */ class FeatureContext implements Context, SnippetAcceptingContext { + use AppConfiguration; use ContactsMenu; + use ExternalStorage; use Search; use WebDav; use Trashbin; + + protected function resetAppConfigs(): void { + $this->deleteServerConfig('bruteForce', 'whitelist_0'); + $this->deleteServerConfig('bruteForce', 'whitelist_1'); + $this->deleteServerConfig('bruteforcesettings', 'apply_allowlist_to_ratelimit'); + } } diff --git a/build/integration/features/bootstrap/FederationContext.php b/build/integration/features/bootstrap/FederationContext.php index 423708adc10..95dc8119ad6 100644 --- a/build/integration/features/bootstrap/FederationContext.php +++ b/build/integration/features/bootstrap/FederationContext.php @@ -1,34 +1,14 @@ <?php + /** - * @copyright Copyright (c) 2016 Sergio Bertolin <sbertolin@solidgear.es> - * - * @author Bjoern Schiessle <bjoern@schiessle.org> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Joas Schilling <coding@schilljs.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Sergio Bertolin <sbertolin@solidgear.es> - * @author Sergio Bertolín <sbertolin@solidgear.es> - * - * @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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Behat\Context\Context; use Behat\Behat\Context\SnippetAcceptingContext; use Behat\Gherkin\Node\TableNode; +use PHPUnit\Framework\Assert; require __DIR__ . '/../../vendor/autoload.php'; @@ -60,7 +40,7 @@ class FederationContext implements Context, SnippetAcceptingContext { $port = getenv('PORT_FED'); - self::$phpFederatedServerPid = exec('php -S localhost:' . $port . ' -t ../../ >/dev/null & echo $!'); + self::$phpFederatedServerPid = exec('PHP_CLI_SERVER_WORKERS=2 php -S localhost:' . $port . ' -t ../../ >/dev/null & echo $!'); } /** @@ -86,7 +66,7 @@ class FederationContext implements Context, SnippetAcceptingContext { * @param string $shareeServer "LOCAL" or "REMOTE" */ public function federateSharing($sharerUser, $sharerServer, $sharerPath, $shareeUser, $shareeServer) { - if ($shareeServer == "REMOTE") { + if ($shareeServer == 'REMOTE') { $shareWith = "$shareeUser@" . substr($this->remoteBaseUrl, 0, -4); } else { $shareWith = "$shareeUser@" . substr($this->localBaseUrl, 0, -4); @@ -107,7 +87,7 @@ class FederationContext implements Context, SnippetAcceptingContext { * @param string $shareeServer "LOCAL" or "REMOTE" */ public function federateGroupSharing($sharerUser, $sharerServer, $sharerPath, $shareeGroup, $shareeServer) { - if ($shareeServer == "REMOTE") { + if ($shareeServer == 'REMOTE') { $shareWith = "$shareeGroup@" . substr($this->remoteBaseUrl, 0, -4); } else { $shareWith = "$shareeGroup@" . substr($this->localBaseUrl, 0, -4); @@ -156,7 +136,7 @@ class FederationContext implements Context, SnippetAcceptingContext { public function acceptLastPendingShare($user, $server) { $previous = $this->usingServer($server); $this->asAn($user); - $this->sendingToWith('GET', "/apps/files_sharing/api/v1/remote_shares/pending", null); + $this->sendingToWith('GET', '/apps/files_sharing/api/v1/remote_shares/pending', null); $this->theHTTPStatusCodeShouldBe('200'); $this->theOCSStatusCodeShouldBe('100'); $share_id = simplexml_load_string($this->response->getBody())->data[0]->element[0]->id; @@ -174,7 +154,7 @@ class FederationContext implements Context, SnippetAcceptingContext { */ public function deleteLastAcceptedRemoteShare($user) { $this->asAn($user); - $this->sendingToWith('DELETE', "/apps/files_sharing/api/v1/remote_shares/" . $this->lastAcceptedRemoteShareId, null); + $this->sendingToWith('DELETE', '/apps/files_sharing/api/v1/remote_shares/' . $this->lastAcceptedRemoteShareId, null); } /** @@ -190,8 +170,52 @@ class FederationContext implements Context, SnippetAcceptingContext { self::$phpFederatedServerPid = ''; } + /** + * @BeforeScenario @TrustedFederation + */ + public function theServersAreTrustingEachOther() { + $this->asAn('admin'); + // Trust the remote server on the local server + $this->usingServer('LOCAL'); + $this->sendRequestForJSON('POST', '/apps/federation/trusted-servers', ['url' => 'http://localhost:' . getenv('PORT')]); + Assert::assertTrue(($this->response->getStatusCode() === 200 || $this->response->getStatusCode() === 409)); + + // Trust the local server on the remote server + $this->usingServer('REMOTE'); + $this->sendRequestForJSON('POST', '/apps/federation/trusted-servers', ['url' => 'http://localhost:' . getenv('PORT_FED')]); + // If the server is already trusted, we expect a 409 + Assert::assertTrue(($this->response->getStatusCode() === 200 || $this->response->getStatusCode() === 409)); + } + + /** + * @AfterScenario @TrustedFederation + */ + public function theServersAreNoLongerTrustingEachOther() { + $this->asAn('admin'); + // Untrust the remote servers on the local server + $this->usingServer('LOCAL'); + $this->sendRequestForJSON('GET', '/apps/federation/trusted-servers'); + $this->theHTTPStatusCodeShouldBe('200'); + $trustedServersIDs = array_map(fn ($server) => $server->id, json_decode($this->response->getBody())->ocs->data); + foreach ($trustedServersIDs as $id) { + $this->sendRequestForJSON('DELETE', '/apps/federation/trusted-servers/' . $id); + $this->theHTTPStatusCodeShouldBe('200'); + } + + // Untrust the local server on the remote server + $this->usingServer('REMOTE'); + $this->sendRequestForJSON('GET', '/apps/federation/trusted-servers'); + $this->theHTTPStatusCodeShouldBe('200'); + $trustedServersIDs = array_map(fn ($server) => $server->id, json_decode($this->response->getBody())->ocs->data); + foreach ($trustedServersIDs as $id) { + $this->sendRequestForJSON('DELETE', '/apps/federation/trusted-servers/' . $id); + $this->theHTTPStatusCodeShouldBe('200'); + } + } + protected function resetAppConfigs() { $this->deleteServerConfig('files_sharing', 'incoming_server2server_group_share_enabled'); $this->deleteServerConfig('files_sharing', 'outgoing_server2server_group_share_enabled'); + $this->deleteServerConfig('files_sharing', 'federated_trusted_share_auto_accept'); } } diff --git a/build/integration/features/bootstrap/FilesDropContext.php b/build/integration/features/bootstrap/FilesDropContext.php index 22eaa639030..0c437f28a72 100644 --- a/build/integration/features/bootstrap/FilesDropContext.php +++ b/build/integration/features/bootstrap/FilesDropContext.php @@ -1,27 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2016 Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Behat\Context\Context; use Behat\Behat\Context\SnippetAcceptingContext; @@ -35,7 +16,7 @@ class FilesDropContext implements Context, SnippetAcceptingContext { /** * @When Dropping file :path with :content */ - public function droppingFileWith($path, $content) { + public function droppingFileWith($path, $content, $nickname = null) { $client = new Client(); $options = []; if (count($this->lastShareData->data->element) > 0) { @@ -45,11 +26,16 @@ class FilesDropContext implements Context, SnippetAcceptingContext { } $base = substr($this->baseUrl, 0, -4); - $fullUrl = $base . "/public.php/dav/files/$token/$path"; + $fullUrl = str_replace('//', '/', $base . "/public.php/dav/files/$token/$path"); $options['headers'] = [ - 'X-REQUESTED-WITH' => 'XMLHttpRequest' + 'X-REQUESTED-WITH' => 'XMLHttpRequest', ]; + + if ($nickname) { + $options['headers']['X-NC-NICKNAME'] = $nickname; + } + $options['body'] = \GuzzleHttp\Psr7\Utils::streamFor($content); try { @@ -59,10 +45,19 @@ class FilesDropContext implements Context, SnippetAcceptingContext { } } + + /** + * @When Dropping file :path with :content as :nickName + */ + public function droppingFileWithAs($path, $content, $nickname) { + $this->droppingFileWith($path, $content, $nickname); + } + + /** * @When Creating folder :folder in drop */ - public function creatingFolderInDrop($folder) { + public function creatingFolderInDrop($folder, $nickname = null) { $client = new Client(); $options = []; if (count($this->lastShareData->data->element) > 0) { @@ -72,16 +67,28 @@ class FilesDropContext implements Context, SnippetAcceptingContext { } $base = substr($this->baseUrl, 0, -4); - $fullUrl = $base . "/public.php/dav/files/$token/$folder"; + $fullUrl = str_replace('//', '/', $base . "/public.php/dav/files/$token/$folder"); $options['headers'] = [ - 'X-REQUESTED-WITH' => 'XMLHttpRequest' + 'X-REQUESTED-WITH' => 'XMLHttpRequest', ]; + if ($nickname) { + $options['headers']['X-NC-NICKNAME'] = $nickname; + } + try { $this->response = $client->request('MKCOL', $fullUrl, $options); } catch (\GuzzleHttp\Exception\ClientException $e) { $this->response = $e->getResponse(); } } + + + /** + * @When Creating folder :folder in drop as :nickName + */ + public function creatingFolderInDropWithNickname($folder, $nickname) { + return $this->creatingFolderInDrop($folder, $nickname); + } } diff --git a/build/integration/features/bootstrap/LDAPContext.php b/build/integration/features/bootstrap/LDAPContext.php index fd4a448b5e9..986dced77a1 100644 --- a/build/integration/features/bootstrap/LDAPContext.php +++ b/build/integration/features/bootstrap/LDAPContext.php @@ -1,27 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Robin Appelman <robin@icewind.nl> - * - * @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 */ use Behat\Behat\Context\Context; use Behat\Gherkin\Node\TableNode; diff --git a/build/integration/features/bootstrap/Mail.php b/build/integration/features/bootstrap/Mail.php index c2d9e86275c..d48ed6399c5 100644 --- a/build/integration/features/bootstrap/Mail.php +++ b/build/integration/features/bootstrap/Mail.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2020, Daniel Calviño Sánchez (danxuliu@gmail.com) - * - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * - * @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: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ trait Mail { // CommandLine trait is expected to be used in the class that uses this @@ -37,7 +21,7 @@ trait Mail { return; } - exec("kill " . $this->fakeSmtpServerPid); + exec('kill ' . $this->fakeSmtpServerPid); $this->invokingTheCommand('config:system:delete mail_smtpport'); } @@ -50,6 +34,6 @@ trait Mail { // FakeSMTP uses 2525 instead. $this->invokingTheCommand('config:system:set mail_smtpport --value=2525 --type integer'); - $this->fakeSmtpServerPid = exec("php features/bootstrap/FakeSMTPHelper.php >/dev/null 2>&1 & echo $!"); + $this->fakeSmtpServerPid = exec('php features/bootstrap/FakeSMTPHelper.php >/dev/null 2>&1 & echo $!'); } } diff --git a/build/integration/features/bootstrap/MetadataContext.php b/build/integration/features/bootstrap/MetadataContext.php new file mode 100644 index 00000000000..32042590c86 --- /dev/null +++ b/build/integration/features/bootstrap/MetadataContext.php @@ -0,0 +1,124 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +use Behat\Behat\Context\Context; +use Behat\Step\Then; +use Behat\Step\When; +use PHPUnit\Framework\Assert; +use Sabre\DAV\Client as SClient; + +require __DIR__ . '/../../vendor/autoload.php'; + +class MetadataContext implements Context { + private string $davPath = '/remote.php/dav'; + + public function __construct( + private string $baseUrl, + private array $admin, + private string $regular_user_password, + ) { + // in case of ci deployment we take the server url from the environment + $testServerUrl = getenv('TEST_SERVER_URL'); + if ($testServerUrl !== false) { + $this->baseUrl = substr($testServerUrl, 0, -5); + } + } + + #[When('User :user sets the :metadataKey prop with value :metadataValue on :fileName')] + public function userSetsProp(string $user, string $metadataKey, string $metadataValue, string $fileName) { + $client = new SClient([ + 'baseUri' => $this->baseUrl, + 'userName' => $user, + 'password' => '123456', + 'authType' => SClient::AUTH_BASIC, + ]); + + $body = '<?xml version="1.0"?> +<d:propertyupdate xmlns:d="DAV:" xmlns:nc="http://nextcloud.com/ns"> + <d:set> + <d:prop> + <nc:' . $metadataKey . '>' . $metadataValue . '</nc:' . $metadataKey . '> + </d:prop> + </d:set> +</d:propertyupdate>'; + + $davUrl = $this->getDavUrl($user, $fileName); + $client->request('PROPPATCH', $this->baseUrl . $davUrl, $body); + } + + #[When('User :user deletes the :metadataKey prop on :fileName')] + public function userDeletesProp(string $user, string $metadataKey, string $fileName) { + $client = new SClient([ + 'baseUri' => $this->baseUrl, + 'userName' => $user, + 'password' => '123456', + 'authType' => SClient::AUTH_BASIC, + ]); + + $body = '<?xml version="1.0"?> +<d:propertyupdate xmlns:d="DAV:" xmlns:nc="http://nextcloud.com/ns"> + <d:remove> + <d:prop> + <nc:' . $metadataKey . '></nc:' . $metadataKey . '> + </d:prop> + </d:remove> +</d:propertyupdate>'; + + $davUrl = $this->getDavUrl($user, $fileName); + $client->request('PROPPATCH', $this->baseUrl . $davUrl, $body); + } + + #[Then('User :user should see the prop :metadataKey equal to :metadataValue for file :fileName')] + public function checkPropForFile(string $user, string $metadataKey, string $metadataValue, string $fileName) { + $client = new SClient([ + 'baseUri' => $this->baseUrl, + 'userName' => $user, + 'password' => '123456', + 'authType' => SClient::AUTH_BASIC, + ]); + + $body = '<?xml version="1.0"?> +<d:propfind xmlns:d="DAV:" xmlns:nc="http://nextcloud.com/ns"> + <d:prop> + <nc:' . $metadataKey . '></nc:' . $metadataKey . '> + </d:prop> +</d:propfind>'; + + $davUrl = $this->getDavUrl($user, $fileName); + $response = $client->request('PROPFIND', $this->baseUrl . $davUrl, $body); + $parsedResponse = $client->parseMultistatus($response['body']); + + Assert::assertEquals($parsedResponse[$davUrl]['200']['{http://nextcloud.com/ns}' . $metadataKey], $metadataValue); + } + + #[Then('User :user should not see the prop :metadataKey for file :fileName')] + public function checkPropDoesNotExistsForFile(string $user, string $metadataKey, string $fileName) { + $client = new SClient([ + 'baseUri' => $this->baseUrl, + 'userName' => $user, + 'password' => '123456', + 'authType' => SClient::AUTH_BASIC, + ]); + + $body = '<?xml version="1.0"?> +<d:propfind xmlns:d="DAV:" xmlns:nc="http://nextcloud.com/ns"> + <d:prop> + <nc:' . $metadataKey . '></nc:' . $metadataKey . '> + </d:prop> +</d:propfind>'; + + $davUrl = $this->getDavUrl($user, $fileName); + $response = $client->request('PROPFIND', $this->baseUrl . $davUrl, $body); + $parsedResponse = $client->parseMultistatus($response['body']); + + Assert::assertEquals($parsedResponse[$davUrl]['404']['{http://nextcloud.com/ns}' . $metadataKey], null); + } + + private function getDavUrl(string $user, string $fileName) { + return $this->davPath . '/files/' . $user . $fileName; + } +} diff --git a/build/integration/features/bootstrap/PrincipalPropertySearchContext.php b/build/integration/features/bootstrap/PrincipalPropertySearchContext.php new file mode 100644 index 00000000000..9dfd9379240 --- /dev/null +++ b/build/integration/features/bootstrap/PrincipalPropertySearchContext.php @@ -0,0 +1,141 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +require __DIR__ . '/../../vendor/autoload.php'; + +use Behat\Behat\Context\Context; +use GuzzleHttp\BodySummarizer; +use GuzzleHttp\Client; +use GuzzleHttp\HandlerStack; +use GuzzleHttp\Middleware; +use GuzzleHttp\Utils; +use Psr\Http\Message\ResponseInterface; + +class PrincipalPropertySearchContext implements Context { + private string $baseUrl; + private Client $client; + private ResponseInterface $response; + + public function __construct(string $baseUrl) { + $this->baseUrl = $baseUrl; + + // in case of ci deployment we take the server url from the environment + $testServerUrl = getenv('TEST_SERVER_URL'); + if ($testServerUrl !== false) { + $this->baseUrl = substr($testServerUrl, 0, -5); + } + } + + /** @BeforeScenario */ + public function setUpScenario(): void { + $this->client = $this->createGuzzleInstance(); + } + + /** + * Create a Guzzle client with a higher truncateAt value to read full error responses. + */ + private function createGuzzleInstance(): Client { + $bodySummarizer = new BodySummarizer(2048); + + $stack = new HandlerStack(Utils::chooseHandler()); + $stack->push(Middleware::httpErrors($bodySummarizer), 'http_errors'); + $stack->push(Middleware::redirect(), 'allow_redirects'); + $stack->push(Middleware::cookies(), 'cookies'); + $stack->push(Middleware::prepareBody(), 'prepare_body'); + + return new Client(['handler' => $stack]); + } + + /** + * @When searching for a principal matching :match + * @param string $match + * @throws \Exception + */ + public function principalPropertySearch(string $match) { + $davUrl = $this->baseUrl . '/remote.php/dav/'; + $user = 'admin'; + $password = 'admin'; + + $this->response = $this->client->request( + 'REPORT', + $davUrl, + [ + 'body' => '<x0:principal-property-search xmlns:x0="DAV:" test="anyof"> + <x0:property-search> + <x0:prop> + <x0:displayname/> + <x2:email-address xmlns:x2="http://sabredav.org/ns"/> + </x0:prop> + <x0:match>' . $match . '</x0:match> + </x0:property-search> + <x0:prop> + <x0:displayname/> + <x1:calendar-user-type xmlns:x1="urn:ietf:params:xml:ns:caldav"/> + <x1:calendar-user-address-set xmlns:x1="urn:ietf:params:xml:ns:caldav"/> + <x0:principal-URL/> + <x0:alternate-URI-set/> + <x2:email-address xmlns:x2="http://sabredav.org/ns"/> + <x3:language xmlns:x3="http://nextcloud.com/ns"/> + <x1:calendar-home-set xmlns:x1="urn:ietf:params:xml:ns:caldav"/> + <x1:schedule-inbox-URL xmlns:x1="urn:ietf:params:xml:ns:caldav"/> + <x1:schedule-outbox-URL xmlns:x1="urn:ietf:params:xml:ns:caldav"/> + <x1:schedule-default-calendar-URL xmlns:x1="urn:ietf:params:xml:ns:caldav"/> + <x3:resource-type xmlns:x3="http://nextcloud.com/ns"/> + <x3:resource-vehicle-type xmlns:x3="http://nextcloud.com/ns"/> + <x3:resource-vehicle-make xmlns:x3="http://nextcloud.com/ns"/> + <x3:resource-vehicle-model xmlns:x3="http://nextcloud.com/ns"/> + <x3:resource-vehicle-is-electric xmlns:x3="http://nextcloud.com/ns"/> + <x3:resource-vehicle-range xmlns:x3="http://nextcloud.com/ns"/> + <x3:resource-vehicle-seating-capacity xmlns:x3="http://nextcloud.com/ns"/> + <x3:resource-contact-person xmlns:x3="http://nextcloud.com/ns"/> + <x3:resource-contact-person-vcard xmlns:x3="http://nextcloud.com/ns"/> + <x3:room-type xmlns:x3="http://nextcloud.com/ns"/> + <x3:room-seating-capacity xmlns:x3="http://nextcloud.com/ns"/> + <x3:room-building-address xmlns:x3="http://nextcloud.com/ns"/> + <x3:room-building-story xmlns:x3="http://nextcloud.com/ns"/> + <x3:room-building-room-number xmlns:x3="http://nextcloud.com/ns"/> + <x3:room-features xmlns:x3="http://nextcloud.com/ns"/> + </x0:prop> + <x0:apply-to-principal-collection-set/> +</x0:principal-property-search> +', + 'auth' => [ + $user, + $password, + ], + 'headers' => [ + 'Content-Type' => 'application/xml; charset=UTF-8', + 'Depth' => '0', + ], + ] + ); + } + + /** + * @Then The search HTTP status code should be :code + * @param string $code + * @throws \Exception + */ + public function theHttpStatusCodeShouldBe(string $code): void { + if ((int)$code !== $this->response->getStatusCode()) { + throw new \Exception('Expected ' . (int)$code . ' got ' . $this->response->getStatusCode()); + } + } + + /** + * @Then The search response should contain :needle + * @param string $needle + * @throws \Exception + */ + public function theResponseShouldContain(string $needle): void { + $body = $this->response->getBody()->getContents(); + + if (str_contains($body, $needle) === false) { + throw new \Exception('Response does not contain "' . $needle . '"'); + } + } +} diff --git a/build/integration/features/bootstrap/Provisioning.php b/build/integration/features/bootstrap/Provisioning.php index 7fb4188f919..935ad2a4a1d 100644 --- a/build/integration/features/bootstrap/Provisioning.php +++ b/build/integration/features/bootstrap/Provisioning.php @@ -1,36 +1,12 @@ <?php + /** - * @copyright Copyright (c) 2016 Sergio Bertolin <sbertolin@solidgear.es> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Sergio Bertolin <sbertolin@solidgear.es> - * @author Sergio Bertolín <sbertolin@solidgear.es> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Vincent Petry <vincent@nextcloud.com> - * @author Jonas Meurer <jonas@freesources.org> - * - * @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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ + +use Behat\Gherkin\Node\TableNode; use GuzzleHttp\Client; use GuzzleHttp\Message\ResponseInterface; use PHPUnit\Framework\Assert; @@ -61,7 +37,7 @@ trait Provisioning { $this->userExists($user); } catch (\GuzzleHttp\Exception\ClientException $ex) { $previous_user = $this->currentUser; - $this->currentUser = "admin"; + $this->currentUser = 'admin'; $this->creatingTheUser($user); $this->currentUser = $previous_user; } @@ -78,7 +54,7 @@ trait Provisioning { $this->userExists($user); } catch (\GuzzleHttp\Exception\ClientException $ex) { $previous_user = $this->currentUser; - $this->currentUser = "admin"; + $this->currentUser = 'admin'; $this->creatingTheUser($user, $displayname); $this->currentUser = $previous_user; } @@ -99,7 +75,7 @@ trait Provisioning { return; } $previous_user = $this->currentUser; - $this->currentUser = "admin"; + $this->currentUser = 'admin'; $this->deletingTheUser($user); $this->currentUser = $previous_user; try { @@ -151,7 +127,7 @@ trait Provisioning { * @Then /^user "([^"]*)" has$/ * * @param string $user - * @param \Behat\Gherkin\Node\TableNode|null $settings + * @param TableNode|null $settings */ public function userHasSetting($user, $settings) { $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users/$user"; @@ -172,12 +148,43 @@ trait Provisioning { if (isset($value['element']) && in_array($setting[0], ['additional_mail', 'additional_mailScope'], true)) { $expectedValues = explode(';', $setting[1]); foreach ($expectedValues as $expected) { - Assert::assertTrue(in_array($expected, $value['element'], true)); + Assert::assertTrue(in_array($expected, $value['element'], true), 'Data wrong for field: ' . $setting[0]); } } elseif (isset($value[0])) { - Assert::assertEqualsCanonicalizing($setting[1], $value[0]); + Assert::assertEqualsCanonicalizing($setting[1], $value[0], 'Data wrong for field: ' . $setting[0]); } else { - Assert::assertEquals('', $setting[1]); + Assert::assertEquals('', $setting[1], 'Data wrong for field: ' . $setting[0]); + } + } + } + + /** + * @Then /^user "([^"]*)" has the following profile data$/ + */ + public function userHasProfileData(string $user, ?TableNode $settings): void { + $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/profile/$user"; + $client = new Client(); + $options = []; + if ($this->currentUser === 'admin') { + $options['auth'] = $this->adminUser; + } else { + $options['auth'] = [$this->currentUser, $this->regularUser]; + } + $options['headers'] = [ + 'OCS-APIREQUEST' => 'true', + 'Accept' => 'application/json', + ]; + + $response = $client->get($fullUrl, $options); + $body = $response->getBody()->getContents(); + $data = json_decode($body, true); + $data = $data['ocs']['data']; + foreach ($settings->getRows() as $setting) { + Assert::assertArrayHasKey($setting[0], $data, 'Profile data field missing: ' . $setting[0]); + if ($setting[1] === 'NULL') { + Assert::assertNull($data[$setting[0]], 'Profile data wrong for field: ' . $setting[0]); + } else { + Assert::assertEquals($setting[1], $data[$setting[0]], 'Profile data wrong for field: ' . $setting[0]); } } } @@ -186,7 +193,7 @@ trait Provisioning { * @Then /^group "([^"]*)" has$/ * * @param string $user - * @param \Behat\Gherkin\Node\TableNode|null $settings + * @param TableNode|null $settings */ public function groupHasSetting($group, $settings) { $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/groups/details?search=$group"; @@ -218,7 +225,7 @@ trait Provisioning { * @Then /^user "([^"]*)" has editable fields$/ * * @param string $user - * @param \Behat\Gherkin\Node\TableNode|null $fields + * @param TableNode|null $fields */ public function userHasEditableFields($user, $fields) { $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/user/fields"; @@ -248,9 +255,9 @@ trait Provisioning { * @Then /^search users by phone for region "([^"]*)" with$/ * * @param string $user - * @param \Behat\Gherkin\Node\TableNode|null $settings + * @param TableNode|null $settings */ - public function searchUserByPhone($region, \Behat\Gherkin\Node\TableNode $searchTable) { + public function searchUserByPhone($region, TableNode $searchTable) { $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users/search/by-phone"; $client = new Client(); $options = []; @@ -277,7 +284,7 @@ trait Provisioning { public function createUser($user) { $previous_user = $this->currentUser; - $this->currentUser = "admin"; + $this->currentUser = 'admin'; $this->creatingTheUser($user); $this->userExists($user); $this->currentUser = $previous_user; @@ -285,7 +292,7 @@ trait Provisioning { public function deleteUser($user) { $previous_user = $this->currentUser; - $this->currentUser = "admin"; + $this->currentUser = 'admin'; $this->deletingTheUser($user); $this->userDoesNotExist($user); $this->currentUser = $previous_user; @@ -293,7 +300,7 @@ trait Provisioning { public function createGroup($group) { $previous_user = $this->currentUser; - $this->currentUser = "admin"; + $this->currentUser = 'admin'; $this->creatingTheGroup($group); $this->groupExists($group); $this->currentUser = $previous_user; @@ -301,7 +308,7 @@ trait Provisioning { public function deleteGroup($group) { $previous_user = $this->currentUser; - $this->currentUser = "admin"; + $this->currentUser = 'admin'; $this->deletingTheGroup($group); $this->groupDoesNotExist($group); $this->currentUser = $previous_user; @@ -370,7 +377,7 @@ trait Provisioning { */ public function assureUserBelongsToGroup($user, $group) { $previous_user = $this->currentUser; - $this->currentUser = "admin"; + $this->currentUser = 'admin'; if (!$this->userBelongsToGroup($user, $group)) { $this->addingUserToGroup($user, $group); @@ -549,7 +556,7 @@ trait Provisioning { $this->groupExists($group); } catch (\GuzzleHttp\Exception\ClientException $ex) { $previous_user = $this->currentUser; - $this->currentUser = "admin"; + $this->currentUser = 'admin'; $this->creatingTheGroup($group); $this->currentUser = $previous_user; } @@ -570,7 +577,7 @@ trait Provisioning { return; } $previous_user = $this->currentUser; - $this->currentUser = "admin"; + $this->currentUser = 'admin'; $this->deletingTheGroup($group); $this->currentUser = $previous_user; try { @@ -651,10 +658,10 @@ trait Provisioning { /** * @Then /^users returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $usersList + * @param TableNode|null $usersList */ public function theUsersShouldBe($usersList) { - if ($usersList instanceof \Behat\Gherkin\Node\TableNode) { + if ($usersList instanceof TableNode) { $users = $usersList->getRows(); $usersSimplified = $this->simplifyArray($users); $respondedArray = $this->getArrayOfUsersResponded($this->response); @@ -664,10 +671,10 @@ trait Provisioning { /** * @Then /^phone matches returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $usersList + * @param TableNode|null $usersList */ public function thePhoneUsersShouldBe($usersList) { - if ($usersList instanceof \Behat\Gherkin\Node\TableNode) { + if ($usersList instanceof TableNode) { $users = $usersList->getRowsHash(); $listCheckedElements = simplexml_load_string($this->response->getBody())->data; $respondedArray = json_decode(json_encode($listCheckedElements), true); @@ -677,10 +684,10 @@ trait Provisioning { /** * @Then /^detailed users returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $usersList + * @param TableNode|null $usersList */ public function theDetailedUsersShouldBe($usersList) { - if ($usersList instanceof \Behat\Gherkin\Node\TableNode) { + if ($usersList instanceof TableNode) { $users = $usersList->getRows(); $usersSimplified = $this->simplifyArray($users); $respondedArray = $this->getArrayOfDetailedUsersResponded($this->response); @@ -691,10 +698,10 @@ trait Provisioning { /** * @Then /^groups returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $groupsList + * @param TableNode|null $groupsList */ public function theGroupsShouldBe($groupsList) { - if ($groupsList instanceof \Behat\Gherkin\Node\TableNode) { + if ($groupsList instanceof TableNode) { $groups = $groupsList->getRows(); $groupsSimplified = $this->simplifyArray($groups); $respondedArray = $this->getArrayOfGroupsResponded($this->response); @@ -704,10 +711,10 @@ trait Provisioning { /** * @Then /^subadmin groups returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $groupsList + * @param TableNode|null $groupsList */ public function theSubadminGroupsShouldBe($groupsList) { - if ($groupsList instanceof \Behat\Gherkin\Node\TableNode) { + if ($groupsList instanceof TableNode) { $groups = $groupsList->getRows(); $groupsSimplified = $this->simplifyArray($groups); $respondedArray = $this->getArrayOfSubadminsResponded($this->response); @@ -717,10 +724,10 @@ trait Provisioning { /** * @Then /^apps returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $appList + * @param TableNode|null $appList */ public function theAppsShouldBe($appList) { - if ($appList instanceof \Behat\Gherkin\Node\TableNode) { + if ($appList instanceof TableNode) { $apps = $appList->getRows(); $appsSimplified = $this->simplifyArray($apps); $respondedArray = $this->getArrayOfAppsResponded($this->response); @@ -730,7 +737,7 @@ trait Provisioning { /** * @Then /^subadmin users returned are$/ - * @param \Behat\Gherkin\Node\TableNode|null $groupsList + * @param TableNode|null $groupsList */ public function theSubadminUsersShouldBe($groupsList) { $this->theSubadminGroupsShouldBe($groupsList); @@ -802,7 +809,7 @@ trait Provisioning { * @param string $app */ public function appIsDisabled($app) { - $fullUrl = $this->baseUrl . "v2.php/cloud/apps?filter=disabled"; + $fullUrl = $this->baseUrl . 'v2.php/cloud/apps?filter=disabled'; $client = new Client(); $options = []; if ($this->currentUser === 'admin') { @@ -823,7 +830,7 @@ trait Provisioning { * @param string $app */ public function appIsEnabled($app) { - $fullUrl = $this->baseUrl . "v2.php/cloud/apps?filter=enabled"; + $fullUrl = $this->baseUrl . 'v2.php/cloud/apps?filter=enabled'; $client = new Client(); $options = []; if ($this->currentUser === 'admin') { @@ -847,7 +854,7 @@ trait Provisioning { * @param string $app */ public function appIsNotEnabled($app) { - $fullUrl = $this->baseUrl . "v2.php/cloud/apps?filter=enabled"; + $fullUrl = $this->baseUrl . 'v2.php/cloud/apps?filter=enabled'; $client = new Client(); $options = []; if ($this->currentUser === 'admin') { @@ -900,7 +907,7 @@ trait Provisioning { $this->response = $client->get($fullUrl, $options); // boolean to string is integer - Assert::assertEquals("1", simplexml_load_string($this->response->getBody())->data[0]->enabled); + Assert::assertEquals('1', simplexml_load_string($this->response->getBody())->data[0]->enabled); } /** @@ -909,13 +916,13 @@ trait Provisioning { * @param string $quota */ public function userHasAQuotaOf($user, $quota) { - $body = new \Behat\Gherkin\Node\TableNode([ + $body = new TableNode([ 0 => ['key', 'quota'], 1 => ['value', $quota], ]); // method used from BasicStructure trait - $this->sendingToWith("PUT", "/cloud/users/" . $user, $body); + $this->sendingToWith('PUT', '/cloud/users/' . $user, $body); } /** @@ -977,7 +984,7 @@ trait Provisioning { /** * @Then /^user "([^"]*)" has not$/ */ - public function userHasNotSetting($user, \Behat\Gherkin\Node\TableNode $settings) { + public function userHasNotSetting($user, TableNode $settings) { $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/cloud/users/$user"; $client = new Client(); $options = []; diff --git a/build/integration/features/bootstrap/RateLimitingContext.php b/build/integration/features/bootstrap/RateLimitingContext.php new file mode 100644 index 00000000000..15c8c5c8379 --- /dev/null +++ b/build/integration/features/bootstrap/RateLimitingContext.php @@ -0,0 +1,31 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +use Behat\Behat\Context\Context; + +class RateLimitingContext implements Context { + use BasicStructure; + use CommandLine; + use Provisioning; + + /** + * @BeforeScenario @RateLimiting + */ + public function enableRateLimiting() { + // Enable rate limiting for the tests. + // Ratelimiting is disabled by default, so we need to enable it + $this->runOcc(['config:system:set', 'ratelimit.protection.enabled', '--value', 'true', '--type', 'bool']); + } + + /** + * @AfterScenario @RateLimiting + */ + public function disableRateLimiting() { + // Restore the default rate limiting configuration. + // Ratelimiting is disabled by default, so we need to disable it + $this->runOcc(['config:system:set', 'ratelimit.protection.enabled', '--value', 'false', '--type', 'bool']); + } +} diff --git a/build/integration/features/bootstrap/RemoteContext.php b/build/integration/features/bootstrap/RemoteContext.php index a3e5e1b5007..6102f686ea7 100644 --- a/build/integration/features/bootstrap/RemoteContext.php +++ b/build/integration/features/bootstrap/RemoteContext.php @@ -1,28 +1,11 @@ <?php + /** - * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl> - * - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Robin Appelman <robin@icewind.nl> - * - * @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 */ use Behat\Behat\Context\Context; +use OCP\Http\Client\IClientService; use PHPUnit\Framework\Assert; require __DIR__ . '/../../vendor/autoload.php'; @@ -50,7 +33,7 @@ class RemoteContext implements Context { } protected function getApiClient() { - return new \OC\Remote\Api\OCS($this->remoteInstance, $this->credentails, \OC::$server->getHTTPClientService()); + return new \OC\Remote\Api\OCS($this->remoteInstance, $this->credentails, \OC::$server->get(IClientService::class)); } /** @@ -59,14 +42,14 @@ class RemoteContext implements Context { * @param string $remoteServer "NON_EXISTING" or "REMOTE" */ public function selectRemoteInstance($remoteServer) { - if ($remoteServer == "REMOTE") { + if ($remoteServer == 'REMOTE') { $baseUri = $this->remoteUrl; } else { $baseUri = 'nonexistingnextcloudserver.local'; } $this->lastException = null; try { - $this->remoteInstance = new \OC\Remote\Instance($baseUri, \OC::$server->getMemCacheFactory()->createLocal(), \OC::$server->getHTTPClientService()); + $this->remoteInstance = new \OC\Remote\Instance($baseUri, \OC::$server->getMemCacheFactory()->createLocal(), \OC::$server->get(IClientService::class)); // trigger the status request $this->remoteInstance->getProtocol(); } catch (\Exception $e) { diff --git a/build/integration/features/bootstrap/RoutingContext.php b/build/integration/features/bootstrap/RoutingContext.php new file mode 100644 index 00000000000..762570547e0 --- /dev/null +++ b/build/integration/features/bootstrap/RoutingContext.php @@ -0,0 +1,19 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +use Behat\Behat\Context\Context; +use Behat\Behat\Context\SnippetAcceptingContext; + +require __DIR__ . '/../../vendor/autoload.php'; + +class RoutingContext implements Context, SnippetAcceptingContext { + use Provisioning; + use AppConfiguration; + use CommandLine; + + protected function resetAppConfigs(): void { + } +} diff --git a/build/integration/features/bootstrap/Search.php b/build/integration/features/bootstrap/Search.php index c9d5f75a1d3..49a4fe92822 100644 --- a/build/integration/features/bootstrap/Search.php +++ b/build/integration/features/bootstrap/Search.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2018, Daniel Calviño Sánchez (danxuliu@gmail.com) - * - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * - * @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: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Gherkin\Node\TableNode; use PHPUnit\Framework\Assert; diff --git a/build/integration/features/bootstrap/SetupContext.php b/build/integration/features/bootstrap/SetupContext.php index 5abdb22ccfc..aa131cec597 100644 --- a/build/integration/features/bootstrap/SetupContext.php +++ b/build/integration/features/bootstrap/SetupContext.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Morris Jobke - * - * @author Morris Jobke <hey@morrisjobke.de> - * - * @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: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Behat\Context\Context; diff --git a/build/integration/features/bootstrap/ShareesContext.php b/build/integration/features/bootstrap/ShareesContext.php index 70e78e24929..37e0e63e547 100644 --- a/build/integration/features/bootstrap/ShareesContext.php +++ b/build/integration/features/bootstrap/ShareesContext.php @@ -1,26 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Joas Schilling <coding@schilljs.com> - * - * @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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Behat\Context\Context; use Behat\Behat\Context\SnippetAcceptingContext; diff --git a/build/integration/features/bootstrap/Sharing.php b/build/integration/features/bootstrap/Sharing.php index 146b1a35044..0cc490ff110 100644 --- a/build/integration/features/bootstrap/Sharing.php +++ b/build/integration/features/bootstrap/Sharing.php @@ -1,35 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2016 Sergio Bertolin <sbertolin@solidgear.es> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Julius Härtl <jus@bitgrid.net> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Sergio Bertolin <sbertolin@solidgear.es> - * @author Sergio Bertolín <sbertolin@solidgear.es> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Gherkin\Node\TableNode; use GuzzleHttp\Client; @@ -81,13 +55,19 @@ trait Sharing { $fd = $body->getRowsHash(); if (array_key_exists('expireDate', $fd)) { $dateModification = $fd['expireDate']; - $fd['expireDate'] = date('Y-m-d', strtotime($dateModification)); + if ($dateModification === 'null') { + $fd['expireDate'] = null; + } elseif (!empty($dateModification)) { + $fd['expireDate'] = date('Y-m-d', strtotime($dateModification)); + } else { + $fd['expireDate'] = ''; + } } $options['form_params'] = $fd; } try { - $this->response = $client->request("POST", $fullUrl, $options); + $this->response = $client->request('POST', $fullUrl, $options); } catch (\GuzzleHttp\Exception\ClientException $ex) { $this->response = $ex->getResponse(); } @@ -123,7 +103,7 @@ trait Sharing { public function acceptingLastShare() { $share_id = $this->lastShareData->data[0]->id; $url = "/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/pending/$share_id"; - $this->sendingToWith("POST", $url, null); + $this->sendingToWith('POST', $url, null); $this->theHTTPStatusCodeShouldBe('200'); } @@ -143,7 +123,7 @@ trait Sharing { $share_id = $this->lastShareData->data[0]->id; $url = "/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/pending/$share_id"; - $this->sendingToWith("POST", $url, null); + $this->sendingToWith('POST', $url, null); $this->currentUser = $previousUser; @@ -159,7 +139,7 @@ trait Sharing { } else { $url = $this->lastShareData->data->url; } - $fullUrl = $url . "/download"; + $fullUrl = $url . '/download'; $this->checkDownload($fullUrl, null, 'text/plain'); } @@ -173,7 +153,7 @@ trait Sharing { $token = $this->lastShareData->data->token; } - $fullUrl = substr($this->baseUrl, 0, -4) . "index.php/s/" . $token . "/download"; + $fullUrl = substr($this->baseUrl, 0, -4) . 'index.php/s/' . $token . '/download'; $this->checkDownload($fullUrl, null, 'text/plain'); } @@ -219,7 +199,7 @@ trait Sharing { * @When /^Adding expiration date to last share$/ */ public function addingExpirationDate() { - $share_id = (string) $this->lastShareData->data[0]->id; + $share_id = (string)$this->lastShareData->data[0]->id; $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/$share_id"; $client = new Client(); $options = []; @@ -228,9 +208,9 @@ trait Sharing { } else { $options['auth'] = [$this->currentUser, $this->regularUser]; } - $date = date('Y-m-d', strtotime("+3 days")); + $date = date('Y-m-d', strtotime('+3 days')); $options['form_params'] = ['expireDate' => $date]; - $this->response = $this->response = $client->request("PUT", $fullUrl, $options); + $this->response = $this->response = $client->request('PUT', $fullUrl, $options); Assert::assertEquals(200, $this->response->getStatusCode()); } @@ -239,7 +219,7 @@ trait Sharing { * @param TableNode|null $body */ public function updatingLastShare($body) { - $share_id = (string) $this->lastShareData->data[0]->id; + $share_id = (string)$this->lastShareData->data[0]->id; $fullUrl = $this->baseUrl . "v{$this->apiVersion}.php/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/$share_id"; $client = new Client(); $options = [ @@ -263,7 +243,7 @@ trait Sharing { } try { - $this->response = $client->request("PUT", $fullUrl, $options); + $this->response = $client->request('PUT', $fullUrl, $options); } catch (\GuzzleHttp\Exception\ClientException $ex) { $this->response = $ex->getResponse(); } @@ -311,13 +291,13 @@ trait Sharing { } if ($viewOnly === true) { - $body['attributes'] = json_encode([['scope' => 'permissions', 'key' => 'download', 'enabled' => false]]); + $body['attributes'] = json_encode([['scope' => 'permissions', 'key' => 'download', 'value' => false]]); } $options['form_params'] = $body; try { - $this->response = $client->request("POST", $fullUrl, $options); + $this->response = $client->request('POST', $fullUrl, $options); $this->lastShareData = simplexml_load_string($this->response->getBody()); } catch (\GuzzleHttp\Exception\ClientException $ex) { $this->response = $ex->getResponse(); @@ -328,16 +308,18 @@ trait Sharing { public function isFieldInResponse($field, $contentExpected) { $data = simplexml_load_string($this->response->getBody())->data[0]; if ((string)$field == 'expiration') { - $contentExpected = date('Y-m-d', strtotime($contentExpected)) . " 00:00:00"; + if (!empty($contentExpected)) { + $contentExpected = date('Y-m-d', strtotime($contentExpected)) . ' 00:00:00'; + } } if (count($data->element) > 0) { foreach ($data as $element) { - if ($contentExpected == "A_TOKEN") { + if ($contentExpected == 'A_TOKEN') { return (strlen((string)$element->$field) == 15); - } elseif ($contentExpected == "A_NUMBER") { + } elseif ($contentExpected == 'A_NUMBER') { return is_numeric((string)$element->$field); - } elseif ($contentExpected == "AN_URL") { - return $this->isExpectedUrl((string)$element->$field, "index.php/s/"); + } elseif ($contentExpected == 'AN_URL') { + return $this->isExpectedUrl((string)$element->$field, 'index.php/s/'); } elseif ((string)$element->$field == $contentExpected) { return true; } else { @@ -347,14 +329,16 @@ trait Sharing { return false; } else { - if ($contentExpected == "A_TOKEN") { + if ($contentExpected == 'A_TOKEN') { return (strlen((string)$data->$field) == 15); - } elseif ($contentExpected == "A_NUMBER") { + } elseif ($contentExpected == 'A_NUMBER') { return is_numeric((string)$data->$field); - } elseif ($contentExpected == "AN_URL") { - return $this->isExpectedUrl((string)$data->$field, "index.php/s/"); + } elseif ($contentExpected == 'AN_URL') { + return $this->isExpectedUrl((string)$data->$field, 'index.php/s/'); } elseif ($contentExpected == $data->$field) { return true; + } else { + print($data->$field); } return false; } @@ -478,7 +462,7 @@ trait Sharing { public function deletingLastShare() { $share_id = $this->lastShareData->data[0]->id; $url = "/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/$share_id"; - $this->sendingToWith("DELETE", $url, null); + $this->sendingToWith('DELETE', $url, null); } /** @@ -487,7 +471,7 @@ trait Sharing { public function gettingInfoOfLastShare() { $share_id = $this->lastShareData->data[0]->id; $url = "/apps/files_sharing/api/v{$this->sharingApiVersion}/shares/$share_id"; - $this->sendingToWith("GET", $url, null); + $this->sendingToWith('GET', $url, null); } /** @@ -519,13 +503,13 @@ trait Sharing { $fd = $body->getRowsHash(); foreach ($fd as $field => $value) { - if (substr($field, 0, 10) === "share_with") { - $value = str_replace("REMOTE", substr($this->remoteBaseUrl, 0, -5), $value); - $value = str_replace("LOCAL", substr($this->localBaseUrl, 0, -5), $value); + if (substr($field, 0, 10) === 'share_with') { + $value = str_replace('REMOTE', substr($this->remoteBaseUrl, 0, -5), $value); + $value = str_replace('LOCAL', substr($this->localBaseUrl, 0, -5), $value); } - if (substr($field, 0, 6) === "remote") { - $value = str_replace("REMOTE", substr($this->remoteBaseUrl, 0, -4), $value); - $value = str_replace("LOCAL", substr($this->localBaseUrl, 0, -4), $value); + if (substr($field, 0, 6) === 'remote') { + $value = str_replace('REMOTE', substr($this->remoteBaseUrl, 0, -4), $value); + $value = str_replace('LOCAL', substr($this->localBaseUrl, 0, -4), $value); } if (!$this->isFieldInResponse($field, $value)) { Assert::fail("$field" . " doesn't have value " . "$value"); @@ -580,18 +564,18 @@ trait Sharing { ]; $expectedFields = array_merge($defaultExpectedFields, $body->getRowsHash()); - if (!array_key_exists('uid_file_owner', $expectedFields) && - array_key_exists('uid_owner', $expectedFields)) { + if (!array_key_exists('uid_file_owner', $expectedFields) + && array_key_exists('uid_owner', $expectedFields)) { $expectedFields['uid_file_owner'] = $expectedFields['uid_owner']; } - if (!array_key_exists('displayname_file_owner', $expectedFields) && - array_key_exists('displayname_owner', $expectedFields)) { + if (!array_key_exists('displayname_file_owner', $expectedFields) + && array_key_exists('displayname_owner', $expectedFields)) { $expectedFields['displayname_file_owner'] = $expectedFields['displayname_owner']; } - if (array_key_exists('share_type', $expectedFields) && - $expectedFields['share_type'] == 10 /* IShare::TYPE_ROOM */ && - array_key_exists('share_with', $expectedFields)) { + if (array_key_exists('share_type', $expectedFields) + && $expectedFields['share_type'] == 10 /* IShare::TYPE_ROOM */ + && array_key_exists('share_with', $expectedFields)) { if ($expectedFields['share_with'] === 'private_conversation') { $expectedFields['share_with'] = 'REGEXP /^private_conversation_[0-9a-f]{6}$/'; } else { @@ -626,7 +610,7 @@ trait Sharing { } if ($field === 'expiration' && !empty($contentExpected)) { - $contentExpected = date('Y-m-d', strtotime($contentExpected)) . " 00:00:00"; + $contentExpected = date('Y-m-d', strtotime($contentExpected)) . ' 00:00:00'; } if ($contentExpected === 'A_NUMBER') { diff --git a/build/integration/features/bootstrap/SharingContext.php b/build/integration/features/bootstrap/SharingContext.php index f187e89f08f..a9dd99108a9 100644 --- a/build/integration/features/bootstrap/SharingContext.php +++ b/build/integration/features/bootstrap/SharingContext.php @@ -1,26 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2016 John Molakvoæ <skjnldsv@protonmail.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * - * @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: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Behat\Context\Context; use Behat\Behat\Context\SnippetAcceptingContext; @@ -36,6 +18,7 @@ class SharingContext implements Context, SnippetAcceptingContext { use Trashbin; use AppConfiguration; use CommandLine; + use Activity; protected function resetAppConfigs() { $this->deleteServerConfig('core', 'shareapi_default_permissions'); @@ -46,6 +29,9 @@ class SharingContext implements Context, SnippetAcceptingContext { $this->deleteServerConfig('core', 'shareapi_default_expire_date'); $this->deleteServerConfig('core', 'shareapi_expire_after_n_days'); $this->deleteServerConfig('core', 'link_defaultExpDays'); + $this->deleteServerConfig('core', 'shareapi_allow_federation_on_public_shares'); + $this->deleteServerConfig('files_sharing', 'outgoing_server2server_share_enabled'); + $this->deleteServerConfig('core', 'shareapi_allow_view_without_download'); $this->runOcc(['config:system:delete', 'share_folder']); } diff --git a/build/integration/features/bootstrap/TagsContext.php b/build/integration/features/bootstrap/TagsContext.php index ecef9c08b1e..c64626de68d 100644 --- a/build/integration/features/bootstrap/TagsContext.php +++ b/build/integration/features/bootstrap/TagsContext.php @@ -1,30 +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 Phil Davis <phil.davis@inf.org> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Sergio Bertolin <sbertolin@solidgear.es> - * @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-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ require __DIR__ . '/../../vendor/autoload.php'; @@ -267,7 +246,7 @@ class TagsContext implements \Behat\Behat\Context\Context { if (count($table->getRows()) !== count($tags)) { throw new \Exception( sprintf( - "Expected %s tags, got %s.", + 'Expected %s tags, got %s.', count($table->getRows()), count($tags) ) @@ -277,9 +256,9 @@ class TagsContext implements \Behat\Behat\Context\Context { foreach ($table->getRowsHash() as $rowDisplayName => $row) { foreach ($tags as $key => $tag) { if ( - $tag['display-name'] === $rowDisplayName && - $tag['user-visible'] === $row[0] && - $tag['user-assignable'] === $row[1] + $tag['display-name'] === $rowDisplayName + && $tag['user-visible'] === $row[0] + && $tag['user-assignable'] === $row[1] ) { unset($tags[$key]); } diff --git a/build/integration/features/bootstrap/TalkContext.php b/build/integration/features/bootstrap/TalkContext.php index 5417c22a058..6f351c30ccf 100644 --- a/build/integration/features/bootstrap/TalkContext.php +++ b/build/integration/features/bootstrap/TalkContext.php @@ -1,24 +1,8 @@ <?php + /** - * @copyright Copyright (c) 2020, Daniel Calviño Sánchez (danxuliu@gmail.com) - * - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * - * @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: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ use Behat\Behat\Context\Context; diff --git a/build/integration/features/bootstrap/Theming.php b/build/integration/features/bootstrap/Theming.php new file mode 100644 index 00000000000..f44a6533a1b --- /dev/null +++ b/build/integration/features/bootstrap/Theming.php @@ -0,0 +1,49 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +require __DIR__ . '/../../vendor/autoload.php'; + +trait Theming { + + private bool $undoAllThemingChangesAfterScenario = false; + + /** + * @AfterScenario + */ + public function undoAllThemingChanges() { + if (!$this->undoAllThemingChangesAfterScenario) { + return; + } + + $this->loggingInUsingWebAs('admin'); + $this->sendingAToWithRequesttoken('POST', '/index.php/apps/theming/ajax/undoAllChanges'); + + $this->undoAllThemingChangesAfterScenario = false; + } + + /** + * @When logged in admin uploads theming image for :key from file :source + * + * @param string $key + * @param string $source + */ + public function loggedInAdminUploadsThemingImageForFromFile(string $key, string $source) { + $this->undoAllThemingChangesAfterScenario = true; + + $file = \GuzzleHttp\Psr7\Utils::streamFor(fopen($source, 'r')); + + $this->sendingAToWithRequesttoken('POST', '/index.php/apps/theming/ajax/uploadImage?key=' . $key, + [ + 'multipart' => [ + [ + 'name' => 'image', + 'contents' => $file + ] + ] + ]); + $this->theHTTPStatusCodeShouldBe('200'); + } +} diff --git a/build/integration/features/bootstrap/Trashbin.php b/build/integration/features/bootstrap/Trashbin.php index 19e9b57c3fb..dfcc23289a7 100644 --- a/build/integration/features/bootstrap/Trashbin.php +++ b/build/integration/features/bootstrap/Trashbin.php @@ -1,26 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2017, ownCloud GmbH. - * - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Robin Appelman <robin@icewind.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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2017 ownCloud GmbH + * SPDX-License-Identifier: AGPL-3.0-only */ use DMS\PHPUnitExtensions\ArraySubset\Assert as AssertArraySubset; use PHPUnit\Framework\Assert; @@ -115,7 +98,7 @@ trait Trashbin { foreach ($elementsSimplified as $expectedElement) { $expectedElement = ltrim($expectedElement, '/'); if (array_search($expectedElement, $trashContent) === false) { - Assert::fail("$expectedElement" . " is not in trash listing"); + Assert::fail("$expectedElement" . ' is not in trash listing'); } } } diff --git a/build/integration/features/bootstrap/WebDav.php b/build/integration/features/bootstrap/WebDav.php index a832e26ec18..2cb37002ac0 100644 --- a/build/integration/features/bootstrap/WebDav.php +++ b/build/integration/features/bootstrap/WebDav.php @@ -1,36 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2016 Sergio Bertolin <sbertolin@solidgear.es> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author David Toledo <dtoledo@solidgear.es> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Maxence Lange <maxence@artificial-owl.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Sergio Bertolin <sbertolin@solidgear.es> - * @author Sergio Bertolín <sbertolin@solidgear.es> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @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: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ use GuzzleHttp\Client as GClient; @@ -45,7 +18,7 @@ require __DIR__ . '/../../vendor/autoload.php'; trait WebDav { use Sharing; - private string $davPath = "remote.php/webdav"; + private string $davPath = 'remote.php/webdav'; private bool $usingOldDavPath = true; private ?array $storedETAG = null; // map with user as key and another map as value, which has path as key and etag as value private ?int $storedFileID = null; @@ -68,7 +41,7 @@ trait WebDav { * @Given /^using old dav path$/ */ public function usingOldDavPath() { - $this->davPath = "remote.php/webdav"; + $this->davPath = 'remote.php/webdav'; $this->usingOldDavPath = true; } @@ -76,7 +49,15 @@ trait WebDav { * @Given /^using new dav path$/ */ public function usingNewDavPath() { - $this->davPath = "remote.php/dav"; + $this->davPath = 'remote.php/dav'; + $this->usingOldDavPath = false; + } + + /** + * @Given /^using new public dav path$/ + */ + public function usingNewPublicDavPath() { + $this->davPath = 'public.php/dav'; $this->usingOldDavPath = false; } @@ -88,13 +69,13 @@ trait WebDav { } } - public function makeDavRequest($user, $method, $path, $headers, $body = null, $type = "files") { - if ($type === "files") { + public function makeDavRequest($user, $method, $path, $headers, $body = null, $type = 'files') { + if ($type === 'files') { $fullUrl = substr($this->baseUrl, 0, -4) . $this->getDavFilesPath($user) . "$path"; - } elseif ($type === "uploads") { + } elseif ($type === 'uploads') { $fullUrl = substr($this->baseUrl, 0, -4) . $this->davPath . "$path"; } else { - $fullUrl = substr($this->baseUrl, 0, -4) . $this->davPath . '/' . $type . "$path"; + $fullUrl = substr($this->baseUrl, 0, -4) . $this->davPath . '/' . $type . "$path"; } $client = new GClient(); $options = [ @@ -103,7 +84,7 @@ trait WebDav { ]; if ($user === 'admin') { $options['auth'] = $this->adminUser; - } else { + } elseif ($user !== '') { $options['auth'] = [$user, $this->regularUser]; } return $client->request($method, $fullUrl, $options); @@ -118,7 +99,7 @@ trait WebDav { public function userMovedFile($user, $entry, $fileSource, $fileDestination) { $fullUrl = substr($this->baseUrl, 0, -4) . $this->getDavFilesPath($user); $headers['Destination'] = $fullUrl . $fileDestination; - $this->response = $this->makeDavRequest($user, "MOVE", $fileSource, $headers); + $this->response = $this->makeDavRequest($user, 'MOVE', $fileSource, $headers); Assert::assertEquals(201, $this->response->getStatusCode()); } @@ -132,7 +113,7 @@ trait WebDav { $fullUrl = substr($this->baseUrl, 0, -4) . $this->getDavFilesPath($user); $headers['Destination'] = $fullUrl . $fileDestination; try { - $this->response = $this->makeDavRequest($user, "MOVE", $fileSource, $headers); + $this->response = $this->makeDavRequest($user, 'MOVE', $fileSource, $headers); } catch (\GuzzleHttp\Exception\ClientException $e) { $this->response = $e->getResponse(); } @@ -162,7 +143,7 @@ trait WebDav { */ public function downloadFileWithRange($fileSource, $range) { $headers['Range'] = $range; - $this->response = $this->makeDavRequest($this->currentUser, "GET", $fileSource, $headers); + $this->response = $this->makeDavRequest($this->currentUser, 'GET', $fileSource, $headers); } /** @@ -179,7 +160,7 @@ trait WebDav { 'Range' => $range ]; - $this->response = $client->request("GET", $fullUrl, $options); + $this->response = $client->request('GET', $fullUrl, $options); } /** @@ -197,7 +178,7 @@ trait WebDav { ] ]; - $this->response = $client->request("GET", $fullUrl, $options); + $this->response = $client->request('GET', $fullUrl, $options); } /** @@ -217,7 +198,7 @@ trait WebDav { */ public function checkPropForFile($file, $prefix, $prop, $value) { $elementList = $this->propfindFile($this->currentUser, $file, "<$prefix:$prop/>"); - $property = $elementList['/'.$this->getDavFilesPath($this->currentUser).$file][200]["{DAV:}$prop"]; + $property = $elementList['/' . $this->getDavFilesPath($this->currentUser) . $file][200]["{DAV:}$prop"]; Assert::assertEquals($property, $value); } @@ -259,6 +240,37 @@ trait WebDav { } /** + * @When Downloading folder :folderName + */ + public function downloadingFolder(string $folderName) { + try { + $this->response = $this->makeDavRequest($this->currentUser, 'GET', $folderName, ['Accept' => 'application/zip']); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** + * @When Downloading public folder :folderName + */ + public function downloadPublicFolder(string $folderName) { + $token = $this->lastShareData->data->token; + $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/dav/files/$token/$folderName"; + + $client = new GClient(); + $options = []; + $options['headers'] = [ + 'Accept' => 'application/zip' + ]; + + try { + $this->response = $client->request('GET', $fullUrl, $options); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** * @When Downloading file :fileName * @param string $fileName */ @@ -271,6 +283,42 @@ trait WebDav { } /** + * @When Downloading public file :filename + */ + public function downloadingPublicFile(string $filename) { + $token = $this->lastShareData->data->token; + $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/dav/files/$token/$filename"; + + $client = new GClient(); + $options = [ + 'headers' => [ + 'X-Requested-With' => 'XMLHttpRequest', + ] + ]; + + try { + $this->response = $client->request('GET', $fullUrl, $options); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** + * @When Downloading public file :filename without ajax header + */ + public function downloadingPublicFileWithoutHeader(string $filename) { + $token = $this->lastShareData->data->token; + $fullUrl = substr($this->baseUrl, 0, -4) . "public.php/dav/files/$token/$filename"; + + $client = new GClient(); + try { + $this->response = $client->request('GET', $fullUrl); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** * @Then Downloaded content should start with :start * @param int $start * @throws \Exception @@ -376,7 +424,7 @@ trait WebDav { public function theResponseShouldContainAShareTypesPropertyWith($table) { $keys = $this->response; if (!array_key_exists('{http://owncloud.org/ns}share-types', $keys)) { - throw new \Exception("Cannot find property \"{http://owncloud.org/ns}share-types\""); + throw new \Exception('Cannot find property "{http://owncloud.org/ns}share-types"'); } $foundTypes = []; @@ -541,7 +589,7 @@ trait WebDav { </d:searchrequest>'; try { - $this->response = $this->makeDavRequest($user, "SEARCH", '', [ + $this->response = $this->makeDavRequest($user, 'SEARCH', '', [ 'Content-Type' => 'text/xml' ], $body, ''); @@ -583,7 +631,7 @@ trait WebDav { if ($type === 'files') { return $this->encodePath($this->getDavFilesPath($user) . $path); } else { - return $this->encodePath($this->davPath . '/' . $type . '/' . $user . '/' . $path); + return $this->encodePath($this->davPath . '/' . $type . '/' . $user . '/' . $path); } } @@ -616,9 +664,9 @@ trait WebDav { $elementRows = $expectedElements->getRows(); $elementsSimplified = $this->simplifyArray($elementRows); foreach ($elementsSimplified as $expectedElement) { - $webdavPath = "/" . $this->getDavFilesPath($user) . $expectedElement; + $webdavPath = '/' . $this->getDavFilesPath($user) . $expectedElement; if (!array_key_exists($webdavPath, $elementList)) { - Assert::fail("$webdavPath" . " is not in propfind answer"); + Assert::fail("$webdavPath" . ' is not in propfind answer'); } } } @@ -633,7 +681,7 @@ trait WebDav { public function userUploadsAFileTo($user, $source, $destination) { $file = \GuzzleHttp\Psr7\Utils::streamFor(fopen($source, 'r')); try { - $this->response = $this->makeDavRequest($user, "PUT", $destination, [], $file); + $this->response = $this->makeDavRequest($user, 'PUT', $destination, [], $file); } catch (\GuzzleHttp\Exception\ServerException $e) { // 5xx responses cause a server exception $this->response = $e->getResponse(); @@ -650,11 +698,11 @@ trait WebDav { * @param string $destination */ public function userAddsAFileTo($user, $bytes, $destination) { - $filename = "filespecificSize.txt"; + $filename = 'filespecificSize.txt'; $this->createFileSpecificSize($filename, $bytes); Assert::assertEquals(1, file_exists("work/$filename")); $this->userUploadsAFileTo($user, "work/$filename", $destination); - $this->removeFile("work/", $filename); + $this->removeFile('work/', $filename); $expectedElements = new \Behat\Gherkin\Node\TableNode([["$destination"]]); $this->checkElementList($user, $expectedElements); } @@ -665,7 +713,7 @@ trait WebDav { public function userUploadsAFileWithContentTo($user, $content, $destination) { $file = \GuzzleHttp\Psr7\Utils::streamFor($content); try { - $this->response = $this->makeDavRequest($user, "PUT", $destination, [], $file); + $this->response = $this->makeDavRequest($user, 'PUT', $destination, [], $file); } catch (\GuzzleHttp\Exception\ServerException $e) { // 5xx responses cause a server exception $this->response = $e->getResponse(); @@ -701,7 +749,7 @@ trait WebDav { public function userCreatedAFolder($user, $destination) { try { $destination = '/' . ltrim($destination, '/'); - $this->response = $this->makeDavRequest($user, "MKCOL", $destination, []); + $this->response = $this->makeDavRequest($user, 'MKCOL', $destination, []); } catch (\GuzzleHttp\Exception\ServerException $e) { // 5xx responses cause a server exception $this->response = $e->getResponse(); @@ -712,21 +760,6 @@ trait WebDav { } /** - * @Given user :user uploads chunk file :num of :total with :data to :destination - * @param string $user - * @param int $num - * @param int $total - * @param string $data - * @param string $destination - */ - public function userUploadsChunkFileOfWithToWithChecksum($user, $num, $total, $data, $destination) { - $num -= 1; - $data = \GuzzleHttp\Psr7\Utils::streamFor($data); - $file = $destination . '-chunking-42-' . $total . '-' . $num; - $this->makeDavRequest($user, 'PUT', $file, ['OC-Chunked' => '1'], $data, "uploads"); - } - - /** * @Given user :user uploads bulked files :name1 with :content1 and :name2 with :content2 and :name3 with :content3 * @param string $user * @param string $name1 @@ -737,31 +770,31 @@ trait WebDav { * @param string $content3 */ public function userUploadsBulkedFiles($user, $name1, $content1, $name2, $content2, $name3, $content3) { - $boundary = "boundary_azertyuiop"; + $boundary = 'boundary_azertyuiop'; - $body = ""; - $body .= '--'.$boundary."\r\n"; - $body .= "X-File-Path: ".$name1."\r\n"; + $body = ''; + $body .= '--' . $boundary . "\r\n"; + $body .= 'X-File-Path: ' . $name1 . "\r\n"; $body .= "X-File-MD5: f6a6263167c92de8644ac998b3c4e4d1\r\n"; $body .= "X-OC-Mtime: 1111111111\r\n"; - $body .= "Content-Length: ".strlen($content1)."\r\n"; + $body .= 'Content-Length: ' . strlen($content1) . "\r\n"; $body .= "\r\n"; - $body .= $content1."\r\n"; - $body .= '--'.$boundary."\r\n"; - $body .= "X-File-Path: ".$name2."\r\n"; + $body .= $content1 . "\r\n"; + $body .= '--' . $boundary . "\r\n"; + $body .= 'X-File-Path: ' . $name2 . "\r\n"; $body .= "X-File-MD5: 87c7d4068be07d390a1fffd21bf1e944\r\n"; $body .= "X-OC-Mtime: 2222222222\r\n"; - $body .= "Content-Length: ".strlen($content2)."\r\n"; + $body .= 'Content-Length: ' . strlen($content2) . "\r\n"; $body .= "\r\n"; - $body .= $content2."\r\n"; - $body .= '--'.$boundary."\r\n"; - $body .= "X-File-Path: ".$name3."\r\n"; + $body .= $content2 . "\r\n"; + $body .= '--' . $boundary . "\r\n"; + $body .= 'X-File-Path: ' . $name3 . "\r\n"; $body .= "X-File-MD5: e86a1cf0678099986a901c79086f5617\r\n"; $body .= "X-File-Mtime: 3333333333\r\n"; - $body .= "Content-Length: ".strlen($content3)."\r\n"; + $body .= 'Content-Length: ' . strlen($content3) . "\r\n"; $body .= "\r\n"; - $body .= $content3."\r\n"; - $body .= '--'.$boundary."--\r\n"; + $body .= $content3 . "\r\n"; + $body .= '--' . $boundary . "--\r\n"; $stream = fopen('php://temp', 'r+'); fwrite($stream, $body); @@ -771,13 +804,13 @@ trait WebDav { $options = [ 'auth' => [$user, $this->regularUser], 'headers' => [ - 'Content-Type' => 'multipart/related; boundary='.$boundary, + 'Content-Type' => 'multipart/related; boundary=' . $boundary, 'Content-Length' => (string)strlen($body), ], 'body' => $body ]; - return $client->request("POST", substr($this->baseUrl, 0, -4) . "remote.php/dav/bulk", $options); + return $client->request('POST', substr($this->baseUrl, 0, -4) . 'remote.php/dav/bulk', $options); } /** @@ -786,7 +819,7 @@ trait WebDav { public function userCreatesANewChunkingUploadWithId($user, $id) { $this->parts = []; $destination = '/uploads/' . $user . '/' . $id; - $this->makeDavRequest($user, 'MKCOL', $destination, [], null, "uploads"); + $this->makeDavRequest($user, 'MKCOL', $destination, [], null, 'uploads'); } /** @@ -795,7 +828,7 @@ trait WebDav { public function userUploadsNewChunkFileOfWithToId($user, $num, $data, $id) { $data = \GuzzleHttp\Psr7\Utils::streamFor($data); $destination = '/uploads/' . $user . '/' . $id . '/' . $num; - $this->makeDavRequest($user, 'PUT', $destination, [], $data, "uploads"); + $this->makeDavRequest($user, 'PUT', $destination, [], $data, 'uploads'); } /** @@ -806,7 +839,7 @@ trait WebDav { $destination = substr($this->baseUrl, 0, -4) . $this->getDavFilesPath($user) . $dest; $this->makeDavRequest($user, 'MOVE', $source, [ 'Destination' => $destination - ], null, "uploads"); + ], null, 'uploads'); } /** @@ -820,7 +853,7 @@ trait WebDav { $this->response = $this->makeDavRequest($user, 'MOVE', $source, [ 'Destination' => $destination, 'OC-Total-Length' => $size - ], null, "uploads"); + ], null, 'uploads'); } catch (\GuzzleHttp\Exception\BadResponseException $ex) { $this->response = $ex->getResponse(); } @@ -836,7 +869,7 @@ trait WebDav { $destination = '/uploads/' . $user . '/' . $this->getUploadId($id); $this->response = $this->makeDavRequest($user, 'MKCOL', $destination, [ 'Destination' => $this->s3MultipartDestination, - ], null, "uploads"); + ], null, 'uploads'); } /** @@ -847,7 +880,7 @@ trait WebDav { $destination = '/uploads/' . $user . '/' . $this->getUploadId($id) . '/' . $num; $this->response = $this->makeDavRequest($user, 'PUT', $destination, [ 'Destination' => $this->s3MultipartDestination - ], $data, "uploads"); + ], $data, 'uploads'); } /** @@ -858,7 +891,7 @@ trait WebDav { try { $this->response = $this->makeDavRequest($user, 'MOVE', $source, [ 'Destination' => $this->s3MultipartDestination, - ], null, "uploads"); + ], null, 'uploads'); } catch (\GuzzleHttp\Exception\ServerException $e) { // 5xx responses cause a server exception $this->response = $e->getResponse(); @@ -985,6 +1018,23 @@ trait WebDav { } /** + * @When Requesting share note on dav endpoint + */ + public function requestingShareNote() { + $propfind = '<d:propfind xmlns:d="DAV:" xmlns:nc="http://nextcloud.org/ns"><d:prop><nc:note /></d:prop></d:propfind>'; + if (count($this->lastShareData->data->element) > 0) { + $token = $this->lastShareData->data[0]->token; + } else { + $token = $this->lastShareData->data->token; + } + try { + $this->response = $this->makeDavRequest('', 'PROPFIND', $token, [], $propfind); + } catch (\GuzzleHttp\Exception\ClientException $e) { + $this->response = $e->getResponse(); + } + } + + /** * @Then there are no duplicate headers */ public function thereAreNoDuplicateHeaders() { @@ -1012,9 +1062,9 @@ trait WebDav { $elementRows = $expectedElements->getRows(); $elementsSimplified = $this->simplifyArray($elementRows); foreach ($elementsSimplified as $expectedElement) { - $webdavPath = "/" . $this->getDavFilesPath($user) . $expectedElement; + $webdavPath = '/' . $this->getDavFilesPath($user) . $expectedElement; if (!array_key_exists($webdavPath, $elementList)) { - Assert::fail("$webdavPath" . " is not in report answer"); + Assert::fail("$webdavPath" . ' is not in report answer'); } } } @@ -1029,12 +1079,12 @@ trait WebDav { $elementList = $this->listFolder($user, $folder, 1); $elementListKeys = array_keys($elementList); array_shift($elementListKeys); - $davPrefix = "/" . $this->getDavFilesPath($user); + $davPrefix = '/' . $this->getDavFilesPath($user); foreach ($elementListKeys as $element) { if (substr($element, 0, strlen($davPrefix)) == $davPrefix) { $element = substr($element, strlen($davPrefix)); } - $this->userDeletesFile($user, "element", $element); + $this->userDeletesFile($user, 'element', $element); } } @@ -1045,7 +1095,7 @@ trait WebDav { * @return int */ private function getFileIdForPath($user, $path) { - $propertiesTable = new \Behat\Gherkin\Node\TableNode([["{http://owncloud.org/ns}fileid"]]); + $propertiesTable = new \Behat\Gherkin\Node\TableNode([['{http://owncloud.org/ns}fileid']]); $this->asGetsPropertiesOfFolderWith($user, 'file', $path, $propertiesTable); return (int)$this->response['{http://owncloud.org/ns}fileid']; } @@ -1075,7 +1125,7 @@ trait WebDav { public function userCreatesAFileLocallyWithChunks($arg1, $chunks) { $this->parts = []; for ($i = 1;$i <= (int)$chunks;$i++) { - $randomletter = substr(str_shuffle("abcdefghijklmnopqrstuvwxyz"), 0, 1); + $randomletter = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 1); file_put_contents('/tmp/part-upload-' . $i, str_repeat($randomletter, 5 * 1024 * 1024)); $this->parts[] = '/tmp/part-upload-' . $i; } @@ -1085,7 +1135,7 @@ trait WebDav { * @Given user :user creates the chunk :id with a size of :size MB */ public function userCreatesAChunk($user, $id, $size) { - $randomletter = substr(str_shuffle("abcdefghijklmnopqrstuvwxyz"), 0, 1); + $randomletter = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 1); file_put_contents('/tmp/part-upload-' . $id, str_repeat($randomletter, (int)$size * 1024 * 1024)); $this->parts[] = '/tmp/part-upload-' . $id; } diff --git a/build/integration/features/contacts-menu.feature b/build/integration/features/contacts-menu.feature index d058644867c..772c0e5405c 100644 --- a/build/integration/features/contacts-menu.feature +++ b/build/integration/features/contacts-menu.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: contacts-menu Scenario: users can be searched by display name @@ -69,8 +71,6 @@ Feature: contacts-menu And searched contact "1" is named "Test name" And searched contact "2" is named "user2" - - Scenario: users can not be found by display name if visibility is private Given user "user0" exists And user "user1" exists @@ -78,11 +78,11 @@ Feature: contacts-menu And Logging in using web as "user1" And Sending a "PUT" to "/settings/users/user1/settings" with requesttoken | displayname | Test name | - | displaynameScope | private | + | displaynameScope | v2-private | And Logging in using web as "user2" And Sending a "PUT" to "/settings/users/user2/settings" with requesttoken | displayname | Another test name | - | displaynameScope | contacts | + | displaynameScope | v2-federated | When Logging in using web as "user0" And searching for contacts matching with "test" # Disabled because it regularly fails on drone: @@ -96,11 +96,11 @@ Feature: contacts-menu And Logging in using web as "user1" And Sending a "PUT" to "/settings/users/user1/settings" with requesttoken | email | test@example.com | - | emailScope | private | + | emailScope | v2-private | And Logging in using web as "user2" And Sending a "PUT" to "/settings/users/user2/settings" with requesttoken | email | another_test@example.com | - | emailScope | contacts | + | emailScope | v2-federated | # Disabled because it regularly fails on drone: # When Logging in using web as "user0" # And searching for contacts matching with "test" @@ -114,15 +114,15 @@ Feature: contacts-menu And Logging in using web as "user1" And Sending a "PUT" to "/settings/users/user1/settings" with requesttoken | displayname | Test name | - | displaynameScope | contacts | + | displaynameScope | v2-federated | | email | test@example.com | - | emailScope | private | + | emailScope | v2-private | And Logging in using web as "user2" And Sending a "PUT" to "/settings/users/user2/settings" with requesttoken | displayname | Another test name | - | displaynameScope | private | + | displaynameScope | v2-private | | email | another_test@example.com | - | emailScope | contacts | + | emailScope | v2-federated | When Logging in using web as "user0" And searching for contacts matching with "test" Then the list of searched contacts has "2" contacts @@ -138,9 +138,9 @@ Feature: contacts-menu And Logging in using web as "user1" And Sending a "PUT" to "/settings/users/user1/settings" with requesttoken | displayname | Test name | - | displaynameScope | private | + | displaynameScope | v2-private | And Sending a "PUT" to "/settings/users/user1/settings" with requesttoken - | displaynameScope | contacts | + | displaynameScope | v2-federated | When Logging in using web as "user0" And searching for contacts matching with "test" Then the list of searched contacts has "1" contacts @@ -152,9 +152,9 @@ Feature: contacts-menu And Logging in using web as "user1" And Sending a "PUT" to "/settings/users/user1/settings" with requesttoken | email | test@example.com | - | emailScope | private | + | emailScope | v2-private | And Sending a "PUT" to "/settings/users/user1/settings" with requesttoken - | emailScope | contacts | + | emailScope | v2-federated | # Disabled because it regularly fails on drone: # When Logging in using web as "user0" # And searching for contacts matching with "test" @@ -168,7 +168,7 @@ Feature: contacts-menu And user "user1" exists And Logging in using web as "user1" And Sending a "PUT" to "/settings/users/user1/settings" with requesttoken - | displaynameScope | private | + | displaynameScope | v2-private | And As an "admin" And sending "PUT" to "/cloud/users/user1" with | key | displayname | @@ -183,7 +183,7 @@ Feature: contacts-menu And user "user1" exists And Logging in using web as "user1" And Sending a "PUT" to "/settings/users/user1/settings" with requesttoken - | emailScope | private | + | emailScope | v2-private | And As an "admin" And sending "PUT" to "/cloud/users/user1" with | key | email | diff --git a/build/integration/features/log-condition.feature b/build/integration/features/log-condition.feature new file mode 100644 index 00000000000..4059db1ebf3 --- /dev/null +++ b/build/integration/features/log-condition.feature @@ -0,0 +1,39 @@ +# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +Feature: log-condition + + Background: + Given invoking occ with "config:system:set log.condition matches 0 users 0 --value admin" + Then the command was successful + + Scenario: Accessing /status.php with log.condition + When requesting "/status.php" with "GET" + Then the HTTP status code should be "200" + + Scenario: Accessing /index.php with log.condition + When requesting "/index.php" with "GET" + Then the HTTP status code should be "200" + + Scenario: Accessing /remote.php/webdav with log.condition + When requesting "/remote.php/webdav" with "GET" + Then the HTTP status code should be "401" + + Scenario: Accessing /remote.php/dav with log.condition + When requesting "/remote.php/dav" with "GET" + Then the HTTP status code should be "401" + + Scenario: Accessing /ocs/v1.php with log.condition + When requesting "/ocs/v1.php" with "GET" + Then the HTTP status code should be "200" + + Scenario: Accessing /ocs/v2.php with log.condition + When requesting "/ocs/v2.php" with "GET" + Then the HTTP status code should be "404" + + Scenario: Accessing /public.php/webdav with log.condition + When requesting "/public.php/webdav" with "GET" + Then the HTTP status code should be "401" + + Scenario: Accessing /public.php/dav with log.condition + When requesting "/public.php/dav" with "GET" + Then the HTTP status code should be "503" diff --git a/build/integration/features/maintenance-mode.feature b/build/integration/features/maintenance-mode.feature index e6637a5edff..72af31f193f 100644 --- a/build/integration/features/maintenance-mode.feature +++ b/build/integration/features/maintenance-mode.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: maintenance-mode Background: diff --git a/build/integration/features/ocs-v1.feature b/build/integration/features/ocs-v1.feature index 6075189ddb4..26907580aee 100644 --- a/build/integration/features/ocs-v1.feature +++ b/build/integration/features/ocs-v1.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: ocs Background: Given using api version "1" diff --git a/build/integration/features/provisioning-v1.feature b/build/integration/features/provisioning-v1.feature index 0d1d5b1a345..8fcfb076497 100644 --- a/build/integration/features/provisioning-v1.feature +++ b/build/integration/features/provisioning-v1.feature @@ -1,60 +1,66 @@ +# SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2015-2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: provisioning - Background: - Given using api version "1" - - Scenario: Getting an not existing user - Given As an "admin" - When sending "GET" to "/cloud/users/test" - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: Listing all users - Given As an "admin" - When sending "GET" to "/cloud/users" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: Create a user - Given As an "admin" - And user "brand-new-user" does not exist - When sending "POST" to "/cloud/users" with - | userid | brand-new-user | - | password | 123456 | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And user "brand-new-user" exists - - Scenario: Create an existing user - Given As an "admin" - And user "brand-new-user" exists - When sending "POST" to "/cloud/users" with - | userid | brand-new-user | - | password | 123456 | - Then the OCS status code should be "102" - And the HTTP status code should be "200" - And user "brand-new-user" has - | id | brand-new-user | - | displayname | brand-new-user | - | email | | - | phone | | - | address | | - | website | | - | twitter | | - - Scenario: Get an existing user - Given As an "admin" - When sending "GET" to "/cloud/users/brand-new-user" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: Getting all users - Given As an "admin" - And user "brand-new-user" exists - And user "admin" exists - When sending "GET" to "/cloud/users" - Then users returned are - | brand-new-user | - | admin | + Background: + Given using api version "1" + Given parameter "whitelist_0" of app "bruteForce" is set to "127.0.0.1" + Given parameter "whitelist_1" of app "bruteForce" is set to "::1" + Given parameter "apply_allowlist_to_ratelimit" of app "bruteforcesettings" is set to "true" + + Scenario: Getting an not existing user + Given As an "admin" + When sending "GET" to "/cloud/users/test" + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: Listing all users + Given As an "admin" + When sending "GET" to "/cloud/users" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: Create a user + Given As an "admin" + And user "brand-new-user" does not exist + When sending "POST" to "/cloud/users" with + | userid | brand-new-user | + | password | 123456 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And user "brand-new-user" exists + + Scenario: Create an existing user + Given As an "admin" + And user "brand-new-user" exists + When sending "POST" to "/cloud/users" with + | userid | brand-new-user | + | password | 123456 | + Then the OCS status code should be "102" + And the HTTP status code should be "200" + And user "brand-new-user" has + | id | brand-new-user | + | displayname | brand-new-user | + | email | | + | phone | | + | address | | + | website | | + | twitter | | + + Scenario: Get an existing user + Given As an "admin" + When sending "GET" to "/cloud/users/brand-new-user" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: Getting all users + Given As an "admin" + And user "brand-new-user" exists + And user "admin" exists + When sending "GET" to "/cloud/users" + Then users returned are + | brand-new-user | + | admin | Scenario: Get editable fields Given As an "admin" @@ -66,13 +72,15 @@ Feature: provisioning | phone | | address | | website | - | twitter | + | twitter | + | bluesky | | fediverse | | organisation | | role | | headline | | biography | | profile_enabled | + | pronouns | Given As an "brand-new-user" Then user "brand-new-user" has editable fields | displayname | @@ -82,12 +90,14 @@ Feature: provisioning | address | | website | | twitter | + | bluesky | | fediverse | | organisation | | role | | headline | | biography | | profile_enabled | + | pronouns | Then user "self" has editable fields | displayname | | email | @@ -96,31 +106,33 @@ Feature: provisioning | address | | website | | twitter | + | bluesky | | fediverse | | organisation | | role | | headline | | biography | | profile_enabled | + | pronouns | - Scenario: Edit a user - Given As an "admin" - And user "brand-new-user" exists - When sending "PUT" to "/cloud/users/brand-new-user" with - | key | displayname | - | value | Brand New User | - And the OCS status code should be "100" - And the HTTP status code should be "200" - And sending "PUT" to "/cloud/users/brand-new-user" with - | key | quota | - | value | 12MB | - And the OCS status code should be "100" - And the HTTP status code should be "200" - And sending "PUT" to "/cloud/users/brand-new-user" with - | key | email | - | value | no-reply@nextcloud.com | - And the OCS status code should be "100" - And the HTTP status code should be "200" + Scenario: Edit a user + Given As an "admin" + And user "brand-new-user" exists + When sending "PUT" to "/cloud/users/brand-new-user" with + | key | displayname | + | value | Brand New User | + And the OCS status code should be "100" + And the HTTP status code should be "200" + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | quota | + | value | 12MB | + And the OCS status code should be "100" + And the HTTP status code should be "200" + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | email | + | value | no-reply@nextcloud.com | + And the OCS status code should be "100" + And the HTTP status code should be "200" And sending "PUT" to "/cloud/users/brand-new-user" with | key | additional_mail | | value | no.reply@nextcloud.com | @@ -131,105 +143,126 @@ Feature: provisioning | value | noreply@nextcloud.com | And the OCS status code should be "100" And the HTTP status code should be "200" - And sending "PUT" to "/cloud/users/brand-new-user" with - | key | phone | - | value | +49 711 / 25 24 28-90 | - And the OCS status code should be "100" - And the HTTP status code should be "200" - And sending "PUT" to "/cloud/users/brand-new-user" with - | key | address | - | value | Foo Bar Town | - And the OCS status code should be "100" - And the HTTP status code should be "200" - And sending "PUT" to "/cloud/users/brand-new-user" with - | key | website | - | value | https://nextcloud.com | - And the OCS status code should be "100" - And the HTTP status code should be "200" - And sending "PUT" to "/cloud/users/brand-new-user" with - | key | twitter | - | value | Nextcloud | - And the OCS status code should be "100" - And the HTTP status code should be "200" - Then user "brand-new-user" has - | id | brand-new-user | - | displayname | Brand New User | - | email | no-reply@nextcloud.com | + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | phone | + | value | +49 711 / 25 24 28-90 | + And the OCS status code should be "100" + And the HTTP status code should be "200" + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | address | + | value | Foo Bar Town | + And the OCS status code should be "100" + And the HTTP status code should be "200" + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | website | + | value | https://nextcloud.com | + And the OCS status code should be "100" + And the HTTP status code should be "200" + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | twitter | + | value | Nextcloud | + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | bluesky | + | value | nextcloud.bsky.social | + And the OCS status code should be "100" + And the HTTP status code should be "200" + Then user "brand-new-user" has + | id | brand-new-user | + | displayname | Brand New User | + | email | no-reply@nextcloud.com | | additional_mail | no.reply@nextcloud.com;noreply@nextcloud.com | - | phone | +4971125242890 | - | address | Foo Bar Town | - | website | https://nextcloud.com | - | twitter | Nextcloud | + | phone | +4971125242890 | + | address | Foo Bar Town | + | website | https://nextcloud.com | + | twitter | Nextcloud | + | bluesky | nextcloud.bsky.social | + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | organisation | + | value | Nextcloud GmbH | + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | role | + | value | Engineer | + And the OCS status code should be "100" + And the HTTP status code should be "200" + Then user "brand-new-user" has the following profile data + | userId | brand-new-user | + | displayname | Brand New User | + | organisation | Nextcloud GmbH | + | role | Engineer | + | address | Foo Bar Town | + | timezone | UTC | + | timezoneOffset | 0 | + | pronouns | NULL | + + Scenario: Edit a user with mixed case emails + Given As an "admin" + And user "brand-new-user" exists + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | email | + | value | mixed-CASE@Nextcloud.com | + And the OCS status code should be "100" + And the HTTP status code should be "200" + Then user "brand-new-user" has + | id | brand-new-user | + | email | mixed-case@nextcloud.com | - Scenario: Edit a user account properties scopes - Given user "brand-new-user" exists + Scenario: Edit a user account properties scopes + Given user "brand-new-user" exists And As an "brand-new-user" - When sending "PUT" to "/cloud/users/brand-new-user" with - | key | phoneScope | - | value | v2-private | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - When sending "PUT" to "/cloud/users/brand-new-user" with - | key | twitterScope | - | value | v2-local | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - When sending "PUT" to "/cloud/users/brand-new-user" with - | key | addressScope | - | value | v2-federated | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - When sending "PUT" to "/cloud/users/brand-new-user" with - | key | emailScope | - | value | v2-published | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - When sending "PUT" to "/cloud/users/brand-new-user" with - | key | websiteScope | - | value | public | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - When sending "PUT" to "/cloud/users/brand-new-user" with - | key | displaynameScope | - | value | contacts | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - When sending "PUT" to "/cloud/users/brand-new-user" with - | key | avatarScope | - | value | private | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And sending "PUT" to "/cloud/users/brand-new-user" with - | key | email | - | value | no-reply@nextcloud.com | - And the OCS status code should be "100" - And the HTTP status code should be "200" - # Duplicating primary address - And sending "PUT" to "/cloud/users/brand-new-user" with - | key | additional_mail | - | value | no-reply@nextcloud.com | - And the OCS status code should be "102" - And the HTTP status code should be "200" - And sending "PUT" to "/cloud/users/brand-new-user" with - | key | additional_mail | - | value | no.reply2@nextcloud.com | - And the OCS status code should be "100" - And the HTTP status code should be "200" - # Duplicating another additional address - And sending "PUT" to "/cloud/users/brand-new-user" with - | key | additional_mail | - | value | no.reply2@nextcloud.com | - And the OCS status code should be "102" - And the HTTP status code should be "200" - Then user "brand-new-user" has - | id | brand-new-user | - | phoneScope | v2-private | - | twitterScope | v2-local | - | addressScope | v2-federated | - | emailScope | v2-published | - | websiteScope | v2-published | - | displaynameScope | v2-federated | - | avatarScope | v2-local | + When sending "PUT" to "/cloud/users/brand-new-user" with + | key | phoneScope | + | value | v2-private | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + When sending "PUT" to "/cloud/users/brand-new-user" with + | key | twitterScope | + | value | v2-local | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + When sending "PUT" to "/cloud/users/brand-new-user" with + | key | blueskyScope | + | value | v2-local | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + When sending "PUT" to "/cloud/users/brand-new-user" with + | key | addressScope | + | value | v2-federated | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + When sending "PUT" to "/cloud/users/brand-new-user" with + | key | emailScope | + | value | v2-published | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | email | + | value | no-reply@nextcloud.com | + And the OCS status code should be "100" + And the HTTP status code should be "200" + # Duplicating primary address + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | additional_mail | + | value | no-reply@nextcloud.com | + And the OCS status code should be "101" + And the HTTP status code should be "200" + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | additional_mail | + | value | no.reply2@nextcloud.com | + And the OCS status code should be "100" + And the HTTP status code should be "200" + # Duplicating another additional address + And sending "PUT" to "/cloud/users/brand-new-user" with + | key | additional_mail | + | value | no.reply2@nextcloud.com | + And the OCS status code should be "101" + And the HTTP status code should be "200" + Then user "brand-new-user" has + | id | brand-new-user | + | phoneScope | v2-private | + | twitterScope | v2-local | + | blueskyScope | v2-local | + | addressScope | v2-federated | + | emailScope | v2-published | Scenario: Edit a user account multivalue property scopes Given user "brand-new-user" exists @@ -258,24 +291,24 @@ Feature: provisioning | id | brand-new-user | | additional_mailScope | v2-federated;v2-published | - Scenario: Edit a user account properties scopes with invalid or unsupported value - Given user "brand-new-user" exists + Scenario: Edit a user account properties scopes with invalid or unsupported value + Given user "brand-new-user" exists And As an "brand-new-user" - When sending "PUT" to "/cloud/users/brand-new-user" with - | key | phoneScope | - | value | invalid | - Then the OCS status code should be "102" - And the HTTP status code should be "200" - When sending "PUT" to "/cloud/users/brand-new-user" with - | key | displaynameScope | - | value | v2-private | - Then the OCS status code should be "102" - And the HTTP status code should be "200" - When sending "PUT" to "/cloud/users/brand-new-user" with - | key | emailScope | - | value | v2-private | - Then the OCS status code should be "102" - And the HTTP status code should be "200" + When sending "PUT" to "/cloud/users/brand-new-user" with + | key | phoneScope | + | value | invalid | + Then the OCS status code should be "101" + And the HTTP status code should be "200" + When sending "PUT" to "/cloud/users/brand-new-user" with + | key | displaynameScope | + | value | v2-private | + Then the OCS status code should be "101" + And the HTTP status code should be "200" + When sending "PUT" to "/cloud/users/brand-new-user" with + | key | emailScope | + | value | v2-private | + Then the OCS status code should be "101" + And the HTTP status code should be "200" Scenario: Edit a user account multi-value property scopes with invalid or unsupported value Given user "brand-new-user" exists @@ -314,539 +347,546 @@ Feature: provisioning Then user "brand-new-user" has not | additional_mail | no.reply6@nextcloud.com | - Scenario: An admin cannot edit user account property scopes - Given As an "admin" - And user "brand-new-user" exists - When sending "PUT" to "/cloud/users/brand-new-user" with - | key | phoneScope | - | value | v2-private | - Then the OCS status code should be "103" - And the HTTP status code should be "200" - - Scenario: Search by phone number - Given As an "admin" - And user "phone-user" exists - And sending "PUT" to "/cloud/users/phone-user" with - | key | phone | - | value | +49 711 / 25 24 28-90 | - And the OCS status code should be "100" - And the HTTP status code should be "200" - Then search users by phone for region "DE" with - | random-string1 | 0711 / 123 456 78 | - | random-string1 | 0711 / 252 428-90 | - | random-string2 | 0711 / 90-824 252 | - And the OCS status code should be "100" - And the HTTP status code should be "200" - Then phone matches returned are - | random-string1 | phone-user@localhost:8080 | - - Scenario: Create a group - Given As an "admin" - And group "new-group" does not exist - When sending "POST" to "/cloud/groups" with - | groupid | new-group | - | password | 123456 | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And group "new-group" exists - And group "new-group" has - | displayname | new-group | - - Scenario: Create a group with custom display name - Given As an "admin" - And group "new-group" does not exist - When sending "POST" to "/cloud/groups" with - | groupid | new-group | - | password | 123456 | - | displayname | new-group-displayname | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And group "new-group" exists - And group "new-group" has - | displayname | new-group-displayname | - - Scenario: Create a group with special characters - Given As an "admin" - And group "España" does not exist - When sending "POST" to "/cloud/groups" with - | groupid | España | - | password | 123456 | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And group "España" exists - And group "España" has - | displayname | España | - - Scenario: adding user to a group without sending the group - Given As an "admin" - And user "brand-new-user" exists - When sending "POST" to "/cloud/users/brand-new-user/groups" with - | groupid | | - Then the OCS status code should be "101" - And the HTTP status code should be "200" - - Scenario: adding user to a group which doesn't exist - Given As an "admin" - And user "brand-new-user" exists - And group "not-group" does not exist - When sending "POST" to "/cloud/users/brand-new-user/groups" with - | groupid | not-group | - Then the OCS status code should be "102" - And the HTTP status code should be "200" - - Scenario: adding user to a group without privileges - Given user "brand-new-user" exists - And As an "brand-new-user" - When sending "POST" to "/cloud/users/brand-new-user/groups" with - | groupid | new-group | - Then the OCS status code should be "403" - And the HTTP status code should be "200" - - Scenario: adding user to a group - Given As an "admin" - And user "brand-new-user" exists - And group "new-group" exists - When sending "POST" to "/cloud/users/brand-new-user/groups" with - | groupid | new-group | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: getting groups of an user - Given As an "admin" - And user "brand-new-user" exists - And group "new-group" exists - When sending "GET" to "/cloud/users/brand-new-user/groups" - Then groups returned are - | new-group | - And the OCS status code should be "100" - - Scenario: adding a user which doesn't exist to a group - Given As an "admin" - And user "not-user" does not exist - And group "new-group" exists - When sending "POST" to "/cloud/users/not-user/groups" with - | groupid | new-group | - Then the OCS status code should be "103" - And the HTTP status code should be "200" - - Scenario: getting a group - Given As an "admin" - And group "new-group" exists - When sending "GET" to "/cloud/groups/new-group" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: Getting all groups - Given As an "admin" - And group "new-group" exists - And group "admin" exists - When sending "GET" to "/cloud/groups" - Then groups returned are - | España | - | admin | - | new-group | - - Scenario: create a subadmin - Given As an "admin" - And user "brand-new-user" exists - And group "new-group" exists - When sending "POST" to "/cloud/users/brand-new-user/subadmins" with - | groupid | new-group | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: get users using a subadmin - Given As an "admin" - And user "brand-new-user" exists - And group "new-group" exists - And user "brand-new-user" belongs to group "new-group" - And user "brand-new-user" is subadmin of group "new-group" - And As an "brand-new-user" - When sending "GET" to "/cloud/users" - Then users returned are - | brand-new-user | - And the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: removing a user from a group which doesn't exists - Given As an "admin" - And user "brand-new-user" exists - And group "not-group" does not exist - When sending "DELETE" to "/cloud/users/brand-new-user/groups" with - | groupid | not-group | - Then the OCS status code should be "102" - - Scenario: removing a user from a group - Given As an "admin" - And user "brand-new-user" exists - And group "new-group" exists - And user "brand-new-user" belongs to group "new-group" - When sending "DELETE" to "/cloud/users/brand-new-user/groups" with - | groupid | new-group | - Then the OCS status code should be "100" - And user "brand-new-user" does not belong to group "new-group" - - Scenario: create a subadmin using a user which not exist - Given As an "admin" - And user "not-user" does not exist - And group "new-group" exists - When sending "POST" to "/cloud/users/not-user/subadmins" with - | groupid | new-group | - Then the OCS status code should be "101" - And the HTTP status code should be "200" - - Scenario: create a subadmin using a group which not exist - Given As an "admin" - And user "brand-new-user" exists - And group "not-group" does not exist - When sending "POST" to "/cloud/users/brand-new-user/subadmins" with - | groupid | not-group | - Then the OCS status code should be "102" - And the HTTP status code should be "200" - - Scenario: Getting subadmin groups - Given As an "admin" - And user "brand-new-user" exists - And group "new-group" exists - When sending "GET" to "/cloud/users/brand-new-user/subadmins" - Then subadmin groups returned are - | new-group | - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: Getting subadmin groups of a user which not exist - Given As an "admin" - And user "not-user" does not exist - And group "new-group" exists - When sending "GET" to "/cloud/users/not-user/subadmins" - Then the OCS status code should be "404" - And the HTTP status code should be "200" - - Scenario: Getting subadmin users of a group - Given As an "admin" - And user "brand-new-user" exists - And group "new-group" exists - When sending "GET" to "/cloud/groups/new-group/subadmins" - Then subadmin users returned are - | brand-new-user | - And the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: Getting subadmin users of a group which doesn't exist - Given As an "admin" - And user "brand-new-user" exists - And group "not-group" does not exist - When sending "GET" to "/cloud/groups/not-group/subadmins" - Then the OCS status code should be "101" - And the HTTP status code should be "200" - - Scenario: Removing subadmin from a group - Given As an "admin" - And user "brand-new-user" exists - And group "new-group" exists - And user "brand-new-user" is subadmin of group "new-group" - When sending "DELETE" to "/cloud/users/brand-new-user/subadmins" with - | groupid | new-group | - And the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: Delete a user - Given As an "admin" - And user "brand-new-user" exists - When sending "DELETE" to "/cloud/users/brand-new-user" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And user "brand-new-user" does not exist - - Scenario: Delete a group - Given As an "admin" - And group "new-group" exists - When sending "DELETE" to "/cloud/groups/new-group" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And group "new-group" does not exist - - Scenario: Delete a group with special characters - Given As an "admin" - And group "España" exists - When sending "DELETE" to "/cloud/groups/España" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And group "España" does not exist - - Scenario: get enabled apps - Given As an "admin" - When sending "GET" to "/cloud/apps?filter=enabled" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And apps returned are - | cloud_federation_api | - | comments | - | contactsinteraction | - | dashboard | - | dav | - | federatedfilesharing | - | federation | - | files | - | files_reminders | - | files_sharing | - | files_trashbin | - | files_versions | - | lookup_server_connector | - | provisioning_api | - | settings | - | sharebymail | - | systemtags | - | theming | - | twofactor_backupcodes | - | updatenotification | - | user_ldap | - | user_status | - | viewer | - | workflowengine | - | weather_status | - | files_external | - | oauth2 | - - Scenario: get app info - Given As an "admin" - When sending "GET" to "/cloud/apps/files" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - - Scenario: get app info from app that does not exist - Given As an "admin" - When sending "GET" to "/cloud/apps/this_app_should_never_exist" - Then the OCS status code should be "998" - And the HTTP status code should be "200" - - Scenario: enable an app - Given As an "admin" - And app "testing" is disabled - When sending "POST" to "/cloud/apps/testing" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And app "testing" is enabled - - Scenario: enable an app that does not exist - Given As an "admin" - When sending "POST" to "/cloud/apps/this_app_should_never_exist" - Then the OCS status code should be "998" - And the HTTP status code should be "200" - - Scenario: disable an app - Given As an "admin" - And app "testing" is enabled - When sending "DELETE" to "/cloud/apps/testing" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And app "testing" is disabled - - Scenario: disable an user - Given As an "admin" - And user "user1" exists - When sending "PUT" to "/cloud/users/user1/disable" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And user "user1" is disabled - - Scenario: enable an user - Given As an "admin" - And user "user1" exists - And assure user "user1" is disabled - When sending "PUT" to "/cloud/users/user1/enable" - Then the OCS status code should be "100" - And the HTTP status code should be "200" - And user "user1" is enabled - - Scenario: Subadmin should be able to enable or disable an user in their group - Given As an "admin" - And user "subadmin" exists - And user "user1" exists - And group "new-group" exists - And user "subadmin" belongs to group "new-group" - And user "user1" belongs to group "new-group" - And Assure user "subadmin" is subadmin of group "new-group" - And As an "subadmin" - When sending "PUT" to "/cloud/users/user1/disable" - Then the OCS status code should be "100" - Then the HTTP status code should be "200" - And As an "admin" - And user "user1" is disabled - - Scenario: Subadmin should not be able to enable or disable an user not in their group - Given As an "admin" - And user "subadmin" exists - And user "user1" exists - And group "new-group" exists - And group "another-group" exists - And user "subadmin" belongs to group "new-group" - And user "user1" belongs to group "another-group" - And Assure user "subadmin" is subadmin of group "new-group" - And As an "subadmin" - When sending "PUT" to "/cloud/users/user1/disable" - Then the OCS status code should be "998" - Then the HTTP status code should be "200" - And As an "admin" - And user "user1" is enabled - - Scenario: Subadmins should not be able to disable users that have admin permissions in their group - Given As an "admin" - And user "another-admin" exists - And user "subadmin" exists - And group "new-group" exists - And user "another-admin" belongs to group "admin" - And user "subadmin" belongs to group "new-group" - And user "another-admin" belongs to group "new-group" - And Assure user "subadmin" is subadmin of group "new-group" - And As an "subadmin" - When sending "PUT" to "/cloud/users/another-admin/disable" - Then the OCS status code should be "998" - Then the HTTP status code should be "200" - And As an "admin" - And user "another-admin" is enabled - - Scenario: Admin can disable another admin user - Given As an "admin" - And user "another-admin" exists - And user "another-admin" belongs to group "admin" - When sending "PUT" to "/cloud/users/another-admin/disable" - Then the OCS status code should be "100" - Then the HTTP status code should be "200" - And user "another-admin" is disabled - - Scenario: Admin can enable another admin user - Given As an "admin" - And user "another-admin" exists - And user "another-admin" belongs to group "admin" - And assure user "another-admin" is disabled - When sending "PUT" to "/cloud/users/another-admin/enable" - Then the OCS status code should be "100" - Then the HTTP status code should be "200" - And user "another-admin" is enabled - - Scenario: Admin can disable subadmins in the same group - Given As an "admin" - And user "subadmin" exists - And group "new-group" exists - And user "subadmin" belongs to group "new-group" - And user "admin" belongs to group "new-group" - And Assure user "subadmin" is subadmin of group "new-group" - When sending "PUT" to "/cloud/users/subadmin/disable" - Then the OCS status code should be "100" - Then the HTTP status code should be "200" - And user "subadmin" is disabled - - Scenario: Admin can enable subadmins in the same group - Given As an "admin" - And user "subadmin" exists - And group "new-group" exists - And user "subadmin" belongs to group "new-group" - And user "admin" belongs to group "new-group" - And Assure user "subadmin" is subadmin of group "new-group" - And assure user "another-admin" is disabled - When sending "PUT" to "/cloud/users/subadmin/disable" - Then the OCS status code should be "100" - Then the HTTP status code should be "200" - And user "subadmin" is disabled - - Scenario: Admin user cannot disable himself - Given As an "admin" - And user "another-admin" exists - And user "another-admin" belongs to group "admin" - And As an "another-admin" - When sending "PUT" to "/cloud/users/another-admin/disable" - Then the OCS status code should be "101" - And the HTTP status code should be "200" - And As an "admin" - And user "another-admin" is enabled - - Scenario:Admin user cannot enable himself - Given As an "admin" - And user "another-admin" exists - And user "another-admin" belongs to group "admin" - And assure user "another-admin" is disabled - And As an "another-admin" - When sending "PUT" to "/cloud/users/another-admin/enable" - And As an "admin" - Then user "another-admin" is disabled - - Scenario: disable an user with a regular user - Given As an "admin" - And user "user1" exists - And user "user2" exists - And As an "user1" - When sending "PUT" to "/cloud/users/user2/disable" - Then the OCS status code should be "403" - And the HTTP status code should be "200" - And As an "admin" - And user "user2" is enabled - - Scenario: enable an user with a regular user - Given As an "admin" - And user "user1" exists - And user "user2" exists - And assure user "user2" is disabled - And As an "user1" - When sending "PUT" to "/cloud/users/user2/enable" - Then the OCS status code should be "403" - And the HTTP status code should be "200" - And As an "admin" - And user "user2" is disabled - - Scenario: Subadmin should not be able to disable himself - Given As an "admin" - And user "subadmin" exists - And group "new-group" exists - And user "subadmin" belongs to group "new-group" - And Assure user "subadmin" is subadmin of group "new-group" - And As an "subadmin" - When sending "PUT" to "/cloud/users/subadmin/disable" - Then the OCS status code should be "101" - Then the HTTP status code should be "200" - And As an "admin" - And user "subadmin" is enabled - - Scenario: Subadmin should not be able to enable himself - Given As an "admin" - And user "subadmin" exists - And group "new-group" exists - And user "subadmin" belongs to group "new-group" - And Assure user "subadmin" is subadmin of group "new-group" - And assure user "subadmin" is disabled - And As an "subadmin" - When sending "PUT" to "/cloud/users/subadmin/enabled" - And As an "admin" - And user "subadmin" is disabled - - Scenario: Making a ocs request with an enabled user - Given As an "admin" - And user "user0" exists - And As an "user0" - When sending "GET" to "/cloud/capabilities" - Then the HTTP status code should be "200" - And the OCS status code should be "100" - - Scenario: Making a web request with an enabled user - Given As an "admin" - And user "user0" exists - And As an "user0" - When sending "GET" with exact url to "/index.php/apps/files" - Then the HTTP status code should be "200" - - Scenario: Making a ocs request with a disabled user - Given As an "admin" - And user "user0" exists - And assure user "user0" is disabled - And As an "user0" - When sending "GET" to "/cloud/capabilities" - Then the OCS status code should be "997" - And the HTTP status code should be "401" - - Scenario: Making a web request with a disabled user - Given As an "admin" - And user "user0" exists - And assure user "user0" is disabled - And As an "user0" - When sending "GET" with exact url to "/index.php/apps/files" - And the HTTP status code should be "401" + Scenario: An admin cannot edit user account property scopes + Given As an "admin" + And user "brand-new-user" exists + When sending "PUT" to "/cloud/users/brand-new-user" with + | key | phoneScope | + | value | v2-private | + Then the OCS status code should be "113" + And the HTTP status code should be "200" + + Scenario: Search by phone number + Given As an "admin" + And user "phone-user" exists + And sending "PUT" to "/cloud/users/phone-user" with + | key | phone | + | value | +49 711 / 25 24 28-90 | + And the OCS status code should be "100" + And the HTTP status code should be "200" + Then search users by phone for region "DE" with + | random-string1 | 0711 / 123 456 78 | + | random-string1 | 0711 / 252 428-90 | + | random-string2 | 0711 / 90-824 252 | + And the OCS status code should be "100" + And the HTTP status code should be "200" + Then phone matches returned are + | random-string1 | phone-user@localhost:8080 | + + Scenario: Create a group + Given As an "admin" + And group "new-group" does not exist + When sending "POST" to "/cloud/groups" with + | groupid | new-group | + | password | 123456 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And group "new-group" exists + And group "new-group" has + | displayname | new-group | + + Scenario: Create a group with custom display name + Given As an "admin" + And group "new-group" does not exist + When sending "POST" to "/cloud/groups" with + | groupid | new-group | + | password | 123456 | + | displayname | new-group-displayname | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And group "new-group" exists + And group "new-group" has + | displayname | new-group-displayname | + + Scenario: Create a group with special characters + Given As an "admin" + And group "España" does not exist + When sending "POST" to "/cloud/groups" with + | groupid | España | + | password | 123456 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And group "España" exists + And group "España" has + | displayname | España | + + Scenario: adding user to a group without sending the group + Given As an "admin" + And user "brand-new-user" exists + When sending "POST" to "/cloud/users/brand-new-user/groups" with + | groupid | | + Then the OCS status code should be "101" + And the HTTP status code should be "200" + + Scenario: adding user to a group which doesn't exist + Given As an "admin" + And user "brand-new-user" exists + And group "not-group" does not exist + When sending "POST" to "/cloud/users/brand-new-user/groups" with + | groupid | not-group | + Then the OCS status code should be "102" + And the HTTP status code should be "200" + + Scenario: adding user to a group without privileges + Given user "brand-new-user" exists + And As an "brand-new-user" + When sending "POST" to "/cloud/users/brand-new-user/groups" with + | groupid | new-group | + Then the OCS status code should be "403" + And the HTTP status code should be "200" + + Scenario: adding user to a group + Given As an "admin" + And user "brand-new-user" exists + And group "new-group" exists + When sending "POST" to "/cloud/users/brand-new-user/groups" with + | groupid | new-group | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: getting groups of an user + Given As an "admin" + And user "brand-new-user" exists + And group "new-group" exists + When sending "GET" to "/cloud/users/brand-new-user/groups" + Then groups returned are + | new-group | + And the OCS status code should be "100" + + Scenario: adding a user which doesn't exist to a group + Given As an "admin" + And user "not-user" does not exist + And group "new-group" exists + When sending "POST" to "/cloud/users/not-user/groups" with + | groupid | new-group | + Then the OCS status code should be "103" + And the HTTP status code should be "200" + + Scenario: getting a group + Given As an "admin" + And group "new-group" exists + When sending "GET" to "/cloud/groups/new-group" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: Getting all groups + Given As an "admin" + And group "new-group" exists + And group "admin" exists + When sending "GET" to "/cloud/groups" + Then groups returned are + | España | + | admin | + | hidden_group | + | new-group | + + Scenario: create a subadmin + Given As an "admin" + And user "brand-new-user" exists + And group "new-group" exists + When sending "POST" to "/cloud/users/brand-new-user/subadmins" with + | groupid | new-group | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: get users using a subadmin + Given As an "admin" + And user "brand-new-user" exists + And group "new-group" exists + And user "brand-new-user" belongs to group "new-group" + And user "brand-new-user" is subadmin of group "new-group" + And As an "brand-new-user" + When sending "GET" to "/cloud/users" + Then users returned are + | brand-new-user | + And the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: removing a user from a group which doesn't exists + Given As an "admin" + And user "brand-new-user" exists + And group "not-group" does not exist + When sending "DELETE" to "/cloud/users/brand-new-user/groups" with + | groupid | not-group | + Then the OCS status code should be "102" + + Scenario: removing a user from a group + Given As an "admin" + And user "brand-new-user" exists + And group "new-group" exists + And user "brand-new-user" belongs to group "new-group" + When sending "DELETE" to "/cloud/users/brand-new-user/groups" with + | groupid | new-group | + Then the OCS status code should be "100" + And user "brand-new-user" does not belong to group "new-group" + + Scenario: create a subadmin using a user which not exist + Given As an "admin" + And user "not-user" does not exist + And group "new-group" exists + When sending "POST" to "/cloud/users/not-user/subadmins" with + | groupid | new-group | + Then the OCS status code should be "101" + And the HTTP status code should be "200" + + Scenario: create a subadmin using a group which not exist + Given As an "admin" + And user "brand-new-user" exists + And group "not-group" does not exist + When sending "POST" to "/cloud/users/brand-new-user/subadmins" with + | groupid | not-group | + Then the OCS status code should be "102" + And the HTTP status code should be "200" + + Scenario: Getting subadmin groups + Given As an "admin" + And user "brand-new-user" exists + And group "new-group" exists + When sending "GET" to "/cloud/users/brand-new-user/subadmins" + Then subadmin groups returned are + | new-group | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: Getting subadmin groups of a user which not exist + Given As an "admin" + And user "not-user" does not exist + And group "new-group" exists + When sending "GET" to "/cloud/users/not-user/subadmins" + Then the OCS status code should be "404" + And the HTTP status code should be "200" + + Scenario: Getting subadmin users of a group + Given As an "admin" + And user "brand-new-user" exists + And group "new-group" exists + When sending "GET" to "/cloud/groups/new-group/subadmins" + Then subadmin users returned are + | brand-new-user | + And the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: Getting subadmin users of a group which doesn't exist + Given As an "admin" + And user "brand-new-user" exists + And group "not-group" does not exist + When sending "GET" to "/cloud/groups/not-group/subadmins" + Then the OCS status code should be "101" + And the HTTP status code should be "200" + + Scenario: Removing subadmin from a group + Given As an "admin" + And user "brand-new-user" exists + And group "new-group" exists + And user "brand-new-user" is subadmin of group "new-group" + When sending "DELETE" to "/cloud/users/brand-new-user/subadmins" with + | groupid | new-group | + And the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: Delete a user + Given As an "admin" + And user "brand-new-user" exists + When sending "DELETE" to "/cloud/users/brand-new-user" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And user "brand-new-user" does not exist + + Scenario: Delete a group + Given As an "admin" + And group "new-group" exists + When sending "DELETE" to "/cloud/groups/new-group" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And group "new-group" does not exist + + Scenario: Delete a group with special characters + Given As an "admin" + And group "España" exists + When sending "DELETE" to "/cloud/groups/España" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And group "España" does not exist + + Scenario: get enabled apps + Given As an "admin" + When sending "GET" to "/cloud/apps?filter=enabled" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And apps returned are + | cloud_federation_api | + | comments | + | contactsinteraction | + | dashboard | + | dav | + | federatedfilesharing | + | federation | + | files | + | files_reminders | + | files_sharing | + | files_trashbin | + | files_versions | + | lookup_server_connector | + | profile | + | provisioning_api | + | settings | + | sharebymail | + | systemtags | + | testing | + | theming | + | twofactor_backupcodes | + | updatenotification | + | user_ldap | + | user_status | + | viewer | + | workflowengine | + | webhook_listeners | + | weather_status | + | files_external | + | oauth2 | + + Scenario: get app info + Given As an "admin" + When sending "GET" to "/cloud/apps/files" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + + Scenario: get app info from app that does not exist + Given As an "admin" + When sending "GET" to "/cloud/apps/this_app_should_never_exist" + Then the OCS status code should be "998" + And the HTTP status code should be "200" + + Scenario: enable an app + Given invoking occ with "app:disable testing" + Given As an "admin" + And app "testing" is disabled + When sending "POST" to "/cloud/apps/testing" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And app "testing" is enabled + + Scenario: enable an app that does not exist + Given As an "admin" + When sending "POST" to "/cloud/apps/this_app_should_never_exist" + Then the OCS status code should be "998" + And the HTTP status code should be "200" + + Scenario: disable an app + Given invoking occ with "app:enable testing" + Given As an "admin" + And app "testing" is enabled + When sending "DELETE" to "/cloud/apps/testing" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And app "testing" is disabled + Given invoking occ with "app:enable testing" + + Scenario: disable an user + Given As an "admin" + And user "user1" exists + When sending "PUT" to "/cloud/users/user1/disable" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And user "user1" is disabled + + Scenario: enable an user + Given As an "admin" + And user "user1" exists + And assure user "user1" is disabled + When sending "PUT" to "/cloud/users/user1/enable" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And user "user1" is enabled + + Scenario: Subadmin should be able to enable or disable an user in their group + Given As an "admin" + And user "subadmin" exists + And user "user1" exists + And group "new-group" exists + And user "subadmin" belongs to group "new-group" + And user "user1" belongs to group "new-group" + And Assure user "subadmin" is subadmin of group "new-group" + And As an "subadmin" + When sending "PUT" to "/cloud/users/user1/disable" + Then the OCS status code should be "100" + Then the HTTP status code should be "200" + And As an "admin" + And user "user1" is disabled + + Scenario: Subadmin should not be able to enable or disable an user not in their group + Given As an "admin" + And user "subadmin" exists + And user "user1" exists + And group "new-group" exists + And group "another-group" exists + And user "subadmin" belongs to group "new-group" + And user "user1" belongs to group "another-group" + And Assure user "subadmin" is subadmin of group "new-group" + And As an "subadmin" + When sending "PUT" to "/cloud/users/user1/disable" + Then the OCS status code should be "998" + Then the HTTP status code should be "200" + And As an "admin" + And user "user1" is enabled + + Scenario: Subadmins should not be able to disable users that have admin permissions in their group + Given As an "admin" + And user "another-admin" exists + And user "subadmin" exists + And group "new-group" exists + And user "another-admin" belongs to group "admin" + And user "subadmin" belongs to group "new-group" + And user "another-admin" belongs to group "new-group" + And Assure user "subadmin" is subadmin of group "new-group" + And As an "subadmin" + When sending "PUT" to "/cloud/users/another-admin/disable" + Then the OCS status code should be "998" + Then the HTTP status code should be "200" + And As an "admin" + And user "another-admin" is enabled + + Scenario: Admin can disable another admin user + Given As an "admin" + And user "another-admin" exists + And user "another-admin" belongs to group "admin" + When sending "PUT" to "/cloud/users/another-admin/disable" + Then the OCS status code should be "100" + Then the HTTP status code should be "200" + And user "another-admin" is disabled + + Scenario: Admin can enable another admin user + Given As an "admin" + And user "another-admin" exists + And user "another-admin" belongs to group "admin" + And assure user "another-admin" is disabled + When sending "PUT" to "/cloud/users/another-admin/enable" + Then the OCS status code should be "100" + Then the HTTP status code should be "200" + And user "another-admin" is enabled + + Scenario: Admin can disable subadmins in the same group + Given As an "admin" + And user "subadmin" exists + And group "new-group" exists + And user "subadmin" belongs to group "new-group" + And user "admin" belongs to group "new-group" + And Assure user "subadmin" is subadmin of group "new-group" + When sending "PUT" to "/cloud/users/subadmin/disable" + Then the OCS status code should be "100" + Then the HTTP status code should be "200" + And user "subadmin" is disabled + + Scenario: Admin can enable subadmins in the same group + Given As an "admin" + And user "subadmin" exists + And group "new-group" exists + And user "subadmin" belongs to group "new-group" + And user "admin" belongs to group "new-group" + And Assure user "subadmin" is subadmin of group "new-group" + And assure user "another-admin" is disabled + When sending "PUT" to "/cloud/users/subadmin/disable" + Then the OCS status code should be "100" + Then the HTTP status code should be "200" + And user "subadmin" is disabled + + Scenario: Admin user cannot disable himself + Given As an "admin" + And user "another-admin" exists + And user "another-admin" belongs to group "admin" + And As an "another-admin" + When sending "PUT" to "/cloud/users/another-admin/disable" + Then the OCS status code should be "101" + And the HTTP status code should be "200" + And As an "admin" + And user "another-admin" is enabled + + Scenario:Admin user cannot enable himself + Given As an "admin" + And user "another-admin" exists + And user "another-admin" belongs to group "admin" + And assure user "another-admin" is disabled + And As an "another-admin" + When sending "PUT" to "/cloud/users/another-admin/enable" + And As an "admin" + Then user "another-admin" is disabled + + Scenario: disable an user with a regular user + Given As an "admin" + And user "user1" exists + And user "user2" exists + And As an "user1" + When sending "PUT" to "/cloud/users/user2/disable" + Then the OCS status code should be "403" + And the HTTP status code should be "200" + And As an "admin" + And user "user2" is enabled + + Scenario: enable an user with a regular user + Given As an "admin" + And user "user1" exists + And user "user2" exists + And assure user "user2" is disabled + And As an "user1" + When sending "PUT" to "/cloud/users/user2/enable" + Then the OCS status code should be "403" + And the HTTP status code should be "200" + And As an "admin" + And user "user2" is disabled + + Scenario: Subadmin should not be able to disable himself + Given As an "admin" + And user "subadmin" exists + And group "new-group" exists + And user "subadmin" belongs to group "new-group" + And Assure user "subadmin" is subadmin of group "new-group" + And As an "subadmin" + When sending "PUT" to "/cloud/users/subadmin/disable" + Then the OCS status code should be "101" + Then the HTTP status code should be "200" + And As an "admin" + And user "subadmin" is enabled + + Scenario: Subadmin should not be able to enable himself + Given As an "admin" + And user "subadmin" exists + And group "new-group" exists + And user "subadmin" belongs to group "new-group" + And Assure user "subadmin" is subadmin of group "new-group" + And assure user "subadmin" is disabled + And As an "subadmin" + When sending "PUT" to "/cloud/users/subadmin/enabled" + And As an "admin" + And user "subadmin" is disabled + + Scenario: Making a ocs request with an enabled user + Given As an "admin" + And user "user0" exists + And As an "user0" + When sending "GET" to "/cloud/capabilities" + Then the HTTP status code should be "200" + And the OCS status code should be "100" + + Scenario: Making a web request with an enabled user + Given As an "admin" + And user "user0" exists + And As an "user0" + When sending "GET" with exact url to "/index.php/apps/files" + Then the HTTP status code should be "200" + + Scenario: Making a ocs request with a disabled user + Given As an "admin" + And user "user0" exists + And assure user "user0" is disabled + And As an "user0" + When sending "GET" to "/cloud/capabilities" + Then the OCS status code should be "997" + And the HTTP status code should be "401" + + Scenario: Making a web request with a disabled user + Given As an "admin" + And user "user0" exists + And assure user "user0" is disabled + And As an "user0" + When sending "GET" with exact url to "/index.php/apps/files" + And the HTTP status code should be "401" diff --git a/build/integration/features/provisioning-v2.feature b/build/integration/features/provisioning-v2.feature index 729c812cb8c..1169dc04b5f 100644 --- a/build/integration/features/provisioning-v2.feature +++ b/build/integration/features/provisioning-v2.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2015 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: provisioning Background: Given using api version "2" diff --git a/build/integration/federation_features/cleanup-remote-storage.feature b/build/integration/federation_features/cleanup-remote-storage.feature index c782987cac0..a3585bdee96 100644 --- a/build/integration/federation_features/cleanup-remote-storage.feature +++ b/build/integration/federation_features/cleanup-remote-storage.feature @@ -1,7 +1,30 @@ +# SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: cleanup-remote-storage Background: Given using api version "1" + Scenario: cleanup remote storage with no storage + Given Using server "LOCAL" + And user "user0" exists + Given Using server "REMOTE" + And user "user1" exists + # Rename file so it has a unique name in the target server (as the target + # server may have its own /textfile0.txt" file) + And User "user1" copies file "/textfile0.txt" to "/remote-share.txt" + And User "user1" from server "REMOTE" shares "/remote-share.txt" with user "user0" from server "LOCAL" + And As an "user1" + And Deleting last share + And the OCS status code should be "100" + And the HTTP status code should be "200" + And Deleting last share + And Using server "LOCAL" + When invoking occ with "sharing:cleanup-remote-storage" + Then the command was successful + And the command output contains the text "0 remote storage(s) need(s) to be checked" + And the command output contains the text "0 remote share(s) exist" + And the command output contains the text "no storages deleted" + Scenario: cleanup remote storage with active storages Given Using server "LOCAL" And user "user0" exists diff --git a/build/integration/federation_features/federated.feature b/build/integration/federation_features/federated.feature index fc7cc4c4bf4..d3a414cb804 100644 --- a/build/integration/federation_features/federated.feature +++ b/build/integration/federation_features/federated.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2015-2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: federated Background: Given using api version "1" @@ -5,7 +8,7 @@ Feature: federated Scenario: Federate share a file with another server Given Using server "REMOTE" And user "user1" exists - And Using server "LOCAL" + Given Using server "LOCAL" And user "user0" exists When User "user0" from server "LOCAL" shares "/textfile0.txt" with user "user1" from server "REMOTE" Then the OCS status code should be "100" @@ -27,6 +30,12 @@ Feature: federated | displayname_owner | user0 | | share_with | user1@REMOTE | | share_with_displayname | user1 | + Given Using server "REMOTE" + And As an "user1" + And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" + And the list of returned shares has 0 shares + When sending "GET" to "/apps/files_sharing/api/v1/remote_shares/pending" + Then the list of returned shares has 1 shares Scenario: Federated group share a file with another server Given Using server "REMOTE" @@ -37,7 +46,7 @@ Feature: federated And As an "admin" And Add user "gs-user1" to the group "group1" And Add user "gs-user2" to the group "group1" - And Using server "LOCAL" + Given Using server "LOCAL" And parameter "outgoing_server2server_group_share_enabled" of app "files_sharing" is set to "yes" And user "gs-user0" exists When User "gs-user0" from server "LOCAL" shares "/textfile0.txt" with group "group1" from server "REMOTE" @@ -61,11 +70,10 @@ Feature: federated | share_with | group1@REMOTE | | share_with_displayname | group1@REMOTE | - Scenario: Federate share a file with local server Given Using server "LOCAL" And user "user0" exists - And Using server "REMOTE" + Given Using server "REMOTE" And user "user1" exists When User "user1" from server "REMOTE" shares "/textfile0.txt" with user "user0" from server "LOCAL" Then the OCS status code should be "100" @@ -91,10 +99,10 @@ Feature: federated Scenario: Remote sharee can see the pending share Given Using server "REMOTE" And user "user1" exists - And Using server "LOCAL" + Given Using server "LOCAL" And user "user0" exists And User "user0" from server "LOCAL" shares "/textfile0.txt" with user "user1" from server "REMOTE" - And Using server "REMOTE" + Given Using server "REMOTE" And As an "user1" When sending "GET" to "/apps/files_sharing/api/v1/remote_shares/pending" Then the OCS status code should be "100" @@ -119,11 +127,11 @@ Feature: federated And As an "admin" And Add user "gs-user1" to the group "group1" And Add user "gs-user2" to the group "group1" - And Using server "LOCAL" + Given Using server "LOCAL" And parameter "outgoing_server2server_group_share_enabled" of app "files_sharing" is set to "yes" And user "gs-user0" exists When User "gs-user0" from server "LOCAL" shares "/textfile0.txt" with group "group1" from server "REMOTE" - And Using server "REMOTE" + Given Using server "REMOTE" And As an "gs-user1" When sending "GET" to "/apps/files_sharing/api/v1/remote_shares/pending" Then the OCS status code should be "100" @@ -156,7 +164,7 @@ Feature: federated Scenario: accept a pending remote share Given Using server "REMOTE" And user "user1" exists - And Using server "LOCAL" + Given Using server "LOCAL" And user "user0" exists And User "user0" from server "LOCAL" shares "/textfile0.txt" with user "user1" from server "REMOTE" When User "user1" from server "REMOTE" accepts last pending share @@ -172,7 +180,7 @@ Feature: federated And As an "admin" And Add user "gs-user1" to the group "group1" And Add user "gs-user2" to the group "group1" - And Using server "LOCAL" + Given Using server "LOCAL" And parameter "outgoing_server2server_group_share_enabled" of app "files_sharing" is set to "yes" And user "gs-user0" exists When User "gs-user0" from server "LOCAL" shares "/textfile0.txt" with group "group1" from server "REMOTE" @@ -184,45 +192,45 @@ Feature: federated Given Using server "REMOTE" And user "user1" exists And user "user2" exists - And Using server "LOCAL" + Given Using server "LOCAL" And user "user0" exists And User "user0" from server "LOCAL" shares "/textfile0.txt" with user "user1" from server "REMOTE" And User "user1" from server "REMOTE" accepts last pending share - And Using server "REMOTE" + Given Using server "REMOTE" And As an "user1" When creating a share with | path | /textfile0 (2).txt | | shareType | 0 | | shareWith | user2 | | permissions | 19 | - #Then the OCS status code should be "100" - #And the HTTP status code should be "200" - #And Share fields of last share match with - # | id | A_NUMBER | - # | item_type | file | - # | item_source | A_NUMBER | - # | share_type | 0 | - # | file_source | A_NUMBER | - # | path | /textfile0 (2).txt | - # | permissions | 19 | - # | stime | A_NUMBER | - # | storage | A_NUMBER | - # | mail_send | 1 | - # | uid_owner | user1 | - # | file_parent | A_NUMBER | - # | displayname_owner | user1 | - # | share_with | user2 | - # | share_with_displayname | user2 | + # Then the OCS status code should be "100" + # And the HTTP status code should be "200" + # And Share fields of last share match with + # | id | A_NUMBER | + # | item_type | file | + # | item_source | A_NUMBER | + # | share_type | 0 | + # | file_source | A_NUMBER | + # | path | /textfile0 (2).txt | + # | permissions | 19 | + # | stime | A_NUMBER | + # | storage | A_NUMBER | + # | mail_send | 1 | + # | uid_owner | user1 | + # | file_parent | A_NUMBER | + # | displayname_owner | user1 | + # | share_with | user2 | + # | share_with_displayname | user2 | Scenario: Overwrite a federated shared file as recipient Given Using server "REMOTE" And user "user1" exists And user "user2" exists - And Using server "LOCAL" + Given Using server "LOCAL" And user "user0" exists And User "user0" from server "LOCAL" shares "/textfile0.txt" with user "user1" from server "REMOTE" And User "user1" from server "REMOTE" accepts last pending share - And Using server "REMOTE" + Given Using server "REMOTE" And As an "user1" And User "user1" modifies text of "/textfile0.txt" with text "BLABLABLA" When User "user1" uploads file "../../data/user1/files/textfile0.txt" to "/textfile0 (2).txt" @@ -233,50 +241,16 @@ Feature: federated Given Using server "REMOTE" And user "user1" exists And user "user2" exists - And Using server "LOCAL" + Given Using server "LOCAL" And user "user0" exists And User "user0" from server "LOCAL" shares "/PARENT" with user "user1" from server "REMOTE" And User "user1" from server "REMOTE" accepts last pending share - And Using server "REMOTE" - And As an "user1" - And User "user1" modifies text of "/textfile0.txt" with text "BLABLABLA" - #When User "user1" uploads file "../../data/user1/files/textfile0.txt" to "/PARENT (2)/textfile0.txt" - #And Downloading file "/PARENT (2)/textfile0.txt" with range "bytes=0-8" - #Then Downloaded content should be "BLABLABLA" - - Scenario: Overwrite a federated shared file as recipient using old chunking - Given Using server "REMOTE" - And user "user1" exists - And user "user2" exists - And Using server "LOCAL" - And user "user0" exists - And User "user0" from server "LOCAL" shares "/textfile0.txt" with user "user1" from server "REMOTE" - And User "user1" from server "REMOTE" accepts last pending share - And Using server "REMOTE" - And As an "user1" - #And user "user1" uploads chunk file "1" of "3" with "AAAAA" to "/textfile0 (2).txt" - #And user "user1" uploads chunk file "2" of "3" with "BBBBB" to "/textfile0 (2).txt" - #And user "user1" uploads chunk file "3" of "3" with "CCCCC" to "/textfile0 (2).txt" - #When Downloading file "/textfile0 (2).txt" with range "bytes=0-4" - #Then Downloaded content should be "AAAAA" - - Scenario: Overwrite a federated shared folder as recipient using old chunking Given Using server "REMOTE" - And user "user1" exists - And user "user2" exists - And Using server "LOCAL" - And user "user0" exists - And User "user0" from server "LOCAL" shares "/PARENT" with user "user1" from server "REMOTE" - And User "user1" from server "REMOTE" accepts last pending share - And Using server "REMOTE" And As an "user1" - #And user "user1" uploads chunk file "1" of "3" with "AAAAA" to "/PARENT (2)/textfile0.txt" - #And user "user1" uploads chunk file "2" of "3" with "BBBBB" to "/PARENT (2)/textfile0.txt" - #And user "user1" uploads chunk file "3" of "3" with "CCCCC" to "/PARENT (2)/textfile0.txt" - #When Downloading file "/PARENT (2)/textfile0.txt" with range "bytes=3-13" - #Then Downloaded content should be "AABBBBBCCCC" - - + And User "user1" modifies text of "/textfile0.txt" with text "BLABLABLA" + When User "user1" uploads file "../../data/user1/files/textfile0.txt" to "/PARENT (2)/textfile0.txt" + And Downloading file "/PARENT (2)/textfile0.txt" with range "bytes=0-8" + Then Downloaded content should be "BLABLABLA" Scenario: List federated share from another server not accepted yet Given Using server "LOCAL" @@ -287,7 +261,7 @@ Feature: federated # server may have its own /textfile0.txt" file) And User "user1" copies file "/textfile0.txt" to "/remote-share.txt" And User "user1" from server "REMOTE" shares "/remote-share.txt" with user "user0" from server "LOCAL" - And Using server "LOCAL" + Given Using server "LOCAL" When As an "user0" And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" Then the list of returned shares has 0 shares @@ -301,7 +275,7 @@ Feature: federated # server may have its own /textfile0.txt" file) And User "user1" copies file "/textfile0.txt" to "/remote-share.txt" And User "user1" from server "REMOTE" shares "/remote-share.txt" with user "user0" from server "LOCAL" - And Using server "LOCAL" + Given Using server "LOCAL" And User "user0" from server "LOCAL" accepts last pending share When As an "user0" And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" @@ -327,7 +301,7 @@ Feature: federated # server may have its own /textfile0.txt" file) And User "user1" copies file "/textfile0.txt" to "/remote-share.txt" And User "user1" from server "REMOTE" shares "/remote-share.txt" with user "user0" from server "LOCAL" - And Using server "LOCAL" + Given Using server "LOCAL" And User "user0" from server "LOCAL" accepts last pending share And remote server is stopped When As an "user0" @@ -349,7 +323,7 @@ Feature: federated # server may have its own /textfile0.txt" file) And User "user1" copies file "/textfile0.txt" to "/remote-share.txt" And User "user1" from server "REMOTE" shares "/remote-share.txt" with user "user0" from server "LOCAL" - And Using server "LOCAL" + Given Using server "LOCAL" And User "user0" from server "LOCAL" accepts last pending share # Checking that the file exists caches the file entry, which causes an # exception to be thrown when getting the file info if the remote server is @@ -366,8 +340,6 @@ Feature: federated | user | user0 | | mountpoint | /remote-share.txt | - - Scenario: Delete federated share with another server Given Using server "LOCAL" And user "user0" exists @@ -380,13 +352,13 @@ Feature: federated And As an "user1" And sending "GET" to "/apps/files_sharing/api/v1/shares" And the list of returned shares has 1 shares - And Using server "LOCAL" + Given Using server "LOCAL" And User "user0" from server "LOCAL" accepts last pending share And as "user0" the file "/remote-share.txt" exists And As an "user0" And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" And the list of returned shares has 1 shares - And Using server "REMOTE" + Given Using server "REMOTE" When As an "user1" And Deleting last share Then the OCS status code should be "100" @@ -394,7 +366,7 @@ Feature: federated And As an "user1" And sending "GET" to "/apps/files_sharing/api/v1/shares" And the list of returned shares has 0 shares - And Using server "LOCAL" + Given Using server "LOCAL" And as "user0" the file "/remote-share.txt" does not exist And As an "user0" And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" @@ -412,7 +384,7 @@ Feature: federated And As an "user1" And sending "GET" to "/apps/files_sharing/api/v1/shares" And the list of returned shares has 1 shares - And Using server "LOCAL" + Given Using server "LOCAL" And User "user0" from server "LOCAL" accepts last pending share And as "user0" the file "/remote-share.txt" exists And As an "user0" @@ -425,7 +397,7 @@ Feature: federated And As an "user0" And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" And the list of returned shares has 0 shares - And Using server "REMOTE" + Given Using server "REMOTE" And As an "user1" And sending "GET" to "/apps/files_sharing/api/v1/shares" And the list of returned shares has 0 shares @@ -439,7 +411,7 @@ Feature: federated # server may have its own /textfile0.txt" file) And User "user1" copies file "/textfile0.txt" to "/remote-share.txt" And User "user1" from server "REMOTE" shares "/remote-share.txt" with user "user0" from server "LOCAL" - And Using server "LOCAL" + Given Using server "LOCAL" And User "user0" from server "LOCAL" accepts last pending share And as "user0" the file "/remote-share.txt" exists And As an "user0" @@ -466,7 +438,7 @@ Feature: federated And As an "user1" And sending "GET" to "/apps/files_sharing/api/v1/shares" And the list of returned shares has 1 shares - And Using server "LOCAL" + Given Using server "LOCAL" And User "user0" from server "LOCAL" accepts last pending share And as "user0" the file "/remote-share.txt" exists And As an "user0" @@ -478,7 +450,7 @@ Feature: federated And As an "user0" And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" And the list of returned shares has 0 shares - And Using server "REMOTE" + Given Using server "REMOTE" And As an "user1" And sending "GET" to "/apps/files_sharing/api/v1/shares" And the list of returned shares has 0 shares @@ -492,7 +464,7 @@ Feature: federated # server may have its own /textfile0.txt" file) And User "user1" copies file "/textfile0.txt" to "/remote-share.txt" And User "user1" from server "REMOTE" shares "/remote-share.txt" with user "user0" from server "LOCAL" - And Using server "LOCAL" + Given Using server "LOCAL" And User "user0" from server "LOCAL" accepts last pending share And as "user0" the file "/remote-share.txt" exists And As an "user0" @@ -505,3 +477,115 @@ Feature: federated And As an "user0" And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" And the list of returned shares has 0 shares + + Scenario: Share to a non-trusted server will NOT auto accept + Given Using server "LOCAL" + And user "user0" exists + Given Using server "REMOTE" + And user "userfed2" exists + And parameter "federated_trusted_share_auto_accept" of app "files_sharing" is set to "yes" + When As an "user0" + When User "user0" from server "LOCAL" shares "/textfile0.txt" with user "userfed2" from server "REMOTE" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=false" + And the list of returned shares has 1 shares + Given Using server "REMOTE" + And using new dav path + And As an "userfed2" + And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" + And the list of returned shares has 0 shares + When sending "GET" to "/apps/files_sharing/api/v1/remote_shares/pending" + And the list of returned shares has 1 shares + And as "userfed2" the file "/textfile0 (2).txt" does not exist + + Scenario: Share to a non-trusted server group will NOT auto accept + Given Using server "REMOTE" + And parameter "incoming_server2server_group_share_enabled" of app "files_sharing" is set to "yes" + And parameter "federated_trusted_share_auto_accept" of app "files_sharing" is set to "yes" + And user "gs-userfed3" exists + And user "gs-userfed4" exists + And group "groupfed2" exists + And As an "admin" + And Add user "gs-userfed3" to the group "groupfed2" + And Add user "gs-userfed4" to the group "groupfed2" + Given Using server "LOCAL" + And parameter "outgoing_server2server_group_share_enabled" of app "files_sharing" is set to "yes" + And user "gs-user0" exists + When As an "gs-user0" + When User "gs-user0" from server "LOCAL" shares "/textfile0.txt" with group "groupfed2" from server "REMOTE" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=false" + And the list of returned shares has 1 shares + Given Using server "REMOTE" + And using new dav path + And As an "gs-userfed3" + And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" + And the list of returned shares has 0 shares + When sending "GET" to "/apps/files_sharing/api/v1/remote_shares/pending" + And the list of returned shares has 1 shares + And as "gs-userfed3" the file "/textfile0 (2).txt" does not exist + And As an "gs-userfed4" + And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" + And the list of returned shares has 0 shares + When sending "GET" to "/apps/files_sharing/api/v1/remote_shares/pending" + And the list of returned shares has 1 shares + And as "gs-userfed4" the file "/textfile0 (2).txt" does not exist + + @TrustedFederation + Scenario: Share to a trusted server auto accept + Given Using server "LOCAL" + And user "user0" exists + Given Using server "REMOTE" + And user "userfed1" exists + And parameter "federated_trusted_share_auto_accept" of app "files_sharing" is set to "yes" + When As an "user0" + When User "user0" from server "LOCAL" shares "/textfile0.txt" with user "userfed1" from server "REMOTE" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=false" + And the list of returned shares has 1 shares + Given Using server "REMOTE" + And using new dav path + And As an "userfed1" + And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" + And the list of returned shares has 1 shares + When sending "GET" to "/apps/files_sharing/api/v1/remote_shares/pending" + And the list of returned shares has 0 shares + And as "userfed1" the file "/textfile0 (2).txt" exists + + @TrustedFederation + Scenario: Share to a trusted server group auto accept + Given Using server "REMOTE" + And parameter "incoming_server2server_group_share_enabled" of app "files_sharing" is set to "yes" + And parameter "federated_trusted_share_auto_accept" of app "files_sharing" is set to "yes" + And user "gs-userfed1" exists + And user "gs-userfed2" exists + And group "groupfed1" exists + And As an "admin" + And Add user "gs-userfed1" to the group "groupfed1" + And Add user "gs-userfed2" to the group "groupfed1" + Given Using server "LOCAL" + And parameter "outgoing_server2server_group_share_enabled" of app "files_sharing" is set to "yes" + And user "gs-user0" exists + When As an "gs-user0" + When User "gs-user0" from server "LOCAL" shares "/textfile0.txt" with group "groupfed1" from server "REMOTE" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=false" + And the list of returned shares has 1 shares + Given Using server "REMOTE" + And using new dav path + And As an "gs-userfed1" + And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" + And the list of returned shares has 1 shares + When sending "GET" to "/apps/files_sharing/api/v1/remote_shares/pending" + And the list of returned shares has 0 shares + And as "gs-userfed1" the file "/textfile0 (2).txt" exists + And As an "gs-userfed2" + And sending "GET" to "/apps/files_sharing/api/v1/remote_shares" + And the list of returned shares has 1 shares + When sending "GET" to "/apps/files_sharing/api/v1/remote_shares/pending" + And the list of returned shares has 0 shares + And as "gs-userfed2" the file "/textfile0 (2).txt" exists diff --git a/build/integration/file_conversions/file_conversions.feature b/build/integration/file_conversions/file_conversions.feature new file mode 100644 index 00000000000..92dc11a647a --- /dev/null +++ b/build/integration/file_conversions/file_conversions.feature @@ -0,0 +1,122 @@ +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-only + +Feature: conversions + Background: + Given using api version "2" + Given using new dav path + Given user "user0" exists + + Scenario: Converting a file works + Given user "user0" uploads file "data/clouds.jpg" to "/image.jpg" + Then as "user0" the file "/image.jpg" exists + When user "user0" converts file "/image.jpg" to "image/png" + Then the HTTP status code should be "201" + Then the OCS status code should be "201" + Then as "user0" the file "/image.png" exists + + Scenario: Converting a file to a given path works + Given user "user0" uploads file "data/clouds.jpg" to "/image.jpg" + And User "user0" created a folder "/folder" + Then as "user0" the file "/image.jpg" exists + Then as "user0" the folder "/folder" exists + When user "user0" converts file "/image.jpg" to "image/png" and saves it to "/folder/image.png" + Then the HTTP status code should be "201" + Then the OCS status code should be "201" + Then as "user0" the file "/folder/image.png" exists + Then as "user0" the file "/image.png" does not exist + + Scenario: Converting a file path with overwrite + Given user "user0" uploads file "data/clouds.jpg" to "/image.jpg" + And user "user0" uploads file "data/green-square-256.png" to "/image.png" + Then as "user0" the file "/image.jpg" exists + Then as "user0" the file "/image.png" exists + When user "user0" converts file "/image.jpg" to "image/png" + Then the HTTP status code should be "201" + Then the OCS status code should be "201" + Then as "user0" the file "/image.jpg" exists + Then as "user0" the file "/image.png" exists + Then as "user0" the file "/image (2).png" exists + + Scenario: Converting a file path with overwrite to a given path + Given user "user0" uploads file "data/clouds.jpg" to "/image.jpg" + And User "user0" created a folder "/folder" + And user "user0" uploads file "data/green-square-256.png" to "/folder/image.png" + Then as "user0" the file "/image.jpg" exists + Then as "user0" the folder "/folder" exists + Then as "user0" the file "/folder/image.png" exists + When user "user0" converts file "/image.jpg" to "image/png" and saves it to "/folder/image.png" + Then the HTTP status code should be "201" + Then the OCS status code should be "201" + Then as "user0" the file "/folder/image.png" exists + Then as "user0" the file "/folder/image (2).png" exists + Then as "user0" the file "/image.png" does not exist + Then as "user0" the file "/image.jpg" exists + + Scenario: Converting a file which does not exist fails + When user "user0" converts file "/image.jpg" to "image/png" + Then the HTTP status code should be "404" + Then the OCS status code should be "404" + Then as "user0" the file "/image.jpg" does not exist + Then as "user0" the file "/image.png" does not exist + + Scenario: Converting a file to an invalid destination path fails + Given user "user0" uploads file "data/clouds.jpg" to "/image.jpg" + When user "user0" converts file "/image.jpg" to "image/png" and saves it to "/folder/image.png" + Then the HTTP status code should be "404" + Then the OCS status code should be "404" + Then as "user0" the file "/image.jpg" exists + Then as "user0" the file "/folder/image.png" does not exist + + Scenario: Converting a file to an invalid format fails + Given user "user0" uploads file "data/clouds.jpg" to "/image.jpg" + When user "user0" converts file "/image.jpg" to "image/invalid" + Then the HTTP status code should be "500" + Then the OCS status code should be "999" + Then as "user0" the file "/image.jpg" exists + Then as "user0" the file "/image.png" does not exist + +Scenario: Converting a file to a given path without extension fails + Given user "user0" uploads file "data/clouds.jpg" to "/image.jpg" + And User "user0" created a folder "/folder" + Then as "user0" the file "/image.jpg" exists + Then as "user0" the folder "/folder" exists + When user "user0" converts file "/image.jpg" to "image/png" and saves it to "/folder/image" + Then the HTTP status code should be "400" + Then the OCS status code should be "400" + Then as "user0" the file "/folder/image.png" does not exist + Then as "user0" the file "/image.png" does not exist + + @local_storage + Scenario: Converting a file bigger than 100 MiB fails + Given file "/image.jpg" of size 108003328 is created in local storage + Then as "user0" the folder "/local_storage" exists + Then as "user0" the file "/local_storage/image.jpg" exists + When user "user0" converts file "/local_storage/image.jpg" to "image/png" and saves it to "/image.png" + Then the HTTP status code should be "400" + Then the OCS status code should be "400" + Then as "user0" the file "/image.png" does not exist + + Scenario: Forbid conversion to a destination without create permission + Given user "user1" exists + # Share the folder with user1 + Given User "user0" created a folder "/folder" + Then As an "user0" + When creating a share with + | path | folder | + | shareWith | user1 | + | shareType | 0 | + | permissions | 1 | + Then the OCS status code should be "200" + And the HTTP status code should be "200" + # Create the folder, upload the image + Then As an "user1" + Given user "user1" accepts last share + Given as "user1" the folder "/folder" exists + Given user "user1" uploads file "data/clouds.jpg" to "/image.jpg" + Then as "user1" the file "/image.jpg" exists + # Try to convert the image to a folder where user1 has no create permission + When user "user1" converts file "/image.jpg" to "image/png" and saves it to "/folder/folder.png" + Then the OCS status code should be "403" + And the HTTP status code should be "403" + Then as "user1" the file "/folder/folder.png" does not exist diff --git a/build/integration/files_features/checksums.feature b/build/integration/files_features/checksums.feature index d391e93afe8..d797c7a503e 100644 --- a/build/integration/files_features/checksums.feature +++ b/build/integration/files_features/checksums.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: checksums Scenario: Uploading a file with checksum should work @@ -58,19 +61,3 @@ Feature: checksums When user "user0" uploads file "data/textfile.txt" to "/myChecksumFile.txt" And user "user0" downloads the file "/myChecksumFile.txt" Then The OC-Checksum header should not be there - - Scenario: Uploading a chunked file with checksum should return the checksum in the propfind - Given user "user0" exists - And user "user0" uploads chunk file "1" of "3" with "AAAAA" to "/myChecksumFile.txt" with checksum "MD5:e892fdd61a74bc89cd05673cc2e22f88" - And user "user0" uploads chunk file "2" of "3" with "BBBBB" to "/myChecksumFile.txt" with checksum "MD5:e892fdd61a74bc89cd05673cc2e22f88" - And user "user0" uploads chunk file "3" of "3" with "CCCCC" to "/myChecksumFile.txt" with checksum "MD5:e892fdd61a74bc89cd05673cc2e22f88" - When user "user0" request the checksum of "/myChecksumFile.txt" via propfind - Then The webdav checksum should match "MD5:e892fdd61a74bc89cd05673cc2e22f88" - - Scenario: Uploading a chunked file with checksum should return the checksum in the download header - Given user "user0" exists - And user "user0" uploads chunk file "1" of "3" with "AAAAA" to "/myChecksumFile.txt" with checksum "MD5:e892fdd61a74bc89cd05673cc2e22f88" - And user "user0" uploads chunk file "2" of "3" with "BBBBB" to "/myChecksumFile.txt" with checksum "MD5:e892fdd61a74bc89cd05673cc2e22f88" - And user "user0" uploads chunk file "3" of "3" with "CCCCC" to "/myChecksumFile.txt" with checksum "MD5:e892fdd61a74bc89cd05673cc2e22f88" - When user "user0" downloads the file "/myChecksumFile.txt" - Then The header checksum should match "MD5:e892fdd61a74bc89cd05673cc2e22f88" diff --git a/build/integration/files_features/download.feature b/build/integration/files_features/download.feature index 16d346b0150..f9d4e7e95b9 100644 --- a/build/integration/files_features/download.feature +++ b/build/integration/files_features/download.feature @@ -1,59 +1,61 @@ +# SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: download - Scenario: downloading 2 small files returns a zip32 + Scenario: downloading 2 small files Given using new dav path And user "user0" exists And User "user0" copies file "/welcome.txt" to "/welcome2.txt" When user "user0" downloads zip file for entries '"welcome.txt","welcome2.txt"' in folder "/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a file named "welcome.txt" with the contents of "/welcome.txt" from "user0" data And the downloaded zip file contains a file named "welcome2.txt" with the contents of "/welcome2.txt" from "user0" data - Scenario: downloading a small file and a directory returns a zip32 + Scenario: downloading a small file and a directory Given using new dav path And user "user0" exists And user "user0" created a folder "/emptySubFolder" When user "user0" downloads zip file for entries '"welcome.txt","emptySubFolder"' in folder "/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a file named "welcome.txt" with the contents of "/welcome.txt" from "user0" data And the downloaded zip file contains a folder named "emptySubFolder/" - Scenario: downloading a small file and 2 nested directories returns a zip32 + Scenario: downloading a small file and 2 nested directories Given using new dav path And user "user0" exists And user "user0" created a folder "/subFolder" And user "user0" created a folder "/subFolder/emptySubSubFolder" When user "user0" downloads zip file for entries '"welcome.txt","subFolder"' in folder "/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a file named "welcome.txt" with the contents of "/welcome.txt" from "user0" data And the downloaded zip file contains a folder named "subFolder/" And the downloaded zip file contains a folder named "subFolder/emptySubSubFolder/" - Scenario: downloading dir with 2 small files returns a zip32 + Scenario: downloading dir with 2 small files Given using new dav path And user "user0" exists And user "user0" created a folder "/sparseFolder" And User "user0" copies file "/welcome.txt" to "/sparseFolder/welcome.txt" And User "user0" copies file "/welcome.txt" to "/sparseFolder/welcome2.txt" When user "user0" downloads zip file for entries '"sparseFolder"' in folder "/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a folder named "sparseFolder/" And the downloaded zip file contains a file named "sparseFolder/welcome.txt" with the contents of "/sparseFolder/welcome.txt" from "user0" data And the downloaded zip file contains a file named "sparseFolder/welcome2.txt" with the contents of "/sparseFolder/welcome2.txt" from "user0" data - Scenario: downloading dir with a small file and a directory returns a zip32 + Scenario: downloading dir with a small file and a directory Given using new dav path And user "user0" exists And user "user0" created a folder "/sparseFolder" And User "user0" copies file "/welcome.txt" to "/sparseFolder/welcome.txt" And user "user0" created a folder "/sparseFolder/emptySubFolder" When user "user0" downloads zip file for entries '"sparseFolder"' in folder "/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a folder named "sparseFolder/" And the downloaded zip file contains a file named "sparseFolder/welcome.txt" with the contents of "/sparseFolder/welcome.txt" from "user0" data And the downloaded zip file contains a folder named "sparseFolder/emptySubFolder/" - Scenario: downloading dir with a small file and 2 nested directories returns a zip32 + Scenario: downloading dir with a small file and 2 nested directories Given using new dav path And user "user0" exists And user "user0" created a folder "/sparseFolder" @@ -61,35 +63,35 @@ Feature: download And user "user0" created a folder "/sparseFolder/subFolder" And user "user0" created a folder "/sparseFolder/subFolder/emptySubSubFolder" When user "user0" downloads zip file for entries '"sparseFolder"' in folder "/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a folder named "sparseFolder/" And the downloaded zip file contains a file named "sparseFolder/welcome.txt" with the contents of "/sparseFolder/welcome.txt" from "user0" data And the downloaded zip file contains a folder named "sparseFolder/subFolder/" And the downloaded zip file contains a folder named "sparseFolder/subFolder/emptySubSubFolder/" - Scenario: downloading (from folder) 2 small files returns a zip32 + Scenario: downloading (from folder) 2 small files Given using new dav path And user "user0" exists And user "user0" created a folder "/baseFolder" And User "user0" copies file "/welcome.txt" to "/baseFolder/welcome.txt" And User "user0" copies file "/welcome.txt" to "/baseFolder/welcome2.txt" When user "user0" downloads zip file for entries '"welcome.txt","welcome2.txt"' in folder "/baseFolder/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a file named "welcome.txt" with the contents of "/baseFolder/welcome.txt" from "user0" data And the downloaded zip file contains a file named "welcome2.txt" with the contents of "/baseFolder/welcome2.txt" from "user0" data - Scenario: downloading (from folder) a small file and a directory returns a zip32 + Scenario: downloading (from folder) a small file and a directory Given using new dav path And user "user0" exists And user "user0" created a folder "/baseFolder" And User "user0" copies file "/welcome.txt" to "/baseFolder/welcome.txt" And user "user0" created a folder "/baseFolder/emptySubFolder" When user "user0" downloads zip file for entries '"welcome.txt","emptySubFolder"' in folder "/baseFolder/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a file named "welcome.txt" with the contents of "/baseFolder/welcome.txt" from "user0" data And the downloaded zip file contains a folder named "emptySubFolder/" - Scenario: downloading (from folder) a small file and 2 nested directories returns a zip32 + Scenario: downloading (from folder) a small file and 2 nested directories Given using new dav path And user "user0" exists And user "user0" created a folder "/baseFolder" @@ -97,12 +99,12 @@ Feature: download And user "user0" created a folder "/baseFolder/subFolder" And user "user0" created a folder "/baseFolder/subFolder/emptySubSubFolder" When user "user0" downloads zip file for entries '"welcome.txt","subFolder"' in folder "/baseFolder/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a file named "welcome.txt" with the contents of "/baseFolder/welcome.txt" from "user0" data And the downloaded zip file contains a folder named "subFolder/" And the downloaded zip file contains a folder named "subFolder/emptySubSubFolder/" - Scenario: downloading (from folder) dir with 2 small files returns a zip32 + Scenario: downloading (from folder) dir with 2 small files Given using new dav path And user "user0" exists And user "user0" created a folder "/baseFolder" @@ -110,12 +112,12 @@ Feature: download And User "user0" copies file "/welcome.txt" to "/baseFolder/sparseFolder/welcome.txt" And User "user0" copies file "/welcome.txt" to "/baseFolder/sparseFolder/welcome2.txt" When user "user0" downloads zip file for entries '"sparseFolder"' in folder "/baseFolder/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a folder named "sparseFolder/" And the downloaded zip file contains a file named "sparseFolder/welcome.txt" with the contents of "/baseFolder/sparseFolder/welcome.txt" from "user0" data And the downloaded zip file contains a file named "sparseFolder/welcome2.txt" with the contents of "/baseFolder/sparseFolder/welcome2.txt" from "user0" data - Scenario: downloading (from folder) dir with a small file and a directory returns a zip32 + Scenario: downloading (from folder) dir with a small file and a directory Given using new dav path And user "user0" exists And user "user0" created a folder "/baseFolder" @@ -123,12 +125,12 @@ Feature: download And User "user0" copies file "/welcome.txt" to "/baseFolder/sparseFolder/welcome.txt" And user "user0" created a folder "/baseFolder/sparseFolder/emptySubFolder" When user "user0" downloads zip file for entries '"sparseFolder"' in folder "/baseFolder/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a folder named "sparseFolder/" And the downloaded zip file contains a file named "sparseFolder/welcome.txt" with the contents of "/baseFolder/sparseFolder/welcome.txt" from "user0" data And the downloaded zip file contains a folder named "sparseFolder/emptySubFolder/" - Scenario: downloading (from folder) dir with a small file and 2 nested directories returns a zip32 + Scenario: downloading (from folder) dir with a small file and 2 nested directories Given using new dav path And user "user0" exists And user "user0" created a folder "/baseFolder" @@ -137,14 +139,14 @@ Feature: download And user "user0" created a folder "/baseFolder/sparseFolder/subFolder" And user "user0" created a folder "/baseFolder/sparseFolder/subFolder/emptySubSubFolder" When user "user0" downloads zip file for entries '"sparseFolder"' in folder "/baseFolder/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a folder named "sparseFolder/" And the downloaded zip file contains a file named "sparseFolder/welcome.txt" with the contents of "/baseFolder/sparseFolder/welcome.txt" from "user0" data And the downloaded zip file contains a folder named "sparseFolder/subFolder/" And the downloaded zip file contains a folder named "sparseFolder/subFolder/emptySubSubFolder/" @large - Scenario: downloading small file and dir with 65524 small files and 9 nested directories returns a zip32 + Scenario: downloading small file and dir with 65524 small files and 9 nested directories Given using new dav path And user "user0" exists And user "user0" created a folder "/crowdedFolder" @@ -172,7 +174,7 @@ Feature: download And user "user0" created a folder "/crowdedFolder/subFolder7/subSubFolder" And user "user0" created a folder "/crowdedFolder/subFolder7/subSubFolder/emptySubSubSubFolder" When user "user0" downloads zip file for entries '"welcome.txt","crowdedFolder"' in folder "/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a file named "welcome.txt" with the contents of "/welcome.txt" from "user0" data And the downloaded zip file contains a folder named "crowdedFolder/" And the downloaded zip file contains a folder named "crowdedFolder/subFolder1/" @@ -181,7 +183,7 @@ Feature: download And the downloaded zip file contains a folder named "crowdedFolder/subFolder7/subSubFolder/emptySubSubSubFolder/" @large - Scenario: downloading dir with 65525 small files and 9 nested directories returns a zip32 + Scenario: downloading dir with 65525 small files and 9 nested directories Given using new dav path And user "user0" exists And user "user0" created a folder "/crowdedFolder" @@ -209,7 +211,7 @@ Feature: download And user "user0" created a folder "/crowdedFolder/subFolder7/subSubFolder" And user "user0" created a folder "/crowdedFolder/subFolder7/subSubFolder/emptySubSubSubFolder" When user "user0" downloads zip file for entries '"crowdedFolder"' in folder "/" - Then the downloaded zip file is a zip32 file + Then the downloaded file is a zip file And the downloaded zip file contains a folder named "crowdedFolder/" And the downloaded zip file contains a folder named "crowdedFolder/subFolder1/" And the downloaded zip file contains a file named "crowdedFolder/subFolder1/test.txt-0" with the contents of "/crowdedFolder/subFolder1/test.txt-0" from "user0" data diff --git a/build/integration/files_features/external-storage.feature b/build/integration/files_features/external-storage.feature index d92cca3c458..77abeb6c5a4 100644 --- a/build/integration/files_features/external-storage.feature +++ b/build/integration/files_features/external-storage.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: external-storage Background: Given using api version "1" @@ -14,14 +17,14 @@ Feature: external-storage And As an "user1" And accepting last share When creating a share with - | path | foo | - | shareType | 3 | + | path | foo | + | shareType | 3 | Then the OCS status code should be "100" And the HTTP status code should be "200" And Share fields of last share match with - | id | A_NUMBER | - | url | AN_URL | - | token | A_TOKEN | + | id | A_NUMBER | + | url | AN_URL | + | token | A_TOKEN | | mimetype | httpd/unix-directory | Scenario: Shares don't overwrite external storage @@ -60,3 +63,65 @@ Feature: external-storage Then as "user1" the file "/local_storage/foo2/textfile0.txt" does not exist And as "user0" the file "/local_storage/foo2/textfile0.txt" does not exist And as "user1" the file "/local.txt" exists + + + + Scenario: Save an external storage with password provided by user + Given Logging in using web as "admin" + And logged in user creates external global storage + | mountPoint | "ExternalStorageTest" | + | backend | "owncloud" | + | authMechanism | "password::userprovided" | + | backendOptions | {"host":"http://localhost:8080","secure":false} | + And fields of last external storage match with + | status | 2 | + When logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"admin"} | + Then fields of last external storage match with + | status | 0 | + + Scenario: Save an external storage again with an unmodified password provided by user + Given Logging in using web as "admin" + And logged in user creates external global storage + | mountPoint | "ExternalStorageTest" | + | backend | "owncloud" | + | authMechanism | "password::userprovided" | + | backendOptions | {"host":"http://localhost:8080","secure":false} | + And fields of last external storage match with + | status | 2 | + And logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"admin"} | + When logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"__unmodified__"} | + Then fields of last external storage match with + | status | 0 | + + Scenario: Save an external storage with global credentials provided by user + Given Logging in using web as "admin" + And logged in user creates external global storage + | mountPoint | "ExternalStorageTest" | + | backend | "owncloud" | + | authMechanism | "password::global::user" | + | backendOptions | {"host":"http://localhost:8080","secure":false} | + And fields of last external storage match with + | status | 2 | + When logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"admin"} | + Then fields of last external storage match with + | status | 0 | + + Scenario: Save an external storage again with unmodified global credentials provided by user + Given Logging in using web as "admin" + And logged in user creates external global storage + | mountPoint | "ExternalStorageTest" | + | backend | "owncloud" | + | authMechanism | "password::global::user" | + | backendOptions | {"host":"http://localhost:8080","secure":false} | + And fields of last external storage match with + | status | 2 | + And logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"admin"} | + When logged in user updates last external userglobal storage + | backendOptions | {"user":"admin","password":"__unmodified__"} | + Then fields of last external storage match with + | status | 0 | diff --git a/build/integration/files_features/favorites.feature b/build/integration/files_features/favorites.feature index 0439ada9d60..8e510799d20 100644 --- a/build/integration/files_features/favorites.feature +++ b/build/integration/files_features/favorites.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: favorite Background: Given using api version "1" diff --git a/build/integration/files_features/metadata.feature b/build/integration/files_features/metadata.feature new file mode 100644 index 00000000000..553a7b62306 --- /dev/null +++ b/build/integration/files_features/metadata.feature @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-only +Feature: metadata + + Scenario: Setting metadata works + Given user "user0" exists + When User "user0" uploads file with content "AAA" to "/test.txt" + And User "user0" sets the "metadata-files-live-photo" prop with value "metadata-value" on "/test.txt" + Then User "user0" should see the prop "metadata-files-live-photo" equal to "metadata-value" for file "/test.txt" + + Scenario: Deleting metadata works + Given user "user0" exists + When User "user0" uploads file with content "AAA" to "/test.txt" + And User "user0" sets the "metadata-files-live-photo" prop with value "metadata-value" on "/test.txt" + And User "user0" deletes the "metadata-files-live-photo" prop on "/test.txt" + Then User "user0" should not see the prop "metadata-files-live-photo" for file "/test.txt" diff --git a/build/integration/files_features/tags.feature b/build/integration/files_features/tags.feature index 495008ffdd2..fef8068cbc8 100644 --- a/build/integration/files_features/tags.feature +++ b/build/integration/files_features/tags.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: tags Scenario: Creating a normal tag as regular user should work diff --git a/build/integration/files_features/transfer-ownership.feature b/build/integration/files_features/transfer-ownership.feature index 22e34dcf7af..6f7a7944166 100644 --- a/build/integration/files_features/transfer-ownership.feature +++ b/build/integration/files_features/transfer-ownership.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: transfer-ownership Scenario: transferring ownership of a file @@ -39,7 +42,7 @@ Feature: transfer-ownership And As an "user1" And using received transfer folder of "user1" as dav path Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" - And transfer folder name contains "transferred from user0 -risky- ヂspḷay -na|-|e- on" + And transfer folder name contains "Transferred from user0 -risky- ヂspḷay -na|-|e- on" And using old dav path And as "user0" the folder "/test" does not exist And using received transfer folder of "user1" as dav path @@ -181,10 +184,10 @@ Feature: transfer-ownership And As an "user2" Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" And using old dav path - And as "user0" the folder "/test" exists + And as "user0" the folder "/test" does not exist And using received transfer folder of "user1" as dav path - And as "user1" the folder "/test" does not exist - And As an "user0" + And as "user1" the folder "/test" exists + And As an "user1" And Getting info of last share And the OCS status code should be "100" And Share fields of last share match with @@ -207,13 +210,12 @@ Feature: transfer-ownership And user "user1" accepts last share When transferring ownership from "user0" to "user1" And the command was successful - And As an "user1" - Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" And using old dav path - And as "user0" the folder "/test" exists + Then as "user0" the folder "/test" does not exist + When As an "user1" And using received transfer folder of "user1" as dav path - And as "user1" the folder "/test" does not exist - And As an "user1" + Then as "user1" the folder "/test" exists + And Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" And Getting info of last share And the OCS status code should be "100" And Share fields of last share match with @@ -239,10 +241,10 @@ Feature: transfer-ownership And As an "user2" Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" And using old dav path - And as "user0" the folder "/test" exists + And as "user0" the folder "/test" does not exist And using received transfer folder of "user1" as dav path - And as "user1" the folder "/test" does not exist - And As an "user0" + And as "user1" the folder "/test" exists + And As an "user1" And Getting info of last share And the OCS status code should be "100" And Share fields of last share match with @@ -250,7 +252,7 @@ Feature: transfer-ownership | uid_file_owner | user3 | | share_with | group1 | - Scenario: transferring ownership does not transfer received shares + Scenario: transferring ownership transfers received shares Given user "user0" exists And user "user1" exists And user "user2" exists @@ -261,16 +263,16 @@ Feature: transfer-ownership And the command was successful And As an "user1" And using received transfer folder of "user1" as dav path - Then as "user1" the folder "/test" does not exist + Then as "user1" the folder "/test" exists And using old dav path - And as "user0" the folder "/test" exists + And as "user0" the folder "/test" does not exist And As an "user2" And Getting info of last share And the OCS status code should be "100" And Share fields of last share match with | uid_owner | user2 | | uid_file_owner | user2 | - | share_with | user0 | + | share_with | user1 | @local_storage Scenario: transferring ownership does not transfer external storage @@ -345,7 +347,7 @@ Feature: transfer-ownership And As an "user1" And using received transfer folder of "user1" as dav path Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is" - And transfer folder name contains "transferred from user0 -risky- ヂspḷay -na|-|e- on" + And transfer folder name contains "Transferred from user0 -risky- ヂspḷay -na|-|e- on" And using old dav path And as "user0" the folder "/test" does not exist And using received transfer folder of "user1" as dav path @@ -511,27 +513,7 @@ Feature: transfer-ownership And user "user2" accepts last share When transferring ownership of path "test" from "user0" to "user1" Then the command failed with exit code 1 - And the command output contains the text "Could not transfer files." - - Scenario: transferring ownership does not transfer received shares - Given user "user0" exists - And user "user1" exists - And user "user2" exists - And User "user2" created a folder "/test" - And User "user0" created a folder "/sub" - And folder "/test" of user "user2" is shared with user "user0" with permissions 31 - And user "user0" accepts last share - And User "user0" moved folder "/test" to "/sub/test" - When transferring ownership of path "sub" from "user0" to "user1" - And the command was successful - And As an "user1" - And using received transfer folder of "user1" as dav path - Then as "user1" the folder "/sub" exists - And as "user1" the folder "/sub/test" does not exist - And using old dav path - And as "user0" the folder "/sub" does not exist - And Getting info of last share - And the OCS status code should be "404" + And the command error output contains the text "Moving a storage (user0/files/test) into another storage (user1) is not allowed" Scenario: transferring ownership transfers received shares into subdir when requested Given user "user0" exists @@ -545,7 +527,7 @@ Feature: transfer-ownership And User "user0" moved folder "/transfer-share" to "/sub/transfer-share" And folder "/do-not-transfer" of user "user2" is shared with user "user0" with permissions 31 And user "user0" accepts last share - When transferring ownership of path "sub" from "user0" to "user1" with received shares + When transferring ownership of path "sub" from "user0" to "user1" And the command was successful And As an "user1" And using received transfer folder of "user1" as dav path diff --git a/build/integration/files_features/trashbin.feature b/build/integration/files_features/trashbin.feature index 3a9c29f7cb8..fd84e396ba3 100644 --- a/build/integration/files_features/trashbin.feature +++ b/build/integration/files_features/trashbin.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2017 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: trashbin Background: Given using api version "1" diff --git a/build/integration/files_features/windows_compatibility.feature b/build/integration/files_features/windows_compatibility.feature new file mode 100644 index 00000000000..feaaca1ed3a --- /dev/null +++ b/build/integration/files_features/windows_compatibility.feature @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +Feature: Windows compatible filenames + Background: + Given using api version "1" + And using new dav path + And As an "admin" + + Scenario: prevent upload files with invalid name + Given As an "admin" + And user "user0" exists + And invoking occ with "files:windows-compatible-filenames --enable" + Given User "user0" created a folder "/com1" + Then as "user0" the file "/com1" does not exist + + Scenario: renaming a folder with invalid name + Given As an "admin" + When invoking occ with "files:windows-compatible-filenames --disable" + And user "user0" exists + Given User "user0" created a folder "/aux" + When invoking occ with "files:windows-compatible-filenames --enable" + And invoking occ with "files:sanitize-filenames user0" + Then as "user0" the file "/aux" does not exist + And as "user0" the file "/aux (renamed)" exists + + Scenario: renaming a file with invalid base name + Given As an "admin" + When invoking occ with "files:windows-compatible-filenames --disable" + And user "user0" exists + When User "user0" uploads file with content "hello" to "/com0.txt" + And invoking occ with "files:windows-compatible-filenames --enable" + And invoking occ with "files:sanitize-filenames user0" + Then as "user0" the file "/com0.txt" does not exist + And as "user0" the file "/com0 (renamed).txt" exists + + Scenario: renaming a file with invalid extension + Given As an "admin" + When invoking occ with "files:windows-compatible-filenames --disable" + And user "user0" exists + When User "user0" uploads file with content "hello" to "/foo.txt." + And as "user0" the file "/foo.txt." exists + And invoking occ with "files:windows-compatible-filenames --enable" + And invoking occ with "files:sanitize-filenames user0" + Then as "user0" the file "/foo.txt." does not exist + And as "user0" the file "/foo.txt" exists + + Scenario: renaming a file with invalid character + Given As an "admin" + When invoking occ with "files:windows-compatible-filenames --disable" + And user "user0" exists + When User "user0" uploads file with content "hello" to "/2*2=4.txt" + And as "user0" the file "/2*2=4.txt" exists + And invoking occ with "files:windows-compatible-filenames --enable" + And invoking occ with "files:sanitize-filenames user0" + Then as "user0" the file "/2*2=4.txt" does not exist + And as "user0" the file "/2_2=4.txt" exists + + Scenario: renaming a file with invalid character and replacement setup + Given As an "admin" + When invoking occ with "files:windows-compatible-filenames --disable" + And user "user0" exists + When User "user0" uploads file with content "hello" to "/2*3=6.txt" + And as "user0" the file "/2*3=6.txt" exists + And invoking occ with "files:windows-compatible-filenames --enable" + And invoking occ with "files:sanitize-filenames --char-replacement + user0" + Then as "user0" the file "/2*3=6.txt" does not exist + And as "user0" the file "/2+3=6.txt" exists diff --git a/build/integration/filesdrop_features/filesdrop.feature b/build/integration/filesdrop_features/filesdrop.feature index 4a8759e241a..7618a31a1d0 100644 --- a/build/integration/filesdrop_features/filesdrop.feature +++ b/build/integration/filesdrop_features/filesdrop.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: FilesDrop Scenario: Put file via files drop @@ -31,7 +33,7 @@ Feature: FilesDrop And Downloading file "/drop/a (2).txt" Then Downloaded content should be "def" - Scenario: Files drop ignores directory + Scenario: Files drop forbid directory without a nickname Given user "user0" exists And As an "user0" And user "user0" created a folder "/drop" @@ -42,10 +44,9 @@ Feature: FilesDrop And Updating last share with | permissions | 4 | When Dropping file "/folder/a.txt" with "abc" - And Downloading file "/drop/a.txt" - Then Downloaded content should be "abc" + Then the HTTP status code should be "400" - Scenario: Files drop forbis MKCOL + Scenario: Files drop forbid MKCOL without a nickname Given user "user0" exists And As an "user0" And user "user0" created a folder "/drop" @@ -56,4 +57,181 @@ Feature: FilesDrop And Updating last share with | permissions | 4 | When Creating folder "folder" in drop + Then the HTTP status code should be "400" + + Scenario: Files drop allows MKCOL with a nickname + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/drop" + And as "user0" creating a share with + | path | drop | + | shareType | 3 | + | publicUpload | true | + And Updating last share with + | permissions | 4 | + When Creating folder "folder" in drop as "nickname" + Then the HTTP status code should be "201" + + Scenario: Files drop forbid subfolder creation without a nickname + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/drop" + And as "user0" creating a share with + | path | drop | + | shareType | 3 | + | publicUpload | true | + And Updating last share with + | permissions | 4 | + When dropping file "/folder/a.txt" with "abc" + Then the HTTP status code should be "400" + + Scenario: Files request drop + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/drop" + And as "user0" creating a share with + | path | drop | + | shareType | 4 | + | permissions | 4 | + | attributes | [{"scope":"fileRequest","key":"enabled","value":true}] | + | shareWith | | + When Dropping file "/folder/a.txt" with "abc" as "Alice" + And Downloading file "/drop/Alice/folder/a.txt" + Then Downloaded content should be "abc" + + Scenario: File drop uploading folder with name of file + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/drop" + And as "user0" creating a share with + | path | drop | + | shareType | 4 | + | permissions | 4 | + | attributes | [{"scope":"fileRequest","key":"enabled","value":true}] | + | shareWith | | + When Dropping file "/folder" with "its a file" as "Alice" + Then the HTTP status code should be "201" + When Dropping file "/folder/a.txt" with "abc" as "Alice" + Then the HTTP status code should be "201" + When Downloading file "/drop/Alice/folder" + Then the HTTP status code should be "200" + And Downloaded content should be "its a file" + When Downloading file "/drop/Alice/folder (2)/a.txt" + Then Downloaded content should be "abc" + + Scenario: File drop uploading file with name of folder + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/drop" + And as "user0" creating a share with + | path | drop | + | shareType | 4 | + | permissions | 4 | + | attributes | [{"scope":"fileRequest","key":"enabled","value":true}] | + | shareWith | | + When Dropping file "/folder/a.txt" with "abc" as "Alice" + Then the HTTP status code should be "201" + When Dropping file "/folder" with "its a file" as "Alice" + Then the HTTP status code should be "201" + When Downloading file "/drop/Alice/folder/a.txt" + Then the HTTP status code should be "200" + And Downloaded content should be "abc" + When Downloading file "/drop/Alice/folder (2)" + Then the HTTP status code should be "200" + And Downloaded content should be "its a file" + + Scenario: Put file same file multiple times via files drop + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/drop" + And as "user0" creating a share with + | path | drop | + | shareType | 4 | + | permissions | 4 | + | attributes | [{"scope":"fileRequest","key":"enabled","value":true}] | + | shareWith | | + When Dropping file "/folder/a.txt" with "abc" as "Mallory" + And Dropping file "/folder/a.txt" with "def" as "Mallory" + # Ensure folder structure and that we only checked + # for files duplicates, but merged the existing folders + Then as "user0" the folder "/drop/Mallory" exists + Then as "user0" the folder "/drop/Mallory/folder" exists + Then as "user0" the folder "/drop/Mallory (2)" does not exist + Then as "user0" the folder "/drop/Mallory/folder (2)" does not exist + Then as "user0" the file "/drop/Mallory/folder/a.txt" exists + Then as "user0" the file "/drop/Mallory/folder/a (2).txt" exists + And Downloading file "/drop/Mallory/folder/a.txt" + Then Downloaded content should be "abc" + And Downloading file "/drop/Mallory/folder/a (2).txt" + Then Downloaded content should be "def" + + Scenario: Files drop prevents GET + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/drop" + And as "user0" creating a share with + | path | drop | + | shareType | 4 | + | permissions | 4 | + | shareWith | | + | attributes | [{"scope":"fileRequest","key":"enabled","value":true}] | + When Dropping file "/folder/a.txt" with "abc" as "Mallory" + When as "user0" the file "/drop/Mallory/folder/a.txt" exists + And Downloading public folder "Mallory" Then the HTTP status code should be "405" + And Downloading public folder "Mallory/folder" + Then the HTTP status code should be "405" + And Downloading public file "Mallory/folder/a.txt" + Then the HTTP status code should be "405" + + Scenario: Files drop requires nickname if file request is enabled + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/drop" + And as "user0" creating a share with + | path | drop | + | shareType | 4 | + | permissions | 4 | + | attributes | [{"scope":"fileRequest","key":"enabled","value":true}] | + | shareWith | | + When Dropping file "/folder/a.txt" with "abc" + Then the HTTP status code should be "400" + + Scenario: Files request drop with invalid nickname with slashes + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/drop" + And as "user0" creating a share with + | path | drop | + | shareType | 4 | + | permissions | 4 | + | attributes | [{"scope":"fileRequest","key":"enabled","value":true}] | + | shareWith | | + When Dropping file "/folder/a.txt" with "abc" as "Alice/Bob/Mallory" + Then the HTTP status code should be "400" + + Scenario: Files request drop with invalid nickname with forbidden characters + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/drop" + And as "user0" creating a share with + | path | drop | + | shareType | 4 | + | permissions | 4 | + | attributes | [{"scope":"fileRequest","key":"enabled","value":true}] | + | shareWith | | + When Dropping file "/folder/a.txt" with "abc" as ".htaccess" + Then the HTTP status code should be "400" + + Scenario: Files request drop with invalid nickname with forbidden characters + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/drop" + And as "user0" creating a share with + | path | drop | + | shareType | 4 | + | permissions | 4 | + | attributes | [{"scope":"fileRequest","key":"enabled","value":true}] | + | shareWith | | + When Dropping file "/folder/a.txt" with "abc" as ".Mallory" + Then the HTTP status code should be "400" diff --git a/build/integration/ldap_features/ldap-ocs.feature b/build/integration/ldap_features/ldap-ocs.feature index a9ad0478702..d6d79ad9c58 100644 --- a/build/integration/ldap_features/ldap-ocs.feature +++ b/build/integration/ldap_features/ldap-ocs.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: LDAP Background: Given using api version "2" diff --git a/build/integration/ldap_features/ldap-openldap.feature b/build/integration/ldap_features/ldap-openldap.feature index 570cf287a2e..14fa3b63968 100644 --- a/build/integration/ldap_features/ldap-openldap.feature +++ b/build/integration/ldap_features/ldap-openldap.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: LDAP Background: Given using api version "2" diff --git a/build/integration/openldap_features/openldap-uid-username.feature b/build/integration/openldap_features/openldap-uid-username.feature index 6793273e8c7..bee4098972b 100644 --- a/build/integration/openldap_features/openldap-uid-username.feature +++ b/build/integration/openldap_features/openldap-uid-username.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: LDAP Background: Given using api version "2" @@ -149,6 +151,7 @@ Feature: LDAP | ldapAttributesForUserSearch | employeeNumber | | useMemberOfToDetectMembership | 1 | And parameter "shareapi_only_share_with_group_members" of app "core" is set to "yes" + And invoking occ with "ldap:check-group cn=Orcharding,ou=OtherGroups,dc=nextcloud,dc=ci --update" And As an "alice" When getting sharees for # "5" is part of the employee number of some LDAP records @@ -160,4 +163,3 @@ Feature: LDAP And "users" sharees returned are | Elisa | 0 | elisa | And "exact groups" sharees returned is empty - diff --git a/build/integration/openldap_numerical_features/openldap-numerical-id.feature b/build/integration/openldap_numerical_features/openldap-numerical-id.feature index 75eb6827192..f4d2b1d77d2 100644 --- a/build/integration/openldap_numerical_features/openldap-numerical-id.feature +++ b/build/integration/openldap_numerical_features/openldap-numerical-id.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: LDAP Background: Given using api version "2" diff --git a/build/integration/features/ratelimiting.feature b/build/integration/ratelimiting_features/ratelimiting.feature index 8f23c073e69..43cfddec85d 100644 --- a/build/integration/features/ratelimiting.feature +++ b/build/integration/ratelimiting_features/ratelimiting.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +@RateLimiting Feature: ratelimiting Background: diff --git a/build/integration/remoteapi_features/remote.feature b/build/integration/remoteapi_features/remote.feature index 62fd95e0130..81e10027aae 100644 --- a/build/integration/remoteapi_features/remote.feature +++ b/build/integration/remoteapi_features/remote.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: remote Scenario: Get status of remote server diff --git a/build/integration/routing_features/apps-and-routes.feature b/build/integration/routing_features/apps-and-routes.feature new file mode 100644 index 00000000000..954ea73bfac --- /dev/null +++ b/build/integration/routing_features/apps-and-routes.feature @@ -0,0 +1,52 @@ +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +Feature: appmanagement + Background: + Given using api version "2" + And user "user1" exists + And user "user2" exists + And group "group1" exists + And user "user1" belongs to group "group1" + + Scenario: Enable app and test route + Given As an "admin" + And sending "DELETE" to "/cloud/apps/weather_status" + And app "weather_status" is disabled + When sending "GET" to "/apps/weather_status/api/v1/location" + Then the OCS status code should be "998" + And the HTTP status code should be "404" + When sending "POST" to "/cloud/apps/weather_status" + Then the OCS status code should be "200" + And the HTTP status code should be "200" + And app "weather_status" is enabled + When sending "GET" to "/apps/weather_status/api/v1/location" + Then the OCS status code should be "200" + And the HTTP status code should be "200" + Given As an "user1" + When sending "GET" to "/apps/weather_status/api/v1/location" + Then the OCS status code should be "200" + And the HTTP status code should be "200" + Given As an "user2" + When sending "GET" to "/apps/weather_status/api/v1/location" + Then the OCS status code should be "200" + And the HTTP status code should be "200" + + Scenario: Enable app only for some groups + Given As an "admin" + And sending "DELETE" to "/cloud/apps/weather_status" + And app "weather_status" is disabled + When sending "GET" to "/apps/weather_status/api/v1/location" + Then the OCS status code should be "998" + And the HTTP status code should be "404" + Given invoking occ with "app:enable weather_status --groups group1" + Then the command was successful + Given As an "user2" + When sending "GET" to "/apps/weather_status/api/v1/location" + Then the HTTP status code should be "412" + Given As an "user1" + When sending "GET" to "/apps/weather_status/api/v1/location" + Then the OCS status code should be "200" + And the HTTP status code should be "200" + Given As an "admin" + And sending "DELETE" to "/cloud/apps/weather_status" + And app "weather_status" is disabled diff --git a/build/integration/run-docker.sh b/build/integration/run-docker.sh index 080a992eefd..e1ec797fcf0 100755 --- a/build/integration/run-docker.sh +++ b/build/integration/run-docker.sh @@ -1,22 +1,7 @@ #!/usr/bin/env bash -# @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com) -# @copyright Copyright (c) 2018, Daniel Calviño Sánchez (danxuliu@gmail.com) -# -# @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 # Helper script to run the integration tests on a fresh Nextcloud server through # Docker. @@ -216,7 +201,7 @@ cd "$(dirname $0)" # "--image XXX" option can be provided to set the Docker image to use to run # the integration tests (one of the "nextcloudci/phpX.Y:phpX.Y-Z" or # "ghcr.io/nextcloud/continuous-integration-integration-phpX.Y:latest" images). -NEXTCLOUD_LOCAL_IMAGE="ghcr.io/nextcloud/continuous-integration-integration-php8.0:latest" +NEXTCLOUD_LOCAL_IMAGE="ghcr.io/nextcloud/continuous-integration-integration-php8.2:latest" if [ "$1" = "--image" ]; then NEXTCLOUD_LOCAL_IMAGE=$2 @@ -242,9 +227,9 @@ fi # "--database-image XXX" option can be provided to set the Docker image to use # for the database container (ignored when using "sqlite"). if [ "$DATABASE" = "mysql" ]; then - DATABASE_IMAGE="mysql:5.7" + DATABASE_IMAGE="mysql:8.4" elif [ "$DATABASE" = "pgsql" ]; then - DATABASE_IMAGE="postgres:10" + DATABASE_IMAGE="postgres:15" fi if [ "$1" = "--database-image" ]; then DATABASE_IMAGE=$2 diff --git a/build/integration/run.sh b/build/integration/run.sh index 09c1d544c6d..30dd0646b10 100755 --- a/build/integration/run.sh +++ b/build/integration/run.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash - +# +# SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2015-2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only +# OC_PATH=../../ OCC=${OC_PATH}occ TAGS="" @@ -14,10 +18,18 @@ HIDE_OC_LOGS=$2 INSTALLED=$($OCC status | grep installed: | cut -d " " -f 5) if [ "$INSTALLED" == "true" ]; then + # Disable appstore to avoid spamming from CI + $OCC config:system:set appstoreenabled --value=false --type=boolean # Disable bruteforce protection because the integration tests do trigger them $OCC config:system:set auth.bruteforce.protection.enabled --value false --type bool + # Disable rate limit protection because the integration tests do trigger them + $OCC config:system:set ratelimit.protection.enabled --value false --type bool # Allow local remote urls otherwise we can not share $OCC config:system:set allow_local_remote_servers --value true --type bool + # Allow self signed certificates + $OCC config:system:set sharing.federation.allowSelfSignedCertificates --value true --type bool + # Allow creating users with dummy passwords + $OCC app:disable password_policy else if [ "$SCENARIO_TO_RUN" != "setup_features/setup.feature" ]; then echo "Nextcloud instance needs to be installed" >&2 @@ -34,15 +46,25 @@ if [ -z "$EXECUTOR_NUMBER" ]; then fi PORT=$((8080 + $EXECUTOR_NUMBER)) echo $PORT +export PORT +echo "" > "${NC_DATADIR}/nextcloud.log" echo "" > phpserver.log -php -S localhost:$PORT -t ../.. &> phpserver.log & +PHP_CLI_SERVER_WORKERS=2 php -S localhost:$PORT -t ../.. &> phpserver.log & PHPPID=$! echo $PHPPID # Output filtered php server logs tail -f phpserver.log | grep --line-buffered -v -E ":[0-9]+ Accepted$" | grep --line-buffered -v -E ":[0-9]+ Closing$" & +LOGPID=$! +echo $LOGPID + +function cleanup() { + kill $PHPPID + kill $LOGPID +} +trap cleanup EXIT # The federated server is started and stopped by the tests themselves PORT_FED=$((8180 + $EXECUTOR_NUMBER)) @@ -69,8 +91,6 @@ fi vendor/bin/behat --strict --colors -f junit -f pretty $TAGS $SCENARIO_TO_RUN RESULT=$? -kill $PHPPID - if [ "$INSTALLED" == "true" ]; then $OCC files_external:delete -y $ID_STORAGE diff --git a/build/integration/setup_features/setup.feature b/build/integration/setup_features/setup.feature index e1d9a73187e..5fb2ff16330 100644 --- a/build/integration/setup_features/setup.feature +++ b/build/integration/setup_features/setup.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: setup Scenario: setup page is shown properly diff --git a/build/integration/sharees_features/sharees.feature b/build/integration/sharees_features/sharees.feature index 1d770b96b72..8b0a0e5133e 100644 --- a/build/integration/sharees_features/sharees.feature +++ b/build/integration/sharees_features/sharees.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2016 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: sharees Background: Given using api version "1" diff --git a/build/integration/sharees_features/sharees_provisioningapiv2.feature b/build/integration/sharees_features/sharees_provisioningapiv2.feature index 6f2b8df8e0e..7bd8ecbdbb7 100644 --- a/build/integration/sharees_features/sharees_provisioningapiv2.feature +++ b/build/integration/sharees_features/sharees_provisioningapiv2.feature @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors +# SPDX-FileCopyrightText: 2017 ownCloud, Inc. +# SPDX-License-Identifier: AGPL-3.0-only Feature: sharees_provisioningapiv2 Background: Given using api version "2" diff --git a/build/integration/sharing_features/sharing-activity.feature b/build/integration/sharing_features/sharing-activity.feature new file mode 100644 index 00000000000..016b376488b --- /dev/null +++ b/build/integration/sharing_features/sharing-activity.feature @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +Feature: sharing + Background: + Given using api version "1" + Given using new dav path + Given invoking occ with "app:enable --force activity" + Given the command was successful + Given user "user0" exists + And Logging in using web as "user0" + And Sending a "POST" to "/apps/activity/settings" with requesttoken + | public_links_notification | 1 | + | public_links_upload_notification | 1 | + | notify_setting_batchtime | 0 | + | activity_digest | 0 | + + Scenario: Creating a new mail share and check activity + Given dummy mail server is listening + And As an "user0" + When creating a share with + | path | welcome.txt | + | shareType | 4 | + | shareWith | dumy@test.com | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last share can be downloaded + Then last activity should be + | app | files_sharing | + | type | public_links | + | object_type | files | + | object_name | /welcome.txt | + + Scenario: Creating a new public share and check activity + Given user "user0" exists + And As an "user0" + When creating a share with + | path | welcome.txt | + | shareType | 3 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last link share can be downloaded + Then last activity should be + | app | files_sharing | + | type | public_links | + | object_type | files | + | object_name | /welcome.txt | diff --git a/build/integration/sharing_features/sharing-v1-part2.feature b/build/integration/sharing_features/sharing-v1-part2.feature index a9e2e50ce02..a6e4c67165a 100644 --- a/build/integration/sharing_features/sharing-v1-part2.feature +++ b/build/integration/sharing_features/sharing-v1-part2.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: sharing Background: Given using api version "1" @@ -541,6 +543,29 @@ Feature: sharing And the HTTP status code should be "200" And last share_id is included in the answer + Scenario: Group shares are deleted when the group is deleted + Given As an "admin" + And user "user0" exists + And user "user1" exists + And group "group0" exists + And user "user0" belongs to group "group0" + And file "textfile0.txt" of user "user1" is shared with group "group0" + And As an "user0" + When sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is included in the answer + When group "group0" does not exist + Then sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + And the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is not included in the answer + When group "group0" exists + Then sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + And the OCS status code should be "100" + And the HTTP status code should be "200" + And last share_id is not included in the answer + Scenario: User is not allowed to reshare file As an "admin" Given user "user0" exists @@ -699,6 +724,79 @@ Feature: sharing Then the OCS status code should be "404" And the HTTP status code should be "200" + Scenario: download restrictions can not be dropped + As an "admin" + Given user "user0" exists + And user "user1" exists + And user "user2" exists + And User "user0" uploads file with content "foo" to "/tmp.txt" + And As an "user0" + And creating a share with + | path | /tmp.txt | + | shareType | 0 | + | shareWith | user1 | + | permissions | 17 | + | attributes | [{"scope":"permissions","key":"download","value":false}] | + And As an "user1" + And accepting last share + When Getting info of last share + Then Share fields of last share match with + | uid_owner | user0 | + | uid_file_owner | user0 | + | permissions | 17 | + | attributes | [{"scope":"permissions","key":"download","value":false}] | + When creating a share with + | path | /tmp.txt | + | shareType | 0 | + | shareWith | user2 | + | permissions | 1 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + When As an "user2" + And accepting last share + And Getting info of last share + Then Share fields of last share match with + | share_type | 0 | + | permissions | 1 | + | uid_owner | user1 | + | uid_file_owner | user0 | + | attributes | [{"scope":"permissions","key":"download","value":false}] | + + Scenario: download restrictions can not be dropped when re-sharing even on link shares + As an "admin" + Given user "user0" exists + And user "user1" exists + And User "user0" uploads file with content "foo" to "/tmp.txt" + And As an "user0" + And creating a share with + | path | /tmp.txt | + | shareType | 0 | + | shareWith | user1 | + | permissions | 17 | + | attributes | [{"scope":"permissions","key":"download","value":false}] | + And As an "user1" + And accepting last share + When Getting info of last share + Then Share fields of last share match with + | uid_owner | user0 | + | attributes | [{"scope":"permissions","key":"download","value":false}] | + When creating a share with + | path | /tmp.txt | + | shareType | 3 | + | permissions | 1 | + And Getting info of last share + And Updating last share with + | hideDownload | false | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + When Getting info of last share + Then Share fields of last share match with + | share_type | 3 | + | uid_owner | user1 | + | uid_file_owner | user0 | + | hide_download | 1 | + | attributes | [{"scope":"permissions","key":"download","value":false}] | + Scenario: User is not allowed to reshare file with additional delete permissions As an "admin" Given user "user0" exists @@ -1167,7 +1265,9 @@ Feature: sharing |{http://open-collaboration-services.org/ns}share-permissions | Then the single response should contain a property "{http://open-collaboration-services.org/ns}share-permissions" with value "19" - Scenario: Cannot download a file when it's shared view-only + Scenario: Cannot download a file when it's shared view-only without shareapi_allow_view_without_download + Given As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "no" Given user "user0" exists And user "user1" exists And User "user0" moves file "/textfile0.txt" to "/document.odt" @@ -1176,8 +1276,15 @@ Feature: sharing When As an "user1" And Downloading file "/document.odt" Then the HTTP status code should be "403" + Then As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "yes" + Then As an "user1" + And Downloading file "/document.odt" + Then the HTTP status code should be "200" - Scenario: Cannot download a file when its parent is shared view-only + Scenario: Cannot download a file when its parent is shared view-only without shareapi_allow_view_without_download + Given As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "no" Given user "user0" exists And user "user1" exists And User "user0" created a folder "/sharedviewonly" @@ -1187,8 +1294,15 @@ Feature: sharing When As an "user1" And Downloading file "/sharedviewonly/document.odt" Then the HTTP status code should be "403" + Then As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "yes" + Then As an "user1" + And Downloading file "/sharedviewonly/document.odt" + Then the HTTP status code should be "200" - Scenario: Cannot copy a file when it's shared view-only + Scenario: Cannot copy a file when it's shared view-only even with shareapi_allow_view_without_download enabled + Given As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "no" Given user "user0" exists And user "user1" exists And User "user0" moves file "/textfile0.txt" to "/document.odt" @@ -1196,8 +1310,15 @@ Feature: sharing And user "user1" accepts last share When User "user1" copies file "/document.odt" to "/copyforbidden.odt" Then the HTTP status code should be "403" + Then As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "yes" + Then As an "user1" + And User "user1" copies file "/document.odt" to "/copyforbidden.odt" + Then the HTTP status code should be "403" Scenario: Cannot copy a file when its parent is shared view-only + Given As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "no" Given user "user0" exists And user "user1" exists And User "user0" created a folder "/sharedviewonly" @@ -1206,5 +1327,10 @@ Feature: sharing And user "user1" accepts last share When User "user1" copies file "/sharedviewonly/document.odt" to "/copyforbidden.odt" Then the HTTP status code should be "403" + Then As an "admin" + And parameter "shareapi_allow_view_without_download" of app "core" is set to "yes" + Then As an "user1" + And User "user1" copies file "/sharedviewonly/document.odt" to "/copyforbidden.odt" + Then the HTTP status code should be "403" # See sharing-v1-part3.feature diff --git a/build/integration/sharing_features/sharing-v1-part3.feature b/build/integration/sharing_features/sharing-v1-part3.feature index 1331d5b2ba6..3c2945e3ad4 100644 --- a/build/integration/sharing_features/sharing-v1-part3.feature +++ b/build/integration/sharing_features/sharing-v1-part3.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 20198 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: sharing Background: Given using api version "1" diff --git a/build/integration/sharing_features/sharing-v1-part4.feature b/build/integration/sharing_features/sharing-v1-part4.feature index ae4e69f2622..d138f0a1769 100644 --- a/build/integration/sharing_features/sharing-v1-part4.feature +++ b/build/integration/sharing_features/sharing-v1-part4.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: sharing Background: Given using api version "1" @@ -39,3 +41,144 @@ Scenario: Creating a new share of a file you own shows the file permissions And the HTTP status code should be "200" And Share fields of last share match with | item_permissions | 27 | + +Scenario: Receiving a share of a file gives no create permission + Given user "user0" exists + And user "user1" exists + And As an "user0" + And parameter "shareapi_default_permissions" of app "core" is set to "31" + And file "welcome.txt" of user "user0" is shared with user "user1" + And sending "GET" to "/apps/files_sharing/api/v1/shares" + And share 0 is returned with + | path | /welcome.txt | + | permissions | 19 | + | item_permissions | 27 | + When As an "user1" + And user "user1" accepts last share + And sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + Then the list of returned shares has 1 shares + And share 0 is returned with + | path | /welcome (2).txt | + | permissions | 19 | + | item_permissions | 27 | + +Scenario: Receiving a share of a folder gives create permission + Given user "user0" exists + And user "user1" exists + And As an "user0" + And parameter "shareapi_default_permissions" of app "core" is set to "31" + And file "PARENT/CHILD" of user "user0" is shared with user "user1" + And sending "GET" to "/apps/files_sharing/api/v1/shares" + And share 0 is returned with + | path | /PARENT/CHILD | + | permissions | 31 | + | item_permissions | 31 | + When As an "user1" + And user "user1" accepts last share + And sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + Then the list of returned shares has 1 shares + And share 0 is returned with + | path | /CHILD | + | permissions | 31 | + | item_permissions | 31 | + +# User can remove itself from a share +Scenario: Receiving a share of a file without delete permission gives delete permission anyway + Given user "user0" exists + And user "user1" exists + And As an "user0" + And parameter "shareapi_default_permissions" of app "core" is set to "23" + And file "welcome.txt" of user "user0" is shared with user "user1" + And sending "GET" to "/apps/files_sharing/api/v1/shares" + And share 0 is returned with + | path | /welcome.txt | + | permissions | 19 | + | item_permissions | 27 | + When As an "user1" + And user "user1" accepts last share + And sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + Then the list of returned shares has 1 shares + And share 0 is returned with + | path | /welcome (2).txt | + | permissions | 19 | + | item_permissions | 27 | + +Scenario: Receiving a share of a file without delete permission gives delete permission anyway + Given user "user0" exists + And user "user1" exists + And As an "user0" + And group "group1" exists + And user "user1" belongs to group "group1" + And parameter "shareapi_default_permissions" of app "core" is set to "23" + And file "welcome.txt" of user "user0" is shared with group "group1" + And sending "GET" to "/apps/files_sharing/api/v1/shares" + And share 0 is returned with + | path | /welcome.txt | + | permissions | 19 | + | item_permissions | 27 | + When As an "user1" + And user "user1" accepts last share + And sending "GET" to "/apps/files_sharing/api/v1/shares?shared_with_me=true" + Then the list of returned shares has 1 shares + And share 0 is returned with + | path | /welcome (2).txt | + | permissions | 19 | + | item_permissions | 27 | + +# This is a regression test as in the past creating a file drop required creating with permissions=5 +# and then afterwards update the share to permissions=4 +Scenario: Directly create link share with CREATE only permissions (file drop) + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/TMP" + When creating a share with + | path | TMP | + | shareType | 3 | + | permissions | 4 | + And Getting info of last share + Then Share fields of last share match with + | uid_file_owner | user0 | + | share_type | 3 | + | permissions | 4 | + +Scenario: Directly create email share with CREATE only permissions (file drop) + Given user "user0" exists + And As an "user0" + And user "user0" created a folder "/TMP" + When creating a share with + | path | TMP | + | shareType | 4 | + | shareWith | j.doe@example.com | + | permissions | 4 | + And Getting info of last share + Then Share fields of last share match with + | uid_file_owner | user0 | + | share_type | 4 | + | permissions | 4 | + +# This ensures the legacy behavior of sharing v1 is kept +Scenario: publicUpload overrides permissions + Given user "user0" exists + And As an "user0" + And parameter "outgoing_server2server_share_enabled" of app "files_sharing" is set to "no" + And user "user0" created a folder "/TMP" + When creating a share with + | path | TMP | + | shareType | 3 | + | permissions | 4 | + | publicUpload | true | + And Getting info of last share + Then Share fields of last share match with + | uid_file_owner | user0 | + | share_type | 3 | + | permissions | 15 | + When creating a share with + | path | TMP | + | shareType | 3 | + | permissions | 4 | + | publicUpload | false | + And Getting info of last share + Then Share fields of last share match with + | uid_file_owner | user0 | + | share_type | 3 | + | permissions | 1 | diff --git a/build/integration/sharing_features/sharing-v1.feature b/build/integration/sharing_features/sharing-v1.feature index ca030bd3a31..25f168db2e7 100644 --- a/build/integration/sharing_features/sharing-v1.feature +++ b/build/integration/sharing_features/sharing-v1.feature @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: sharing Background: Given using api version "1" @@ -229,6 +231,62 @@ Feature: sharing | url | AN_URL | | mimetype | httpd/unix-directory | + Scenario: Creating a new share with expiration date empty, when default expiration is set + Given user "user0" exists + And user "user1" exists + And parameter "shareapi_default_internal_expire_date" of app "core" is set to "yes" + And parameter "shareapi_internal_expire_after_n_days" of app "core" is set to "3" + And As an "user0" + When creating a share with + | path | welcome.txt | + | shareWith | user1 | + | shareType | 0 | + | expireDate | | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Getting info of last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | expiration || + + Scenario: Creating a new share with expiration date removed, when default expiration is set + Given user "user0" exists + And user "user1" exists + And parameter "shareapi_default_internal_expire_date" of app "core" is set to "yes" + And parameter "shareapi_internal_expire_after_n_days" of app "core" is set to "3" + And As an "user0" + When creating a share with + | path | welcome.txt | + | shareWith | user1 | + | shareType | 0 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Getting info of last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | expiration | +3 days | + + Scenario: Creating a new share with expiration date null, when default expiration is set + Given user "user0" exists + And user "user1" exists + And parameter "shareapi_default_internal_expire_date" of app "core" is set to "yes" + And parameter "shareapi_internal_expire_after_n_days" of app "core" is set to "3" + And As an "user0" + When creating a share with + | path | welcome.txt | + | shareWith | user1 | + | shareType | 0 | + | expireDate | null | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Getting info of last share + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And Share fields of last share match with + | expiration | +3 days | + Scenario: Creating a new public share, updating its password and getting its info Given user "user0" exists And As an "user0" diff --git a/build/integration/theming_features/theming.feature b/build/integration/theming_features/theming.feature new file mode 100644 index 00000000000..2ae5d4f75c3 --- /dev/null +++ b/build/integration/theming_features/theming.feature @@ -0,0 +1,131 @@ +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +Feature: theming + + Background: + Given user "user0" exists + + Scenario: themed stylesheets are available for users + Given As an "user0" + When sending "GET" with exact url to "/index.php/apps/theming/theme/default.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/light.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/dark.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/light-highcontrast.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/dark-highcontrast.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/opendyslexic.css" + Then the HTTP status code should be "200" + + Scenario: themed stylesheets are available for guests + Given As an "anonymous" + When sending "GET" with exact url to "/index.php/apps/theming/theme/default.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/light.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/dark.css" + Then the HTTP status code should be "200" + # Themes that can not be explicitly set by a guest could have been + # globally set too through "enforce_theme". + When sending "GET" with exact url to "/index.php/apps/theming/theme/light-highcontrast.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/dark-highcontrast.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/opendyslexic.css" + Then the HTTP status code should be "200" + + Scenario: themed stylesheets are available for disabled users + Given As an "admin" + And assure user "user0" is disabled + And As an "user0" + When sending "GET" with exact url to "/index.php/apps/theming/theme/default.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/light.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/dark.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/light-highcontrast.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/dark-highcontrast.css" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/theme/opendyslexic.css" + Then the HTTP status code should be "200" + + Scenario: themed images are available for users + Given Logging in using web as "admin" + And logged in admin uploads theming image for "background" from file "data/clouds.jpg" + And logged in admin uploads theming image for "logo" from file "data/coloured-pattern-non-square.png" + And logged in admin uploads theming image for "logoheader" from file "data/coloured-pattern-non-square.png" + And As an "user0" + When sending "GET" with exact url to "/index.php/apps/theming/image/background" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/image/logo" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/image/logoheader" + Then the HTTP status code should be "200" + + Scenario: themed images are available for guests + Given Logging in using web as "admin" + And logged in admin uploads theming image for "background" from file "data/clouds.jpg" + And logged in admin uploads theming image for "logo" from file "data/coloured-pattern-non-square.png" + And logged in admin uploads theming image for "logoheader" from file "data/coloured-pattern-non-square.png" + And As an "anonymous" + When sending "GET" with exact url to "/index.php/apps/theming/image/background" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/image/logo" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/image/logoheader" + Then the HTTP status code should be "200" + + Scenario: themed images are available for disabled users + Given Logging in using web as "admin" + And logged in admin uploads theming image for "background" from file "data/clouds.jpg" + And logged in admin uploads theming image for "logo" from file "data/coloured-pattern-non-square.png" + And logged in admin uploads theming image for "logoheader" from file "data/coloured-pattern-non-square.png" + And As an "admin" + And assure user "user0" is disabled + And As an "user0" + When sending "GET" with exact url to "/index.php/apps/theming/image/background" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/image/logo" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/image/logoheader" + Then the HTTP status code should be "200" + + Scenario: themed icons are available for users + Given As an "user0" + When sending "GET" with exact url to "/index.php/apps/theming/favicon" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/icon" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/favicon/dashboard" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/icon/dashboard" + Then the HTTP status code should be "200" + + Scenario: themed icons are available for guests + Given As an "anonymous" + When sending "GET" with exact url to "/index.php/apps/theming/favicon" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/icon" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/favicon/dashboard" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/icon/dashboard" + Then the HTTP status code should be "200" + + Scenario: themed icons are available for disabled users + Given As an "admin" + And assure user "user0" is disabled + And As an "user0" + When sending "GET" with exact url to "/index.php/apps/theming/favicon" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/icon" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/favicon/dashboard" + Then the HTTP status code should be "200" + When sending "GET" with exact url to "/index.php/apps/theming/icon/dashboard" + Then the HTTP status code should be "200" diff --git a/build/integration/videoverification_features/sharing-v1-video-verification.feature b/build/integration/videoverification_features/sharing-v1-video-verification.feature index cc4be425aab..0bd4ed4b0f2 100644 --- a/build/integration/videoverification_features/sharing-v1-video-verification.feature +++ b/build/integration/videoverification_features/sharing-v1-video-verification.feature @@ -1,4 +1,6 @@ @Talk +# SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later Feature: sharing Background: Given using api version "1" diff --git a/build/jsdocs9.tar.bz2.license b/build/jsdocs9.tar.bz2.license new file mode 100644 index 00000000000..f7804ddc385 --- /dev/null +++ b/build/jsdocs9.tar.bz2.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: 2015 ownCloud, Inc. +SPDX-License-Identifier: AGPL-3.0-only
\ No newline at end of file diff --git a/build/license.php b/build/license.php index 94ef4e4b02c..bb6351181c6 100644 --- a/build/license.php +++ b/build/license.php @@ -1,22 +1,9 @@ <?php + /** - * @author Thomas Müller - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @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-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ class Licenses { @@ -71,7 +58,7 @@ EOD; * */ EOD; - $this->licenseTextLegacy = str_replace('@YEAR@', date("Y"), $this->licenseTextLegacy); + $this->licenseTextLegacy = str_replace('@YEAR@', date('Y'), $this->licenseTextLegacy); } /** @@ -123,7 +110,7 @@ EOD; public function writeAuthorsFile() { ksort($this->authors); - $template = "Nextcloud is written by: + $template = 'Nextcloud is written by: @AUTHORS@ With help from many libraries and frameworks including: @@ -131,12 +118,12 @@ With help from many libraries and frameworks including: SabreDAV jQuery … -"; +'; $authors = implode(PHP_EOL, array_map(function ($author) { - return " - ".$author; + return ' - ' . $author; }, $this->authors)); $template = str_replace('@AUTHORS@', $authors, $template); - file_put_contents(__DIR__.'/../AUTHORS', $template); + file_put_contents(__DIR__ . '/../AUTHORS', $template); } public function handleFile($path, $gitRoot) { @@ -167,9 +154,9 @@ With help from many libraries and frameworks including: if ($isPhp) { if ($isStrict) { - $source = "<?php" . PHP_EOL . PHP_EOL . 'declare(strict_types=1);' . PHP_EOL . PHP_EOL . $license . PHP_EOL . $source; + $source = '<?php' . PHP_EOL . PHP_EOL . 'declare(strict_types=1);' . PHP_EOL . PHP_EOL . $license . PHP_EOL . $source; } else { - $source = "<?php" . PHP_EOL . $license . PHP_EOL . $source; + $source = '<?php' . PHP_EOL . $license . PHP_EOL . $source; } } else { $source = $license . PHP_EOL . PHP_EOL . $source; @@ -234,7 +221,7 @@ With help from many libraries and frameworks including: $index++; continue; } - + if (strpos($line, '<?php declare(strict_types') !== false) { $isStrict = true; array_splice($lines, $index, 1); @@ -276,7 +263,7 @@ With help from many libraries and frameworks including: private function getCopyrightNotices($path, $file) { $licenseHeaderCopyrightAtLines = trim(shell_exec("grep -ni 'copyright' $path | cut -d ':' -f 1")); $lineByLine = explode(PHP_EOL, $file); - + $copyrightNotice = []; if (trim($licenseHeaderCopyrightAtLines !== '')) { $copyrightNotice = array_map(function ($line) use ($lineByLine) { @@ -324,8 +311,8 @@ With help from many libraries and frameworks including: private function printFilesToCheck() { if (!empty($this->checkFiles)) { print "\n"; - print "For following files all lines changed since the Nextcloud fork." . PHP_EOL; - print "Please check if these files can be moved over to AGPLv3 or later" . PHP_EOL; + print 'For following files all lines changed since the Nextcloud fork.' . PHP_EOL; + print 'Please check if these files can be moved over to AGPLv3 or later' . PHP_EOL; print "\n"; foreach ($this->checkFiles as $file) { print $file . PHP_EOL; @@ -369,7 +356,7 @@ With help from many libraries and frameworks including: } $authors = $this->filterAuthors($authors); - + if ($gitRoot) { $authors = array_map([$this, 'checkCoreMailMap'], $authors); $authors = array_unique($authors); @@ -436,7 +423,7 @@ With help from many libraries and frameworks including: private function fixInvalidEmail($author) { preg_match('/<(.*)>/', $author, $mailMatch); if (count($mailMatch) === 2 && !filter_var($mailMatch[1], FILTER_VALIDATE_EMAIL)) { - $author = str_replace('<'.$mailMatch[1].'>', '"'.$mailMatch[1].'"', $author); + $author = str_replace('<' . $mailMatch[1] . '>', '"' . $mailMatch[1] . '"', $author); } return $author; } diff --git a/build/merge-font-noto-fix-merging-v20201206-phase3-76b29f8f8f9b.patch.license b/build/merge-font-noto-fix-merging-v20201206-phase3-76b29f8f8f9b.patch.license new file mode 100644 index 00000000000..b8f52265f1f --- /dev/null +++ b/build/merge-font-noto-fix-merging-v20201206-phase3-76b29f8f8f9b.patch.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors +SPDX-License-Identifier: AGPL-3.0-or-later
\ No newline at end of file diff --git a/build/merge-font-noto.sh b/build/merge-font-noto.sh index ee4831dac74..603f6dba9d3 100755 --- a/build/merge-font-noto.sh +++ b/build/merge-font-noto.sh @@ -1,21 +1,7 @@ #!/usr/bin/env bash -# @copyright Copyright (c) 2021, Daniel Calviño Sánchez (danxuliu@gmail.com) -# -# @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: 2021 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later # Helper script to merge several Noto fonts in a single TTF file. # diff --git a/build/npm-post-build.sh b/build/npm-post-build.sh new file mode 100755 index 00000000000..7f12728f14b --- /dev/null +++ b/build/npm-post-build.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +set -e + +# Build CSS files from SCSS +npm run sass +# Build icons +npm run sass:icons + +# Add licenses for source maps +if [ -d "dist" ]; then + for f in dist/*.js; do + # If license file and source map exists copy license for the source map + if [ -f "$f.license" ] && [ -f "$f.map" ]; then + # Remove existing link + [ -e "$f.map.license" ] || [ -L "$f.map.license" ] && rm "$f.map.license" + # Create a new link + ln -s "$(basename "$f.license")" "$f.map.license" + fi + done + echo "Copying licenses for sourcemaps done" +else + echo "This script needs to be executed from the root of the repository" + exit 1 +fi + diff --git a/build/openapi-checker.sh b/build/openapi-checker.sh index 00b2b7d7baa..9e4a4802b25 100755 --- a/build/openapi-checker.sh +++ b/build/openapi-checker.sh @@ -1,12 +1,28 @@ #!/usr/bin/env bash +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +specs=() for path in core apps/*; do if [ ! -f "$path/.noopenapi" ] && [[ "$(git check-ignore "$path")" != "$path" ]]; then composer exec generate-spec "$path" "$path/openapi.json" || exit 1 + if [[ "$(basename "$path")" != "core" ]]; then + if [ -f "$path/openapi-full.json" ]; then + specs+=("$path/openapi-full.json") + else + specs+=("$path/openapi.json") + fi; + fi; fi done -files="$(git diff --name-only)" +composer exec merge-specs -- \ + --core core/openapi-full.json \ + --merged openapi.json \ + "${specs[@]}" + +files="$(git ls-files --exclude-standard --modified --others)" changed=false for file in $files; do if [[ $file == *"openapi"*".json" ]]; then diff --git a/build/phpDocumentor.sh b/build/phpDocumentor.sh index fd8afba4641..452f756aecc 100755 --- a/build/phpDocumentor.sh +++ b/build/phpDocumentor.sh @@ -1,5 +1,8 @@ #!/bin/bash +# SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + wget https://phpdoc.org/phpDocumentor.phar mkdir -p api/ diff --git a/build/psalm-baseline-ocp.xml b/build/psalm-baseline-ocp.xml index 09110c58190..8500cf735be 100644 --- a/build/psalm-baseline-ocp.xml +++ b/build/psalm-baseline-ocp.xml @@ -1,98 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> -<files psalm-version="5.9.0@8b9ad1eb9e8b7d3101f949291da2b9f7767cd163"> - <file src="lib/private/legacy/OC_Template.php"> - <UndefinedClass> - <code>OC</code> - </UndefinedClass> - </file> - <file src="lib/public/AppFramework/ApiController.php"> - <NoInterfaceProperties> - <code><![CDATA[$this->request->server]]></code> - </NoInterfaceProperties> - </file> +<files psalm-version="5.26.1@d747f6500b38ac4f7dfc5edbcae6e4b637d7add0"> <file src="lib/public/AppFramework/App.php"> - <InternalMethod> - <code><![CDATA[new RouteConfig($this->container, $router, $routes)]]></code> - </InternalMethod> - <UndefinedClass> - <code>\OC</code> - </UndefinedClass> - </file> - <file src="lib/public/AppFramework/Db/Entity.php"> - <InvalidNullableReturnType> - <code>string</code> - </InvalidNullableReturnType> - <NullableReturnStatement> - <code>$column</code> - </NullableReturnStatement> - </file> - <file src="lib/public/AppFramework/Http/RedirectToDefaultAppResponse.php"> - <UndefinedClass> - <code>\OC</code> - </UndefinedClass> - </file> - <file src="lib/public/AppFramework/Http/Response.php"> - <UndefinedClass> - <code>\OC</code> - <code>\OC</code> - </UndefinedClass> - </file> - <file src="lib/public/Defaults.php"> - <UndefinedClass> - <code>\OC</code> - </UndefinedClass> - </file> - <file src="lib/public/Diagnostics/IQueryLogger.php"> - <LessSpecificImplementedReturnType> - <code>mixed</code> - </LessSpecificImplementedReturnType> - </file> - <file src="lib/public/EventDispatcher/GenericEvent.php"> - <MissingTemplateParam> - <code>ArrayAccess</code> - <code>IteratorAggregate</code> - </MissingTemplateParam> - </file> - <file src="lib/public/Files.php"> - <FalsableReturnStatement> - <code>\OC_App::getStorage($app)</code> - </FalsableReturnStatement> - <UndefinedClass> - <code>\OC</code> - </UndefinedClass> - </file> - <file src="lib/public/L10N/ILanguageIterator.php"> - <MissingTemplateParam> - <code>\Iterator</code> - </MissingTemplateParam> - </file> - <file src="lib/public/Template.php"> - <UndefinedFunction> - <code>\html_select_options($options, $selected, $params)</code> - <code>\human_file_size($bytes)</code> - <code>\image_path($app, $image)</code> - <code>\mimetype_icon($mimetype)</code> - <code>\preview_icon($path)</code> - <code>\publicPreview_icon($path, $token)</code> - <code>\relative_modified_date($timestamp, null, $dateOnly)</code> - </UndefinedFunction> - </file> - <file src="lib/public/Util.php"> <UndefinedClass> - <code>\OC</code> - <code>\OC</code> - <code>\OC</code> - <code>\OC</code> - <code>\OC</code> - <code>\OC</code> - <code>\OC</code> - <code>\OC</code> - <code>\OC</code> - <code>\OC</code> - <code>\OC</code> - <code>\OC</code> - <code>\OC</code> - <code>\OC</code> + <code><![CDATA[\OC]]></code> </UndefinedClass> </file> </files> diff --git a/build/psalm-baseline-security.xml b/build/psalm-baseline-security.xml new file mode 100644 index 00000000000..d9ab9c91076 --- /dev/null +++ b/build/psalm-baseline-security.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<files psalm-version="5.26.1@d747f6500b38ac4f7dfc5edbcae6e4b637d7add0"> + <file src="lib/public/DB/QueryBuilder/IQueryBuilder.php"> + <TaintedSql> + <code><![CDATA[$column]]></code> + </TaintedSql> + </file> +</files> diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index da3ff49f5f3..07df0637d57 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -1,99 +1,261 @@ <?xml version="1.0" encoding="UTF-8"?> -<files psalm-version="5.9.0@8b9ad1eb9e8b7d3101f949291da2b9f7767cd163"> - <file src="3rdparty/sabre/dav/lib/CalDAV/Calendar.php"> - <MoreSpecificImplementedParamType> - <code>$data</code> - </MoreSpecificImplementedParamType> - </file> - <file src="3rdparty/sabre/dav/lib/CalDAV/CalendarHome.php"> - <MoreSpecificImplementedParamType> - <code>$data</code> - </MoreSpecificImplementedParamType> - </file> - <file src="3rdparty/sabre/dav/lib/CalDAV/Principal/User.php"> - <MoreSpecificImplementedParamType> - <code>$data</code> - </MoreSpecificImplementedParamType> - </file> - <file src="3rdparty/sabre/dav/lib/CardDAV/AddressBook.php"> - <MoreSpecificImplementedParamType> - <code>$data</code> - </MoreSpecificImplementedParamType> - </file> - <file src="3rdparty/sabre/dav/lib/CardDAV/AddressBookHome.php"> - <InvalidPropertyAssignmentValue> - <code>$principalUri</code> - </InvalidPropertyAssignmentValue> - <MoreSpecificImplementedParamType> - <code>$data</code> - </MoreSpecificImplementedParamType> - </file> - <file src="3rdparty/sabre/dav/lib/CardDAV/Card.php"> - <MoreSpecificImplementedParamType> - <code>$cardData</code> - </MoreSpecificImplementedParamType> - </file> - <file src="3rdparty/sabre/dav/lib/DAVACL/AbstractPrincipalCollection.php"> - <LessSpecificImplementedReturnType> - <code>array</code> - </LessSpecificImplementedReturnType> - </file> - <file src="3rdparty/symfony/routing/Route.php"> - <MethodSignatureMustProvideReturnType> - <code>unserialize</code> - </MethodSignatureMustProvideReturnType> +<files psalm-version="5.26.1@d747f6500b38ac4f7dfc5edbcae6e4b637d7add0"> + <file src="apps/admin_audit/lib/AppInfo/Application.php"> + <DeprecatedClass> + <code><![CDATA[Share::class]]></code> + <code><![CDATA[Share::class]]></code> + <code><![CDATA[Share::class]]></code> + <code><![CDATA[Share::class]]></code> + </DeprecatedClass> + <DeprecatedConstant> + <code><![CDATA[ManagerEvent::EVENT_CREATE]]></code> + </DeprecatedConstant> + <DeprecatedMethod> + <code><![CDATA[Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', $trashActions, 'restore')]]></code> + <code><![CDATA[Util::connectHook('\OCP\Trashbin', 'preDelete', $trashActions, 'delete')]]></code> + <code><![CDATA[Util::connectHook('\OCP\Versions', 'delete', $versionsActions, 'delete')]]></code> + <code><![CDATA[Util::connectHook(Share::class, 'post_set_expiration_date', $shareActions, 'updateExpirationDate')]]></code> + <code><![CDATA[Util::connectHook(Share::class, 'post_update_password', $shareActions, 'updatePassword')]]></code> + <code><![CDATA[Util::connectHook(Share::class, 'post_update_permissions', $shareActions, 'updatePermissions')]]></code> + <code><![CDATA[Util::connectHook(Share::class, 'share_link_access', $shareActions, 'shareAccessed')]]></code> + </DeprecatedMethod> + </file> + <file src="apps/admin_audit/lib/AuditLogger.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/admin_audit/lib/BackgroundJobs/Rotate.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/cloud_federation_api/lib/Controller/RequestHandlerController.php"> + <DeprecatedMethod> + <code><![CDATA[Util::emitHook( + '\OCA\Files_Sharing\API\Server2Server', + 'preLoginNameUsedAsUserName', + ['uid' => &$uid] + )]]></code> + </DeprecatedMethod> + </file> + <file src="apps/comments/lib/Activity/Listener.php"> + <DeprecatedConstant> + <code><![CDATA[CommentsEvent::EVENT_ADD]]></code> + </DeprecatedConstant> + </file> + <file src="apps/comments/lib/Listener/CommentsEventListener.php"> + <DeprecatedConstant> + <code><![CDATA[CommentsEvent::EVENT_ADD]]></code> + <code><![CDATA[CommentsEvent::EVENT_DELETE]]></code> + <code><![CDATA[CommentsEvent::EVENT_PRE_UPDATE]]></code> + <code><![CDATA[CommentsEvent::EVENT_UPDATE]]></code> + </DeprecatedConstant> + </file> + <file src="apps/comments/lib/MaxAutoCompleteResultsInitialState.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> </file> <file src="apps/comments/lib/Notification/Listener.php"> - <LessSpecificReturnStatement> - <code>$uids</code> - </LessSpecificReturnStatement> - <MoreSpecificReturnType> - <code><![CDATA[list<string>]]></code> - </MoreSpecificReturnType> + <DeprecatedConstant> + <code><![CDATA[CommentsEvent::EVENT_DELETE]]></code> + <code><![CDATA[CommentsEvent::EVENT_PRE_UPDATE]]></code> + </DeprecatedConstant> + </file> + <file src="apps/comments/lib/Search/CommentsSearchProvider.php"> + <DeprecatedClass> + <code><![CDATA[Result]]></code> + </DeprecatedClass> + <DeprecatedProperty> + <code><![CDATA[$result->authorId]]></code> + <code><![CDATA[$result->authorId]]></code> + <code><![CDATA[$result->authorId]]></code> + <code><![CDATA[$result->name]]></code> + <code><![CDATA[$result->path]]></code> + </DeprecatedProperty> + </file> + <file src="apps/comments/lib/Search/LegacyProvider.php"> + <DeprecatedClass> + <code><![CDATA[Provider]]></code> + <code><![CDATA[new Result($query, + $comment, + $displayName, + $file->getPath() + )]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[Provider]]></code> + <code><![CDATA[getUserFolder]]></code> + </DeprecatedMethod> + </file> + <file src="apps/comments/lib/Search/Result.php"> + <DeprecatedClass> + <code><![CDATA[BaseResult]]></code> + <code><![CDATA[parent::__construct( + $comment->getId(), + $comment->getMessage() + /* @todo , [link to file] */ + )]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[parent::__construct( + $comment->getId(), + $comment->getMessage() + /* @todo , [link to file] */ + )]]></code> + </DeprecatedMethod> + <DeprecatedProperty> + <code><![CDATA[$this->authorId]]></code> + <code><![CDATA[$this->comment]]></code> + <code><![CDATA[$this->fileName]]></code> + <code><![CDATA[$this->path]]></code> + </DeprecatedProperty> + </file> + <file src="apps/dashboard/lib/Controller/DashboardApiController.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dashboard/lib/Service/DashboardService.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> </file> <file src="apps/dav/appinfo/v1/caldav.php"> + <DeprecatedMethod> + <code><![CDATA[exec]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getL10N]]></code> + <code><![CDATA[getL10NFactory]]></code> + </DeprecatedMethod> <UndefinedGlobalVariable> - <code>$baseuri</code> + <code><![CDATA[$baseuri]]></code> </UndefinedGlobalVariable> </file> <file src="apps/dav/appinfo/v1/carddav.php"> + <DeprecatedMethod> + <code><![CDATA[exec]]></code> + <code><![CDATA[getL10N]]></code> + <code><![CDATA[getL10NFactory]]></code> + </DeprecatedMethod> <UndefinedGlobalVariable> - <code>$baseuri</code> + <code><![CDATA[$baseuri]]></code> </UndefinedGlobalVariable> </file> <file src="apps/dav/appinfo/v1/publicwebdav.php"> + <DeprecatedClass> + <code><![CDATA[OC_Util::obEnd()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[OC_App::loadApps($RUNTIME_APPTYPES)]]></code> + <code><![CDATA[exec]]></code> + <code><![CDATA[getL10N]]></code> + </DeprecatedMethod> <InternalMethod> - <code>\OC\Files\Filesystem::logWarningWhenAddingStorageWrapper($previousLog)</code> - <code>\OC\Files\Filesystem::logWarningWhenAddingStorageWrapper(false)</code> + <code><![CDATA[Filesystem::logWarningWhenAddingStorageWrapper($previousLog)]]></code> + <code><![CDATA[Filesystem::logWarningWhenAddingStorageWrapper(false)]]></code> </InternalMethod> <UndefinedGlobalVariable> - <code>$baseuri</code> + <code><![CDATA[$baseuri]]></code> </UndefinedGlobalVariable> </file> <file src="apps/dav/appinfo/v1/webdav.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::obEnd()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[dispatch]]></code> + <code><![CDATA[exec]]></code> + <code><![CDATA[getL10N]]></code> + </DeprecatedMethod> <UndefinedGlobalVariable> - <code>$baseuri</code> + <code><![CDATA[$baseuri]]></code> </UndefinedGlobalVariable> </file> <file src="apps/dav/appinfo/v2/direct.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::obEnd()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[exec]]></code> + </DeprecatedMethod> <UndefinedGlobalVariable> - <code>$baseuri</code> + <code><![CDATA[$baseuri]]></code> </UndefinedGlobalVariable> </file> + <file src="apps/dav/appinfo/v2/publicremote.php"> + <DeprecatedClass> + <code><![CDATA[OC_Util::obEnd()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[OC_App::loadApps($RUNTIME_APPTYPES)]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/appinfo/v2/remote.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::obEnd()]]></code> + </DeprecatedClass> <UndefinedGlobalVariable> - <code>$baseuri</code> + <code><![CDATA[$baseuri]]></code> </UndefinedGlobalVariable> </file> <file src="apps/dav/lib/AppInfo/Application.php"> + <DeprecatedInterface> + <code><![CDATA[IAppContainer]]></code> + <code><![CDATA[IAppContainer]]></code> + <code><![CDATA[IAppContainer]]></code> + <code><![CDATA[IAppContainer]]></code> + <code><![CDATA[IAppContainer]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[getServer]]></code> + <code><![CDATA[getServer]]></code> + <code><![CDATA[getURLGenerator]]></code> + <code><![CDATA[getURLGenerator]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[register]]></code> + </DeprecatedMethod> <InvalidArgument> - <code>registerEventListener</code> + <code><![CDATA[registerEventListener]]></code> </InvalidArgument> </file> + <file src="apps/dav/lib/BackgroundJob/CleanupInvitationTokenJob.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/BackgroundJob/EventReminderJob.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/BackgroundJob/PruneOutdatedSyncTokensJob.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/BackgroundJob/RefreshWebcalJob.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/CalDAV/BirthdayService.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> <UndefinedMethod> - <code>setDateTime</code> - <code>setDateTime</code> + <code><![CDATA[setDateTime]]></code> + <code><![CDATA[setDateTime]]></code> </UndefinedMethod> <UndefinedPropertyFetch> <code><![CDATA[$existingBirthday->VEVENT->DTSTART]]></code> @@ -107,129 +269,188 @@ <code><![CDATA[$this->objectData['calendardata']]]></code> </NullableReturnStatement> <ParamNameMismatch> - <code>$calendarData</code> - <code>$calendarData</code> + <code><![CDATA[$calendarData]]></code> + <code><![CDATA[$calendarData]]></code> </ParamNameMismatch> </file> <file src="apps/dav/lib/CalDAV/CalDavBackend.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> <InvalidNullableReturnType> - <code>array</code> + <code><![CDATA[array]]></code> </InvalidNullableReturnType> <LessSpecificReturnStatement> - <code>Reader::read($objectData)</code> + <code><![CDATA[Reader::read($objectData)]]></code> </LessSpecificReturnStatement> <MoreSpecificImplementedParamType> - <code>$objectData</code> - <code>$uris</code> - <code>$uris</code> + <code><![CDATA[$objectData]]></code> + <code><![CDATA[$uris]]></code> + <code><![CDATA[$uris]]></code> </MoreSpecificImplementedParamType> <MoreSpecificReturnType> - <code>VCalendar</code> + <code><![CDATA[VCalendar]]></code> </MoreSpecificReturnType> <NullableReturnStatement> - <code>null</code> + <code><![CDATA[null]]></code> </NullableReturnStatement> </file> <file src="apps/dav/lib/CalDAV/CalendarHome.php"> + <DeprecatedMethod> + <code><![CDATA[getL10N]]></code> + </DeprecatedMethod> <InvalidNullableReturnType> - <code>INode</code> + <code><![CDATA[INode]]></code> </InvalidNullableReturnType> <LessSpecificImplementedReturnType> - <code>INode</code> + <code><![CDATA[INode]]></code> </LessSpecificImplementedReturnType> <NullableReturnStatement> <code><![CDATA[$calendarPlugin->getCalendarInCalendarHome($this->principalInfo['uri'], $calendarUri)]]></code> </NullableReturnStatement> <UndefinedInterfaceMethod> - <code>calendarSearch</code> + <code><![CDATA[calendarSearch]]></code> </UndefinedInterfaceMethod> </file> + <file src="apps/dav/lib/CalDAV/CalendarManager.php"> + <DeprecatedMethod> + <code><![CDATA[registerCalendar]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/CalDAV/CalendarRoot.php"> <ParamNameMismatch> - <code>$principal</code> + <code><![CDATA[$principal]]></code> </ParamNameMismatch> </file> + <file src="apps/dav/lib/CalDAV/ICSExportPlugin/ICSExportPlugin.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php"> + <DeprecatedMethod> + <code><![CDATA[getL10N]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/CalDAV/Outbox.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/CalDAV/Plugin.php"> <ImplementedReturnTypeMismatch> - <code>string|null</code> + <code><![CDATA[string|null]]></code> </ImplementedReturnTypeMismatch> </file> <file src="apps/dav/lib/CalDAV/Principal/Collection.php"> <ParamNameMismatch> - <code>$principalInfo</code> + <code><![CDATA[$principalInfo]]></code> </ParamNameMismatch> </file> <file src="apps/dav/lib/CalDAV/PublicCalendar.php"> <MoreSpecificImplementedParamType> - <code>$paths</code> + <code><![CDATA[$paths]]></code> </MoreSpecificImplementedParamType> </file> + <file src="apps/dav/lib/CalDAV/Publishing/PublishPlugin.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/CalDAV/Reminder/NotificationProvider/AbstractProvider.php"> <LessSpecificReturnStatement> <code><![CDATA[$vevent->DTEND]]></code> </LessSpecificReturnStatement> <UndefinedMethod> - <code>hasTime</code> - <code>isFloating</code> - <code>isFloating</code> + <code><![CDATA[hasTime]]></code> + <code><![CDATA[isFloating]]></code> + <code><![CDATA[isFloating]]></code> </UndefinedMethod> </file> <file src="apps/dav/lib/CalDAV/Reminder/NotificationProvider/EmailProvider.php"> <LessSpecificReturnStatement> - <code>$emailAddresses</code> + <code><![CDATA[$emailAddresses]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> <code><![CDATA[array<string, array{LANG?: string}>]]></code> </MoreSpecificReturnType> <UndefinedMethod> - <code>getDateTime</code> - <code>getDateTime</code> - <code>isFloating</code> + <code><![CDATA[getDateTime]]></code> + <code><![CDATA[getDateTime]]></code> + <code><![CDATA[isFloating]]></code> </UndefinedMethod> </file> + <file src="apps/dav/lib/CalDAV/Reminder/NotificationProvider/PushProvider.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/CalDAV/Reminder/NotificationProviderManager.php"> <UndefinedConstant> - <code>$provider::NOTIFICATION_TYPE</code> + <code><![CDATA[$provider::NOTIFICATION_TYPE]]></code> </UndefinedConstant> </file> <file src="apps/dav/lib/CalDAV/Reminder/Notifier.php"> <TypeDoesNotContainType> - <code>$diff === false</code> + <code><![CDATA[$diff === false]]></code> </TypeDoesNotContainType> </file> <file src="apps/dav/lib/CalDAV/Reminder/ReminderService.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> <LessSpecificReturnStatement> - <code>$vevents</code> - <code>VObject\Reader::read($calendarData, - VObject\Reader::OPTION_FORGIVING)</code> + <code><![CDATA[$vevents]]></code> + <code><![CDATA[VObject\Reader::read($calendarData, + VObject\Reader::OPTION_FORGIVING)]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>VObject\Component\VCalendar|null</code> - <code>VObject\Component\VEvent[]</code> + <code><![CDATA[VObject\Component\VCalendar|null]]></code> + <code><![CDATA[VObject\Component\VEvent[]]]></code> </MoreSpecificReturnType> <UndefinedMethod> - <code>getDateTime</code> - <code>getDateTime</code> + <code><![CDATA[getDateTime]]></code> + <code><![CDATA[getDateTime]]></code> </UndefinedMethod> <UndefinedPropertyFetch> <code><![CDATA[$valarm->parent->UID]]></code> </UndefinedPropertyFetch> </file> <file src="apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> <InvalidNullableReturnType> - <code>array</code> + <code><![CDATA[array]]></code> </InvalidNullableReturnType> <InvalidReturnStatement> - <code>$principals</code> + <code><![CDATA[$principals]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>string[]</code> + <code><![CDATA[string[]]]></code> </InvalidReturnType> <NullableReturnStatement> - <code>null</code> - <code>null</code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> </NullableReturnStatement> </file> + <file src="apps/dav/lib/CalDAV/RetentionService.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/CalDAV/Schedule/IMipPlugin.php"> <RedundantCast> <code><![CDATA[(string)$iTipMessage->recipientName]]></code> @@ -240,12 +461,18 @@ </RedundantCondition> </file> <file src="apps/dav/lib/CalDAV/Schedule/IMipService.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> <UndefinedMethod> - <code>getNormalizedValue</code> - <code>getNormalizedValue</code> + <code><![CDATA[getNormalizedValue]]></code> + <code><![CDATA[getNormalizedValue]]></code> </UndefinedMethod> </file> <file src="apps/dav/lib/CalDAV/Schedule/Plugin.php"> + <DeprecatedMethod> + <code><![CDATA[getPropertiesForPath]]></code> + </DeprecatedMethod> <InvalidArgument> <code><![CDATA[[$aclPlugin, 'propFind']]]></code> <code><![CDATA[[$aclPlugin, 'propFind']]]></code> @@ -254,20 +481,22 @@ <code><![CDATA[$vevent->DTEND]]></code> </LessSpecificReturnStatement> <UndefinedInterfaceMethod> - <code>get</code> - <code>getChildren</code> + <code><![CDATA[getChildren]]></code> </UndefinedInterfaceMethod> <UndefinedMethod> - <code>getDateTime</code> - <code>hasTime</code> - <code>isFloating</code> - <code>isFloating</code> - <code>principalSearch</code> + <code><![CDATA[getDateTime]]></code> + <code><![CDATA[hasTime]]></code> + <code><![CDATA[isFloating]]></code> + <code><![CDATA[isFloating]]></code> + <code><![CDATA[principalSearch]]></code> </UndefinedMethod> </file> <file src="apps/dav/lib/CalDAV/Search/SearchPlugin.php"> + <DeprecatedMethod> + <code><![CDATA[getPropertiesForPath]]></code> + </DeprecatedMethod> <InvalidNullableReturnType> - <code>bool</code> + <code><![CDATA[bool]]></code> </InvalidNullableReturnType> </file> <file src="apps/dav/lib/CalDAV/Search/Xml/Filter/ParamFilter.php"> @@ -278,7 +507,7 @@ ]]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>string</code> + <code><![CDATA[string]]></code> </InvalidReturnType> </file> <file src="apps/dav/lib/CalDAV/Search/Xml/Request/CalendarSearchReport.php"> @@ -293,7 +522,7 @@ </file> <file src="apps/dav/lib/CalDAV/WebcalCaching/RefreshWebcalService.php"> <InvalidArgument> - <code>$webcalData</code> + <code><![CDATA[$webcalData]]></code> </InvalidArgument> </file> <file src="apps/dav/lib/CardDAV/AddressBookImpl.php"> @@ -302,143 +531,187 @@ <code><![CDATA[$this->getKey()]]></code> </InvalidArgument> <LessSpecificReturnStatement> - <code>Reader::read($cardData)</code> + <code><![CDATA[Reader::read($cardData)]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>VCard</code> + <code><![CDATA[VCard]]></code> </MoreSpecificReturnType> </file> <file src="apps/dav/lib/CardDAV/AddressBookRoot.php"> <ParamNameMismatch> - <code>$principal</code> + <code><![CDATA[$principal]]></code> </ParamNameMismatch> </file> <file src="apps/dav/lib/CardDAV/CardDavBackend.php"> <FalsableReturnStatement> - <code>false</code> + <code><![CDATA[false]]></code> </FalsableReturnStatement> <LessSpecificReturnStatement> - <code>Reader::read($cardData)</code> + <code><![CDATA[Reader::read($cardData)]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>VCard</code> + <code><![CDATA[VCard]]></code> </MoreSpecificReturnType> <TypeDoesNotContainType> <code><![CDATA[$addressBooks[$row['id']][$readOnlyPropertyName] === 0]]></code> </TypeDoesNotContainType> </file> + <file src="apps/dav/lib/CardDAV/Converter.php"> + <DeprecatedConstant> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + </DeprecatedConstant> + </file> <file src="apps/dav/lib/CardDAV/MultiGetExportPlugin.php"> <InvalidNullableReturnType> - <code>bool</code> + <code><![CDATA[bool]]></code> </InvalidNullableReturnType> </file> - <file src="apps/dav/lib/CardDAV/PhotoCache.php"> - <LessSpecificReturnStatement> - <code><![CDATA[[ - 'Content-Type' => $type, - 'body' => $val - ]]]></code> - </LessSpecificReturnStatement> - <MoreSpecificReturnType> - <code>false|array{body: string, Content-Type: string}</code> - </MoreSpecificReturnType> - </file> <file src="apps/dav/lib/CardDAV/Plugin.php"> <ImplementedReturnTypeMismatch> - <code>string|null</code> + <code><![CDATA[string|null]]></code> </ImplementedReturnTypeMismatch> </file> + <file src="apps/dav/lib/CardDAV/SystemAddressbook.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/CardDAV/UserAddressBooks.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getL10N]]></code> + </DeprecatedMethod> <InvalidArgument> <code><![CDATA[$this->principalUri]]></code> <code><![CDATA[$this->principalUri]]></code> </InvalidArgument> </file> - <file src="apps/dav/lib/CardDAV/Xml/Groups.php"> - <InvalidPropertyAssignmentValue> - <code>$groups</code> - </InvalidPropertyAssignmentValue> + <file src="apps/dav/lib/Command/CreateCalendar.php"> + <DeprecatedMethod> + <code><![CDATA[getL10NFactory]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Command/SendEventReminders.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Command/SyncBirthdayCalendar.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Command/SyncSystemAddressBook.php"> + <DeprecatedMethod> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> </file> <file src="apps/dav/lib/Comments/CommentsPlugin.php"> + <DeprecatedMethod> + <code><![CDATA[getPropertiesForPath]]></code> + </DeprecatedMethod> <UndefinedFunction> - <code>\Sabre\HTTP\toDate($value)</code> + <code><![CDATA[\Sabre\HTTP\toDate($value)]]></code> </UndefinedFunction> </file> + <file src="apps/dav/lib/Comments/RootCollection.php"> + <DeprecatedConstant> + <code><![CDATA[CommentsEntityEvent::EVENT_ENTITY]]></code> + </DeprecatedConstant> + <DeprecatedMethod> + <code><![CDATA[dispatch]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/Connector/Sabre/AnonymousOptionsPlugin.php"> <InvalidNullableReturnType> - <code>bool</code> + <code><![CDATA[bool]]></code> </InvalidNullableReturnType> </file> <file src="apps/dav/lib/Connector/Sabre/Auth.php"> <LessSpecificReturnStatement> - <code>$data</code> + <code><![CDATA[$data]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>array{bool, string}</code> + <code><![CDATA[array{bool, string}]]></code> </MoreSpecificReturnType> </file> <file src="apps/dav/lib/Connector/Sabre/BearerAuth.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($userId)]]></code> + <code><![CDATA[\OC_Util::setupFS()]]></code> + </DeprecatedClass> <UndefinedInterfaceMethod> - <code>tryTokenLogin</code> + <code><![CDATA[tryTokenLogin]]></code> </UndefinedInterfaceMethod> </file> <file src="apps/dav/lib/Connector/Sabre/Directory.php"> <InvalidPropertyAssignmentValue> - <code>$nodes</code> + <code><![CDATA[$nodes]]></code> </InvalidPropertyAssignmentValue> <InvalidReturnStatement> <code><![CDATA[$this->dirContent]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>\Sabre\DAV\INode[]</code> + <code><![CDATA[\Sabre\DAV\INode[]]]></code> </InvalidReturnType> <LessSpecificReturnStatement> <code><![CDATA[$this->node]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>Folder</code> + <code><![CDATA[Folder]]></code> </MoreSpecificReturnType> <NullArgument> - <code>null</code> - <code>null</code> - <code>null</code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> </NullArgument> <ParamNameMismatch> - <code>$fullSourcePath</code> + <code><![CDATA[$fullSourcePath]]></code> </ParamNameMismatch> </file> <file src="apps/dav/lib/Connector/Sabre/File.php"> + <DeprecatedClass> + <code><![CDATA[Files::streamCopy($data, $target, true)]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[Files::streamCopy($data, $target, true)]]></code> + </DeprecatedMethod> <LessSpecificReturnStatement> <code><![CDATA[$this->node]]></code> </LessSpecificReturnStatement> - <MoreSpecificImplementedParamType> - <code>$data</code> - </MoreSpecificImplementedParamType> <MoreSpecificReturnType> - <code>\OCP\Files\File</code> + <code><![CDATA[\OCP\Files\File]]></code> </MoreSpecificReturnType> </file> <file src="apps/dav/lib/Connector/Sabre/FilesReportPlugin.php"> - <InvalidArgument> - <code>0</code> - </InvalidArgument> <InvalidNullableReturnType> - <code>bool</code> + <code><![CDATA[bool]]></code> </InvalidNullableReturnType> - <TooManyArguments> - <code><![CDATA[new PreconditionFailed('Cannot filter by non-existing tag', 0, $e)]]></code> - </TooManyArguments> <UndefinedClass> - <code>\OCA\Circles\Api\v1\Circles</code> + <code><![CDATA[Circles]]></code> </UndefinedClass> <UndefinedInterfaceMethod> - <code>getPath</code> + <code><![CDATA[getPath]]></code> </UndefinedInterfaceMethod> </file> + <file src="apps/dav/lib/Connector/Sabre/MaintenancePlugin.php"> + <DeprecatedMethod> + <code><![CDATA[getL10N]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/Connector/Sabre/Node.php"> <InvalidNullableReturnType> - <code>int</code> - <code>integer</code> + <code><![CDATA[int]]></code> + <code><![CDATA[integer]]></code> </InvalidNullableReturnType> <NullableReturnStatement> <code><![CDATA[$this->info->getId()]]></code> @@ -447,41 +720,42 @@ </file> <file src="apps/dav/lib/Connector/Sabre/Principal.php"> <InvalidNullableReturnType> - <code>array</code> + <code><![CDATA[array]]></code> </InvalidNullableReturnType> <InvalidReturnStatement> - <code>$principals</code> + <code><![CDATA[$principals]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>string[]</code> + <code><![CDATA[string[]]]></code> </InvalidReturnType> <InvalidScalarArgument> - <code>$results</code> + <code><![CDATA[$results]]></code> </InvalidScalarArgument> <NullableReturnStatement> <code><![CDATA[$this->circleToPrincipal($decodedName) ?: $this->circleToPrincipal($name)]]></code> - <code>null</code> - <code>null</code> - <code>null</code> - <code>null</code> - <code>null</code> - <code>null</code> - <code>null</code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> </NullableReturnStatement> <UndefinedClass> - <code>\OCA\Circles\Api\v1\Circles</code> - <code>\OCA\Circles\Api\v1\Circles</code> + <code><![CDATA[Circles]]></code> + <code><![CDATA[Circles]]></code> </UndefinedClass> </file> <file src="apps/dav/lib/Connector/Sabre/ServerFactory.php"> - <TooManyArguments> - <code>new \OCA\DAV\Connector\Sabre\QuotaPlugin($view, true)</code> - </TooManyArguments> + <DeprecatedMethod> + <code><![CDATA[getL10NFactory]]></code> + <code><![CDATA[getUserFolder]]></code> + </DeprecatedMethod> </file> <file src="apps/dav/lib/Connector/Sabre/ShareTypeList.php"> <InvalidArgument> - <code>$shareType</code> + <code><![CDATA[$shareType]]></code> </InvalidArgument> </file> <file src="apps/dav/lib/Connector/Sabre/ShareeList.php"> @@ -491,52 +765,67 @@ </file> <file src="apps/dav/lib/Connector/Sabre/TagsPlugin.php"> <NullableReturnStatement> - <code>null</code> + <code><![CDATA[null]]></code> </NullableReturnStatement> <UndefinedInterfaceMethod> - <code>getId</code> + <code><![CDATA[getId]]></code> </UndefinedInterfaceMethod> </file> + <file src="apps/dav/lib/Controller/BirthdayCalendarController.php"> + <DeprecatedMethod> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/Controller/InvitationResponseController.php"> <UndefinedPropertyAssignment> <code><![CDATA[$vEvent->DTSTAMP]]></code> </UndefinedPropertyAssignment> </file> <file src="apps/dav/lib/DAV/CustomPropertiesBackend.php"> + <DeprecatedMethod> + <code><![CDATA[closeCursor]]></code> + <code><![CDATA[closeCursor]]></code> + </DeprecatedMethod> <InvalidArgument> - <code>$whereValues</code> + <code><![CDATA[$whereValues]]></code> </InvalidArgument> </file> <file src="apps/dav/lib/DAV/GroupPrincipalBackend.php"> <InvalidNullableReturnType> - <code>array</code> - <code>string</code> + <code><![CDATA[array]]></code> + <code><![CDATA[string]]></code> </InvalidNullableReturnType> <InvalidReturnStatement> - <code>$principals</code> + <code><![CDATA[$principals]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>string[]</code> + <code><![CDATA[string[]]]></code> </InvalidReturnType> <MoreSpecificImplementedParamType> - <code>$members</code> + <code><![CDATA[$members]]></code> </MoreSpecificImplementedParamType> <NullableReturnStatement> - <code>null</code> - <code>null</code> - <code>null</code> - <code>null</code> - <code>null</code> - <code>null</code> - <code>null</code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> </NullableReturnStatement> </file> + <file src="apps/dav/lib/DAV/Sharing/Plugin.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/DAV/SystemPrincipalBackend.php"> <InvalidNullableReturnType> - <code>array</code> + <code><![CDATA[array]]></code> </InvalidNullableReturnType> <NullableReturnStatement> - <code>null</code> + <code><![CDATA[null]]></code> </NullableReturnStatement> </file> <file src="apps/dav/lib/Direct/Server.php"> @@ -546,13 +835,13 @@ </file> <file src="apps/dav/lib/Files/FileSearchBackend.php"> <InvalidReturnStatement> - <code>$value</code> + <code><![CDATA[$value]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>?string</code> + <code><![CDATA[?string]]></code> </InvalidReturnType> <ParamNameMismatch> - <code>$search</code> + <code><![CDATA[$search]]></code> </ParamNameMismatch> <RedundantCondition> <code><![CDATA[$date->getTimestamp() !== false]]></code> @@ -567,25 +856,101 @@ <code><![CDATA[$this->backend->getArbiterPath()]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>bool</code> + <code><![CDATA[bool]]></code> </InvalidReturnType> </file> - <file src="apps/dav/lib/HookManager.php"> - <InvalidPropertyAssignmentValue> - <code><![CDATA[$this->usersToDelete]]></code> - <code><![CDATA[$this->usersToDelete]]></code> - </InvalidPropertyAssignmentValue> + <file src="apps/dav/lib/Files/RootCollection.php"> + <DeprecatedMethod> + <code><![CDATA[getUserFolder]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Migration/BuildCalendarSearchIndex.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> </file> <file src="apps/dav/lib/Migration/BuildCalendarSearchIndexBackgroundJob.php"> <ParamNameMismatch> - <code>$arguments</code> + <code><![CDATA[$arguments]]></code> </ParamNameMismatch> </file> + <file src="apps/dav/lib/Migration/BuildSocialSearchIndex.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/Migration/BuildSocialSearchIndexBackgroundJob.php"> <ParamNameMismatch> - <code>$arguments</code> + <code><![CDATA[$arguments]]></code> </ParamNameMismatch> </file> + <file src="apps/dav/lib/Migration/ChunkCleanup.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Migration/RefreshWebcalJobRegistrar.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Migration/RegenerateBirthdayCalendars.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Migration/RegisterBuildReminderIndexBackgroundJob.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Migration/RemoveDeletedUsersCalendarSubscriptions.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Migration/Version1004Date20170825134824.php"> + <DeprecatedMethod> + <code><![CDATA[changeColumn]]></code> + <code><![CDATA[changeColumn]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Migration/Version1008Date20181105104826.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Migration/Version1008Date20181105110300.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Migration/Version1025Date20240308063933.php"> + <DeprecatedMethod> + <code><![CDATA[fetchColumn]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Migration/Version1027Date20230504122946.php"> + <DeprecatedMethod> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/RootCollection.php"> + <DeprecatedMethod> + <code><![CDATA[getL10N]]></code> + <code><![CDATA[getL10NFactory]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/Search/ContactsSearchProvider.php"> <InvalidOperand> <code><![CDATA[$query->getCursor()]]></code> @@ -608,14 +973,14 @@ <code><![CDATA[$this->l10n->l('date', $startDateTime, ['width' => 'medium'])]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>string</code> + <code><![CDATA[string]]></code> </InvalidReturnType> <UndefinedMethod> - <code>getDateTime</code> - <code>getDateTime</code> - <code>hasTime</code> - <code>isFloating</code> - <code>isFloating</code> + <code><![CDATA[getDateTime]]></code> + <code><![CDATA[getDateTime]]></code> + <code><![CDATA[hasTime]]></code> + <code><![CDATA[isFloating]]></code> + <code><![CDATA[isFloating]]></code> </UndefinedMethod> </file> <file src="apps/dav/lib/Search/TasksSearchProvider.php"> @@ -623,52 +988,82 @@ <code><![CDATA[$query->getCursor()]]></code> </InvalidOperand> <UndefinedMethod> - <code>getDateTime</code> - <code>getDateTime</code> - <code>hasTime</code> + <code><![CDATA[getDateTime]]></code> + <code><![CDATA[getDateTime]]></code> + <code><![CDATA[hasTime]]></code> </UndefinedMethod> </file> + <file src="apps/dav/lib/Server.php"> + <DeprecatedMethod> + <code><![CDATA[dispatch]]></code> + <code><![CDATA[dispatch]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getL10N]]></code> + <code><![CDATA[getL10N]]></code> + <code><![CDATA[getUserFolder]]></code> + <code><![CDATA[getUserFolder]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/Settings/CalDAVSettings.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/dav/lib/SetupChecks/NeedsSystemAddressBookSync.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/SystemTag/SystemTagsObjectMappingCollection.php"> <ParamNameMismatch> - <code>$tagId</code> - <code>$tagName</code> + <code><![CDATA[$tagId]]></code> + <code><![CDATA[$tagName]]></code> </ParamNameMismatch> </file> <file src="apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php"> <ParamNameMismatch> - <code>$objectName</code> + <code><![CDATA[$objectName]]></code> </ParamNameMismatch> </file> + <file src="apps/dav/lib/SystemTag/SystemTagsRelationsCollection.php"> + <DeprecatedConstant> + <code><![CDATA[SystemTagsEntityEvent::EVENT_ENTITY]]></code> + </DeprecatedConstant> + <DeprecatedMethod> + <code><![CDATA[dispatch]]></code> + </DeprecatedMethod> + </file> <file src="apps/dav/lib/Traits/PrincipalProxyTrait.php"> <MoreSpecificImplementedParamType> - <code>$members</code> + <code><![CDATA[$members]]></code> </MoreSpecificImplementedParamType> </file> <file src="apps/dav/lib/Upload/AssemblyStream.php"> <FalsableReturnStatement> - <code>false</code> + <code><![CDATA[false]]></code> </FalsableReturnStatement> <InvalidPropertyAssignmentValue> <code><![CDATA[$this->currentStream]]></code> </InvalidPropertyAssignmentValue> <InvalidReturnStatement> - <code>$context</code> + <code><![CDATA[$context]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>array</code> + <code><![CDATA[array]]></code> </InvalidReturnType> <RedundantFunctionCall> - <code>array_values</code> + <code><![CDATA[array_values]]></code> </RedundantFunctionCall> </file> <file src="apps/dav/lib/Upload/ChunkingV2Plugin.php"> <UndefinedInterfaceMethod> - <code>getId</code> - <code>getId</code> - <code>getId</code> - <code>getInternalPath</code> - <code>getNode</code> - <code>getSize</code> + <code><![CDATA[getId]]></code> + <code><![CDATA[getId]]></code> + <code><![CDATA[getId]]></code> + <code><![CDATA[getInternalPath]]></code> + <code><![CDATA[getNode]]></code> + <code><![CDATA[getSize]]></code> </UndefinedInterfaceMethod> </file> <file src="apps/dav/lib/UserMigration/ContactsMigrator.php"> @@ -681,109 +1076,234 @@ ]]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>array{name: string, displayName: string, description: ?string, vCards: VCard[]}</code> + <code><![CDATA[array{name: string, displayName: string, description: ?string, vCards: VCard[]}]]></code> </MoreSpecificReturnType> </file> + <file src="apps/encryption/lib/Command/DisableMasterKey.php"> + <DeprecatedMethod> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/encryption/lib/Command/DropLegacyFileKey.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($uid)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> + <file src="apps/encryption/lib/Command/EnableMasterKey.php"> + <DeprecatedMethod> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/encryption/lib/Command/FixEncryptedVersion.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($uid)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> <file src="apps/encryption/lib/Command/FixKeyLocation.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($user->getUID())]]></code> + </DeprecatedClass> <MoreSpecificReturnType> <code><![CDATA[\Generator<File>]]></code> </MoreSpecificReturnType> </file> + <file src="apps/encryption/lib/Command/ScanLegacyFormat.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($uid)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> <file src="apps/encryption/lib/Crypto/Crypt.php"> + <DeprecatedMethod> + <code><![CDATA[opensslSeal]]></code> + </DeprecatedMethod> <TypeDoesNotContainType> <code><![CDATA[get_class($res) === 'OpenSSLAsymmetricKey']]></code> </TypeDoesNotContainType> </file> + <file src="apps/encryption/lib/Crypto/EncryptAll.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($uid)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> <file src="apps/encryption/lib/Crypto/Encryption.php"> <ImplementedParamTypeMismatch> - <code>$position</code> + <code><![CDATA[$position]]></code> </ImplementedParamTypeMismatch> </file> <file src="apps/encryption/lib/KeyManager.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> <InvalidThrow> - <code>throw $exception;</code> + <code><![CDATA[throw $exception;]]></code> </InvalidThrow> </file> - <file src="apps/encryption/lib/Session.php"> - <TooManyArguments> - <code><![CDATA[new Exceptions\PrivateKeyMissingException('please try to log-out and log-in again', 0)]]></code> - </TooManyArguments> + <file src="apps/encryption/lib/Migration/SetMasterKeyStatus.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/encryption/lib/Recovery.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/encryption/lib/Settings/Admin.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/encryption/lib/Settings/Personal.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> </file> <file src="apps/encryption/lib/Util.php"> - <LessSpecificReturnStatement> - <code><![CDATA[$this->files->getMount($path)->getStorage()]]></code> - </LessSpecificReturnStatement> - <MoreSpecificReturnType> - <code>\OC\Files\Storage\Storage|null</code> - </MoreSpecificReturnType> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/federatedfilesharing/lib/AddressHandler.php"> + <DeprecatedMethod> + <code><![CDATA[Util::emitHook( + '\OCA\Files_Sharing\API\Server2Server', + 'preLoginNameUsedAsUserName', + ['uid' => &$user1] + )]]></code> + <code><![CDATA[Util::emitHook( + '\OCA\Files_Sharing\API\Server2Server', + 'preLoginNameUsedAsUserName', + ['uid' => &$user2] + )]]></code> + </DeprecatedMethod> + </file> + <file src="apps/federatedfilesharing/lib/AppInfo/Application.php"> + <DeprecatedInterface> + <code><![CDATA[IAppContainer]]></code> + </DeprecatedInterface> </file> <file src="apps/federatedfilesharing/lib/Controller/RequestHandlerController.php"> <InvalidArgument> - <code>$id</code> - <code>$id</code> - <code>$id</code> - <code>$id</code> - <code>$id</code> - <code>$id</code> - <code>$remoteId</code> + <code><![CDATA[$id]]></code> + <code><![CDATA[$id]]></code> + <code><![CDATA[$id]]></code> + <code><![CDATA[$id]]></code> + <code><![CDATA[$id]]></code> + <code><![CDATA[$id]]></code> + <code><![CDATA[$remoteId]]></code> </InvalidArgument> </file> <file src="apps/federatedfilesharing/lib/FederatedShareProvider.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> <InvalidArgument> - <code>$shareId</code> - <code>$shareId</code> - <code>$shareId</code> - <code>$shareId</code> + <code><![CDATA[$shareId]]></code> + <code><![CDATA[$shareId]]></code> + <code><![CDATA[$shareId]]></code> + <code><![CDATA[$shareId]]></code> <code><![CDATA[(int)$data['id']]]></code> </InvalidArgument> </file> + <file src="apps/federatedfilesharing/lib/Migration/Version1011Date20201120125158.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[getName]]></code> + </DeprecatedMethod> + </file> <file src="apps/federatedfilesharing/lib/Notifications.php"> + <DeprecatedMethod> + <code><![CDATA[sendNotification]]></code> + <code><![CDATA[sendNotification]]></code> + <code><![CDATA[sendNotification]]></code> + <code><![CDATA[sendShare]]></code> + </DeprecatedMethod> <InvalidReturnType> - <code>bool</code> - <code>bool</code> - <code>bool</code> + <code><![CDATA[bool]]></code> + <code><![CDATA[bool]]></code> + <code><![CDATA[bool]]></code> </InvalidReturnType> </file> <file src="apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($shareWith)]]></code> + <code><![CDATA[\OC_Util::setupFS($user)]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[Util::emitHook( + '\OCA\Files_Sharing\API\Server2Server', + 'preLoginNameUsedAsUserName', + ['uid' => &$shareWith] + )]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[lastInsertId]]></code> + <code><![CDATA[sendNotification]]></code> + <code><![CDATA[sendNotification]]></code> + </DeprecatedMethod> <InvalidArgument> - <code>$id</code> - <code>$id</code> - <code>$id</code> - <code>$id</code> + <code><![CDATA[$id]]></code> + <code><![CDATA[$id]]></code> + <code><![CDATA[$id]]></code> + <code><![CDATA[$id]]></code> </InvalidArgument> <InvalidReturnStatement> - <code>$shareId</code> + <code><![CDATA[$shareId]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>string</code> + <code><![CDATA[string]]></code> </InvalidReturnType> - <InvalidScalarArgument> - <code><![CDATA[(int)$share['id']]]></code> - </InvalidScalarArgument> </file> <file src="apps/federation/lib/DbHandler.php"> <LessSpecificReturnStatement> - <code>$result</code> + <code><![CDATA[$result]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> <code><![CDATA[list<array{id: int, url: string, url_hash: string, shared_secret: ?string, status: int, sync_token: ?string}>]]></code> </MoreSpecificReturnType> </file> - <file src="apps/files/ajax/download.php"> - <InvalidArgument> - <code>$files_list</code> - </InvalidArgument> - </file> <file src="apps/files/lib/Activity/Provider.php"> <FalsableReturnStatement> <code><![CDATA[$this->fileEncrypted[$fileId]]]></code> </FalsableReturnStatement> <LessSpecificReturnStatement> - <code>$folder</code> + <code><![CDATA[$folder]]></code> <code><![CDATA[$this->fileEncrypted[$fileId]]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>Folder</code> + <code><![CDATA[Folder]]></code> </MoreSpecificReturnType> <TypeDoesNotContainType> <code><![CDATA[$this->fileIsEncrypted]]></code> @@ -802,55 +1322,126 @@ <code><![CDATA[$this->fileIsEncrypted]]></code> </TypeDoesNotContainType> </file> + <file src="apps/files/lib/AppInfo/Application.php"> + <DeprecatedInterface> + <code><![CDATA[$server]]></code> + <code><![CDATA[$server]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[Util::connectHook('\OCP\Config', 'js', '\OCA\Files\App', 'extendJsConfig')]]></code> + <code><![CDATA[getUserFolder]]></code> + <code><![CDATA[getUserFolder]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files/lib/BackgroundJob/ScanFiles.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files/lib/Command/RepairTree.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files/lib/Command/Scan.php"> + <DeprecatedMethod> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + </DeprecatedMethod> + </file> <file src="apps/files/lib/Command/ScanAppData.php"> + <DeprecatedMethod> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + </DeprecatedMethod> <NullArgument> - <code>null</code> - <code>null</code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> </NullArgument> </file> <file src="apps/files/lib/Controller/DirectEditingController.php"> <InvalidArgument> - <code>$templateId</code> + <code><![CDATA[$templateId]]></code> </InvalidArgument> <UndefinedInterfaceMethod> - <code>getTemplates</code> - <code>open</code> + <code><![CDATA[getTemplates]]></code> + <code><![CDATA[open]]></code> </UndefinedInterfaceMethod> </file> <file src="apps/files/lib/Helper.php"> <UndefinedInterfaceMethod> - <code>$file</code> - <code>$i</code> - <code>$i</code> - <code>$i</code> - <code>$i</code> - <code>$i</code> - <code>$i</code> - <code>$i</code> - <code>$i</code> - <code>$i</code> - <code>$i</code> - <code>$i</code> - <code>$i</code> + <code><![CDATA[$i]]></code> + <code><![CDATA[$i]]></code> + <code><![CDATA[$i]]></code> + <code><![CDATA[$i]]></code> </UndefinedInterfaceMethod> </file> + <file src="apps/files/lib/Migration/Version2003Date20241021095629.php"> + <DeprecatedMethod> + <code><![CDATA[deleteAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/files/lib/Service/OwnershipTransferService.php"> - <TypeDoesNotContainType> - <code>empty($encryptedFiles)</code> - </TypeDoesNotContainType> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($destinationUser->getUID())]]></code> + <code><![CDATA[\OC_Util::setupFS($destinationUser->getUID())]]></code> + <code><![CDATA[\OC_Util::setupFS($sourceUser->getUID())]]></code> + </DeprecatedClass> <UndefinedInterfaceMethod> - <code>isReadyForUser</code> + <code><![CDATA[isReadyForUser]]></code> </UndefinedInterfaceMethod> </file> + <file src="apps/files_external/ajax/applicable.php"> + <DeprecatedMethod> + <code><![CDATA[\OC_JSON::callCheck()]]></code> + <code><![CDATA[\OC_JSON::checkAdminUser()]]></code> + <code><![CDATA[\OC_JSON::checkAppEnabled('files_external')]]></code> + <code><![CDATA[\OC_JSON::success($results)]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_external/ajax/oauth2.php"> + <DeprecatedMethod> + <code><![CDATA[\OC_JSON::callCheck()]]></code> + <code><![CDATA[\OC_JSON::checkAppEnabled('files_external')]]></code> + <code><![CDATA[\OC_JSON::checkLoggedIn()]]></code> + <code><![CDATA[getL10N]]></code> + </DeprecatedMethod> + </file> <file src="apps/files_external/appinfo/routes.php"> <InvalidScope> - <code>$this</code> + <code><![CDATA[$this]]></code> </InvalidScope> </file> + <file src="apps/files_external/lib/Command/Notify.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::normalizeUnicode($parent)]]></code> + <code><![CDATA[\OC_Util::normalizeUnicode($path)]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_external/lib/Command/Scan.php"> + <DeprecatedMethod> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + </DeprecatedMethod> + </file> <file src="apps/files_external/lib/Controller/StoragesController.php"> <RedundantCast> <code><![CDATA[(int)$e->getCode()]]></code> - <code>(int)$status</code> + <code><![CDATA[(int)$status]]></code> </RedundantCast> </file> <file src="apps/files_external/lib/Lib/Backend/Backend.php"> @@ -863,7 +1454,7 @@ </file> <file src="apps/files_external/lib/Lib/Storage/SFTP.php"> <InternalMethod> - <code>put</code> + <code><![CDATA[put]]></code> </InternalMethod> </file> <file src="apps/files_external/lib/Lib/Storage/SMB.php"> @@ -882,118 +1473,347 @@ <code><![CDATA[$object->lastModified]]></code> </InvalidArgument> <InvalidNullableReturnType> - <code>filetype</code> - <code>fopen</code> + <code><![CDATA[filetype]]></code> + <code><![CDATA[fopen]]></code> </InvalidNullableReturnType> </file> <file src="apps/files_external/lib/Migration/DummyUserSession.php"> <InvalidReturnType> - <code>login</code> + <code><![CDATA[login]]></code> </InvalidReturnType> </file> + <file src="apps/files_external/lib/Migration/Version1011Date20200630192246.php"> + <DeprecatedMethod> + <code><![CDATA[changeColumn]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_external/lib/Migration/Version1015Date20211104103506.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> <file src="apps/files_external/lib/MountConfig.php"> <InternalMethod> - <code>decrypt</code> - <code>encrypt</code> - <code>setIV</code> - <code>setIV</code> - <code>setKey</code> + <code><![CDATA[decrypt]]></code> + <code><![CDATA[encrypt]]></code> + <code><![CDATA[setIV]]></code> + <code><![CDATA[setIV]]></code> + <code><![CDATA[setKey]]></code> </InternalMethod> - <TooManyArguments> - <code>test</code> - </TooManyArguments> + </file> + <file src="apps/files_external/lib/Service/BackendService.php"> + <DeprecatedClass> + <code><![CDATA[new GenericEvent()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[dispatch]]></code> + <code><![CDATA[registerAuthMechanism]]></code> + <code><![CDATA[registerAuthMechanisms]]></code> + <code><![CDATA[registerBackend]]></code> + <code><![CDATA[registerBackends]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_external/lib/Service/DBConfigService.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_external/lib/Service/StoragesService.php"> + <DeprecatedMethod> + <code><![CDATA[Util::emitHook( + Filesystem::CLASSNAME, + $signal, + [ + Filesystem::signal_param_path => $mountPoint, + Filesystem::signal_param_mount_type => $mountType, + Filesystem::signal_param_users => $applicable, + ] + )]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_reminders/lib/Model/RichReminder.php"> + <ConstructorSignatureMismatch> + <code><![CDATA[public function __construct(]]></code> + <code><![CDATA[public function __construct(]]></code> + </ConstructorSignatureMismatch> + </file> + <file src="apps/files_sharing/lib/AppInfo/Application.php"> + <DeprecatedMethod> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_sharing/lib/Capabilities.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_sharing/lib/Controller/DeletedShareAPIController.php"> + <DeprecatedClass> + <code><![CDATA[new QueryException()]]></code> + <code><![CDATA[new QueryException()]]></code> + <code><![CDATA[new QueryException()]]></code> + </DeprecatedClass> </file> <file src="apps/files_sharing/lib/Controller/ShareAPIController.php"> + <DeprecatedClass> + <code><![CDATA[new QueryException()]]></code> + <code><![CDATA[new QueryException()]]></code> + <code><![CDATA[new QueryException()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> <RedundantCast> - <code>(int)$code</code> - <code>(int)$code</code> + <code><![CDATA[(int)$code]]></code> + <code><![CDATA[(int)$code]]></code> </RedundantCast> <UndefinedClass> - <code>\OCA\Circles\Api\v1\Circles</code> - <code>\OCA\Circles\Api\v1\Circles</code> + <code><![CDATA[Circles]]></code> + <code><![CDATA[Circles]]></code> </UndefinedClass> <UndefinedDocblockClass> <code><![CDATA[$this->getRoomShareHelper()]]></code> <code><![CDATA[$this->getRoomShareHelper()]]></code> <code><![CDATA[$this->getRoomShareHelper()]]></code> - <code>\OCA\Talk\Share\Helper\ShareAPIController</code> + <code><![CDATA[\OCA\Talk\Share\Helper\ShareAPIController]]></code> </UndefinedDocblockClass> </file> <file src="apps/files_sharing/lib/Controller/ShareController.php"> - <InvalidArgument> - <code>$files_list</code> - </InvalidArgument> + <DeprecatedClass> + <code><![CDATA[Share::class]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[emitAccessShareHook]]></code> + <code><![CDATA[emitAccessShareHook]]></code> + <code><![CDATA[emitAccessShareHook]]></code> + <code><![CDATA[emitAccessShareHook]]></code> + <code><![CDATA[emitAccessShareHook]]></code> + <code><![CDATA[emitAccessShareHook]]></code> + <code><![CDATA[emitAccessShareHook]]></code> + <code><![CDATA[emitAccessShareHook]]></code> + </DeprecatedMethod> </file> <file src="apps/files_sharing/lib/External/Manager.php"> + <DeprecatedClass> + <code><![CDATA[Files::buildNotExistingFileName($shareFolder, $share['name'])]]></code> + <code><![CDATA[Files::buildNotExistingFileName('/', $name)]]></code> + <code><![CDATA[Share::RESPONSE_FORMAT]]></code> + <code><![CDATA[\OC_Util::setupFS($user)]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[Files::buildNotExistingFileName($shareFolder, $share['name'])]]></code> + <code><![CDATA[Files::buildNotExistingFileName('/', $name)]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[insertIfNotExist]]></code> + <code><![CDATA[sendNotification]]></code> + <code><![CDATA[sendNotification]]></code> + </DeprecatedMethod> <LessSpecificReturnStatement> - <code>$mount</code> + <code><![CDATA[$mount]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>Mount</code> + <code><![CDATA[Mount]]></code> </MoreSpecificReturnType> </file> <file src="apps/files_sharing/lib/External/Scanner.php"> - <MoreSpecificImplementedParamType> - <code>$cacheData</code> - </MoreSpecificImplementedParamType> + <DeprecatedInterface> + <code><![CDATA[Scanner]]></code> + </DeprecatedInterface> + </file> + <file src="apps/files_sharing/lib/External/Storage.php"> + <DeprecatedInterface> + <code><![CDATA[Storage]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[Util::isSharingDisabledForUser()]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_sharing/lib/Helper.php"> + <DeprecatedMethod> + <code><![CDATA[Util::connectHook('OC_Filesystem', 'post_delete', '\OCA\Files_Sharing\Hooks', 'unshareChildren')]]></code> + <code><![CDATA[Util::connectHook('OC_Filesystem', 'post_rename', '\OCA\Files_Sharing\Updater', 'renameHook')]]></code> + <code><![CDATA[Util::connectHook('OC_User', 'post_deleteUser', '\OCA\Files_Sharing\Hooks', 'deleteUser')]]></code> + </DeprecatedMethod> </file> <file src="apps/files_sharing/lib/Middleware/SharingCheckMiddleware.php"> - <InvalidArgument> - <code><![CDATA[$exception->getMessage()]]></code> - </InvalidArgument> + <DeprecatedInterface> + <code><![CDATA[protected]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[hasAnnotation]]></code> + <code><![CDATA[hasAnnotation]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_sharing/lib/Migration/OwncloudGuestShareType.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_sharing/lib/Migration/SetAcceptedStatus.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_sharing/lib/Migration/SetPasswordColumn.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_sharing/lib/Migration/Version11300Date20201120141438.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[getName]]></code> + </DeprecatedMethod> </file> <file src="apps/files_sharing/lib/MountProvider.php"> <RedundantFunctionCall> - <code>array_values</code> + <code><![CDATA[array_values]]></code> </RedundantFunctionCall> </file> + <file src="apps/files_sharing/lib/Scanner.php"> + <DeprecatedInterface> + <code><![CDATA[Scanner]]></code> + </DeprecatedInterface> + </file> <file src="apps/files_sharing/lib/ShareBackend/File.php"> <InvalidArgument> - <code>$itemSource</code> - <code>$itemSource</code> + <code><![CDATA[$itemSource]]></code> + <code><![CDATA[$itemSource]]></code> </InvalidArgument> <MoreSpecificImplementedParamType> - <code>$shareWith</code> + <code><![CDATA[$shareWith]]></code> </MoreSpecificImplementedParamType> </file> <file src="apps/files_sharing/lib/ShareBackend/Folder.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> <UndefinedInterfaceMethod> - <code>fetchRow</code> + <code><![CDATA[fetchRow]]></code> </UndefinedInterfaceMethod> </file> <file src="apps/files_sharing/lib/SharedMount.php"> <InvalidReturnType> - <code>bool</code> + <code><![CDATA[bool]]></code> </InvalidReturnType> </file> <file src="apps/files_sharing/lib/SharedStorage.php"> + <DeprecatedInterface> + <code><![CDATA[SharedStorage]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info)]]></code> + <code><![CDATA[Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info)]]></code> + <code><![CDATA[Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info)]]></code> + <code><![CDATA[Util::isSharingDisabledForUser()]]></code> + </DeprecatedMethod> <FalsableReturnStatement> <code><![CDATA[$this->sourceRootInfo]]></code> </FalsableReturnStatement> <InvalidNullableReturnType> - <code>ICacheEntry</code> + <code><![CDATA[ICacheEntry]]></code> </InvalidNullableReturnType> - <InvalidReturnStatement> - <code>new FailedCache()</code> - </InvalidReturnStatement> <NullableReturnStatement> <code><![CDATA[$this->sourceRootInfo]]></code> </NullableReturnStatement> </file> + <file src="apps/files_sharing/lib/SharesReminderJob.php"> + <DeprecatedConstant> + <code><![CDATA[IQueryBuilder::PARAM_DATE]]></code> + <code><![CDATA[IQueryBuilder::PARAM_DATE]]></code> + <code><![CDATA[IQueryBuilder::PARAM_DATE]]></code> + <code><![CDATA[IQueryBuilder::PARAM_DATE]]></code> + </DeprecatedConstant> + </file> <file src="apps/files_sharing/lib/Updater.php"> + <DeprecatedMethod> + <code><![CDATA[getUserFolder]]></code> + </DeprecatedMethod> <UndefinedMethod> - <code>moveMount</code> + <code><![CDATA[moveMount]]></code> </UndefinedMethod> </file> - <file src="apps/files_sharing/templates/public.php"> - <RedundantCondition> - <code><![CDATA[$_['hideFileList'] !== true]]></code> - <code><![CDATA[isset($_['hideFileList']) && $_['hideFileList'] !== true]]></code> - </RedundantCondition> + <file src="apps/files_trashbin/lib/BackgroundJob/ExpireTrash.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($user)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_trashbin/lib/Command/CleanUp.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($uid)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_trashbin/lib/Command/Expire.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($this->user)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_trashbin/lib/Command/ExpireTrash.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($user)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_trashbin/lib/Command/RestoreAllFiles.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($uid)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_trashbin/lib/Command/Size.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> </file> <file src="apps/files_trashbin/lib/Sabre/AbstractTrash.php"> <InvalidNullableReturnType> - <code>int</code> + <code><![CDATA[int]]></code> </InvalidNullableReturnType> <NullableReturnStatement> <code><![CDATA[$this->data->getId()]]></code> @@ -1001,118 +1821,384 @@ </file> <file src="apps/files_trashbin/lib/Sabre/AbstractTrashFolder.php"> <InvalidReturnStatement> - <code>$entry</code> + <code><![CDATA[$entry]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>ITrash</code> + <code><![CDATA[ITrash]]></code> </InvalidReturnType> </file> <file src="apps/files_trashbin/lib/Sabre/RestoreFolder.php"> <InvalidNullableReturnType> - <code>getChild</code> + <code><![CDATA[getChild]]></code> </InvalidNullableReturnType> <NullableReturnStatement> - <code>null</code> + <code><![CDATA[null]]></code> </NullableReturnStatement> </file> <file src="apps/files_trashbin/lib/Sabre/RootCollection.php"> <MismatchingDocblockReturnType> - <code>INode</code> + <code><![CDATA[INode]]></code> </MismatchingDocblockReturnType> </file> <file src="apps/files_trashbin/lib/Sabre/TrashRoot.php"> <InvalidReturnStatement> - <code>$entry</code> + <code><![CDATA[$entry]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>ITrash</code> + <code><![CDATA[ITrash]]></code> </InvalidReturnType> </file> + <file src="apps/files_trashbin/lib/Storage.php"> + <DeprecatedMethod> + <code><![CDATA[dispatch]]></code> + </DeprecatedMethod> + </file> <file src="apps/files_trashbin/lib/Trash/LegacyTrashBackend.php"> <UndefinedInterfaceMethod> - <code>$file</code> + <code><![CDATA[$file]]></code> </UndefinedInterfaceMethod> </file> <file src="apps/files_trashbin/lib/Trashbin.php"> - <FalsableReturnStatement> - <code>false</code> - </FalsableReturnStatement> + <DeprecatedMethod> + <code><![CDATA[Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', ['filePath' => Filesystem::normalizePath($file_path), + 'trashPath' => Filesystem::normalizePath(static::getTrashFilename($filename, $timestamp))])]]></code> + <code><![CDATA[Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', ['filePath' => $targetPath, 'trashPath' => $sourcePath])]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getUserFolder]]></code> + <code><![CDATA[getUserFolder]]></code> + <code><![CDATA[getUserFolder]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + </DeprecatedMethod> <InvalidArgument> - <code>$timestamp</code> + <code><![CDATA[$timestamp]]></code> </InvalidArgument> - <InvalidScalarArgument> - <code>$timestamp</code> - </InvalidScalarArgument> </file> - <file src="apps/files_versions/appinfo/routes.php"> - <InvalidScope> - <code>$this</code> - <code>$this</code> - </InvalidScope> + <file src="apps/files_versions/lib/AppInfo/Application.php"> + <DeprecatedClass> + <code><![CDATA[LegacyRollbackListener::class]]></code> + </DeprecatedClass> + <DeprecatedInterface> + <code><![CDATA[$server]]></code> + </DeprecatedInterface> + </file> + <file src="apps/files_versions/lib/BackgroundJob/ExpireVersions.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($user)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_versions/lib/Command/CleanUp.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($user)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> + <file src="apps/files_versions/lib/Command/ExpireVersions.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($user)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> </file> <file src="apps/files_versions/lib/Sabre/RestoreFolder.php"> <InvalidNullableReturnType> - <code>getChild</code> + <code><![CDATA[getChild]]></code> </InvalidNullableReturnType> <NullableReturnStatement> - <code>null</code> + <code><![CDATA[null]]></code> </NullableReturnStatement> </file> + <file src="apps/files_versions/lib/Sabre/VersionFile.php"> + <DeprecatedMethod> + <code><![CDATA[getLabel]]></code> + <code><![CDATA[setVersionLabel]]></code> + </DeprecatedMethod> + </file> <file src="apps/files_versions/lib/Sabre/VersionHome.php"> <InvalidNullableReturnType> - <code>getChild</code> + <code><![CDATA[getChild]]></code> </InvalidNullableReturnType> </file> <file src="apps/files_versions/lib/Storage.php"> - <RedundantCondition> - <code><![CDATA[$storage1->instanceOfStorage('\OC\Files\ObjectStore\ObjectStoreStorage')]]></code> - </RedundantCondition> + <DeprecatedClass> + <code><![CDATA[Files::streamCopy($source, $target, true)]]></code> + <code><![CDATA[\OC_Util::setupFS($uid)]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[Files::streamCopy($source, $target, true)]]></code> + <code><![CDATA[dispatch]]></code> + </DeprecatedMethod> </file> <file src="apps/lookup_server_connector/lib/BackgroundJobs/RetryJob.php"> - <InvalidArgument> - <code><![CDATA[$this->retries + 1]]></code> - </InvalidArgument> + <DeprecatedConstant> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + </DeprecatedConstant> </file> <file src="apps/oauth2/lib/Controller/OauthApiController.php"> <NoInterfaceProperties> <code><![CDATA[$this->request->server]]></code> </NoInterfaceProperties> </file> + <file src="apps/provisioning_api/lib/Controller/AUserDataOCSController.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($user->getUID())]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedConstant> + <code><![CDATA[IAccountManager::PROPERTY_DISPLAYNAME_LEGACY]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + </DeprecatedConstant> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + <code><![CDATA[implementsActions]]></code> + <code><![CDATA[implementsActions]]></code> + </DeprecatedMethod> + </file> <file src="apps/provisioning_api/lib/Controller/UsersController.php"> + <DeprecatedConstant> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + </DeprecatedConstant> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[implementsActions]]></code> + <code><![CDATA[implementsActions]]></code> + <code><![CDATA[implementsActions]]></code> + </DeprecatedMethod> <TypeDoesNotContainNull> - <code>$groupid === null</code> - <code>$groupid === null</code> + <code><![CDATA[$groupid === null]]></code> + <code><![CDATA[$groupid === null]]></code> </TypeDoesNotContainNull> </file> + <file src="apps/provisioning_api/lib/FederatedShareProviderFactory.php"> + <DeprecatedInterface> + <code><![CDATA[private]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[query]]></code> + </DeprecatedMethod> + </file> <file src="apps/provisioning_api/lib/Middleware/ProvisioningApiMiddleware.php"> + <DeprecatedInterface> + <code><![CDATA[IControllerMethodReflector]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[hasAnnotation]]></code> + <code><![CDATA[hasAnnotation]]></code> + </DeprecatedMethod> <InvalidReturnType> - <code>Response</code> + <code><![CDATA[Response]]></code> </InvalidReturnType> </file> <file src="apps/settings/lib/AppInfo/Application.php"> + <DeprecatedInterface> + <code><![CDATA[$serverContainer]]></code> + <code><![CDATA[$serverContainer]]></code> + <code><![CDATA[IAppContainer]]></code> + <code><![CDATA[IAppContainer]]></code> + <code><![CDATA[IAppContainer]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[Util::connectHook('OC_User', 'changeUser', $this, 'onChangeInfo')]]></code> + <code><![CDATA[Util::connectHook('OC_User', 'post_setPassword', $this, 'onChangePassword')]]></code> + <code><![CDATA[getConfig]]></code> + <code><![CDATA[getCrypto]]></code> + <code><![CDATA[getL10NFactory]]></code> + <code><![CDATA[getMailer]]></code> + <code><![CDATA[getSecureRandom]]></code> + <code><![CDATA[getURLGenerator]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + </DeprecatedMethod> <UndefinedInterfaceMethod> - <code>getSettingsManager</code> + <code><![CDATA[getSettingsManager]]></code> </UndefinedInterfaceMethod> </file> + <file src="apps/settings/lib/BackgroundJobs/VerifyUserData.php"> + <DeprecatedConstant> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + </DeprecatedConstant> + </file> <file src="apps/settings/lib/Controller/AppSettingsController.php"> - <UndefinedInterfaceMethod> - <code>ignoreNextcloudRequirementForApp</code> - </UndefinedInterfaceMethod> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getSupportedApps]]></code> + </DeprecatedMethod> + </file> + <file src="apps/settings/lib/Controller/MailSettingsController.php"> + <DeprecatedMethod> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/settings/lib/Controller/UsersController.php"> + <DeprecatedConstant> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + </DeprecatedConstant> + <DeprecatedMethod> + <code><![CDATA[dispatch]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/settings/lib/Controller/WebAuthnController.php"> + <DeprecatedMethod> + <code><![CDATA[PublicKeyCredentialCreationOptions::createFromArray($this->session->get(self::WEBAUTHN_REGISTRATION))]]></code> + </DeprecatedMethod> </file> <file src="apps/settings/lib/Hooks.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> <InvalidArrayOffset> <code><![CDATA[[$user->getEMailAddress() => $user->getDisplayName()]]]></code> </InvalidArrayOffset> </file> + <file src="apps/settings/lib/Settings/Admin/ArtificialIntelligence.php"> + <DeprecatedInterface> + <code><![CDATA[$taskProcessingSettings]]></code> + <code><![CDATA[$textProcessingSettings]]></code> + <code><![CDATA[private]]></code> + <code><![CDATA[private]]></code> + <code><![CDATA[private]]></code> + <code><![CDATA[private]]></code> + <code><![CDATA[try { + $taskType = $this->container->get($taskTypeClass); + } catch (NotFoundExceptionInterface $e) { + continue; + } catch (ContainerExceptionInterface $e) { + continue; + }]]></code> + </DeprecatedInterface> + </file> <file src="apps/settings/lib/Settings/Admin/Security.php"> <UndefinedInterfaceMethod> - <code>isReady</code> + <code><![CDATA[isReady]]></code> </UndefinedInterfaceMethod> </file> + <file src="apps/settings/lib/Settings/Admin/Server.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/settings/lib/Settings/Admin/Sharing.php"> - <NullArgument> - <code>null</code> - </NullArgument> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/settings/lib/Settings/Personal/PersonalInfo.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($user->getUID())]]></code> + </DeprecatedClass> + <DeprecatedConstant> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + </DeprecatedConstant> + </file> + <file src="apps/settings/lib/Settings/Personal/Security/Authtokens.php"> + <DeprecatedClass> + <code><![CDATA[IToken::WIPE_TOKEN]]></code> + </DeprecatedClass> + <DeprecatedInterface> + <code><![CDATA[IToken]]></code> + </DeprecatedInterface> + </file> + <file src="apps/settings/lib/Settings/Personal/Security/WebAuthn.php"> + <DeprecatedInterface> + <code><![CDATA[private]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[provideInitialState]]></code> + </DeprecatedMethod> + </file> + <file src="apps/settings/lib/Settings/Personal/ServerDevNotice.php"> + <DeprecatedMethod> + <code><![CDATA[dispatch]]></code> + </DeprecatedMethod> + </file> + <file src="apps/settings/lib/SetupChecks/CheckUserCertificates.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/settings/lib/SetupChecks/CronErrors.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/settings/lib/SetupChecks/EmailTestSuccessful.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/settings/lib/SetupChecks/PushService.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/settings/lib/SetupChecks/SupportedDatabase.php"> + <DeprecatedMethod> + <code><![CDATA[getDatabasePlatform]]></code> + </DeprecatedMethod> + </file> + <file src="apps/sharebymail/lib/Settings/SettingsManager.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> </file> <file src="apps/sharebymail/lib/ShareByMailProvider.php"> <InvalidArgument> @@ -1121,130 +2207,540 @@ </InvalidArgument> </file> <file src="apps/systemtags/lib/Activity/Listener.php"> + <DeprecatedConstant> + <code><![CDATA[ManagerEvent::EVENT_CREATE]]></code> + <code><![CDATA[ManagerEvent::EVENT_CREATE]]></code> + <code><![CDATA[ManagerEvent::EVENT_DELETE]]></code> + <code><![CDATA[ManagerEvent::EVENT_UPDATE]]></code> + <code><![CDATA[ManagerEvent::EVENT_UPDATE]]></code> + <code><![CDATA[MapperEvent::EVENT_ASSIGN]]></code> + <code><![CDATA[MapperEvent::EVENT_ASSIGN]]></code> + <code><![CDATA[MapperEvent::EVENT_ASSIGN]]></code> + <code><![CDATA[MapperEvent::EVENT_UNASSIGN]]></code> + <code><![CDATA[MapperEvent::EVENT_UNASSIGN]]></code> + </DeprecatedConstant> <InvalidArgument> <code><![CDATA[$event->getObjectId()]]></code> <code><![CDATA[$event->getObjectId()]]></code> </InvalidArgument> </file> + <file src="apps/systemtags/lib/AppInfo/Application.php"> + <DeprecatedConstant> + <code><![CDATA[ManagerEvent::EVENT_CREATE]]></code> + <code><![CDATA[ManagerEvent::EVENT_DELETE]]></code> + <code><![CDATA[ManagerEvent::EVENT_UPDATE]]></code> + <code><![CDATA[MapperEvent::EVENT_ASSIGN]]></code> + <code><![CDATA[MapperEvent::EVENT_UNASSIGN]]></code> + </DeprecatedConstant> + <DeprecatedMethod> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + </DeprecatedMethod> + </file> + <file src="apps/testing/lib/AlternativeHomeUserBackend.php"> + <DeprecatedInterface> + <code><![CDATA[AlternativeHomeUserBackend]]></code> + </DeprecatedInterface> + </file> + <file src="apps/testing/lib/AppInfo/Application.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getConfig]]></code> + <code><![CDATA[getUserManager]]></code> + </DeprecatedMethod> + </file> + <file src="apps/testing/lib/Controller/ConfigController.php"> + <DeprecatedMethod> + <code><![CDATA[deleteAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/testing/lib/Controller/LockingController.php"> + <DeprecatedMethod> + <code><![CDATA[deleteAppValue]]></code> + <code><![CDATA[getAppKeys]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/testing/lib/Locking/FakeDBLockingProvider.php"> + <DeprecatedMethod> + <code><![CDATA[executeUpdate]]></code> + </DeprecatedMethod> + </file> + <file src="apps/testing/lib/Provider/FakeText2ImageProvider.php"> + <DeprecatedInterface> + <code><![CDATA[FakeText2ImageProvider]]></code> + </DeprecatedInterface> + </file> + <file src="apps/testing/lib/Provider/FakeTextProcessingProvider.php"> + <DeprecatedClass> + <code><![CDATA[FakeTextProcessingProvider]]></code> + <code><![CDATA[FreePromptTaskType::class]]></code> + </DeprecatedClass> + <DeprecatedInterface> + <code><![CDATA[FakeTextProcessingProvider]]></code> + <code><![CDATA[FakeTextProcessingProvider]]></code> + </DeprecatedInterface> + </file> + <file src="apps/testing/lib/Provider/FakeTextProcessingProviderSync.php"> + <DeprecatedClass> + <code><![CDATA[FakeTextProcessingProviderSync]]></code> + <code><![CDATA[FreePromptTaskType::class]]></code> + </DeprecatedClass> + <DeprecatedInterface> + <code><![CDATA[FakeTextProcessingProviderSync]]></code> + <code><![CDATA[FakeTextProcessingProviderSync]]></code> + <code><![CDATA[FakeTextProcessingProviderSync]]></code> + </DeprecatedInterface> + </file> + <file src="apps/testing/lib/Provider/FakeTranslationProvider.php"> + <DeprecatedClass> + <code><![CDATA[new LanguageTuple('de', 'German', 'en', 'English')]]></code> + <code><![CDATA[new LanguageTuple('en', 'English', 'de', 'German')]]></code> + </DeprecatedClass> + <DeprecatedInterface> + <code><![CDATA[FakeTranslationProvider]]></code> + </DeprecatedInterface> + </file> + <file src="apps/theming/lib/Capabilities.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/theming/lib/Command/UpdateConfig.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/theming/lib/Controller/ThemingController.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/theming/lib/ImageManager.php"> + <DeprecatedMethod> + <code><![CDATA[deleteAppValue]]></code> + <code><![CDATA[deleteAppValue]]></code> + <code><![CDATA[deleteAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/theming/lib/Settings/Admin.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/theming/lib/Settings/Personal.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/theming/lib/Themes/CommonThemeTrait.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/theming/lib/ThemingDefaults.php"> + <DeprecatedMethod> + <code><![CDATA[deleteAppValue]]></code> + <code><![CDATA[deleteAppValue]]></code> + <code><![CDATA[deleteAppValues]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/theming/lib/Util.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> <InvalidReturnStatement> <code><![CDATA[array_values($color->getRgb())]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>array{0: int, 1: int, 2: int}</code> + <code><![CDATA[array{0: int, 1: int, 2: int}]]></code> </InvalidReturnType> </file> + <file src="apps/twofactor_backupcodes/lib/Db/BackupCodeMapper.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="apps/twofactor_backupcodes/lib/Migration/Version1002Date20170607113030.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="apps/twofactor_backupcodes/lib/Migration/Version1002Date20170919123342.php"> + <DeprecatedMethod> + <code><![CDATA[getName]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_ldap/ajax/clearMappings.php"> + <DeprecatedMethod> + <code><![CDATA[\OC_JSON::callCheck()]]></code> + <code><![CDATA[\OC_JSON::checkAdminUser()]]></code> + <code><![CDATA[\OC_JSON::checkAppEnabled('user_ldap')]]></code> + <code><![CDATA[\OC_JSON::error(['message' => $e->getMessage()])]]></code> + <code><![CDATA[\OC_JSON::success()]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_ldap/ajax/deleteConfiguration.php"> + <DeprecatedMethod> + <code><![CDATA[\OC_JSON::callCheck()]]></code> + <code><![CDATA[\OC_JSON::checkAdminUser()]]></code> + <code><![CDATA[\OC_JSON::checkAppEnabled('user_ldap')]]></code> + <code><![CDATA[\OC_JSON::error(['message' => $l->t('Failed to delete the server configuration')])]]></code> + <code><![CDATA[\OC_JSON::success()]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_ldap/ajax/getConfiguration.php"> + <DeprecatedMethod> + <code><![CDATA[\OC_JSON::callCheck()]]></code> + <code><![CDATA[\OC_JSON::checkAdminUser()]]></code> + <code><![CDATA[\OC_JSON::checkAppEnabled('user_ldap')]]></code> + <code><![CDATA[\OC_JSON::success(['configuration' => $configuration])]]></code> + </DeprecatedMethod> + </file> <file src="apps/user_ldap/ajax/getNewServerConfigPrefix.php"> - <InvalidScalarArgument> - <code>$ln + 1</code> - </InvalidScalarArgument> + <DeprecatedMethod> + <code><![CDATA[\OC_JSON::callCheck()]]></code> + <code><![CDATA[\OC_JSON::checkAdminUser()]]></code> + <code><![CDATA[\OC_JSON::checkAppEnabled('user_ldap')]]></code> + <code><![CDATA[\OC_JSON::success($resultData)]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_ldap/ajax/setConfiguration.php"> + <DeprecatedMethod> + <code><![CDATA[\OC_JSON::callCheck()]]></code> + <code><![CDATA[\OC_JSON::checkAdminUser()]]></code> + <code><![CDATA[\OC_JSON::checkAppEnabled('user_ldap')]]></code> + <code><![CDATA[\OC_JSON::success()]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_ldap/ajax/testConfiguration.php"> + <DeprecatedMethod> + <code><![CDATA[\OC_JSON::callCheck()]]></code> + <code><![CDATA[\OC_JSON::checkAdminUser()]]></code> + <code><![CDATA[\OC_JSON::checkAppEnabled('user_ldap')]]></code> + <code><![CDATA[\OC_JSON::error(['message' + => $l->t('Valid configuration, but binding failed. Please check the server settings and credentials.')])]]></code> + <code><![CDATA[\OC_JSON::error(['message' + => $l->t('Invalid configuration: %s', $configurationError)])]]></code> + <code><![CDATA[\OC_JSON::error(['message' => $e->getMessage()])]]></code> + <code><![CDATA[\OC_JSON::error(['message' => $l->t('Invalid configuration: Anonymous binding is not allowed.')])]]></code> + <code><![CDATA[\OC_JSON::success(['message' + => $l->t('Valid configuration, connection established!')])]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_ldap/ajax/wizard.php"> + <DeprecatedMethod> + <code><![CDATA[\OC_JSON::callCheck()]]></code> + <code><![CDATA[\OC_JSON::checkAdminUser()]]></code> + <code><![CDATA[\OC_JSON::checkAppEnabled('user_ldap')]]></code> + <code><![CDATA[\OC_JSON::error()]]></code> + <code><![CDATA[\OC_JSON::error()]]></code> + <code><![CDATA[\OC_JSON::error(['message' => $e->getMessage(), 'code' => $e->getCode()])]]></code> + <code><![CDATA[\OC_JSON::error(['message' => $e->getMessage()])]]></code> + <code><![CDATA[\OC_JSON::error(['message' => $l->t('Action does not exist')])]]></code> + <code><![CDATA[\OC_JSON::error(['message' => $l->t('Could not set configuration %1$s to %2$s', [$key, $setParameters[0]])])]]></code> + <code><![CDATA[\OC_JSON::error(['message' => $l->t('Invalid data specified')])]]></code> + <code><![CDATA[\OC_JSON::error(['message' => $l->t('No action specified')])]]></code> + <code><![CDATA[\OC_JSON::error(['message' => $l->t('No configuration specified')])]]></code> + <code><![CDATA[\OC_JSON::error(['message' => $l->t('No data specified')])]]></code> + <code><![CDATA[\OC_JSON::success($result->getResultArray())]]></code> + <code><![CDATA[\OC_JSON::success($result->getResultArray())]]></code> + <code><![CDATA[\OC_JSON::success()]]></code> + </DeprecatedMethod> </file> <file src="apps/user_ldap/appinfo/routes.php"> <InvalidScope> - <code>$this</code> + <code><![CDATA[$this]]></code> </InvalidScope> </file> <file src="apps/user_ldap/lib/Access.php"> + <DeprecatedMethod> + <code><![CDATA[emit]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> <InvalidReturnStatement> - <code>$uuid</code> - <code>$values</code> + <code><![CDATA[$uuid]]></code> + <code><![CDATA[$values]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>string[]</code> + <code><![CDATA[string[]]]></code> </InvalidReturnType> <RedundantCast> <code><![CDATA[(int)$e->getCode()]]></code> </RedundantCast> </file> + <file src="apps/user_ldap/lib/AppInfo/Application.php"> + <DeprecatedInterface> + <code><![CDATA[$server]]></code> + <code><![CDATA[$server]]></code> + <code><![CDATA[IAppContainer]]></code> + <code><![CDATA[IAppContainer]]></code> + <code><![CDATA[IAppContainer]]></code> + <code><![CDATA[IAppContainer]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[Util::connectHook( + '\OCA\Files_Sharing\API\Server2Server', + 'preLoginNameUsedAsUserName', + '\OCA\User_LDAP\Helper', + 'loginName2UserName' + )]]></code> + <code><![CDATA[dispatch]]></code> + <code><![CDATA[getConfig]]></code> + <code><![CDATA[getConfig]]></code> + <code><![CDATA[getRequest]]></code> + <code><![CDATA[getURLGenerator]]></code> + <code><![CDATA[registerService]]></code> + <code><![CDATA[registerService]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_ldap/lib/Configuration.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/user_ldap/lib/Connection.php"> <NoValue> - <code>$subj</code> + <code><![CDATA[$subj]]></code> </NoValue> <ParadoxicalCondition> - <code>default: + <code><![CDATA[default: $subj = $key; - break;</code> + break;]]></code> </ParadoxicalCondition> </file> <file src="apps/user_ldap/lib/Group_LDAP.php"> <InvalidScalarArgument> - <code>$groupID</code> + <code><![CDATA[$groupID]]></code> </InvalidScalarArgument> </file> <file src="apps/user_ldap/lib/Group_Proxy.php"> <ParamNameMismatch> - <code>$gid</code> + <code><![CDATA[$gid]]></code> </ParamNameMismatch> </file> + <file src="apps/user_ldap/lib/Jobs/CleanUp.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/user_ldap/lib/Jobs/Sync.php"> + <DeprecatedMethod> + <code><![CDATA[getAppKeys]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> <InvalidOperand> - <code>$i</code> + <code><![CDATA[$i]]></code> </InvalidOperand> - <NullArgument> - <code>null</code> - </NullArgument> + </file> + <file src="apps/user_ldap/lib/Jobs/UpdateGroups.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_ldap/lib/LDAPProvider.php"> + <DeprecatedInterface> + <code><![CDATA[IServerContainer]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[getGroupManager]]></code> + <code><![CDATA[getUserManager]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_ldap/lib/LDAPProviderFactory.php"> + <DeprecatedInterface> + <code><![CDATA[private]]></code> + </DeprecatedInterface> </file> <file src="apps/user_ldap/lib/Mapping/AbstractMapping.php"> + <DeprecatedClass> + <code><![CDATA[\Doctrine\DBAL\FetchMode::ASSOCIATIVE]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[getDatabasePlatform]]></code> + <code><![CDATA[insertIfNotExist]]></code> + </DeprecatedMethod> <RedundantCondition> - <code>isset($qb)</code> + <code><![CDATA[isset($qb)]]></code> </RedundantCondition> <TypeDoesNotContainNull> - <code>isset($qb)</code> + <code><![CDATA[isset($qb)]]></code> </TypeDoesNotContainNull> </file> + <file src="apps/user_ldap/lib/Migration/RemoveRefreshTime.php"> + <DeprecatedMethod> + <code><![CDATA[deleteAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_ldap/lib/Migration/UUIDFixInsert.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_ldap/lib/Migration/Version1120Date20210917155206.php"> + <DeprecatedMethod> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_ldap/lib/Migration/Version1130Date20211102154716.php"> + <DeprecatedMethod> + <code><![CDATA[getDatabasePlatform]]></code> + </DeprecatedMethod> + </file> <file src="apps/user_ldap/lib/User/Manager.php"> <InvalidDocblock> - <code>public function setLdapAccess(Access $access) {</code> + <code><![CDATA[public function setLdapAccess(Access $access) {]]></code> </InvalidDocblock> </file> <file src="apps/user_ldap/lib/User/User.php"> - <FalsableReturnStatement> - <code><![CDATA[$this->avatarImage]]></code> - </FalsableReturnStatement> - <InvalidPropertyAssignmentValue> - <code><![CDATA[$this->refreshedFeatures]]></code> - </InvalidPropertyAssignmentValue> - <InvalidReturnType> - <code>null</code> - </InvalidReturnType> - <RedundantCondition> - <code><![CDATA[$aQuota && (count($aQuota) > 0)]]></code> - </RedundantCondition> + <DeprecatedConstant> + <code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code> + </DeprecatedConstant> + <DeprecatedMethod> + <code><![CDATA[Util::connectHook('OC_User', 'post_login', $this, 'handlePasswordExpiry')]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> </file> <file src="apps/user_ldap/lib/User_LDAP.php"> + <DeprecatedInterface> + <code><![CDATA[User_LDAP]]></code> + </DeprecatedInterface> <ImplementedReturnTypeMismatch> - <code>string|false</code> + <code><![CDATA[string|false]]></code> </ImplementedReturnTypeMismatch> <MoreSpecificImplementedParamType> - <code>$limit</code> - <code>$offset</code> + <code><![CDATA[$limit]]></code> + <code><![CDATA[$offset]]></code> </MoreSpecificImplementedParamType> <NullableReturnStatement> - <code>null</code> + <code><![CDATA[null]]></code> </NullableReturnStatement> <RedundantCondition> <code><![CDATA[$displayName && (count($displayName) > 0)]]></code> - <code>is_string($dn)</code> + <code><![CDATA[is_string($dn)]]></code> </RedundantCondition> </file> <file src="apps/user_ldap/lib/User_Proxy.php"> + <DeprecatedInterface> + <code><![CDATA[User_Proxy]]></code> + </DeprecatedInterface> <ParamNameMismatch> - <code>$uid</code> + <code><![CDATA[$uid]]></code> </ParamNameMismatch> </file> <file src="apps/user_ldap/lib/Wizard.php"> <InvalidArrayOffset> - <code>$possibleAttrs[$i]</code> + <code><![CDATA[$possibleAttrs[$i]]]></code> </InvalidArrayOffset> </file> <file src="apps/user_status/lib/AppInfo/Application.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[query]]></code> + </DeprecatedMethod> <UndefinedInterfaceMethod> - <code>registerProvider</code> + <code><![CDATA[registerProvider]]></code> </UndefinedInterfaceMethod> </file> + <file src="apps/user_status/lib/Listener/BeforeTemplateRenderedListener.php"> + <DeprecatedInterface> + <code><![CDATA[IInitialStateService]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[provideLazyInitialState]]></code> + <code><![CDATA[provideLazyInitialState]]></code> + </DeprecatedMethod> + </file> + <file src="apps/user_status/lib/Service/PredefinedStatusService.php"> + <DeprecatedConstant> + <code><![CDATA[self::CALL]]></code> + <code><![CDATA[self::CALL]]></code> + <code><![CDATA[self::CALL]]></code> + <code><![CDATA[self::CALL]]></code> + </DeprecatedConstant> + </file> + <file src="apps/user_status/lib/Service/StatusService.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="apps/workflowengine/lib/BackgroundJobs/Rotate.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/workflowengine/lib/Check/AbstractStringCheck.php"> <NullArgument> - <code>null</code> + <code><![CDATA[null]]></code> </NullArgument> </file> <file src="apps/workflowengine/lib/Check/FileSize.php"> @@ -1252,123 +2748,262 @@ <code><![CDATA[$this->size]]></code> </FalsableReturnStatement> <InvalidPropertyAssignmentValue> - <code>$size</code> + <code><![CDATA[$size]]></code> </InvalidPropertyAssignmentValue> <InvalidReturnStatement> <code><![CDATA[$this->size]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>string</code> + <code><![CDATA[string]]></code> </InvalidReturnType> </file> - <file src="apps/workflowengine/lib/Check/FileSystemTags.php"> - <UndefinedDocblockClass> - <code><![CDATA[$this->storage]]></code> - </UndefinedDocblockClass> - </file> <file src="apps/workflowengine/lib/Check/RequestRemoteAddress.php"> <InvalidArgument> - <code>$decodedValue[1]</code> - <code>$decodedValue[1]</code> - <code>$decodedValue[1]</code> - <code>$decodedValue[1]</code> + <code><![CDATA[$decodedValue[1]]]></code> + <code><![CDATA[$decodedValue[1]]]></code> + <code><![CDATA[$decodedValue[1]]]></code> + <code><![CDATA[$decodedValue[1]]]></code> </InvalidArgument> </file> - <file src="apps/workflowengine/lib/Check/RequestTime.php"> - <InvalidScalarArgument> - <code>$hour1</code> - <code>$minute1</code> - </InvalidScalarArgument> - </file> <file src="apps/workflowengine/lib/Check/TFileCheck.php"> <InvalidArgument> <code><![CDATA[['app' => Application::APP_ID, 'class' => get_class($subject)]]]></code> </InvalidArgument> </file> <file src="apps/workflowengine/lib/Entity/File.php"> + <DeprecatedConstant> + <code><![CDATA[MapperEvent::EVENT_ASSIGN]]></code> + <code><![CDATA[MapperEvent::EVENT_ASSIGN]]></code> + <code><![CDATA[MapperEvent::EVENT_ASSIGN]]></code> + </DeprecatedConstant> + <DeprecatedMethod> + <code><![CDATA[getSubject]]></code> + <code><![CDATA[getSubject]]></code> + </DeprecatedMethod> <InvalidReturnType> - <code>string</code> + <code><![CDATA[string]]></code> </InvalidReturnType> </file> <file src="apps/workflowengine/lib/Manager.php"> + <DeprecatedInterface> + <code><![CDATA[protected]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + <code><![CDATA[query]]></code> + </DeprecatedMethod> <InvalidArgument> - <code>$missingCheck</code> + <code><![CDATA[$missingCheck]]></code> </InvalidArgument> <InvalidOperand> - <code>$result</code> + <code><![CDATA[$result]]></code> </InvalidOperand> <InvalidReturnStatement> - <code>$result</code> + <code><![CDATA[$result]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>bool</code> + <code><![CDATA[bool]]></code> </InvalidReturnType> </file> + <file src="apps/workflowengine/lib/Migration/Version2200Date20210805101925.php"> + <DeprecatedMethod> + <code><![CDATA[changeColumn]]></code> + </DeprecatedMethod> + </file> + <file src="apps/workflowengine/lib/Service/Logger.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> <file src="apps/workflowengine/lib/Service/RuleMatcher.php"> - <UndefinedInterfaceMethod> - <code>getAllConfiguredScopesForOperation</code> - <code>getChecks</code> - <code>getOperations</code> - <code>getOperations</code> - <code>isUserScopeEnabled</code> - </UndefinedInterfaceMethod> + <DeprecatedInterface> + <code><![CDATA[protected]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[query]]></code> + </DeprecatedMethod> + </file> + <file src="apps/workflowengine/lib/Settings/ASettings.php"> + <DeprecatedMethod> + <code><![CDATA[dispatch]]></code> + </DeprecatedMethod> + </file> + <file src="core/BackgroundJobs/BackgroundCleanupUpdaterBackupsJob.php"> + <DeprecatedClass> + <code><![CDATA[Files::rmdirr($dir)]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[Files::rmdirr($dir)]]></code> + </DeprecatedMethod> </file> <file src="core/BackgroundJobs/CheckForUserCertificates.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($userId)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + <code><![CDATA[deleteAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> <ParamNameMismatch> - <code>$arguments</code> + <code><![CDATA[$arguments]]></code> </ParamNameMismatch> </file> - <file src="core/Command/App/Install.php"> - <TypeDoesNotContainType> - <code>$result === false</code> - </TypeDoesNotContainType> - </file> <file src="core/Command/App/ListApps.php"> <LessSpecificImplementedReturnType> - <code>array</code> + <code><![CDATA[array]]></code> </LessSpecificImplementedReturnType> </file> - <file src="core/Command/App/Update.php"> - <RedundantCondition> - <code>$result === true</code> - </RedundantCondition> + <file src="core/Command/Broadcast/Test.php"> + <DeprecatedMethod> + <code><![CDATA[dispatch]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/Check.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::checkServer($this->config)]]></code> + </DeprecatedClass> </file> <file src="core/Command/Config/Import.php"> + <DeprecatedMethod> + <code><![CDATA[deleteAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> <InvalidScalarArgument> - <code>0</code> - <code>1</code> + <code><![CDATA[0]]></code> + <code><![CDATA[1]]></code> </InvalidScalarArgument> </file> <file src="core/Command/Config/ListConfigs.php"> + <DeprecatedMethod> + <code><![CDATA[\OC_App::getAllApps()]]></code> + <code><![CDATA[getFilteredValues]]></code> + <code><![CDATA[getValues]]></code> + </DeprecatedMethod> <FalsableReturnStatement> <code><![CDATA[$this->appConfig->getValues($app, false)]]></code> </FalsableReturnStatement> - <TooManyArguments> - <code>getFilteredValues</code> - </TooManyArguments> + </file> + <file src="core/Command/Db/AddMissingPrimaryKeys.php"> + <DeprecatedMethod> + <code><![CDATA[hasPrimaryKey]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/Db/ConvertFilecacheBigInt.php"> + <DeprecatedMethod> + <code><![CDATA[getName]]></code> + </DeprecatedMethod> </file> <file src="core/Command/Db/ConvertType.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[getName]]></code> + <code><![CDATA[getPrimaryKeyColumns]]></code> + </DeprecatedMethod> <InvalidScalarArgument> - <code>0</code> - <code>1</code> + <code><![CDATA[0]]></code> + <code><![CDATA[1]]></code> </InvalidScalarArgument> </file> + <file src="core/Command/Db/ExportSchema.php"> + <DeprecatedMethod> + <code><![CDATA[getDatabasePlatform]]></code> + <code><![CDATA[getDatabasePlatform]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/Db/Migrations/ExecuteCommand.php"> + <DeprecatedMethod> + <code><![CDATA[\OC_App::getAllApps()]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/Db/Migrations/GenerateCommand.php"> + <DeprecatedMethod> + <code><![CDATA[Util::getVersion()]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/Db/Migrations/MigrateCommand.php"> + <DeprecatedMethod> + <code><![CDATA[\OC_App::getAllApps()]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/Db/Migrations/StatusCommand.php"> + <DeprecatedMethod> + <code><![CDATA[\OC_App::getAllApps()]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/Encryption/ChangeKeyStorageRoot.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($uid)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/Encryption/DecryptAll.php"> + <DeprecatedMethod> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/Encryption/Disable.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> + </file> <file src="core/Command/Encryption/Enable.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[getAppValue]]></code> + <code><![CDATA[setAppValue]]></code> + </DeprecatedMethod> <NullArgument> - <code>null</code> + <code><![CDATA[null]]></code> </NullArgument> </file> + <file src="core/Command/Encryption/MigrateKeyStorage.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($uid)]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> <file src="core/Command/Log/File.php"> <InvalidReturnStatement> - <code>[0]</code> + <code><![CDATA[[0]]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>string[]</code> + <code><![CDATA[string[]]]></code> </InvalidReturnType> </file> <file src="core/Command/Log/Manage.php"> <InvalidArgument> - <code>$levelNum</code> + <code><![CDATA[$levelNum]]></code> </InvalidArgument> </file> <file src="core/Command/Maintenance/DataFingerprint.php"> @@ -1376,77 +3011,281 @@ <code><![CDATA[$this->timeFactory->getTime()]]></code> </InvalidScalarArgument> </file> - <file src="core/Command/Maintenance/Mimetype/UpdateDB.php"> - <UndefinedInterfaceMethod> - <code>getAllMappings</code> - <code>updateFilecache</code> - </UndefinedInterfaceMethod> - </file> - <file src="core/Command/Maintenance/RepairShareOwnership.php"> - <LessSpecificReturnStatement> - <code>$found</code> - <code>$found</code> - </LessSpecificReturnStatement> - <MoreSpecificReturnType> - <code>array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string}[]</code> - <code>array{shareId: int, fileTarget: string, initiator: string, receiver: string, owner: string, mountOwner: string}[]</code> - </MoreSpecificReturnType> - </file> <file src="core/Command/Preview/Repair.php"> <UndefinedInterfaceMethod> - <code>section</code> - <code>section</code> + <code><![CDATA[section]]></code> + <code><![CDATA[section]]></code> </UndefinedInterfaceMethod> </file> <file src="core/Command/Preview/ResetRenderedTexts.php"> <InvalidReturnStatement> - <code>[]</code> + <code><![CDATA[[]]]></code> </InvalidReturnStatement> </file> + <file src="core/Command/Security/BruteforceAttempts.php"> + <DeprecatedMethod> + <code><![CDATA[getAttempts]]></code> + <code><![CDATA[getDelay]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/Security/BruteforceResetAttempts.php"> + <DeprecatedMethod> + <code><![CDATA[resetDelayForIP]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/Upgrade.php"> + <DeprecatedMethod> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/User/AuthTokens/Add.php"> + <DeprecatedClass> + <code><![CDATA[IToken::DO_NOT_REMEMBER]]></code> + <code><![CDATA[IToken::PERMANENT_TOKEN]]></code> + </DeprecatedClass> + </file> + <file src="core/Command/User/AuthTokens/ListCommand.php"> + <DeprecatedClass> + <code><![CDATA[IToken::PERMANENT_TOKEN]]></code> + <code><![CDATA[IToken::TEMPORARY_TOKEN]]></code> + <code><![CDATA[IToken::WIPE_TOKEN]]></code> + </DeprecatedClass> + <DeprecatedInterface> + <code><![CDATA[IToken]]></code> + </DeprecatedInterface> + </file> + <file src="core/Command/User/Info.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($user->getUID())]]></code> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[\OC_Util::tearDownFS()]]></code> + </DeprecatedMethod> + </file> + <file src="core/Command/User/Setting.php"> + <DeprecatedMethod> + <code><![CDATA[setEMailAddress]]></code> + </DeprecatedMethod> + </file> + <file src="core/Controller/AppPasswordController.php"> + <DeprecatedClass> + <code><![CDATA[IToken::DO_NOT_REMEMBER]]></code> + <code><![CDATA[IToken::PERMANENT_TOKEN]]></code> + </DeprecatedClass> + </file> + <file src="core/Controller/AutoCompleteController.php"> + <DeprecatedClass> + <code><![CDATA[new AutoCompleteEvent([ + 'search' => $search, + 'results' => $results, + 'itemType' => $itemType, + 'itemId' => $itemId, + 'sorter' => $sorter, + 'shareTypes' => $shareTypes, + 'limit' => $limit, + ])]]></code> + </DeprecatedClass> + <DeprecatedMethod> + <code><![CDATA[dispatch]]></code> + </DeprecatedMethod> + </file> <file src="core/Controller/ClientFlowLoginV2Controller.php"> <TypeDoesNotContainType> - <code>!is_string($stateToken)</code> + <code><![CDATA[!is_string($stateToken)]]></code> </TypeDoesNotContainType> </file> <file src="core/Controller/CollaborationResourcesController.php"> <UndefinedInterfaceMethod> - <code>searchCollections</code> + <code><![CDATA[searchCollections]]></code> </UndefinedInterfaceMethod> </file> + <file src="core/Controller/LoginController.php"> + <DeprecatedMethod> + <code><![CDATA[getDelay]]></code> + </DeprecatedMethod> + </file> <file src="core/Controller/LostController.php"> + <DeprecatedMethod> + <code><![CDATA[Util::emitHook( + '\OCA\Files_Sharing\API\Server2Server', + 'preLoginNameUsedAsUserName', + ['uid' => &$user] + )]]></code> + </DeprecatedMethod> <RedundantCast> <code><![CDATA[(int)$e->getCode()]]></code> </RedundantCast> </file> + <file src="core/Controller/OCJSController.php"> + <DeprecatedInterface> + <code><![CDATA[IInitialStateService]]></code> + </DeprecatedInterface> + </file> + <file src="core/Controller/RecommendedAppsController.php"> + <DeprecatedInterface> + <code><![CDATA[private]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[provideInitialState]]></code> + </DeprecatedMethod> + </file> + <file src="core/Controller/SetupController.php"> + <DeprecatedInterface> + <code><![CDATA[protected]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[provideInitialState]]></code> + <code><![CDATA[provideInitialState]]></code> + <code><![CDATA[provideInitialState]]></code> + </DeprecatedMethod> + </file> + <file src="core/Controller/TaskProcessingApiController.php"> + <DeprecatedClass> + <code><![CDATA[\OC_Util::setupFS($task->getUserId())]]></code> + </DeprecatedClass> + </file> + <file src="core/Controller/TextProcessingApiController.php"> + <DeprecatedClass> + <code><![CDATA[Task]]></code> + <code><![CDATA[new Task($type, $input, $appId, $this->userId, $identifier)]]></code> + </DeprecatedClass> + <DeprecatedInterface> + <code><![CDATA[$object]]></code> + <code><![CDATA[Task]]></code> + <code><![CDATA[private]]></code> + </DeprecatedInterface> + </file> + <file src="core/Controller/TextToImageApiController.php"> + <DeprecatedClass> + <code><![CDATA[Task]]></code> + <code><![CDATA[new Task($input, $appId, $numberOfImages, $this->userId, $identifier)]]></code> + </DeprecatedClass> + <DeprecatedInterface> + <code><![CDATA[private]]></code> + </DeprecatedInterface> + </file> + <file src="core/Controller/TranslationApiController.php"> + <DeprecatedInterface> + <code><![CDATA[private]]></code> + </DeprecatedInterface> + </file> <file src="core/Controller/UnifiedSearchController.php"> + <DeprecatedInterface> + <code><![CDATA[private]]></code> + </DeprecatedInterface> <UndefinedInterfaceMethod> - <code>findMatchingRoute</code> + <code><![CDATA[findMatchingRoute]]></code> </UndefinedInterfaceMethod> </file> + <file src="core/Controller/WebAuthnController.php"> + <DeprecatedMethod> + <code><![CDATA[PublicKeyCredentialRequestOptions::createFromString($this->session->get(self::WEBAUTHN_LOGIN))]]></code> + <code><![CDATA[Util::emitHook( + '\OCA\Files_Sharing\API\Server2Server', + 'preLoginNameUsedAsUserName', + ['uid' => &$uid] + )]]></code> + </DeprecatedMethod> + </file> <file src="core/Middleware/TwoFactorMiddleware.php"> + <DeprecatedInterface> + <code><![CDATA[private]]></code> + </DeprecatedInterface> + <DeprecatedMethod> + <code><![CDATA[hasAnnotation]]></code> + <code><![CDATA[hasAnnotation]]></code> + </DeprecatedMethod> <NoInterfaceProperties> <code><![CDATA[$this->request->server]]></code> </NoInterfaceProperties> </file> - <file src="core/routes.php"> - <InvalidScope> - <code>$this</code> - <code><![CDATA[$this->create('core_ajax_update', '/core/ajax/update.php')]]></code> - </InvalidScope> - </file> - <file src="core/templates/layout.public.php"> - <UndefinedInterfaceMethod> - <code>getIcon</code> - </UndefinedInterfaceMethod> - </file> - <file src="lib/autoloader.php"> - <RedundantCondition> - <code><![CDATA[$this->memoryCache]]></code> - </RedundantCondition> + <file src="core/Migrations/Version13000Date20170718121200.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="core/Migrations/Version14000Date20180404140050.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="core/Migrations/Version16000Date20190427105638.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="core/Migrations/Version18000Date20190920085628.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="core/Migrations/Version20000Date20201109081918.php"> + <DeprecatedMethod> + <code><![CDATA[execute]]></code> + <code><![CDATA[execute]]></code> + </DeprecatedMethod> + </file> + <file src="core/Migrations/Version21000Date20201120141228.php"> + <DeprecatedMethod> + <code><![CDATA[changeColumn]]></code> + <code><![CDATA[changeColumn]]></code> + <code><![CDATA[changeColumn]]></code> + <code><![CDATA[changeColumn]]></code> + <code><![CDATA[changeColumn]]></code> + </DeprecatedMethod> + </file> + <file src="core/Service/LoginFlowV2Service.php"> + <DeprecatedClass> + <code><![CDATA[IToken::DO_NOT_REMEMBER]]></code> + <code><![CDATA[IToken::PERMANENT_TOKEN]]></code> + </DeprecatedClass> + </file> + <file src="core/ajax/update.php"> + <DeprecatedMethod> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> + </DeprecatedMethod> + </file> + <file src="cron.php"> + <DeprecatedMethod> + <code><![CDATA[OC_JSON::error(['data' => ['message' => 'Background jobs disabled!']])]]></code> + <code><![CDATA[OC_JSON::error(['data' => ['message' => 'Backgroundjobs are using system cron!']])]]></code> + <code><![CDATA[OC_JSON::success()]]></code> + </DeprecatedMethod> </file> <file src="lib/base.php"> <InvalidArgument> - <code>$restrictions</code> + <code><![CDATA[$restrictions]]></code> </InvalidArgument> </file> <file src="lib/private/Activity/Manager.php"> @@ -1459,121 +3298,72 @@ <code><![CDATA[$this->settings]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>ActivitySettings[]</code> + <code><![CDATA[ActivitySettings[]]]></code> </MoreSpecificReturnType> </file> <file src="lib/private/AllConfig.php"> <MoreSpecificImplementedParamType> - <code>$key</code> + <code><![CDATA[$key]]></code> </MoreSpecificImplementedParamType> - <TypeDoesNotContainType> - <code>!is_array($userIds)</code> - </TypeDoesNotContainType> - </file> - <file src="lib/private/App/AppManager.php"> - <LessSpecificImplementedReturnType> - <code>array</code> - <code>array</code> - </LessSpecificImplementedReturnType> - </file> - <file src="lib/private/App/AppStore/Fetcher/Fetcher.php"> - <TooManyArguments> - <code>fetch</code> - </TooManyArguments> </file> <file src="lib/private/App/DependencyAnalyzer.php"> <InvalidNullableReturnType> - <code>bool</code> + <code><![CDATA[bool]]></code> </InvalidNullableReturnType> <NullableReturnStatement> - <code>version_compare($first, $second, $operator)</code> + <code><![CDATA[version_compare($first, $second, $operator)]]></code> </NullableReturnStatement> </file> - <file src="lib/private/App/InfoParser.php"> - <InvalidArrayOffset> - <code>$array[$element][]</code> - <code>$array[$element][]</code> - </InvalidArrayOffset> - <InvalidReturnStatement> - <code>(string)$xml</code> - </InvalidReturnStatement> - <InvalidReturnType> - <code>array</code> - </InvalidReturnType> - </file> <file src="lib/private/AppConfig.php"> <NullableReturnStatement> <code><![CDATA[$this->fastCache[$app][$key] ?? $default]]></code> </NullableReturnStatement> </file> - <file src="lib/private/AppFramework/Bootstrap/Coordinator.php"> - <InvalidPropertyAssignmentValue> - <code><![CDATA[$this->bootedApps]]></code> - </InvalidPropertyAssignmentValue> - </file> <file src="lib/private/AppFramework/Bootstrap/FunctionInjector.php"> <UndefinedMethod> - <code>getName</code> + <code><![CDATA[getName]]></code> </UndefinedMethod> </file> <file src="lib/private/AppFramework/DependencyInjection/DIContainer.php"> - <ImplementedReturnTypeMismatch> - <code>boolean|null</code> - </ImplementedReturnTypeMismatch> <InvalidReturnStatement> <code><![CDATA[$this->server]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>\OCP\IServerContainer</code> + <code><![CDATA[\OCP\IServerContainer]]></code> </InvalidReturnType> - <UndefinedInterfaceMethod> - <code>getAppDataDir</code> - </UndefinedInterfaceMethod> </file> <file src="lib/private/AppFramework/Http/Dispatcher.php"> - <NoInterfaceProperties> - <code><![CDATA[$this->request->method]]></code> - </NoInterfaceProperties> <NullArgument> - <code>null</code> + <code><![CDATA[null]]></code> </NullArgument> </file> <file src="lib/private/AppFramework/Http/Output.php"> <InvalidReturnStatement> - <code>@readfile($path)</code> - <code>http_response_code()</code> + <code><![CDATA[@readfile($path)]]></code> + <code><![CDATA[http_response_code()]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>bool</code> - <code>int</code> + <code><![CDATA[bool]]></code> + <code><![CDATA[int]]></code> </InvalidReturnType> </file> <file src="lib/private/AppFramework/Http/Request.php"> <NullableReturnStatement> - <code>$name</code> - <code>$remoteAddress</code> <code><![CDATA[$this->getOverwriteHost()]]></code> - <code><![CDATA[$this->method]]></code> - <code>$uri</code> <code><![CDATA[isset($this->cookies[$key]) ? $this->cookies[$key] : null]]></code> <code><![CDATA[isset($this->env[$key]) ? $this->env[$key] : null]]></code> <code><![CDATA[isset($this->files[$key]) ? $this->files[$key] : null]]></code> </NullableReturnStatement> <RedundantCondition> - <code>\is_array($params)</code> + <code><![CDATA[\is_array($params)]]></code> </RedundantCondition> <UndefinedFunction> - <code>\Sabre\HTTP\decodePath($pathInfo)</code> + <code><![CDATA[\Sabre\HTTP\decodePath($pathInfo)]]></code> </UndefinedFunction> </file> - <file src="lib/private/AppFramework/Logger.php"> - <InvalidReturnType> - <code>log</code> - </InvalidReturnType> - </file> <file src="lib/private/AppFramework/Middleware/OCSMiddleware.php"> <InternalMethod> - <code>setOCSVersion</code> + <code><![CDATA[setOCSVersion]]></code> </InternalMethod> </file> <file src="lib/private/AppFramework/Middleware/Security/CORSMiddleware.php"> @@ -1587,69 +3377,20 @@ <code><![CDATA[$this->request->server]]></code> </NoInterfaceProperties> <UndefinedClass> - <code>\OCA\Talk\Controller\PageController</code> + <code><![CDATA[\OCA\Talk\Controller\PageController]]></code> </UndefinedClass> </file> - <file src="lib/private/AppFramework/Routing/RouteConfig.php"> - <InvalidArrayOffset> - <code><![CDATA[$action['url-postfix']]]></code> - </InvalidArrayOffset> - </file> <file src="lib/private/AppFramework/Services/AppConfig.php"> <MoreSpecificImplementedParamType> - <code>$default</code> + <code><![CDATA[$default]]></code> </MoreSpecificImplementedParamType> </file> <file src="lib/private/AppFramework/Utility/SimpleContainer.php"> - <LessSpecificReturnStatement> - <code><![CDATA[$class->newInstance()]]></code> - <code><![CDATA[$class->newInstanceArgs(array_map(function (ReflectionParameter $parameter) { - $parameterType = $parameter->getType(); - - $resolveName = $parameter->getName(); - - // try to find out if it is a class or a simple parameter - if ($parameterType !== null && ($parameterType instanceof ReflectionNamedType) && !$parameterType->isBuiltin()) { - $resolveName = $parameterType->getName(); - } - - try { - $builtIn = $parameter->hasType() && ($parameter->getType() instanceof ReflectionNamedType) - && $parameter->getType()->isBuiltin(); - return $this->query($resolveName, !$builtIn); - } catch (QueryException $e) { - // Service not found, use the default value when available - if ($parameter->isDefaultValueAvailable()) { - return $parameter->getDefaultValue(); - } - - if ($parameterType !== null && ($parameterType instanceof ReflectionNamedType) && !$parameterType->isBuiltin()) { - $resolveName = $parameter->getName(); - try { - return $this->query($resolveName); - } catch (QueryException $e2) { - // Pass null if typed and nullable - if ($parameter->allowsNull() && ($parameterType instanceof ReflectionNamedType)) { - return null; - } - - // don't lose the error we got while trying to query by type - throw new QueryException($e->getMessage(), (int) $e->getCode(), $e); - } - } - - throw $e; - } - }, $constructor->getParameters()))]]></code> - </LessSpecificReturnStatement> <MissingTemplateParam> - <code>ArrayAccess</code> + <code><![CDATA[ArrayAccess]]></code> </MissingTemplateParam> - <MoreSpecificReturnType> - <code>\stdClass</code> - </MoreSpecificReturnType> <RedundantCast> - <code><![CDATA[(int) $e->getCode()]]></code> + <code><![CDATA[(int)$e->getCode()]]></code> </RedundantCast> </file> <file src="lib/private/Archive/TAR.php"> @@ -1659,27 +3400,27 @@ </file> <file src="lib/private/Authentication/LoginCredentials/Store.php"> <RedundantCondition> - <code>$trySession</code> + <code><![CDATA[$trySession]]></code> </RedundantCondition> </file> <file src="lib/private/Authentication/Token/PublicKeyToken.php"> <UndefinedMagicMethod> - <code>getExpires</code> - <code>getLastCheck</code> - <code>getLoginName</code> - <code>getName</code> - <code>getPassword</code> - <code>getRemember</code> - <code>getScope</code> - <code>setExpires</code> - <code>setLastCheck</code> - <code>setName</code> - <code>setPassword</code> - <code>setPasswordInvalid</code> - <code>setScope</code> - <code>setScope</code> - <code>setToken</code> - <code>setType</code> + <code><![CDATA[getExpires]]></code> + <code><![CDATA[getLastCheck]]></code> + <code><![CDATA[getLoginName]]></code> + <code><![CDATA[getName]]></code> + <code><![CDATA[getPassword]]></code> + <code><![CDATA[getRemember]]></code> + <code><![CDATA[getScope]]></code> + <code><![CDATA[setExpires]]></code> + <code><![CDATA[setLastCheck]]></code> + <code><![CDATA[setName]]></code> + <code><![CDATA[setPassword]]></code> + <code><![CDATA[setPasswordInvalid]]></code> + <code><![CDATA[setScope]]></code> + <code><![CDATA[setScope]]></code> + <code><![CDATA[setToken]]></code> + <code><![CDATA[setType]]></code> </UndefinedMagicMethod> </file> <file src="lib/private/Authentication/TwoFactorAuth/ProviderSet.php"> @@ -1688,13 +3429,13 @@ </InvalidArgument> <InvalidPropertyAssignmentValue> <code><![CDATA[$this->providers]]></code> - <code>[]</code> + <code><![CDATA[[]]]></code> </InvalidPropertyAssignmentValue> <InvalidReturnStatement> <code><![CDATA[$this->providers]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>IProvider[]</code> + <code><![CDATA[IProvider[]]]></code> </InvalidReturnType> <UndefinedInterfaceMethod> <code><![CDATA[$this->providers]]></code> @@ -1702,13 +3443,13 @@ </file> <file src="lib/private/Cache/CappedMemoryCache.php"> <MissingTemplateParam> - <code>\ArrayAccess</code> + <code><![CDATA[\ArrayAccess]]></code> </MissingTemplateParam> </file> <file src="lib/private/Cache/File.php"> <LessSpecificImplementedReturnType> - <code>bool|mixed</code> - <code>bool|mixed</code> + <code><![CDATA[bool|mixed]]></code> + <code><![CDATA[bool|mixed]]></code> </LessSpecificImplementedReturnType> </file> <file src="lib/private/Calendar/Manager.php"> @@ -1730,7 +3471,7 @@ )]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>ICreateFromString[]</code> + <code><![CDATA[ICreateFromString[]]]></code> </MoreSpecificReturnType> <NamedArgumentNotAllowed> <code><![CDATA[array_map(function ($registration) use ($principalUri, $calendarUris) { @@ -1750,17 +3491,17 @@ </file> <file src="lib/private/Command/CallableJob.php"> <ParamNameMismatch> - <code>$serializedCallable</code> + <code><![CDATA[$serializedCallable]]></code> </ParamNameMismatch> </file> <file src="lib/private/Command/ClosureJob.php"> <InvalidArgument> - <code>[LaravelClosure::class]</code> + <code><![CDATA[[LaravelClosure::class]]]></code> </InvalidArgument> </file> <file src="lib/private/Comments/Manager.php"> <RedundantCast> - <code>(string)$id</code> + <code><![CDATA[(string)$id]]></code> </RedundantCast> </file> <file src="lib/private/Config.php"> @@ -1769,8 +3510,8 @@ <code><![CDATA[$this->set($key, $value)]]></code> </InvalidOperand> <UndefinedVariable> - <code>$CONFIG</code> - <code>$CONFIG</code> + <code><![CDATA[$CONFIG]]></code> + <code><![CDATA[$CONFIG]]></code> </UndefinedVariable> </file> <file src="lib/private/Console/Application.php"> @@ -1780,12 +3521,12 @@ </file> <file src="lib/private/ContactsManager.php"> <InvalidArgument> - <code>$searchOptions</code> + <code><![CDATA[$searchOptions]]></code> </InvalidArgument> </file> <file src="lib/private/DB/AdapterMySQL.php"> <InternalMethod> - <code>getParams</code> + <code><![CDATA[getParams]]></code> </InternalMethod> <InvalidArrayOffset> <code><![CDATA[$params['collation']]]></code> @@ -1793,10 +3534,10 @@ </file> <file src="lib/private/DB/Connection.php"> <InternalMethod> - <code>getParams</code> + <code><![CDATA[getParams]]></code> </InternalMethod> <InvalidArgument> - <code>$params</code> + <code><![CDATA[$params]]></code> </InvalidArgument> <InvalidArrayOffset> <code><![CDATA[$params['adapter']]]></code> @@ -1808,15 +3549,15 @@ <code><![CDATA[is_int($original->getCode())]]></code> </RedundantCondition> <TypeDoesNotContainType> - <code>0</code> + <code><![CDATA[0]]></code> </TypeDoesNotContainType> </file> <file src="lib/private/DB/MigrationService.php"> <LessSpecificReturnStatement> - <code>$s</code> + <code><![CDATA[$s]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>IMigrationStep</code> + <code><![CDATA[IMigrationStep]]></code> </MoreSpecificReturnType> </file> <file src="lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php"> @@ -1824,13 +3565,13 @@ <code><![CDATA[$this->functionBuilder->lower($x)]]></code> </ImplicitToStringCast> <InvalidArgument> - <code>$y</code> - <code>$y</code> + <code><![CDATA[$y]]></code> + <code><![CDATA[$y]]></code> </InvalidArgument> </file> <file src="lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php"> <InternalMethod> - <code>getParams</code> + <code><![CDATA[getParams]]></code> </InternalMethod> <InvalidArrayOffset> <code><![CDATA[$params['collation']]]></code> @@ -1838,22 +3579,21 @@ </file> <file src="lib/private/DB/QueryBuilder/QueryBuilder.php"> <InvalidNullableReturnType> - <code>string</code> + <code><![CDATA[string]]></code> </InvalidNullableReturnType> <NullableReturnStatement> - <code>$alias</code> + <code><![CDATA[$alias]]></code> </NullableReturnStatement> <ParamNameMismatch> - <code>$groupBys</code> - <code>$selects</code> + <code><![CDATA[$selects]]></code> </ParamNameMismatch> </file> <file src="lib/private/DB/QueryBuilder/QuoteHelper.php"> <InvalidNullableReturnType> - <code>string</code> + <code><![CDATA[string]]></code> </InvalidNullableReturnType> <NullableReturnStatement> - <code>$string</code> + <code><![CDATA[$string]]></code> </NullableReturnStatement> </file> <file src="lib/private/DateTimeFormatter.php"> @@ -1868,40 +3608,33 @@ ])]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>string</code> + <code><![CDATA[string]]></code> </InvalidReturnType> </file> <file src="lib/private/DateTimeZone.php"> <InvalidScalarArgument> - <code>$timestamp</code> + <code><![CDATA[$timestamp]]></code> </InvalidScalarArgument> </file> <file src="lib/private/Diagnostics/Query.php"> <ImplementedReturnTypeMismatch> - <code>float</code> + <code><![CDATA[float]]></code> </ImplementedReturnTypeMismatch> </file> <file src="lib/private/Diagnostics/QueryLogger.php"> <InvalidArgument> - <code>microtime(true)</code> + <code><![CDATA[microtime(true)]]></code> </InvalidArgument> - <InvalidReturnType> - <code>stopQuery</code> - </InvalidReturnType> </file> <file src="lib/private/DirectEditing/Manager.php"> - <InvalidReturnStatement> - <code><![CDATA[$query->execute()]]></code> - </InvalidReturnStatement> <InvalidReturnType> - <code>TemplateResponse</code> - <code>int</code> + <code><![CDATA[TemplateResponse]]></code> </InvalidReturnType> <UndefinedMethod> - <code>$template</code> - <code>$template</code> - <code>$template</code> - <code>$template</code> + <code><![CDATA[$template]]></code> + <code><![CDATA[$template]]></code> + <code><![CDATA[$template]]></code> + <code><![CDATA[$template]]></code> </UndefinedMethod> </file> <file src="lib/private/DirectEditing/Token.php"> @@ -1909,35 +3642,27 @@ <code><![CDATA[$this->manager->getFileForToken($this->data['user_id'], $this->data['file_id'], $this->data['file_path'])]]></code> </LessSpecificReturnStatement> <UndefinedMethod> - <code>getShareForToken</code> + <code><![CDATA[getShareForToken]]></code> </UndefinedMethod> </file> - <file src="lib/private/Encryption/File.php"> - <LessSpecificReturnStatement> - <code><![CDATA[['users' => $uniqueUserIds, 'public' => $public]]]></code> - </LessSpecificReturnStatement> - <MoreSpecificReturnType> - <code>array{users: string[], public: bool}</code> - </MoreSpecificReturnType> - </file> <file src="lib/private/Encryption/Keys/Storage.php"> <InvalidNullableReturnType> - <code>deleteUserKey</code> + <code><![CDATA[deleteUserKey]]></code> </InvalidNullableReturnType> <NullArgument> - <code>null</code> - <code>null</code> - <code>null</code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> </NullArgument> </file> <file src="lib/private/Encryption/Manager.php"> <ImplementedReturnTypeMismatch> - <code>bool</code> + <code><![CDATA[bool]]></code> </ImplementedReturnTypeMismatch> </file> <file src="lib/private/Federation/CloudFederationProviderManager.php"> <ParamNameMismatch> - <code>$providerId</code> + <code><![CDATA[$providerId]]></code> </ParamNameMismatch> </file> <file src="lib/private/Files/AppData/AppData.php"> @@ -1945,61 +3670,45 @@ <code><![CDATA[$this->folder]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>Folder</code> + <code><![CDATA[Folder]]></code> </MoreSpecificReturnType> </file> <file src="lib/private/Files/Cache/Cache.php"> - <InvalidArgument> - <code>$parentData</code> - </InvalidArgument> <InvalidNullableReturnType> - <code>array</code> + <code><![CDATA[array]]></code> </InvalidNullableReturnType> - <InvalidScalarArgument> - <code>$path</code> - <code>\OC_Util::normalizeUnicode($path)</code> - </InvalidScalarArgument> <NullableReturnStatement> - <code>null</code> - <code>null</code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> </NullableReturnStatement> - <ParamNameMismatch> - <code>$searchQuery</code> - </ParamNameMismatch> </file> <file src="lib/private/Files/Cache/FailedCache.php"> <InvalidReturnStatement> - <code>[]</code> + <code><![CDATA[[]]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>getIncomplete</code> - <code>insert</code> - <code>put</code> + <code><![CDATA[getIncomplete]]></code> + <code><![CDATA[insert]]></code> + <code><![CDATA[put]]></code> </InvalidReturnType> </file> <file src="lib/private/Files/Cache/HomeCache.php"> <FalsableReturnStatement> - <code>$data</code> + <code><![CDATA[$data]]></code> </FalsableReturnStatement> <MoreSpecificImplementedParamType> - <code>$file</code> - <code>$file</code> + <code><![CDATA[$file]]></code> + <code><![CDATA[$file]]></code> </MoreSpecificImplementedParamType> </file> <file src="lib/private/Files/Cache/Scanner.php"> <InvalidArgument> - <code>self::SCAN_RECURSIVE_INCOMPLETE</code> + <code><![CDATA[self::SCAN_RECURSIVE_INCOMPLETE]]></code> </InvalidArgument> - <InvalidReturnStatement> - <code>$existingChildren</code> - </InvalidReturnStatement> - <InvalidReturnType> - <code>array[]</code> - </InvalidReturnType> </file> <file src="lib/private/Files/Cache/Storage.php"> <InvalidNullableReturnType> - <code>array</code> + <code><![CDATA[array]]></code> </InvalidNullableReturnType> <NullableReturnStatement> <code><![CDATA[self::getGlobalCache()->getStorageInfo($storageId)]]></code> @@ -2012,16 +3721,13 @@ </file> <file src="lib/private/Files/Cache/Wrapper/CacheWrapper.php"> <LessSpecificImplementedReturnType> - <code>array</code> - <code>array</code> + <code><![CDATA[array]]></code> + <code><![CDATA[array]]></code> </LessSpecificImplementedReturnType> - <ParamNameMismatch> - <code>$searchQuery</code> - </ParamNameMismatch> </file> <file src="lib/private/Files/Config/MountProviderCollection.php"> <InvalidOperand> - <code>$user</code> + <code><![CDATA[$user]]></code> </InvalidOperand> <RedundantCondition> <code><![CDATA[get_class($provider) !== 'OCA\Files_Sharing\MountProvider']]></code> @@ -2032,17 +3738,17 @@ </file> <file src="lib/private/Files/Config/UserMountCache.php"> <InvalidReturnType> - <code>remoteStorageMounts</code> - <code>removeUserStorageMount</code> + <code><![CDATA[remoteStorageMounts]]></code> + <code><![CDATA[removeUserStorageMount]]></code> </InvalidReturnType> <LessSpecificImplementedReturnType> - <code>array</code> + <code><![CDATA[array]]></code> </LessSpecificImplementedReturnType> <LessSpecificReturnStatement> <code><![CDATA[$this->cacheInfoCache[$fileId]]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>array{int, string, int}</code> + <code><![CDATA[array{int, string, int}]]></code> </MoreSpecificReturnType> </file> <file src="lib/private/Files/Filesystem.php"> @@ -2052,65 +3758,52 @@ <code><![CDATA[self::getMountManager()->findByStorageId($id)]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>Mount\MountPoint[]</code> - <code>Mount\MountPoint[]</code> - <code>\OC\Files\Storage\Storage|null</code> + <code><![CDATA[Mount\MountPoint[]]]></code> + <code><![CDATA[Mount\MountPoint[]]]></code> + <code><![CDATA[\OC\Files\Storage\Storage|null]]></code> </MoreSpecificReturnType> - <TooManyArguments> - <code>addStorageWrapper</code> - </TooManyArguments> </file> <file src="lib/private/Files/Mount/MountPoint.php"> <UndefinedInterfaceMethod> - <code>wrap</code> + <code><![CDATA[wrap]]></code> </UndefinedInterfaceMethod> </file> - <file src="lib/private/Files/Mount/ObjectHomeMountProvider.php"> - <InvalidNullableReturnType> - <code>\OCP\Files\Mount\IMountPoint</code> - </InvalidNullableReturnType> - <NullableReturnStatement> - <code>null</code> - </NullableReturnStatement> - </file> <file src="lib/private/Files/Node/File.php"> <InvalidReturnStatement> <code><![CDATA[$this->view->hash($type, $this->path, $raw)]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>string</code> + <code><![CDATA[string]]></code> </InvalidReturnType> </file> <file src="lib/private/Files/Node/Folder.php"> <LessSpecificReturnStatement> - <code><![CDATA[$this->root->get($this->getFullPath($path))]]></code> <code><![CDATA[array_map(function (FileInfo $file) { return $this->createNode($file->getPath(), $file); }, $files)]]></code> </LessSpecificReturnStatement> <MoreSpecificImplementedParamType> - <code>$node</code> + <code><![CDATA[$node]]></code> </MoreSpecificImplementedParamType> <MoreSpecificReturnType> - <code>\OC\Files\Node\Node</code> - <code>\OC\Files\Node\Node[]</code> + <code><![CDATA[\OC\Files\Node\Node[]]]></code> </MoreSpecificReturnType> </file> <file src="lib/private/Files/Node/HookConnector.php"> <UndefinedInterfaceMethod> - <code>emit</code> - <code>emit</code> - <code>emit</code> - <code>emit</code> - <code>emit</code> - <code>emit</code> - <code>emit</code> - <code>emit</code> - <code>emit</code> - <code>emit</code> - <code>emit</code> - <code>emit</code> - <code>emit</code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> </UndefinedInterfaceMethod> </file> <file src="lib/private/Files/Node/LazyFolder.php"> @@ -2120,30 +3813,30 @@ </file> <file src="lib/private/Files/Node/LazyUserFolder.php"> <LessSpecificReturnStatement> - <code>$node</code> + <code><![CDATA[$node]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>Folder</code> + <code><![CDATA[Folder]]></code> </MoreSpecificReturnType> </file> <file src="lib/private/Files/Node/Node.php"> <InvalidNullableReturnType> - <code>FileInfo</code> + <code><![CDATA[FileInfo]]></code> </InvalidNullableReturnType> <InvalidReturnType> - <code>getChecksum</code> + <code><![CDATA[getChecksum]]></code> </InvalidReturnType> <LessSpecificReturnStatement> <code><![CDATA[$this->parent]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>INode|IRootFolder</code> + <code><![CDATA[INode|IRootFolder]]></code> </MoreSpecificReturnType> <NullableReturnStatement> <code><![CDATA[$this->fileInfo]]></code> </NullableReturnStatement> <ParamNameMismatch> - <code>$type</code> + <code><![CDATA[$type]]></code> </ParamNameMismatch> <UndefinedInterfaceMethod> <code><![CDATA[$this->fileInfo]]></code> @@ -2152,119 +3845,64 @@ </file> <file src="lib/private/Files/Node/Root.php"> <LessSpecificReturnStatement> - <code>$folders</code> - <code><![CDATA[$this->createNode($fullPath, $fileInfo, false)]]></code> + <code><![CDATA[$folders]]></code> <code><![CDATA[$this->mountManager->findByNumericId($numericId)]]></code> <code><![CDATA[$this->mountManager->findByStorageId($storageId)]]></code> <code><![CDATA[$this->mountManager->findIn($mountPoint)]]></code> <code><![CDATA[$this->user]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>MountPoint[]</code> - <code>Node</code> - <code>\OC\Files\Mount\MountPoint[]</code> - <code>\OC\Files\Mount\MountPoint[]</code> - <code>\OC\User\User</code> + <code><![CDATA[MountPoint[]]]></code> + <code><![CDATA[\OC\Files\Mount\MountPoint[]]]></code> + <code><![CDATA[\OC\Files\Mount\MountPoint[]]]></code> + <code><![CDATA[\OC\User\User]]></code> </MoreSpecificReturnType> <NullableReturnStatement> <code><![CDATA[$this->user]]></code> </NullableReturnStatement> <UndefinedMethod> - <code>remove</code> + <code><![CDATA[remove]]></code> </UndefinedMethod> </file> - <file src="lib/private/Files/ObjectStore/ObjectStoreStorage.php"> - <InvalidScalarArgument> - <code>$source</code> - </InvalidScalarArgument> - </file> <file src="lib/private/Files/ObjectStore/S3ConnectionTrait.php"> <InternalClass> - <code>ClientResolver::_default_signature_provider()</code> - <code>ClientResolver::_default_signature_provider()</code> + <code><![CDATA[ClientResolver::_default_signature_provider()]]></code> + <code><![CDATA[ClientResolver::_default_signature_provider()]]></code> </InternalClass> <InternalMethod> - <code>ClientResolver::_default_signature_provider()</code> + <code><![CDATA[ClientResolver::_default_signature_provider()]]></code> </InternalMethod> <UndefinedFunction> - <code>Promise\promise_for( - new Credentials($key, $secret) - )</code> <code><![CDATA[\Aws\or_chain([self::class, 'legacySignatureProvider'], ClientResolver::_default_signature_provider())]]></code> </UndefinedFunction> </file> <file src="lib/private/Files/ObjectStore/S3ObjectTrait.php"> <InternalMethod> - <code>upload</code> + <code><![CDATA[upload]]></code> </InternalMethod> <UndefinedFunction> - <code>\Aws\serialize($command)</code> + <code><![CDATA[\Aws\serialize($command)]]></code> </UndefinedFunction> </file> - <file src="lib/private/Files/ObjectStore/S3Signature.php"> - <NullArgument> - <code>null</code> - </NullArgument> - </file> - <file src="lib/private/Files/ObjectStore/StorageObjectStore.php"> - <InvalidReturnType> - <code>string</code> - </InvalidReturnType> - </file> <file src="lib/private/Files/Storage/Common.php"> - <ImplementedReturnTypeMismatch> - <code>string|false</code> - </ImplementedReturnTypeMismatch> <InvalidOperand> - <code>!$permissions</code> + <code><![CDATA[!$permissions]]></code> <code><![CDATA[$this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file)]]></code> </InvalidOperand> - <NoInterfaceProperties> - <code><![CDATA[$storage->cache]]></code> - <code><![CDATA[$storage->cache]]></code> - <code><![CDATA[$storage->propagator]]></code> - <code><![CDATA[$storage->propagator]]></code> - <code><![CDATA[$storage->scanner]]></code> - <code><![CDATA[$storage->scanner]]></code> - <code><![CDATA[$storage->updater]]></code> - <code><![CDATA[$storage->updater]]></code> - </NoInterfaceProperties> </file> <file src="lib/private/Files/Storage/DAV.php"> <InvalidClass> - <code>ArrayCache</code> - <code>ArrayCache</code> + <code><![CDATA[ArrayCache]]></code> + <code><![CDATA[ArrayCache]]></code> </InvalidClass> - <InvalidReturnStatement> - <code><![CDATA[$response->getBody()]]></code> - </InvalidReturnStatement> - <InvalidReturnType> - <code>fopen</code> - </InvalidReturnType> - <NullableReturnStatement> - <code>null</code> - </NullableReturnStatement> - </file> - <file src="lib/private/Files/Storage/FailedStorage.php"> - <InvalidReturnStatement> - <code>new FailedCache()</code> - <code>true</code> - </InvalidReturnStatement> - <InvalidReturnType> - <code>getCache</code> - <code>verifyPath</code> - </InvalidReturnType> </file> <file src="lib/private/Files/Storage/Local.php"> - <ImplicitToStringCast> - <code>$file</code> - </ImplicitToStringCast> <TypeDoesNotContainNull> - <code>$space === false || is_null($space)</code> - <code>is_null($space)</code> + <code><![CDATA[$space === false || is_null($space)]]></code> + <code><![CDATA[is_null($space)]]></code> </TypeDoesNotContainNull> <TypeDoesNotContainType> - <code>$stat === false</code> + <code><![CDATA[$stat === false]]></code> </TypeDoesNotContainType> </file> <file src="lib/private/Files/Storage/LocalRootStorage.php"> @@ -2274,11 +3912,6 @@ </NoInterfaceProperties> </file> <file src="lib/private/Files/Storage/Wrapper/Encoding.php"> - <InvalidArgument> - <code>\Normalizer::FORM_C</code> - <code>\Normalizer::FORM_C</code> - <code>\Normalizer::FORM_D</code> - </InvalidArgument> <UndefinedInterfaceMethod> <code><![CDATA[$this->namesCache]]></code> <code><![CDATA[$this->namesCache]]></code> @@ -2300,80 +3933,36 @@ </UndefinedInterfaceMethod> </file> <file src="lib/private/Files/Storage/Wrapper/Encryption.php"> - <InvalidOperand> - <code>$result</code> - <code>$result</code> - <code><![CDATA[$this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file, false, $isRename)]]></code> - </InvalidOperand> <InvalidReturnStatement> - <code>$newUnencryptedSize</code> - <code>$result</code> + <code><![CDATA[$result]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>bool</code> - <code>int</code> + <code><![CDATA[int]]></code> </InvalidReturnType> <InvalidScalarArgument> - <code>$lastChunkPos</code> - <code>$size</code> + <code><![CDATA[$lastChunkPos]]></code> + <code><![CDATA[$size]]></code> </InvalidScalarArgument> </file> - <file src="lib/private/Files/Storage/Wrapper/Jail.php"> - <InvalidReturnStatement> - <code><![CDATA[$this->getWrapperStorage()->filetype($this->getUnjailedPath($path))]]></code> - </InvalidReturnStatement> - <InvalidReturnType> - <code>bool</code> - </InvalidReturnType> - </file> - <file src="lib/private/Files/Storage/Wrapper/Wrapper.php"> - <InvalidReturnStatement> - <code><![CDATA[$this->getWrapperStorage()->test()]]></code> - </InvalidReturnStatement> - <InvalidReturnType> - <code>true</code> - </InvalidReturnType> - </file> <file src="lib/private/Files/Stream/SeekableHttpStream.php"> <InvalidReturnType> - <code>stream_close</code> - <code>stream_flush</code> + <code><![CDATA[stream_close]]></code> + <code><![CDATA[stream_flush]]></code> </InvalidReturnType> </file> <file src="lib/private/Files/Template/TemplateManager.php"> <RedundantCondition> - <code>!$isDefaultTemplates</code> + <code><![CDATA[!$isDefaultTemplates]]></code> </RedundantCondition> </file> - <file src="lib/private/Files/Type/Detection.php"> - <ParamNameMismatch> - <code>$mimetype</code> - </ParamNameMismatch> - </file> - <file src="lib/private/Files/Type/Loader.php"> - <InvalidReturnStatement> - <code><![CDATA[$update->execute()]]></code> - </InvalidReturnStatement> - <InvalidReturnType> - <code>int</code> - </InvalidReturnType> - </file> - <file src="lib/private/Files/Utils/Scanner.php"> - <LessSpecificReturnStatement> - <code>$mounts</code> - </LessSpecificReturnStatement> - <MoreSpecificReturnType> - <code>\OC\Files\Mount\MountPoint[]</code> - </MoreSpecificReturnType> - </file> <file src="lib/private/Files/View.php"> <InvalidScalarArgument> - <code>$mtime</code> + <code><![CDATA[$mtime]]></code> </InvalidScalarArgument> <UndefinedInterfaceMethod> - <code>acquireLock</code> - <code>changeLock</code> - <code>releaseLock</code> + <code><![CDATA[acquireLock]]></code> + <code><![CDATA[changeLock]]></code> + <code><![CDATA[releaseLock]]></code> </UndefinedInterfaceMethod> </file> <file src="lib/private/FullTextSearch/Model/IndexDocument.php"> @@ -2382,17 +3971,11 @@ </TypeDoesNotContainNull> </file> <file src="lib/private/Group/Group.php"> - <InvalidArgument> - <code>bool</code> - </InvalidArgument> - <InvalidOperand> - <code>$hide</code> - </InvalidOperand> <LessSpecificReturnStatement> - <code>$users</code> + <code><![CDATA[$users]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>\OC\User\User[]</code> + <code><![CDATA[\OC\User\User[]]]></code> </MoreSpecificReturnType> <RedundantCondition> <code><![CDATA[$this->emitter]]></code> @@ -2400,49 +3983,40 @@ <code><![CDATA[$this->emitter]]></code> </RedundantCondition> <UndefinedMethod> - <code>addToGroup</code> - <code>countUsersInGroup</code> - <code>deleteGroup</code> - <code>removeFromGroup</code> + <code><![CDATA[addToGroup]]></code> + <code><![CDATA[countUsersInGroup]]></code> + <code><![CDATA[deleteGroup]]></code> + <code><![CDATA[removeFromGroup]]></code> </UndefinedMethod> </file> <file src="lib/private/Group/Manager.php"> <LessSpecificReturnStatement> - <code>$groups</code> - <code>array_values($groups)</code> - <code>array_values($groups)</code> + <code><![CDATA[$groups]]></code> + <code><![CDATA[array_values($groups)]]></code> + <code><![CDATA[array_values($groups)]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>\OC\Group\Group[]</code> - <code>\OC\Group\Group[]</code> + <code><![CDATA[\OC\Group\Group[]]]></code> + <code><![CDATA[\OC\Group\Group[]]]></code> </MoreSpecificReturnType> <UndefinedInterfaceMethod> - <code>createGroup</code> - <code>getGroupDetails</code> - <code>isAdmin</code> + <code><![CDATA[createGroup]]></code> + <code><![CDATA[getGroupDetails]]></code> + <code><![CDATA[isAdmin]]></code> </UndefinedInterfaceMethod> </file> - <file src="lib/private/Http/Client/Response.php"> - <InvalidNullableReturnType> - <code>string|resource</code> - </InvalidNullableReturnType> - <NullableReturnStatement> - <code><![CDATA[$this->stream ? - $this->response->getBody()->detach(): - $this->response->getBody()->getContents()]]></code> - </NullableReturnStatement> + <file src="lib/private/InitialStateService.php"> + <UndefinedInterfaceMethod> + <code><![CDATA[query]]></code> + </UndefinedInterfaceMethod> </file> <file src="lib/private/Installer.php"> <InvalidArgument> - <code>false</code> - <code>false</code> + <code><![CDATA[false]]></code> + <code><![CDATA[false]]></code> </InvalidArgument> - <InvalidArrayOffset> - <code><![CDATA[$app['path']]]></code> - <code><![CDATA[$app['path']]]></code> - </InvalidArrayOffset> <NullArgument> - <code>null</code> + <code><![CDATA[null]]></code> </NullArgument> </file> <file src="lib/private/IntegrityCheck/Checker.php"> @@ -2452,96 +4026,51 @@ <code><![CDATA[$x509->getDN(true)['CN']]]></code> </InvalidArrayAccess> <UndefinedInterfaceMethod> - <code>getOnlyDefaultAliases</code> + <code><![CDATA[getOnlyDefaultAliases]]></code> </UndefinedInterfaceMethod> </file> <file src="lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php"> <MissingTemplateParam> - <code>ExcludeFileByNameFilterIterator</code> + <code><![CDATA[ExcludeFileByNameFilterIterator]]></code> </MissingTemplateParam> </file> <file src="lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php"> <MissingTemplateParam> - <code>ExcludeFoldersByPathFilterIterator</code> + <code><![CDATA[ExcludeFoldersByPathFilterIterator]]></code> </MissingTemplateParam> </file> <file src="lib/private/L10N/Factory.php"> <ImplementedReturnTypeMismatch> - <code>null|string</code> + <code><![CDATA[null|string]]></code> </ImplementedReturnTypeMismatch> <LessSpecificImplementedReturnType> - <code>array|mixed</code> + <code><![CDATA[array|mixed]]></code> </LessSpecificImplementedReturnType> </file> <file src="lib/private/LargeFileHelper.php"> <InvalidOperand> - <code>$matches[1]</code> + <code><![CDATA[$matches[1]]]></code> </InvalidOperand> </file> <file src="lib/private/Lockdown/Filesystem/NullCache.php"> - <InvalidNullableReturnType> - <code>get</code> - </InvalidNullableReturnType> - <InvalidReturnStatement> - <code>[]</code> - </InvalidReturnStatement> - <InvalidReturnType> - <code>getIncomplete</code> - </InvalidReturnType> - <NullableReturnStatement> - <code><![CDATA[$file !== '' ? null : - new CacheEntry([ - 'fileid' => -1, - 'parent' => -1, - 'name' => '', - 'path' => '', - 'size' => '0', - 'mtime' => time(), - 'storage_mtime' => time(), - 'etag' => '', - 'mimetype' => FileInfo::MIMETYPE_FOLDER, - 'mimepart' => 'httpd', - 'permissions' => Constants::PERMISSION_READ - ])]]></code> - </NullableReturnStatement> - </file> - <file src="lib/private/Lockdown/Filesystem/NullStorage.php"> - <InvalidNullableReturnType> - <code>getOwner</code> - <code>getPermissions</code> - </InvalidNullableReturnType> <InvalidReturnStatement> - <code>new IteratorDirectory([])</code> - <code>new NullCache()</code> + <code><![CDATA[[]]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>getCache</code> - <code>opendir</code> + <code><![CDATA[getIncomplete]]></code> </InvalidReturnType> - <NullableReturnStatement> - <code>null</code> - <code>null</code> - </NullableReturnStatement> - <TooManyArguments> - <code>new IteratorDirectory([])</code> - </TooManyArguments> </file> <file src="lib/private/Lockdown/LockdownManager.php"> <InvalidFunctionCall> - <code>$callback()</code> + <code><![CDATA[$callback()]]></code> </InvalidFunctionCall> <InvalidPropertyAssignmentValue> - <code>$sessionCallback</code> + <code><![CDATA[$sessionCallback]]></code> </InvalidPropertyAssignmentValue> </file> - <file src="lib/private/Log.php"> - <RedundantCondition> - <code>$request</code> - </RedundantCondition> - </file> <file src="lib/private/Log/File.php"> <TypeDoesNotContainNull> - <code>$limit === null</code> + <code><![CDATA[$limit === null]]></code> </TypeDoesNotContainNull> </file> <file src="lib/private/Log/LogDetails.php"> @@ -2551,8 +4080,8 @@ </file> <file src="lib/private/Log/Systemdlog.php"> <UndefinedFunction> - <code><![CDATA[sd_journal_send('PRIORITY='.$journal_level, - 'SYSLOG_IDENTIFIER='.$this->syslogId, + <code><![CDATA[sd_journal_send('PRIORITY=' . $journal_level, + 'SYSLOG_IDENTIFIER=' . $this->syslogId, 'MESSAGE=' . $this->logDetailsAsJSON($app, $message, $level))]]></code> </UndefinedFunction> </file> @@ -2561,84 +4090,76 @@ <code><![CDATA[apcu_add($this->getPrefix() . $key, $value, $ttl)]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>bool</code> + <code><![CDATA[bool]]></code> </InvalidReturnType> </file> <file src="lib/private/Memcache/Cache.php"> <LessSpecificImplementedReturnType> - <code>mixed</code> - <code>mixed</code> - <code>mixed</code> - <code>mixed</code> + <code><![CDATA[mixed]]></code> + <code><![CDATA[mixed]]></code> + <code><![CDATA[mixed]]></code> + <code><![CDATA[mixed]]></code> </LessSpecificImplementedReturnType> </file> + <file src="lib/private/Notification/Manager.php"> + <UndefinedClass> + <code><![CDATA[\OCA\Notifications\App]]></code> + </UndefinedClass> + </file> <file src="lib/private/Preview/BackgroundCleanupJob.php"> <InvalidReturnStatement> - <code>[]</code> + <code><![CDATA[[]]]></code> </InvalidReturnStatement> </file> <file src="lib/private/Preview/Generator.php"> - <InvalidArgument> - <code>$maxPreviewImage</code> - </InvalidArgument> <LessSpecificReturnType> - <code>null|string</code> + <code><![CDATA[null|string]]></code> </LessSpecificReturnType> - <MismatchingDocblockParamType> - <code>ISimpleFile</code> - </MismatchingDocblockParamType> - <UndefinedInterfaceMethod> - <code>height</code> - <code>height</code> - <code>preciseResizeCopy</code> - <code>resizeCopy</code> - <code>valid</code> - <code>width</code> - <code>width</code> - </UndefinedInterfaceMethod> </file> <file src="lib/private/Preview/ProviderV1Adapter.php"> <InvalidReturnStatement> - <code>$thumbnail === false ? null: $thumbnail</code> + <code><![CDATA[$thumbnail === false ? null: $thumbnail]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>?IImage</code> + <code><![CDATA[?IImage]]></code> </InvalidReturnType> </file> + <file src="lib/private/Profile/Actions/FediverseAction.php"> + <NoValue> + <code><![CDATA[$instance]]></code> + </NoValue> + <RedundantCondition> + <code><![CDATA[$instance === '']]></code> + </RedundantCondition> + </file> <file src="lib/private/RedisFactory.php"> <InvalidArgument> - <code>\RedisCluster::OPT_SLAVE_FAILOVER</code> + <code><![CDATA[\RedisCluster::OPT_SLAVE_FAILOVER]]></code> </InvalidArgument> </file> <file src="lib/private/Remote/Api/OCS.php"> <ImplementedReturnTypeMismatch> - <code>array</code> + <code><![CDATA[array]]></code> </ImplementedReturnTypeMismatch> </file> <file src="lib/private/Remote/Instance.php"> - <InvalidReturnStatement> - <code><![CDATA[$request->getBody()]]></code> - </InvalidReturnStatement> - <InvalidReturnType> - <code>bool|string</code> - </InvalidReturnType> <InvalidScalarArgument> - <code>$response</code> + <code><![CDATA[$response]]></code> </InvalidScalarArgument> </file> <file src="lib/private/Repair/Owncloud/CleanPreviews.php"> <InvalidArgument> - <code>false</code> + <code><![CDATA[false]]></code> </InvalidArgument> </file> <file src="lib/private/Repair/Owncloud/CleanPreviewsBackgroundJob.php"> <ParamNameMismatch> - <code>$arguments</code> + <code><![CDATA[$arguments]]></code> </ParamNameMismatch> </file> <file src="lib/private/Repair/Owncloud/MoveAvatarsBackgroundJob.php"> <ParamNameMismatch> - <code>$arguments</code> + <code><![CDATA[$arguments]]></code> </ParamNameMismatch> </file> <file src="lib/private/Repair/RemoveLinkShares.php"> @@ -2648,43 +4169,22 @@ </file> <file src="lib/private/Repair/RepairInvalidShares.php"> <ParamNameMismatch> - <code>$out</code> + <code><![CDATA[$out]]></code> </ParamNameMismatch> </file> <file src="lib/private/Repair/RepairMimeTypes.php"> <ParamNameMismatch> - <code>$out</code> + <code><![CDATA[$out]]></code> </ParamNameMismatch> </file> <file src="lib/private/Route/Router.php"> - <InvalidClass> - <code>\OC_APP</code> - </InvalidClass> <InvalidNullableReturnType> - <code>string</code> + <code><![CDATA[string]]></code> </InvalidNullableReturnType> <NullableReturnStatement> <code><![CDATA[$this->collectionName]]></code> </NullableReturnStatement> </file> - <file src="lib/private/Search.php"> - <RedundantCondition> - <code>$provider instanceof Provider</code> - </RedundantCondition> - </file> - <file src="lib/private/Search/Result/File.php"> - <InvalidPropertyAssignmentValue> - <code><![CDATA[$data->getId()]]></code> - <code><![CDATA[$data->getMtime()]]></code> - <code><![CDATA[$data->getPermissions()]]></code> - <code><![CDATA[$this->hasPreview($data)]]></code> - </InvalidPropertyAssignmentValue> - </file> - <file src="lib/private/Security/Bruteforce/Throttler.php"> - <NullArgument> - <code>null</code> - </NullArgument> - </file> <file src="lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php"> <NoInterfaceProperties> <code><![CDATA[$this->request->server]]></code> @@ -2695,51 +4195,34 @@ <code><![CDATA[\strlen($this->value)]]></code> </InvalidArgument> </file> - <file src="lib/private/Security/CredentialsManager.php"> - <InvalidReturnStatement> - <code><![CDATA[$qb->execute()]]></code> - <code><![CDATA[$qb->execute()]]></code> - </InvalidReturnStatement> - <InvalidReturnType> - <code>int</code> - <code>int</code> - </InvalidReturnType> - </file> <file src="lib/private/Security/Crypto.php"> <InternalMethod> - <code>decrypt</code> - <code>encrypt</code> - <code>setIV</code> - <code>setIV</code> - <code>setPassword</code> - <code>setPassword</code> + <code><![CDATA[decrypt]]></code> + <code><![CDATA[encrypt]]></code> + <code><![CDATA[setIV]]></code> + <code><![CDATA[setIV]]></code> + <code><![CDATA[setPassword]]></code> + <code><![CDATA[setPassword]]></code> </InternalMethod> </file> <file src="lib/private/Server.php"> <ImplementedReturnTypeMismatch> - <code>\OCP\Calendar\Resource\IManager</code> - <code>\OCP\Calendar\Room\IManager</code> - <code>\OCP\Files\Folder|null</code> + <code><![CDATA[\OCP\Files\Folder|null]]></code> </ImplementedReturnTypeMismatch> <LessSpecificReturnStatement> <code><![CDATA[$this->get(IFile::class)]]></code> <code><![CDATA[$this->get(IGroupManager::class)]]></code> - <code><![CDATA[$this->get(INavigationManager::class)]]></code> <code><![CDATA[$this->get(IUserManager::class)]]></code> <code><![CDATA[$this->get(IUserSession::class)]]></code> <code><![CDATA[$this->get(\OCP\Encryption\IManager::class)]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>\OC\Encryption\File</code> - <code>\OC\Encryption\Manager</code> - <code>\OC\Group\Manager</code> - <code>\OC\NavigationManager</code> - <code>\OC\User\Manager</code> - <code>\OC\User\Session</code> + <code><![CDATA[\OC\Encryption\File]]></code> + <code><![CDATA[\OC\Encryption\Manager]]></code> + <code><![CDATA[\OC\Group\Manager]]></code> + <code><![CDATA[\OC\User\Manager]]></code> + <code><![CDATA[\OC\User\Session]]></code> </MoreSpecificReturnType> - <UndefinedDocblockClass> - <code>\OC\OCSClient</code> - </UndefinedDocblockClass> </file> <file src="lib/private/ServerContainer.php"> <InvalidPropertyAssignmentValue> @@ -2751,12 +4234,12 @@ </file> <file src="lib/private/Session/Internal.php"> <MoreSpecificImplementedParamType> - <code>$value</code> + <code><![CDATA[$value]]></code> </MoreSpecificImplementedParamType> </file> <file src="lib/private/Session/Memory.php"> <MoreSpecificImplementedParamType> - <code>$value</code> + <code><![CDATA[$value]]></code> </MoreSpecificImplementedParamType> </file> <file src="lib/private/Setup.php"> @@ -2764,7 +4247,7 @@ <code><![CDATA[$type === 'pdo']]></code> </RedundantCondition> <UndefinedVariable> - <code>$vendor</code> + <code><![CDATA[$vendor]]></code> </UndefinedVariable> </file> <file src="lib/private/Setup/AbstractDatabase.php"> @@ -2784,324 +4267,182 @@ <code><![CDATA[$share->getId()]]></code> <code><![CDATA[(int)$data['id']]]></code> </InvalidArgument> - <TooManyArguments> - <code>set</code> - </TooManyArguments> - <UndefinedInterfaceMethod> - <code>getParent</code> - </UndefinedInterfaceMethod> </file> <file src="lib/private/Share20/Manager.php"> <InvalidArgument> - <code>$id</code> + <code><![CDATA[$id]]></code> </InvalidArgument> - <TooManyArguments> - <code>update</code> - </TooManyArguments> <UndefinedClass> - <code>\OCA\Circles\Api\v1\Circles</code> + <code><![CDATA[\OCA\Circles\Api\v1\Circles]]></code> </UndefinedClass> - <UndefinedInterfaceMethod> - <code>getChildren</code> - </UndefinedInterfaceMethod> </file> <file src="lib/private/Share20/ProviderFactory.php"> - <InvalidNullableReturnType> - <code>FederatedShareProvider</code> - <code>ShareByMailProvider</code> - </InvalidNullableReturnType> <InvalidReturnStatement> - <code>$provider</code> - <code>$provider</code> - <code><![CDATA[$this->shareByCircleProvider]]></code> + <code><![CDATA[$provider]]></code> + <code><![CDATA[$provider]]></code> </InvalidReturnStatement> <InvalidReturnType> - <code>getProviderForType</code> + <code><![CDATA[getProviderForType]]></code> </InvalidReturnType> - <NullableReturnStatement> - <code>null</code> - <code>null</code> - <code>null</code> - <code>null</code> - <code>null</code> - <code>null</code> - </NullableReturnStatement> - <ParamNameMismatch> - <code>$shareProviderClass</code> - </ParamNameMismatch> - <UndefinedClass> - <code>\OCA\Circles\ShareByCircleProvider</code> - </UndefinedClass> - <UndefinedDocblockClass> - <code>RoomShareProvider</code> - <code>\OCA\Circles\ShareByCircleProvider</code> - <code>\OCA\Talk\Share\RoomShareProvider</code> - <code>private $roomShareProvider = null;</code> - <code>private $shareByCircleProvider = null;</code> - </UndefinedDocblockClass> </file> <file src="lib/private/Share20/Share.php"> <LessSpecificReturnStatement> <code><![CDATA[$this->node]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>getNode</code> + <code><![CDATA[getNode]]></code> </MoreSpecificReturnType> </file> <file src="lib/private/Streamer.php"> <UndefinedInterfaceMethod> - <code>get</code> + <code><![CDATA[get]]></code> </UndefinedInterfaceMethod> </file> <file src="lib/private/SubAdmin.php"> <UndefinedInterfaceMethod> - <code>listen</code> - <code>listen</code> + <code><![CDATA[listen]]></code> + <code><![CDATA[listen]]></code> </UndefinedInterfaceMethod> </file> <file src="lib/private/Support/Subscription/Registry.php"> <UndefinedInterfaceMethod> - <code>getSupportedApps</code> + <code><![CDATA[getSupportedApps]]></code> </UndefinedInterfaceMethod> </file> <file src="lib/private/TagManager.php"> <InvalidNullableReturnType> - <code>\OCP\ITags</code> + <code><![CDATA[\OCP\ITags]]></code> </InvalidNullableReturnType> <NullableReturnStatement> - <code>null</code> + <code><![CDATA[null]]></code> </NullableReturnStatement> </file> <file src="lib/private/Tags.php"> <InvalidScalarArgument> - <code>$from</code> - <code>$names</code> + <code><![CDATA[$from]]></code> + <code><![CDATA[$names]]></code> </InvalidScalarArgument> <MoreSpecificImplementedParamType> - <code>$tag</code> + <code><![CDATA[$tag]]></code> </MoreSpecificImplementedParamType> </file> - <file src="lib/private/TempManager.php"> - <FalsableReturnStatement> - <code>false</code> - <code>false</code> - </FalsableReturnStatement> - </file> <file src="lib/private/Template/CSSResourceLocator.php"> <ParamNameMismatch> - <code>$style</code> - <code>$style</code> + <code><![CDATA[$style]]></code> + <code><![CDATA[$style]]></code> </ParamNameMismatch> </file> <file src="lib/private/Template/JSConfigHelper.php"> <NullArgument> - <code>null</code> - <code>null</code> + <code><![CDATA[null]]></code> + <code><![CDATA[null]]></code> </NullArgument> </file> <file src="lib/private/Template/JSResourceLocator.php"> <InvalidArgument> - <code>false</code> + <code><![CDATA[false]]></code> </InvalidArgument> <ParamNameMismatch> - <code>$script</code> - <code>$script</code> + <code><![CDATA[$script]]></code> + <code><![CDATA[$script]]></code> </ParamNameMismatch> </file> - <file src="lib/private/TemplateLayout.php"> - <InvalidParamDefault> - <code>string</code> - <code>string</code> - </InvalidParamDefault> - <InvalidScalarArgument> - <code>$appName</code> - <code>$appName</code> - </InvalidScalarArgument> - <UndefinedInterfaceMethod> - <code>getInitialStates</code> - </UndefinedInterfaceMethod> - </file> <file src="lib/private/URLGenerator.php"> <InvalidReturnStatement> - <code>$path</code> + <code><![CDATA[$path]]></code> </InvalidReturnStatement> </file> <file src="lib/private/User/Database.php"> <FalsableReturnStatement> - <code>false</code> + <code><![CDATA[false]]></code> </FalsableReturnStatement> </file> <file src="lib/private/User/Manager.php"> <ImplementedReturnTypeMismatch> - <code>IUser|false</code> + <code><![CDATA[IUser|false]]></code> </ImplementedReturnTypeMismatch> <InvalidArgument> - <code>$backend</code> + <code><![CDATA[$backend]]></code> </InvalidArgument> <UndefinedInterfaceMethod> - <code>createUser</code> - <code>getUsersForUserValueCaseInsensitive</code> + <code><![CDATA[createUser]]></code> + <code><![CDATA[getUsersForUserValueCaseInsensitive]]></code> </UndefinedInterfaceMethod> </file> <file src="lib/private/User/Session.php"> <ImplementedReturnTypeMismatch> - <code>boolean|null</code> + <code><![CDATA[boolean|null]]></code> </ImplementedReturnTypeMismatch> <NoInterfaceProperties> <code><![CDATA[$request->server]]></code> <code><![CDATA[$request->server]]></code> </NoInterfaceProperties> + <RedundantCondition> + <code><![CDATA[$this->manager instanceof PublicEmitter]]></code> + </RedundantCondition> </file> <file src="lib/private/User/User.php"> <UndefinedInterfaceMethod> - <code>emit</code> - <code>emit</code> - <code>emit</code> - <code>emit</code> - <code>emit</code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> + <code><![CDATA[emit]]></code> </UndefinedInterfaceMethod> </file> - <file src="lib/private/legacy/OC_API.php"> - <InvalidNullableReturnType> - <code>int</code> - </InvalidNullableReturnType> - <NullableReturnStatement> - <code>null</code> - </NullableReturnStatement> - </file> <file src="lib/private/legacy/OC_App.php"> <InvalidArgument> - <code>$groupsList</code> + <code><![CDATA[$groupsList]]></code> </InvalidArgument> - <InvalidArrayOffset> - <code><![CDATA[$dir['path']]]></code> - <code><![CDATA[$dir['url']]]></code> - </InvalidArrayOffset> <NullArgument> - <code>null</code> + <code><![CDATA[null]]></code> </NullArgument> - <TypeDoesNotContainNull> - <code>$appId === null</code> - <code>$appId === null</code> - </TypeDoesNotContainNull> - </file> - <file src="lib/private/legacy/OC_FileChunking.php"> - <UndefinedDocblockClass> - <code>\OC\InsufficientStorageException</code> - </UndefinedDocblockClass> - </file> - <file src="lib/private/legacy/OC_Files.php"> - <RedundantCondition> - <code>$getType === self::ZIP_DIR</code> - <code>$getType === self::ZIP_DIR</code> - </RedundantCondition> - <UndefinedInterfaceMethod> - <code>get</code> - <code>get</code> - </UndefinedInterfaceMethod> </file> <file src="lib/private/legacy/OC_Helper.php"> <InvalidArrayOffset> - <code>$matches[0][$last_match]</code> - <code>$matches[1][$last_match]</code> + <code><![CDATA[$matches[0][$last_match]]]></code> + <code><![CDATA[$matches[1][$last_match]]]></code> </InvalidArrayOffset> - <InvalidScalarArgument> - <code>$path</code> - </InvalidScalarArgument> <UndefinedInterfaceMethod> - <code>getQuota</code> + <code><![CDATA[getQuota]]></code> </UndefinedInterfaceMethod> </file> - <file src="lib/private/legacy/OC_Template.php"> - <InvalidReturnType> - <code>bool|string</code> - </InvalidReturnType> - </file> <file src="lib/private/legacy/OC_User.php"> <UndefinedClass> - <code>\Test\Util\User\Dummy</code> + <code><![CDATA[\Test\Util\User\Dummy]]></code> </UndefinedClass> </file> - <file src="lib/private/legacy/OC_Util.php"> - <InvalidReturnType> - <code>void</code> - </InvalidReturnType> - </file> - <file src="lib/public/AppFramework/ApiController.php"> - <NoInterfaceProperties> - <code><![CDATA[$this->request->server]]></code> - </NoInterfaceProperties> - </file> - <file src="lib/public/AppFramework/App.php"> - <InternalMethod> - <code><![CDATA[new RouteConfig($this->container, $router, $routes)]]></code> - </InternalMethod> - </file> - <file src="lib/public/AppFramework/Db/Entity.php"> - <InvalidNullableReturnType> - <code>string</code> - </InvalidNullableReturnType> - <NullableReturnStatement> - <code>$column</code> - </NullableReturnStatement> - </file> <file src="lib/public/AppFramework/Http/Response.php"> <LessSpecificReturnStatement> <code><![CDATA[array_merge($mergeWith, $this->headers)]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>array{X-Request-Id: string, Cache-Control: string, Content-Security-Policy: string, Feature-Policy: string, X-Robots-Tag: string, Last-Modified?: string, ETag?: string, ...H}</code> - </MoreSpecificReturnType> - </file> - <file src="lib/public/Authentication/Token/IToken.php"> - <AmbiguousConstantInheritance> - <code>DO_NOT_REMEMBER</code> - <code>PERMANENT_TOKEN</code> - <code>REMEMBER</code> - <code>TEMPORARY_TOKEN</code> - <code>WIPE_TOKEN</code> - </AmbiguousConstantInheritance> - </file> - <file src="lib/public/Color.php"> - <LessSpecificReturnStatement> - <code>$step</code> - </LessSpecificReturnStatement> - <MoreSpecificReturnType> - <code>array{0: int, 1: int, 2: int}</code> + <code><![CDATA[array{X-Request-Id: string, Cache-Control: string, Content-Security-Policy: string, Feature-Policy: string, X-Robots-Tag: string, Last-Modified?: string, ETag?: string, ...H}]]></code> </MoreSpecificReturnType> </file> - <file src="lib/public/Diagnostics/IQueryLogger.php"> - <LessSpecificImplementedReturnType> - <code>mixed</code> - </LessSpecificImplementedReturnType> - </file> - <file src="lib/public/EventDispatcher/GenericEvent.php"> - <MissingTemplateParam> - <code>ArrayAccess</code> - <code>IteratorAggregate</code> - </MissingTemplateParam> - </file> - <file src="lib/public/Files.php"> - <FalsableReturnStatement> - <code>\OC_App::getStorage($app)</code> - </FalsableReturnStatement> - </file> - <file src="lib/public/Files/Storage.php"> - <InvalidParamDefault> - <code>array</code> - </InvalidParamDefault> - </file> - <file src="lib/public/L10N/ILanguageIterator.php"> - <MissingTemplateParam> - <code>\Iterator</code> - </MissingTemplateParam> - </file> <file src="lib/public/Preview/BeforePreviewFetchedEvent.php"> <LessSpecificReturnStatement> <code><![CDATA[$this->mode]]></code> </LessSpecificReturnStatement> <MoreSpecificReturnType> - <code>null|IPreview::MODE_FILL|IPreview::MODE_COVER</code> + <code><![CDATA[null|IPreview::MODE_FILL|IPreview::MODE_COVER]]></code> </MoreSpecificReturnType> </file> + <file src="ocs-provider/index.php"> + <DeprecatedMethod> + <code><![CDATA[getAppManager]]></code> + <code><![CDATA[getRequest]]></code> + </DeprecatedMethod> + </file> + <file src="public.php"> + <DeprecatedMethod> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> + <file src="remote.php"> + <DeprecatedMethod> + <code><![CDATA[exec]]></code> + <code><![CDATA[getAppValue]]></code> + </DeprecatedMethod> + </file> </files> diff --git a/build/psalm-checker.sh b/build/psalm-checker.sh new file mode 100755 index 00000000000..a56fecebe52 --- /dev/null +++ b/build/psalm-checker.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +if [ -d "dist" ]; then + missing='' + for app in apps/*; do + if git check-ignore "$app" -q ; then + echo "ℹ️ Ignoring non shipped app: $app" + continue + fi + + grep "directory name=\"$app\"" psalm.xml 2>&1 > /dev/null + if [ $? -ne 0 ]; then + missing="$missing - $app\n" + fi + done + + if [ "$missing" = "" ]; then + echo "✅ All apps will be linted by psalm" + else + echo "❌ Following apps are not setup for linting using psalm:" + echo -e "$missing" + exit 1 + fi +else + echo "⚠️ This script needs to be executed from the root of the repository" + exit 1 +fi + diff --git a/build/psalm/AppFrameworkTainter.php b/build/psalm/AppFrameworkTainter.php index 9a68885b175..448922d25a5 100644 --- a/build/psalm/AppFrameworkTainter.php +++ b/build/psalm/AppFrameworkTainter.php @@ -1,28 +1,9 @@ <?php /** - * Copyright (c) 2020 Lukas Reschke <lukas@statuscode.ch> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT */ - use Psalm\CodeLocation; use Psalm\Plugin\EventHandler\AfterFunctionLikeAnalysisInterface; use Psalm\Plugin\EventHandler\Event\AfterFunctionLikeAnalysisEvent; diff --git a/build/psalm/AttributeNamedParameters.php b/build/psalm/AttributeNamedParameters.php new file mode 100644 index 00000000000..0b34cf3cf22 --- /dev/null +++ b/build/psalm/AttributeNamedParameters.php @@ -0,0 +1,53 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +use PhpParser\Node\Attribute; +use Psalm\CodeLocation; +use Psalm\FileSource; +use Psalm\Issue\InvalidDocblock; +use Psalm\IssueBuffer; +use Psalm\Plugin\EventHandler\Event\AfterClassLikeVisitEvent; + +class AttributeNamedParameters implements Psalm\Plugin\EventHandler\AfterClassLikeVisitInterface { + public static function afterClassLikeVisit(AfterClassLikeVisitEvent $event): void { + $stmt = $event->getStmt(); + $statementsSource = $event->getStatementsSource(); + + foreach ($stmt->attrGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attr) { + self::checkAttribute($attr, $statementsSource); + } + } + + foreach ($stmt->getMethods() as $method) { + foreach ($method->attrGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attr) { + self::checkAttribute($attr, $statementsSource); + } + } + } + } + + private static function checkAttribute(Attribute $stmt, FileSource $statementsSource): void { + if ($stmt->name->getLast() === 'Attribute') { + return; + } + + foreach ($stmt->args as $arg) { + if ($arg->name === null) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + 'Attribute arguments must be named.', + new CodeLocation($statementsSource, $stmt) + ) + ); + } + } + } +} diff --git a/build/psalm/NcuExperimentalChecker.php b/build/psalm/NcuExperimentalChecker.php new file mode 100644 index 00000000000..eaa70480ccc --- /dev/null +++ b/build/psalm/NcuExperimentalChecker.php @@ -0,0 +1,131 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +use PhpParser\Node\Stmt; +use PhpParser\Node\Stmt\ClassConst; +use PhpParser\Node\Stmt\ClassLike; +use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\EnumCase; +use Psalm\CodeLocation; +use Psalm\DocComment; +use Psalm\Exception\DocblockParseException; +use Psalm\FileSource; +use Psalm\Issue\InvalidDocblock; +use Psalm\IssueBuffer; +use Psalm\Plugin\EventHandler\Event\AfterClassLikeVisitEvent; + +class NcuExperimentalChecker implements Psalm\Plugin\EventHandler\AfterClassLikeVisitInterface { + public static function afterClassLikeVisit(AfterClassLikeVisitEvent $event): void { + $classLike = $event->getStmt(); + $statementsSource = $event->getStatementsSource(); + + self::checkClassComment($classLike, $statementsSource); + + foreach ($classLike->stmts as $stmt) { + if ($stmt instanceof ClassConst) { + self::checkStatementComment($stmt, $statementsSource, 'constant'); + } + + if ($stmt instanceof ClassMethod) { + self::checkStatementComment($stmt, $statementsSource, 'method'); + } + + if ($stmt instanceof EnumCase) { + self::checkStatementComment($stmt, $statementsSource, 'enum'); + } + } + } + + private static function checkClassComment(ClassLike $stmt, FileSource $statementsSource): void { + $docblock = $stmt->getDocComment(); + + if ($docblock === null) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + 'PHPDoc is required for classes/interfaces in NCU.', + new CodeLocation($statementsSource, $stmt) + ) + ); + return; + } + + try { + $parsedDocblock = DocComment::parsePreservingLength($docblock); + } catch (DocblockParseException $e) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + $e->getMessage(), + new CodeLocation($statementsSource, $stmt) + ) + ); + return; + } + + if (!isset($parsedDocblock->tags['experimental'])) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + '@experimental is required for classes/interfaces in NCU.', + new CodeLocation($statementsSource, $stmt) + ) + ); + } + + if (isset($parsedDocblock->tags['depreacted'])) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + 'Typo in @deprecated for classes/interfaces in NCU.', + new CodeLocation($statementsSource, $stmt) + ) + ); + } + } + + private static function checkStatementComment(Stmt $stmt, FileSource $statementsSource, string $type): void { + $docblock = $stmt->getDocComment(); + + if ($docblock === null) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + 'PHPDoc is required for ' . $type . 's in NCU.', + new CodeLocation($statementsSource, $stmt) + ), + ); + return; + } + + try { + $parsedDocblock = DocComment::parsePreservingLength($docblock); + } catch (DocblockParseException $e) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + $e->getMessage(), + new CodeLocation($statementsSource, $stmt) + ) + ); + return; + } + + if (!isset($parsedDocblock->tags['experimental'])) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + '@experimental is required for ' . $type . 's in NCU.', + new CodeLocation($statementsSource, $stmt) + ) + ); + } + + if (isset($parsedDocblock->tags['depreacted'])) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + 'Typo in @deprecated for ' . $type . ' in NCU.', + new CodeLocation($statementsSource, $stmt) + ) + ); + } + } +} diff --git a/build/psalm/OcpSinceChecker.php b/build/psalm/OcpSinceChecker.php index 92437a8f3ab..38af92cf4ef 100644 --- a/build/psalm/OcpSinceChecker.php +++ b/build/psalm/OcpSinceChecker.php @@ -1,26 +1,10 @@ <?php declare(strict_types=1); - /** - * @copyright 2023 Daniel Kesselberg <mail@danielkesselberg.de> - * - * @author 2023 Daniel Kesselberg <mail@danielkesselberg.de> - * - * 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: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only */ - use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\ClassLike; use Psalm\CodeLocation; @@ -33,17 +17,88 @@ use Psalm\Plugin\EventHandler\Event\AfterClassLikeVisitEvent; class OcpSinceChecker implements Psalm\Plugin\EventHandler\AfterClassLikeVisitInterface { public static function afterClassLikeVisit(AfterClassLikeVisitEvent $event): void { - $stmt = $event->getStmt(); + $classLike = $event->getStmt(); $statementsSource = $event->getStatementsSource(); - self::checkClassComment($stmt, $statementsSource); + if (!str_contains($statementsSource->getFilePath(), '/lib/public/')) { + return; + } - foreach ($stmt->getMethods() as $method) { - self::checkMethodOrConstantComment($method, $statementsSource, 'method'); + $isTesting = str_contains($statementsSource->getFilePath(), '/lib/public/Notification/') + || str_contains($statementsSource->getFilePath(), '/lib/public/Config/') + || str_contains($statementsSource->getFilePath(), 'CalendarEventStatus'); + + if ($isTesting) { + self::checkStatementAttributes($classLike, $statementsSource); + } else { + self::checkClassComment($classLike, $statementsSource); } - foreach ($stmt->getConstants() as $constant) { - self::checkMethodOrConstantComment($constant, $statementsSource, 'constant'); + foreach ($classLike->stmts as $stmt) { + if ($stmt instanceof ClassConst) { + self::checkStatementComment($stmt, $statementsSource, 'constant'); + } + + if ($stmt instanceof ClassMethod) { + self::checkStatementComment($stmt, $statementsSource, 'method'); + } + + if ($stmt instanceof EnumCase) { + if ($isTesting) { + self::checkStatementAttributes($classLike, $statementsSource); + } else { + self::checkStatementComment($stmt, $statementsSource, 'enum'); + } + } + } + } + + private static function checkStatementAttributes(ClassLike $stmt, FileSource $statementsSource): void { + $hasAppFrameworkAttribute = false; + $mustBeConsumable = false; + $isConsumable = false; + foreach ($stmt->attrGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attr) { + if (in_array($attr->name->getLast(), [ + 'Catchable', + 'Consumable', + 'Dispatchable', + 'Implementable', + 'Listenable', + 'Throwable', + ], true)) { + $hasAppFrameworkAttribute = true; + self::checkAttributeHasValidSinceVersion($attr, $statementsSource); + } + if (in_array($attr->name->getLast(), [ + 'Catchable', + 'Consumable', + 'Listenable', + ], true)) { + $isConsumable = true; + } + if ($attr->name->getLast() === 'ExceptionalImplementable') { + $mustBeConsumable = true; + } + } + } + + if ($mustBeConsumable && !$isConsumable) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + 'Attribute OCP\\AppFramework\\Attribute\\ExceptionalImplementable is only valid on classes that also have OCP\\AppFramework\\Attribute\\Consumable', + new CodeLocation($statementsSource, $stmt) + ) + ); + } + + if (!$hasAppFrameworkAttribute) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + 'At least one of the OCP\\AppFramework\\Attribute attributes is required', + new CodeLocation($statementsSource, $stmt) + ) + ); } } @@ -91,7 +146,7 @@ class OcpSinceChecker implements Psalm\Plugin\EventHandler\AfterClassLikeVisitIn } } - private static function checkMethodOrConstantComment(Stmt $stmt, FileSource $statementsSource, string $type): void { + private static function checkStatementComment(Stmt $stmt, FileSource $statementsSource, string $type): void { $docblock = $stmt->getDocComment(); if ($docblock === null) { @@ -134,4 +189,28 @@ class OcpSinceChecker implements Psalm\Plugin\EventHandler\AfterClassLikeVisitIn ); } } + + private static function checkAttributeHasValidSinceVersion(\PhpParser\Node\Attribute $stmt, FileSource $statementsSource): void { + foreach ($stmt->args as $arg) { + if ($arg->name?->name === 'since') { + if (!$arg->value instanceof \PhpParser\Node\Scalar\String_) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + 'Attribute since argument is not a valid version string', + new CodeLocation($statementsSource, $stmt) + ) + ); + } else { + if (!preg_match('/^[1-9][0-9]*(\.[0-9]+){0,3}$/', $arg->value->value)) { + IssueBuffer::maybeAdd( + new InvalidDocblock( + 'Attribute since argument is not a valid version string', + new CodeLocation($statementsSource, $stmt) + ) + ); + } + } + } + } + } } diff --git a/build/rector.php b/build/rector.php new file mode 100644 index 00000000000..246741bb34f --- /dev/null +++ b/build/rector.php @@ -0,0 +1,115 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +use Nextcloud\Rector\Set\NextcloudSets; +use PhpParser\Node; +use Rector\CodingStyle\Contract\ClassNameImport\ClassNameImportSkipVoterInterface; +use Rector\Config\RectorConfig; +use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector; +use Rector\PHPUnit\AnnotationsToAttributes\Rector\ClassMethod\DataProviderAnnotationToAttributeRector; +use Rector\PHPUnit\CodeQuality\Rector\MethodCall\UseSpecificWillMethodRector; +use Rector\PHPUnit\PHPUnit100\Rector\Class_\StaticDataProviderClassMethodRector; +use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType; +use Rector\ValueObject\Application\File; + +$nextcloudDir = dirname(__DIR__); + +class NextcloudNamespaceSkipVoter implements ClassNameImportSkipVoterInterface { + private array $namespacePrefixes = [ + 'OC', + 'OCA', + 'OCP', + ]; + private array $skippedClassNames = [ + 'Backend', + 'Connection', + 'Exception', + 'IManager', + 'IProvider', + 'Manager', + 'Plugin', + 'Provider', + ]; + public function shouldSkip(File $file, FullyQualifiedObjectType $fullyQualifiedObjectType, Node $node) : bool { + if (in_array($fullyQualifiedObjectType->getShortName(), $this->skippedClassNames)) { + // Skip common class names to avoid confusion + return true; + } + foreach ($this->namespacePrefixes as $prefix) { + if (str_starts_with($fullyQualifiedObjectType->getClassName(), $prefix . '\\')) { + // Import Nextcloud namespaces + return false; + } + } + // Skip everything else + return true; + } +} + +$config = RectorConfig::configure() + ->withPaths([ + $nextcloudDir . '/apps', + $nextcloudDir . '/core', + $nextcloudDir . '/ocs', + $nextcloudDir . '/ocs-provider', + $nextcloudDir . '/console.php', + $nextcloudDir . '/cron.php', + $nextcloudDir . '/index.php', + $nextcloudDir . '/occ', + $nextcloudDir . '/public.php', + $nextcloudDir . '/remote.php', + $nextcloudDir . '/status.php', + $nextcloudDir . '/version.php', + $nextcloudDir . '/lib/private/Share20/ProviderFactory.php', + $nextcloudDir . '/tests', + // $nextcloudDir . '/config', + // $nextcloudDir . '/lib', + // $nextcloudDir . '/themes', + ]) + ->withSkip([ + $nextcloudDir . '/apps/*/3rdparty/*', + $nextcloudDir . '/apps/*/build/stubs/*', + $nextcloudDir . '/apps/*/composer/*', + $nextcloudDir . '/apps/*/config/*', + ]) + // uncomment to reach your current PHP version + // ->withPhpSets() + ->withImportNames(importShortClasses:false) + ->withTypeCoverageLevel(0) + ->withRules([ + UseSpecificWillMethodRector::class, + StaticDataProviderClassMethodRector::class, + DataProviderAnnotationToAttributeRector::class, + ]) + ->withConfiguredRule(ClassPropertyAssignToConstructorPromotionRector::class, [ + 'inline_public' => true, + 'rename_property' => true, + ]) + ->withSets([ + NextcloudSets::NEXTCLOUD_25, + ]); + +$config->registerService(NextcloudNamespaceSkipVoter::class, tag:ClassNameImportSkipVoterInterface::class); + +/* Ignore all files ignored by git */ +$ignoredEntries = shell_exec('git status --porcelain --ignored ' . escapeshellarg($nextcloudDir)); +$ignoredEntries = explode("\n", $ignoredEntries); +$ignoredEntries = array_filter($ignoredEntries, static fn (string $line) => str_starts_with($line, '!! ')); +$ignoredEntries = array_map(static fn (string $line) => substr($line, 3), $ignoredEntries); +$ignoredEntries = array_values($ignoredEntries); + +foreach ($ignoredEntries as $ignoredEntry) { + if (str_ends_with($ignoredEntry, '/')) { + $config->withSkip([$ignoredEntry . '*']); + } else { + $config->withSkip([$ignoredEntry . '/*']); + } +} + +return $config; diff --git a/build/signed-off-checker.php b/build/signed-off-checker.php deleted file mode 100644 index 9620309932a..00000000000 --- a/build/signed-off-checker.php +++ /dev/null @@ -1,129 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016 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/>. - * - */ - -/** - * Script to verify that all commits have been signed-off, if a commit doesn't end - * with a signed-off message the script is failing. - */ -$baseDir = __DIR__ . '/../'; - -$pullRequestNumber = getenv('DRONE_PULL_REQUEST'); -$repoOwner = getenv('DRONE_REPO_OWNER'); -$repoName = getenv('DRONE_REPO_NAME'); -$droneEvent = getenv('DRONE_BUILD_EVENT'); -$githubToken = getenv('GITHUB_TOKEN'); - -if (is_string($droneEvent) && $droneEvent === 'push') { - echo("Push event - no signed-off check required.\n"); - exit(0); -} - -if (!is_string($pullRequestNumber) || $pullRequestNumber === '') { - echo("The environment variable DRONE_PULL_REQUEST has no proper value.\n"); - exit(1); -} - -if (!is_string($repoOwner) || $repoOwner === '') { - echo("The environment variable DRONE_REPO_OWNER has no proper value.\n"); - exit(1); -} - -if (!is_string($repoName) || $repoName === '') { - echo("The environment variable DRONE_REPO_NAME has no proper value.\n"); - exit(1); -} - -if (!is_string($githubToken) || $githubToken === '') { - echo("The environment variable GITHUB_TOKEN has no proper value.\n"); - exit(1); -} - -$ch = curl_init(); -curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); -curl_setopt($ch, CURLOPT_URL, 'https://api.github.com/repos/' . $repoOwner . '/' . $repoName . '/pulls/' . $pullRequestNumber . '/commits'); -curl_setopt($ch, CURLOPT_USERAGENT, 'CI for Nextcloud (https://github.com/nextcloud/server)'); -curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: token ' . $githubToken]); -$response = curl_exec($ch); -curl_close($ch); - -$decodedResponse = json_decode($response, true); -if (!is_array($decodedResponse) || count($decodedResponse) === 0) { - echo("Could not decode JSON response from GitHub API.\n"); - exit(1); -} - -// Get all commits SHAs -$commits = []; - -foreach ($decodedResponse as $commit) { - if (!isset($commit['sha'])) { - echo("No SHA specified in $commit\n"); - exit(1); - } - if (!isset($commit['commit']['message'])) { - echo("No commit message specified in $commit\n"); - exit(1); - } - $commits[$commit['sha']] = $commit['commit']['message']; -} - -if (count($commits) < 1) { - echo("Could not read commits.\n"); - exit(1); -} - -$notSignedCommits = []; -foreach ($commits as $commit => $message) { - if ($commit === '') { - continue; - } - - $signOffMessage = false; - $commitMessageLines = explode("\n", $message); - - foreach ($commitMessageLines as $line) { - if (preg_match('/^Signed-off-by: .* <.*@.*>$/', $line)) { - echo "$commit is signed-off with \"$line\"\n"; - $signOffMessage = true; - continue; - } - } - if ($signOffMessage === true) { - continue; - } - - $notSignedCommits[] = $commit; -} - -if ($notSignedCommits !== []) { - echo("\n"); - echo("Some commits were not signed off!\n"); - echo("Missing signatures on:\n"); - foreach ($notSignedCommits as $commit) { - echo("- " . $commit . "\n"); - } - echo("Build has failed\n"); - exit(1); -} else { - exit(0); -} diff --git a/build/stubs/app_api.php b/build/stubs/app_api.php index 1ab63499b77..04a6042dffd 100644 --- a/build/stubs/app_api.php +++ b/build/stubs/app_api.php @@ -1,15 +1,92 @@ <?php -namespace OCA\AppAPI\Service; - -use OCP\IRequest; - -class AppAPIService { - /** - * @param IRequest $request - * @param bool $isDav - * - * @return bool - */ - public function validateExAppRequestToNC(IRequest $request, bool $isDav = false): bool {} +namespace OCA\AppAPI\Service { + use OCP\IRequest; + + class AppAPIService { + /** + * @param IRequest $request + * @param bool $isDav + * + * @return bool + */ + public function validateExAppRequestToNC(IRequest $request, bool $isDav = false): bool {} + } +} + +namespace OCA\AppAPI { + + use OCP\IRequest; + use OCP\Http\Client\IPromise; + use OCP\Http\Client\IResponse; + + class PublicFunctions { + + public function __construct( + private readonly ExAppService $exAppService, + private readonly AppAPIService $service, + ) { + } + + /** + * Request to ExApp with AppAPI auth headers + */ + public function exAppRequest( + string $appId, + string $route, + ?string $userId = null, + string $method = 'POST', + array $params = [], + array $options = [], + ?IRequest $request = null, + ): array|IResponse { + $exApp = $this->exAppService->getExApp($appId); + if ($exApp === null) { + return ['error' => sprintf('ExApp `%s` not found', $appId)]; + } + return $this->service->requestToExApp($exApp, $route, $userId, $method, $params, $options, $request); + } + + /** + * Async request to ExApp with AppAPI auth headers + * + * @throws \Exception if ExApp not found + */ + public function asyncExAppRequest( + string $appId, + string $route, + ?string $userId = null, + string $method = 'POST', + array $params = [], + array $options = [], + ?IRequest $request = null, + ): IPromise { + $exApp = $this->exAppService->getExApp($appId); + if ($exApp === null) { + throw new \Exception(sprintf('ExApp `%s` not found', $appId)); + } + return $this->service->requestToExAppAsync($exApp, $route, $userId, $method, $params, $options, $request); + } + + /** + * Get basic ExApp info by appid + * + * @param string $appId + * + * @return array|null ExApp info (appid, version, name, enabled) or null if no ExApp found + */ + public function getExApp(string $appId): ?array { + $exApp = $this->exAppService->getExApp($appId); + if ($exApp !== null) { + $info = $exApp->jsonSerialize(); + return [ + 'appid' => $info['appid'], + 'version' => $info['version'], + 'name' => $info['name'], + 'enabled' => $info['enabled'], + ]; + } + return null; + } + } } diff --git a/build/stubs/excimer.php b/build/stubs/excimer.php new file mode 100644 index 00000000000..e29eb2fd219 --- /dev/null +++ b/build/stubs/excimer.php @@ -0,0 +1,282 @@ +<?php + +/** Real (wall-clock) time */ +define('EXCIMER_REAL', 0); + +/** CPU time (user and system) consumed by the thread during execution */ +define('EXCIMER_CPU', 1); + +/** + * A sampling profiler. + * + * Collects a stack trace every time a timer event fires. + */ +class ExcimerProfiler { + /** + * Set the period. + * + * This will take effect the next time start() is called. + * + * If this method is not called, the default period of 0.1 seconds + * will be used. + * + * @param float $period The period in seconds + */ + public function setPeriod($period) { + } + + /** + * Set the event type. May be either EXCIMER_REAL, for real (wall-clock) + * time, or EXCIMER_CPU, for CPU time. The default is EXCIMER_REAL. + * + * This will take effect the next time start() is called. + * + * @param int $eventType + */ + public function setEventType($eventType) { + } + + /** + * Set the maximum depth of stack trace collection. If this depth is + * exceeded, the traversal up the stack will be terminated, so the function + * will appear to have no caller. + * + * By default, there is no limit. If this is called with a depth of zero, + * the limit is disabled. + * + * This will take effect immediately. + * + * @param int $maxDepth + */ + public function setMaxDepth($maxDepth) { + } + + /** + * Set a callback which will be called once the specified number of samples + * has been collected. + * + * When the ExcimerProfiler object is destroyed, the callback will also + * be called, unless no samples have been collected. + * + * The callback will be called with a single argument: the ExcimerLog + * object containing the samples. Before the callback is called, a new + * ExcimerLog object will be created and registered with the + * ExcimerProfiler. So ExcimerProfiler::getLog() should not be used from + * the callback, since it will not return the samples. + * + * @param callable $callback + * @param int $maxSamples + */ + public function setFlushCallback($callback, $maxSamples) { + } + + /** + * Clear the flush callback. No callback will be called regardless of + * how many samples are collected. + */ + public function clearFlushCallback() { + } + + /** + * Start the profiler. If the profiler was already running, it will be + * stopped and restarted with new options. + */ + public function start() { + } + + /** + * Stop the profiler. + */ + public function stop() { + } + + /** + * Get the current ExcimerLog object. + * + * Note that if the profiler is running, the object thus returned may be + * modified by a timer event at any time, potentially invalidating your + * analysis. Instead, the profiler should be stopped first, or flush() + * should be used. + * + * @return ExcimerLog + */ + public function getLog() { + } + + /** + * Create and register a new ExcimerLog object, and return the old + * ExcimerLog object. + * + * This will return all accumulated events to this point, and reset the + * log with a new log of zero length. + * + * @return ExcimerLog + */ + public function flush() { + } +} + +/** + * A collected series of stack traces and some utility methods to aggregate them. + * + * ExcimerLog acts as a container for ExcimerLogEntry objects. The Iterator or + * ArrayAccess interfaces may be used to access them. For example: + * + * foreach ( $profiler->getLog() as $entry ) { + * var_dump( $entry->getTrace() ); + * } + */ +class ExcimerLog implements ArrayAccess, Iterator { + /** + * ExcimerLog is not constructible by user code. Objects of this type + * are available via: + * - ExcimerProfiler::getLog() + * - ExcimerProfiler::flush() + * - The callback to ExcimerProfiler::setFlushCallback() + */ + final private function __construct() { + } + + /** + * Aggregate the stack traces and convert them to a line-based format + * understood by Brendan Gregg's FlameGraph utility. Each stack trace is + * represented as a series of function names, separated by semicolons. + * After this identifier, there is a single space character, then a number + * giving the number of times the stack appeared. Then there is a line + * break. This is repeated for each unique stack trace. + * + * @return string + */ + public function formatCollapsed() { + } + + /** + * Produce an array with an element for every function which appears in + * the log. The key is a human-readable unique identifier for the function, + * method or closure. The value is an associative array with the following + * elements: + * + * - self: The number of events in which the function itself was running, + * no other userspace function was being called. This includes time + * spent in internal functions that this function called. + * - inclusive: The number of events in which this function appeared + * somewhere in the stack. + * + * And optionally the following elements, if they are relevant: + * + * - file: The filename in which the function appears + * - line: The exact line number at which the first relevant event + * occurred. + * - class: The class name in which the method is defined + * - function: The name of the function or method + * - closure_line: The line number at which the closure was defined + * + * The event counts in the "self" and "inclusive" fields are adjusted for + * overruns. They represent an estimate of the number of profiling periods + * in which those functions were present. + * + * @return array + */ + public function aggregateByFunction() { + } + + /** + * Get an array which can be JSON encoded for import into speedscope + * + * @return array + */ + public function getSpeedscopeData() { + } + + /** + * Get the total number of profiling periods represented by this log. + * + * @return int + */ + public function getEventCount() { + } + + /** + * Get the current ExcimerLogEntry object. Part of the Iterator interface. + * + * @return ExcimerLogEntry|null + */ + public function current() { + } + + /** + * Get the current integer key or null. Part of the Iterator interface. + * + * @return int|null + */ + public function key() { + } + + /** + * Advance to the next log entry. Part of the Iterator interface. + */ + public function next() { + } + + /** + * Rewind back to the first log entry. Part of the Iterator interface. + */ + public function rewind() { + } + + /** + * Check if the current position is valid. Part of the Iterator interface. + * + * @return bool + */ + public function valid() { + } + + /** + * Get the number of log entries contained in this log. This is always less + * than or equal to the number returned by getEventCount(), which includes + * overruns. + * + * @return int + */ + public function count() { + } + + /** + * Determine whether a log entry exists at the specified array offset. + * Part of the ArrayAccess interface. + * + * @param int $offset + * @return bool + */ + public function offsetExists($offset) { + } + + /** + * Get the ExcimerLogEntry object at the specified array offset. + * + * @param int $offset + * @return ExcimerLogEntry|null + */ + public function offsetGet($offset) { + } + + /** + * This function is included for compliance with the ArrayAccess interface. + * It raises a warning and does nothing. + * + * @param int $offset + * @param mixed $value + */ + public function offsetSet($offset, $value) { + } + + /** + * This function is included for compliance with the ArrayAccess interface. + * It raises a warning and does nothing. + * + * @param int $offset + */ + public function offsetUnset($offset) { + } +} diff --git a/build/stubs/intl.php b/build/stubs/intl.php index 08e0c719338..5ca558d049f 100644 --- a/build/stubs/intl.php +++ b/build/stubs/intl.php @@ -1,21 +1,27 @@ <?php +/** + * SPDX-FileCopyrightText: 2023 JetBrains s.r.o. + * SPDX-License-Identifier: Apache-2.0 + */ + // Start of intl v.1.1.0 -class Collator { - const DEFAULT_VALUE = -1; - const PRIMARY = 0; - const SECONDARY = 1; - const TERTIARY = 2; - const DEFAULT_STRENGTH = 2; - const QUATERNARY = 3; - const IDENTICAL = 15; - const OFF = 16; - const ON = 17; - const SHIFTED = 20; - const NON_IGNORABLE = 21; - const LOWER_FIRST = 24; - const UPPER_FIRST = 25; +class Collator +{ + public const DEFAULT_VALUE = -1; + public const PRIMARY = 0; + public const SECONDARY = 1; + public const TERTIARY = 2; + public const DEFAULT_STRENGTH = 2; + public const QUATERNARY = 3; + public const IDENTICAL = 15; + public const OFF = 16; + public const ON = 17; + public const SHIFTED = 20; + public const NON_IGNORABLE = 21; + public const LOWER_FIRST = 24; + public const UPPER_FIRST = 25; /** * <p> @@ -37,9 +43,9 @@ class Collator { * F=ON cote < côte < coté < côté * </p> * </p> - * @link https://php.net/manual/en/intl.collator-constants.php + * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ - const FRENCH_COLLATION = 0; + public const FRENCH_COLLATION = 0; /** * <p> @@ -82,9 +88,9 @@ class Collator { * S=4, A=S di Silva < diSilva < Di Silva < U.S.A. < USA * </p> * </p> - * @link https://php.net/manual/en/intl.collator-constants.php + * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ - const ALTERNATE_HANDLING = 1; + public const ALTERNATE_HANDLING = 1; /** * <p> @@ -116,9 +122,9 @@ class Collator { * C=U "China" < "china" < "Denmark" < "denmark" * </p> * </p> - * @link https://php.net/manual/en/intl.collator-constants.php + * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ - const CASE_FIRST = 2; + public const CASE_FIRST = 2; /** * <p> @@ -142,9 +148,9 @@ class Collator { * S=1, E=O role = rôle < Role * </p> * </p> - * @link https://php.net/manual/en/intl.collator-constants.php + * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ - const CASE_LEVEL = 3; + public const CASE_LEVEL = 3; /** * <p> @@ -168,9 +174,9 @@ class Collator { * <b>Collator::ON</b> * <b>Collator::DEFAULT_VALUE</b> * </p> - * @link https://php.net/manual/en/intl.collator-constants.php + * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ - const NORMALIZATION_MODE = 4; + public const NORMALIZATION_MODE = 4; /** * <p> @@ -186,14 +192,14 @@ class Collator { * Possible values are: * <b>Collator::PRIMARY</b> * <b>Collator::SECONDARY</b> - * <b>Collator::TERTIARY</b>(<default) + * <b>Collator::TERTIARY</b>(default) * <b>Collator::QUATERNARY</b> * <b>Collator::IDENTICAL</b> * <b>Collator::DEFAULT_VALUE</b> * </p> - * @link https://php.net/manual/en/intl.collator-constants.php + * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ - const STRENGTH = 5; + public const STRENGTH = 5; /** * <p> @@ -210,9 +216,9 @@ class Collator { * <b>Collator::ON</b> * <b>Collator::DEFAULT_VALUE</b> * </p> - * @link https://php.net/manual/en/intl.collator-constants.php + * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ - const HIRAGANA_QUATERNARY_MODE = 6; + public const HIRAGANA_QUATERNARY_MODE = 6; /** * <p> @@ -226,13 +232,12 @@ class Collator { * <b>Collator::ON</b> * <b>Collator::DEFAULT_VALUE</b> * </p> - * @link https://php.net/manual/en/intl.collator-constants.php + * @link https://php.net/manual/en/class.collator.php#intl.collator-constants */ - const NUMERIC_COLLATION = 7; - const SORT_REGULAR = 0; - const SORT_STRING = 1; - const SORT_NUMERIC = 2; - + public const NUMERIC_COLLATION = 7; + public const SORT_REGULAR = 0; + public const SORT_STRING = 1; + public const SORT_NUMERIC = 2; /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -240,7 +245,7 @@ class Collator { * @link https://php.net/manual/en/collator.construct.php * @param string $locale */ - public function __construct($locale) { } + public function __construct(string $locale) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -252,22 +257,22 @@ class Collator { * default locale collation rules will be used. If empty string ("") or * "root" are passed, UCA rules will be used. * </p> - * @return Collator Return new instance of <b>Collator</b> object, or <b>NULL</b> + * @return Collator|null Return new instance of <b>Collator</b> object, or <b>NULL</b> * on error. */ - public static function create($locale) { } + public static function create(string $locale): ?Collator {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Compare two Unicode strings * @link https://php.net/manual/en/collator.compare.php - * @param string $str1 <p> + * @param string $string1 <p> * The first string to compare. * </p> - * @param string $str2 <p> + * @param string $string2 <p> * The second string to compare. * </p> - * @return int Return comparison result:</p> + * @return int|false Return comparison result:</p> * <p> * <p> * 1 if <i>str1</i> is greater than @@ -286,81 +291,93 @@ class Collator { * <b>FALSE</b> * is returned. */ - public function compare($str1, $str2) { } + public function compare( + string $string1, + string $string2 + ): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Sort array using specified collator * @link https://php.net/manual/en/collator.sort.php - * @param array $arr <p> + * @param string[] &$array <p> * Array of strings to sort. * </p> - * @param int $sort_flag [optional] <p> + * @param int $flags [optional] <p> * Optional sorting type, one of the following: * </p> * <p> - * <p> * <b>Collator::SORT_REGULAR</b> * - compare items normally (don't change types) * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public function sort(array &$arr, $sort_flag = null) { } + public function sort( + array &$array, + int $flags = 0 + ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Sort array using specified collator and sort keys * @link https://php.net/manual/en/collator.sortwithsortkeys.php - * @param array $arr <p>Array of strings to sort</p> + * @param string[] &$array <p>Array of strings to sort</p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public function sortWithSortKeys(array &$arr) { } + public function sortWithSortKeys( + array &$array, + ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Sort array maintaining index association * @link https://php.net/manual/en/collator.asort.php - * @param array $arr <p>Array of strings to sort.</p> - * @param int $sort_flag [optional] <p> + * @param string[] &$array <p>Array of strings to sort.</p> + * @param int $flags [optional] <p> * Optional sorting type, one of the following: - * <p> * <b>Collator::SORT_REGULAR</b> * - compare items normally (don't change types) * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public function asort(array &$arr, $sort_flag = null) { } + public function asort( + array &$array, + int $flags = 0 + ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get collation attribute value * @link https://php.net/manual/en/collator.getattribute.php - * @param int $attr <p> + * @param int $attribute <p> * Attribute to get value for. * </p> * @return int|false Attribute value, or boolean <b>FALSE</b> on error. */ - public function getAttribute($attr) { } + public function getAttribute(int $attribute): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Set collation attribute * @link https://php.net/manual/en/collator.setattribute.php - * @param int $attr <p>Attribute.</p> - * @param int $val <p> + * @param int $attribute <p>Attribute.</p> + * @param int $value <p> * Attribute value. * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public function setAttribute($attr, $val) { } + public function setAttribute( + int $attribute, + int $value + ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get current collation strength * @link https://php.net/manual/en/collator.getstrength.php - * @return int|false current collation strength, or boolean <b>FALSE</b> on error. + * @return int current collation strength, or boolean <b>FALSE</b> on error. */ - public function getStrength() { } + public function getStrength(): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -369,513 +386,538 @@ class Collator { * @param int $strength <p>Strength to set.</p> * <p> * Possible values are: - * <p> * <b>Collator::PRIMARY</b> * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public function setStrength($strength) { } + public function setStrength(int $strength): bool {} + + /** + * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> + * Get collator's last error code + * @link https://php.net/manual/en/collator.geterrorcode.php + * @return int|false Error code returned by the last Collator API function call. + */ + public function getErrorCode(): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the locale name of the collator * @link https://php.net/manual/en/collator.getlocale.php - * @param int $type [optional] <p> + * @param int $type <p> * You can choose between valid and actual locale ( * <b>Locale::VALID_LOCALE</b> and * <b>Locale::ACTUAL_LOCALE</b>, - * respectively). The default is the actual locale. + * respectively). * </p> - * @return string Real locale name from which the collation data comes. If the collator was + * @return string|false Real locale name from which the collation data comes. If the collator was * instantiated from rules or an error occurred, returns * boolean <b>FALSE</b>. */ - public function getLocale($type = null) { } - - /** - * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> - * Get collator's last error code - * @link https://php.net/manual/en/collator.geterrorcode.php - * @return int Error code returned by the last Collator API function call. - */ - public function getErrorCode() { } + public function getLocale( + int $type + ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get text for collator's last error code * @link https://php.net/manual/en/collator.geterrormessage.php - * @return string Description of an error occurred in the last Collator API function call. + * @return string|false Description of an error occurred in the last Collator API function call. */ - public function getErrorMessage() { } + public function getErrorMessage(): string|false {} /** - * (No version information available, might only be in SVN)<br/> + * (PHP 5 >= 5.3.2, PECL intl >= 1.0.3)<br/> * Get sorting key for a string * @link https://php.net/manual/en/collator.getsortkey.php - * @param string $str <p> + * @param string $string <p> * The string to produce the key from. * </p> - * @return string the collation key for the string. Collation keys can be compared directly instead of strings. + * @return string|false the collation key for the string. Collation keys can be compared directly instead of strings. */ - public function getSortKey($str) { } + public function getSortKey( + string $string, + ): string|false {} } -class NumberFormatter { +class NumberFormatter +{ + public const CURRENCY_ACCOUNTING = 12; /** * Decimal format defined by pattern - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PATTERN_DECIMAL = 0; + public const PATTERN_DECIMAL = 0; /** * Decimal format - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const DECIMAL = 1; + public const DECIMAL = 1; /** * Currency format - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const CURRENCY = 2; + public const CURRENCY = 2; /** * Percent format - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PERCENT = 3; + public const PERCENT = 3; /** * Scientific format - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const SCIENTIFIC = 4; + public const SCIENTIFIC = 4; /** * Spellout rule-based format - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const SPELLOUT = 5; + public const SPELLOUT = 5; /** * Ordinal rule-based format - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const ORDINAL = 6; + public const ORDINAL = 6; /** * Duration rule-based format - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const DURATION = 7; + public const DURATION = 7; /** * Rule-based format defined by pattern - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.locale.php#intl.locale-constants */ - const PATTERN_RULEBASED = 9; + public const PATTERN_RULEBASED = 9; /** * Alias for PATTERN_DECIMAL - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const IGNORE = 0; + public const IGNORE = 0; /** * Default format for the locale - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const DEFAULT_STYLE = 1; + public const DEFAULT_STYLE = 1; /** * Rounding mode to round towards positive infinity. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const ROUND_CEILING = 0; + public const ROUND_CEILING = 0; /** * Rounding mode to round towards negative infinity. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const ROUND_FLOOR = 1; + public const ROUND_FLOOR = 1; /** * Rounding mode to round towards zero. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const ROUND_DOWN = 2; + public const ROUND_DOWN = 2; /** * Rounding mode to round away from zero. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const ROUND_UP = 3; + public const ROUND_UP = 3; /** * Rounding mode to round towards the "nearest neighbor" unless both * neighbors are equidistant, in which case, round towards the even * neighbor. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const ROUND_HALFEVEN = 4; + public const ROUND_HALFEVEN = 4; /** * Rounding mode to round towards "nearest neighbor" unless both neighbors * are equidistant, in which case round down. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const ROUND_HALFDOWN = 5; + public const ROUND_HALFDOWN = 5; /** * Rounding mode to round towards "nearest neighbor" unless both neighbors * are equidistant, in which case round up. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const ROUND_HALFUP = 6; + public const ROUND_HALFUP = 6; /** * Pad characters inserted before the prefix. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PAD_BEFORE_PREFIX = 0; + public const PAD_BEFORE_PREFIX = 0; /** * Pad characters inserted after the prefix. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PAD_AFTER_PREFIX = 1; + public const PAD_AFTER_PREFIX = 1; /** * Pad characters inserted before the suffix. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PAD_BEFORE_SUFFIX = 2; + public const PAD_BEFORE_SUFFIX = 2; /** * Pad characters inserted after the suffix. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PAD_AFTER_SUFFIX = 3; + public const PAD_AFTER_SUFFIX = 3; /** * Parse integers only. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PARSE_INT_ONLY = 0; + public const PARSE_INT_ONLY = 0; /** * Use grouping separator. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const GROUPING_USED = 1; + public const GROUPING_USED = 1; /** * Always show decimal point. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const DECIMAL_ALWAYS_SHOWN = 2; + public const DECIMAL_ALWAYS_SHOWN = 2; /** * Maximum integer digits. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const MAX_INTEGER_DIGITS = 3; + public const MAX_INTEGER_DIGITS = 3; /** * Minimum integer digits. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const MIN_INTEGER_DIGITS = 4; + public const MIN_INTEGER_DIGITS = 4; /** * Integer digits. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const INTEGER_DIGITS = 5; + public const INTEGER_DIGITS = 5; /** * Maximum fraction digits. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const MAX_FRACTION_DIGITS = 6; + public const MAX_FRACTION_DIGITS = 6; /** * Minimum fraction digits. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const MIN_FRACTION_DIGITS = 7; + public const MIN_FRACTION_DIGITS = 7; /** * Fraction digits. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const FRACTION_DIGITS = 8; + public const FRACTION_DIGITS = 8; /** * Multiplier. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const MULTIPLIER = 9; + public const MULTIPLIER = 9; /** * Grouping size. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const GROUPING_SIZE = 10; + public const GROUPING_SIZE = 10; /** * Rounding Mode. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const ROUNDING_MODE = 11; + public const ROUNDING_MODE = 11; /** * Rounding increment. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const ROUNDING_INCREMENT = 12; + public const ROUNDING_INCREMENT = 12; /** * The width to which the output of format() is padded. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const FORMAT_WIDTH = 13; + public const FORMAT_WIDTH = 13; /** * The position at which padding will take place. See pad position * constants for possible argument values. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PADDING_POSITION = 14; + public const PADDING_POSITION = 14; /** * Secondary grouping size. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const SECONDARY_GROUPING_SIZE = 15; + public const SECONDARY_GROUPING_SIZE = 15; /** * Use significant digits. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const SIGNIFICANT_DIGITS_USED = 16; + public const SIGNIFICANT_DIGITS_USED = 16; /** * Minimum significant digits. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const MIN_SIGNIFICANT_DIGITS = 17; + public const MIN_SIGNIFICANT_DIGITS = 17; /** * Maximum significant digits. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const MAX_SIGNIFICANT_DIGITS = 18; + public const MAX_SIGNIFICANT_DIGITS = 18; /** * Lenient parse mode used by rule-based formats. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const LENIENT_PARSE = 19; + public const LENIENT_PARSE = 19; /** * Positive prefix. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const POSITIVE_PREFIX = 0; + public const POSITIVE_PREFIX = 0; /** * Positive suffix. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const POSITIVE_SUFFIX = 1; + public const POSITIVE_SUFFIX = 1; /** * Negative prefix. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const NEGATIVE_PREFIX = 2; + public const NEGATIVE_PREFIX = 2; /** * Negative suffix. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const NEGATIVE_SUFFIX = 3; + public const NEGATIVE_SUFFIX = 3; /** * The character used to pad to the format width. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PADDING_CHARACTER = 4; + public const PADDING_CHARACTER = 4; /** * The ISO currency code. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const CURRENCY_CODE = 5; + public const CURRENCY_CODE = 5; /** * The default rule set. This is only available with rule-based * formatters. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const DEFAULT_RULESET = 6; + public const DEFAULT_RULESET = 6; /** * The public rule sets. This is only available with rule-based * formatters. This is a read-only attribute. The public rulesets are * returned as a single string, with each ruleset name delimited by ';' * (semicolon). - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PUBLIC_RULESETS = 7; + public const PUBLIC_RULESETS = 7; /** * The decimal separator. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const DECIMAL_SEPARATOR_SYMBOL = 0; + public const DECIMAL_SEPARATOR_SYMBOL = 0; /** * The grouping separator. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const GROUPING_SEPARATOR_SYMBOL = 1; + public const GROUPING_SEPARATOR_SYMBOL = 1; /** * The pattern separator. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PATTERN_SEPARATOR_SYMBOL = 2; + public const PATTERN_SEPARATOR_SYMBOL = 2; /** * The percent sign. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PERCENT_SYMBOL = 3; + public const PERCENT_SYMBOL = 3; /** * Zero. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const ZERO_DIGIT_SYMBOL = 4; + public const ZERO_DIGIT_SYMBOL = 4; /** * Character representing a digit in the pattern. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const DIGIT_SYMBOL = 5; + public const DIGIT_SYMBOL = 5; /** * The minus sign. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const MINUS_SIGN_SYMBOL = 6; + public const MINUS_SIGN_SYMBOL = 6; /** * The plus sign. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PLUS_SIGN_SYMBOL = 7; + public const PLUS_SIGN_SYMBOL = 7; /** * The currency symbol. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const CURRENCY_SYMBOL = 8; + public const CURRENCY_SYMBOL = 8; /** * The international currency symbol. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const INTL_CURRENCY_SYMBOL = 9; + public const INTL_CURRENCY_SYMBOL = 9; /** * The monetary separator. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const MONETARY_SEPARATOR_SYMBOL = 10; + public const MONETARY_SEPARATOR_SYMBOL = 10; /** * The exponential symbol. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const EXPONENTIAL_SYMBOL = 11; + public const EXPONENTIAL_SYMBOL = 11; /** * Per mill symbol. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PERMILL_SYMBOL = 12; + public const PERMILL_SYMBOL = 12; /** * Escape padding character. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PAD_ESCAPE_SYMBOL = 13; + public const PAD_ESCAPE_SYMBOL = 13; /** * Infinity symbol. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const INFINITY_SYMBOL = 14; + public const INFINITY_SYMBOL = 14; /** * Not-a-number symbol. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const NAN_SYMBOL = 15; + public const NAN_SYMBOL = 15; /** * Significant digit symbol. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const SIGNIFICANT_DIGIT_SYMBOL = 16; + public const SIGNIFICANT_DIGIT_SYMBOL = 16; /** * The monetary grouping separator. - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const MONETARY_GROUPING_SEPARATOR_SYMBOL = 17; + public const MONETARY_GROUPING_SEPARATOR_SYMBOL = 17; /** * Derive the type from variable type - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const TYPE_DEFAULT = 0; + public const TYPE_DEFAULT = 0; /** * Format/parse as 32-bit integer - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const TYPE_INT32 = 1; + public const TYPE_INT32 = 1; /** * Format/parse as 64-bit integer - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const TYPE_INT64 = 2; + public const TYPE_INT64 = 2; /** * Format/parse as floating point value - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const TYPE_DOUBLE = 3; + public const TYPE_DOUBLE = 3; /** * Format/parse as currency value - * @link https://php.net/manual/en/intl.numberformatter-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants + * @deprecated 8.3 + */ + public const TYPE_CURRENCY = 4; + + /** + * @since 8.4 */ - const TYPE_CURRENCY = 4; + public const ROUND_TOWARD_ZERO = 2; + /** + * @since 8.4 + */ + public const ROUND_AWAY_FROM_ZERO = 3; /** - * @param $locale - * @param $style - * @param $pattern [optional] + * @since 8.4 + */ + public const ROUND_HALFODD = 8; + + /** + * @link https://www.php.net/manual/en/class.numberformatter.php + * @param string $locale + * @param int $style + * @param string $pattern [optional] */ - public function __construct($locale, $style, $pattern = null) { } + public function __construct( + string $locale, + int $style, + string|null $pattern = null + ) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -901,13 +943,17 @@ class NumberFormatter { * </p> * @return NumberFormatter|false <b>NumberFormatter</b> object or <b>FALSE</b> on error. */ - public static function create($locale, $style, $pattern = null) { } + public static function create( + string $locale, + int $style, + string|null $pattern = null + ): ?NumberFormatter {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Format a number * @link https://php.net/manual/en/numberformatter.format.php - * @param int|float $value <p> + * @param int|float $num <p> * The value to format. Can be integer or float, * other values will be converted to a numeric value. * </p> @@ -917,62 +963,72 @@ class NumberFormatter { * </p> * @return string|false the string containing formatted value, or <b>FALSE</b> on error. */ - public function format($value, $type = null) { } + public function format( + int|float $num, + int $type = 0 + ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Parse a number * @link https://php.net/manual/en/numberformatter.parse.php - * @param string $value + * @param string $string * @param int $type [optional] <p> * The * formatting type to use. By default, * <b>NumberFormatter::TYPE_DOUBLE</b> is used. * </p> - * @param int $position [optional] <p> + * @param int &$offset [optional] <p> * Offset in the string at which to begin parsing. On return, this value * will hold the offset at which parsing ended. * </p> * @return mixed The value of the parsed number or <b>FALSE</b> on error. */ - public function parse($value, $type = null, &$position = null) { } + public function parse( + string $string, + int $type = NumberFormatter::TYPE_DOUBLE, + &$offset = null + ): int|float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Format a currency value * @link https://php.net/manual/en/numberformatter.formatcurrency.php - * @param float $value <p> + * @param float $amount <p> * The numeric currency value. * </p> * @param string $currency <p> * The 3-letter ISO 4217 currency code indicating the currency to use. * </p> - * @return string String representing the formatted currency value. + * @return string|false String representing the formatted currency value. */ - public function formatCurrency($value, $currency) { } + public function formatCurrency( + float $amount, + string $currency + ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Parse a currency number * @link https://php.net/manual/en/numberformatter.parsecurrency.php - * @param string $value - * @param string $currency <p> + * @param string $string + * @param string &$currency <p> * Parameter to receive the currency name (3-letter ISO 4217 currency * code). * </p> - * @param int $position [optional] <p> + * @param int &$offset [optional] <p> * Offset in the string at which to begin parsing. On return, this value * will hold the offset at which parsing ended. * </p> * @return float|false The parsed numeric value or <b>FALSE</b> on error. */ - public function parseCurrency($value, &$currency, &$position = null) { } + public function parseCurrency(string $string, &$currency, &$offset = null): float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Set an attribute * @link https://php.net/manual/en/numberformatter.setattribute.php - * @param int $attr <p> + * @param int $attribute <p> * Attribute specifier - one of the * numeric attribute constants. * </p> @@ -981,25 +1037,28 @@ class NumberFormatter { * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public function setAttribute($attr, $value) { } + public function setAttribute( + int $attribute, + int|float $value + ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get an attribute * @link https://php.net/manual/en/numberformatter.getattribute.php - * @param int $attr <p> + * @param int $attribute <p> * Attribute specifier - one of the * numeric attribute constants. * </p> - * @return int|false Return attribute value on success, or <b>FALSE</b> on error. + * @return int|float|false Return attribute value on success, or <b>FALSE</b> on error. */ - public function getAttribute($attr) { } + public function getAttribute(int $attribute): int|float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Set a text attribute * @link https://php.net/manual/en/numberformatter.settextattribute.php - * @param int $attr <p> + * @param int $attribute <p> * Attribute specifier - one of the * text attribute * constants. @@ -1009,25 +1068,28 @@ class NumberFormatter { * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public function setTextAttribute($attr, $value) { } + public function setTextAttribute( + int $attribute, + string $value + ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get a text attribute * @link https://php.net/manual/en/numberformatter.gettextattribute.php - * @param int $attr <p> + * @param int $attribute <p> * Attribute specifier - one of the * text attribute constants. * </p> * @return string|false Return attribute value on success, or <b>FALSE</b> on error. */ - public function getTextAttribute($attr) { } + public function getTextAttribute(int $attribute): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Set a symbol value * @link https://php.net/manual/en/numberformatter.setsymbol.php - * @param int $attr <p> + * @param int $symbol <p> * Symbol specifier, one of the * format symbol constants. * </p> @@ -1036,19 +1098,22 @@ class NumberFormatter { * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public function setSymbol($attr, $value) { } + public function setSymbol( + int $symbol, + string $value + ): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get a symbol value * @link https://php.net/manual/en/numberformatter.getsymbol.php - * @param int $attr <p> + * @param int $symbol <p> * Symbol specifier, one of the * format symbol constants. * </p> * @return string|false The symbol string or <b>FALSE</b> on error. */ - public function getSymbol($attr) { } + public function getSymbol(int $symbol): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1061,7 +1126,7 @@ class NumberFormatter { * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public function setPattern($pattern) { } + public function setPattern(string $pattern): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1069,7 +1134,7 @@ class NumberFormatter { * @link https://php.net/manual/en/numberformatter.getpattern.php * @return string|false Pattern string that is used by the formatter, or <b>FALSE</b> if an error happens. */ - public function getPattern() { } + public function getPattern(): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1081,9 +1146,11 @@ class NumberFormatter { * <b>Locale::ACTUAL_LOCALE</b>, * respectively). The default is the actual locale. * </p> - * @return string The locale name used to create the formatter. + * @return string|false The locale name used to create the formatter. */ - public function getLocale($type = null) { } + public function getLocale( + int $type = 0 + ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1091,7 +1158,7 @@ class NumberFormatter { * @link https://php.net/manual/en/numberformatter.geterrorcode.php * @return int error code from last formatter call. */ - public function getErrorCode() { } + public function getErrorCode(): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1099,142 +1166,155 @@ class NumberFormatter { * @link https://php.net/manual/en/numberformatter.geterrormessage.php * @return string error message from last formatter call. */ - public function getErrorMessage() { } + public function getErrorMessage(): string {} } -class Normalizer { +class Normalizer +{ + public const NFKC_CF = 48; + public const FORM_KC_CF = 48; /** * Default normalization options - * @link https://www.php.net/manual/en/class.normalizer.php - */ - const OPTION_DEFAULT = ""; - - /** - * No decomposition/composition - * @link https://www.php.net/manual/en/class.normalizer.php - * @removed 8.0 + * @link https://secure.php.net/manual/en/class.normalizer.php */ - const NONE = "1"; + public const OPTION_DEFAULT = ""; /** * Normalization Form D (NFD) - Canonical Decomposition - * @link https://www.php.net/manual/en/class.normalizer.php + * @link https://secure.php.net/manual/en/class.normalizer.php */ - const FORM_D = "2"; - const NFD = 2; + public const FORM_D = 4; + public const NFD = 4; /** * Normalization Form KD (NFKD) - Compatibility Decomposition - * @link https://www.php.net/manual/en/class.normalizer.php + * @link https://secure.php.net/manual/en/class.normalizer.php */ - const FORM_KD = "3"; - const NFKD = 3; + public const FORM_KD = 8; + public const NFKD = 8; /** * Normalization Form C (NFC) - Canonical Decomposition followed by * Canonical Composition - * @link https://www.php.net/manual/en/class.normalizer.php + * @link https://secure.php.net/manual/en/class.normalizer.php */ - const FORM_C = "4"; - const NFC = 4; + public const FORM_C = 16; + public const NFC = 16; /** * Normalization Form KC (NFKC) - Compatibility Decomposition, followed by * Canonical Composition - * @link https://www.php.net/manual/en/class.normalizer.php + * @link https://secure.php.net/manual/en/class.normalizer.php */ - const FORM_KC = "5"; - const NFKC = 5; - + public const FORM_KC = 32; + public const NFKC = 32; /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Normalizes the input provided and returns the normalized string * @link https://php.net/manual/en/normalizer.normalize.php - * @param string $input <p>The input string to normalize</p> - * @param string $form [optional] <p>One of the normalization forms.</p> - * @return string The normalized string or <b>NULL</b> if an error occurred. + * @param string $string <p>The input string to normalize</p> + * @param int $form <p>One of the normalization forms.</p> + * @return string|false The normalized string or <b>FALSE</b> if an error occurred. */ - public static function normalize($input, $form = Normalizer::FORM_C) { } + public static function normalize( + string $string, + int $form = Normalizer::FORM_C, + ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Checks if the provided string is already in the specified normalization form. * @link https://php.net/manual/en/normalizer.isnormalized.php - * @param string $input <p>The input string to normalize</p> - * @param string $form [optional] <p> + * @param string $string <p>The input string to normalize</p> + * @param int $form <p> * One of the normalization forms. * </p> * @return bool <b>TRUE</b> if normalized, <b>FALSE</b> otherwise or if there an error */ - public static function isNormalized($input, $form = Normalizer::FORM_C) { } -} + public static function isNormalized( + string $string, + int $form = Normalizer::FORM_C, + ): bool {} -class Locale { + /** + * @param string $string <p>The input string to normalize</p> + * @param int $form + * @return string|null <p>Returns a string containing the Decomposition_Mapping property, if present in the UCD. + * Returns null if there is no Decomposition_Mapping property for the character.</p> + * @link https://www.php.net/manual/en/normalizer.getrawdecomposition.php + * @since 7.3 + */ + public static function getRawDecomposition( + string $string, + int $form = 16 + ): ?string {} +} +class Locale +{ /** * This is locale the data actually comes from. - * @link https://php.net/manual/en/intl.locale-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const ACTUAL_LOCALE = 0; + public const ACTUAL_LOCALE = 0; /** * This is the most specific locale supported by ICU. - * @link https://php.net/manual/en/intl.locale-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const VALID_LOCALE = 1; + public const VALID_LOCALE = 1; /** * Used as locale parameter with the methods of the various locale affected classes, * such as NumberFormatter. This constant would make the methods to use default * locale. - * @link https://php.net/manual/en/intl.locale-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const DEFAULT_LOCALE = null; + public const DEFAULT_LOCALE = null; /** * Language subtag - * @link https://php.net/manual/en/intl.locale-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const LANG_TAG = "language"; + public const LANG_TAG = "language"; /** * Extended language subtag - * @link https://php.net/manual/en/intl.locale-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const EXTLANG_TAG = "extlang"; + public const EXTLANG_TAG = "extlang"; /** * Script subtag - * @link https://php.net/manual/en/intl.locale-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const SCRIPT_TAG = "script"; + public const SCRIPT_TAG = "script"; /** * Region subtag - * @link https://php.net/manual/en/intl.locale-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const REGION_TAG = "region"; + public const REGION_TAG = "region"; /** * Variant subtag - * @link https://php.net/manual/en/intl.locale-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const VARIANT_TAG = "variant"; + public const VARIANT_TAG = "variant"; /** * Grandfathered Language subtag - * @link https://php.net/manual/en/intl.locale-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const GRANDFATHERED_LANG_TAG = "grandfathered"; + public const GRANDFATHERED_LANG_TAG = "grandfathered"; /** * Private subtag - * @link https://php.net/manual/en/intl.locale-constants.php + * @link https://php.net/manual/en/class.numberformatter.php#intl.numberformatter-constants */ - const PRIVATE_TAG = "private"; - + public const PRIVATE_TAG = "private"; /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1242,7 +1322,7 @@ class Locale { * @link https://php.net/manual/en/locale.getdefault.php * @return string The current runtime locale */ - public static function getDefault() { } + public static function getDefault(): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1253,7 +1333,7 @@ class Locale { * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public static function setDefault($locale) { } + public static function setDefault(string $locale): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1262,9 +1342,9 @@ class Locale { * @param string $locale <p> * The locale to extract the primary language code from * </p> - * @return string The language code associated with the language or <b>NULL</b> in case of error. + * @return string|null The language code associated with the language or <b>NULL</b> in case of error. */ - public static function getPrimaryLanguage($locale) { } + public static function getPrimaryLanguage(string $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1273,9 +1353,9 @@ class Locale { * @param string $locale <p> * The locale to extract the script code from * </p> - * @return string The script subtag for the locale or <b>NULL</b> if not present + * @return string|null The script subtag for the locale or <b>NULL</b> if not present */ - public static function getScript($locale) { } + public static function getScript(string $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1284,9 +1364,9 @@ class Locale { * @param string $locale <p> * The locale to extract the region code from * </p> - * @return string The region subtag for the locale or <b>NULL</b> if not present + * @return string|null The region subtag for the locale or <b>NULL</b> if not present */ - public static function getRegion($locale) { } + public static function getRegion(string $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1295,9 +1375,9 @@ class Locale { * @param string $locale <p> * The locale to extract the keywords from * </p> - * @return array Associative array containing the keyword-value pairs for this locale + * @return array|false|null Associative array containing the keyword-value pairs for this locale */ - public static function getKeywords($locale) { } + public static function getKeywords(string $locale): array|false|null {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1306,13 +1386,16 @@ class Locale { * @param string $locale <p> * The locale to return a display script for * </p> - * @param string $in_locale [optional] <p> + * @param string $displayLocale <p> * Optional format locale to use to display the script name * </p> - * @return string Display name of the script for the $locale in the format appropriate for + * @return string|false Display name of the script for the $locale in the format appropriate for * $in_locale. */ - public static function getDisplayScript($locale, $in_locale = null) { } + public static function getDisplayScript( + string $locale, + string|null $displayLocale = null + ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1321,13 +1404,16 @@ class Locale { * @param string $locale <p> * The locale to return a display region for. * </p> - * @param string $in_locale [optional] <p> + * @param string $displayLocale <p> * Optional format locale to use to display the region name * </p> - * @return string display name of the region for the $locale in the format appropriate for + * @return string|false display name of the region for the $locale in the format appropriate for * $in_locale. */ - public static function getDisplayRegion($locale, $in_locale = null) { } + public static function getDisplayRegion( + string $locale, + string|null $displayLocale = null + ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1336,10 +1422,13 @@ class Locale { * @param string $locale <p> * The locale to return a display name for. * </p> - * @param string $in_locale [optional] <p>optional format locale</p> - * @return string Display name of the locale in the format appropriate for $in_locale. + * @param string $displayLocale <p>optional format locale</p> + * @return string|false Display name of the locale in the format appropriate for $in_locale. */ - public static function getDisplayName($locale, $in_locale = null) { } + public static function getDisplayName( + string $locale, + string|null $displayLocale = null + ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1348,13 +1437,16 @@ class Locale { * @param string $locale <p> * The locale to return a display language for * </p> - * @param string $in_locale [optional] <p> + * @param string $displayLocale <p> * Optional format locale to use to display the language name * </p> - * @return string display name of the language for the $locale in the format appropriate for + * @return string|false display name of the language for the $locale in the format appropriate for * $in_locale. */ - public static function getDisplayLanguage($locale, $in_locale = null) { } + public static function getDisplayLanguage( + string $locale, + string|null $displayLocale = null + ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1363,13 +1455,16 @@ class Locale { * @param string $locale <p> * The locale to return a display variant for * </p> - * @param string $in_locale [optional] <p> + * @param string $displayLocale <p> * Optional format locale to use to display the variant name * </p> - * @return string Display name of the variant for the $locale in the format appropriate for + * @return string|false Display name of the variant for the $locale in the format appropriate for * $in_locale. */ - public static function getDisplayVariant($locale, $in_locale = null) { } + public static function getDisplayVariant( + string $locale, + string|null $displayLocale = null + ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1393,9 +1488,9 @@ class Locale { * (e.g. 'variant0', 'variant1', etc.). * </p> * </p> - * @return string The corresponding locale identifier. + * @return string|false The corresponding locale identifier. */ - public static function composeLocale(array $subtags) { } + public static function composeLocale(array $subtags): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1406,14 +1501,14 @@ class Locale { * 'private' subtags can take maximum 15 values whereas 'extlang' can take * maximum 3 values. * </p> - * @return array an array containing a list of key-value pairs, where the keys + * @return array|null an array containing a list of key-value pairs, where the keys * identify the particular locale ID subtags, and the values are the * associated subtag values. The array will be ordered as the locale id * subtags e.g. in the locale id if variants are '-varX-varY-varZ' then the * returned array will have variant0=>varX , variant1=>varY , * variant2=>varZ */ - public static function parseLocale($locale) { } + public static function parseLocale(string $locale): ?array {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1422,57 +1517,66 @@ class Locale { * @param string $locale <p> * The locale to extract the variants from * </p> - * @return array The array containing the list of all variants subtag for the locale + * @return array|null The array containing the list of all variants subtag for the locale * or <b>NULL</b> if not present */ - public static function getAllVariants($locale) { } + public static function getAllVariants(string $locale): ?array {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Checks if a language tag filter matches with locale * @link https://php.net/manual/en/locale.filtermatches.php - * @param string $langtag <p> + * @param string $languageTag <p> * The language tag to check * </p> * @param string $locale <p> * The language range to check against * </p> - * @param bool $canonicalize [optional] <p> + * @param bool $canonicalize <p> * If true, the arguments will be converted to canonical form before * matching. * </p> - * @return bool <b>TRUE</b> if $locale matches $langtag <b>FALSE</b> otherwise. + * @return bool|null <b>TRUE</b> if $locale matches $langtag <b>FALSE</b> otherwise. */ - public static function filterMatches($langtag, $locale, $canonicalize = false) { } + public static function filterMatches( + string $languageTag, + string $locale, + bool $canonicalize = false + ): ?bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Searches the language tag list for the best match to the language * @link https://php.net/manual/en/locale.lookup.php - * @param array $langtag <p> + * @param array $languageTag <p> * An array containing a list of language tags to compare to * <i>locale</i>. Maximum 100 items allowed. * </p> * @param string $locale <p> * The locale to use as the language range when matching. * </p> - * @param bool $canonicalize [optional] <p> + * @param bool $canonicalize <p> * If true, the arguments will be converted to canonical form before * matching. * </p> - * @param string $default [optional] <p> + * @param string $defaultLocale <p> * The locale to use if no match is found. * </p> - * @return string The closest matching language tag or default value. + * @return string|null The closest matching language tag or default value. */ - public static function lookup(array $langtag, $locale, $canonicalize = false, $default = null) { } + public static function lookup( + array $languageTag, + string $locale, + bool $canonicalize = false, + string|null $defaultLocale = null + ): ?string {} /** * @link https://php.net/manual/en/locale.canonicalize.php * @param string $locale - * @return string + * @return string|null */ - public static function canonicalize($locale) { } + public static function canonicalize(string $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1481,13 +1585,13 @@ class Locale { * @param string $header <p> * The string containing the "Accept-Language" header according to format in RFC 2616. * </p> - * @return string The corresponding locale identifier. + * @return string|false The corresponding locale identifier. */ - public static function acceptFromHttp($header) { } + public static function acceptFromHttp(string $header): string|false {} } -class MessageFormatter { - +class MessageFormatter +{ /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Constructs a new Message Formatter @@ -1501,8 +1605,12 @@ class MessageFormatter { * umsg_autoQuoteApostrophe * before being interpreted. * </p> + * @throws IntlException on failure. */ - public function __construct($locale, $pattern) { } + public function __construct( + string $locale, + string $pattern + ) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1517,20 +1625,23 @@ class MessageFormatter { * umsg_autoQuoteApostrophe * before being interpreted. * </p> - * @return MessageFormatter The formatter object + * @return MessageFormatter|null The formatter object */ - public static function create($locale, $pattern) { } + public static function create( + string $locale, + string $pattern + ): ?MessageFormatter {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Format the message * @link https://php.net/manual/en/messageformatter.format.php - * @param array $args <p> + * @param array $values <p> * Arguments to insert into the format string * </p> * @return string|false The formatted string, or <b>FALSE</b> if an error occurred */ - public function format(array $args) { } + public function format(array $values): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1545,23 +1656,27 @@ class MessageFormatter { * umsg_autoQuoteApostrophe * before being interpreted. * </p> - * @param array $args <p> + * @param array $values <p> * The array of values to insert into the format string * </p> * @return string|false The formatted pattern string or <b>FALSE</b> if an error occurred */ - public static function formatMessage($locale, $pattern, array $args) { } + public static function formatMessage( + string $locale, + string $pattern, + array $values + ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Parse input string according to pattern * @link https://php.net/manual/en/messageformatter.parse.php - * @param string $value <p> + * @param string $string <p> * The string to parse * </p> * @return array|false An array containing the items extracted, or <b>FALSE</b> on error */ - public function parse($value) { } + public function parse(string $string): array|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1573,12 +1688,16 @@ class MessageFormatter { * @param string $pattern <p> * The pattern with which to parse the <i>value</i>. * </p> - * @param string $source <p> + * @param string $message <p> * The string to parse, conforming to the <i>pattern</i>. * </p> * @return array|false An array containing items extracted, or <b>FALSE</b> on error */ - public static function parseMessage($locale, $pattern, $source) { } + public static function parseMessage( + string $locale, + string $pattern, + string $message + ): array|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1592,15 +1711,15 @@ class MessageFormatter { * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public function setPattern($pattern) { } + public function setPattern(string $pattern): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the pattern used by the formatter * @link https://php.net/manual/en/messageformatter.getpattern.php - * @return string The pattern string for this message formatter + * @return string|false The pattern string for this message formatter */ - public function getPattern() { } + public function getPattern(): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1608,7 +1727,7 @@ class MessageFormatter { * @link https://php.net/manual/en/messageformatter.getlocale.php * @return string The locale name */ - public function getLocale() { } + public function getLocale(): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1616,7 +1735,7 @@ class MessageFormatter { * @link https://php.net/manual/en/messageformatter.geterrorcode.php * @return int The error code, one of UErrorCode values. Initial value is U_ZERO_ERROR. */ - public function getErrorCode() { } + public function getErrorCode(): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1624,68 +1743,74 @@ class MessageFormatter { * @link https://php.net/manual/en/messageformatter.geterrormessage.php * @return string Description of the last error. */ - public function getErrorMessage() { } + public function getErrorMessage(): string {} } -class IntlDateFormatter { - +class IntlDateFormatter +{ /** * Completely specified style (Tuesday, April 12, 1952 AD or 3:30:42pm PST) * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ - const FULL = 0; + public const FULL = 0; /** * Long style (January 12, 1952 or 3:30:32pm) * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ - const LONG = 1; + public const LONG = 1; /** * Medium style (Jan 12, 1952) * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ - const MEDIUM = 2; + public const MEDIUM = 2; /** * Most abbreviated style, only essential data (12/13/52 or 3:30pm) * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ - const SHORT = 3; + public const SHORT = 3; /** * Do not include this element * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ - const NONE = -1; + public const NONE = -1; /** * Gregorian Calendar * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ - const GREGORIAN = 1; + public const GREGORIAN = 1; /** * Non-Gregorian Calendar * @link https://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants */ - const TRADITIONAL = 0; - - const RELATIVE_FULL = 0; - const RELATIVE_LONG = 1; - const RELATIVE_MEDIUM = 2; - const RELATIVE_SHORT = 3; - + public const TRADITIONAL = 0; + public const RELATIVE_FULL = 128; + public const RELATIVE_LONG = 129; + public const RELATIVE_MEDIUM = 130; + public const RELATIVE_SHORT = 131; + public const PATTERN = -2; /** * @param string|null $locale - * @param int $datetype - * @param int $timetype + * @param int $dateType + * @param int $timeType * @param mixed|null $timezone [optional] * @param mixed|null $calendar [optional] * @param string $pattern [optional] */ - public function __construct($locale, $datetype, $timetype, $timezone = null, $calendar = null, $pattern = '') { } + public function __construct( + string|null $locale, + int $dateType = 0, + int $timeType = 0, + $timezone = null, + $calendar = null, + string|null $pattern = null + ) {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1694,14 +1819,14 @@ class IntlDateFormatter { * @param string $locale <p> * Locale to use when formatting or parsing; default is specified in the ini setting intl.default_locale. * </p> - * @param int $datetype <p> + * @param int $dateType <p> * Date type to use (<b>none</b>, * <b>short</b>, <b>medium</b>, * <b>long</b>, <b>full</b>). * This is one of the * IntlDateFormatter constants. * </p> - * @param int $timetype <p> + * @param int $timeType <p> * Time type to use (<b>none</b>, * <b>short</b>, <b>medium</b>, * <b>long</b>, <b>full</b>). @@ -1720,123 +1845,116 @@ class IntlDateFormatter { * Optional pattern to use when formatting or parsing. * Possible patterns are documented at http://userguide.icu-project.org/formatparse/datetime. * </p> - * @return IntlDateFormatter + * @return IntlDateFormatter|null */ - public static function create($locale, $datetype, $timetype, $timezone = null, $calendar = null, $pattern = '') { } + public static function create( + string|null $locale, + int $dateType = 0, + int $timeType = 0, + $timezone = null, + IntlCalendar|int|null $calendar = null, + string|null $pattern = null + ): ?IntlDateFormatter {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the datetype used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.getdatetype.php - * @return int The current date type value of the formatter. + * @return int|false The current date type value of the formatter. */ - public function getDateType() { } + public function getDateType(): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the timetype used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.gettimetype.php - * @return int The current date type value of the formatter. + * @return int|false The current date type value of the formatter. */ - public function getTimeType() { } + public function getTimeType(): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the calendar used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.getcalendar.php - * @return int The calendar being used by the formatter. + * @return int|false The calendar being used by the formatter. */ - public function getCalendar() { } + public function getCalendar(): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * sets the calendar used to the appropriate calendar, which must be * @link https://php.net/manual/en/intldateformatter.setcalendar.php - * @param int $which <p> + * @param int $calendar <p> * The calendar to use. * Default is <b>IntlDateFormatter::GREGORIAN</b>. * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public function setCalendar($which) { } + public function setCalendar(IntlCalendar|int|null $calendar): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the timezone-id used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.gettimezoneid.php - * @return string ID string for the time zone used by this formatter. + * @return string|false ID string for the time zone used by this formatter. */ - public function getTimeZoneId() { } + public function getTimeZoneId(): string|false {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)<br/> * Get copy of formatter's calendar object - * @link https://www.php.net/manual/en/intldateformatter.getcalendarobject.php - * @return IntlCalendar A copy of the internal calendar object used by this formatter. + * @link https://secure.php.net/manual/en/intldateformatter.getcalendarobject.php + * @return IntlCalendar|false|null A copy of the internal calendar object used by this formatter. */ - public function getCalendarObject() { } + public function getCalendarObject(): IntlCalendar|false|null {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)<br/> * Get formatter's timezone - * @link https://www.php.net/manual/en/intldateformatter.gettimezone.php + * @link https://secure.php.net/manual/en/intldateformatter.gettimezone.php * @return IntlTimeZone|false The associated IntlTimeZone object or FALSE on failure. */ - public function getTimeZone() { } - - /** - * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> - * Sets the time zone to use - * @link https://php.net/manual/en/intldateformatter.settimezoneid.php - * @param string $zone <p> - * The time zone ID string of the time zone to use. - * If <b>NULL</b> or the empty string, the default time zone for the runtime is used. - * </p> - * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. - * @deprecated 5.5 https://www.php.net/manual/en/migration55.deprecated.php - * @removed 7.0 - */ - public function setTimeZoneId($zone) { } + public function getTimeZone(): IntlTimeZone|false {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)<br/> * Sets formatter's timezone * @link https://php.net/manual/en/intldateformatter.settimezone.php - * @param mixed $zone <p> + * @param mixed $timezone <p> * The timezone to use for this formatter. This can be specified in the * following forms: * <ul> * <li> * <p> * <b>NULL</b>, in which case the default timezone will be used, as specified in - * the ini setting {@link "https://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone" date.timezone} or - * through the function {@link "https://www.php.net/manual/en/function.date-default-timezone-set.php" date_default_timezone_set()} and as - * returned by {@link "https://www.php.net/manual/en/function.date-default-timezone-get.php" date_default_timezone_get()}. + * the ini setting {@link "https://secure.php.net/manual/en/datetime.configuration.php#ini.date.timezone" date.timezone} or + * through the function {@link "https://secure.php.net/manual/en/function.date-default-timezone-set.php" date_default_timezone_set()} and as + * returned by {@link "https://secure.php.net/manual/en/function.date-default-timezone-get.php" date_default_timezone_get()}. * </p> * </li> * <li> * <p> - * An {@link "https://www.php.net/manual/en/class.intltimezone.php" IntlTimeZone}, which will be used directly. + * An {@link "https://secure.php.net/manual/en/class.intltimezone.php" IntlTimeZone}, which will be used directly. * </p> * </li> * <li> * <p> - * A {@link "https://www.php.net/manual/en/class.datetimezone.php" DateTimeZone}. Its identifier will be extracted + * A {@link "https://secure.php.net/manual/en/class.datetimezone.php" DateTimeZone}. Its identifier will be extracted * and an ICU timezone object will be created; the timezone will be backed * by ICU's database, not PHP's. * </p> * </li> - *<li> + * <li> * <p> - * A {@link "https://www.php.net/manual/en/language.types.string.php" string}, which should be a valid ICU timezone identifier. + * A {@link "https://secure.php.net/manual/en/language.types.string.php" string}, which should be a valid ICU timezone identifier. * See <b>IntlTimeZone::createTimeZoneIDEnumeration()</b>. Raw offsets such as <em>"GMT+08:30"</em> are also accepted. * </p> * </li> * </ul> * </p> - * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. + * @return bool|null <b>TRUE</b> on success (since 8.3 - previously null) or <b>FALSE</b> on failure. */ - public function setTimeZone($zone) { } + public function setTimeZone($timezone): ?bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1849,24 +1967,26 @@ class IntlDateFormatter { * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. * Bad formatstrings are usually the cause of the failure. */ - public function setPattern($pattern) { } + public function setPattern(string $pattern): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the pattern used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.getpattern.php - * @return string The pattern string being used to format/parse. + * @return string|false The pattern string being used to format/parse. */ - public function getPattern() { } + public function getPattern(): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the locale used by formatter * @link https://php.net/manual/en/intldateformatter.getlocale.php - * @param int $which [optional] + * @param int $type [optional] * @return string|false the locale of this formatter or 'false' if error */ - public function getLocale($which = null) { } + public function getLocale( + int $type = 0 + ): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1875,9 +1995,9 @@ class IntlDateFormatter { * @param bool $lenient <p> * Sets whether the parser is lenient or not, default is <b>TRUE</b> (lenient). * </p> - * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. + * @return void */ - public function setLenient($lenient) { } + public function setLenient(bool $lenient): void {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1885,13 +2005,13 @@ class IntlDateFormatter { * @link https://php.net/manual/en/intldateformatter.islenient.php * @return bool <b>TRUE</b> if parser is lenient, <b>FALSE</b> if parser is strict. By default the parser is lenient. */ - public function isLenient() { } + public function isLenient(): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Format the date/time value as a string * @link https://php.net/manual/en/intldateformatter.format.php - * @param mixed $value <p> + * @param mixed $datetime <p> * Value to format. This may be a <b>DateTime</b> object, * an integer representing a Unix timestamp value (seconds * since epoch, UTC) or an array in the format output by @@ -1899,17 +2019,19 @@ class IntlDateFormatter { * </p> * @return string|false The formatted string or, if an error occurred, <b>FALSE</b>. */ - public function format($value) { } + public function format( + $datetime, + ): string|false {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)<br/> * Formats an object - * @link https://www.php.net/manual/en/intldateformatter.formatobject.php - * @param object $object <p> - * An object of type {@link "https://www.php.net/manual/en/class.intlcalendar.php" IntlCalendar} or {@link "https://www.php.net/manual/en/class.datetime.php" DateTime}. The timezone information in the object will be used. + * @link https://secure.php.net/manual/en/intldateformatter.formatobject.php + * @param object $datetime <p> + * An object of type {@link "https://secure.php.net/manual/en/class.intlcalendar.php" IntlCalendar} or {@link "https://secure.php.net/manual/en/class.datetime.php" DateTime}. The timezone information in the object will be used. * </p> * @param mixed $format [optional] <p> - * How to format the date/time. This can either be an {@link "https://www.php.net/manual/en/language.types.array.php" array} with + * How to format the date/time. This can either be an {@link "https://secure.php.net/manual/en/language.types.array.php" array} with * two elements (first the date style, then the time style, these being one * of the constants <b>IntlDateFormatter::NONE</b>, * <b>IntlDateFormatter::SHORT</b>, @@ -1917,50 +2039,50 @@ class IntlDateFormatter { * <b>IntlDateFormatter::LONG</b>, * <b>IntlDateFormatter::FULL</b>), a long with * the value of one of these constants (in which case it will be used both - * for the time and the date) or a {@link "https://www.php.net/manual/en/language.types.string.php" string} with the format + * for the time and the date) or a {@link "https://secure.php.net/manual/en/language.types.string.php" string} with the format * described in {@link "http://www.icu-project.org/apiref/icu4c/classSimpleDateFormat.html#details" the ICU documentation}. - * If <br>NULL</br>, the default style will be used. + * If <b>NULL</b>, the default style will be used. * </p> - * @param string $locale [optional] <p> - * The locale to use, or <b>NULL</b> to use the {@link "https://www.php.net/manual/en/intl.configuration.php#ini.intl.default-locale"default one}.</p> + * @param string|null $locale [optional] <p> + * The locale to use, or <b>NULL</b> to use the {@link "https://secure.php.net/manual/en/intl.configuration.php#ini.intl.default-locale" default one}.</p> * @return string|false A string with result or <b>FALSE</b> on failure. */ - public static function formatObject($object, $format = null, $locale = null) { } + public static function formatObject($datetime, $format = null, string|null $locale = null): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Parse string to a timestamp value * @link https://php.net/manual/en/intldateformatter.parse.php - * @param string $value <p> + * @param string $string <p> * string to convert to a time * </p> - * @param int $position [optional] <p> + * @param int &$offset [optional] <p> * Position at which to start the parsing in $value (zero-based). * If no error occurs before $value is consumed, $parse_pos will contain -1 * otherwise it will contain the position at which parsing ended (and the error occurred). * This variable will contain the end position if the parse fails. * If $parse_pos > strlen($value), the parse fails immediately. * </p> - * @return int timestamp parsed value + * @return int|float|false timestamp parsed value */ - public function parse($value, &$position = null) { } + public function parse(string $string, &$offset = null): int|float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Parse string to a field-based time value * @link https://php.net/manual/en/intldateformatter.localtime.php - * @param string $value <p> + * @param string $string <p> * string to convert to a time * </p> - * @param int $position [optional] <p> + * @param int &$offset [optional] <p> * Position at which to start the parsing in $value (zero-based). * If no error occurs before $value is consumed, $parse_pos will contain -1 * otherwise it will contain the position at which parsing ended . * If $parse_pos > strlen($value), the parse fails immediately. * </p> - * @return array Localtime compatible array of integers : contains 24 hour clock value in tm_hour field + * @return array|false Localtime compatible array of integers : contains 24 hour clock value in tm_hour field */ - public function localtime($value, &$position = null) { } + public function localtime(string $string, &$offset = null): array|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1968,7 +2090,7 @@ class IntlDateFormatter { * @link https://php.net/manual/en/intldateformatter.geterrorcode.php * @return int The error code, one of UErrorCode values. Initial value is U_ZERO_ERROR. */ - public function getErrorCode() { } + public function getErrorCode(): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -1976,17 +2098,27 @@ class IntlDateFormatter { * @link https://php.net/manual/en/intldateformatter.geterrormessage.php * @return string Description of the last error. */ - public function getErrorMessage() { } -} + public function getErrorMessage(): string {} -class ResourceBundle implements IteratorAggregate { + /** + * @since 8.4 + */ + public function parseToCalendar(string $string, &$offset = null): int|float|false {} +} +class ResourceBundle implements IteratorAggregate, Countable +{ /** - * @param $locale - * @param $bundlename - * @param $fallback [optional] + * @link https://www.php.net/manual/en/resourcebundle.create.php + * @param string $locale <p>Locale for which the resources should be loaded (locale name, e.g. en_CA).</p> + * @param string $bundle <p>The directory where the data is stored or the name of the .dat file.</p> + * @param bool $fallback [optional] <p>Whether locale should match exactly or fallback to parent locale is allowed.</p> */ - public function __construct($locale, $bundlename, $fallback) { } + public function __construct( + string|null $locale, + string|null $bundle, + bool $fallback = true + ) {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> @@ -1995,15 +2127,19 @@ class ResourceBundle implements IteratorAggregate { * @param string $locale <p> * Locale for which the resources should be loaded (locale name, e.g. en_CA). * </p> - * @param string $bundlename <p> + * @param string $bundle <p> * The directory where the data is stored or the name of the .dat file. * </p> * @param bool $fallback [optional] <p> * Whether locale should match exactly or fallback to parent locale is allowed. * </p> - * @return ResourceBundle|false <b>ResourceBundle</b> object or <b>FALSE</b> on error. + * @return ResourceBundle|null <b>ResourceBundle</b> object or <b>null</b> on error. */ - public static function create($locale, $bundlename, $fallback = null) { } + public static function create( + string|null $locale, + string|null $bundle, + bool $fallback = true + ): ?ResourceBundle {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> @@ -2012,31 +2148,32 @@ class ResourceBundle implements IteratorAggregate { * @param string|int $index <p> * Data index, must be string or integer. * </p> + * @param bool $fallback * @return mixed the data located at the index or <b>NULL</b> on error. Strings, integers and binary data strings * are returned as corresponding PHP types, integer array is returned as PHP array. Complex types are * returned as <b>ResourceBundle</b> object. */ - public function get($index) { } + public function get($index, bool $fallback = true): mixed {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> * Get number of elements in the bundle * @link https://php.net/manual/en/resourcebundle.count.php - * @return int number of elements in the bundle. + * @return int<0,max> number of elements in the bundle. */ - public function count() { } + public function count(): int {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> * Get supported locales * @link https://php.net/manual/en/resourcebundle.locales.php - * @param string $bundlename <p> + * @param string $bundle <p> * Path of ResourceBundle for which to get available locales, or * empty string for default locales list. * </p> - * @return array the list of locales supported by the bundle. + * @return array|false the list of locales supported by the bundle. */ - public static function getLocales($bundlename) { } + public static function getLocales(string $bundle): array|false {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> @@ -2044,7 +2181,7 @@ class ResourceBundle implements IteratorAggregate { * @link https://php.net/manual/en/resourcebundle.geterrorcode.php * @return int error code from last bundle object call. */ - public function getErrorCode() { } + public function getErrorCode(): int {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> @@ -2052,30 +2189,34 @@ class ResourceBundle implements IteratorAggregate { * @link https://php.net/manual/en/resourcebundle.geterrormessage.php * @return string error message from last bundle object's call. */ - public function getErrorMessage() { } + public function getErrorMessage(): string {} /** + * @return Iterator * @since 8.0 */ - public function getIterator(){} + public function getIterator(): Iterator {} } /** * @since 5.4 */ -class Transliterator { - const FORWARD = 0; - const REVERSE = 1; - - public $id; +class Transliterator +{ + public const FORWARD = 0; + public const REVERSE = 1; + /** + * Starting 8.2 $id is readonly to unlock subclassing it + */ + public string $id; /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Private constructor to deny instantiation * @link https://php.net/manual/en/transliterator.construct.php */ - final private function __construct() { } + final private function __construct() {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> @@ -2086,14 +2227,17 @@ class Transliterator { * </p> * @param int $direction [optional] <p> * The direction, defaults to - * >Transliterator::FORWARD. + * Transliterator::FORWARD. * May also be set to * Transliterator::REVERSE. * </p> - * @return Transliterator a <b>Transliterator</b> object on success, + * @return Transliterator|null a <b>Transliterator</b> object on success, * or <b>NULL</b> on failure. */ - public static function create($id, $direction = null) { } + public static function create( + string $id, + int $direction = 0 + ): ?Transliterator {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> @@ -2102,40 +2246,43 @@ class Transliterator { * @param string $rules <p> * The rules. * </p> - * @param string $direction [optional] <p> + * @param int $direction [optional] <p> * The direction, defaults to - * >Transliterator::FORWARD. + * {@see Transliterator::FORWARD}. * May also be set to - * Transliterator::REVERSE. + * {@see Transliterator::REVERSE}. * </p> - * @return Transliterator a <b>Transliterator</b> object on success, + * @return Transliterator|null a <b>Transliterator</b> object on success, * or <b>NULL</b> on failure. */ - public static function createFromRules($rules, $direction = null) { } + public static function createFromRules( + string $rules, + int $direction = 0 + ): ?Transliterator {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Create an inverse transliterator * @link https://php.net/manual/en/transliterator.createinverse.php - * @return Transliterator a <b>Transliterator</b> object on success, + * @return Transliterator|null a <b>Transliterator</b> object on success, * or <b>NULL</b> on failure */ - public function createInverse() { } + public function createInverse(): ?Transliterator {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Get transliterator IDs * @link https://php.net/manual/en/transliterator.listids.php - * @return array An array of registered transliterator IDs on success, + * @return array|false An array of registered transliterator IDs on success, * or <b>FALSE</b> on failure. */ - public static function listIDs() { } + public static function listIDs(): array|false {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Transliterate a string * @link https://php.net/manual/en/transliterator.transliterate.php - * @param string $subject <p> + * @param string $string <p> * The string to be transformed. * </p> * @param int $start [optional] <p> @@ -2150,240 +2297,308 @@ class Transliterator { * </p> * @return string|false The transfomed string on success, or <b>FALSE</b> on failure. */ - public function transliterate($subject, $start = null, $end = null) { } + public function transliterate( + string $string, + int $start = 0, + int $end = -1 + ): string|false {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Get last error code * @link https://php.net/manual/en/transliterator.geterrorcode.php - * @return int The error code on success, + * @return int|false The error code on success, * or <b>FALSE</b> if none exists, or on failure. */ - public function getErrorCode() { } + public function getErrorCode(): int|false {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Get last error message * @link https://php.net/manual/en/transliterator.geterrormessage.php - * @return string The error code on success, + * @return string|false The error code on success, * or <b>FALSE</b> if none exists, or on failure. */ - public function getErrorMessage() { } + public function getErrorMessage(): string|false {} } /** * @link https://php.net/manual/en/class.spoofchecker.php */ -class Spoofchecker { - const SINGLE_SCRIPT_CONFUSABLE = 1; - const MIXED_SCRIPT_CONFUSABLE = 2; - const WHOLE_SCRIPT_CONFUSABLE = 4; - const ANY_CASE = 8; - const SINGLE_SCRIPT = 16; - const INVISIBLE = 32; - const CHAR_LIMIT = 64; +class Spoofchecker +{ + public const SINGLE_SCRIPT_CONFUSABLE = 1; + public const MIXED_SCRIPT_CONFUSABLE = 2; + public const WHOLE_SCRIPT_CONFUSABLE = 4; + public const ANY_CASE = 8; + public const SINGLE_SCRIPT = 16; + public const INVISIBLE = 32; + public const CHAR_LIMIT = 64; + public const ASCII = 268435456; + public const HIGHLY_RESTRICTIVE = 805306368; + public const MODERATELY_RESTRICTIVE = 1073741824; + public const MINIMALLY_RESTRICTIVE = 1342177280; + public const UNRESTRICTIVE = 1610612736; + public const SINGLE_SCRIPT_RESTRICTIVE = 536870912; + public const MIXED_NUMBERS = 1; + public const HIDDEN_OVERLAY = 2; + + /** + * @since 8.4 + */ + public const IGNORE_SPACE = 1; + /** + * @since 8.4 + */ + public const CASE_INSENSITIVE = 2; + + /** + * @since 8.4 + */ + public const ADD_CASE_MAPPINGS = 4; + + /** + * @since 8.4 + */ + public const SIMPLE_CASE_INSENSITIVE = 6; /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Constructor * @link https://php.net/manual/en/spoofchecker.construct.php */ - public function __construct() { } + public function __construct() {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Checks if a given text contains any suspicious characters * @link https://php.net/manual/en/spoofchecker.issuspicious.php - * @param string $text <p> + * @param string $string <p> * </p> - * @param string $error [optional] <p> + * @param string &$errorCode [optional] <p> * </p> * @return bool */ - public function isSuspicious($text, &$error = null) { } + public function isSuspicious(string $string, &$errorCode = null): bool {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Checks if a given text contains any confusable characters * @link https://php.net/manual/en/spoofchecker.areconfusable.php - * @param string $s1 <p> + * @param string $string1 <p> * </p> - * @param string $s2 <p> + * @param string $string2 <p> * </p> - * @param string $error [optional] <p> + * @param int &$errorCode [optional] <p> * </p> * @return bool */ - public function areConfusable($s1, $s2, &$error = null) { } + public function areConfusable( + string $string1, + string $string2, + &$errorCode = null + ): bool {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Locales to use when running checks * @link https://php.net/manual/en/spoofchecker.setallowedlocales.php - * @param string $locale_list <p> + * @param string $locales <p> * </p> * @return void */ - public function setAllowedLocales($locale_list) { } + public function setAllowedLocales(string $locales): void {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Set the checks to run * @link https://php.net/manual/en/spoofchecker.setchecks.php - * @param string $checks <p> + * @param int $checks <p> * </p> * @return void */ - public function setChecks($checks) { } + public function setChecks(int $checks): void {} + + /** + * @param int $level + */ + public function setRestrictionLevel(int $level): void {} + + /** + * @since 8.4 + */ + public function setAllowedChars(string $pattern, int $patternOptions = 0): void {} } /** * @since 5.5 */ -class IntlGregorianCalendar extends IntlCalendar { +class IntlGregorianCalendar extends IntlCalendar +{ + /** + * @link https://www.php.net/manual/en/intlgregoriancalendar.construct + * @param int $timezoneOrYear [optional] + * @param int $localeOrMonth [optional] + * @param int $day [optional] + * @param int $hour [optional] + * @param int $minute [optional] + * @param int $second [optional] + */ + public function __construct($timezoneOrYear, $localeOrMonth, $day, $hour, $minute, $second) {} + /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * @param mixed $timeZone * @param string $locale * @return IntlGregorianCalendar */ - public static function createInstance($timeZone = null, $locale = null) { } + public static function createInstance($timeZone = null, $locale = null) {} /** - * @param double $change - * + * @param float $timestamp */ - public function setGregorianChange($change) { } + public function setGregorianChange(float $timestamp): bool {} /** - * @return double $change + * @return float */ - public function getGregorianChange() { } + public function getGregorianChange(): float {} /** * @param int $year * @return bool */ - public function isLeapYear($year) { } + public function isLeapYear(int $year): bool {} + + /** + * @since 8.3 + */ + public static function createFromDate(int $year, int $month, int $dayOfMonth): static {} + + /** + * @since 8.3 + */ + public static function createFromDateTime(int $year, int $month, int $dayOfMonth, int $hour, int $minute, ?int $second = null): static {} } /** * @since 5.5 */ -class IntlCalendar { +class IntlCalendar +{ /* Constants */ - const FIELD_ERA = 0; - const FIELD_YEAR = 1; - const FIELD_MONTH = 2; - const FIELD_WEEK_OF_YEAR = 3; - const FIELD_WEEK_OF_MONTH = 4; - const FIELD_DATE = 5; - const FIELD_DAY_OF_YEAR = 6; - const FIELD_DAY_OF_WEEK = 7; - const FIELD_DAY_OF_WEEK_IN_MONTH = 8; - const FIELD_AM_PM = 9; - const FIELD_HOUR = 10; - const FIELD_HOUR_OF_DAY = 11; - const FIELD_MINUTE = 12; - const FIELD_SECOND = 13; - const FIELD_MILLISECOND = 14; - const FIELD_ZONE_OFFSET = 15; - const FIELD_DST_OFFSET = 16; - const FIELD_YEAR_WOY = 17; - const FIELD_DOW_LOCAL = 18; - const FIELD_EXTENDED_YEAR = 19; - const FIELD_JULIAN_DAY = 20; - const FIELD_MILLISECONDS_IN_DAY = 21; - const FIELD_IS_LEAP_MONTH = 22; - const FIELD_FIELD_COUNT = 23; - const FIELD_DAY_OF_MONTH = 5; - const DOW_SUNDAY = 1; - const DOW_MONDAY = 2; - const DOW_TUESDAY = 3; - const DOW_WEDNESDAY = 4; - const DOW_THURSDAY = 5; - const DOW_FRIDAY = 6; - const DOW_SATURDAY = 7; - const DOW_TYPE_WEEKDAY = 0; - const DOW_TYPE_WEEKEND = 1; - const DOW_TYPE_WEEKEND_OFFSET = 2; - const DOW_TYPE_WEEKEND_CEASE = 3; - const WALLTIME_FIRST = 1; - const WALLTIME_LAST = 0; - const WALLTIME_NEXT_VALID = 2; + public const FIELD_ERA = 0; + public const FIELD_YEAR = 1; + public const FIELD_MONTH = 2; + public const FIELD_WEEK_OF_YEAR = 3; + public const FIELD_WEEK_OF_MONTH = 4; + public const FIELD_DATE = 5; + public const FIELD_DAY_OF_YEAR = 6; + public const FIELD_DAY_OF_WEEK = 7; + public const FIELD_DAY_OF_WEEK_IN_MONTH = 8; + public const FIELD_AM_PM = 9; + public const FIELD_HOUR = 10; + public const FIELD_HOUR_OF_DAY = 11; + public const FIELD_MINUTE = 12; + public const FIELD_SECOND = 13; + public const FIELD_MILLISECOND = 14; + public const FIELD_ZONE_OFFSET = 15; + public const FIELD_DST_OFFSET = 16; + public const FIELD_YEAR_WOY = 17; + public const FIELD_DOW_LOCAL = 18; + public const FIELD_EXTENDED_YEAR = 19; + public const FIELD_JULIAN_DAY = 20; + public const FIELD_MILLISECONDS_IN_DAY = 21; + public const FIELD_IS_LEAP_MONTH = 22; + public const FIELD_FIELD_COUNT = 23; + public const FIELD_DAY_OF_MONTH = 5; + public const DOW_SUNDAY = 1; + public const DOW_MONDAY = 2; + public const DOW_TUESDAY = 3; + public const DOW_WEDNESDAY = 4; + public const DOW_THURSDAY = 5; + public const DOW_FRIDAY = 6; + public const DOW_SATURDAY = 7; + public const DOW_TYPE_WEEKDAY = 0; + public const DOW_TYPE_WEEKEND = 1; + public const DOW_TYPE_WEEKEND_OFFSET = 2; + public const DOW_TYPE_WEEKEND_CEASE = 3; + public const WALLTIME_FIRST = 1; + public const WALLTIME_LAST = 0; + public const WALLTIME_NEXT_VALID = 2; /* Methods */ /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Add a (signed) amount of time to a field - * @link https://www.php.net/manual/en/intlcalendar.add.php + * @link https://secure.php.net/manual/en/intlcalendar.add.php * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. * These are integer values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @param int $amount <p>The signed amount to add to the current field. If the amount is positive, the instant will be moved forward; if it is negative, the instant wil be moved into the past. The unit is implicit to the field type. + * @param int $value <p>The signed amount to add to the current field. If the amount is positive, the instant will be moved forward; if it is negative, the instant wil be moved into the past. The unit is implicit to the field type. * For instance, hours for <b>IntlCalendar::FIELD_HOUR_OF_DAY</b>.</p> * @return bool Returns TRUE on success or FALSE on failure. */ - public function add($field, $amount) { } + public function add( + int $field, + int $value + ): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether this object's time is after that of the passed object - * https://www.php.net/manual/en/intlcalendar.after.php - * @param IntlCalendar $calendar <p>The calendar whose time will be checked against this object's time.</p> + * https://secure.php.net/manual/en/intlcalendar.after.php + * @param IntlCalendar $other <p>The calendar whose time will be checked against this object's time.</p> * @return bool * Returns <b>TRUE</b> if this object's current time is after that of the * <em>calendar</em> argument's time. Returns <b>FALSE</b> otherwise. - * Also returns <b>FALSE</b> on failure. You can use {@link https://www.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or - * {@link https://www.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to detect error conditions. + * Also returns <b>FALSE</b> on failure. You can use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or + * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to detect error conditions. */ - public function after(IntlCalendar $calendar) { } + public function after(IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether this object's time is before that of the passed object - * @link https://www.php.net/manual/en/intlcalendar.before.php - * @param IntlCalendar $calendar <p> The calendar whose time will be checked against this object's time.</p> + * @link https://secure.php.net/manual/en/intlcalendar.before.php + * @param IntlCalendar $other <p> The calendar whose time will be checked against this object's time.</p> * @return bool * Returns <b>TRUE</B> if this object's current time is before that of the * <em>calendar</em> argument's time. Returns <b>FALSE</b> otherwise. - * Also returns <b>FALSE</b> on failure. You can use {@link https://www.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or - * {@link https://www.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to detect error conditions. - * </p> + * Also returns <b>FALSE</b> on failure. You can use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or + * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to detect error conditions. */ - public function before(IntlCalendar $calendar) { } + public function before(IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Clear a field or all fields - * @link https://www.php.net/manual/en/intlcalendar.clear.php + * @link https://secure.php.net/manual/en/intlcalendar.clear.php * @param int $field [optional] <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> * @return bool Returns <b>TRUE</b> on success or <b>FALSE</b> on failure. Failure can only occur is invalid arguments are provided. */ - public function clear($field = null) { } + public function clear(int|null $field = null): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Private constructor for disallowing instantiation - * @link https://www.php.net/manual/en/intlcalendar.construct.php - * + * @link https://secure.php.net/manual/en/intlcalendar.construct.php */ - private function __construct() { } - + private function __construct() {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Create a new IntlCalendar - * @link https://www.php.net/manual/en/intlcalendar.createinstance.php - * @param mixed $timeZone [optional] <p> <p> + * @link https://secure.php.net/manual/en/intlcalendar.createinstance.php + * @param mixed $timezone [optional] <p> <p> * The timezone to use. * </p> * @@ -2391,61 +2606,61 @@ class IntlCalendar { * <li> * <p> * <b>NULL</b>, in which case the default timezone will be used, as specified in - * the ini setting {@link https://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone date.timezone} or - * through the function {@link https://www.php.net/manual/en/function.date-default-timezone-set.php date_default_timezone_set()} and as - * returned by {@link https://www.php.net/manual/en/function.date-default-timezone-get.php date_default_timezone_get()}. + * the ini setting {@link https://secure.php.net/manual/en/datetime.configuration.php#ini.date.timezone date.timezone} or + * through the function {@link https://secure.php.net/manual/en/function.date-default-timezone-set.php date_default_timezone_set()} and as + * returned by {@link https://secure.php.net/manual/en/function.date-default-timezone-get.php date_default_timezone_get()}. * </p> * </li> * <li> * <p> - * An {@link https://www.php.net/manual/en/class.intltimezone.php IntlTimeZone}, which will be used directly. + * An {@link https://secure.php.net/manual/en/class.intltimezone.php IntlTimeZone}, which will be used directly. * </p> * </li> * <li> * <p> - * A {@link https://www.php.net/manual/en/class.datetimezone.php DateTimeZone}. Its identifier will be extracted + * A {@link https://secure.php.net/manual/en/class.datetimezone.php DateTimeZone}. Its identifier will be extracted * and an ICU timezone object will be created; the timezone will be backed * by ICU's database, not PHP's. * </p> * </li> * <li> * <p> - * A {@link https://www.php.net/manual/en/language.types.string.php string}, which should be a valid ICU timezone identifier. + * A {@link https://secure.php.net/manual/en/language.types.string.php string}, which should be a valid ICU timezone identifier. * See <b>IntlTimeZone::createTimeZoneIDEnumeration()</b>. Raw * offsets such as <em>"GMT+08:30"</em> are also accepted. * </p> * </li> * </ul> * </p> - * @param string $locale [optional] <p> - * A locale to use or <b>NULL</b> to use {@link https://www.php.net/manual/en/intl.configuration.php#ini.intl.default-locale the default locale}. + * @param string|null $locale [optional] <p> + * A locale to use or <b>NULL</b> to use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.default-locale the default locale}. * </p> - * @return IntlCalendar - * The created {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} instance or <b>NULL</b> on + * @return IntlCalendar|null + * The created {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} instance or <b>NULL</b> on * failure. */ - public static function createInstance($timeZone = null, $locale = null) { } + public static function createInstance($timezone = null, string|null $locale = null): ?IntlCalendar {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Compare time of two IntlCalendar objects for equality - * @link https://www.php.net/manual/en/intlcalendar.equals.php - * @param IntlCalendar $calendar + * @link https://secure.php.net/manual/en/intlcalendar.equals.php + * @param IntlCalendar $other * @return bool <p> * Returns <b>TRUE</b> if the current time of both this and the passed in - * {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} object are the same, or <b>FALSE</b> + * {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} object are the same, or <b>FALSE</b> * otherwise. The value <b>FALSE</b> can also be returned on failure. This can only * happen if bad arguments are passed in. In any case, the two cases can be - * distinguished by calling {@link https://www.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()}. + * distinguished by calling {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()}. * </p> */ - public function equals($calendar) { } + public function equals(IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Calculate difference between given time and this object's time - * @link https://www.php.net/manual/en/intlcalendar.fielddifference.php - * @param float $when <p> + * @link https://secure.php.net/manual/en/intlcalendar.fielddifference.php + * @param float $timestamp <p> * The time against which to compare the quantity represented by the * <em>field</em>. For the result to be positive, the time * given for this parameter must be ahead of the time of the object the @@ -2456,82 +2671,87 @@ class IntlCalendar { * </p> * * <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @return int Returns a (signed) difference of time in the unit associated with the + * @return int|false Returns a (signed) difference of time in the unit associated with the * specified field or <b>FALSE</b> on failure. - * */ - public function fieldDifference($when, $field) { } + public function fieldDifference( + float $timestamp, + int $field + ): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a2)<br/> * Create an IntlCalendar from a DateTime object or string - * @link https://www.php.net/manual/en/intlcalendar.fromdatetime.php - * @param mixed $dateTime <p> - * A {@link https://www.php.net/manual/en/class.datetime.php DateTime} object or a {@link https://www.php.net/manual/en/language.types.string.php string} that - * can be passed to {@link https://www.php.net/manual/en/datetime.construct.php DateTime::__construct()}. + * @link https://secure.php.net/manual/en/intlcalendar.fromdatetime.php + * @param mixed $datetime <p> + * A {@link https://secure.php.net/manual/en/class.datetime.php DateTime} object or a {@link https://secure.php.net/manual/en/language.types.string.php string} that + * can be passed to {@link https://secure.php.net/manual/en/datetime.construct.php DateTime::__construct()}. * </p> - * @return IntlCalendar - * The created {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} object or <b>NULL</b> in case of - * failure. If a {@link https://www.php.net/manual/en/language.types.string.php string} is passed, any exception that occurs - * inside the {@link https://www.php.net/manual/en/class.datetime.php DateTime} constructor is propagated. + * @param $locale [optional] + * @return IntlCalendar|null + * The created {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} object or <b>NULL</b> in case of + * failure. If a {@link https://secure.php.net/manual/en/language.types.string.php string} is passed, any exception that occurs + * inside the {@link https://secure.php.net/manual/en/class.datetime.php DateTime} constructor is propagated. */ - public static function fromDateTime($dateTime) { } + public static function fromDateTime( + DateTime|string $datetime, + string|null $locale + ): ?IntlCalendar {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the value for a field - * @link https://www.php.net/manual/en/intlcalendar.get.php + * @link https://secure.php.net/manual/en/intlcalendar.get.php * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @return int An integer with the value of the time field. + * @return int|false An integer with the value of the time field. */ - public function get($field) { } + public function get(int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * The maximum value for a field, considering the object's current time - * @link https://www.php.net/manual/en/intlcalendar.getactualmaximum.php + * @link https://secure.php.net/manual/en/intlcalendar.getactualmaximum.php * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @return int - * An {@link https://www.php.net/manual/en/language.types.integer.php int} representing the maximum value in the units associated + * @return int|false + * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing the maximum value in the units associated * with the given <em>field</em> or <b>FALSE</b> on failure. */ - public function getActualMaximum($field) { } + public function getActualMaximum(int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * The minimum value for a field, considering the object's current time - * @link https://www.php.net/manual/en/intlcalendar.getactualminimum.php + * @link https://secure.php.net/manual/en/intlcalendar.getactualminimum.php * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. * These are integer values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @return int - * An {@link https://www.php.net/manual/en/language.types.integer.php int} representing the minimum value in the field's + * @return int|false + * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing the minimum value in the field's * unit or <b>FALSE</b> on failure. */ - public function getActualMinimum($field) { } + public function getActualMinimum(int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get array of locales for which there is data - * @link https://www.php.net/manual/en/intlcalendar.getavailablelocales.php - * @return array An array of strings, one for which locale. + * @link https://secure.php.net/manual/en/intlcalendar.getavailablelocales.php + * @return string[] An array of strings, one for which locale. */ - - public static function getAvailableLocales() { } + public static function getAvailableLocales(): array {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> @@ -2541,98 +2761,98 @@ class IntlCalendar { * <b>IntlCalendar::DOW_MONDAY</b>, ..., * <b>IntlCalendar::DOW_SATURDAY</b>. * </p> - * @return int + * @return int|false * Returns one of the constants * <b>IntlCalendar::DOW_TYPE_WEEKDAY</b>, * <b>IntlCalendar::DOW_TYPE_WEEKEND</b>, * <b>IntlCalendar::DOW_TYPE_WEEKEND_OFFSET</b> or * <b>IntlCalendar::DOW_TYPE_WEEKEND_CEASE</b> or <b>FALSE</b> on failure. - * */ - public function getDayOfWeekType($dayOfWeek) { } + public function getDayOfWeekType(int $dayOfWeek): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get last error code on the object - * @link https://www.php.net/manual/en/intlcalendar.geterrorcode.php - * @return int An ICU error code indicating either success, failure or a warning. - * + * @link https://secure.php.net/manual/en/intlcalendar.geterrorcode.php + * @return int|false An ICU error code indicating either success, failure or a warning. */ - public function getErrorCode() { } + public function getErrorCode(): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get last error message on the object - * @link https://www.php.net/manual/en/intlcalendar.geterrormessage.php - * @return string The error message associated with last error that occurred in a function call on this object, or a string indicating the non-existance of an error. + * @link https://secure.php.net/manual/en/intlcalendar.geterrormessage.php + * @return string|false The error message associated with last error that occurred in a function call on this object, or a string indicating the non-existance of an error. */ - public function getErrorMessage() { } + public function getErrorMessage(): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the first day of the week for the calendar's locale - * @link https://www.php.net/manual/en/intlcalendar.getfirstdayofweek.php - * @return int + * @link https://secure.php.net/manual/en/intlcalendar.getfirstdayofweek.php + * @return int|false * One of the constants <b>IntlCalendar::DOW_SUNDAY</b>, * <b>IntlCalendar::DOW_MONDAY</b>, ..., * <b>IntlCalendar::DOW_SATURDAY</b> or <b>FALSE</b> on failure. - * */ - public function getFirstDayOfWeek() { } + public function getFirstDayOfWeek(): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the largest local minimum value for a field - * @link https://www.php.net/manual/en/intlcalendar.getgreatestminimum.php - * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * @link https://secure.php.net/manual/en/intlcalendar.getgreatestminimum.php + * @param int $field + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. - * @return int - * An {@link https://www.php.net/manual/en/language.types.integer.php int} representing a field value, in the field's + * @return int|false + * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing a field value, in the field's * unit, or <b>FALSE</b> on failure. */ - public function getGreatestMinimum($field) { } + public function getGreatestMinimum(int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get set of locale keyword values - * @param string $key <p> + * @param string $keyword <p> * The locale keyword for which relevant values are to be queried. Only * <em>'calendar'</em> is supported. * </p> * @param string $locale <p> * The locale onto which the keyword/value pair are to be appended. * </p> - * @param bool $commonlyUsed + * @param bool $onlyCommon * <p> * Whether to show only the values commonly used for the specified locale. * </p> * @return Iterator|false An iterator that yields strings with the locale keyword values or <b>FALSE</b> on failure. */ - public static function getKeywordValuesForLocale($key, $locale, $commonlyUsed) { } + public static function getKeywordValuesForLocale( + string $keyword, + string $locale, + bool $onlyCommon + ): IntlIterator|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the smallest local maximum for a field - * @link https://www.php.net/manual/en/intlcalendar.getleastmaximum.php + * @link https://secure.php.net/manual/en/intlcalendar.getleastmaximum.php * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @return int - * An {@link https://www.php.net/manual/en/language.types.integer.ph int} representing a field value in the field's + * @return int|false + * An {@link https://secure.php.net/manual/en/language.types.integer.ph int} representing a field value in the field's * unit or <b>FALSE</b> on failure. - * </p> */ - public function getLeastMaximum($field) { } + public function getLeastMaximum(int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the locale associated with the object - * @link https://www.php.net/manual/en/intlcalendar.getlocale.php - * @param int $localeType <p> + * @link https://secure.php.net/manual/en/intlcalendar.getlocale.php + * @param int $type <p> * Whether to fetch the actual locale (the locale from which the calendar * data originates, with <b>Locale::ACTUAL_LOCALE</b>) or the * valid locale, i.e., the most specific locale supported by ICU relatively @@ -2640,213 +2860,208 @@ class IntlCalendar { * From the most general to the most specific, the locales are ordered in * this fashion – actual locale, valid locale, requested locale. * </p> - * @return string - * A locale string or <b>FALSE</b> on failure. - * + * @return string|false */ - public function getLocale($localeType) { } + public function getLocale(int $type): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the global maximum value for a field - * @link https://www.php.net/manual/en/intlcalendar.getmaximum.php + * @link https://secure.php.net/manual/en/intlcalendar.getmaximum.php * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @return string - * A locale string or <b>FALSE</b> on failure. + * @return int|false */ - public function getMaximum($field) { } + public function getMaximum(int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get minimal number of days the first week in a year or month can have - * @link https://www.php.net/manual/en/intlcalendar.getminimaldaysinfirstweek.php - * @return int - * An {@link https://www.php.net/manual/en/language.types.integer.php int} representing a number of days or <b>FALSE</b> on failure. + * @link https://secure.php.net/manual/en/intlcalendar.getminimaldaysinfirstweek.php + * @return int|false + * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing a number of days or <b>FALSE</b> on failure. */ - public function getMinimalDaysInFirstWeek() { } + public function getMinimalDaysInFirstWeek(): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the global minimum value for a field - * @link https://www.php.net/manual/en/intlcalendar.getminimum.php + * @link https://secure.php.net/manual/en/intlcalendar.getminimum.php * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @return int + * @return int|false * An int representing a value for the given field in the field's unit or FALSE on failure. */ - public function getMinimum($field) { } + public function getMinimum(int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get number representing the current time * @return float A float representing a number of milliseconds since the epoch, not counting leap seconds. */ - public static function getNow() { } + public static function getNow(): float {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get behavior for handling repeating wall time - * @link https://www.php.net/manual/en/intlcalendar.getrepeatedwalltimeoption.php + * @link https://secure.php.net/manual/en/intlcalendar.getrepeatedwalltimeoption.php * @return int * One of the constants <b>IntlCalendar::WALLTIME_FIRST</b> or * <b>IntlCalendar::WALLTIME_LAST</b>. - * */ - public function getRepeatedWallTimeOption() { } + public function getRepeatedWallTimeOption(): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get behavior for handling skipped wall time - * @link https://www.php.net/manual/en/intlcalendar.getskippedwalltimeoption.php + * @link https://secure.php.net/manual/en/intlcalendar.getskippedwalltimeoption.php * @return int * One of the constants <b>IntlCalendar::WALLTIME_FIRST</b>, * <b>IntlCalendar::WALLTIME_LAST</b> or * <b>IntlCalendar::WALLTIME_NEXT_VALID</b>. */ - public function getSkippedWallTimeOption() { } + public function getSkippedWallTimeOption(): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get time currently represented by the object - * @return float - * A {@link https://www.php.net/manual/en/language.types.float.php float} representing the number of milliseconds elapsed since the + * @return float|false + * A {@link https://secure.php.net/manual/en/language.types.float.php float} representing the number of milliseconds elapsed since the * reference time (1 Jan 1970 00:00:00 UTC). */ - public function getTime() { } + public function getTime(): float|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the object's timezone - * @link https://www.php.net/manual/en/intlcalendar.gettimezone.php - * @return IntlTimeZone - * An {@link https://www.php.net/manual/en/class.intltimezone.php IntlTimeZone} object corresponding to the one used + * @link https://secure.php.net/manual/en/intlcalendar.gettimezone.php + * @return IntlTimeZone|false + * An {@link https://secure.php.net/manual/en/class.intltimezone.php IntlTimeZone} object corresponding to the one used * internally in this object. */ - public function getTimeZone() { } + public function getTimeZone(): IntlTimeZone|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the calendar type - * @link https://www.php.net/manual/en/intlcalendar.gettype.php + * @link https://secure.php.net/manual/en/intlcalendar.gettype.php * @return string - * A {@link https://www.php.net/manual/en/language.types.string.php string} representing the calendar type, such as + * A {@link https://secure.php.net/manual/en/language.types.string.php string} representing the calendar type, such as * <em>'gregorian'</em>, <em>'islamic'</em>, etc. */ - public function getType() { } + public function getType(): string {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get time of the day at which weekend begins or ends - * @link https://www.php.net/manual/en/intlcalendar.getweekendtransition.php + * @link https://secure.php.net/manual/en/intlcalendar.getweekendtransition.php * @param string $dayOfWeek <p> * One of the constants <b>IntlCalendar::DOW_SUNDAY</b>, * <b>IntlCalendar::DOW_MONDAY</b>, ..., * <b>IntlCalendar::DOW_SATURDAY</b>. * </p> - * @return int + * @return int|false * The number of milliseconds into the day at which the the weekend begins or * ends or <b>FALSE</b> on failure. */ - public function getWeekendTransition($dayOfWeek) { } + public function getWeekendTransition(int $dayOfWeek): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether the object's time is in Daylight Savings Time - * @link https://www.php.net/manual/en/intlcalendar.indaylighttime.php + * @link https://secure.php.net/manual/en/intlcalendar.indaylighttime.php * @return bool * Returns <b>TRUE</b> if the date is in Daylight Savings Time, <b>FALSE</b> otherwise. * The value <b>FALSE</b> may also be returned on failure, for instance after - * specifying invalid field values on non-lenient mode; use {@link https://www.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or query - * {@link https://www.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to disambiguate. + * specifying invalid field values on non-lenient mode; use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or query + * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to disambiguate. */ - public function inDaylightTime() { } + public function inDaylightTime(): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether another calendar is equal but for a different time - * @link https://www.php.net/manual/en/intlcalendar.isequivalentto.php - * @param IntlCalendar $calendar The other calendar against which the comparison is to be made. + * @link https://secure.php.net/manual/en/intlcalendar.isequivalentto.php + * @param IntlCalendar $other The other calendar against which the comparison is to be made. * @return bool * Assuming there are no argument errors, returns <b>TRUE</b> iif the calendars are equivalent except possibly for their set time. */ - public function isEquivalentTo(IntlCalendar $calendar) { } + public function isEquivalentTo(IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether date/time interpretation is in lenient mode - * @link https://www.php.net/manual/en/intlcalendar.islenient.php + * @link https://secure.php.net/manual/en/intlcalendar.islenient.php * @return bool - * A {@link https://www.php.net/manual/en/language.types.boolean.php bool} representing whether the calendar is set to lenient mode. + * A {@link https://secure.php.net/manual/en/language.types.boolean.php bool} representing whether the calendar is set to lenient mode. */ - public function isLenient() { } + public function isLenient(): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether a certain date/time is in the weekend - * @link https://www.php.net/manual/en/intlcalendar.isweekend.php - * @param float|null $date [optional] <p> + * @link https://secure.php.net/manual/en/intlcalendar.isweekend.php + * @param float|null $timestamp [optional] <p> * An optional timestamp representing the number of milliseconds since the * epoch, excluding leap seconds. If <b>NULL</b>, this object's current time is * used instead. * </p> * @return bool - * <p> A {@link https://www.php.net/manual/en/language.types.boolean.php bool} indicating whether the given or this object's time occurs + * <p> A {@link https://secure.php.net/manual/en/language.types.boolean.php bool} indicating whether the given or this object's time occurs * in a weekend. * </p> * <p> * The value <b>FALSE</b> may also be returned on failure, for instance after giving - * a date out of bounds on non-lenient mode; use {@link https://www.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or query - * {@link https://www.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to disambiguate.</p> + * a date out of bounds on non-lenient mode; use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or query + * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to disambiguate.</p> */ - public function isWeekend($date = null) { } + public function isWeekend(float|null $timestamp = null): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Add value to field without carrying into more significant fields - * @link https://www.php.net/manual/en/intlcalendar.roll.php + * @link https://secure.php.net/manual/en/intlcalendar.roll.php * @param int $field - * <p>One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time - * {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * <p>One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time + * {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @param mixed $amountOrUpOrDown <p> + * @param mixed $value <p> * The (signed) amount to add to the field, <b>TRUE</b> for rolling up (adding * <em>1</em>), or <b>FALSE</b> for rolling down (subtracting * <em>1</em>). * </p> * @return bool Returns <b>TRUE</b> on success or <b>FALSE</b> on failure. */ - public function roll($field, $amountOrUpOrDown) { } - + public function roll(int $field, $value): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether a field is set - * @link https://www.php.net/manual/en/intlcalendar.isset.php + * @link https://secure.php.net/manual/en/intlcalendar.isset.php * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time - * {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time + * {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. * These are integer values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> * @return bool Assuming there are no argument errors, returns <b>TRUE</b> iif the field is set. */ - public function PS_UNRESERVE_PREFIX_isSet($field) { } + public function PS_UNRESERVE_PREFIX_isSet(int $field): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set a time field or several common fields at once - * @link https://www.php.net/manual/en/intlcalendar.set.php + * @link https://secure.php.net/manual/en/intlcalendar.set.php * @param int $year <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> @@ -2869,26 +3084,26 @@ class IntlCalendar { * </p> * @param int $second [optional] <p> * The new value for <b>IntlCalendar::FIELD_SECOND</b>. - *</p> + * </p> * @return bool Returns <b>TRUE</b> on success and <b>FALSE</b> on failure. */ - public function set($year, $month, $dayOfMonth = null, $hour = null, $minute = null, $second = null) { } + public function set($year, $month, $dayOfMonth = null, $hour = null, $minute = null, $second = null) {} /** - * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> + * (PHP 5 >= 5.5.0 PECL intl >= 3.0.0a1)<br/> * Set a time field or several common fields at once - * @link https://www.php.net/manual/en/intlcalendar.set.php + * @link https://secure.php.net/manual/en/intlcalendar.set.php * @param int $field One of the IntlCalendar date/time field constants. These are integer values between 0 and IntlCalendar::FIELD_COUNT. * @param int $value The new value of the given field. * @return bool Returns <b>TRUE</b> on success and <b>FALSE</b> on failure. * @since 5.5 */ - public function set($field, $value) { } + public function set($field, $value) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set the day on which the week is deemed to start - * @link https://www.php.net/manual/en/intlcalendar.setfirstdayofweek.php + * @link https://secure.php.net/manual/en/intlcalendar.setfirstdayofweek.php * @param int $dayOfWeek <p> * One of the constants <b>IntlCalendar::DOW_SUNDAY</b>, * <b>IntlCalendar::DOW_MONDAY</b>, ..., @@ -2896,38 +3111,37 @@ class IntlCalendar { * </p> * @return bool Returns TRUE on success. Failure can only happen due to invalid parameters. */ - public function setFirstDayOfWeek($dayOfWeek) { } + public function setFirstDayOfWeek(int $dayOfWeek): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set whether date/time interpretation is to be lenient - * @link https://www.php.net/manual/en/intlcalendar.setlenient.php - * @param string $isLenient <p> + * @link https://secure.php.net/manual/en/intlcalendar.setlenient.php + * @param bool $lenient <p> * Use <b>TRUE</b> to activate the lenient mode; <b>FALSE</b> otherwise. * </p> * @return bool Returns <b>TRUE</b> on success. Failure can only happen due to invalid parameters. */ - public function setLenient($isLenient) { } + public function setLenient(bool $lenient): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set behavior for handling repeating wall times at negative timezone offset transitions - * @link https://www.php.net/manual/en/intlcalendar.setrepeatedwalltimeoption.php - * @param int $wallTimeOption <p> + * @link https://secure.php.net/manual/en/intlcalendar.setrepeatedwalltimeoption.php + * @param int $option <p> * One of the constants <b>IntlCalendar::WALLTIME_FIRST</b> or * <b>IntlCalendar::WALLTIME_LAST</b>. * </p> * @return bool * Returns <b>TRUE</b> on success. Failure can only happen due to invalid parameters. - * */ - public function setRepeatedWallTimeOption($wallTimeOption) { } + public function setRepeatedWallTimeOption(int $option): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set behavior for handling skipped wall times at positive timezone offset transitions - * @link https://www.php.net/manual/en/intlcalendar.setskippedwalltimeoption.php - * @param int $wallTimeOption <p> + * @link https://secure.php.net/manual/en/intlcalendar.setskippedwalltimeoption.php + * @param int $option <p> * One of the constants <b>IntlCalendar::WALLTIME_FIRST</b>, * <b>IntlCalendar::WALLTIME_LAST</b> or * <b>IntlCalendar::WALLTIME_NEXT_VALID</b>. @@ -2937,26 +3151,26 @@ class IntlCalendar { * Returns <b>TRUE</b> on success. Failure can only happen due to invalid parameters. * </p> */ - public function setSkippedWallTimeOption($wallTimeOption) { } + public function setSkippedWallTimeOption(int $option): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set the calendar time in milliseconds since the epoch - * @link https://www.php.net/manual/en/intlcalendar.settime.php - * @param float $date <p> + * @link https://secure.php.net/manual/en/intlcalendar.settime.php + * @param float $timestamp <p> * An instant represented by the number of number of milliseconds between * such instant and the epoch, ignoring leap seconds. * </p> * @return bool * Returns <b>TRUE</b> on success and <b>FALSE</b> on failure. */ - public function setTime($date) { } + public function setTime(float $timestamp): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set the timezone used by this calendar - * @link https://www.php.net/manual/en/intlcalendar.settimezone.php - * @param mixed $timeZone <p> + * @link https://secure.php.net/manual/en/intlcalendar.settimezone.php + * @param mixed $timezone <p> * The new timezone to be used by this calendar. It can be specified in the * following ways: * @@ -2964,26 +3178,26 @@ class IntlCalendar { * <li> * <p> * <b>NULL</b>, in which case the default timezone will be used, as specified in - * the ini setting {@link https://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone date.timezone} or - * through the function {@link https://www.php.net/manual/en/function.date-default-timezone-set.php date_default_timezone_set()} and as - * returned by {@link https://www.php.net/manual/en/function.date-default-timezone-get.php date_default_timezone_get()}. + * the ini setting {@link https://secure.php.net/manual/en/datetime.configuration.php#ini.date.timezone date.timezone} or + * through the function {@link https://secure.php.net/manual/en/function.date-default-timezone-set.php date_default_timezone_set()} and as + * returned by {@link https://secure.php.net/manual/en/function.date-default-timezone-get.php date_default_timezone_get()}. * </p> * </li> * <li> * <p> - * An {@link https://www.php.net/manual/en/class.intltimezone.php IntlTimeZone}, which will be used directly. + * An {@link https://secure.php.net/manual/en/class.intltimezone.php IntlTimeZone}, which will be used directly. * </p> * </li> * <li> * <p> - * A {@link https://www.php.net/manual/en/class.datetimezone.php DateTimeZone}. Its identifier will be extracted + * A {@link https://secure.php.net/manual/en/class.datetimezone.php DateTimeZone}. Its identifier will be extracted * and an ICU timezone object will be created; the timezone will be backed * by ICU's database, not PHP's. * </p> * </li> * <li> * <p> - * A {@link https://www.php.net/manual/en/language.types.string.php string}, which should be a valid ICU timezone identifier. + * A {@link https://secure.php.net/manual/en/language.types.string.php string}, which should be a valid ICU timezone identifier. * See b>IntlTimeZone::createTimeZoneIDEnumeration()</b>. Raw * offsets such as <em>"GMT+08:30"</em> are also accepted. * </p> @@ -2991,183 +3205,221 @@ class IntlCalendar { * </ul> * @return bool Returns <b>TRUE</b> on success and <b>FALSE</b> on failure. */ - public function setTimeZone($timeZone) { } + public function setTimeZone($timezone): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a2)<br/> * Convert an IntlCalendar into a DateTime object - * @link https://www.php.net/manual/en/intlcalendar.todatetime.php + * @link https://secure.php.net/manual/en/intlcalendar.todatetime.php * @return DateTime|false - * A {@link https://www.php.net/manual/en/class.datetime.php DateTime} object with the same timezone as this + * A {@link https://secure.php.net/manual/en/class.datetime.php DateTime} object with the same timezone as this * object (though using PHP's database instead of ICU's) and the same time, * except for the smaller precision (second precision instead of millisecond). * Returns <b>FALSE</b> on failure. */ - public function toDateTime() { } + public function toDateTime(): DateTime|false {} + + /** + * @link https://www.php.net/manual/en/intlcalendar.setminimaldaysinfirstweek.php + * @param int $days + * @return bool + */ + public function setMinimalDaysInFirstWeek(int $days): bool {} + + /** + * @since 8.3 + */ + public function setDate(int $year, int $month, int $dayOfMonth): void {} + + /** + * @since 8.3 + */ + public function setDateTime(int $year, int $month, int $dayOfMonth, int $hour, int $minute, ?int $second = null): void {} } /** * @since 5.5 */ -class IntlIterator implements Iterator { - - public function current() { } +class IntlIterator implements Iterator +{ + public function current(): mixed {} - public function key() { } + public function key(): mixed {} - public function next() { } + public function next(): void {} - public function rewind() { } + public function rewind(): void {} - public function valid() { } + public function valid(): bool {} } /** * @since 5.5 */ -class IntlException extends Exception { - -} +class IntlException extends Exception {} /** * @since 5.5 */ -class IntlTimeZone { +class IntlTimeZone +{ /* Constants */ - const DISPLAY_SHORT = 1; - const DISPLAY_LONG = 2; + public const DISPLAY_SHORT = 1; + public const DISPLAY_LONG = 2; + public const DISPLAY_SHORT_GENERIC = 3; + public const DISPLAY_LONG_GENERIC = 4; + public const DISPLAY_SHORT_GMT = 5; + public const DISPLAY_LONG_GMT = 6; + public const DISPLAY_SHORT_COMMONLY_USED = 7; + public const DISPLAY_GENERIC_LOCATION = 8; + public const TYPE_ANY = 0; + public const TYPE_CANONICAL = 1; + public const TYPE_CANONICAL_LOCATION = 2; /* Methods */ + private function __construct() {} + /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the number of IDs in the equivalency group that includes the given ID - * @link https://www.php.net/manual/en/intltimezone.countequivalentids.php - * @param string $zoneId + * @link https://secure.php.net/manual/en/intltimezone.countequivalentids.php + * @param string $timezoneId * @return int|false number of IDs or <b>FALSE</b> on failure */ - public static function countEquivalentIDs($zoneId) { } + public static function countEquivalentIDs(string $timezoneId): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Create a new copy of the default timezone for this host - * @link https://www.php.net/manual/en/intltimezone.createdefault.php + * @link https://secure.php.net/manual/en/intltimezone.createdefault.php * @return IntlTimeZone */ - public static function createDefault() { } + public static function createDefault(): IntlTimeZone {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get an enumeration over time zone IDs associated with the given country or offset - * @link https://www.php.net/manual/en/intltimezone.createenumeration.php + * @link https://secure.php.net/manual/en/intltimezone.createenumeration.php * @param mixed $countryOrRawOffset [optional] * @return IntlIterator|false an iterator or <b>FALSE</b> on failure */ - public static function createEnumeration($countryOrRawOffset) { } + public static function createEnumeration($countryOrRawOffset): IntlIterator|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Create a timezone object for the given ID - * @link https://www.php.net/manual/en/intltimezone.createtimezone.php - * @param string $zoneId + * @link https://secure.php.net/manual/en/intltimezone.createtimezone.php + * @param string $timezoneId * @return IntlTimeZone|null a timezone object or <b>NULL</b> on failure */ - public static function createTimeZone($zoneId) { } + public static function createTimeZone(string $timezoneId): ?IntlTimeZone {} /** * (PHP 5 >=5.5.0)<br/> * Get an enumeration over system time zone IDs with the given filter conditions - * @link https://www.php.net/manual/en/intltimezone.createtimezoneidenumeration.php - * @param int $zoneType + * @link https://secure.php.net/manual/en/intltimezone.createtimezoneidenumeration.php + * @param int $type * @param string|null $region [optional] * @param int $rawOffset [optional] * @return IntlIterator|false an iterator or <b>FALSE</b> on failure */ - public static function createTimeZoneIDEnumeration($zoneType, $region = null, $rawOffset = 0) { } + public static function createTimeZoneIDEnumeration( + int $type, + string|null $region = null, + int|null $rawOffset = null + ): IntlIterator|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Create a timezone object from DateTimeZone - * @link https://www.php.net/manual/en/intltimezone.fromdatetimezone.php - * @param DateTimeZone $zoneId + * @link https://secure.php.net/manual/en/intltimezone.fromdatetimezone.php + * @param DateTimeZone $timezone * @return IntlTimeZone|null a timezone object or <b>NULL</b> on failure */ - public static function fromDateTimeZone($zoneId) { } + public static function fromDateTimeZone(DateTimeZone $timezone): ?IntlTimeZone {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the canonical system timezone ID or the normalized custom time zone ID for the given time zone ID - * @link https://www.php.net/manual/en/intltimezone.getcanonicalid.php - * @param string $zoneId - * @param bool $isSystemID [optional] + * @link https://secure.php.net/manual/en/intltimezone.getcanonicalid.php + * @param string $timezoneId + * @param bool &$isSystemId [optional] * @return string|false the timezone ID or <b>FALSE</b> on failure */ - public static function getCanonicalID($zoneId, &$isSystemID) { } + public static function getCanonicalID(string $timezoneId, &$isSystemId): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get a name of this time zone suitable for presentation to the user - * @param bool $isDaylight [optional] + * @param bool $dst [optional] * @param int $style [optional] * @param string $locale [optional] * @return string|false the timezone name or <b>FALSE</b> on failure */ - public function getDisplayName($isDaylight, $style, $locale) { } + public function getDisplayName( + bool $dst = false, + int $style = 2, + string|null $locale + ): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the amount of time to be added to local standard time to get local wall clock time - * @link https://www.php.net/manual/en/intltimezone.getequivalentid.php + * @link https://secure.php.net/manual/en/intltimezone.getequivalentid.php * @return int */ - public function getDSTSavings() { } + public function getDSTSavings(): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get an ID in the equivalency group that includes the given ID - * @link https://www.php.net/manual/en/intltimezone.getequivalentid.php - * @param string $zoneId - * @param int $index + * @link https://secure.php.net/manual/en/intltimezone.getequivalentid.php + * @param string $timezoneId + * @param int $offset * @return string|false the time zone ID or <b>FALSE</b> on failure */ - public static function getEquivalentID($zoneId, $index) { } + public static function getEquivalentID( + string $timezoneId, + int $offset + ): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get last error code on the object - * @link https://www.php.net/manual/en/intltimezone.geterrorcode.php - * @return int + * @link https://secure.php.net/manual/en/intltimezone.geterrorcode.php + * @return int|false */ - public function getErrorCode() { } + public function getErrorCode(): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get last error message on the object - * @link https://www.php.net/manual/en/intltimezone.geterrormessage.php - * @return string + * @link https://secure.php.net/manual/en/intltimezone.geterrormessage.php + * @return string|false */ - public function getErrorMessage() { } + public function getErrorMessage(): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Create GMT (UTC) timezone - * @link https://www.php.net/manual/en/intltimezone.getgmt.php + * @link https://secure.php.net/manual/en/intltimezone.getgmt.php * @return IntlTimeZone */ - public static function getGMT() { } + public static function getGMT(): IntlTimeZone {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get timezone ID - * @return string + * @return string|false */ - public function getID() { } + public function getID(): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the time zone raw and GMT offset for the given moment in time - * @link https://www.php.net/manual/en/intltimezone.getoffset.php - * @param float $date + * @link https://secure.php.net/manual/en/intltimezone.getoffset.php + * @param float $timestamp * moment in time for which to return offsets, in units of milliseconds from * January 1, 1970 0:00 GMT, either GMT time or local wall time, depending on * `local'. @@ -3183,76 +3435,95 @@ class IntlTimeZone { * typically one hour. * @return bool boolean indication of success */ - public function getOffset($date, $local, &$rawOffset, &$dstOffset) { } + public function getOffset( + float $timestamp, + bool $local, + &$rawOffset, + &$dstOffset + ): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the raw GMT offset (before taking daylight savings time into account - * @link https://www.php.net/manual/en/intltimezone.getrawoffset.php + * @link https://secure.php.net/manual/en/intltimezone.getrawoffset.php * @return int */ - public function getRawOffset() { } + public function getRawOffset(): int {} /** * (PHP 5 >=5.5.0)<br/> * Get the region code associated with the given system time zone ID - * @link https://www.php.net/manual/en/intltimezone.getregion.php - * @param string $zoneId + * @link https://secure.php.net/manual/en/intltimezone.getregion.php + * @param string $timezoneId * @return string|false region or <b>FALSE</b> on failure */ - public static function getRegion($zoneId) { } + public static function getRegion(string $timezoneId): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the timezone data version currently used by ICU - * @link https://www.php.net/manual/en/intltimezone.gettzdataversion.php - * @return string + * @link https://secure.php.net/manual/en/intltimezone.gettzdataversion.php + * @return string|false */ - public static function getTZDataVersion() { } + public static function getTZDataVersion(): string|false {} /** * (PHP 5 >=5.5.0)<br/> * Get the "unknown" time zone - * @link https://www.php.net/manual/en/intltimezone.getunknown.php + * @link https://secure.php.net/manual/en/intltimezone.getunknown.php * @return IntlTimeZone */ - public static function getUnknown() { } + public static function getUnknown(): IntlTimeZone {} /** * (PHP 7 >=7.1.0)<br/> * Translates a system timezone (e.g. "America/Los_Angeles") into a Windows * timezone (e.g. "Pacific Standard Time"). - * @link https://www.php.net/manual/en/intltimezone.getwindowsid.php - * @param string $timezone + * @link https://secure.php.net/manual/en/intltimezone.getwindowsid.php + * @param string $timezoneId + * @return string|false the Windows timezone or <b>FALSE</b> on failure + * @since 7.1 + */ + public static function getWindowsID(string $timezoneId): string|false {} + + /** + * @link https://www.php.net/manual/en/intltimezone.getidforwindowsid.php + * @param string $timezoneId + * @param string|null $region * @return string|false the Windows timezone or <b>FALSE</b> on failure * @since 7.1 */ - public static function getWindowsID($timezone) { } + public static function getIDForWindowsID(string $timezoneId, ?string $region = null): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Check if this zone has the same rules and offset as another zone - * @link https://www.php.net/manual/en/intltimezone.hassamerules.php - * @param IntlTimeZone $otherTimeZone + * @link https://secure.php.net/manual/en/intltimezone.hassamerules.php + * @param IntlTimeZone $other * @return bool */ - public function hasSameRules(IntlTimeZone $otherTimeZone) { } + public function hasSameRules(IntlTimeZone $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Convert to DateTimeZone object - * @link https://www.php.net/manual/ru/intltimezone.todatetimezone.php + * @link https://secure.php.net/manual/en/intltimezone.todatetimezone.php * @return DateTimeZone|false the DateTimeZone object or <b>FALSE</b> on failure */ - public function toDateTimeZone() { } + public function toDateTimeZone(): DateTimeZone|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Check if this time zone uses daylight savings time - * @link https://www.php.net/manual/ru/intltimezone.usedaylighttime.php + * @link https://secure.php.net/manual/en/intltimezone.usedaylighttime.php * @return bool */ - public function useDaylightTime() { } + public function useDaylightTime(): bool {} + + /** + * @since 8.4 + */ + public static function getIanaID(string $timezoneId): string|false {} } /** @@ -3265,76 +3536,76 @@ class IntlTimeZone { * default locale collation rules will be used. If empty string ("") or * "root" are passed, UCA rules will be used. * </p> - * @return Collator Return new instance of <b>Collator</b> object, or <b>NULL</b> + * @return Collator|null Return new instance of <b>Collator</b> object, or <b>NULL</b> * on error. */ -function collator_create($locale) { } +function collator_create(string $locale): ?Collator {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Compare two Unicode strings * @link https://php.net/manual/en/collator.compare.php * @param Collator $object - * @param string $str1 <p> + * @param string $string1 <p> * The first string to compare. * </p> - * @param string $str2 <p> + * @param string $string2 <p> * The second string to compare. * </p> - * @return int Return comparison result:</p> + * @return int|false Return comparison result:</p> * <p> * <p> - * 1 if <i>str1</i> is greater than - * <i>str2</i> ; + * 1 if <i>string1</i> is greater than + * <i>string2</i> ; * </p> * <p> - * 0 if <i>str1</i> is equal to - * <i>str2</i>; + * 0 if <i>string1</i> is equal to + * <i>string2</i>; * </p> * <p> - * -1 if <i>str1</i> is less than - * <i>str2</i> . + * -1 if <i>string1</i> is less than + * <i>string2</i> . * </p> * On error * boolean * <b>FALSE</b> * is returned. */ -function collator_compare(Collator $object, $str1, $str2) { } +function collator_compare(Collator $object, string $string1, string $string2): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get collation attribute value * @link https://php.net/manual/en/collator.getattribute.php * @param Collator $object - * @param int $attr <p> + * @param int $attribute <p> * Attribute to get value for. * </p> * @return int|false Attribute value, or boolean <b>FALSE</b> on error. */ -function collator_get_attribute(Collator $object, $attr) { } +function collator_get_attribute(Collator $object, int $attribute): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Set collation attribute * @link https://php.net/manual/en/collator.setattribute.php * @param Collator $object - * @param int $attr <p>Attribute.</p> - * @param int $val <p> + * @param int $attribute <p>Attribute.</p> + * @param int $value <p> * Attribute value. * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function collator_set_attribute(Collator $object, $attr, $val) { } +function collator_set_attribute(Collator $object, int $attribute, int $value): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get current collation strength * @link https://php.net/manual/en/collator.getstrength.php * @param Collator $object - * @return int|false current collation strength, or boolean <b>FALSE</b> on error. + * @return int current collation strength */ -function collator_get_strength(Collator $object) { } +function collator_get_strength(Collator $object): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3344,105 +3615,108 @@ function collator_get_strength(Collator $object) { } * @param int $strength <p>Strength to set.</p> * <p> * Possible values are: - * <p> * <b>Collator::PRIMARY</b> * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function collator_set_strength(Collator $object, $strength) { } +function collator_set_strength(Collator $object, int $strength): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Sort array using specified collator * @link https://php.net/manual/en/collator.sort.php * @param Collator $object - * @param array $arr <p> + * @param string[] &$array <p> * Array of strings to sort. * </p> - * @param int $sort_flag [optional] <p> + * @param int $flags <p> * Optional sorting type, one of the following: * </p> * <p> - * <p> * <b>Collator::SORT_REGULAR</b> * - compare items normally (don't change types) * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function collator_sort(Collator $object, array &$arr, $sort_flag = null) { } +function collator_sort(Collator $object, array &$array, int $flags = 0): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Sort array using specified collator and sort keys * @link https://php.net/manual/en/collator.sortwithsortkeys.php * @param Collator $object - * @param array $arr <p>Array of strings to sort</p> + * @param string[] &$array <p>Array of strings to sort</p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function collator_sort_with_sort_keys(Collator $object, array &$arr) { } +function collator_sort_with_sort_keys( + Collator $object, + array &$array, +): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Sort array maintaining index association * @link https://php.net/manual/en/collator.asort.php * @param Collator $object - * @param array $arr <p>Array of strings to sort.</p> - * @param int $sort_flag [optional] <p> + * @param string[] &$array <p>Array of strings to sort.</p> + * @param int $flags <p> * Optional sorting type, one of the following: - * <p> * <b>Collator::SORT_REGULAR</b> * - compare items normally (don't change types) * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function collator_asort(Collator $object, array &$arr, $sort_flag = null) { } +function collator_asort(Collator $object, array &$array, int $flags = 0): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the locale name of the collator * @link https://php.net/manual/en/collator.getlocale.php * @param Collator $object - * @param int $type [optional] <p> + * @param int $type <p> * You can choose between valid and actual locale ( * <b>Locale::VALID_LOCALE</b> and * <b>Locale::ACTUAL_LOCALE</b>, * respectively). The default is the actual locale. * </p> - * @return string Real locale name from which the collation data comes. If the collator was + * @return string|false Real locale name from which the collation data comes. If the collator was * instantiated from rules or an error occurred, returns * boolean <b>FALSE</b>. */ -function collator_get_locale(Collator $object, $type = null) { } +function collator_get_locale(Collator $object, int $type): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get collator's last error code * @link https://php.net/manual/en/collator.geterrorcode.php * @param Collator $object - * @return int Error code returned by the last Collator API function call. + * @return int|false Error code returned by the last Collator API function call. */ -function collator_get_error_code(Collator $object) { } +function collator_get_error_code(Collator $object): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get text for collator's last error code * @link https://php.net/manual/en/collator.geterrormessage.php * @param Collator $object - * @return string Description of an error occurred in the last Collator API function call. + * @return string|false Description of an error occurred in the last Collator API function call. */ -function collator_get_error_message(Collator $object) { } +function collator_get_error_message(Collator $object): string|false {} /** - * (No version information available, might only be in SVN)<br/> + * (PHP 5 >= 5.3.2, PHP 7, PECL intl >= 1.0.3)<br/> * Get sorting key for a string * @link https://php.net/manual/en/collator.getsortkey.php * @param Collator $object - * @param string $str <p> + * @param string $string <p> * The string to produce the key from. * </p> - * @return string the collation key for the string. Collation keys can be compared directly instead of strings. + * @return string|false the collation key for the string. Collation keys can be compared directly instead of strings. */ -function collator_get_sort_key(Collator $object, $str) { } +function collator_get_sort_key( + Collator $object, + string $string, +): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3463,117 +3737,117 @@ function collator_get_sort_key(Collator $object, $str) { } * ICU RuleBasedNumberFormat * documentation, respectively. * </p> - * @param string $pattern [optional] <p> + * @param string|null $pattern [optional] <p> * Pattern string if the chosen style requires a pattern. * </p> - * @return NumberFormatter|false <b>NumberFormatter</b> object or <b>FALSE</b> on error. + * @return NumberFormatter|null <b>NumberFormatter</b> object or <b>NULL</b> on error. */ -function numfmt_create($locale, $style, $pattern = null) { } +function numfmt_create(string $locale, int $style, ?string $pattern = null): ?NumberFormatter {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Format a number * @link https://php.net/manual/en/numberformatter.format.php - * @param NumberFormatter $fmt - * @param int|float $value <p> + * @param NumberFormatter $formatter + * @param int|float $num <p> * The value to format. Can be integer or float, * other values will be converted to a numeric value. * </p> - * @param int $type [optional] <p> + * @param int $type <p> * The * formatting type to use. * </p> * @return string|false the string containing formatted value, or <b>FALSE</b> on error. */ -function numfmt_format(NumberFormatter $fmt, $value, $type = null) { } +function numfmt_format(NumberFormatter $formatter, int|float $num, int $type = 0): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Parse a number * @link https://php.net/manual/en/numberformatter.parse.php - * @param NumberFormatter $fmt - * @param string $value + * @param NumberFormatter $formatter + * @param string $string * @param int $type [optional] <p> * The * formatting type to use. By default, * <b>NumberFormatter::TYPE_DOUBLE</b> is used. * </p> - * @param int $position [optional] <p> + * @param int &$offset [optional] <p> * Offset in the string at which to begin parsing. On return, this value * will hold the offset at which parsing ended. * </p> - * @return mixed The value of the parsed number or <b>FALSE</b> on error. + * @return int|float|false The value of the parsed number or <b>FALSE</b> on error. */ -function numfmt_parse(NumberFormatter $fmt, $value, $type = null, &$position = null) { } +function numfmt_parse(NumberFormatter $formatter, string $string, int $type = NumberFormatter::TYPE_DOUBLE, &$offset = null): int|float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Format a currency value * @link https://php.net/manual/en/numberformatter.formatcurrency.php - * @param NumberFormatter $fmt - * @param float $value <p> + * @param NumberFormatter $formatter + * @param float $amount <p> * The numeric currency value. * </p> * @param string $currency <p> * The 3-letter ISO 4217 currency code indicating the currency to use. * </p> - * @return string String representing the formatted currency value. + * @return string|false String representing the formatted currency value. */ -function numfmt_format_currency(NumberFormatter $fmt, $value, $currency) { } +function numfmt_format_currency(NumberFormatter $formatter, float $amount, string $currency): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Parse a currency number * @link https://php.net/manual/en/numberformatter.parsecurrency.php - * @param NumberFormatter $fmt - * @param string $value - * @param string $currency <p> + * @param NumberFormatter $formatter + * @param string $string + * @param string &$currency <p> * Parameter to receive the currency name (3-letter ISO 4217 currency * code). * </p> - * @param int $position [optional] <p> + * @param int &$offset [optional] <p> * Offset in the string at which to begin parsing. On return, this value * will hold the offset at which parsing ended. * </p> * @return float|false The parsed numeric value or <b>FALSE</b> on error. */ -function numfmt_parse_currency(NumberFormatter $fmt, $value, &$currency, &$position = null) { } +function numfmt_parse_currency(NumberFormatter $formatter, string $string, &$currency, &$offset = null): float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Set an attribute * @link https://php.net/manual/en/numberformatter.setattribute.php - * @param NumberFormatter $fmt - * @param int $attr <p> + * @param NumberFormatter $formatter + * @param int $attribute <p> * Attribute specifier - one of the * numeric attribute constants. * </p> - * @param int $value <p> + * @param int|float $value <p> * The attribute value. * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function numfmt_set_attribute(NumberFormatter $fmt, $attr, $value) { } +function numfmt_set_attribute(NumberFormatter $formatter, int $attribute, int|float $value): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get an attribute * @link https://php.net/manual/en/numberformatter.getattribute.php - * @param NumberFormatter $fmt - * @param int $attr <p> + * @param NumberFormatter $formatter + * @param int $attribute <p> * Attribute specifier - one of the * numeric attribute constants. * </p> - * @return int|false Return attribute value on success, or <b>FALSE</b> on error. + * @return int|float|false Return attribute value on success, or <b>FALSE</b> on error. */ -function numfmt_get_attribute(NumberFormatter $fmt, $attr) { } +function numfmt_get_attribute(NumberFormatter $formatter, int $attribute): int|float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Set a text attribute * @link https://php.net/manual/en/numberformatter.settextattribute.php - * @param NumberFormatter $fmt - * @param int $attr <p> + * @param NumberFormatter $formatter + * @param int $attribute <p> * Attribute specifier - one of the * text attribute * constants. @@ -3583,27 +3857,27 @@ function numfmt_get_attribute(NumberFormatter $fmt, $attr) { } * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function numfmt_set_text_attribute(NumberFormatter $fmt, $attr, $value) { } +function numfmt_set_text_attribute(NumberFormatter $formatter, int $attribute, string $value): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get a text attribute * @link https://php.net/manual/en/numberformatter.gettextattribute.php - * @param NumberFormatter $fmt - * @param int $attr <p> + * @param NumberFormatter $formatter + * @param int $attribute <p> * Attribute specifier - one of the * text attribute constants. * </p> * @return string|false Return attribute value on success, or <b>FALSE</b> on error. */ -function numfmt_get_text_attribute(NumberFormatter $fmt, $attr) { } +function numfmt_get_text_attribute(NumberFormatter $formatter, int $attribute): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Set a symbol value * @link https://php.net/manual/en/numberformatter.setsymbol.php - * @param NumberFormatter $fmt - * @param int $attr <p> + * @param NumberFormatter $formatter + * @param int $symbol <p> * Symbol specifier, one of the * format symbol constants. * </p> @@ -3612,26 +3886,26 @@ function numfmt_get_text_attribute(NumberFormatter $fmt, $attr) { } * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function numfmt_set_symbol(NumberFormatter $fmt, $attr, $value) { } +function numfmt_set_symbol(NumberFormatter $formatter, int $symbol, string $value): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get a symbol value * @link https://php.net/manual/en/numberformatter.getsymbol.php - * @param NumberFormatter $fmt - * @param int $attr <p> + * @param NumberFormatter $formatter + * @param int $symbol <p> * Symbol specifier, one of the * format symbol constants. * </p> * @return string|false The symbol string or <b>FALSE</b> on error. */ -function numfmt_get_symbol(NumberFormatter $fmt, $attr) { } +function numfmt_get_symbol(NumberFormatter $formatter, int $symbol): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Set formatter pattern * @link https://php.net/manual/en/numberformatter.setpattern.php - * @param NumberFormatter $fmt + * @param NumberFormatter $formatter * @param string $pattern <p> * Pattern in syntax described in * ICU DecimalFormat @@ -3639,94 +3913,91 @@ function numfmt_get_symbol(NumberFormatter $fmt, $attr) { } * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function numfmt_set_pattern(NumberFormatter $fmt, $pattern) { } +function numfmt_set_pattern(NumberFormatter $formatter, string $pattern): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get formatter pattern * @link https://php.net/manual/en/numberformatter.getpattern.php - * @param NumberFormatter $fmt - * @param $nf + * @param NumberFormatter $formatter * @return string|false Pattern string that is used by the formatter, or <b>FALSE</b> if an error happens. */ -function numfmt_get_pattern(NumberFormatter $fmt, $nf) { } +function numfmt_get_pattern(NumberFormatter $formatter): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get formatter locale * @link https://php.net/manual/en/numberformatter.getlocale.php - * @param NumberFormatter $fmt - * @param int $type [optional] <p> + * @param NumberFormatter $formatter + * @param int $type <p> * You can choose between valid and actual locale ( * <b>Locale::VALID_LOCALE</b>, * <b>Locale::ACTUAL_LOCALE</b>, * respectively). The default is the actual locale. * </p> - * @return string The locale name used to create the formatter. + * @return string|false The locale name used to create the formatter. */ -function numfmt_get_locale(NumberFormatter $fmt, $type = null) { } +function numfmt_get_locale(NumberFormatter $formatter, int $type = 0): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get formatter's last error code. * @link https://php.net/manual/en/numberformatter.geterrorcode.php - * @param NumberFormatter $fmt - * @param $nf + * @param NumberFormatter $formatter * @return int error code from last formatter call. */ -function numfmt_get_error_code(NumberFormatter $fmt, $nf) { } +function numfmt_get_error_code(NumberFormatter $formatter): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get formatter's last error message. * @link https://php.net/manual/en/numberformatter.geterrormessage.php - * @param NumberFormatter $fmt - * @param $nf + * @param NumberFormatter $formatter * @return string error message from last formatter call. */ -function numfmt_get_error_message(NumberFormatter $fmt, $nf) { } +function numfmt_get_error_message(NumberFormatter $formatter): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Normalizes the input provided and returns the normalized string * @link https://php.net/manual/en/normalizer.normalize.php - * @param string $input <p>The input string to normalize</p> - * @param string $form [optional] <p>One of the normalization forms.</p> - * @return string The normalized string or <b>NULL</b> if an error occurred. + * @param string $string <p>The input string to normalize</p> + * @param int $form [optional] <p>One of the normalization forms.</p> + * @return string|false The normalized string or <b>FALSE</b> if an error occurred. */ -function normalizer_normalize($input, $form = Normalizer::FORM_C) { } +function normalizer_normalize(string $string, int $form = Normalizer::FORM_C): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Checks if the provided string is already in the specified normalization -form. + * form. * @link https://php.net/manual/en/normalizer.isnormalized.php - * @param string $input <p>The input string to normalize</p> - * @param string $form [optional] <p> + * @param string $string <p>The input string to normalize</p> + * @param int $form [optional] <p> * One of the normalization forms. * </p> * @return bool <b>TRUE</b> if normalized, <b>FALSE</b> otherwise or if there an error */ -function normalizer_is_normalized($input, $form = Normalizer::FORM_C) { } +function normalizer_is_normalized(string $string, int $form = Normalizer::FORM_C): bool {} /** - * Get the default Locale + * Gets the default locale value from the intl global 'default_locale' * @link https://php.net/manual/en/function.locale-get-default.php * @return string a string with the current Locale. */ -function locale_get_default() { } +function locale_get_default(): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> - * Set the default Locale + * Set the default runtime Locale * @link https://php.net/manual/en/function.locale-set-default.php - * @param string $name <p> + * @param string $locale <p> * The new Locale name. A comprehensive list of the supported locales is * available at . * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function locale_set_default($name) { } +function locale_set_default(string $locale): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3735,9 +4006,9 @@ function locale_set_default($name) { } * @param string $locale <p> * The locale to extract the primary language code from * </p> - * @return string The language code associated with the language or <b>NULL</b> in case of error. + * @return string|null The language code associated with the language or <b>NULL</b> in case of error. */ -function locale_get_primary_language($locale) { } +function locale_get_primary_language(string $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3746,9 +4017,9 @@ function locale_get_primary_language($locale) { } * @param string $locale <p> * The locale to extract the script code from * </p> - * @return string The script subtag for the locale or <b>NULL</b> if not present + * @return string|null The script subtag for the locale or <b>NULL</b> if not present */ -function locale_get_script($locale) { } +function locale_get_script(string $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3757,9 +4028,9 @@ function locale_get_script($locale) { } * @param string $locale <p> * The locale to extract the region code from * </p> - * @return string The region subtag for the locale or <b>NULL</b> if not present + * @return string|null The region subtag for the locale or <b>NULL</b> if not present */ -function locale_get_region($locale) { } +function locale_get_region(string $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3768,9 +4039,9 @@ function locale_get_region($locale) { } * @param string $locale <p> * The locale to extract the keywords from * </p> - * @return array Associative array containing the keyword-value pairs for this locale + * @return array|false|null Associative array containing the keyword-value pairs for this locale */ -function locale_get_keywords($locale) { } +function locale_get_keywords(string $locale): array|false|null {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3779,13 +4050,16 @@ function locale_get_keywords($locale) { } * @param string $locale <p> * The locale to return a display script for * </p> - * @param string $in_locale [optional] <p> + * @param string|null $displayLocale <p> * Optional format locale to use to display the script name * </p> - * @return string Display name of the script for the $locale in the format appropriate for + * @return string|false Display name of the script for the $locale in the format appropriate for * $in_locale. */ -function locale_get_display_script($locale, $in_locale = null) { } +function locale_get_display_script( + string $locale, + ?string $displayLocale = null +): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3794,13 +4068,16 @@ function locale_get_display_script($locale, $in_locale = null) { } * @param string $locale <p> * The locale to return a display region for. * </p> - * @param string $in_locale [optional] <p> + * @param string|null $displayLocale <p> * Optional format locale to use to display the region name * </p> - * @return string display name of the region for the $locale in the format appropriate for + * @return string|false display name of the region for the $locale in the format appropriate for * $in_locale. */ -function locale_get_display_region($locale, $in_locale = null) { } +function locale_get_display_region( + string $locale, + ?string $displayLocale = null +): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3809,10 +4086,13 @@ function locale_get_display_region($locale, $in_locale = null) { } * @param string $locale <p> * The locale to return a display name for. * </p> - * @param string $in_locale [optional] <p>optional format locale</p> - * @return string Display name of the locale in the format appropriate for $in_locale. + * @param string|null $displayLocale <p>optional format locale</p> + * @return string|false Display name of the locale in the format appropriate for $in_locale. */ -function locale_get_display_name($locale, $in_locale = null) { } +function locale_get_display_name( + string $locale, + ?string $displayLocale = null +): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3821,13 +4101,16 @@ function locale_get_display_name($locale, $in_locale = null) { } * @param string $locale <p> * The locale to return a display language for * </p> - * @param string $in_locale [optional] <p> + * @param string|null $displayLocale <p> * Optional format locale to use to display the language name * </p> - * @return string display name of the language for the $locale in the format appropriate for + * @return string|false display name of the language for the $locale in the format appropriate for * $in_locale. */ -function locale_get_display_language($locale, $in_locale = null) { } +function locale_get_display_language( + string $locale, + ?string $displayLocale = null +): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3836,19 +4119,22 @@ function locale_get_display_language($locale, $in_locale = null) { } * @param string $locale <p> * The locale to return a display variant for * </p> - * @param string $in_locale [optional] <p> + * @param string|null $displayLocale <p> * Optional format locale to use to display the variant name * </p> - * @return string Display name of the variant for the $locale in the format appropriate for + * @return string|false Display name of the variant for the $locale in the format appropriate for * $in_locale. */ -function locale_get_display_variant($locale, $in_locale = null) { } +function locale_get_display_variant( + string $locale, + ?string $displayLocale = null +): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Returns a correctly ordered and delimited locale ID * @link https://php.net/manual/en/locale.composelocale.php - * @param array $subtags <p> + * @param string[] $subtags <p> * an array containing a list of key-value pairs, where the keys identify * the particular locale ID subtags, and the values are the associated * subtag values. @@ -3866,9 +4152,9 @@ function locale_get_display_variant($locale, $in_locale = null) { } * (e.g. 'variant0', 'variant1', etc.). * </p> * </p> - * @return string The corresponding locale identifier. + * @return string|false The corresponding locale identifier. */ -function locale_compose(array $subtags) { } +function locale_compose(array $subtags): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3879,14 +4165,14 @@ function locale_compose(array $subtags) { } * 'private' subtags can take maximum 15 values whereas 'extlang' can take * maximum 3 values. * </p> - * @return array an array containing a list of key-value pairs, where the keys + * @return string[]|null an array containing a list of key-value pairs, where the keys * identify the particular locale ID subtags, and the values are the * associated subtag values. The array will be ordered as the locale id * subtags e.g. in the locale id if variants are '-varX-varY-varZ' then the * returned array will have variant0=>varX , variant1=>varY , * variant2=>varZ */ -function locale_parse($locale) { } +function locale_parse(string $locale): ?array {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3895,55 +4181,67 @@ function locale_parse($locale) { } * @param string $locale <p> * The locale to extract the variants from * </p> - * @return array The array containing the list of all variants subtag for the locale + * @return array|null The array containing the list of all variants subtag for the locale * or <b>NULL</b> if not present */ -function locale_get_all_variants($locale) { } +function locale_get_all_variants(string $locale): ?array {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Checks if a language tag filter matches with locale * @link https://php.net/manual/en/locale.filtermatches.php - * @param string $langtag <p> + * @param string $languageTag <p> * The language tag to check * </p> * @param string $locale <p> * The language range to check against * </p> - * @param bool $canonicalize [optional] <p> + * @param bool $canonicalize <p> * If true, the arguments will be converted to canonical form before * matching. * </p> - * @return bool <b>TRUE</b> if $locale matches $langtag <b>FALSE</b> otherwise. + * @return bool|null <b>TRUE</b> if $locale matches $langtag <b>FALSE</b> otherwise. */ -function locale_filter_matches($langtag, $locale, $canonicalize = false) { } +function locale_filter_matches( + string $languageTag, + string $locale, + bool $canonicalize = false +): ?bool {} /** - * @param $arg1 + * Canonicalize the locale string + * @param string $locale + * + * @return null|string */ -function locale_canonicalize($arg1) { } +function locale_canonicalize(string $locale): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Searches the language tag list for the best match to the language * @link https://php.net/manual/en/locale.lookup.php - * @param array $langtag <p> + * @param string[] $languageTag <p> * An array containing a list of language tags to compare to * <i>locale</i>. Maximum 100 items allowed. * </p> * @param string $locale <p> * The locale to use as the language range when matching. * </p> - * @param bool $canonicalize [optional] <p> + * @param bool $canonicalize <p> * If true, the arguments will be converted to canonical form before * matching. * </p> - * @param string $default [optional] <p> + * @param string|null $defaultLocale <p> * The locale to use if no match is found. * </p> - * @return string The closest matching language tag or default value. + * @return string|null The closest matching language tag or default value. */ -function locale_lookup(array $langtag, $locale, $canonicalize = false, $default = null) { } +function locale_lookup( + array $languageTag, + string $locale, + bool $canonicalize = false, + ?string $defaultLocale = null, +): ?string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3952,27 +4250,29 @@ function locale_lookup(array $langtag, $locale, $canonicalize = false, $default * @param string $header <p> * The string containing the "Accept-Language" header according to format in RFC 2616. * </p> - * @return string The corresponding locale identifier. + * @return string|false The corresponding locale identifier. */ -function locale_accept_from_http($header) { } +function locale_accept_from_http(string $header): string|false {} /** - * @param $locale - * @param $pattern + * Constructs a new message formatter + * @param string $locale + * @param string $pattern + * @return MessageFormatter|null */ -function msgfmt_create($locale, $pattern) { } +function msgfmt_create(string $locale, string $pattern): ?MessageFormatter {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Format the message * @link https://php.net/manual/en/messageformatter.format.php - * @param MessageFormatter $fmt - * @param array $args <p> + * @param MessageFormatter $formatter + * @param array $values <p> * Arguments to insert into the format string * </p> * @return string|false The formatted string, or <b>FALSE</b> if an error occurred */ -function msgfmt_format(MessageFormatter $fmt, array $args) { } +function msgfmt_format(MessageFormatter $formatter, array $values): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -3987,48 +4287,47 @@ function msgfmt_format(MessageFormatter $fmt, array $args) { } * umsg_autoQuoteApostrophe * before being interpreted. * </p> - * @param array $args <p> + * @param array $values <p> * The array of values to insert into the format string * </p> * @return string|false The formatted pattern string or <b>FALSE</b> if an error occurred */ -function msgfmt_format_message(string $locale, string $pattern, array $args) { } +function msgfmt_format_message(string $locale, string $pattern, array $values): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Parse input string according to pattern * @link https://php.net/manual/en/messageformatter.parse.php - * @param MessageFormatter $fmt - * @param string $value <p> + * @param MessageFormatter $formatter + * @param string $string <p> * The string to parse * </p> * @return array|false An array containing the items extracted, or <b>FALSE</b> on error */ -function msgfmt_parse(MessageFormatter $fmt, $value) { } +function msgfmt_parse(MessageFormatter $formatter, string $string): array|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Quick parse input string * @link https://php.net/manual/en/messageformatter.parsemessage.php - * @param MessageFormatter $fmt * @param string $locale <p> * The locale to use for parsing locale-dependent parts * </p> * @param string $pattern <p> * The pattern with which to parse the <i>value</i>. * </p> - * @param string $source <p> + * @param string $message <p> * The string to parse, conforming to the <i>pattern</i>. * </p> * @return array|false An array containing items extracted, or <b>FALSE</b> on error */ -function msgfmt_parse_message(MessageFormatter $fmt, $locale, $pattern, $source) { } +function msgfmt_parse_message(string $locale, string $pattern, string $message): array|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Set the pattern used by the formatter * @link https://php.net/manual/en/messageformatter.setpattern.php - * @param MessageFormatter $fmt + * @param MessageFormatter $formatter * @param string $pattern <p> * The pattern string to use in this message formatter. * The pattern uses an 'apostrophe-friendly' syntax; it is run through @@ -4037,47 +4336,43 @@ function msgfmt_parse_message(MessageFormatter $fmt, $locale, $pattern, $source) * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function msgfmt_set_pattern(MessageFormatter $fmt, $pattern) { } +function msgfmt_set_pattern(MessageFormatter $formatter, string $pattern): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the pattern used by the formatter * @link https://php.net/manual/en/messageformatter.getpattern.php - * @param MessageFormatter $fmt - * @param $mf - * @return string The pattern string for this message formatter + * @param MessageFormatter $formatter + * @return string|false The pattern string for this message formatter */ -function msgfmt_get_pattern(MessageFormatter $fmt, $mf) { } +function msgfmt_get_pattern(MessageFormatter $formatter): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the locale for which the formatter was created. * @link https://php.net/manual/en/messageformatter.getlocale.php - * @param MessageFormatter $fmt - * @param $mf + * @param MessageFormatter $formatter * @return string The locale name */ -function msgfmt_get_locale(MessageFormatter $fmt, $mf) { } +function msgfmt_get_locale(MessageFormatter $formatter): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the error code from last operation * @link https://php.net/manual/en/messageformatter.geterrorcode.php - * @param MessageFormatter $fmt - * @param $nf + * @param MessageFormatter $formatter * @return int The error code, one of UErrorCode values. Initial value is U_ZERO_ERROR. */ -function msgfmt_get_error_code(MessageFormatter $fmt, $nf) { } +function msgfmt_get_error_code(MessageFormatter $formatter): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the error text from the last operation * @link https://php.net/manual/en/messageformatter.geterrormessage.php - * @param MessageFormatter $fmt - * @param $coll + * @param MessageFormatter $formatter * @return string Description of the last error. */ -function msgfmt_get_error_message(MessageFormatter $fmt, $coll) { } +function msgfmt_get_error_message(MessageFormatter $formatter): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -4086,14 +4381,14 @@ function msgfmt_get_error_message(MessageFormatter $fmt, $coll) { } * @param string|null $locale <p> * Locale to use when formatting or parsing. * </p> - * @param int $datetype <p> + * @param int $dateType <p> * Date type to use (<b>none</b>, * <b>short</b>, <b>medium</b>, * <b>long</b>, <b>full</b>). * This is one of the * IntlDateFormatter constants. * </p> - * @param int $timetype <p> + * @param int $timeType <p> * Time type to use (<b>none</b>, * <b>short</b>, <b>medium</b>, * <b>long</b>, <b>full</b>). @@ -4103,164 +4398,160 @@ function msgfmt_get_error_message(MessageFormatter $fmt, $coll) { } * @param string|null $timezone [optional] <p> * Time zone ID, default is system default. * </p> - * @param int|null $calendar [optional] <p> + * @param IntlCalendar|int|null $calendar [optional] <p> * Calendar to use for formatting or parsing; default is Gregorian. * This is one of the * IntlDateFormatter calendar constants. * </p> - * @param string $pattern [optional] <p> + * @param string|null $pattern [optional] <p> * Optional pattern to use when formatting or parsing. * Possible patterns are documented at http://userguide.icu-project.org/formatparse/datetime. * </p> - * @return IntlDateFormatter + * @return IntlDateFormatter|null */ -function datefmt_create($locale, $datetype, $timetype, $timezone = null, $calendar = null, $pattern = '') { } +function datefmt_create( + ?string $locale, + int $dateType = 0, + int $timeType = 0, + $timezone = null, + IntlCalendar|int|null $calendar = null, + string|null $pattern = null +): ?IntlDateFormatter {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the datetype used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.getdatetype.php - * @param $mf - * @return int The current date type value of the formatter. + * @param IntlDateFormatter $formatter + * @return int|false The current date type value of the formatter. */ -function datefmt_get_datetype(MessageFormatter $mf) { } +function datefmt_get_datetype(IntlDateFormatter $formatter): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the timetype used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.gettimetype.php - * @param $mf - * @return int The current date type value of the formatter. + * @param IntlDateFormatter $formatter + * @return int|false The current date type value of the formatter. */ -function datefmt_get_timetype(MessageFormatter $mf) { } +function datefmt_get_timetype(IntlDateFormatter $formatter): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> - * Get the calendar used for the IntlDateFormatter + * Get the calendar type used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.getcalendar.php - * @param $mf - * @return int The calendar being used by the formatter. + * @param IntlDateFormatter $formatter + * @return int|false The calendar being used by the formatter. */ -function datefmt_get_calendar(MessageFormatter $mf) { } +function datefmt_get_calendar(IntlDateFormatter $formatter): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * sets the calendar used to the appropriate calendar, which must be * @link https://php.net/manual/en/intldateformatter.setcalendar.php - * @param MessageFormatter $mf - * @param int $which <p> + * @param IntlDateFormatter $formatter $mf + * @param IntlCalendar|int|null $calendar <p> * The calendar to use. * Default is <b>IntlDateFormatter::GREGORIAN</b>. * </p> * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function datefmt_set_calendar(MessageFormatter $mf, $which) { } +function datefmt_set_calendar(IntlDateFormatter $formatter, IntlCalendar|int|null $calendar): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the locale used by formatter * @link https://php.net/manual/en/intldateformatter.getlocale.php - * @param MessageFormatter $mf - * @param int $which [optional] + * @param IntlDateFormatter $formatter + * @param int $type [optional] * @return string|false the locale of this formatter or 'false' if error */ -function datefmt_get_locale(MessageFormatter $mf, $which = null) { } +function datefmt_get_locale( + IntlDateFormatter $formatter, + int $type = ULOC_ACTUAL_LOCALE +): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the timezone-id used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.gettimezoneid.php - * @param $mf - * @return string ID string for the time zone used by this formatter. + * @param IntlDateFormatter $formatter + * @return string|false ID string for the time zone used by this formatter. */ -function datefmt_get_timezone_id(MessageFormatter $mf) { } +function datefmt_get_timezone_id(IntlDateFormatter $formatter): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 3.0.0)<br/> * Get copy of formatter's calendar object - * @link https://www.php.net/manual/en/intldateformatter.getcalendarobject.php - * @return IntlCalendar A copy of the internal calendar object used by this formatter. + * @link https://secure.php.net/manual/en/intldateformatter.getcalendarobject.php + * @param IntlDateFormatter $formatter + * @return IntlCalendar|false|null A copy of the internal calendar object used by this formatter. */ -function datefmt_get_calendar_object() { } +function datefmt_get_calendar_object(IntlDateFormatter $formatter): IntlCalendar|false|null {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)<br/> * Get formatter's timezone - * @link https://www.php.net/manual/en/intldateformatter.gettimezone.php + * @link https://secure.php.net/manual/en/intldateformatter.gettimezone.php + * @param IntlDateFormatter $formatter * @return IntlTimeZone|false The associated IntlTimeZone object or FALSE on failure. */ -function datefmt_get_timezone() { } - -/** - * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> - * Sets the time zone to use - * @link https://php.net/manual/en/intldateformatter.settimezoneid.php - * @param MessageFormatter $mf - * @param string $zone <p> - * The time zone ID string of the time zone to use. - * If <b>NULL</b> or the empty string, the default time zone for the runtime is used. - * </p> - * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. - * @deprecated 5.5 https://www.php.net/manual/en/migration55.deprecated.php - * @removed 7.0 - */ -function datefmt_set_timezone_id(MessageFormatter $mf, $zone) { } - +function datefmt_get_timezone(IntlDateFormatter $formatter): IntlTimeZone|false {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)<br/> * Sets formatter's timezone * @link https://php.net/manual/en/intldateformatter.settimezone.php - * @param MessageFormatter $mf - * @param mixed $zone <p> + * @param IntlDateFormatter $formatter + * @param IntlTimeZone|DateTimeZone|string|null $timezone <p> * The timezone to use for this formatter. This can be specified in the * following forms: * <ul> * <li> * <p> * <b>NULL</b>, in which case the default timezone will be used, as specified in - * the ini setting {@link "https://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone" date.timezone} or - * through the function {@link "https://www.php.net/manual/en/function.date-default-timezone-set.php" date_default_timezone_set()} and as - * returned by {@link "https://www.php.net/manual/en/function.date-default-timezone-get.php" date_default_timezone_get()}. + * the ini setting {@link "https://secure.php.net/manual/en/datetime.configuration.php#ini.date.timezone" date.timezone} or + * through the function {@link "https://secure.php.net/manual/en/function.date-default-timezone-set.php" date_default_timezone_set()} and as + * returned by {@link "https://secure.php.net/manual/en/function.date-default-timezone-get.php" date_default_timezone_get()}. * </p> * </li> * <li> * <p> - * An {@link "https://www.php.net/manual/en/class.intltimezone.php" IntlTimeZone}, which will be used directly. + * An {@link "https://secure.php.net/manual/en/class.intltimezone.php" IntlTimeZone}, which will be used directly. * </p> * </li> * <li> * <p> - * A {@link "https://www.php.net/manual/en/class.datetimezone.php" DateTimeZone}. Its identifier will be extracted + * A {@link "https://secure.php.net/manual/en/class.datetimezone.php" DateTimeZone}. Its identifier will be extracted * and an ICU timezone object will be created; the timezone will be backed * by ICU's database, not PHP's. * </p> * </li> * <li> * <p> - * A {@link "https://www.php.net/manual/en/language.types.string.php" string}, which should be a valid ICU timezone identifier. + * A {@link "https://secure.php.net/manual/en/language.types.string.php" string}, which should be a valid ICU timezone identifier. * See <b>IntlTimeZone::createTimeZoneIDEnumeration()</b>. Raw offsets such as <em>"GMT+08:30"</em> are also accepted. * </p> * </li> * </ul> * </p> - * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. + * @return bool|null <b>TRUE</b> on success or <b>FALSE</b> on failure. */ -function datefmt_set_timezone(MessageFormatter $mf, $zone) { } +function datefmt_set_timezone(IntlDateFormatter $formatter, $timezone): bool|null {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the pattern used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.getpattern.php - * @param $mf - * @return string The pattern string being used to format/parse. + * @param IntlDateFormatter $formatter + * @return string|false The pattern string being used to format/parse. */ -function datefmt_get_pattern(MessageFormatter $mf) { } +function datefmt_get_pattern(IntlDateFormatter $formatter): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Set the pattern used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.setpattern.php - * @param MessageFormatter $mf + * @param IntlDateFormatter $formatter * @param string $pattern <p> * New pattern string to use. * Possible patterns are documented at http://userguide.icu-project.org/formatparse/datetime. @@ -4268,35 +4559,38 @@ function datefmt_get_pattern(MessageFormatter $mf) { } * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. * Bad formatstrings are usually the cause of the failure. */ -function datefmt_set_pattern(MessageFormatter $mf, $pattern) { } +function datefmt_set_pattern(IntlDateFormatter $formatter, string $pattern): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the lenient used for the IntlDateFormatter * @link https://php.net/manual/en/intldateformatter.islenient.php - * @param $mf + * @param IntlDateFormatter $formatter * @return bool <b>TRUE</b> if parser is lenient, <b>FALSE</b> if parser is strict. By default the parser is lenient. */ -function datefmt_is_lenient(MessageFormatter $mf) { } +function datefmt_is_lenient(IntlDateFormatter $formatter): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Set the leniency of the parser * @link https://php.net/manual/en/intldateformatter.setlenient.php - * @param MessageFormatter $mf + * @param IntlDateFormatter $formatter * @param bool $lenient <p> * Sets whether the parser is lenient or not, default is <b>TRUE</b> (lenient). * </p> - * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. + * @return void */ -function datefmt_set_lenient(MessageFormatter $mf, $lenient) { } +function datefmt_set_lenient( + IntlDateFormatter $formatter, + bool $lenient +): void {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Format the date/time value as a string * @link https://php.net/manual/en/intldateformatter.format.php - * @param MessageFormatter $mf - * @param mixed $value <p> + * @param IntlDateFormatter $formatter + * @param object|array|string|int|float $datetime <p> * Value to format. This may be a <b>DateTime</b> object, * an integer representing a Unix timestamp value (seconds * since epoch, UTC) or an array in the format output by @@ -4304,17 +4598,20 @@ function datefmt_set_lenient(MessageFormatter $mf, $lenient) { } * </p> * @return string|false The formatted string or, if an error occurred, <b>FALSE</b>. */ -function datefmt_format(MessageFormatter $mf, $value) { } +function datefmt_format( + IntlDateFormatter $formatter, + $datetime +): string|false {} /** * (PHP 5 >= 5.5.0, PECL intl >= 3.0.0)<br/> * Formats an object - * @link https://www.php.net/manual/en/intldateformatter.formatobject.php - * @param object $object <p> + * @link https://secure.php.net/manual/en/intldateformatter.formatobject.php + * @param IntlCalendar|DateTimeInterface $datetime <p> * An object of type IntlCalendar or DateTime. The timezone information in the object will be used. * </p> - * @param mixed $format [optional] <p> - * How to format the date/time. This can either be an {https://www.php.net/manual/en/language.types.array.php array} with + * @param array|int|string|null $format [optional] <p> + * How to format the date/time. This can either be an {https://secure.php.net/manual/en/language.types.array.php array} with * two elements (first the date style, then the time style, these being one * of the constants <b>IntlDateFormatter::NONE</b>, * <b>IntlDateFormatter::SHORT</b>, @@ -4322,7 +4619,7 @@ function datefmt_format(MessageFormatter $mf, $value) { } * <b>IntlDateFormatter::LONG</b>, * <b>IntlDateFormatter::FULL</b>), a long with * the value of one of these constants (in which case it will be used both - * for the time and the date) or a {@link https://www.php.net/manual/en/language.types.string.php} with the format + * for the time and the date) or a {@link https://secure.php.net/manual/en/language.types.string.php} with the format * described in {@link http://www.icu-project.org/apiref/icu4c/classSimpleDateFormat.html#details the ICU documentation} * documentation. If <b>NULL</b>, the default style will be used. * </p> @@ -4330,74 +4627,73 @@ function datefmt_format(MessageFormatter $mf, $value) { } * The locale to use, or NULL to use the default one.</p> * @return string|false The formatted string or, if an error occurred, <b>FALSE</b>. */ -function datefmt_format_object($object, $format = null, $locale = null) { } +function datefmt_format_object($datetime, $format = null, ?string $locale = null): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Parse string to a timestamp value * @link https://php.net/manual/en/intldateformatter.parse.php - * @param MessageFormatter $mf - * @param string $value <p> + * @param IntlDateFormatter $formatter + * @param string $string <p> * string to convert to a time * </p> - * @param int $position [optional] <p> + * @param int &$offset [optional] <p> * Position at which to start the parsing in $value (zero-based). * If no error occurs before $value is consumed, $parse_pos will contain -1 * otherwise it will contain the position at which parsing ended (and the error occurred). * This variable will contain the end position if the parse fails. * If $parse_pos > strlen($value), the parse fails immediately. * </p> - * @return int timestamp parsed value + * @return int|float|false timestamp parsed value */ -function datefmt_parse(MessageFormatter $mf, $value, &$position = null) { } +function datefmt_parse(IntlDateFormatter $formatter, string $string, &$offset = null): int|float|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Parse string to a field-based time value * @link https://php.net/manual/en/intldateformatter.localtime.php - * @param MessageFormatter $mf - * @param string $value <p> + * @param IntlDateFormatter $formatter + * @param string $string <p> * string to convert to a time * </p> - * @param int $position [optional] <p> + * @param int &$offset [optional] <p> * Position at which to start the parsing in $value (zero-based). * If no error occurs before $value is consumed, $parse_pos will contain -1 * otherwise it will contain the position at which parsing ended . * If $parse_pos > strlen($value), the parse fails immediately. * </p> - * @return array Localtime compatible array of integers : contains 24 hour clock value in tm_hour field + * @return array|false Localtime compatible array of integers : contains 24 hour clock value in tm_hour field */ -function datefmt_localtime(MessageFormatter $mf, $value, &$position = null) { } +function datefmt_localtime(IntlDateFormatter $formatter, string $string, &$offset = null): array|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the error code from last operation * @link https://php.net/manual/en/intldateformatter.geterrorcode.php - * @param MessageFormatter $mf + * @param IntlDateFormatter $formatter * @return int The error code, one of UErrorCode values. Initial value is U_ZERO_ERROR. */ -function datefmt_get_error_code(MessageFormatter $mf) { } +function datefmt_get_error_code(IntlDateFormatter $formatter): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get the error text from the last operation. * @link https://php.net/manual/en/intldateformatter.geterrormessage.php - * @param MessageFormatter $mf - * @param $coll + * @param IntlDateFormatter $formatter * @return string Description of the last error. */ -function datefmt_get_error_message(MessageFormatter $mf, $coll) { } +function datefmt_get_error_message(IntlDateFormatter $formatter): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get string length in grapheme units * @link https://php.net/manual/en/function.grapheme-strlen.php - * @param string $input <p> + * @param string $string <p> * The string being measured for length. It must be a valid UTF-8 string. * </p> * @return int|false|null The length of the string on success, and 0 if the string is empty. */ -function grapheme_strlen($input) { } +function grapheme_strlen(string $string): int|false|null {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -4417,7 +4713,7 @@ function grapheme_strlen($input) { } * </p> * @return int|false the position as an integer. If needle is not found, strpos() will return boolean FALSE. */ -function grapheme_strpos($haystack, $needle, $offset = 0) { } +function grapheme_strpos(string $haystack, string $needle, int $offset = 0): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -4437,7 +4733,7 @@ function grapheme_strpos($haystack, $needle, $offset = 0) { } * </p> * @return int|false the position as an integer. If needle is not found, grapheme_stripos() will return boolean FALSE. */ -function grapheme_stripos($haystack, $needle, $offset = 0) { } +function grapheme_stripos(string $haystack, string $needle, int $offset = 0): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -4457,7 +4753,7 @@ function grapheme_stripos($haystack, $needle, $offset = 0) { } * </p> * @return int|false the position as an integer. If needle is not found, grapheme_strrpos() will return boolean FALSE. */ -function grapheme_strrpos($haystack, $needle, $offset = 0) { } +function grapheme_strrpos(string $haystack, string $needle, int $offset = 0): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -4477,7 +4773,7 @@ function grapheme_strrpos($haystack, $needle, $offset = 0) { } * </p> * @return int|false the position as an integer. If needle is not found, grapheme_strripos() will return boolean FALSE. */ -function grapheme_strripos($haystack, $needle, $offset = 0) { } +function grapheme_strripos(string $haystack, string $needle, int $offset = 0): int|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -4486,14 +4782,14 @@ function grapheme_strripos($haystack, $needle, $offset = 0) { } * @param string $string <p> * The input string. Must be valid UTF-8. * </p> - * @param int $start <p> + * @param int $offset <p> * Start position in default grapheme units. * If $start is non-negative, the returned string will start at the * $start'th position in $string, counting from zero. If $start is negative, * the returned string will start at the $start'th grapheme unit from the * end of string. * </p> - * @param int $length [optional] <p> + * @param int|null $length [optional] <p> * Length in grapheme units. * If $length is given and is positive, the string returned will contain * at most $length grapheme units beginning from $start (depending on the @@ -4503,10 +4799,10 @@ function grapheme_strripos($haystack, $needle, $offset = 0) { } * denotes a position beyond this truncation, <b>FALSE</b> will be returned. * </p> * @return string|false <p>the extracted part of $string,<br /> - or <strong>FALSE</strong> if $length is negative and $start denotes a position beyond truncation $length,<br /> - or also <strong>FALSE</strong> if $start denotes a position beyond $string length</p> + * or <strong>FALSE</strong> if $length is negative and $start denotes a position beyond truncation $length,<br /> + * or also <strong>FALSE</strong> if $start denotes a position beyond $string length</p> */ -function grapheme_substr($string, $start, $length = null) { } +function grapheme_substr(string $string, int $offset, ?int $length = null): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -4518,13 +4814,13 @@ function grapheme_substr($string, $start, $length = null) { } * @param string $needle <p> * The string to look for. Must be valid UTF-8. * </p> - * @param bool $before_needle [optional] <p> + * @param bool $beforeNeedle [optional] <p> * If <b>TRUE</b>, grapheme_strstr() returns the part of the * haystack before the first occurrence of the needle (excluding the needle). * </p> * @return string|false the portion of string, or FALSE if needle is not found. */ -function grapheme_strstr($haystack, $needle, $before_needle = false) { } +function grapheme_strstr(string $haystack, string $needle, bool $beforeNeedle = false): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -4536,13 +4832,13 @@ function grapheme_strstr($haystack, $needle, $before_needle = false) { } * @param string $needle <p> * The string to look for. Must be valid UTF-8. * </p> - * @param bool $before_needle [optional] <p> + * @param bool $beforeNeedle [optional] <p> * If <b>TRUE</b>, grapheme_strstr() returns the part of the * haystack before the first occurrence of the needle (excluding needle). * </p> * @return string|false the portion of $haystack, or FALSE if $needle is not found. */ -function grapheme_stristr($haystack, $needle, $before_needle = false) { } +function grapheme_stristr(string $haystack, string $needle, bool $beforeNeedle = false): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -4554,7 +4850,7 @@ function grapheme_stristr($haystack, $needle, $before_needle = false) { } * @param int $size <p> * Maximum number items - based on the $extract_type - to return. * </p> - * @param int $extract_type [optional] <p> + * @param int $type <p> * Defines the type of units referred to by the $size parameter: * </p> * <p> @@ -4565,20 +4861,20 @@ function grapheme_stristr($haystack, $needle, $before_needle = false) { } * GRAPHEME_EXTR_MAXCHARS - $size is the maximum number of UTF-8 * characters returned. * </p> - * @param int $start [optional] <p> + * @param int $offset [optional] <p> * Starting position in $haystack in bytes - if given, it must be zero or a * positive value that is less than or equal to the length of $haystack in * bytes. If $start does not point to the first byte of a UTF-8 * character, the start position is moved to the next character boundary. * </p> - * @param int $next [optional] <p> + * @param int &$next [optional] <p> * Reference to a value that will be set to the next starting position. * When the call returns, this may point to the first byte position past the end of the string. * </p> * @return string|false A string starting at offset $start and ending on a default grapheme cluster * boundary that conforms to the $size and $extract_type specified. */ -function grapheme_extract($haystack, $size, $extract_type = null, $start = 0, &$next = null) { } +function grapheme_extract(string $haystack, int $size, int $type = 0, int $offset = 0, &$next = null): string|false {} /** * (PHP 5 >= 5.3.0, PHP 7, PECL intl >= 1.0.2, PHP 7, PECL idn >= 0.1)<br/> @@ -4590,13 +4886,13 @@ function grapheme_extract($haystack, $size, $extract_type = null, $start = 0, &$ * passed it will be converted into an ACE encoded "xn--" string. * It will not be the one you expected though! * </p> - * @param int $options [optional] <p> + * @param int $flags [optional] <p> * Conversion options - combination of IDNA_* constants (except IDNA_ERROR_* constants). * </p> * @param int $variant [optional] <p> * Either INTL_IDNA_VARIANT_2003 for IDNA 2003 or INTL_IDNA_VARIANT_UTS46 for UTS #46. * </p> - * @param array $idna_info [optional] <p> + * @param array &$idna_info [optional] <p> * This parameter can be used only if INTL_IDNA_VARIANT_UTS46 was used for variant. * In that case, it will be filled with an array with the keys 'result', * the possibly illegal result of the transformation, 'isTransitionalDifferent', @@ -4606,7 +4902,7 @@ function grapheme_extract($haystack, $size, $extract_type = null, $start = 0, &$ * </p> * @return string|false The ACE encoded version of the domain name or <b>FALSE</b> on failure. */ -function idn_to_ascii($domain, $options = 0, $variant = INTL_IDNA_VARIANT_2003, array &$idna_info = null) { } +function idn_to_ascii(string $domain, int $flags = 0, int $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info): string|false {} /** * (PHP 5 >= 5.3.0, PHP 7, PECL intl >= 1.0.2, PHP 7, PECL idn >= 0.1)<br/> @@ -4616,7 +4912,7 @@ function idn_to_ascii($domain, $options = 0, $variant = INTL_IDNA_VARIANT_2003, * Domain to convert in IDNA ASCII-compatible format. * The ASCII encoded domain name. Looks like "xn--..." if the it originally contained non-ASCII characters. * </p> - * @param int $options [optional] <p> + * @param int $flags [optional] <p> * Conversion options - combination of IDNA_* constants (except IDNA_ERROR_* constants). * </p> * @param int $variant [optional] <p> @@ -4634,13 +4930,18 @@ function idn_to_ascii($domain, $options = 0, $variant = INTL_IDNA_VARIANT_2003, * RFC 3490 4.2 states though "ToUnicode never fails. If any step fails, then the original input * sequence is returned immediately in that step." */ -function idn_to_utf8($domain, $options = 0, $variant = INTL_IDNA_VARIANT_2003, array &$idna_info = null) { } +function idn_to_utf8( + string $domain, + int $flags = 0, + int $variant = INTL_IDNA_VARIANT_UTS46, + &$idna_info = null, +): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Create a new IntlCalendar - * @link https://www.php.net/manual/en/intlcalendar.createinstance.php - * @param mixed $timeZone [optional] <p> <p> + * @link https://secure.php.net/manual/en/intlcalendar.createinstance.php + * @param IntlTimeZone|DateTimeZone|string|null $timezone [optional] <p> <p> * The timezone to use. * </p> * @@ -4648,113 +4949,115 @@ function idn_to_utf8($domain, $options = 0, $variant = INTL_IDNA_VARIANT_2003, a * <li> * <p> * <b>NULL</b>, in which case the default timezone will be used, as specified in - * the ini setting {@link https://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone date.timezone} or - * through the function {@link https://www.php.net/manual/en/function.date-default-timezone-set.php date_default_timezone_set()} and as - * returned by {@link https://www.php.net/manual/en/function.date-default-timezone-get.php date_default_timezone_get()}. + * the ini setting {@link https://secure.php.net/manual/en/datetime.configuration.php#ini.date.timezone date.timezone} or + * through the function {@link https://secure.php.net/manual/en/function.date-default-timezone-set.php date_default_timezone_set()} and as + * returned by {@link https://secure.php.net/manual/en/function.date-default-timezone-get.php date_default_timezone_get()}. * </p> * </li> * <li> * <p> - * An {@link https://www.php.net/manual/en/class.intltimezone.php IntlTimeZone}, which will be used directly. + * An {@link https://secure.php.net/manual/en/class.intltimezone.php IntlTimeZone}, which will be used directly. * </p> * </li> * <li> * <p> - * A {@link https://www.php.net/manual/en/class.datetimezone.php DateTimeZone}. Its identifier will be extracted + * A {@link https://secure.php.net/manual/en/class.datetimezone.php DateTimeZone}. Its identifier will be extracted * and an ICU timezone object will be created; the timezone will be backed * by ICU's database, not PHP's. * </p> * </li> * <li> * <p> - * A {@link https://www.php.net/manual/en/language.types.string.php string}, which should be a valid ICU timezone identifier. + * A {@link https://secure.php.net/manual/en/language.types.string.php string}, which should be a valid ICU timezone identifier. * See <b>IntlTimeZone::createTimeZoneIDEnumeration()</b>. Raw * offsets such as <em>"GMT+08:30"</em> are also accepted. * </p> * </li> * </ul> * </p> - * @param string $locale [optional] <p> - * A locale to use or <b>NULL</b> to use {@link https://www.php.net/manual/en/intl.configuration.php#ini.intl.default-locale the default locale}. + * @param string|null $locale [optional] <p> + * A locale to use or <b>NULL</b> to use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.default-locale the default locale}. * </p> - * @return IntlCalendar - * The created {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} instance or <b>NULL</b> on + * @return IntlCalendar|null + * The created {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} instance or <b>NULL</b> on * failure. * @since 5.5 */ -function intlcal_create_instance($timeZone = null, $locale = null) { } +function intlcal_create_instance($timezone = null, ?string $locale = null): ?IntlCalendar {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get set of locale keyword values - * @param string $key <p> + * @param string $keyword <p> * The locale keyword for which relevant values are to be queried. Only * <em>'calendar'</em> is supported. * </p> * @param string $locale <p> * The locale onto which the keyword/value pair are to be appended. * </p> - * @param bool $commonlyUsed + * @param bool $onlyCommon * <p> * Whether to show only the values commonly used for the specified locale. * </p> - * @return Iterator|false An iterator that yields strings with the locale keyword values or <b>FALSE</b> on failure. + * @return IntlIterator|false An iterator that yields strings with the locale keyword values or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_get_keyword_values_for_locale($key, $locale, $commonlyUsed) { } +function intlcal_get_keyword_values_for_locale(string $keyword, string $locale, bool $onlyCommon): IntlIterator|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get number representing the current time - * @link https://www.php.net/manual/en/intlcalendar.getnow.php + * @link https://secure.php.net/manual/en/intlcalendar.getnow.php * @return float A float representing a number of milliseconds since the epoch, not counting leap seconds. * @since 5.5 */ -function intlcal_get_now() { } +function intlcal_get_now(): float {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get array of locales for which there is data - * @link https://www.php.net/manual/en/intlcalendar.getavailablelocales.php - * @return array An array of strings, one for which locale. + * @link https://secure.php.net/manual/en/intlcalendar.getavailablelocales.php + * @return string[] An array of strings, one for which locale. * @since 5.5 */ - -function intlcal_get_available_locales() { } +function intlcal_get_available_locales(): array {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the value for a field - * @link https://www.php.net/manual/en/intlcalendar.get.php + * @link https://secure.php.net/manual/en/intlcalendar.get.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> * @return int An integer with the value of the time field. * @since 5.5 */ -function intl_get($calendar, $field) { } +function intl_get($calendar, $field) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get time currently represented by the object * @param IntlCalendar $calendar <p>The calendar whose time will be checked against this object's time.</p> * @return float - * A {@link https://www.php.net/manual/en/language.types.float.php float} representing the number of milliseconds elapsed since the + * A {@link https://secure.php.net/manual/en/language.types.float.php float} representing the number of milliseconds elapsed since the * reference time (1 Jan 1970 00:00:00 UTC). * @since 5.5 */ -function intlcal_get_time($calendar) { } +function intlcal_get_time(IntlCalendar $calendar): float|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set the calendar time in milliseconds since the epoch - * @link https://www.php.net/manual/en/intlcalendar.settime.php - * @param float $date <p> + * @link https://secure.php.net/manual/en/intlcalendar.settime.php + * @param IntlCalendar $calendar <p> + * The IntlCalendar resource. + * </p> + * @param float $timestamp <p> * An instant represented by the number of number of milliseconds between * such instant and the epoch, ignoring leap seconds. * </p> @@ -4762,35 +5065,35 @@ function intlcal_get_time($calendar) { } * Returns <b>TRUE</b> on success and <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_set_time($date) { } +function intlcal_set_time(IntlCalendar $calendar, float $timestamp): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Add a (signed) amount of time to a field - * @link https://www.php.net/manual/en/intlcalendar.add.php + * @link https://secure.php.net/manual/en/intlcalendar.add.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. * These are integer values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @param int $amount <p>The signed amount to add to the current field. If the amount is positive, the instant will be moved forward; if it is negative, the instant wil be moved into the past. The unit is implicit to the field type. + * @param int $value <p>The signed amount to add to the current field. If the amount is positive, the instant will be moved forward; if it is negative, the instant wil be moved into the past. The unit is implicit to the field type. * For instance, hours for IntlCalendar::FIELD_HOUR_OF_DAY.</p> * @return bool Returns <b>TRUE</b> on success or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_add($calendar, $field, $amount) { } +function intlcal_add(IntlCalendar $calendar, int $field, int $value): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set the timezone used by this calendar - * @link https://www.php.net/manual/en/intlcalendar.settimezone.php + * @link https://secure.php.net/manual/en/intlcalendar.settimezone.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param mixed $timeZone <p> + * @param IntlTimeZone|DateTimeZone|string|null $timezone <p> * The new timezone to be used by this calendar. It can be specified in the * following ways: * @@ -4798,26 +5101,26 @@ function intlcal_add($calendar, $field, $amount) { } * <li> * <p> * <b>NULL</b>, in which case the default timezone will be used, as specified in - * the ini setting {@link https://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone date.timezone} or - * through the function {@link https://www.php.net/manual/en/function.date-default-timezone-set.php date_default_timezone_set()} and as - * returned by {@link https://www.php.net/manual/en/function.date-default-timezone-get.php date_default_timezone_get()}. + * the ini setting {@link https://secure.php.net/manual/en/datetime.configuration.php#ini.date.timezone date.timezone} or + * through the function {@link https://secure.php.net/manual/en/function.date-default-timezone-set.php date_default_timezone_set()} and as + * returned by {@link https://secure.php.net/manual/en/function.date-default-timezone-get.php date_default_timezone_get()}. * </p> * </li> * <li> * <p> - * An {@link https://www.php.net/manual/en/class.intltimezone.php IntlTimeZone}, which will be used directly. + * An {@link https://secure.php.net/manual/en/class.intltimezone.php IntlTimeZone}, which will be used directly. * </p> * </li> * <li> * <p> - * A {@link https://www.php.net/manual/en/class.datetimezone.php DateTimeZone}. Its identifier will be extracted + * A {@link https://secure.php.net/manual/en/class.datetimezone.php DateTimeZone}. Its identifier will be extracted * and an ICU timezone object will be created; the timezone will be backed * by ICU's database, not PHP's. * </p> * </li> * <li> * <p> - * A {@link https://www.php.net/manual/en/language.types.string.php string}, which should be a valid ICU timezone identifier. + * A {@link https://secure.php.net/manual/en/language.types.string.php string}, which should be a valid ICU timezone identifier. * See <b>IntlTimeZone::createTimeZoneIDEnumeration()</b>. Raw * offsets such as <em>"GMT+08:30"</em> are also accepted. * </p> @@ -4826,53 +5129,53 @@ function intlcal_add($calendar, $field, $amount) { } * @return bool Returns <b>TRUE</b> on success and <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_set_time_zone($calendar, $timeZone) { } +function intlcal_set_time_zone(IntlCalendar $calendar, $timezone): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether this object's time is after that of the passed object - * https://www.php.net/manual/en/intlcalendar.after.php - * @param IntlCalendar $calendarObject <p> + * https://secure.php.net/manual/en/intlcalendar.after.php + * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param IntlCalendar $calendar <p>The calendar whose time will be checked against this object's time.</p> + * @param IntlCalendar $other <p>The calendar whose time will be checked against this object's time.</p> * @return bool * Returns <b>TRUE</b> if this object's current time is after that of the * <em>calendar</em> argument's time. Returns <b>FALSE</b> otherwise. - * Also returns <b>FALSE</b> on failure. You can use {@link https://www.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or - * {@link https://www.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to detect error conditions. + * Also returns <b>FALSE</b> on failure. You can use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or + * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to detect error conditions. * @since 5.5 */ -function intlcal_after(IntlCalendar $calendarObject, IntlCalendar $calendar) { } +function intlcal_after(IntlCalendar $calendar, IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether this object's time is before that of the passed object - * @link https://www.php.net/manual/en/intlcalendar.before.php - * @param IntlCalendar $calendarObject <p> + * @link https://secure.php.net/manual/en/intlcalendar.before.php + * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param IntlCalendar $calendar <p> The calendar whose time will be checked against this object's time.</p> + * @param IntlCalendar $other <p> The calendar whose time will be checked against this object's time.</p> * @return bool + * <p> * Returns <b>TRUE</B> if this object's current time is before that of the * <em>calendar</em> argument's time. Returns <b>FALSE</b> otherwise. - * Also returns <b>FALSE</b> on failure. You can use {@link https://www.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or - * {@link https://www.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to detect error conditions. + * Also returns <b>FALSE</b> on failure. You can use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or + * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to detect error conditions. * </p> * @since 5.5 */ -function intlcal_before(IntlCalendar $calendarObject, IntlCalendar $calendar) { } - +function intlcal_before(IntlCalendar $calendar, IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set a time field or several common fields at once - * @link https://www.php.net/manual/en/intlcalendar.set.php + * @link https://secure.php.net/manual/en/intlcalendar.set.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $year <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> @@ -4895,26 +5198,26 @@ function intlcal_before(IntlCalendar $calendarObject, IntlCalendar $calendar) { * </p> * @param int $second [optional] <p> * The new value for <b>IntlCalendar::FIELD_SECOND</b>. - *</p> + * </p> * @return bool Returns <b>TRUE</b> on success and <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_set($calendar, $year, $month, $dayOfMonth = null, $hour = null, $minute = null, $second = null) { } +function intlcal_set(IntlCalendar $calendar, int $year, int $month, int $dayOfMonth, int $hour, int $minute, int $second): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Add value to field without carrying into more significant fields - * @link https://www.php.net/manual/en/intlcalendar.roll.php + * @link https://secure.php.net/manual/en/intlcalendar.roll.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $field <p>One of the - * {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time - * {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. + * {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time + * {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. * These are integer values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @param mixed $amountOrUpOrDown <p> + * @param int|bool $value <p> * The (signed) amount to add to the field, <b>TRUE</b> for rolling up (adding * <em>1</em>), or <b>FALSE</b> for rolling down (subtracting * <em>1</em>). @@ -4922,33 +5225,37 @@ function intlcal_set($calendar, $year, $month, $dayOfMonth = null, $hour = null, * @return bool Returns <b>TRUE</b> on success or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_roll($calendar, $field, $amountOrUpOrDown) { } +function intlcal_roll( + IntlCalendar $calendar, + int $field, + $value +): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Clear a field or all fields - * @link https://www.php.net/manual/en/intlcalendar.clear.php + * @link https://secure.php.net/manual/en/intlcalendar.clear.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param int $field [optional] <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * @param int|null $field [optional] <p> + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> * @return bool Returns <b>TRUE</b> on success or <b>FALSE</b> on failure. Failure can only occur is invalid arguments are provided. * @since 5.5 */ -function intlcal_clear($calendar, $field = null) { } +function intlcal_clear(IntlCalendar $calendar, ?int $field = null): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Calculate difference between given time and this object's time - * @link https://www.php.net/manual/en/intlcalendar.fielddifference.php + * @link https://secure.php.net/manual/en/intlcalendar.fielddifference.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param float $when <p> + * @param float $timestamp <p> * The time against which to compare the quantity represented by the * <em>field</em>. For the result to be positive, the time * given for this parameter must be ahead of the time of the object the @@ -4959,7 +5266,7 @@ function intlcal_clear($calendar, $field = null) { } * </p> * * <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> @@ -4967,50 +5274,49 @@ function intlcal_clear($calendar, $field = null) { } * specified field or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_field_difference($calendar, $when, $field) { } - +function intlcal_field_difference(IntlCalendar $calendar, float $timestamp, int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * The maximum value for a field, considering the object's current time - * @link https://www.php.net/manual/en/intlcalendar.getactualmaximum.php + * @link https://secure.php.net/manual/en/intlcalendar.getactualmaximum.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> * @return int - * An {@link https://www.php.net/manual/en/language.types.integer.php int} representing the maximum value in the units associated + * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing the maximum value in the units associated * with the given <em>field</em> or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_get_actual_maximum($calendar, $field) { } +function intlcal_get_actual_maximum(IntlCalendar $calendar, int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * The minimum value for a field, considering the object's current time - * @link https://www.php.net/manual/en/intlcalendar.getactualminimum.php + * @link https://secure.php.net/manual/en/intlcalendar.getactualminimum.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. * These are integer values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> * @return int - * An {@link https://www.php.net/manual/en/language.types.integer.php int} representing the minimum value in the field's + * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing the minimum value in the field's * unit or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_get_actual_minimum($calendar, $field) { } +function intlcal_get_actual_minimum(IntlCalendar $calendar, int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> - * @link https://www.php.net/manual/en/intlcalendar.getdayofweektype.php + * @link https://secure.php.net/manual/en/intlcalendar.getdayofweektype.php * Tell whether a day is a weekday, weekend or a day that has a transition between the two * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. @@ -5028,12 +5334,12 @@ function intlcal_get_actual_minimum($calendar, $field) { } * <b>IntlCalendar::DOW_TYPE_WEEKEND_CEASE</b> or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_get_day_of_week_type($calendar, $dayOfWeek) { } +function intlcal_get_day_of_week_type(IntlCalendar $calendar, int $dayOfWeek): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the first day of the week for the calendar's locale - * @link https://www.php.net/manual/en/intlcalendar.getfirstdayofweek.php + * @link https://secure.php.net/manual/en/intlcalendar.getfirstdayofweek.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> @@ -5043,88 +5349,86 @@ function intlcal_get_day_of_week_type($calendar, $dayOfWeek) { } * <b>IntlCalendar::DOW_SATURDAY</b> or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_get_first_day_of_week($calendar) { } +function intlcal_get_first_day_of_week(IntlCalendar $calendar): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the largest local minimum value for a field - * @link https://www.php.net/manual/en/intlcalendar.getgreatestminimum.php + * @link https://secure.php.net/manual/en/intlcalendar.getgreatestminimum.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and - * <b>IntlCalendar::FIELD_COUNT</b>. + * <b>IntlCalendar::FIELD_COUNT</b>.</p> * @return int - * An {@link https://www.php.net/manual/en/language.types.integer.php int} representing a field value, in the field's + * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing a field value, in the field's * unit, or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_greates_minimum($calendar, $field) { } +function intlcal_greates_minimum($calendar, $field) {} /** - * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> - * Get data from the bundle - * @link https://php.net/manual/en/resourcebundle.get.php + * (PHP >= 5.5.0, PECL intl >= 3.0.0a1)<br/> + * Gets the value for a specific field. + * @link https://www.php.net/manual/en/intlcalendar.get.php * @param IntlCalendar $calendar <p> - * The calendar object, on the procedural style interface. + * The IntlCalendar resource. * </p> - * @param string|int $index <p> - * Data index, must be string or integer. + * @param int $field <p> + * One of the IntlCalendar date/time field constants. These are integer values between 0 and IntlCalendar::FIELD_COUNT. * </p> - * @return mixed the data located at the index or <b>NULL</b> on error. Strings, integers and binary data strings - * are returned as corresponding PHP types, integer array is returned as PHP array. Complex types are - * returned as <b>ResourceBundle</b> object. + * @return int An integer with the value of the time field. */ -function intlcal_get($calendar, $index) { } +function intlcal_get(IntlCalendar $calendar, int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the smallest local maximum for a field - * @link https://www.php.net/manual/en/intlcalendar.getleastmaximum.php + * @link https://secure.php.net/manual/en/intlcalendar.getleastmaximum.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> * @return int - * An {@link https://www.php.net/manual/en/language.types.integer.ph int} representing a field value in the field's + * <p>An {@link https://secure.php.net/manual/en/language.types.integer.ph int} representing a field value in the field's * unit or <b>FALSE</b> on failure. * </p> * @since 5.5 */ -function intlcal_get_least_maximum($calendar, $field) { } +function intlcal_get_least_maximum(IntlCalendar $calendar, int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the largest local minimum value for a field - * @link https://www.php.net/manual/en/intlcalendar.getgreatestminimum.php + * @link https://secure.php.net/manual/en/intlcalendar.getgreatestminimum.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and - * <b>IntlCalendar::FIELD_COUNT</b>. + * <b>IntlCalendar::FIELD_COUNT</b>.</p> * @return int - * An {@link https://www.php.net/manual/en/language.types.integer.php int} representing a field value, in the field's + * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing a field value, in the field's * unit, or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_get_greatest_minimum($calendar, $field) { } +function intlcal_get_greatest_minimum(IntlCalendar $calendar, int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the locale associated with the object - * @link https://www.php.net/manual/en/intlcalendar.getlocale.php + * @link https://secure.php.net/manual/en/intlcalendar.getlocale.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param int $localeType <p> + * @param int $type <p> * Whether to fetch the actual locale (the locale from which the calendar * data originates, with <b>Locale::ACTUAL_LOCALE</b>) or the * valid locale, i.e., the most specific locale supported by ICU relatively @@ -5136,49 +5440,47 @@ function intlcal_get_greatest_minimum($calendar, $field) { } * A locale string or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_get_locale($calendar, $localeType) { } +function intlcal_get_locale(IntlCalendar $calendar, int $type): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the global maximum value for a field - * @link https://www.php.net/manual/en/intlcalendar.getmaximum.php + * @link https://secure.php.net/manual/en/intlcalendar.getmaximum.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @return string - * A locale string or <b>FALSE</b> on failure. + * @return int|false * @since 5.5 */ -function intcal_get_maximum($calendar, $field) { } - +function intcal_get_maximum($calendar, $field) {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> - * @link https://www.php.net/manual/en/intlcalendar.getminimaldaysinfirstweek.php + * @link https://secure.php.net/manual/en/intlcalendar.getminimaldaysinfirstweek.php * Get minimal number of days the first week in a year or month can have * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @return int - * An {@link https://www.php.net/manual/en/language.types.integer.php int} representing a number of days or <b>FALSE</b> on failure. + * An {@link https://secure.php.net/manual/en/language.types.integer.php int} representing a number of days or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_get_minimal_days_in_first_week($calendar) { } +function intlcal_get_minimal_days_in_first_week(IntlCalendar $calendar): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the global minimum value for a field - * @link https://www.php.net/manual/en/intlcalendar.getminimum.php + * @link https://secure.php.net/manual/en/intlcalendar.getminimum.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> @@ -5186,44 +5488,44 @@ function intlcal_get_minimal_days_in_first_week($calendar) { } * An int representing a value for the given field in the field's unit or FALSE on failure. * @since 5.5 */ -function intlcal_get_minimum($calendar, $field) { } +function intlcal_get_minimum(IntlCalendar $calendar, int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the object's timezone - * @link https://www.php.net/manual/en/intlcalendar.gettimezone.php + * @link https://secure.php.net/manual/en/intlcalendar.gettimezone.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @return IntlTimeZone - * An {@link https://www.php.net/manual/en/class.intltimezone.php IntlTimeZone} object corresponding to the one used + * @return IntlTimeZone|false + * An {@link https://secure.php.net/manual/en/class.intltimezone.php IntlTimeZone} object corresponding to the one used * internally in this object. * @since 5.5 */ -function intlcal_get_time_zone($calendar) { } +function intlcal_get_time_zone(IntlCalendar $calendar): IntlTimeZone|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the calendar type - * @link https://www.php.net/manual/en/intlcalendar.gettype.php + * @link https://secure.php.net/manual/en/intlcalendar.gettype.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @return string - * A {@link https://www.php.net/manual/en/language.types.string.php string} representing the calendar type, such as + * A {@link https://secure.php.net/manual/en/language.types.string.php string} representing the calendar type, such as * <em>'gregorian'</em>, <em>'islamic'</em>, etc. * @since 5.5 */ -function intlcal_get_type($calendar) { } +function intlcal_get_type(IntlCalendar $calendar): string {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get time of the day at which weekend begins or ends - * @link https://www.php.net/manual/en/intlcalendar.getweekendtransition.php + * @link https://secure.php.net/manual/en/intlcalendar.getweekendtransition.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param string $dayOfWeek <p> + * @param int $dayOfWeek <p> * One of the constants <b>IntlCalendar::DOW_SUNDAY</b>, * <b>IntlCalendar::DOW_MONDAY</b>, ..., * <b>IntlCalendar::DOW_SATURDAY</b>. @@ -5233,115 +5535,113 @@ function intlcal_get_type($calendar) { } * ends or <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_get_weekend_transition($calendar, $dayOfWeek) { } +function intlcal_get_weekend_transition(IntlCalendar $calendar, int $dayOfWeek): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether the object's time is in Daylight Savings Time - * @link https://www.php.net/manual/en/intlcalendar.indaylighttime.php + * @link https://secure.php.net/manual/en/intlcalendar.indaylighttime.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @return bool * Returns <b>TRUE</b> if the date is in Daylight Savings Time, <b>FALSE</b> otherwise. * The value <b>FALSE</b> may also be returned on failure, for instance after - * specifying invalid field values on non-lenient mode; use {@link https://www.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or query - * {@link https://www.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to disambiguate. + * specifying invalid field values on non-lenient mode; use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or query + * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to disambiguate. * @since 5.5 */ -function intlcal_in_daylight_time($calendar) { } +function intlcal_in_daylight_time(IntlCalendar $calendar): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether date/time interpretation is in lenient mode - * @link https://www.php.net/manual/en/intlcalendar.islenient.php + * @link https://secure.php.net/manual/en/intlcalendar.islenient.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @return bool - * A {@link https://www.php.net/manual/en/language.types.boolean.php bool} representing whether the calendar is set to lenient mode. + * A {@link https://secure.php.net/manual/en/language.types.boolean.php bool} representing whether the calendar is set to lenient mode. * @since 5.5 */ -function intlcal_is_lenient($calendar) { } +function intlcal_is_lenient(IntlCalendar $calendar): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether a field is set - * @link https://www.php.net/manual/en/intlcalendar.isset.php + * @link https://secure.php.net/manual/en/intlcalendar.isset.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> * @return bool Assuming there are no argument errors, returns <b>TRUE</b> iif the field is set. * @since 5.5 */ -function intlcal_is_set($calendar, $field) { } +function intlcal_is_set(IntlCalendar $calendar, int $field): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the global maximum value for a field - * @link https://www.php.net/manual/en/intlcalendar.getmaximum.php + * @link https://secure.php.net/manual/en/intlcalendar.getmaximum.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @param int $field <p> - * One of the {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://www.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer + * One of the {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} date/time {@link https://secure.php.net/manual/en/class.intlcalendar.php#intlcalendar.constants field constants}. These are integer * values between <em>0</em> and * <b>IntlCalendar::FIELD_COUNT</b>. * </p> - * @return string - * A locale string or <b>FALSE</b> on failure. + * @return int|false * @since 5.5 */ -function intlcal_get_maximum($calendar, $field) { } +function intlcal_get_maximum(IntlCalendar $calendar, int $field): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether another calendar is equal but for a different time - * @link https://www.php.net/manual/en/intlcalendar.isequivalentto.php - * @param IntlCalendar $calendarObject <p> + * @link https://secure.php.net/manual/en/intlcalendar.isequivalentto.php + * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param IntlCalendar $calendar The other calendar against which the comparison is to be made. + * @param IntlCalendar $other The other calendar against which the comparison is to be made. * @return bool * Assuming there are no argument errors, returns <b>TRUE</b> iif the calendars are equivalent except possibly for their set time. * @since 5.5 */ -function intlcal_is_equivalent_to(IntlCalendar $calendarObject, IntlCalendar $calendar) { } +function intlcal_is_equivalent_to(IntlCalendar $calendar, IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Whether a certain date/time is in the weekend - * @link https://www.php.net/manual/en/intlcalendar.isweekend.php + * @link https://secure.php.net/manual/en/intlcalendar.isweekend.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param float|null $date [optional] <p> + * @param float|null $timestamp [optional] <p> * An optional timestamp representing the number of milliseconds since the * epoch, excluding leap seconds. If <b>NULL</b>, this object's current time is * used instead. * </p> * @return bool - * <p> A {@link https://www.php.net/manual/en/language.types.boolean.php bool} indicating whether the given or this object's time occurs + * <p> A {@link https://secure.php.net/manual/en/language.types.boolean.php bool} indicating whether the given or this object's time occurs * in a weekend. * </p> * <p> * The value <b>FALSE</b> may also be returned on failure, for instance after giving - * a date out of bounds on non-lenient mode; use {@link https://www.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or query - * {@link https://www.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to disambiguate.</p> + * a date out of bounds on non-lenient mode; use {@link https://secure.php.net/manual/en/intl.configuration.php#ini.intl.use-exceptions exceptions} or query + * {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()} to disambiguate.</p> * @since 5.5 */ -function intlcal_is_weekend($calendar, $date = null) { } - +function intlcal_is_weekend(IntlCalendar $calendar, ?float $timestamp = null): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set the day on which the week is deemed to start - * @link https://www.php.net/manual/en/intlcalendar.setfirstdayofweek.php + * @link https://secure.php.net/manual/en/intlcalendar.setfirstdayofweek.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> @@ -5353,28 +5653,27 @@ function intlcal_is_weekend($calendar, $date = null) { } * @return bool Returns TRUE on success. Failure can only happen due to invalid parameters. * @since 5.5 */ -function intlcal_set_first_day_of_week($calendar, $dayOfWeek) { } +function intlcal_set_first_day_of_week(IntlCalendar $calendar, int $dayOfWeek): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set whether date/time interpretation is to be lenient - * @link https://www.php.net/manual/en/intlcalendar.setlenient.php + * @link https://secure.php.net/manual/en/intlcalendar.setlenient.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param string $isLenient <p> + * @param bool $lenient <p> * Use <b>TRUE</b> to activate the lenient mode; <b>FALSE</b> otherwise. * </p> * @return bool Returns <b>TRUE</b> on success. Failure can only happen due to invalid parameters. * @since 5.5 */ -function intlcal_set_lenient($calendar, $isLenient) { } - +function intlcal_set_lenient(IntlCalendar $calendar, bool $lenient): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get behavior for handling repeating wall time - * @link https://www.php.net/manual/en/intlcalendar.getrepeatedwalltimeoption.php + * @link https://secure.php.net/manual/en/intlcalendar.getrepeatedwalltimeoption.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> @@ -5383,31 +5682,31 @@ function intlcal_set_lenient($calendar, $isLenient) { } * <b>IntlCalendar::WALLTIME_LAST</b>. * @since 5.5 */ -function intlcal_get_repeated_wall_time_option($calendar) { } +function intlcal_get_repeated_wall_time_option(IntlCalendar $calendar): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Compare time of two IntlCalendar objects for equality - * @link https://www.php.net/manual/en/intlcalendar.equals.php - * @param IntlCalendar $calendarObject <p> + * @link https://secure.php.net/manual/en/intlcalendar.equals.php + * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param IntlCalendar $calendar + * @param IntlCalendar $other * @return bool <p> * Returns <b>TRUE</b> if the current time of both this and the passed in - * {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} object are the same, or <b>FALSE</b> + * {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} object are the same, or <b>FALSE</b> * otherwise. The value <b>FALSE</b> can also be returned on failure. This can only * happen if bad arguments are passed in. In any case, the two cases can be - * distinguished by calling {@link https://www.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()}. + * distinguished by calling {@link https://secure.php.net/manual/en/function.intl-get-error-code.php intl_get_error_code()}. * </p> * @since 5.5 */ -function intlcal_equals($calendarObject, $calendar) { } +function intlcal_equals(IntlCalendar $calendar, IntlCalendar $other): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get behavior for handling skipped wall time - * @link https://www.php.net/manual/en/intlcalendar.getskippedwalltimeoption.php + * @link https://secure.php.net/manual/en/intlcalendar.getskippedwalltimeoption.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> @@ -5417,16 +5716,16 @@ function intlcal_equals($calendarObject, $calendar) { } * <b>IntlCalendar::WALLTIME_NEXT_VALID</b>. * @since 5.5 */ -function intlcal_get_skipped_wall_time_option($calendar) { } +function intlcal_get_skipped_wall_time_option(IntlCalendar $calendar): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set behavior for handling repeating wall times at negative timezone offset transitions - * @link https://www.php.net/manual/en/intlcalendar.setrepeatedwalltimeoption.php + * @link https://secure.php.net/manual/en/intlcalendar.setrepeatedwalltimeoption.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param int $wallTimeOption <p> + * @param int $option <p> * One of the constants <b>IntlCalendar::WALLTIME_FIRST</b> or * <b>IntlCalendar::WALLTIME_LAST</b>. * </p> @@ -5434,16 +5733,16 @@ function intlcal_get_skipped_wall_time_option($calendar) { } * Returns <b>TRUE</b> on success. Failure can only happen due to invalid parameters. * @since 5.5 */ -function intlcal_set_repeated_wall_time_option($calendar, $wallTimeOption) { } +function intlcal_set_repeated_wall_time_option(IntlCalendar $calendar, int $option): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Set behavior for handling skipped wall times at positive timezone offset transitions - * @link https://www.php.net/manual/en/intlcalendar.setskippedwalltimeoption.php + * @link https://secure.php.net/manual/en/intlcalendar.setskippedwalltimeoption.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @param int $wallTimeOption <p> + * @param int $option <p> * One of the constants <b>IntlCalendar::WALLTIME_FIRST</b>, * <b>IntlCalendar::WALLTIME_LAST</b> or * <b>IntlCalendar::WALLTIME_NEXT_VALID</b>. @@ -5454,367 +5753,373 @@ function intlcal_set_repeated_wall_time_option($calendar, $wallTimeOption) { } * </p> * @since 5.5 */ -function intlcal_set_skipped_wall_time_option($calendar, $wallTimeOption) { } +function intlcal_set_skipped_wall_time_option(IntlCalendar $calendar, int $option): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a2)<br/> * Create an IntlCalendar from a DateTime object or string - * @link https://www.php.net/manual/en/intlcalendar.fromdatetime.php - * @param mixed $dateTime <p> - * A {@link https://www.php.net/manual/en/class.datetime.php DateTime} object or a {@link https://www.php.net/manual/en/language.types.string.php string} that - * can be passed to {@link https://www.php.net/manual/en/datetime.construct.php DateTime::__construct()}. - * </p> - * @return IntlCalendar - * The created {@link https://www.php.net/manual/en/class.intlcalendar.php IntlCalendar} object or <b>NULL</b> in case of - * failure. If a {@link https://www.php.net/manual/en/language.types.string.php string} is passed, any exception that occurs - * inside the {@link https://www.php.net/manual/en/class.datetime.php DateTime} constructor is propagated. + * @link https://secure.php.net/manual/en/intlcalendar.fromdatetime.php + * @param DateTime|string $datetime <p> + * A {@link https://secure.php.net/manual/en/class.datetime.php DateTime} object or a {@link https://secure.php.net/manual/en/language.types.string.php string} that + * can be passed to {@link https://secure.php.net/manual/en/datetime.construct.php DateTime::__construct()}. + * </p> + * @param null|string $locale + * @return IntlCalendar|null + * The created {@link https://secure.php.net/manual/en/class.intlcalendar.php IntlCalendar} object or <b>NULL</b> in case of + * failure. If a {@link https://secure.php.net/manual/en/language.types.string.php string} is passed, any exception that occurs + * inside the {@link https://secure.php.net/manual/en/class.datetime.php DateTime} constructor is propagated. * @since 5.5 */ -function intlcal_from_date_time($dateTime) { } - +function intlcal_from_date_time( + DateTime|string $datetime, + ?string $locale = null +): ?IntlCalendar {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a2)<br/> * Convert an IntlCalendar into a DateTime object - * @link https://www.php.net/manual/en/intlcalendar.todatetime.php + * @link https://secure.php.net/manual/en/intlcalendar.todatetime.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> * @return DateTime|false - * A {@link https://www.php.net/manual/en/class.datetime.php DateTime} object with the same timezone as this + * A {@link https://secure.php.net/manual/en/class.datetime.php DateTime} object with the same timezone as this * object (though using PHP's database instead of ICU's) and the same time, * except for the smaller precision (second precision instead of millisecond). * Returns <b>FALSE</b> on failure. * @since 5.5 */ -function intlcal_to_date_time($calendar) { } - +function intlcal_to_date_time(IntlCalendar $calendar): DateTime|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get last error code on the object - * @link https://www.php.net/manual/en/intlcalendar.geterrorcode.php + * @link https://secure.php.net/manual/en/intlcalendar.geterrorcode.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @return int An ICU error code indicating either success, failure or a warning. + * @return int|false An ICU error code indicating either success, failure or a warning. * @since 5.5 */ -function intlcal_get_error_code($calendar) { } +function intlcal_get_error_code(IntlCalendar $calendar): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get last error message on the object - * @link https://www.php.net/manual/en/intlcalendar.geterrormessage.php + * @link https://secure.php.net/manual/en/intlcalendar.geterrormessage.php * @param IntlCalendar $calendar <p> * The calendar object, on the procedural style interface. * </p> - * @return string The error message associated with last error that occurred in a function call on this object, or a string indicating the non-existance of an error. + * @return string|false The error message associated with last error that occurred in a function call on this object, or a string indicating the non-existance of an error. * @since 5.5 */ -function intlcal_get_error_message($calendar) { } - +function intlcal_get_error_message(IntlCalendar $calendar): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the number of IDs in the equivalency group that includes the given ID - * @link https://www.php.net/manual/en/intltimezone.countequivalentids.php - * @param string $zoneId - * @return int + * @link https://secure.php.net/manual/en/intltimezone.countequivalentids.php + * @param string $timezoneId + * @return int|false * @since 5.5 */ -function intltz_count_equivalent_ids($zoneId) { } +function intltz_count_equivalent_ids(string $timezoneId): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Create a new copy of the default timezone for this host - * @link https://www.php.net/manual/en/intltimezone.createdefault.php + * @link https://secure.php.net/manual/en/intltimezone.createdefault.php * @return IntlTimeZone * @since 5.5 */ -function intlz_create_default() { } +function intlz_create_default() {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> - * @link https://www.php.net/manual/en/intltimezone.createenumeration.php - * @param mixed $countryOrRawOffset [optional] - * @return IntlIterator + * @link https://secure.php.net/manual/en/intltimezone.createenumeration.php + * @param IntlTimeZone|string|int|float|null $countryOrRawOffset [optional] + * @return IntlIterator|false * @since 5.5 */ -function intltz_create_enumeration($countryOrRawOffset) { } +function intltz_create_enumeration($countryOrRawOffset): IntlIterator|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> - * @link https://www.php.net/manual/en/intltimezone.createtimezone.php - * @param string $zoneId - * @return IntlTimeZone + * @link https://secure.php.net/manual/en/intltimezone.createtimezone.php + * @param string $timezoneId + * @return IntlTimeZone|null * @since 5.5 */ -function intltz_create_time_zone($zoneId) { } +function intltz_create_time_zone(string $timezoneId): ?IntlTimeZone {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> - * @link https://www.php.net/manual/en/intltimezone.fromdatetimezone.php - * @param DateTimeZone $zoneId - * @return IntlTimeZone + * @link https://secure.php.net/manual/en/intltimezone.fromdatetimezone.php + * @param DateTimeZone $timezone + * @return IntlTimeZone|null * @since 5.5 */ -function intltz_from_date_time_zone($zoneId) { } +function intltz_from_date_time_zone(DateTimeZone $timezone): ?IntlTimeZone {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the canonical system timezone ID or the normalized custom time zone ID for the given time zone ID - * @link https://www.php.net/manual/en/intltimezone.getcanonicalid.php - * @param string $zoneId - * @param bool $isSystemID [optional] - * @return string + * @link https://secure.php.net/manual/en/intltimezone.getcanonicalid.php + * @param string $timezoneId + * @param bool &$isSystemId [optional] + * @return string|false * @since 5.5 */ -function intltz_get_canonical_id($zoneId, &$isSystemID) { } +function intltz_get_canonical_id(string $timezoneId, &$isSystemId): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get a name of this time zone suitable for presentation to the user - * @param IntlTimeZone $obj - <p> + * @param IntlTimeZone $timezone - <p> * The time zone object, on the procedural style interface. * </p> - * @param bool $isDaylight [optional] + * @param bool $dst [optional] * @param int $style [optional] - * @param string $locale [optional] - * @return string + * @param string|null $locale [optional] + * @return string|false * @since 5.5 */ -function intltz_get_display_name($obj, $isDaylight, $style, $locale) { } +function intltz_get_display_name(IntlTimeZone $timezone, bool $dst = false, int $style = 2, ?string $locale): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the amount of time to be added to local standard time to get local wall clock time - * @param IntlTimeZone $obj - <p> + * @param IntlTimeZone $timezone - <p> * The time zone object, on the procedural style interface. * </p> - * @link https://www.php.net/manual/en/intltimezone.getequivalentid.php * @return int + * @link https://secure.php.net/manual/en/intltimezone.getequivalentid.php * @since 5.5 */ -function intltz_get_dst_savings($obj) { } +function intltz_get_dst_savings(IntlTimeZone $timezone): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get an ID in the equivalency group that includes the given ID - * @link https://www.php.net/manual/en/intltimezone.getequivalentid.php - * @param string $zoneId - * @param int $index - * @return string + * @link https://secure.php.net/manual/en/intltimezone.getequivalentid.php + * @param string $timezoneId + * @param int $offset + * @return string|false * @since 5.5 */ -function intltz_get_equivalent_id($zoneId, $index) { } +function intltz_get_equivalent_id(string $timezoneId, int $offset): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get last error code on the object - * @link https://www.php.net/manual/en/intltimezone.geterrorcode.php - * @param IntlTimeZone $obj - <p> + * @link https://secure.php.net/manual/en/intltimezone.geterrorcode.php + * @param IntlTimeZone $timezone - <p> * The time zone object, on the procedural style interface. * </p> - * @return int + * @return int|false * @since 5.5 */ -function intltz_get_error_code($obj) { } +function intltz_get_error_code(IntlTimeZone $timezone): int|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get last error message on the object - * @link https://www.php.net/manual/en/intltimezone.geterrormessage.php - * @param IntlTimeZone $obj - <p> + * @link https://secure.php.net/manual/en/intltimezone.geterrormessage.php + * @param IntlTimeZone $timezone - <p> * The time zone object, on the procedural style interface. * </p> - * @return string + * @return string|false * @since 5.5 */ -function intltz_get_error_message($obj) { } +function intltz_get_error_message(IntlTimeZone $timezone): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Create GMT (UTC) timezone - * @link https://www.php.net/manual/en/intltimezone.getgmt.php + * @link https://secure.php.net/manual/en/intltimezone.getgmt.php * @return IntlTimeZone * @since 5.5 */ -function intltz_getGMT() { } +function intltz_getGMT(): IntlTimeZone {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get timezone ID - * @link https://www.php.net/manual/en/intltimezone.getid.php - * @param IntlTimeZone $obj - * @return string + * @link https://secure.php.net/manual/en/intltimezone.getid.php + * @param IntlTimeZone $timezone + * @return string|false * @since 5.5 */ -function intltz_get_id($obj) { } +function intltz_get_id(IntlTimeZone $timezone): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the time zone raw and GMT offset for the given moment in time - * @link https://www.php.net/manual/en/intltimezone.getoffset.php - * @param IntlTimeZone $obj - * @param float $date + * @link https://secure.php.net/manual/en/intltimezone.getoffset.php + * @param IntlTimeZone $timezone + * @param float $timestamp * @param bool $local - * @param int $rawOffset - * @param int $dstOffset - * @return int + * @param int &$rawOffset + * @param int &$dstOffset + * @return bool * @since 5.5 */ -function intltz_get_offset($obj, $date, $local, &$rawOffset, &$dstOffset) { } +function intltz_get_offset(IntlTimeZone $timezone, float $timestamp, bool $local, &$rawOffset, &$dstOffset): bool {} /** * Get the raw GMT offset (before taking daylight savings time into account - * @link https://www.php.net/manual/en/intltimezone.getrawoffset.php - * @param IntlTimeZone $obj + * @link https://secure.php.net/manual/en/intltimezone.getrawoffset.php + * @param IntlTimeZone $timezone * @return int */ -function intltz_get_raw_offset($obj) { } +function intltz_get_raw_offset(IntlTimeZone $timezone): int {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Get the timezone data version currently used by ICU - * @link https://www.php.net/manual/en/intltimezone.gettzdataversion.php - * @param IntlTimeZone $obj - * @return string + * @link https://secure.php.net/manual/en/intltimezone.gettzdataversion.php + * @return string|false * @since 5.5 */ -function intltz_get_tz_data_version($obj) { } +function intltz_get_tz_data_version(): string|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Check if this zone has the same rules and offset as another zone - * @link https://www.php.net/manual/en/intltimezone.hassamerules.php - * @param IntlTimeZone $obj - * @param IntlTimeZone $otherTimeZone + * @link https://secure.php.net/manual/en/intltimezone.hassamerules.php + * @param IntlTimeZone $timezone + * @param IntlTimeZone $other * @return bool * @since 5.5 */ -function intltz_has_same_rules($obj, $otherTimeZone) { } +function intltz_has_same_rules( + IntlTimeZone $timezone, + IntlTimeZone $other +): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Convert to DateTimeZone object - * @link https://www.php.net/manual/ru/intltimezone.todatetimezone.php - * @param $obj - * @return DateTimeZone + * @link https://secure.php.net/manual/en/intltimezone.todatetimezone.php + * @param IntlTimeZone $timezone + * @return DateTimeZone|false * @since 5.5 */ -function intltz_to_date_time_zone($obj) { } +function intltz_to_date_time_zone(IntlTimeZone $timezone): DateTimeZone|false {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> * Check if this time zone uses daylight savings time - * @link https://www.php.net/manual/ru/intltimezone.usedaylighttime.php - * @param $obj + * @link https://secure.php.net/manual/en/intltimezone.usedaylighttime.php + * @param IntlTimeZone $timezone * @return bool * @since 5.5 */ -function intltz_use_daylight_time($obj) { } - +function intltz_use_daylight_time(IntlTimeZone $timezone): bool {} /** * (PHP 5 >=5.5.0 PECL intl >= 3.0.0a1)<br/> - * @param mixed $timeZone - * @param string $locale - * @return IntlGregorianCalendar + * @param DateTimeZone|IntlTimeZone|string|int|null $timezoneOrYear [optional] + * @param string|null $localeOrMonth [optional] + * @param int $day [optional] + * @param int $hour [optional] + * @param int $minute [optional] + * @param int $second [optional] + * @return IntlGregorianCalendar|null * @since 5.5 */ -function intlgregcal_create_instance($timeZone = null, $locale = null) { } +function intlgregcal_create_instance($timezoneOrYear, $localeOrMonth, $day, $hour, $minute, $second): ?IntlGregorianCalendar {} /** - * @param IntlGregorianCalendar $obj - * @param double $change - * + * @param IntlGregorianCalendar $calendar + * @param float $timestamp + * @return bool */ -function intlgregcal_set_gregorian_change($obj, $change) { } +function intlgregcal_set_gregorian_change(IntlGregorianCalendar $calendar, float $timestamp): bool {} /** - * @param IntlGregorianCalendar $obj - * @return double $change + * @param IntlGregorianCalendar $calendar + * @return float */ -function intlgregcal_get_gregorian_change($obj) { } +function intlgregcal_get_gregorian_change(IntlGregorianCalendar $calendar): float {} /** + * @param IntlGregorianCalendar $calendar * @param int $year * @return bool */ -function intlgregcal_is_leap_year($year) { } - +function intlgregcal_is_leap_year(IntlGregorianCalendar $calendar, int $year): bool {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> * Create a resource bundle * @link https://php.net/manual/en/resourcebundle.create.php - * @param string $locale <p> + * @param string|null $locale <p> * Locale for which the resources should be loaded (locale name, e.g. en_CA). * </p> - * @param string $bundlename <p> + * @param string|null $bundle <p> * The directory where the data is stored or the name of the .dat file. * </p> * @param bool $fallback [optional] <p> * Whether locale should match exactly or fallback to parent locale is allowed. * </p> - * @return ResourceBundle|false <b>ResourceBundle</b> object or <b>FALSE</b> on error. + * @return ResourceBundle|null <b>ResourceBundle</b> object or <b>NULL</b> on error. */ -function resourcebundle_create($locale, $bundlename, $fallback = null) { } +function resourcebundle_create(?string $locale, ?string $bundle, bool $fallback = true): ?ResourceBundle {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> * Get data from the bundle * @link https://php.net/manual/en/resourcebundle.get.php - * @param ResourceBundle $r + * @param ResourceBundle $bundle * @param string|int $index <p> * Data index, must be string or integer. * </p> + * @param bool $fallback * @return mixed the data located at the index or <b>NULL</b> on error. Strings, integers and binary data strings * are returned as corresponding PHP types, integer array is returned as PHP array. Complex types are * returned as <b>ResourceBundle</b> object. */ -function resourcebundle_get(ResourceBundle $r, $index) { } +function resourcebundle_get(ResourceBundle $bundle, string|int $index, bool $fallback = true) {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> * Get number of elements in the bundle * @link https://php.net/manual/en/resourcebundle.count.php - * @param ResourceBundle $r - * @param $bundle + * @param ResourceBundle $bundle * @return int number of elements in the bundle. */ -function resourcebundle_count(ResourceBundle $r, $bundle) { } +function resourcebundle_count(ResourceBundle $bundle): int {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> * Get supported locales * @link https://php.net/manual/en/resourcebundle.locales.php - * @param string $bundlename <p> + * @param string $bundle <p> * Path of ResourceBundle for which to get available locales, or * empty string for default locales list. * </p> - * @return array the list of locales supported by the bundle. + * @return array|false the list of locales supported by the bundle. */ -function resourcebundle_locales($bundlename) { } +function resourcebundle_locales(string $bundle): array|false {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> * Get bundle's last error code. * @link https://php.net/manual/en/resourcebundle.geterrorcode.php - * @param $bundle + * @param ResourceBundle $bundle * @return int error code from last bundle object call. */ -function resourcebundle_get_error_code(ResourceBundle $bundle) { } +function resourcebundle_get_error_code(ResourceBundle $bundle): int {} /** * (PHP >= 5.3.2, PECL intl >= 2.0.0)<br/> * Get bundle's last error message. * @link https://php.net/manual/en/resourcebundle.geterrormessage.php - * @param $bundle + * @param ResourceBundle $bundle * @return string error message from last bundle object's call. */ -function resourcebundle_get_error_message(ResourceBundle $bundle) { } +function resourcebundle_get_error_message(ResourceBundle $bundle): string {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> @@ -5823,9 +6128,9 @@ function resourcebundle_get_error_message(ResourceBundle $bundle) { } * @param string $id <p> * The id. * </p> - * @param int $direction [optional] <p> + * @param int $direction <p> * The direction, defaults to - * >Transliterator::FORWARD. + * Transliterator::FORWARD. * May also be set to * Transliterator::REVERSE. * </p> @@ -5833,7 +6138,7 @@ function resourcebundle_get_error_message(ResourceBundle $bundle) { } * or <b>NULL</b> on failure. * @since 5.4 */ -function transliterator_create($id, $direction = null) { } +function transliterator_create(string $id, int $direction = 0): ?Transliterator {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> @@ -5842,53 +6147,53 @@ function transliterator_create($id, $direction = null) { } * @param string $rules <p> * The rules. * </p> - * @param string $direction [optional] <p> + * @param int $direction <p> * The direction, defaults to - * >Transliterator::FORWARD. + * Transliterator::FORWARD. * May also be set to * Transliterator::REVERSE. * </p> - * @return Transliterator a <b>Transliterator</b> object on success, + * @return Transliterator|null a <b>Transliterator</b> object on success, * or <b>NULL</b> on failure. * @since 5.4 */ -function transliterator_create_from_rules($rules, $direction = null) { } +function transliterator_create_from_rules(string $rules, int $direction = 0): ?Transliterator {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Get transliterator IDs * @link https://php.net/manual/en/transliterator.listids.php - * @return array An array of registered transliterator IDs on success, + * @return string[]|false An array of registered transliterator IDs on success, * or <b>FALSE</b> on failure. * @since 5.4 */ -function transliterator_list_ids() { } +function transliterator_list_ids(): array|false {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Create an inverse transliterator * @link https://php.net/manual/en/transliterator.createinverse.php - * @param Transliterator $orig_trans - * @return Transliterator a <b>Transliterator</b> object on success, + * @param Transliterator $transliterator + * @return Transliterator|null a <b>Transliterator</b> object on success, * or <b>NULL</b> on failure * @since 5.4 */ -function transliterator_create_inverse(Transliterator $orig_trans) { } +function transliterator_create_inverse(Transliterator $transliterator): ?Transliterator {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Transliterate a string * @link https://php.net/manual/en/transliterator.transliterate.php * @param Transliterator|string $transliterator - * @param string $subject <p> + * @param string $string <p> * The string to be transformed. * </p> - * @param int $start [optional] <p> + * @param int $start <p> * The start index (in UTF-16 code units) from which the string will start * to be transformed, inclusive. Indexing starts at 0. The text before will * be left as is. * </p> - * @param int $end [optional] <p> + * @param int $end <p> * The end index (in UTF-16 code units) until which the string will be * transformed, exclusive. Indexing starts at 0. The text after will be * left as is. @@ -5896,29 +6201,29 @@ function transliterator_create_inverse(Transliterator $orig_trans) { } * @return string|false The transfomed string on success, or <b>FALSE</b> on failure. * @since 5.4 */ -function transliterator_transliterate($transliterator, $subject, $start = null, $end = null) { } +function transliterator_transliterate(Transliterator|string $transliterator, string $string, int $start = 0, int $end = -1): string|false {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Get last error code * @link https://php.net/manual/en/transliterator.geterrorcode.php - * @param Transliterator $trans - * @return int The error code on success, + * @param Transliterator $transliterator + * @return int|false The error code on success, * or <b>FALSE</b> if none exists, or on failure. * @since 5.4 */ -function transliterator_get_error_code(Transliterator $trans) { } +function transliterator_get_error_code(Transliterator $transliterator): int|false {} /** * (PHP >= 5.4.0, PECL intl >= 2.0.0)<br/> * Get last error message * @link https://php.net/manual/en/transliterator.geterrormessage.php - * @param Transliterator $trans - * @return string The error code on success, + * @param Transliterator $transliterator + * @return string|false The error code on success, * or <b>FALSE</b> if none exists, or on failure. * @since 5.4 */ -function transliterator_get_error_message(Transliterator $trans) { } +function transliterator_get_error_message(Transliterator $transliterator): string|false {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -5926,7 +6231,7 @@ function transliterator_get_error_message(Transliterator $trans) { } * @link https://php.net/manual/en/function.intl-get-error-code.php * @return int Error code returned by the last API function call. */ -function intl_get_error_code() { } +function intl_get_error_code(): int {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> @@ -5934,13 +6239,13 @@ function intl_get_error_code() { } * @link https://php.net/manual/en/function.intl-get-error-message.php * @return string Description of an error occurred in the last API function call. */ -function intl_get_error_message() { } +function intl_get_error_message(): string {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Check whether the given error code indicates failure * @link https://php.net/manual/en/function.intl-is-failure.php - * @param int $error_code <p> + * @param int $errorCode <p> * is a value that returned by functions: * <b>intl_get_error_code</b>, * <b>collator_get_error_code</b> . @@ -5948,56 +6253,66 @@ function intl_get_error_message() { } * @return bool <b>TRUE</b> if it the code indicates some failure, and <b>FALSE</b> * in case of success or a warning. */ -function intl_is_failure($error_code) { } +function intl_is_failure(int $errorCode): bool {} /** * (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)<br/> * Get symbolic name for a given error code * @link https://php.net/manual/en/function.intl-error-name.php - * @param int $error_code <p> + * @param int $errorCode <p> * ICU error code. * </p> * @return string The returned string will be the same as the name of the error code * constant. */ -function intl_error_name($error_code) { } +function intl_error_name(int $errorCode): string {} /** * Gets the Decomposition_Mapping property for the given UTF-8 encoded code point * * @link https://www.php.net/manual/en/normalizer.getrawdecomposition.php * - * @param string $input + * @param string $string + * @param int $form * @return string|null * * @since 7.3 */ -function normalizer_get_raw_decomposition($input) { } +function normalizer_get_raw_decomposition(string $string, int $form = Normalizer::FORM_C): ?string {} /** + * @return IntlTimeZone * @since 5.5 */ -function intltz_create_default() { } +function intltz_create_default(): IntlTimeZone {} /** + * @return IntlTimeZone * @since 5.5 */ -function intltz_get_gmt() { } +function intltz_get_gmt(): IntlTimeZone {} /** + * @return IntlTimeZone * @since 5.5 */ -function intltz_get_unknown() { } +function intltz_get_unknown(): IntlTimeZone {} /** + * @param int $type + * @param null|string $region + * @param null|int $rawOffset + * @return IntlIterator|false * @since 5.5 */ -function intltz_create_time_zone_id_enumeration($zoneType, $region = null, $rawOffset = null) { } +function intltz_create_time_zone_id_enumeration(int $type, ?string $region = null, ?int $rawOffset = null): IntlIterator|false {} /** + * @param string $timezoneId + * @return string|false * @since 5.5 */ -function intltz_get_region($zoneId) { } +function intltz_get_region(string $timezoneId): string|false {} /** * Set minimal number of days the first week in a year or month can have @@ -6005,200 +6320,214 @@ function intltz_get_region($zoneId) { } * @link https://www.php.net/manual/en/intlcalendar.setminimaldaysinfirstweek.php * * @param IntlCalendar $calendar - * @param int $numberOfDays + * @param int $days * @return bool * * @since 5.5.1 */ -function intlcal_set_minimal_days_in_first_week(IntlCalendar $calendar, $numberOfDays) { } +function intlcal_set_minimal_days_in_first_week(IntlCalendar $calendar, int $days): bool {} + +function intltz_get_windows_id(string $timezoneId): string|false {} + +function intltz_get_id_for_windows_id(string $timezoneId, ?string $region = null): string|false {} + +/** + * @since 8.4 + */ +function grapheme_str_split(string $string, int $length = 1): array|false {} + +/** + * @since 8.4 + */ +function intltz_get_iana_id(string $timezoneId): string|false {} /** * Limit on locale length, set to 80 in PHP code. Locale names longer * than this limit will not be accepted. * @link https://php.net/manual/en/intl.constants.php */ -define ('INTL_MAX_LOCALE_LEN', 80); -define ('INTL_ICU_VERSION', "4.8.1.1"); -define ('INTL_ICU_DATA_VERSION', "4.8.1"); -define ('ULOC_ACTUAL_LOCALE', 0); -define ('ULOC_VALID_LOCALE', 1); -define ('GRAPHEME_EXTR_COUNT', 0); -define ('GRAPHEME_EXTR_MAXBYTES', 1); -define ('GRAPHEME_EXTR_MAXCHARS', 2); -define ('U_USING_FALLBACK_WARNING', -128); -define ('U_ERROR_WARNING_START', -128); -define ('U_USING_DEFAULT_WARNING', -127); -define ('U_SAFECLONE_ALLOCATED_WARNING', -126); -define ('U_STATE_OLD_WARNING', -125); -define ('U_STRING_NOT_TERMINATED_WARNING', -124); -define ('U_SORT_KEY_TOO_SHORT_WARNING', -123); -define ('U_AMBIGUOUS_ALIAS_WARNING', -122); -define ('U_DIFFERENT_UCA_VERSION', -121); -define ('U_ERROR_WARNING_LIMIT', -119); -define ('U_ZERO_ERROR', 0); -define ('U_ILLEGAL_ARGUMENT_ERROR', 1); -define ('U_MISSING_RESOURCE_ERROR', 2); -define ('U_INVALID_FORMAT_ERROR', 3); -define ('U_FILE_ACCESS_ERROR', 4); -define ('U_INTERNAL_PROGRAM_ERROR', 5); -define ('U_MESSAGE_PARSE_ERROR', 6); -define ('U_MEMORY_ALLOCATION_ERROR', 7); -define ('U_INDEX_OUTOFBOUNDS_ERROR', 8); -define ('U_PARSE_ERROR', 9); -define ('U_INVALID_CHAR_FOUND', 10); -define ('U_TRUNCATED_CHAR_FOUND', 11); -define ('U_ILLEGAL_CHAR_FOUND', 12); -define ('U_INVALID_TABLE_FORMAT', 13); -define ('U_INVALID_TABLE_FILE', 14); -define ('U_BUFFER_OVERFLOW_ERROR', 15); -define ('U_UNSUPPORTED_ERROR', 16); -define ('U_RESOURCE_TYPE_MISMATCH', 17); -define ('U_ILLEGAL_ESCAPE_SEQUENCE', 18); -define ('U_UNSUPPORTED_ESCAPE_SEQUENCE', 19); -define ('U_NO_SPACE_AVAILABLE', 20); -define ('U_CE_NOT_FOUND_ERROR', 21); -define ('U_PRIMARY_TOO_LONG_ERROR', 22); -define ('U_STATE_TOO_OLD_ERROR', 23); -define ('U_TOO_MANY_ALIASES_ERROR', 24); -define ('U_ENUM_OUT_OF_SYNC_ERROR', 25); -define ('U_INVARIANT_CONVERSION_ERROR', 26); -define ('U_INVALID_STATE_ERROR', 27); -define ('U_COLLATOR_VERSION_MISMATCH', 28); -define ('U_USELESS_COLLATOR_ERROR', 29); -define ('U_NO_WRITE_PERMISSION', 30); -define ('U_STANDARD_ERROR_LIMIT', 31); -define ('U_BAD_VARIABLE_DEFINITION', 65536); -define ('U_PARSE_ERROR_START', 65536); -define ('U_MALFORMED_RULE', 65537); -define ('U_MALFORMED_SET', 65538); -define ('U_MALFORMED_SYMBOL_REFERENCE', 65539); -define ('U_MALFORMED_UNICODE_ESCAPE', 65540); -define ('U_MALFORMED_VARIABLE_DEFINITION', 65541); -define ('U_MALFORMED_VARIABLE_REFERENCE', 65542); -define ('U_MISMATCHED_SEGMENT_DELIMITERS', 65543); -define ('U_MISPLACED_ANCHOR_START', 65544); -define ('U_MISPLACED_CURSOR_OFFSET', 65545); -define ('U_MISPLACED_QUANTIFIER', 65546); -define ('U_MISSING_OPERATOR', 65547); -define ('U_MISSING_SEGMENT_CLOSE', 65548); -define ('U_MULTIPLE_ANTE_CONTEXTS', 65549); -define ('U_MULTIPLE_CURSORS', 65550); -define ('U_MULTIPLE_POST_CONTEXTS', 65551); -define ('U_TRAILING_BACKSLASH', 65552); -define ('U_UNDEFINED_SEGMENT_REFERENCE', 65553); -define ('U_UNDEFINED_VARIABLE', 65554); -define ('U_UNQUOTED_SPECIAL', 65555); -define ('U_UNTERMINATED_QUOTE', 65556); -define ('U_RULE_MASK_ERROR', 65557); -define ('U_MISPLACED_COMPOUND_FILTER', 65558); -define ('U_MULTIPLE_COMPOUND_FILTERS', 65559); -define ('U_INVALID_RBT_SYNTAX', 65560); -define ('U_INVALID_PROPERTY_PATTERN', 65561); -define ('U_MALFORMED_PRAGMA', 65562); -define ('U_UNCLOSED_SEGMENT', 65563); -define ('U_ILLEGAL_CHAR_IN_SEGMENT', 65564); -define ('U_VARIABLE_RANGE_EXHAUSTED', 65565); -define ('U_VARIABLE_RANGE_OVERLAP', 65566); -define ('U_ILLEGAL_CHARACTER', 65567); -define ('U_INTERNAL_TRANSLITERATOR_ERROR', 65568); -define ('U_INVALID_ID', 65569); -define ('U_INVALID_FUNCTION', 65570); -define ('U_PARSE_ERROR_LIMIT', 65571); -define ('U_UNEXPECTED_TOKEN', 65792); -define ('U_FMT_PARSE_ERROR_START', 65792); -define ('U_MULTIPLE_DECIMAL_SEPARATORS', 65793); -define ('U_MULTIPLE_DECIMAL_SEPERATORS', 65793); -define ('U_MULTIPLE_EXPONENTIAL_SYMBOLS', 65794); -define ('U_MALFORMED_EXPONENTIAL_PATTERN', 65795); -define ('U_MULTIPLE_PERCENT_SYMBOLS', 65796); -define ('U_MULTIPLE_PERMILL_SYMBOLS', 65797); -define ('U_MULTIPLE_PAD_SPECIFIERS', 65798); -define ('U_PATTERN_SYNTAX_ERROR', 65799); -define ('U_ILLEGAL_PAD_POSITION', 65800); -define ('U_UNMATCHED_BRACES', 65801); -define ('U_UNSUPPORTED_PROPERTY', 65802); -define ('U_UNSUPPORTED_ATTRIBUTE', 65803); -define ('U_FMT_PARSE_ERROR_LIMIT', 65810); -define ('U_BRK_INTERNAL_ERROR', 66048); -define ('U_BRK_ERROR_START', 66048); -define ('U_BRK_HEX_DIGITS_EXPECTED', 66049); -define ('U_BRK_SEMICOLON_EXPECTED', 66050); -define ('U_BRK_RULE_SYNTAX', 66051); -define ('U_BRK_UNCLOSED_SET', 66052); -define ('U_BRK_ASSIGN_ERROR', 66053); -define ('U_BRK_VARIABLE_REDFINITION', 66054); -define ('U_BRK_MISMATCHED_PAREN', 66055); -define ('U_BRK_NEW_LINE_IN_QUOTED_STRING', 66056); -define ('U_BRK_UNDEFINED_VARIABLE', 66057); -define ('U_BRK_INIT_ERROR', 66058); -define ('U_BRK_RULE_EMPTY_SET', 66059); -define ('U_BRK_UNRECOGNIZED_OPTION', 66060); -define ('U_BRK_MALFORMED_RULE_TAG', 66061); -define ('U_BRK_ERROR_LIMIT', 66062); -define ('U_REGEX_INTERNAL_ERROR', 66304); -define ('U_REGEX_ERROR_START', 66304); -define ('U_REGEX_RULE_SYNTAX', 66305); -define ('U_REGEX_INVALID_STATE', 66306); -define ('U_REGEX_BAD_ESCAPE_SEQUENCE', 66307); -define ('U_REGEX_PROPERTY_SYNTAX', 66308); -define ('U_REGEX_UNIMPLEMENTED', 66309); -define ('U_REGEX_MISMATCHED_PAREN', 66310); -define ('U_REGEX_NUMBER_TOO_BIG', 66311); -define ('U_REGEX_BAD_INTERVAL', 66312); -define ('U_REGEX_MAX_LT_MIN', 66313); -define ('U_REGEX_INVALID_BACK_REF', 66314); -define ('U_REGEX_INVALID_FLAG', 66315); -define ('U_REGEX_LOOK_BEHIND_LIMIT', 66316); -define ('U_REGEX_SET_CONTAINS_STRING', 66317); -define ('U_REGEX_ERROR_LIMIT', 66324); -define ('U_IDNA_PROHIBITED_ERROR', 66560); -define ('U_IDNA_ERROR_START', 66560); -define ('U_IDNA_UNASSIGNED_ERROR', 66561); -define ('U_IDNA_CHECK_BIDI_ERROR', 66562); -define ('U_IDNA_STD3_ASCII_RULES_ERROR', 66563); -define ('U_IDNA_ACE_PREFIX_ERROR', 66564); -define ('U_IDNA_VERIFICATION_ERROR', 66565); -define ('U_IDNA_LABEL_TOO_LONG_ERROR', 66566); -define ('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567); -define ('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568); -define ('U_IDNA_ERROR_LIMIT', 66569); -define ('U_STRINGPREP_PROHIBITED_ERROR', 66560); -define ('U_STRINGPREP_UNASSIGNED_ERROR', 66561); -define ('U_STRINGPREP_CHECK_BIDI_ERROR', 66562); -define ('U_ERROR_LIMIT', 66818); +define('INTL_MAX_LOCALE_LEN', 156); +define('INTL_ICU_VERSION', "74.1"); +define('INTL_ICU_DATA_VERSION', "74.1"); +define('ULOC_ACTUAL_LOCALE', 0); +define('ULOC_VALID_LOCALE', 1); +define('GRAPHEME_EXTR_COUNT', 0); +define('GRAPHEME_EXTR_MAXBYTES', 1); +define('GRAPHEME_EXTR_MAXCHARS', 2); +define('U_USING_FALLBACK_WARNING', -128); +define('U_ERROR_WARNING_START', -128); +define('U_USING_DEFAULT_WARNING', -127); +define('U_SAFECLONE_ALLOCATED_WARNING', -126); +define('U_STATE_OLD_WARNING', -125); +define('U_STRING_NOT_TERMINATED_WARNING', -124); +define('U_SORT_KEY_TOO_SHORT_WARNING', -123); +define('U_AMBIGUOUS_ALIAS_WARNING', -122); +define('U_DIFFERENT_UCA_VERSION', -121); +define('U_ERROR_WARNING_LIMIT', -119); +define('U_ZERO_ERROR', 0); +define('U_ILLEGAL_ARGUMENT_ERROR', 1); +define('U_MISSING_RESOURCE_ERROR', 2); +define('U_INVALID_FORMAT_ERROR', 3); +define('U_FILE_ACCESS_ERROR', 4); +define('U_INTERNAL_PROGRAM_ERROR', 5); +define('U_MESSAGE_PARSE_ERROR', 6); +define('U_MEMORY_ALLOCATION_ERROR', 7); +define('U_INDEX_OUTOFBOUNDS_ERROR', 8); +define('U_PARSE_ERROR', 9); +define('U_INVALID_CHAR_FOUND', 10); +define('U_TRUNCATED_CHAR_FOUND', 11); +define('U_ILLEGAL_CHAR_FOUND', 12); +define('U_INVALID_TABLE_FORMAT', 13); +define('U_INVALID_TABLE_FILE', 14); +define('U_BUFFER_OVERFLOW_ERROR', 15); +define('U_UNSUPPORTED_ERROR', 16); +define('U_RESOURCE_TYPE_MISMATCH', 17); +define('U_ILLEGAL_ESCAPE_SEQUENCE', 18); +define('U_UNSUPPORTED_ESCAPE_SEQUENCE', 19); +define('U_NO_SPACE_AVAILABLE', 20); +define('U_CE_NOT_FOUND_ERROR', 21); +define('U_PRIMARY_TOO_LONG_ERROR', 22); +define('U_STATE_TOO_OLD_ERROR', 23); +define('U_TOO_MANY_ALIASES_ERROR', 24); +define('U_ENUM_OUT_OF_SYNC_ERROR', 25); +define('U_INVARIANT_CONVERSION_ERROR', 26); +define('U_INVALID_STATE_ERROR', 27); +define('U_COLLATOR_VERSION_MISMATCH', 28); +define('U_USELESS_COLLATOR_ERROR', 29); +define('U_NO_WRITE_PERMISSION', 30); +define('U_STANDARD_ERROR_LIMIT', 32); +define('U_BAD_VARIABLE_DEFINITION', 65536); +define('U_PARSE_ERROR_START', 65536); +define('U_MALFORMED_RULE', 65537); +define('U_MALFORMED_SET', 65538); +define('U_MALFORMED_SYMBOL_REFERENCE', 65539); +define('U_MALFORMED_UNICODE_ESCAPE', 65540); +define('U_MALFORMED_VARIABLE_DEFINITION', 65541); +define('U_MALFORMED_VARIABLE_REFERENCE', 65542); +define('U_MISMATCHED_SEGMENT_DELIMITERS', 65543); +define('U_MISPLACED_ANCHOR_START', 65544); +define('U_MISPLACED_CURSOR_OFFSET', 65545); +define('U_MISPLACED_QUANTIFIER', 65546); +define('U_MISSING_OPERATOR', 65547); +define('U_MISSING_SEGMENT_CLOSE', 65548); +define('U_MULTIPLE_ANTE_CONTEXTS', 65549); +define('U_MULTIPLE_CURSORS', 65550); +define('U_MULTIPLE_POST_CONTEXTS', 65551); +define('U_TRAILING_BACKSLASH', 65552); +define('U_UNDEFINED_SEGMENT_REFERENCE', 65553); +define('U_UNDEFINED_VARIABLE', 65554); +define('U_UNQUOTED_SPECIAL', 65555); +define('U_UNTERMINATED_QUOTE', 65556); +define('U_RULE_MASK_ERROR', 65557); +define('U_MISPLACED_COMPOUND_FILTER', 65558); +define('U_MULTIPLE_COMPOUND_FILTERS', 65559); +define('U_INVALID_RBT_SYNTAX', 65560); +define('U_INVALID_PROPERTY_PATTERN', 65561); +define('U_MALFORMED_PRAGMA', 65562); +define('U_UNCLOSED_SEGMENT', 65563); +define('U_ILLEGAL_CHAR_IN_SEGMENT', 65564); +define('U_VARIABLE_RANGE_EXHAUSTED', 65565); +define('U_VARIABLE_RANGE_OVERLAP', 65566); +define('U_ILLEGAL_CHARACTER', 65567); +define('U_INTERNAL_TRANSLITERATOR_ERROR', 65568); +define('U_INVALID_ID', 65569); +define('U_INVALID_FUNCTION', 65570); +define('U_PARSE_ERROR_LIMIT', 65571); +define('U_UNEXPECTED_TOKEN', 65792); +define('U_FMT_PARSE_ERROR_START', 65792); +define('U_MULTIPLE_DECIMAL_SEPARATORS', 65793); +define('U_MULTIPLE_DECIMAL_SEPERATORS', 65793); +define('U_MULTIPLE_EXPONENTIAL_SYMBOLS', 65794); +define('U_MALFORMED_EXPONENTIAL_PATTERN', 65795); +define('U_MULTIPLE_PERCENT_SYMBOLS', 65796); +define('U_MULTIPLE_PERMILL_SYMBOLS', 65797); +define('U_MULTIPLE_PAD_SPECIFIERS', 65798); +define('U_PATTERN_SYNTAX_ERROR', 65799); +define('U_ILLEGAL_PAD_POSITION', 65800); +define('U_UNMATCHED_BRACES', 65801); +define('U_UNSUPPORTED_PROPERTY', 65802); +define('U_UNSUPPORTED_ATTRIBUTE', 65803); +define('U_FMT_PARSE_ERROR_LIMIT', 65812); +define('U_BRK_INTERNAL_ERROR', 66048); +define('U_BRK_ERROR_START', 66048); +define('U_BRK_HEX_DIGITS_EXPECTED', 66049); +define('U_BRK_SEMICOLON_EXPECTED', 66050); +define('U_BRK_RULE_SYNTAX', 66051); +define('U_BRK_UNCLOSED_SET', 66052); +define('U_BRK_ASSIGN_ERROR', 66053); +define('U_BRK_VARIABLE_REDFINITION', 66054); +define('U_BRK_MISMATCHED_PAREN', 66055); +define('U_BRK_NEW_LINE_IN_QUOTED_STRING', 66056); +define('U_BRK_UNDEFINED_VARIABLE', 66057); +define('U_BRK_INIT_ERROR', 66058); +define('U_BRK_RULE_EMPTY_SET', 66059); +define('U_BRK_UNRECOGNIZED_OPTION', 66060); +define('U_BRK_MALFORMED_RULE_TAG', 66061); +define('U_BRK_ERROR_LIMIT', 66062); +define('U_REGEX_INTERNAL_ERROR', 66304); +define('U_REGEX_ERROR_START', 66304); +define('U_REGEX_RULE_SYNTAX', 66305); +define('U_REGEX_INVALID_STATE', 66306); +define('U_REGEX_BAD_ESCAPE_SEQUENCE', 66307); +define('U_REGEX_PROPERTY_SYNTAX', 66308); +define('U_REGEX_UNIMPLEMENTED', 66309); +define('U_REGEX_MISMATCHED_PAREN', 66310); +define('U_REGEX_NUMBER_TOO_BIG', 66311); +define('U_REGEX_BAD_INTERVAL', 66312); +define('U_REGEX_MAX_LT_MIN', 66313); +define('U_REGEX_INVALID_BACK_REF', 66314); +define('U_REGEX_INVALID_FLAG', 66315); +define('U_REGEX_LOOK_BEHIND_LIMIT', 66316); +define('U_REGEX_SET_CONTAINS_STRING', 66317); +define('U_REGEX_ERROR_LIMIT', 66326); +define('U_IDNA_PROHIBITED_ERROR', 66560); +define('U_IDNA_ERROR_START', 66560); +define('U_IDNA_UNASSIGNED_ERROR', 66561); +define('U_IDNA_CHECK_BIDI_ERROR', 66562); +define('U_IDNA_STD3_ASCII_RULES_ERROR', 66563); +define('U_IDNA_ACE_PREFIX_ERROR', 66564); +define('U_IDNA_VERIFICATION_ERROR', 66565); +define('U_IDNA_LABEL_TOO_LONG_ERROR', 66566); +define('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567); +define('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568); +define('U_IDNA_ERROR_LIMIT', 66569); +define('U_STRINGPREP_PROHIBITED_ERROR', 66560); +define('U_STRINGPREP_UNASSIGNED_ERROR', 66561); +define('U_STRINGPREP_CHECK_BIDI_ERROR', 66562); +define('U_ERROR_LIMIT', 66818); /** * Prohibit processing of unassigned codepoints in the input for IDN * functions and do not check if the input conforms to domain name ASCII rules. * @link https://php.net/manual/en/intl.constants.php */ -define ('IDNA_DEFAULT', 0); +define('IDNA_DEFAULT', 0); /** * Allow processing of unassigned codepoints in the input for IDN functions. * @link https://php.net/manual/en/intl.constants.php */ -define ('IDNA_ALLOW_UNASSIGNED', 1); +define('IDNA_ALLOW_UNASSIGNED', 1); /** * Check if the input for IDN functions conforms to domain name ASCII rules. * @link https://php.net/manual/en/intl.constants.php */ -define ('IDNA_USE_STD3_RULES', 2); +define('IDNA_USE_STD3_RULES', 2); /** * Check whether the input conforms to the BiDi rules. * Ignored by the IDNA2003 implementation, which always performs this check. * @link https://php.net/manual/en/intl.constants.php */ -define ('IDNA_CHECK_BIDI', 4); +define('IDNA_CHECK_BIDI', 4); /** * Check whether the input conforms to the CONTEXTJ rules. * Ignored by the IDNA2003 implementation, as this check is new in IDNA2008. * @link https://php.net/manual/en/intl.constants.php */ -define ('IDNA_CHECK_CONTEXTJ', 8); +define('IDNA_CHECK_CONTEXTJ', 8); /** * Option for nontransitional processing in @@ -6206,7 +6535,7 @@ define ('IDNA_CHECK_CONTEXTJ', 8); * by default. This option is ignored by the IDNA2003 implementation. * @link https://php.net/manual/en/intl.constants.php */ -define ('IDNA_NONTRANSITIONAL_TO_ASCII', 16); +define('IDNA_NONTRANSITIONAL_TO_ASCII', 16); /** * Option for nontransitional processing in @@ -6214,23 +6543,22 @@ define ('IDNA_NONTRANSITIONAL_TO_ASCII', 16); * by default. This option is ignored by the IDNA2003 implementation. * @link https://php.net/manual/en/intl.constants.php */ -define ('IDNA_NONTRANSITIONAL_TO_UNICODE', 32); +define('IDNA_NONTRANSITIONAL_TO_UNICODE', 32); /** * Use IDNA 2003 algorithm in {@see idn_to_utf8} and * {@see idn_to_ascii}. This is the default. * @link https://php.net/manual/en/intl.constants.php * @deprecated 7.2 Use {@see INTL_IDNA_VARIANT_UTS46} instead. - * @removed 8.0 */ -define ('INTL_IDNA_VARIANT_2003', 0); +define('INTL_IDNA_VARIANT_2003', 0); /** * Use UTS #46 algorithm in <b>idn_to_utf8</b> and * <b>idn_to_ascii</b>. * @link https://php.net/manual/en/intl.constants.php */ -define ('INTL_IDNA_VARIANT_UTS46', 1); +define('INTL_IDNA_VARIANT_UTS46', 1); /** * Errors reported in a bitset returned by the UTS #46 algorithm in @@ -6238,67 +6566,67 @@ define ('INTL_IDNA_VARIANT_UTS46', 1); * <b>idn_to_ascii</b>. * @link https://php.net/manual/en/intl.constants.php */ -define ('IDNA_ERROR_EMPTY_LABEL', 1); +define('IDNA_ERROR_EMPTY_LABEL', 1); /** - * @link https://www.php.net/manual/en/migration54.global-constants.php + * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ -define ('IDNA_ERROR_LABEL_TOO_LONG', 2); +define('IDNA_ERROR_LABEL_TOO_LONG', 2); /** - * @link https://www.php.net/manual/en/migration54.global-constants.php + * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ -define ('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4); +define('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4); /** - * @link https://www.php.net/manual/en/migration54.global-constants.php + * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ -define ('IDNA_ERROR_LEADING_HYPHEN', 8); +define('IDNA_ERROR_LEADING_HYPHEN', 8); /** - * @link https://www.php.net/manual/en/migration54.global-constants.php + * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ -define ('IDNA_ERROR_TRAILING_HYPHEN', 16); +define('IDNA_ERROR_TRAILING_HYPHEN', 16); /** - * @link https://www.php.net/manual/en/migration54.global-constants.php + * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ -define ('IDNA_ERROR_HYPHEN_3_4', 32); +define('IDNA_ERROR_HYPHEN_3_4', 32); /** - * @link https://www.php.net/manual/en/migration54.global-constants.php + * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ -define ('IDNA_ERROR_LEADING_COMBINING_MARK', 64); +define('IDNA_ERROR_LEADING_COMBINING_MARK', 64); /** - * @link https://www.php.net/manual/en/migration54.global-constants.php + * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ -define ('IDNA_ERROR_DISALLOWED', 128); +define('IDNA_ERROR_DISALLOWED', 128); /** - * @link https://www.php.net/manual/en/migration54.global-constants.php + * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ -define ('IDNA_ERROR_PUNYCODE', 256); +define('IDNA_ERROR_PUNYCODE', 256); /** - * @link https://www.php.net/manual/en/migration54.global-constants.php + * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ -define ('IDNA_ERROR_LABEL_HAS_DOT', 512); +define('IDNA_ERROR_LABEL_HAS_DOT', 512); /** - * @link https://www.php.net/manual/en/migration54.global-constants.php + * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ -define ('IDNA_ERROR_INVALID_ACE_LABEL', 1024); +define('IDNA_ERROR_INVALID_ACE_LABEL', 1024); /** - * @link https://www.php.net/manual/en/migration54.global-constants.php + * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ -define ('IDNA_ERROR_BIDI', 2048); +define('IDNA_ERROR_BIDI', 2048); /** - * @link https://www.php.net/manual/en/migration54.global-constants.php + * @link https://secure.php.net/manual/en/migration54.global-constants.php * @since 5.4 */ -define ('IDNA_ERROR_CONTEXTJ', 4096); +define('IDNA_ERROR_CONTEXTJ', 4096); /** * @since 5.5 @@ -6306,368 +6634,396 @@ define ('IDNA_ERROR_CONTEXTJ', 4096); class IntlBreakIterator implements IteratorAggregate { /* Constants */ - const DONE = -1; - const WORD_NONE = 0; - const WORD_NONE_LIMIT = 100; - const WORD_NUMBER = 100; - const WORD_NUMBER_LIMIT = 200; - const WORD_LETTER = 200; - const WORD_LETTER_LIMIT = 300; - const WORD_KANA = 300; - const WORD_KANA_LIMIT = 400; - const WORD_IDEO = 400; - const WORD_IDEO_LIMIT = 500; - const LINE_SOFT = 0; - const LINE_SOFT_LIMIT = 100; - const LINE_HARD = 100; - const LINE_HARD_LIMIT = 200; - const SENTENCE_TERM = 0; - const SENTENCE_TERM_LIMIT = 100; - const SENTENCE_SEP = 100; - const SENTENCE_SEP_LIMIT = 200; + public const DONE = -1; + public const WORD_NONE = 0; + public const WORD_NONE_LIMIT = 100; + public const WORD_NUMBER = 100; + public const WORD_NUMBER_LIMIT = 200; + public const WORD_LETTER = 200; + public const WORD_LETTER_LIMIT = 300; + public const WORD_KANA = 300; + public const WORD_KANA_LIMIT = 400; + public const WORD_IDEO = 400; + public const WORD_IDEO_LIMIT = 500; + public const LINE_SOFT = 0; + public const LINE_SOFT_LIMIT = 100; + public const LINE_HARD = 100; + public const LINE_HARD_LIMIT = 200; + public const SENTENCE_TERM = 0; + public const SENTENCE_TERM_LIMIT = 100; + public const SENTENCE_SEP = 100; + public const SENTENCE_SEP_LIMIT = 200; /* Methods */ /** * (PHP 5 >=5.5.0)<br/> * Private constructor for disallowing instantiation */ - private function __construct() { } + private function __construct() {} /** * (PHP 5 >=5.5.0)<br/> * Create break iterator for boundaries of combining character sequences - * @link https://www.php.net/manual/en/intlbreakiterator.createcharacterinstance.php + * @link https://secure.php.net/manual/en/intlbreakiterator.createcharacterinstance.php * @param string $locale - * @return IntlBreakIterator + * @return IntlBreakIterator|null */ - public static function createCharacterInstance($locale = null) { } + public static function createCharacterInstance(string|null $locale = null): ?IntlBreakIterator {} /** * (PHP 5 >=5.5.0)<br/> * Create break iterator for boundaries of code points - * @link https://www.php.net/manual/en/intlbreakiterator.createcodepointinstance.php - * @return IntlBreakIterator + * @link https://secure.php.net/manual/en/intlbreakiterator.createcodepointinstance.php + * @return IntlCodePointBreakIterator */ - public static function createCodePointInstance() { } + public static function createCodePointInstance(): IntlCodePointBreakIterator {} /** * (PHP 5 >=5.5.0)<br/> * Create break iterator for logically possible line breaks - * @link https://www.php.net/manual/en/intlbreakiterator.createlineinstance.php - * @param string $locale - * @return IntlBreakIterator + * @link https://secure.php.net/manual/en/intlbreakiterator.createlineinstance.php + * @param string $locale [optional] + * @return IntlBreakIterator|null */ - public static function createLineInstance($locale) { } + public static function createLineInstance(string|null $locale): ?IntlBreakIterator {} /** * (PHP 5 >=5.5.0)<br/> * Create break iterator for sentence breaks - * @link https://www.php.net/manual/en/intlbreakiterator.createsentenceinstance.php - * @param string $locale - * @return IntlBreakIterator + * @link https://secure.php.net/manual/en/intlbreakiterator.createsentenceinstance.php + * @param string $locale [optional] + * @return IntlBreakIterator|null */ - public static function createSentenceInstance($locale) { } + public static function createSentenceInstance(string|null $locale): ?IntlBreakIterator {} /** * (PHP 5 >=5.5.0)<br/> * Create break iterator for title-casing breaks - * @link https://www.php.net/manual/en/intlbreakiterator.createtitleinstance.php - * @param string $locale - * @return IntlBreakIterator + * @link https://secure.php.net/manual/en/intlbreakiterator.createtitleinstance.php + * @param string $locale [optional] + * @return IntlBreakIterator|null */ - public static function createTitleInstance($locale) { } + public static function createTitleInstance(string|null $locale): ?IntlBreakIterator {} /** * (PHP 5 >=5.5.0)<br/> * Create break iterator for word breaks - * @link https://www.php.net/manual/en/intlbreakiterator.createwordinstance.php - * @param string $locale - * @return IntlBreakIterator + * @link https://secure.php.net/manual/en/intlbreakiterator.createwordinstance.php + * @param string $locale [optional] + * @return IntlBreakIterator|null */ - public static function createWordInstance($locale) { } + public static function createWordInstance(string|null $locale): ?IntlBreakIterator {} /** * (PHP 5 >=5.5.0)<br/> * Get index of current position - * @link https://www.php.net/manual/en/intlbreakiterator.current.php + * @link https://secure.php.net/manual/en/intlbreakiterator.current.php * @return int */ - public function current() { } + public function current(): int {} /** * (PHP 5 >=5.5.0)<br/> * Set position to the first character in the text - * @link https://www.php.net/manual/en/intlbreakiterator.first.php + * @link https://secure.php.net/manual/en/intlbreakiterator.first.php */ - public function first() { } + public function first(): int {} /** * (PHP 5 >=5.5.0)<br/> * Advance the iterator to the first boundary following specified offset - * @link https://www.php.net/manual/en/intlbreakiterator.following.php + * @link https://secure.php.net/manual/en/intlbreakiterator.following.php * @param int $offset */ - public function following($offset) { } + public function following(int $offset): int {} /** * (PHP 5 >=5.5.0)<br/> * Get last error code on the object - * @link https://www.php.net/manual/en/intlbreakiterator.geterrorcode.php + * @link https://secure.php.net/manual/en/intlbreakiterator.geterrorcode.php * @return int */ - public function getErrorCode() { } + public function getErrorCode(): int {} /** * (PHP 5 >=5.5.0)<br/> * Get last error message on the object - * @link https://www.php.net/manual/en/intlbreakiterator.geterrormessage.php + * @link https://secure.php.net/manual/en/intlbreakiterator.geterrormessage.php * @return string */ - public function getErrorMessage() { } - + public function getErrorMessage(): string {} /** * (PHP 5 >=5.5.0)<br/> * Get the locale associated with the object - * @link https://www.php.net/manual/en/intlbreakiterator.getlocale.php - * @param string $locale_type + * @link https://secure.php.net/manual/en/intlbreakiterator.getlocale.php + * @param string $type */ - public function getLocale($locale_type) { } + public function getLocale(int $type): string|false {} /** * (PHP 5 >=5.5.0)<br/> * Create iterator for navigating fragments between boundaries - * @link https://www.php.net/manual/en/intlbreakiterator.getpartsiterator.php - * @param string $key_type [optional] + * @link https://secure.php.net/manual/en/intlbreakiterator.getpartsiterator.php + * @param int $type [optional] + * <p> + * Optional key type. Possible values are: + * </p><ul> + * <li> + * {@see IntlPartsIterator::KEY_SEQUENTIAL} + * - The default. Sequentially increasing integers used as key. + * </li> + * <li> + * {@see IntlPartsIterator::KEY_LEFT} + * - Byte offset left of current part used as key. + * </li> + * <li> + * {@see IntlPartsIterator::KEY_RIGHT} + * - Byte offset right of current part used as key. + * </li> + * </ul> */ - public function getPartsIterator($key_type = IntlPartsIterator::KEY_SEQUENTIAL) { } + public function getPartsIterator( + int $type = IntlPartsIterator::KEY_SEQUENTIAL + ): IntlPartsIterator {} /** * (PHP 5 >=5.5.0)<br/> * Get the text being scanned - * @link https://www.php.net/manual/en/intlbreakiterator.gettext.php + * @link https://secure.php.net/manual/en/intlbreakiterator.gettext.php */ - public function getText() { } + public function getText(): ?string {} /** * (PHP 5 >=5.5.0)<br/> * Tell whether an offset is a boundary's offset - * @link https://www.php.net/manual/en/intlbreakiterator.isboundary.php - * @param string $offset + * @link https://secure.php.net/manual/en/intlbreakiterator.isboundary.php + * @param int $offset */ - public function isBoundary($offset) { } + public function isBoundary(int $offset): bool {} /** * (PHP 5 >=5.5.0)<br/> * Set the iterator position to index beyond the last character - * @link https://www.php.net/manual/en/intlbreakiterator.last.php + * @link https://secure.php.net/manual/en/intlbreakiterator.last.php * @return int */ - public function last() { } + public function last(): int {} /** * (PHP 5 >=5.5.0)<br/> - * @link https://www.php.net/manual/en/intlbreakiterator.next.php - * @param string $offset [optional] + * @link https://secure.php.net/manual/en/intlbreakiterator.next.php + * @param int $offset [optional] * @return int */ - public function next($offset = null) { } + public function next(int|null $offset = null): int {} /** * (PHP 5 >=5.5.0)<br/> - * @link https://www.php.net/manual/en/intlbreakiterator.preceding.php + * @link https://secure.php.net/manual/en/intlbreakiterator.preceding.php * @param int $offset */ - public function preceding($offset) { } + public function preceding(int $offset): int {} /** * (PHP 5 >=5.5.0)<br/> * Set the iterator position to the boundary immediately before the current - * @link https://www.php.net/manual/en/intlbreakiterator.previous.php + * @link https://secure.php.net/manual/en/intlbreakiterator.previous.php * @return int */ - public function previous() { } + public function previous(): int {} /** * (PHP 5 >=5.5.0)<br/> * Set the text being scanned - * @link https://www.php.net/manual/en/intlbreakiterator.settext.php + * @link https://secure.php.net/manual/en/intlbreakiterator.settext.php * @param string $text */ - public function setText($text) { } + public function setText(string $text): bool {} - public function getIterator(){} + /** + * @since 8.0 + * @return Iterator + */ + public function getIterator(): Iterator {} } -class IntlRuleBasedBreakIterator extends IntlBreakIterator implements Traversable { - +class IntlRuleBasedBreakIterator extends IntlBreakIterator implements Traversable +{ /* Methods */ /** * (PHP 5 >=5.5.0)<br/> - * @link https://www.php.net/manual/en/intlbreakiterator.construct.php + * @link https://secure.php.net/manual/en/intlbreakiterator.construct.php * @param string $rules - * @param string $areCompiled [optional] + * @param string $compiled [optional] */ - public function __construct($rules, $areCompiled) { } + public function __construct( + string $rules, + bool $compiled = false + ) {} /** * (PHP 5 >=5.5.0)<br/> * Create break iterator for boundaries of combining character sequences - * @link https://www.php.net/manual/en/intlbreakiterator.createcharacterinstance.php + * @link https://secure.php.net/manual/en/intlbreakiterator.createcharacterinstance.php * @param string $locale * @return IntlRuleBasedBreakIterator */ - public static function createCharacterInstance($locale) { } + public static function createCharacterInstance($locale) {} - /* + /** * (PHP 5 >=5.5.0)<br/> * Create break iterator for boundaries of code points - * @link https://www.php.net/manual/en/intlbreakiterator.createcodepointinstance.php + * @link https://secure.php.net/manual/en/intlbreakiterator.createcodepointinstance.php * @return IntlRuleBasedBreakIterator */ - public static function createCodePointInstance() { } + public static function createCodePointInstance() {} /** * (PHP 5 >=5.5.0)<br/> * Create break iterator for logically possible line breaks - * @link https://www.php.net/manual/en/intlbreakiterator.createlineinstance.php - * @param string $locale + * @link https://secure.php.net/manual/en/intlbreakiterator.createlineinstance.php + * @param string $locale [optional] * @return IntlRuleBasedBreakIterator */ - public static function createLineInstance($locale) { } + public static function createLineInstance($locale) {} /** * (PHP 5 >=5.5.0)<br/> * Create break iterator for sentence breaks - * @link https://www.php.net/manual/en/intlbreakiterator.createsentenceinstance.php - * @param string $locale + * @link https://secure.php.net/manual/en/intlbreakiterator.createsentenceinstance.php + * @param string $locale [optional] * @return IntlRuleBasedBreakIterator */ - public static function createSentenceInstance($locale) { } + public static function createSentenceInstance($locale) {} /** * (PHP 5 >=5.5.0)<br/> * Create break iterator for title-casing breaks - * @link https://www.php.net/manual/en/intlbreakiterator.createtitleinstance.php - * @param string $locale + * @link https://secure.php.net/manual/en/intlbreakiterator.createtitleinstance.php + * @param string $locale [optional] * @return IntlRuleBasedBreakIterator */ - public static function createTitleInstance($locale) { } + public static function createTitleInstance($locale) {} /** * (PHP 5 >=5.5.0)<br/> * Create break iterator for word breaks - * @link https://www.php.net/manual/en/intlbreakiterator.createwordinstance.php - * @param string $locale + * @link https://secure.php.net/manual/en/intlbreakiterator.createwordinstance.php + * @param string $locale [optional] * @return IntlRuleBasedBreakIterator */ - public static function createWordInstance($locale) { } + public static function createWordInstance($locale) {} /** * (PHP 5 >=5.5.0)<br/> - * @link https://www.php.net/manual/en/intlrulebasedbreakiterator.getbinaryrules.php + * @link https://secure.php.net/manual/en/intlrulebasedbreakiterator.getbinaryrules.php * Get the binary form of compiled rules - * @return string + * @return string|false */ - public function getBinaryRules() { } + public function getBinaryRules(): string|false {} /** * (PHP 5 >=5.5.0)<br/> - * @link https://www.php.net/manual/en/intlrulebasedbreakiterator.getrules.php + * @link https://secure.php.net/manual/en/intlrulebasedbreakiterator.getrules.php * Get the rule set used to create this object - * @return string + * @return string|false */ - public function getRules() { } + public function getRules(): string|false {} /** * (PHP 5 >=5.5.0)<br/> - * @link https://www.php.net/manual/en/intlrulebasedbreakiterator.getrulesstatus.php + * @link https://secure.php.net/manual/en/intlrulebasedbreakiterator.getrulesstatus.php * Get the largest status value from the break rules that determined the current break position * @return int */ - public function getRuleStatus() { } + public function getRuleStatus(): int {} /** * (PHP 5 >=5.5.0)<br/> - * @link https://www.php.net/manual/en/intlrulebasedbreakiterator.getrulestatusvec.php + * @link https://secure.php.net/manual/en/intlrulebasedbreakiterator.getrulestatusvec.php * Get the status values from the break rules that determined the current break position - * @return array + * @return array|false */ - public function getRuleStatusVec() { } + public function getRuleStatusVec(): array|false {} } /** * @link https://www.php.net/manual/en/class.intlpartsiterator.php * @since 5.5 */ -class IntlPartsIterator extends IntlIterator implements Iterator { - - const KEY_SEQUENTIAL = 0 ; - const KEY_LEFT = 1 ; - const KEY_RIGHT = 2 ; +class IntlPartsIterator extends IntlIterator implements Iterator +{ + public const KEY_SEQUENTIAL = 0; + public const KEY_LEFT = 1; + public const KEY_RIGHT = 2; /** * @return IntlBreakIterator */ - public function getBreakIterator() { } -} - -class IntlCodePointBreakIterator extends IntlBreakIterator implements Traversable { + public function getBreakIterator(): IntlBreakIterator {} + /** + * @since 8.1 + */ + public function getRuleStatus(): int {} +} +class IntlCodePointBreakIterator extends IntlBreakIterator implements Traversable +{ /** * (PHP 5 >=5.5.0)<br/> * Get last code point passed over after advancing or receding the iterator - * @link https://www.php.net/manual/en/intlcodepointbreakiterator.getlastcodepoint.php + * @link https://secure.php.net/manual/en/intlcodepointbreakiterator.getlastcodepoint.php * @return int */ - public function getLastCodePoint() { } + public function getLastCodePoint(): int {} } -class UConverter { - +class UConverter +{ /* Constants */ - const REASON_UNASSIGNED = 0; - const REASON_ILLEGAL = 1; - const REASON_IRREGULAR = 2; - const REASON_RESET = 3; - const REASON_CLOSE = 4; - const REASON_CLONE = 5; - const UNSUPPORTED_CONVERTER = -1; - const SBCS = 0; - const DBCS = 1; - const MBCS = 2; - const LATIN_1 = 3; - const UTF8 = 4; - const UTF16_BigEndian = 5; - const UTF16_LittleEndian = 6; - const UTF32_BigEndian = 7; - const UTF32_LittleEndian = 8; - const EBCDIC_STATEFUL = 9; - const ISO_2022 = 10; - const LMBCS_1 = 11; - const LMBCS_2 = 12; - const LMBCS_3 = 13; - const LMBCS_4 = 14; - const LMBCS_5 = 15; - const LMBCS_6 = 16; - const LMBCS_8 = 17; - const LMBCS_11 = 18; - const LMBCS_16 = 19; - const LMBCS_17 = 20; - const LMBCS_18 = 21; - const LMBCS_19 = 22; - const LMBCS_LAST = 22; - const HZ = 23; - const SCSU = 24; - const ISCII = 25; - const US_ASCII = 26; - const UTF7 = 27; - const BOCU1 = 28; - const UTF16 = 29; - const UTF32 = 30; - const CESU8 = 31; - const IMAP_MAILBOX = 32; + public const REASON_UNASSIGNED = 0; + public const REASON_ILLEGAL = 1; + public const REASON_IRREGULAR = 2; + public const REASON_RESET = 3; + public const REASON_CLOSE = 4; + public const REASON_CLONE = 5; + public const UNSUPPORTED_CONVERTER = -1; + public const SBCS = 0; + public const DBCS = 1; + public const MBCS = 2; + public const LATIN_1 = 3; + public const UTF8 = 4; + public const UTF16_BigEndian = 5; + public const UTF16_LittleEndian = 6; + public const UTF32_BigEndian = 7; + public const UTF32_LittleEndian = 8; + public const EBCDIC_STATEFUL = 9; + public const ISO_2022 = 10; + public const LMBCS_1 = 11; + public const LMBCS_2 = 12; + public const LMBCS_3 = 13; + public const LMBCS_4 = 14; + public const LMBCS_5 = 15; + public const LMBCS_6 = 16; + public const LMBCS_8 = 17; + public const LMBCS_11 = 18; + public const LMBCS_16 = 19; + public const LMBCS_17 = 20; + public const LMBCS_18 = 21; + public const LMBCS_19 = 22; + public const LMBCS_LAST = 22; + public const HZ = 23; + public const SCSU = 24; + public const ISCII = 25; + public const US_ASCII = 26; + public const UTF7 = 27; + public const BOCU1 = 28; + public const UTF16 = 29; + public const UTF32 = 30; + public const CESU8 = 31; + public const IMAP_MAILBOX = 32; /* Methods */ /** @@ -6677,17 +7033,23 @@ class UConverter { * @param string $destination_encoding * @param string $source_encoding */ - public function __construct($destination_encoding = null, $source_encoding = null) { } + public function __construct( + string|null $destination_encoding = null, + string|null $source_encoding = null + ) {} /** * (PHP 5 >=5.5.0)<br/> * Convert string from one charset to anothe * @link https://php.net/manual/en/uconverter.convert.php * @param string $str - * @param bool $reverse - * @return string + * @param bool $reverse [optional] + * @return string|false */ - public function convert($str, $reverse) { } + public function convert( + string $str, + bool $reverse = false + ): string|false {} /** * (PHP 5 >=5.5.0)<br/> @@ -6696,19 +7058,26 @@ class UConverter { * @param int $reason * @param string $source * @param string $codePoint - * @param int $error - * @return mixed + * @param int &$error + * @return array|string|int|null */ - public function fromUCallback($reason, $source, $codePoint, &$error) { } + public function fromUCallback( + int $reason, + array $source, + int $codePoint, + &$error + ): array|string|int|null {} /** * (PHP 5 >=5.5.0)<br/> * Get the aliases of the given name * @link https://php.net/manual/en/uconverter.getaliases.php * @param string $name - * @return array + * @return array|false|null */ - public static function getAliases($name = null) { } + public static function getAliases( + string $name + ): array|false|null {} /** * (PHP 5 >=5.5.0)<br/> @@ -6716,23 +7085,23 @@ class UConverter { * @link https://php.net/manual/en/uconverter.getavailable.php * @return array */ - public static function getAvailable() { } + public static function getAvailable(): array {} /** * (PHP 5 >=5.5.0)<br/> * Get the destination encoding * @link https://php.net/manual/en/uconverter.getdestinationencoding.php - * @return string + * @return string|false|null */ - public function getDestinationEncoding() { } + public function getDestinationEncoding(): string|false|null {} /** * (PHP 5 >=5.5.0)<br/> * Get the destination converter type * @link https://php.net/manual/en/uconverter.getdestinationtype.php - * @return int + * @return int|false|null */ - public function getDestinationType() { } + public function getDestinationType(): int|false|null {} /** * (PHP 5 >=5.5.0)<br/> @@ -6740,47 +7109,47 @@ class UConverter { * @link https://php.net/manual/en/uconverter.geterrorcode.php * @return int */ - public function getErrorCode() { } + public function getErrorCode(): int {} /** * (PHP 5 >=5.5.0)<br/> * Get last error message on the object * @link https://php.net/manual/en/uconverter.geterrormessage.php - * @return string + * @return string|null */ - public function getErrorMessage() { } + public function getErrorMessage(): ?string {} /** * (PHP 5 >=5.5.0)<br/> * Get the source encoding * @link https://php.net/manual/en/uconverter.getsourceencoding.php - * @return string + * @return string|false|null */ - public function getSourceEncoding() { } + public function getSourceEncoding(): string|false|null {} /** * (PHP 5 >=5.5.0)<br/> * Get the source convertor type * @link https://php.net/manual/en/uconverter.getsourcetype.php - * @return int + * @return int|false|null */ - public function getSourceType() { } + public function getSourceType(): int|false|null {} /** * (PHP 5 >=5.5.0)<br/> * Get standards associated to converter names * @link https://php.net/manual/en/uconverter.getstandards.php - * @return array + * @return array|null */ - public static function getStandards() { } + public static function getStandards(): ?array {} /** * (PHP 5 >=5.5.0)<br/> * Get substitution chars * @link https://php.net/manual/en/uconverter.getsubstchars.php - * @return string + * @return string|false|null */ - public function getSubstChars() { } + public function getSubstChars(): string|false|null {} /** * (PHP 5 >=5.5.0)<br/> @@ -6789,34 +7158,36 @@ class UConverter { * @param int $reason * @return string */ - public static function reasonText($reason) { } + public static function reasonText( + int $reason + ): string {} /** * (PHP 5 >=5.5.0)<br/> * Set the destination encoding * @link https://php.net/manual/en/uconverter.setdestinationencoding.php * @param string $encoding - * @return void + * @return bool */ - public function setDestinationEncoding($encoding) { } + public function setDestinationEncoding(string $encoding): bool {} /** * (PHP 5 >=5.5.0)<br/> * Set the source encoding * @link https://php.net/manual/en/uconverter.setsourceencoding.php * @param string $encoding - * @return void + * @return bool */ - public function setSourceEncoding($encoding) { } + public function setSourceEncoding(string $encoding): bool {} /** * (PHP 5 >=5.5.0)<br/> * Set the substitution chars * @link https://php.net/manual/en/uconverter.setsubstchars.php * @param string $chars - * @return void + * @return bool */ - public function setSubstChars($chars) { } + public function setSubstChars(string $chars): bool {} /** * (PHP 5 >=5.5.0)<br/> @@ -6825,10 +7196,15 @@ class UConverter { * @param int $reason * @param string $source * @param string $codeUnits - * @param int $error - * @return mixed + * @param int &$error + * @return array|string|int|null */ - public function toUCallback($reason, $source, $codeUnits, &$error) { } + public function toUCallback( + int $reason, + string $source, + string $codeUnits, + &$error + ): array|string|int|null {} /** * (PHP 5 >=5.5.0)<br/> @@ -6837,10 +7213,14 @@ class UConverter { * @param string $str * @param string $toEncoding * @param string $fromEncoding - * @param array $options - * @return string - */ - public static function transcode($str, $toEncoding, $fromEncoding, array $options = []) { } + * @param array|null $options + * @return string|false + */ + public static function transcode( + string $str, + string $toEncoding, + string $fromEncoding, + array|null $options = null + ): string|false {} } // End of intl v.1.1.0 -?> diff --git a/build/translation-checker.php b/build/translation-checker.php index 7bc80d53cdb..98859fc7d47 100644 --- a/build/translation-checker.php +++ b/build/translation-checker.php @@ -1,22 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com> - * - * @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 */ $directories = [ @@ -25,17 +12,63 @@ $directories = [ $isDebug = in_array('--debug', $argv, true) || in_array('-d', $argv, true); +$txConfig = file_get_contents(__DIR__ . '/../.tx/config'); + +$untranslatedApps = [ + 'testing', +]; + +$txConfigAppMap = [ + 'dashboard' => 'dashboard-shipped-with-server', + 'encryption' => 'files_encryption', + 'settings' => 'settings-1', +]; + +// Next line only looks messed up, but it works. Don't touch it! +$rtlCharacters = [ + '\x{061C}', // ARABIC LETTER MARK + '\x{0623}', // ARABIC LETTER ALEF WITH HAMZA ABOVE + '\x{200E}', // LEFT-TO-RIGHT MARK + '\x{200F}', // RIGHT-TO-LEFT MARK + '\x{202A}', // LEFT-TO-RIGHT EMBEDDING + '\x{202B}', // RIGHT-TO-LEFT EMBEDDING + '\x{202C}', // POP DIRECTIONAL FORMATTING + '\x{202D}', // LEFT-TO-RIGHT OVERRIDE + '\x{202E}', // RIGHT-TO-LEFT OVERRIDE + '\x{2066}', // LEFT-TO-RIGHT ISOLATE + '\x{2067}', // RIGHT-TO-LEFT ISOLATE + '\x{2068}', // FIRST STRONG ISOLATE + '\x{2069}', // POP DIRECTIONAL ISOLATE + '\x{206C}', // INHIBIT ARABIC FORM SHAPING + '\x{206D}', // ACTIVATE ARABIC FORM SHAPING +]; + +$rtlLanguages = [ + 'ar', // Arabic + 'fa', // Persian + 'he', // Hebrew + 'ps', // Pashto, + 'ug', // 'Uyghurche / Uyghur + 'ur_PK', // Urdu +]; + +$valid = 0; +$errors = []; $apps = new \DirectoryIterator(__DIR__ . '/../apps'); foreach ($apps as $app) { - if (!file_exists($app->getPathname() . '/l10n')) { + if ($app->isDot() || in_array($app->getBasename(), $untranslatedApps, true)) { + continue; + } + + $resourceName = $txConfigAppMap[$app->getBasename()] ?? $app->getBasename(); + if (!file_exists($app->getPathname() . '/l10n') || !str_contains($txConfig, '[o:nextcloud:p:nextcloud:r:' . $resourceName . ']')) { + $errors[] = $app->getBasename() . "\n" . ' App is not correctly configured for translation sync via transifex and also not marked as untranslated' . "\n"; continue; } $directories[] = $app->getPathname() . '/l10n'; } -$errors = []; -$valid = 0; foreach ($directories as $dir) { if (!file_exists($dir)) { continue; @@ -48,6 +81,12 @@ foreach ($directories as $dir) { } $content = file_get_contents($file->getPathname()); + + $language = pathinfo($file->getFilename(), PATHINFO_FILENAME); + if (!in_array($language, $rtlLanguages, true) && preg_match_all('/^(.+[' . implode('', $rtlCharacters) . '].+)$/mu', $content, $matches)) { + $errors[] = $file->getPathname() . "\n" . ' ' . 'Contains a RTL limited characters in the translations. Offending strings:' . "\n" . implode("\n", $matches[0]) . "\n"; + } + $json = json_decode($content, true); $translations = json_encode($json['translations']); @@ -74,10 +113,10 @@ foreach ($directories as $dir) { } if (count($errors) > 0) { - echo sprintf('ERROR: There were %d errors:', count($errors)) . "\n\n"; + echo "\033[0;31m" . sprintf('ERROR: There were %d errors:', count($errors)) . "\033[0m\n\n"; echo implode("\n", $errors); exit(1); } -echo 'OK: ' . $valid . ' files parse' . "\n"; +echo "\033[0;32m" . 'OK: ' . $valid . ' files parse' . "\033[0m\n"; exit(0); diff --git a/build/triple-dot-checker.php b/build/triple-dot-checker.php index 15985a0a95c..171abfaf433 100644 --- a/build/triple-dot-checker.php +++ b/build/triple-dot-checker.php @@ -1,25 +1,9 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com> - * @copyright Copyright (c) 2020 Gary Kim <gary@garykim.dev> - * - * @author Gary Kim <gary@garykim.dev> - * - * @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 */ $directories = [ diff --git a/build/update-apps.sh b/build/update-apps.sh index e4611a79aff..c4de9410237 100755 --- a/build/update-apps.sh +++ b/build/update-apps.sh @@ -1,4 +1,8 @@ #!/bin/bash +# +# SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +# # Update Nextcloud apps from latest git master # For local development environment # Use from Nextcloud server folder with `./build/update-apps.sh` @@ -6,9 +10,23 @@ # It automatically: # - goes through all apps which are not shipped via server # - shows the app name in bold and uses whitespace for separation -# - changes to master and pulls quietly +# - changes to master/main and pulls quietly # - shows the 3 most recent commits for context -# - removes branches merged into master +# - removes branches merged into master/main # - … could even do the build steps if they are consistent for the apps (like `make`) -find apps* -maxdepth 2 -name .git -exec sh -c 'cd {}/../ && printf "\n\033[1m${PWD##*/}\033[0m\n" && git checkout master && git pull --quiet -p && git --no-pager log -3 --pretty=format:"%h %Cblue%ar%x09%an %Creset%s" && printf "\n" && git branch --merged master | grep -v "master$" | xargs git branch -d && cd ..' \; +set -euo pipefail + +for path in apps*/*/.git; do + ( + path="$(dirname "$path")" + cd "$path" + printf "\n\033[1m${PWD##*/}\033[0m\n" + branch="$(git remote show origin | sed -n '/HEAD branch/s/.*: //p')" + git checkout "$branch" + git pull --quiet -p + git --no-pager log -3 --pretty=format:"%h %Cblue%ar%x09%an %Creset%s" + printf "\n" + git branch --merged "$branch" | grep -v "$branch$" | xargs git branch -d || true + ) +done diff --git a/build/update.sh b/build/update.sh index 3a3d2eac5dc..4f20535d917 100755 --- a/build/update.sh +++ b/build/update.sh @@ -1,4 +1,8 @@ #!/bin/bash +# +# SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +# # Update Nextcloud server and apps from latest git master # For local development environment # Use from Nextcloud server folder with `./build/update.sh` |