diff options
Diffstat (limited to 'lib/private/AppFramework/Utility')
4 files changed, 78 insertions, 124 deletions
diff --git a/lib/private/AppFramework/Utility/ControllerMethodReflector.php b/lib/private/AppFramework/Utility/ControllerMethodReflector.php index 5a1ed0fd6ee..679e1788004 100644 --- a/lib/private/AppFramework/Utility/ControllerMethodReflector.php +++ b/lib/private/AppFramework/Utility/ControllerMethodReflector.php @@ -1,35 +1,10 @@ <?php declare(strict_types=1); - /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Bernhard Posselt <dev@bernhard-posselt.com> - * @author Bjoern Schiessle <bjoern@schiessle.org> - * @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 Morris Jobke <hey@morrisjobke.de> - * @author Olivier Paroz <github@oparoz.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @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 */ namespace OC\AppFramework\Utility; @@ -58,7 +33,7 @@ class ControllerMethodReflector implements IControllerMethodReflector { foreach ($matches['annotation'] as $key => $annotation) { $annotation = strtolower($annotation); $annotationValue = $matches['parameter'][$key]; - if (isset($annotationValue[0]) && $annotationValue[0] === '(' && $annotationValue[\strlen($annotationValue) - 1] === ')') { + if (str_starts_with($annotationValue, '(') && str_ends_with($annotationValue, ')')) { $cutString = substr($annotationValue, 1, -1); $cutString = str_replace(' ', '', $cutString); $splitArray = explode(',', $cutString); @@ -75,7 +50,7 @@ class ControllerMethodReflector implements IControllerMethodReflector { // extract type parameter information preg_match_all('/@param\h+(?P<type>\w+)\h+\$(?P<var>\w+)/', $docs, $matches); $this->types = array_combine($matches['var'], $matches['type']); - preg_match_all('/@psalm-param\h+(?P<type>\w+)<(?P<rangeMin>(-?\d+|min)),\h*(?P<rangeMax>(-?\d+|max))>\h+\$(?P<var>\w+)/', $docs, $matches); + preg_match_all('/@psalm-param\h+(\?)?(?P<type>\w+)<(?P<rangeMin>(-?\d+|min)),\h*(?P<rangeMax>(-?\d+|max))>(\|null)?\h+\$(?P<var>\w+)/', $docs, $matches); foreach ($matches['var'] as $index => $varName) { if ($matches['type'][$index] !== 'int') { // only int ranges are possible at the moment @@ -107,9 +82,9 @@ class ControllerMethodReflector implements IControllerMethodReflector { /** * Inspects the PHPDoc parameters for types * @param string $parameter the parameter whose type comments should be - * parsed + * parsed * @return string|null type in the type parameters (@param int $something) - * would return int or null if not existing + * would return int or null if not existing */ public function getType(string $parameter) { if (array_key_exists($parameter, $this->types)) { diff --git a/lib/private/AppFramework/Utility/QueryNotFoundException.php b/lib/private/AppFramework/Utility/QueryNotFoundException.php index 04faaa51a4b..4d2df14ebc8 100644 --- a/lib/private/AppFramework/Utility/QueryNotFoundException.php +++ b/lib/private/AppFramework/Utility/QueryNotFoundException.php @@ -3,25 +3,8 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2023, Ferdinand Thiessen <rpm@fthiessen.de> - * - * @author Ferdinand Thiessen <rpm@fthiessen.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: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OC\AppFramework\Utility; diff --git a/lib/private/AppFramework/Utility/SimpleContainer.php b/lib/private/AppFramework/Utility/SimpleContainer.php index 83aed4381b3..0db3bfc1c77 100644 --- a/lib/private/AppFramework/Utility/SimpleContainer.php +++ b/lib/private/AppFramework/Utility/SimpleContainer.php @@ -1,31 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Bernhard Posselt <dev@bernhard-posselt.com> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Robin McCorkell <robin@mccorkell.me.uk> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @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 */ namespace OC\AppFramework\Utility; @@ -34,7 +12,9 @@ use Closure; use OCP\AppFramework\QueryException; use OCP\IContainer; use Pimple\Container; +use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; use ReflectionClass; use ReflectionException; use ReflectionNamedType; @@ -45,8 +25,9 @@ use function class_exists; * SimpleContainer is a simple implementation of a container on basis of Pimple */ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { - /** @var Container */ - private $container; + public static bool $useLazyObjects = false; + + private Container $container; public function __construct() { $this->container = new Container(); @@ -60,7 +41,7 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { * @psalm-param S $id * @psalm-return (S is class-string<T> ? T : mixed) */ - public function get(string $id) { + public function get(string $id): mixed { return $this->query($id); } @@ -71,16 +52,29 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { /** * @param ReflectionClass $class the class to instantiate - * @return \stdClass the created class + * @return object the created class * @suppress PhanUndeclaredClassInstanceof */ - private function buildClass(ReflectionClass $class) { + private function buildClass(ReflectionClass $class): object { $constructor = $class->getConstructor(); if ($constructor === null) { + /* No constructor, return a instance directly */ return $class->newInstance(); } + if (PHP_VERSION_ID >= 80400 && self::$useLazyObjects) { + /* For PHP>=8.4, use a lazy ghost to delay constructor and dependency resolving */ + /** @psalm-suppress UndefinedMethod */ + return $class->newLazyGhost(function (object $object) use ($constructor): void { + /** @psalm-suppress DirectConstructorCall For lazy ghosts we have to call the constructor directly */ + $object->__construct(...$this->buildClassConstructorParameters($constructor)); + }); + } else { + return $class->newInstanceArgs($this->buildClassConstructorParameters($constructor)); + } + } - return $class->newInstanceArgs(array_map(function (ReflectionParameter $parameter) { + private function buildClassConstructorParameters(\ReflectionMethod $constructor): array { + return array_map(function (ReflectionParameter $parameter) { $parameterType = $parameter->getType(); $resolveName = $parameter->getName(); @@ -91,10 +85,10 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { } try { - $builtIn = $parameter->hasType() && ($parameter->getType() instanceof ReflectionNamedType) - && $parameter->getType()->isBuiltin(); + $builtIn = $parameterType !== null && ($parameterType instanceof ReflectionNamedType) + && $parameterType->isBuiltin(); return $this->query($resolveName, !$builtIn); - } catch (QueryException $e) { + } catch (ContainerExceptionInterface $e) { // Service not found, use the default value when available if ($parameter->isDefaultValueAvailable()) { return $parameter->getDefaultValue(); @@ -104,20 +98,20 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { $resolveName = $parameter->getName(); try { return $this->query($resolveName); - } catch (QueryException $e2) { + } catch (ContainerExceptionInterface $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 new QueryException($e->getMessage(), (int)$e->getCode(), $e); } } throw $e; } - }, $constructor->getParameters())); + }, $constructor->getParameters()); } public function resolve($name) { @@ -127,8 +121,8 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { if ($class->isInstantiable()) { return $this->buildClass($class); } else { - throw new QueryException($baseMsg . - ' Class can not be instantiated'); + throw new QueryException($baseMsg + . ' Class can not be instantiated'); } } catch (ReflectionException $e) { // Class does not exist @@ -175,13 +169,13 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { return $closure($this); }; $name = $this->sanitizeName($name); - if (isset($this[$name])) { - unset($this[$name]); + if (isset($this->container[$name])) { + unset($this->container[$name]); } if ($shared) { - $this[$name] = $wrapped; + $this->container[$name] = $wrapped; } else { - $this[$name] = $this->container->factory($wrapped); + $this->container[$name] = $this->container->factory($wrapped); } } @@ -192,13 +186,28 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { * @param string $alias the alias that should be registered * @param string $target the target that should be resolved instead */ - public function registerAlias($alias, $target) { - $this->registerService($alias, function (ContainerInterface $container) use ($target) { + public function registerAlias($alias, $target): void { + $this->registerService($alias, function (ContainerInterface $container) use ($target): mixed { return $container->get($target); }, false); } - /* + protected function registerDeprecatedAlias(string $alias, string $target): void { + $this->registerService($alias, function (ContainerInterface $container) use ($target, $alias): mixed { + try { + $logger = $container->get(LoggerInterface::class); + $logger->debug('The requested alias "' . $alias . '" is deprecated. Please request "' . $target . '" directly. This alias will be removed in a future Nextcloud version.', [ + 'app' => $this->appName ?? 'serverDI', + ]); + } catch (ContainerExceptionInterface $e) { + // Could not get logger. Continue + } + + return $container->get($target); + }, false); + } + + /** * @param string $name * @return string */ @@ -228,8 +237,8 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { /** * @deprecated 20.0.0 use \OCP\IContainer::registerService */ - public function offsetSet($id, $service): void { - $this->container->offsetSet($id, $service); + public function offsetSet($offset, $value): void { + $this->container->offsetSet($offset, $value); } /** diff --git a/lib/private/AppFramework/Utility/TimeFactory.php b/lib/private/AppFramework/Utility/TimeFactory.php index 2763751132c..0584fd05ef9 100644 --- a/lib/private/AppFramework/Utility/TimeFactory.php +++ b/lib/private/AppFramework/Utility/TimeFactory.php @@ -1,30 +1,10 @@ <?php declare(strict_types=1); - /** - * @copyright Copyright (c) 2022, Joas Schilling <coding@schilljs.com> - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Bernhard Posselt <dev@bernhard-posselt.com> - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @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: 2022 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace OC\AppFramework\Utility; @@ -60,7 +40,7 @@ class TimeFactory implements ITimeFactory { * @since 15.0.0 * @deprecated 26.0.0 {@see ITimeFactory::now()} */ - public function getDateTime(string $time = 'now', \DateTimeZone $timezone = null): \DateTime { + public function getDateTime(string $time = 'now', ?\DateTimeZone $timezone = null): \DateTime { return new \DateTime($time, $timezone); } @@ -73,4 +53,11 @@ class TimeFactory implements ITimeFactory { return $clone; } + + public function getTimeZone(?string $timezone = null): \DateTimeZone { + if ($timezone !== null) { + return new \DateTimeZone($timezone); + } + return $this->timezone; + } } |