From d4ab55b06172ec10dcd2c8c008675f753a8b631b Mon Sep 17 00:00:00 2001 From: Guy Sartorelli Date: Wed, 10 Jan 2024 17:24:07 +1300 Subject: [PATCH] ENH Add generic types There are also a few general corrections to PHPDocs that I noticed along the way (e.g. adding `|null` when the method is returning a null value. There are some cases where either the return type or the whole PHPDoc was duplicated from the parent class - in those cases I've simply removed the duplication. --- src/Control/Director.php | 2 - src/Control/HTTPResponse.php | 1 - src/Control/Middleware/FlushMiddleware.php | 1 - .../URLSpecialsMiddleware/FlushScheduler.php | 1 - src/Core/Extension.php | 8 +- src/Core/Injector/Injector.php | 26 ++-- src/Core/Manifest/ModuleManifest.php | 2 - src/Core/Manifest/ModuleResource.php | 1 - src/Core/Manifest/ModuleResourceLoader.php | 1 - src/Dev/FixtureFactory.php | 7 +- src/Dev/FunctionalTest.php | 2 - src/Dev/SapphireTest.php | 8 +- src/Dev/State/FixtureTestState.php | 1 - src/Dev/State/LoggerState.php | 1 - src/Dev/State/SapphireTestState.php | 2 - src/Dev/TestSession.php | 1 - src/Dev/Validation/DatabaseAdminExtension.php | 1 + src/Forms/CheckboxSetField.php | 2 +- src/Forms/CompositeField.php | 6 - src/Forms/CompositeValidator.php | 15 +-- src/Forms/ConfirmedPasswordField.php | 5 - src/Forms/FieldList.php | 5 +- src/Forms/FileField.php | 1 - src/Forms/Form.php | 2 - src/Forms/FormField.php | 11 +- src/Forms/GridField/GridField.php | 2 +- src/Forms/GridField/GridFieldConfig.php | 14 ++- .../GridFieldDetailForm_ItemRequest.php | 5 +- src/Forms/GridField/GridFieldExportButton.php | 5 +- src/Forms/GridField/GridFieldFilterHeader.php | 1 - src/Forms/GridField/GridFieldPageCount.php | 1 - src/Forms/GridField/GridFieldPrintButton.php | 2 - .../GridField/GridFieldSortableHeader.php | 5 +- src/Forms/HTMLEditor/TinyMCEConfig.php | 1 - src/Forms/ListboxField.php | 2 +- src/Forms/Schema/FormSchema.php | 6 +- src/Forms/SearchableDropdownTrait.php | 11 +- src/Forms/SelectField.php | 11 +- src/Forms/SingleSelectField.php | 1 - src/Forms/TimeField.php | 1 - src/Forms/TreeDropdownField.php | 6 - src/Forms/TreeMultiselectField.php | 1 - src/ORM/ArrayList.php | 51 +++----- src/ORM/Connect/DBSchemaManager.php | 3 - src/ORM/Connect/MySQLDatabase.php | 1 - src/ORM/DB.php | 2 - src/ORM/DataExtension.php | 3 +- src/ORM/DataList.php | 117 ++++++++---------- src/ORM/DataObject.php | 44 +++---- src/ORM/DataObjectSchema.php | 6 +- src/ORM/DataQuery.php | 1 - src/ORM/EagerLoadedList.php | 30 ++++- src/ORM/Filterable.php | 17 ++- src/ORM/GroupedList.php | 6 +- src/ORM/HasManyList.php | 7 +- src/ORM/Hierarchy/Hierarchy.php | 23 ++-- src/ORM/Hierarchy/MarkedSet.php | 6 +- src/ORM/Limitable.php | 4 + src/ORM/ListDecorator.php | 56 +++++++-- src/ORM/ManyManyList.php | 18 ++- src/ORM/ManyManyThroughList.php | 18 +-- src/ORM/ManyManyThroughQueryManipulator.php | 16 ++- src/ORM/PaginatedList.php | 7 +- src/ORM/PolymorphicHasManyList.php | 23 ++-- src/ORM/Relation.php | 10 +- src/ORM/RelationList.php | 10 +- src/ORM/SS_List.php | 14 ++- src/ORM/Search/FulltextSearchable.php | 3 +- src/ORM/Search/SearchContext.php | 20 +-- src/ORM/Sortable.php | 9 +- src/ORM/UnsavedRelationList.php | 26 ++-- src/Security/BasicAuth.php | 1 - src/Security/DefaultAdminService.php | 1 - src/Security/Group.php | 8 +- src/Security/InheritedPermissionFlusher.php | 3 + src/Security/InheritedPermissions.php | 1 - .../InheritedPermissionsExtension.php | 2 + src/Security/LoginAttempt.php | 2 +- src/Security/LoginForm.php | 1 - src/Security/Member.php | 7 +- .../ChangePasswordHandler.php | 3 - .../CookieAuthenticationHandler.php | 2 - .../MemberAuthenticator/LoginHandler.php | 2 - .../LostPasswordHandler.php | 2 - .../MemberAuthenticator.php | 1 - .../SessionAuthenticationHandler.php | 2 - src/Security/Member_GroupSet.php | 2 + src/Security/PasswordValidator.php | 1 - src/Security/PermissionCheckboxSetField.php | 1 - src/Security/RememberLoginHash.php | 1 - src/Security/RequestAuthenticationHandler.php | 1 - src/Security/Security.php | 3 - src/View/GenericTemplateGlobalProvider.php | 5 +- src/View/Parsers/ShortcodeParser.php | 4 +- .../Shortcodes/EmbedShortcodeProvider.php | 2 +- src/View/ViewableData.php | 4 + src/includes/functions.php | 5 +- .../SSListContainsOnlyMatchingItemsTest.php | 2 +- tests/php/Dev/SSListContainsOnlyTest.php | 2 +- tests/php/Dev/SSListContainsTest.php | 2 +- 100 files changed, 389 insertions(+), 423 deletions(-) diff --git a/src/Control/Director.php b/src/Control/Director.php index c49fa86b370..f91fc93b478 100644 --- a/src/Control/Director.php +++ b/src/Control/Director.php @@ -164,7 +164,6 @@ public static function mockRequest( // Build list of cleanup promises $finally = []; - /** @var Kernel $kernel */ $kernel = Injector::inst()->get(Kernel::class); $kernel->nest(); $finally[] = function () use ($kernel) { @@ -1016,7 +1015,6 @@ public static function is_cli() */ public static function get_environment_type() { - /** @var Kernel $kernel */ $kernel = Injector::inst()->get(Kernel::class); return $kernel->getEnvironment(); } diff --git a/src/Control/HTTPResponse.php b/src/Control/HTTPResponse.php index d209257ec3c..b7e47cbbe67 100644 --- a/src/Control/HTTPResponse.php +++ b/src/Control/HTTPResponse.php @@ -411,7 +411,6 @@ protected function outputBody() // a more specific error description. $body = $this->getBody(); if ($this->isError() && empty($body)) { - /** @var HandlerInterface $handler */ $handler = Injector::inst()->get(HandlerInterface::class); $formatter = $handler->getFormatter(); echo $formatter->format([ diff --git a/src/Control/Middleware/FlushMiddleware.php b/src/Control/Middleware/FlushMiddleware.php index 98b49423b12..374063eec36 100644 --- a/src/Control/Middleware/FlushMiddleware.php +++ b/src/Control/Middleware/FlushMiddleware.php @@ -16,7 +16,6 @@ class FlushMiddleware implements HTTPMiddleware { public function process(HTTPRequest $request, callable $delegate) { - /** @var BaseKernel $kernel */ $kernel = Injector::inst()->get(Kernel::class); if ((method_exists($kernel, 'isFlushed') && $kernel->isFlushed())) { // Disable cache when flushing diff --git a/src/Control/Middleware/URLSpecialsMiddleware/FlushScheduler.php b/src/Control/Middleware/URLSpecialsMiddleware/FlushScheduler.php index f2b62d0c267..809936b0d38 100644 --- a/src/Control/Middleware/URLSpecialsMiddleware/FlushScheduler.php +++ b/src/Control/Middleware/URLSpecialsMiddleware/FlushScheduler.php @@ -30,7 +30,6 @@ public function scheduleFlush(HTTPRequest $request) { $flush = array_key_exists('flush', $request->getVars() ?? []) || ($request->getURL() === 'dev/build'); - /** @var BaseKernel $kernel */ $kernel = Injector::inst()->get(Kernel::class); if (!$flush || (method_exists($kernel, 'isFlushed') && $kernel->isFlushed())) { return false; diff --git a/src/Core/Extension.php b/src/Core/Extension.php index 6cf12c79d11..f693e21e0a4 100644 --- a/src/Core/Extension.php +++ b/src/Core/Extension.php @@ -13,6 +13,8 @@ * Every object instance gets its own set of extension instances, * meaning you can set parameters specific to the "owner instance" * in new Extension instances. + * + * @template T of object */ abstract class Extension { @@ -25,14 +27,14 @@ abstract class Extension /** * The object this extension is applied to. * - * @var Object + * @var T */ protected $owner; /** * Stack of all parent owners, not including current owner * - * @var array + * @var array */ private $ownerStack = []; @@ -95,7 +97,7 @@ public function clearOwner() /** * Returns the owner of this extension. * - * @return Object + * @return T */ public function getOwner() { diff --git a/src/Core/Injector/Injector.php b/src/Core/Injector/Injector.php index 75cbf79988c..7af9df4c240 100644 --- a/src/Core/Injector/Injector.php +++ b/src/Core/Injector/Injector.php @@ -966,12 +966,13 @@ public function unregisterObjects($types) * * @throws NotFoundExceptionInterface No entry was found for **this** identifier. * - * @param string $name The name of the service to retrieve. If not a registered + * @template T of object + * @param class-string|string $name The name of the service to retrieve. If not a registered * service, then a class of the given name is instantiated * @param bool $asSingleton If set to false a new instance will be returned. * If true a singleton will be returned unless the spec is type=prototype' * @param array $constructorArgs Args to pass in to the constructor. Note: Ignored for singletons - * @return mixed Instance of the specified object + * @return T|mixed Instance of the specified object */ public function get($name, $asSingleton = true, $constructorArgs = []) { @@ -987,12 +988,13 @@ public function get($name, $asSingleton = true, $constructorArgs = []) /** * Returns the service, or `null` if it doesnt' exist. See {@link get()} for main usage. * - * @param string $name The name of the service to retrieve. If not a registered + * @template T of object + * @param class-string|string $name The name of the service to retrieve. If not a registered * service, then a class of the given name is instantiated * @param bool $asSingleton If set to false a new instance will be returned. * If true a singleton will be returned unless the spec is type=prototype' * @param array $constructorArgs Args to pass in to the constructor. Note: Ignored for singletons - * @return mixed Instance of the specified object + * @return T|mixed Instance of the specified object */ protected function getNamedService($name, $asSingleton = true, $constructorArgs = []) { @@ -1111,9 +1113,9 @@ public function getServiceSpec($name, $inherit = true) /** * Magic method to return an item directly * - * @param string $name - * The named object to retrieve - * @return mixed + * @template T of object + * @param class-string|string $name The named object to retrieve + * @return T|mixed */ public function __get($name) { @@ -1125,9 +1127,10 @@ public function __get($name) * * Additional parameters are passed through as * - * @param string $name + * @template T of object + * @param class-string|string $name * @param mixed ...$argument arguments to pass to the constructor - * @return mixed A new instance of the specified object + * @return T|mixed A new instance of the specified object */ public function create($name, $argument = null) { @@ -1139,9 +1142,10 @@ public function create($name, $argument = null) /** * Creates an object with the supplied argument array * - * @param string $name Name of the class to create an object of + * @template T of object + * @param class-string|string $name Name of the class to create an object of * @param array $constructorArgs Arguments to pass to the constructor - * @return mixed + * @return T|mixed */ public function createWithArgs($name, $constructorArgs) { diff --git a/src/Core/Manifest/ModuleManifest.php b/src/Core/Manifest/ModuleManifest.php index 0c5d117f5b9..1ec7eaedfe0 100644 --- a/src/Core/Manifest/ModuleManifest.php +++ b/src/Core/Manifest/ModuleManifest.php @@ -148,7 +148,6 @@ public function activateConfig() { $modules = $this->getModules(); // Work in reverse priority, so the higher priority modules get later execution - /** @var Module $module */ foreach (array_reverse($modules ?? []) as $module) { $module->activate(); } @@ -262,7 +261,6 @@ public function getModuleByPath($path) return null; } - /** @var Module $rootModule */ $rootModule = null; // Find based on loaded modules diff --git a/src/Core/Manifest/ModuleResource.php b/src/Core/Manifest/ModuleResource.php index 71d13baacd0..e89b90ac547 100644 --- a/src/Core/Manifest/ModuleResource.php +++ b/src/Core/Manifest/ModuleResource.php @@ -88,7 +88,6 @@ public function getRelativePath() */ public function getURL() { - /** @var ResourceURLGenerator $generator */ $generator = Injector::inst()->get(ResourceURLGenerator::class); return $generator->urlForResource($this); } diff --git a/src/Core/Manifest/ModuleResourceLoader.php b/src/Core/Manifest/ModuleResourceLoader.php index 96cf80e2c61..960b797deaa 100644 --- a/src/Core/Manifest/ModuleResourceLoader.php +++ b/src/Core/Manifest/ModuleResourceLoader.php @@ -51,7 +51,6 @@ public function resolveURL($resource) $resource = $this->resolveResource($resource); // Resolve resource to url - /** @var ResourceURLGenerator $generator */ $generator = Injector::inst()->get(ResourceURLGenerator::class); return $generator->urlForResource($resource); } diff --git a/src/Dev/FixtureFactory.php b/src/Dev/FixtureFactory.php index 183bb1d80ba..97580fcd1b1 100644 --- a/src/Dev/FixtureFactory.php +++ b/src/Dev/FixtureFactory.php @@ -121,7 +121,7 @@ public function createRaw($table, $identifier, $data) * * @param string $class The data class, as specified in your fixture file. Parent classes won't work * @param string $identifier The identifier string, as provided in your fixture file - * @return int + * @return int|false */ public function getId($class, $identifier) { @@ -162,9 +162,10 @@ public function setId($class, $identifier, $databaseId) /** * Get an object from the fixture. * - * @param string $class The data class or table name, as specified in your fixture file. Parent classes won't work + * @template T of DataObject + * @param class-string $class The data class or table name, as specified in your fixture file. Parent classes won't work * @param string $identifier The identifier string, as provided in your fixture file - * @return DataObject + * @return T|null */ public function get($class, $identifier) { diff --git a/src/Dev/FunctionalTest.php b/src/Dev/FunctionalTest.php index 25169e381a6..3adadde3dc4 100644 --- a/src/Dev/FunctionalTest.php +++ b/src/Dev/FunctionalTest.php @@ -337,7 +337,6 @@ public function assertPartialHTMLMatchBySelector($selector, $expectedMatches, $m $actuals = []; if ($items) { - /** @var SimpleXMLElement $item */ foreach ($items as $item) { $actuals[$item->asXML()] = true; } @@ -371,7 +370,6 @@ public function assertExactHTMLMatchBySelector($selector, $expectedMatches, $mes $actuals = []; if ($items) { - /** @var SimpleXMLElement $item */ foreach ($items as $item) { $actuals[] = $item->asXML(); } diff --git a/src/Dev/SapphireTest.php b/src/Dev/SapphireTest.php index 65c63dab5e4..3694f18ae42 100644 --- a/src/Dev/SapphireTest.php +++ b/src/Dev/SapphireTest.php @@ -464,10 +464,11 @@ protected function allFixtureIDs($className) /** * Get an object from the fixture. * - * @param string $className The data class or table name, as specified in your fixture file. Parent classes won't work + * @template T of DataObject + * @param class-string $className The data class or table name, as specified in your fixture file. Parent classes won't work * @param string $identifier The identifier string, as provided in your fixture file * - * @return DataObject + * @return T */ protected function objFromFixture($className, $identifier) { @@ -563,7 +564,6 @@ protected function tearDown(): void */ public function clearEmails() { - /** @var MailerInterface $mailer */ $mailer = Injector::inst()->get(MailerInterface::class); if ($mailer instanceof TestMailer) { $mailer->clearEmails(); @@ -584,7 +584,6 @@ public function clearEmails() */ public static function findEmail($to, $from = null, $subject = null, $content = null) { - /** @var MailerInterface $mailer */ $mailer = Injector::inst()->get(MailerInterface::class); if ($mailer instanceof TestMailer) { return $mailer->findEmail($to, $from, $subject, $content); @@ -1041,7 +1040,6 @@ public function logInAs($member) */ public function logOut() { - /** @var IdentityStore $store */ $store = Injector::inst()->get(IdentityStore::class); $store->logOut(); } diff --git a/src/Dev/State/FixtureTestState.php b/src/Dev/State/FixtureTestState.php index 48731ca6587..441f212c3bc 100644 --- a/src/Dev/State/FixtureTestState.php +++ b/src/Dev/State/FixtureTestState.php @@ -175,7 +175,6 @@ protected function loadFixtures(SapphireTest $test) */ protected function loadFixture($fixtureFile, SapphireTest $test) { - /** @var YamlFixture $fixture */ $fixture = Injector::inst()->create(YamlFixture::class, $fixtureFile); $fixture->writeInto($this->getFixtureFactory(get_class($test))); } diff --git a/src/Dev/State/LoggerState.php b/src/Dev/State/LoggerState.php index 2b1fc713628..e302e0246d9 100644 --- a/src/Dev/State/LoggerState.php +++ b/src/Dev/State/LoggerState.php @@ -18,7 +18,6 @@ class LoggerState implements TestState { public function setUp(SapphireTest $test) { - /** @var Logger $userLogger */ $userLogger = Injector::inst()->get(LoggerInterface::class); if ($userLogger && $userLogger instanceof Logger) { $userLogger->setHandlers([new NullHandler()]); diff --git a/src/Dev/State/SapphireTestState.php b/src/Dev/State/SapphireTestState.php index b73e93ce27d..d07c541add0 100644 --- a/src/Dev/State/SapphireTestState.php +++ b/src/Dev/State/SapphireTestState.php @@ -72,7 +72,6 @@ public function setUp(SapphireTest $test) public function tearDown(SapphireTest $test) { // Tear down in reverse order - /** @var TestState $state */ foreach (array_reverse($this->states ?? []) as $state) { $state->tearDown($test); } @@ -93,7 +92,6 @@ public function setUpOnce($class) public function tearDownOnce($class) { // Tear down in reverse order - /** @var TestState $state */ foreach (array_reverse($this->states ?? []) as $state) { $state->tearDownOnce($class); } diff --git a/src/Dev/TestSession.php b/src/Dev/TestSession.php index 666fcc8c5c0..2c1ff07a659 100644 --- a/src/Dev/TestSession.php +++ b/src/Dev/TestSession.php @@ -208,7 +208,6 @@ public function sendRequest($method, $url, $data, $headers = null, $session = nu */ public function submitForm(string $formID, string $button = null, array $data = [], bool $withSecurityToken = true): HTTPResponse { - /** @var Crawler $page */ $page = $this->lastPage(); if ($page) { try { diff --git a/src/Dev/Validation/DatabaseAdminExtension.php b/src/Dev/Validation/DatabaseAdminExtension.php index 9907f1d3cbb..fbcf5ffc244 100644 --- a/src/Dev/Validation/DatabaseAdminExtension.php +++ b/src/Dev/Validation/DatabaseAdminExtension.php @@ -9,6 +9,7 @@ /** * Hook up static validation to the deb/build process * + * @extends Extension */ class DatabaseAdminExtension extends Extension { diff --git a/src/Forms/CheckboxSetField.php b/src/Forms/CheckboxSetField.php index 765737e3e51..786d5f6e456 100644 --- a/src/Forms/CheckboxSetField.php +++ b/src/Forms/CheckboxSetField.php @@ -58,7 +58,7 @@ public function Field($properties = []) /** * Gets the list of options to render in this formfield * - * @return ArrayList + * @return ArrayList */ public function getOptions() { diff --git a/src/Forms/CompositeField.php b/src/Forms/CompositeField.php index d1f9bbf8bd7..15c164c0791 100644 --- a/src/Forms/CompositeField.php +++ b/src/Forms/CompositeField.php @@ -76,7 +76,6 @@ public function getSchemaDataDefaults() $children = $this->getChildren(); if ($children && $children->count()) { $childSchema = []; - /** @var FormField $child */ foreach ($children as $child) { $childSchema[] = $child->getSchemaData(); } @@ -132,7 +131,6 @@ public function getName() $fieldList = $this->FieldList(); $compositeTitle = ''; $count = 0; - /** @var FormField $subfield */ foreach ($fieldList as $subfield) { $compositeTitle .= $subfield->getName(); if ($subfield->getName()) { @@ -415,7 +413,6 @@ public function performReadonlyTransformation() $clone = clone $this; if ($clone->getChildren()) { foreach ($clone->getChildren() as $child) { - /** @var FormField $child */ $child = $child->transform(new ReadonlyTransformation()); $newChildren->push($child); } @@ -441,7 +438,6 @@ public function performDisabledTransformation() $clone = clone $this; if ($clone->getChildren()) { foreach ($clone->getChildren() as $child) { - /** @var FormField $child */ $child = $child->transform(new DisabledTransformation()); $newChildren->push($child); } @@ -482,7 +478,6 @@ public function fieldPosition($field) $i = 0; foreach ($this->children as $child) { - /** @var FormField $child */ if ($child->getName() == $field->getName()) { return $i; } @@ -540,7 +535,6 @@ public function validate($validator) { $valid = true; foreach ($this->children as $child) { - /** @var FormField $child */ $valid = ($child && $child->validate($validator) && $valid); } return $this->extendValidationResult($valid, $validator); diff --git a/src/Forms/CompositeValidator.php b/src/Forms/CompositeValidator.php index 04e3530f7dd..2efbf5c6ea0 100644 --- a/src/Forms/CompositeValidator.php +++ b/src/Forms/CompositeValidator.php @@ -30,22 +30,18 @@ * { * $compositeValidator->addValidator(RequiredFields::create(['AdditionalContent'])); * } - * - * Class CompositeValidator - * - * @package SilverStripe\Forms */ class CompositeValidator extends Validator { /** - * @var array|Validator[] + * @var array */ private $validators; /** * CompositeValidator constructor. * - * @param array|Validator[] $validators + * @param array $validators */ public function __construct(array $validators = []) { @@ -146,7 +142,7 @@ public function fieldIsRequired($fieldName) } /** - * @return array|Validator[] + * @return array */ public function getValidators(): array { @@ -159,8 +155,9 @@ public function getValidators(): array * The keys for the return array match the keys in the unfiltered array. You cannot assume the keys will be * sequential or that the first key will be ZERO. * - * @param string $className - * @return array|Validator[] + * @template T of Validator + * @param class-string $className + * @return T[] */ public function getValidatorsByType(string $className): array { diff --git a/src/Forms/ConfirmedPasswordField.php b/src/Forms/ConfirmedPasswordField.php index 269aa626504..ce33be04fd4 100644 --- a/src/Forms/ConfirmedPasswordField.php +++ b/src/Forms/ConfirmedPasswordField.php @@ -168,7 +168,6 @@ public function __construct( // disable auto complete foreach ($this->getChildren() as $child) { - /** @var FormField $child */ $child->setAttribute('autocomplete', 'off'); } @@ -200,7 +199,6 @@ public function Field($properties = []) // Build inner content $fieldContent = ''; foreach ($this->getChildren() as $field) { - /** @var FormField $field */ $field->setDisabled($this->isDisabled()); $field->setReadonly($this->isReadonly()); @@ -321,7 +319,6 @@ public function getShowOnClickTitle() public function setRightTitle($title) { foreach ($this->getChildren() as $field) { - /** @var FormField $field */ $field->setRightTitle($title); } @@ -343,7 +340,6 @@ public function setChildrenTitles($titles) if (is_array($titles) && count($titles ?? []) === $expectedChildren) { foreach ($this->getChildren() as $field) { if (isset($titles[0])) { - /** @var FormField $field */ $field->setTitle($titles[0]); array_shift($titles); @@ -613,7 +609,6 @@ public function saveInto(DataObjectInterface $record) */ public function performReadonlyTransformation() { - /** @var ReadonlyField $field */ $field = $this->castedCopy(ReadonlyField::class) ->setTitle($this->title ? $this->title : _t('SilverStripe\\Security\\Member.PASSWORD', 'Password')) ->setValue('*****'); diff --git a/src/Forms/FieldList.php b/src/Forms/FieldList.php index bdaabe384cb..7e8a80cd15e 100644 --- a/src/Forms/FieldList.php +++ b/src/Forms/FieldList.php @@ -7,7 +7,7 @@ /** * A list designed to hold form field instances. * - * @method FormField[] getIterator() + * @extends ArrayList */ class FieldList extends ArrayList { @@ -65,7 +65,6 @@ public function recursiveWalk(callable $callback) { $stack = $this->toArray(); while (!empty($stack)) { - /** @var FormField $field */ $field = array_shift($stack); $callback($field); if ($field instanceof CompositeField) { @@ -399,7 +398,6 @@ public function findTab($tabName) $currentPointer = $this; foreach ($parts as $k => $part) { - /** @var FormField $currentPointer */ $currentPointer = $currentPointer->fieldByName($part); } @@ -426,7 +424,6 @@ public function findOrMakeTab($tabName, $title = null) $currentPointer = $this; foreach ($parts as $k => $part) { $parentPointer = $currentPointer; - /** @var FormField $currentPointer */ $currentPointer = $currentPointer->fieldByName($part); // Create any missing tabs if (!$currentPointer) { diff --git a/src/Forms/FileField.php b/src/Forms/FileField.php index 66b0fe51f15..8040d1fd594 100644 --- a/src/Forms/FileField.php +++ b/src/Forms/FileField.php @@ -138,7 +138,6 @@ public function saveInto(DataObjectInterface $record) File::get_file_extension($_FILES[$this->name]['name']) ); - /** @var File $file */ if ($this->relationAutoSetting) { // assume that the file is connected via a has-one $objectClass = DataObject::getSchema()->hasOneComponent(get_class($record), $this->name); diff --git a/src/Forms/Form.php b/src/Forms/Form.php index db7044ac9fb..6ded0bdef10 100644 --- a/src/Forms/Form.php +++ b/src/Forms/Form.php @@ -1372,7 +1372,6 @@ public function loadDataFrom($data, $mergeStrategy = 0, $fieldList = null) return $this; } - /** @var FormField $field */ foreach ($dataFields as $field) { $name = $field->getName(); @@ -1533,7 +1532,6 @@ public function getData() $data = []; if ($dataFields) { - /** @var FormField $field */ foreach ($dataFields as $field) { if ($field->getName()) { $data[$field->getName()] = $field->dataValue(); diff --git a/src/Forms/FormField.php b/src/Forms/FormField.php index e8c821f65d3..c6a56ece7e6 100644 --- a/src/Forms/FormField.php +++ b/src/Forms/FormField.php @@ -1352,9 +1352,10 @@ public function rootFieldList() * * Does not copy custom field templates, since they probably won't apply to the new instance. * - * @param mixed $classOrCopy Class name for copy, or existing copy instance to update + * @template T + * @param class-string|T $classOrCopy Class name for copy, or existing copy instance to update * - * @return FormField + * @return T */ public function castedCopy($classOrCopy) { @@ -1397,7 +1398,7 @@ public function canSubmitValue() * Sets the component type the FormField will be rendered as on the front-end. * * @param string $componentType - * @return FormField + * @return static */ public function setSchemaComponent($componentType) { @@ -1422,7 +1423,7 @@ public function getSchemaComponent() * If you want to pass around ad hoc data use the `data` array e.g. pass `['data' => ['myCustomKey' => 'yolo']]`. * * @param array $schemaData - The data to be merged with $this->schemaData. - * @return FormField + * @return static */ public function setSchemaData($schemaData = []) { @@ -1494,7 +1495,7 @@ public function getSchemaDataDefaults() * If you want to pass around ad hoc data use the `data` array e.g. pass `['data' => ['myCustomKey' => 'yolo']]`. * * @param array $schemaState The data to be merged with $this->schemaData. - * @return FormField + * @return static */ public function setSchemaState($schemaState = []) { diff --git a/src/Forms/GridField/GridField.php b/src/Forms/GridField/GridField.php index 2590aa7585e..d42fb7b34e9 100644 --- a/src/Forms/GridField/GridField.php +++ b/src/Forms/GridField/GridField.php @@ -335,7 +335,7 @@ public function setReadonly($readonly) } /** - * @return ArrayList + * @return ArrayList */ public function getComponents() { diff --git a/src/Forms/GridField/GridFieldConfig.php b/src/Forms/GridField/GridFieldConfig.php index ea111f8379b..6851fc7a0da 100644 --- a/src/Forms/GridField/GridFieldConfig.php +++ b/src/Forms/GridField/GridFieldConfig.php @@ -31,7 +31,7 @@ class GridFieldConfig use Configurable; /** - * @var ArrayList + * @var ArrayList */ protected $components = null; @@ -111,7 +111,7 @@ public function removeComponentsByType($types) } /** - * @return ArrayList Of GridFieldComponent + * @return ArrayList */ public function getComponents() { @@ -124,8 +124,9 @@ public function getComponents() /** * Returns all components extending a certain class, or implementing a certain interface. * - * @param string $type Class name or interface - * @return ArrayList Of GridFieldComponent + * @template T of GridFieldComponent + * @param class-string $type Class name or interface + * @return ArrayList */ public function getComponentsByType($type) { @@ -141,8 +142,9 @@ public function getComponentsByType($type) /** * Returns the first available component with the given class or interface. * - * @param string $type ClassName - * @return GridFieldComponent + * @template T of GridFieldComponent + * @param class-string $type ClassName + * @return T|null */ public function getComponentByType($type) { diff --git a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php index 252b270bd60..97a9e5cbfae 100644 --- a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php +++ b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php @@ -340,7 +340,6 @@ protected function getRightGroupField() $previousAndNextGroup->addExtraClass('btn-group--circular mr-2'); $previousAndNextGroup->setFieldHolderTemplate(CompositeField::class . '_holder_buttongroup'); - /** @var GridFieldDetailForm $component */ $component = $this->gridField->getConfig()->getComponentByType(GridFieldDetailForm::class); $paginator = $this->getGridField()->getConfig()->getComponentByType(GridFieldPaginator::class); $gridState = $this->getGridField()->getState(); @@ -902,7 +901,7 @@ public function getRecord() * see {@link LeftAndMain->Breadcrumbs()} for details. * * @param boolean $unlinked - * @return ArrayList + * @return ArrayList */ public function Breadcrumbs($unlinked = false) { @@ -910,7 +909,7 @@ public function Breadcrumbs($unlinked = false) return null; } - /** @var ArrayList $items */ + /** @var ArrayList $items */ $items = $this->popupController->Breadcrumbs($unlinked); if (!$items) { diff --git a/src/Forms/GridField/GridFieldExportButton.php b/src/Forms/GridField/GridFieldExportButton.php index 7a1b63e4826..710b0e20757 100644 --- a/src/Forms/GridField/GridFieldExportButton.php +++ b/src/Forms/GridField/GridFieldExportButton.php @@ -150,7 +150,6 @@ protected function getExportColumnsForGridField(GridField $gridField) return $this->exportColumns; } - /** @var GridFieldDataColumns $dataCols */ $dataCols = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class); if ($dataCols) { return $dataCols->getDisplayFields($gridField); @@ -224,17 +223,15 @@ public function generateExportFileData($gridField) } } - /** @var GridFieldDataColumns|null $gridFieldColumnsComponent */ $gridFieldColumnsComponent = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class); $columnsHandled = ($gridFieldColumnsComponent) ? $gridFieldColumnsComponent->getColumnsHandled($gridField) : []; - /** @var ArrayList|DataList $items */ + /** @var SS_List $items */ // Remove limit as the list may be paginated, we want the full list for the export $items = $items->limit(null); - /** @var ViewableData $item */ foreach ($items as $item) { // Assume item can be viewed if canView() isn't implemented if (!$item->hasMethod('canView') || $item->canView()) { diff --git a/src/Forms/GridField/GridFieldFilterHeader.php b/src/Forms/GridField/GridFieldFilterHeader.php index edeb9f69337..1fb47d2499d 100755 --- a/src/Forms/GridField/GridFieldFilterHeader.php +++ b/src/Forms/GridField/GridFieldFilterHeader.php @@ -185,7 +185,6 @@ public function getManipulatedData(GridField $gridField, SS_List $dataList) return $dataList; } - /** @var Filterable $dataList */ /** @var array $filterArguments */ $filterArguments = $this->getState($gridField)->Columns->toArray(); if (empty($filterArguments)) { diff --git a/src/Forms/GridField/GridFieldPageCount.php b/src/Forms/GridField/GridFieldPageCount.php index bebbadcd0a0..be2f0593a7c 100755 --- a/src/Forms/GridField/GridFieldPageCount.php +++ b/src/Forms/GridField/GridFieldPageCount.php @@ -46,7 +46,6 @@ public function __construct($targetFragment = 'before') */ protected function getPaginator($gridField) { - /** @var GridFieldPaginator $paginator */ $paginator = $gridField->getConfig()->getComponentByType(GridFieldPaginator::class); if (!$paginator && GridFieldPageCount::config()->uninherited('require_paginator')) { diff --git a/src/Forms/GridField/GridFieldPrintButton.php b/src/Forms/GridField/GridFieldPrintButton.php index 0cf56bf6b12..96a47508859 100644 --- a/src/Forms/GridField/GridFieldPrintButton.php +++ b/src/Forms/GridField/GridFieldPrintButton.php @@ -156,7 +156,6 @@ protected function getPrintColumnsForGridField(GridField $gridField) return $this->printColumns; } - /** @var GridFieldDataColumns $dataCols */ $dataCols = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class); if ($dataCols) { return $dataCols->getDisplayFields($gridField); @@ -232,7 +231,6 @@ public function generatePrintData(GridField $gridField) $items = $gridField->getManipulatedList(); $itemRows = new ArrayList(); - /** @var GridFieldDataColumns $gridFieldColumnsComponent */ $gridFieldColumnsComponent = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class); /** @var ViewableData $item */ diff --git a/src/Forms/GridField/GridFieldSortableHeader.php b/src/Forms/GridField/GridFieldSortableHeader.php index 1320bbc4c94..d0943fba374 100644 --- a/src/Forms/GridField/GridFieldSortableHeader.php +++ b/src/Forms/GridField/GridFieldSortableHeader.php @@ -124,7 +124,6 @@ public function getHTMLFragments($gridField) if (!$this->checkDataType($list)) { return null; } - /** @var Sortable $list */ $forTemplate = new ArrayData([]); $forTemplate->Fields = new ArrayList; @@ -247,7 +246,7 @@ public function handleAction(GridField $gridField, $actionName, $arguments, $dat * {@link DataQuery} first. * * @param GridField $gridField - * @param SS_List $dataList + * @param SS_List&Sortable $dataList * @return SS_List */ public function getManipulatedData(GridField $gridField, SS_List $dataList) @@ -256,14 +255,12 @@ public function getManipulatedData(GridField $gridField, SS_List $dataList) return $dataList; } - /** @var Sortable $dataList */ $state = $this->getState($gridField); if ($state->SortColumn == "") { return $dataList; } // Prevent SQL Injection by validating that SortColumn exists - /** @var GridFieldDataColumns $columns */ $columns = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class); $fields = $columns->getDisplayFields($gridField); if (!array_key_exists($state->SortColumn, $fields) && diff --git a/src/Forms/HTMLEditor/TinyMCEConfig.php b/src/Forms/HTMLEditor/TinyMCEConfig.php index 8e85d8e7430..80621abd086 100644 --- a/src/Forms/HTMLEditor/TinyMCEConfig.php +++ b/src/Forms/HTMLEditor/TinyMCEConfig.php @@ -819,7 +819,6 @@ public function setContentCSS($css) */ public function getScriptURL() { - /** @var TinyMCEScriptGenerator $generator */ $generator = Injector::inst()->get(TinyMCEScriptGenerator::class); return $generator->getScriptURL($this); } diff --git a/src/Forms/ListboxField.php b/src/Forms/ListboxField.php index 1c792ae5496..b305c453d6a 100644 --- a/src/Forms/ListboxField.php +++ b/src/Forms/ListboxField.php @@ -84,7 +84,7 @@ public function Field($properties = []) /** * Gets the list of options to render in this formfield * - * @return ArrayList + * @return ArrayList */ public function getOptions() { diff --git a/src/Forms/Schema/FormSchema.php b/src/Forms/Schema/FormSchema.php index a6bd1c2a520..a8b712a14e7 100644 --- a/src/Forms/Schema/FormSchema.php +++ b/src/Forms/Schema/FormSchema.php @@ -103,12 +103,10 @@ public function getSchema(Form $form) 'actions' => [] ]; - /** @var FormField $action */ foreach ($form->Actions() as $action) { $schema['actions'][] = $action->getSchemaData(); } - /** @var FormField $field */ foreach ($form->Fields() as $field) { $schema['fields'][] = $field->getSchemaData(); } @@ -197,10 +195,12 @@ protected function getSchemaForMessage($message) ]; } + /** + * @param iterable $fields + */ protected function getFieldStates($fields) { $states = []; - /** @var FormField $field */ foreach ($fields as $field) { $states[] = $field->getSchemaState(); diff --git a/src/Forms/SearchableDropdownTrait.php b/src/Forms/SearchableDropdownTrait.php index 39c5daeb954..5931912f9d2 100644 --- a/src/Forms/SearchableDropdownTrait.php +++ b/src/Forms/SearchableDropdownTrait.php @@ -177,6 +177,8 @@ public function setPlaceholder(string $placeholder): static * If a search context has been set via setSearchContext() that will be used * Will fallback to using the dataobjects default search context if a sourceList has been set * Otherwise will return null + * + * @return SearchContext|null */ public function getSearchContext(): ?SearchContext { @@ -368,7 +370,6 @@ public function getValueArray(): array // Don't know what value is, handle gracefully. We should not raise an exception here because // of there is a bad data for whatever a content editor will not be able to resolve and it will // render part of the CMS unusable - // /** @var LoggerInterface $logger */ $logger = Injector::inst()->get(LoggerInterface::class); $logger->warning('Could not determine value in ' . __CLASS__ . '::getValueArray()'); return []; @@ -399,7 +400,7 @@ public function saveInto(DataObjectInterface $record): void if (!$record->hasMethod($name)) { throw new LogicException("Relation $name does not exist"); } - /** @var Relation $relation */ + /** @var Relation $relationList */ $relationList = $record->$name(); // Use RelationList rather than Relation here since some Relation classes don't allow setting value // but RelationList does @@ -542,9 +543,9 @@ private function updateDataForSchema(array $data): array } /** - * @var ArrayList $options The options list being updated that will become - * @var DataList|ArrayList $items The items to be turned into options - * @var DataList|ArrayList $values The values that have been selected i.e. the value of the Field + * @param ArrayList $options The options list being updated that will become + * @param DataList|ArrayList $items The items to be turned into options + * @param DataList|ArrayList $values The values that have been selected i.e. the value of the Field */ private function updateOptionsForSchema( ArrayList $options, diff --git a/src/Forms/SelectField.php b/src/Forms/SelectField.php index edc3f4f0401..fb48443be9b 100644 --- a/src/Forms/SelectField.php +++ b/src/Forms/SelectField.php @@ -240,8 +240,7 @@ public function isSelectedValue($dataValue, $userValue) public function performReadonlyTransformation() { - /** @var LookupField $field */ - $field = $this->castedCopy('SilverStripe\\Forms\\LookupField'); + $field = $this->castedCopy(LookupField::class); $field->setSource($this->getSource()); $field->setReadonly(true); @@ -255,14 +254,6 @@ public function performDisabledTransformation() return $clone; } - /** - * Returns another instance of this field, but "cast" to a different class. - * - * @see FormField::castedCopy() - * - * @param string $classOrCopy - * @return FormField - */ public function castedCopy($classOrCopy) { $field = parent::castedCopy($classOrCopy); diff --git a/src/Forms/SingleSelectField.php b/src/Forms/SingleSelectField.php index 2230cd807c8..b3a97be5eea 100644 --- a/src/Forms/SingleSelectField.php +++ b/src/Forms/SingleSelectField.php @@ -175,7 +175,6 @@ public function castedCopy($classOrCopy) */ public function performReadonlyTransformation() { - /** @var SingleLookupField $field */ $field = $this->castedCopy(SingleLookupField::class); $field->setSource($this->getSource()); $field->setReadonly(true); diff --git a/src/Forms/TimeField.php b/src/Forms/TimeField.php index 01d4e99fd05..24ba4645f3d 100644 --- a/src/Forms/TimeField.php +++ b/src/Forms/TimeField.php @@ -372,7 +372,6 @@ public function setLocale($locale) */ public function performReadonlyTransformation() { - /** @var TimeField_Readonly $result */ $result = $this->castedCopy(TimeField_Readonly::class); $result ->setValue(false) diff --git a/src/Forms/TreeDropdownField.php b/src/Forms/TreeDropdownField.php index 3cea2178b08..d50e22772b2 100644 --- a/src/Forms/TreeDropdownField.php +++ b/src/Forms/TreeDropdownField.php @@ -458,7 +458,6 @@ public function tree(HTTPRequest $request) $this->populateIDs(); } - /** @var DataObject|Hierarchy $obj */ $obj = null; $sourceObject = $this->getSourceObject(); @@ -837,7 +836,6 @@ protected function objectForKey($key) */ public function performReadonlyTransformation() { - /** @var TreeDropdownField_Readonly $copy */ $copy = $this->castedCopy(TreeDropdownField_Readonly::class); $copy->setKeyField($this->getKeyField()); $copy->setLabelField($this->getLabelField()); @@ -846,10 +844,6 @@ public function performReadonlyTransformation() return $copy; } - /** - * @param string|FormField $classOrCopy - * @return FormField - */ public function castedCopy($classOrCopy) { $field = $classOrCopy; diff --git a/src/Forms/TreeMultiselectField.php b/src/Forms/TreeMultiselectField.php index 3bc5e0be1db..eb4e1e02e23 100644 --- a/src/Forms/TreeMultiselectField.php +++ b/src/Forms/TreeMultiselectField.php @@ -281,7 +281,6 @@ public function saveInto(DataObjectInterface $record) */ public function performReadonlyTransformation() { - /** @var TreeMultiselectField_Readonly $copy */ $copy = $this->castedCopy(TreeMultiselectField_Readonly::class); $copy->setKeyField($this->getKeyField()); $copy->setLabelField($this->getLabelField()); diff --git a/src/ORM/ArrayList.php b/src/ORM/ArrayList.php index 30858902f5d..f953ffb6176 100644 --- a/src/ORM/ArrayList.php +++ b/src/ORM/ArrayList.php @@ -29,6 +29,12 @@ * - sort * - filter * - exclude + * + * @template T + * @implements SS_List + * @implements Filterable + * @implements Sortable + * @implements Limitable */ class ArrayList extends ViewableData implements SS_List, Filterable, Sortable, Limitable { @@ -45,13 +51,12 @@ class ArrayList extends ViewableData implements SS_List, Filterable, Sortable, L /** * Holds the items in the list * - * @var array + * @var array */ protected $items = []; /** - * - * @param array $items - an initial array to fill this object with + * @param array $items - an initial array to fill this object with */ public function __construct(array $items = []) { @@ -62,14 +67,14 @@ public function __construct(array $items = []) /** * Underlying type class for this list * - * @var string + * @var class-string|null */ protected $dataClass = null; /** * Return the class of items in this list, by looking at the first item inside it. * - * @return string + * @return class-string|null */ public function dataClass() { @@ -85,7 +90,7 @@ public function dataClass() /** * Hint this list to a specific type * - * @param string $class + * @param class-string $class * @return $this */ public function setDataClass($class) @@ -116,6 +121,8 @@ public function exists() /** * Returns an Iterator for this ArrayList. * This function allows you to use ArrayList in foreach loops + * + * @return Traversable */ public function getIterator(): Traversable { @@ -130,8 +137,6 @@ public function getIterator(): Traversable /** * Return an array of the actual items that this ArrayList contains. - * - * @return array */ public function toArray() { @@ -164,8 +169,6 @@ public function debug() /** * Return this list as an array and every object it as an sub array as well - * - * @return array */ public function toNestedArray() { @@ -263,7 +266,7 @@ public function replace($item, $with) * Merges with another array or list by pushing all the items in it onto the * end of this list. * - * @param array|object $with + * @param iterable $with */ public function merge($with) { @@ -342,11 +345,6 @@ public function shift() return array_shift($this->items); } - /** - * Returns the first item in the list - * - * @return mixed - */ public function first() { if (empty($this->items)) { @@ -356,11 +354,6 @@ public function first() return reset($this->items); } - /** - * Returns the last item in the list - * - * @return mixed - */ public function last() { if (empty($this->items)) { @@ -425,7 +418,7 @@ public function canSortBy($by) /** * Reverses an {@link ArrayList} * - * @return ArrayList + * @return static */ public function reverse() { @@ -479,7 +472,6 @@ protected function parseSortColumn($column, $direction = null) * * Note that columns may be double quoted as per ANSI sql standard * - * @return static * @see SS_List::sort() * @example $list->sort('Name'); // default ASC sorting * @example $list->sort('Name DESC'); // DESC sorting @@ -596,8 +588,7 @@ public function canFilterBy($by) * Find the first item of this list where the given key = value * * @param string $key - * @param string $value - * @return mixed + * @param mixed $value */ public function find($key, $value) { @@ -607,7 +598,6 @@ public function find($key, $value) /** * Filter the list to include items with these characteristics * - * @return ArrayList * @see Filterable::filter() * @example $list->filter('Name', 'bob'); // only bob in the list * @example $list->filter('Name', array('aziz', 'bob'); // aziz and bob in list @@ -645,7 +635,6 @@ public function filter() * $list = $list->filterAny('Name:PartialMatch', 'sam'); * * @param string|array See {@link filter()} - * @return static */ public function filterAny() { @@ -656,7 +645,6 @@ public function filterAny() /** * Exclude the list to not contain items with these characteristics * - * @return ArrayList * @see SS_List::exclude() * @example $list->exclude('Name', 'bob'); // exclude bob from list * @example $list->exclude('Name', array('aziz', 'bob'); // exclude aziz and bob from list @@ -694,6 +682,7 @@ public function exclude() * $list = $list->excludeAny('Name:PartialMatch', 'sam'); * * @param string|array See {@link filter()} + * @return static */ public function excludeAny(): static { @@ -703,6 +692,7 @@ public function excludeAny(): static /** * Apply the appropriate filtering or excluding + * @return static */ protected function filterOrExclude(array $filters, bool $inclusive = true, bool $any = false): static { @@ -740,7 +730,6 @@ protected function filterOrExclude(array $filters, bool $inclusive = true, bool foreach ($this->items as $item) { $matches = []; foreach ($filters as $filterKey => $filterValue) { - /** @var SearchFilter $searchFilter */ $searchFilter = $searchFilters[$filterKey]; $extractedValue = $this->extractValue($item, $searchFilter->getFullName()); $hasMatch = null; @@ -840,7 +829,6 @@ protected function normaliseFilterArgs($column, $value = null) * Filter this list to only contain the given Primary IDs * * @param array $ids Array of integers, will be automatically cast/escaped. - * @return ArrayList */ public function byIDs($ids) { @@ -864,7 +852,7 @@ public function byID($id) * * @example $list = $list->filterByCallback(function($item, $list) { return $item->Age == 9; }) * @param callable $callback - * @return ArrayList + * @return static */ public function filterByCallback($callback) { @@ -901,6 +889,7 @@ public function offsetExists(mixed $offset): bool /** * Returns item stored in list with index $key + * @return T|null */ public function offsetGet(mixed $offset): mixed { diff --git a/src/ORM/Connect/DBSchemaManager.php b/src/ORM/Connect/DBSchemaManager.php index 56a50867f1e..449333e4a67 100644 --- a/src/ORM/Connect/DBSchemaManager.php +++ b/src/ORM/Connect/DBSchemaManager.php @@ -167,8 +167,6 @@ public function schemaUpdate($callback) // Clear update list for client code to mess around with $this->schemaUpdateTransaction = []; - /** @var Exception $error */ - $error = null; try { // Yield control to client code $callback(); @@ -425,7 +423,6 @@ public function requireTable( $fieldObj->setTable($table); if ($fieldObj instanceof DBPrimaryKey) { - /** @var DBPrimaryKey $fieldObj */ $fieldObj->setAutoIncrement($hasAutoIncPK); } diff --git a/src/ORM/Connect/MySQLDatabase.php b/src/ORM/Connect/MySQLDatabase.php index 6883ae3f525..b0633d20a9a 100644 --- a/src/ORM/Connect/MySQLDatabase.php +++ b/src/ORM/Connect/MySQLDatabase.php @@ -278,7 +278,6 @@ public function searchEngine( $queryParameters = []; $totalCount = 0; foreach ($lists as $class => $list) { - /** @var SQLSelect $query */ $query = $list->dataQuery()->query(); // There's no need to do all that joining diff --git a/src/ORM/DB.php b/src/ORM/DB.php index 250a09229a1..7be15a65c7c 100644 --- a/src/ORM/DB.php +++ b/src/ORM/DB.php @@ -198,7 +198,6 @@ public static function set_alternative_database_name($name = null) if (!Injector::inst()->has(HTTPRequest::class)) { return; } - /** @var HTTPRequest $request */ $request = Injector::inst()->get(HTTPRequest::class); if ($name) { $request->getSession()->set(self::ALT_DB_KEY, $name); @@ -226,7 +225,6 @@ public static function get_alternative_database_name() if (!Injector::inst()->has(HTTPRequest::class)) { return null; } - /** @var HTTPRequest $request */ $request = Injector::inst()->get(HTTPRequest::class); // Skip if the session hasn't been started if (!$request->getSession()->isStarted()) { diff --git a/src/ORM/DataExtension.php b/src/ORM/DataExtension.php index d4548d246d5..6d8a61d806b 100644 --- a/src/ORM/DataExtension.php +++ b/src/ORM/DataExtension.php @@ -13,7 +13,8 @@ /** * An extension that adds additional functionality to a {@link DataObject}. * - * @property DataObject $owner + * @template T of DataObject + * @extends Extension */ abstract class DataExtension extends Extension { diff --git a/src/ORM/DataList.php b/src/ORM/DataList.php index ea33bf85437..ec30649d225 100644 --- a/src/ORM/DataList.php +++ b/src/ORM/DataList.php @@ -35,6 +35,12 @@ * - removeAll * * Subclasses of DataList may add other methods that have the same effect. + * + * @template T of DataObject + * @implements SS_List + * @implements Filterable + * @implements Sortable + * @implements Limitable */ class DataList extends ViewableData implements SS_List, Filterable, Sortable, Limitable { @@ -49,7 +55,7 @@ class DataList extends ViewableData implements SS_List, Filterable, Sortable, Li /** * The DataObject class name that this data list is querying * - * @var string + * @var class-string */ protected $dataClass; @@ -63,7 +69,7 @@ class DataList extends ViewableData implements SS_List, Filterable, Sortable, Li /** * A cached Query to save repeated database calls. {@see DataList::getTemplateIteratorCount()} * - * @var SilverStripe\ORM\Connect\Query + * @var Query */ protected $finalisedQuery; @@ -89,7 +95,7 @@ class DataList extends ViewableData implements SS_List, Filterable, Sortable, Li * Create a new DataList. * No querying is done on construction, but the initial query schema is set up. * - * @param string $dataClass - The DataObject class to query. + * @param class-string $dataClass - The DataObject class to query. */ public function __construct($dataClass) { @@ -102,7 +108,7 @@ public function __construct($dataClass) /** * Get the dataClass name for this DataList, ie the DataObject ClassName * - * @return string + * @return class-string */ public function dataClass() { @@ -150,7 +156,7 @@ public function dataQuery() * alterDataQuery * * @param callable $callback - * @return static + * @return static * @throws Exception */ public function alterDataQuery($callback) @@ -187,7 +193,7 @@ public function alterDataQuery($callback) * Return a new DataList instance with the underlying {@link DataQuery} object changed * * @param DataQuery $dataQuery - * @return static + * @return static */ public function setDataQuery(DataQuery $dataQuery) { @@ -201,7 +207,7 @@ public function setDataQuery(DataQuery $dataQuery) * * @param string|array $keyOrArray Either the single key to set, or an array of key value pairs to set * @param mixed $val If $keyOrArray is not an array, this is the value to set - * @return static + * @return static */ public function setDataQueryParam($keyOrArray, $val = null) { @@ -242,7 +248,7 @@ public function sql(&$parameters = []) * * @param string|array|SQLConditionGroup $filter Predicate(s) to set, as escaped SQL statements or * paramaterised queries - * @return static + * @return static */ public function where($filter) { @@ -264,7 +270,7 @@ public function where($filter) * * @param string|array|SQLConditionGroup $filter Predicate(s) to set, as escaped SQL statements or * paramaterised queries - * @return static + * @return static */ public function whereAny($filter) { @@ -336,7 +342,7 @@ public function limit(?int $length, int $offset = 0): static * Return a new DataList instance with distinct records or not * * @param bool $value - * @return static + * @return static */ public function distinct($value) { @@ -446,6 +452,7 @@ private function validateSortDirection(string $direction): void * * This method accepts raw SQL so could be vulnerable to SQL injection attacks if used incorrectly, * it's preferable to use sort() instead which does not allow raw SQL + * @return static */ public function orderBy(string $orderBy): static { @@ -473,7 +480,6 @@ public function orderBy(string $orderBy): static * ->filter('Field:not', null) will generate '"Field" IS NOT NULL' * * @param string|array Escaped SQL statement. If passed as array, all keys and values will be escaped internally - * @return $this */ public function filter() { @@ -499,7 +505,7 @@ public function filter() * Return a new instance of the list with an added filter * * @param array $filterArray - * @return $this + * @return static */ public function addFilter($filterArray) { @@ -535,7 +541,6 @@ public function addFilter($filterArray) * // SQL: WHERE (("Name" IN ('bob', 'phil')) OR ("Age" IN ('21', '43')) * * @param string|array See {@link filter()} - * @return static */ public function filterAny() { @@ -580,7 +585,7 @@ private function getFilterAnySubquery(DataQuery $query, array $whereArguments): * * @example $list = $list->filterByCallback(function($item, $list) { return $item->Age == 9; }) * @param callable $callback - * @return ArrayList (this may change in future implementations) + * @return ArrayList */ public function filterByCallback($callback) { @@ -590,7 +595,6 @@ public function filterByCallback($callback) gettype($callback) )); } - /** @var ArrayList $output */ $output = ArrayList::create(); foreach ($this as $item) { if (call_user_func($callback, $item, $this)) { @@ -620,7 +624,7 @@ public function filterByCallback($callback) * @param string $columnName Quoted column name (by reference) * @param bool $linearOnly Set to true to restrict to linear relations only. Set this * if this relation will be used for sorting, and should not include duplicate rows. - * @return $this DataList with this relation applied + * @return static DataList with this relation applied */ public function applyRelation($field, &$columnName = null, $linearOnly = false) { @@ -677,8 +681,6 @@ protected function isValidRelationName($field) * * @param string|array * @param string [optional] - * - * @return $this */ public function exclude() { @@ -718,7 +720,7 @@ public function exclude() * @param string|array * @param string [optional] * - * @return $this + * @return static */ public function excludeAny() { @@ -747,8 +749,8 @@ public function excludeAny() * * The $list passed needs to contain the same dataclass as $this * - * @param DataList $list - * @return static + * @param DataList $list + * @return static * @throws InvalidArgumentException */ public function subtract(DataList $list) @@ -772,7 +774,7 @@ public function subtract(DataList $list) * will cause the query to appear first. The default is 20, and joins created automatically by the * ORM have a value of 10. * @param array $parameters Any additional parameters if the join is a parameterised subquery - * @return static + * @return static */ public function innerJoin($table, $onClause, $alias = null, $order = 20, $parameters = []) { @@ -791,7 +793,7 @@ public function innerJoin($table, $onClause, $alias = null, $order = 20, $parame * will cause the query to appear first. The default is 20, and joins created automatically by the * ORM have a value of 10. * @param array $parameters Any additional parameters if the join is a parameterised subquery - * @return static + * @return static */ public function leftJoin($table, $onClause, $alias = null, $order = 20, $parameters = []) { @@ -810,7 +812,7 @@ public function leftJoin($table, $onClause, $alias = null, $order = 20, $paramet * will cause the query to appear first. The default is 20, and joins created automatically by the * ORM have a value of 10. * @param array $parameters Any additional parameters if the join is a parameterised subquery - * @return static + * @return static */ public function rightJoin($table, $onClause, $alias = null, $order = 20, $parameters = []) { @@ -822,8 +824,6 @@ public function rightJoin($table, $onClause, $alias = null, $order = 20, $parame /** * Return an array of the actual items that this DataList contains at this stage. * This is when the query is actually executed. - * - * @return array */ public function toArray() { @@ -852,12 +852,6 @@ public function toNestedArray() return $result; } - /** - * Walks the list using the specified callback - * - * @param callable $callback - * @return $this - */ public function each($callback) { foreach ($this as $row) { @@ -894,7 +888,7 @@ public function map($keyField = 'ID', $titleField = 'Title') * If called without $row['ID'] set, then a new object will be created rather than rehydrated. * * @param array $row - * @return DataObject + * @return T */ public function createDataObject($row) { @@ -946,6 +940,7 @@ public function getQueryParams() /** * Returns an Iterator for this DataList. * This function allows you to use DataLists in foreach loops + * @return Traversable */ public function getIterator(): Traversable { @@ -1048,10 +1043,10 @@ private function fetchEagerLoadRelations(Query $query): void foreach ($this->eagerLoadRelationChains as $relationChain) { $parentDataClass = $this->dataClass(); $parentIDs = $topLevelIDs; - /** @var Query|array */ $parentRelationData = $query; $chainToDate = []; foreach (explode('.', $relationChain) as $relationName) { + /** @var Query|array $parentRelationData */ $chainToDate[] = $relationName; list( $relationDataClass, @@ -1457,6 +1452,8 @@ private function fillEmptyEagerLoadedRelations( * * IMPORTANT: Calling eagerLoad() will cause any relations on DataObjects to be returned as an EagerLoadedList * instead of a subclass of DataList such as HasManyList i.e. MyDataObject->MyHasManyRelation() returns an EagerLoadedList + * + * @return static */ public function eagerLoad(...$relationChains): static { @@ -1548,11 +1545,9 @@ public function sum($fieldName) /** - * Returns the first item in this DataList (instanceof DataObject) + * Returns the first item in this DataList * * The object returned is not cached, unlike {@link DataObject::get_one()} - * - * @return DataObject|null */ public function first() { @@ -1568,11 +1563,9 @@ public function first() } /** - * Returns the last item in this DataList (instanceof DataObject) + * Returns the last item in this DataList * * The object returned is not cached, unlike {@link DataObject::get_one()} - * - * @return DataObject|null */ public function last() { @@ -1605,7 +1598,6 @@ public function exists() * * @param string $key * @param string $value - * @return DataObject|null */ public function find($key, $value) { @@ -1616,7 +1608,7 @@ public function find($key, $value) * Restrict the columns to fetch into this DataList * * @param array $queriedColumns - * @return static + * @return static */ public function setQueriedColumns($queriedColumns) { @@ -1625,12 +1617,6 @@ public function setQueriedColumns($queriedColumns) }); } - /** - * Filter this list to only contain the given Primary IDs - * - * @param array $ids Array of integers - * @return $this - */ public function byIDs($ids) { return $this->filter('ID', $ids); @@ -1640,9 +1626,6 @@ public function byIDs($ids) * Return the first DataObject with the given ID * * The object returned is not cached, unlike {@link DataObject::get_by_id()} - * - * @param int $id - * @return DataObject|null */ public function byID($id) { @@ -1683,7 +1666,7 @@ public function columnUnique($colName = "ID") * Sets the ComponentSet to be the given ID list. * Records will be added and deleted as appropriate. * - * @param array $idList List of IDs. + * @param array $idList List of IDs. */ public function setByIDList($idList) { @@ -1716,7 +1699,7 @@ public function setByIDList($idList) * Returns an array with both the keys and values set to the IDs of the records in this list. * Does not respect sort order. Use ->column("ID") to get an ID list with the current sort. * - * @return array + * @return array */ public function getIDList() { @@ -1734,13 +1717,13 @@ public function getIDList() * DataList::Create(\SilverStripe\Security\Group::class)->relation("Members") * * @param string $relationName - * @return HasManyList|ManyManyList + * @return RelationList */ public function relation($relationName) { $ids = $this->column('ID'); $singleton = DataObject::singleton($this->dataClass); - /** @var HasManyList|ManyManyList $relation */ + /** @var RelationList $relation */ $relation = $singleton->$relationName($ids); return $relation; } @@ -1753,8 +1736,8 @@ public function dbObject($fieldName) /** * Add a number of items to the component set. * - * @param array $items Items to add, as either DataObjects or IDs. - * @return $this + * @param array $items Items to add, as either DataObjects or IDs. + * @return static */ public function addMany($items) { @@ -1767,8 +1750,8 @@ public function addMany($items) /** * Remove the items from this list with the given IDs * - * @param array $idList - * @return $this + * @param array $idList + * @return static */ public function removeMany($idList) { @@ -1782,7 +1765,7 @@ public function removeMany($idList) * Remove every element in this DataList matching the given $filter. * * @param string|array $filter - a sql type where filter - * @return $this + * @return static */ public function removeByFilter($filter) { @@ -1795,7 +1778,7 @@ public function removeByFilter($filter) /** * Shuffle the datalist using a random function provided by the SQL engine * - * @return $this + * @return static */ public function shuffle() { @@ -1805,7 +1788,7 @@ public function shuffle() /** * Remove every element in this DataList. * - * @return $this + * @return static */ public function removeAll() { @@ -1819,7 +1802,7 @@ public function removeAll() * This method are overloaded by HasManyList and ManyMany list to perform more sophisticated * list manipulation * - * @param mixed $item + * @param DataObject|int $item */ public function add($item) { @@ -1831,7 +1814,7 @@ public function add($item) * Return a new item to add to this DataList. * * @param array $initialFields - * @return DataObject + * @return T */ public function newObject($initialFields = null) { @@ -1867,7 +1850,7 @@ public function removeByID($itemID) /** * Reverses a list of items. * - * @return static + * @return static */ public function reverse() { @@ -1888,6 +1871,8 @@ public function offsetExists(mixed $key): bool * Returns item stored in list with index $key * * The object returned is not cached, unlike {@link DataObject::get_one()} + * + * @return T|null */ public function offsetGet(mixed $key): ?DataObject { @@ -1922,7 +1907,7 @@ public function offsetUnset(mixed $key): void * * @param int $chunkSize * @throws InvalidArgumentException If `$chunkSize` has an invalid size. - * @return Generator|DataObject[] + * @return iterable */ public function chunkedFetch(int $chunkSize = 1000): iterable { diff --git a/src/ORM/DataObject.php b/src/ORM/DataObject.php index e445db6e09a..dd5e81da509 100644 --- a/src/ORM/DataObject.php +++ b/src/ORM/DataObject.php @@ -109,7 +109,6 @@ */ class DataObject extends ViewableData implements DataObjectInterface, i18nEntityProvider, Resettable { - /** * Human-readable singular name. * @var string @@ -525,7 +524,6 @@ public function duplicate(bool $doWrite = true, array|null $relations = null): s // Create unsaved raw duplicate $map = $this->toMap(); unset($map['Created']); - /** @var static $clone */ $clone = Injector::inst()->create(static::class, $map, false, $this->getSourceQueryParams()); $clone->ID = 0; @@ -628,7 +626,6 @@ protected function duplicateHasManyRelation($sourceObject, $destinationObject, $ $source = $sourceObject->getComponents($relation); $dest = $destinationObject->getComponents($relation); - /** @var DataObject $item */ foreach ($source as $item) { // Don't write on duplicate; Wait until ParentID is available later. // writeRelations() will eventually write these records when converting @@ -742,9 +739,10 @@ public function setClassName($className) * there is no record, or the record has no ID. In this case, we do have an ID but * we still need to repopulate the defaults. * - * @param string $newClassName The name of the new class + * @template T of DataObject + * @param class-string $newClassName The name of the new class * - * @return DataObject The new instance of the new class, The exact type will be of the class name provided. + * @return T The new instance of the new class, The exact type will be of the class name provided. */ public function newClassInstance($newClassName) { @@ -963,7 +961,7 @@ public function getTitle() * Returns the associated database record - in this case, the object itself. * This is included so that you can call $dataOrController->data() and get a DataObject all the time. * - * @return DataObject Associated database record + * @return static Associated database record */ public function data() { @@ -1012,7 +1010,7 @@ public function getQueriedDatabaseFields() * whitelist the allowed keys. * * @param array $data A map of field name to data values to update. - * @return DataObject $this + * @return static $this */ public function update($data) { @@ -1021,7 +1019,6 @@ public function update($data) if (strpos($key ?? '', '.') !== false) { $relations = explode('.', $key ?? ''); $fieldName = array_pop($relations); - /** @var static $relObj */ $relObj = $this; $relation = null; foreach ($relations as $i => $relation) { @@ -1029,6 +1026,7 @@ public function update($data) // as the updater wouldn't know which object to write to (or create) if ($relObj->$relation() instanceof DataObject) { $parentObj = $relObj; + /** @var static $relObj */ $relObj = $relObj->$relation(); // If the intermediate relationship objects haven't been created, then write them if ($i < sizeof($relations ?? []) - 1 && !$relObj->ID || (!$relObj->ID && $parentObj !== $this)) { @@ -1073,7 +1071,7 @@ public function update($data) * use the write() method. * * @param array $data A map of field name to data values to update. - * @return DataObject $this + * @return static $this */ public function castedUpdate($data) { @@ -1097,7 +1095,7 @@ public function castedUpdate($data) * Caution: Does not delete the merged object. * Caution: Does now overwrite Created date on the original object. * - * @param DataObject $rightObj + * @param static $rightObj Object to merge in * @param string $priority left|right Determines who wins in case of a conflict (optional) * @param bool $includeRelations Merge any existing relations (optional) * @param bool $overwriteWithEmpty Overwrite existing left values with empty right values. @@ -1151,7 +1149,6 @@ public function merge($rightObj, $priority = 'right', $includeRelations = true, if ($includeRelations) { if ($manyMany = $this->manyMany()) { foreach ($manyMany as $relationship => $class) { - /** @var DataObject $leftComponents */ $leftComponents = $leftObj->getManyManyComponents($relationship); $rightComponents = $rightObj->getManyManyComponents($relationship); if ($rightComponents && $rightComponents->exists()) { @@ -1263,7 +1260,7 @@ protected function onAfterWrite() * * @param bool $recursive True if recursive * @param ArrayList $list Optional list to add items to - * @return ArrayList list of objects + * @return ArrayList list of objects */ public function findCascadeDeletes($recursive = true, $list = null) { @@ -1303,7 +1300,7 @@ protected function onAfterDelete() * Called by the constructor when creating new records. * * @uses DataExtension::populateDefaults() - * @return DataObject $this + * @return static $this */ public function populateDefaults() { @@ -1654,7 +1651,7 @@ public function writeRelations() * * @param bool $recursive Recursively write components * @param array $skip List of DataObject references to skip - * @return DataObject $this + * @return static $this */ public function writeComponents($recursive = false, $skip = []) { @@ -2339,7 +2336,7 @@ public function database_extensions($class) * Generates a SearchContext to be used for building and processing * a generic search form for properties on this object. * - * @return SearchContext + * @return SearchContext */ public function getDefaultSearchContext() { @@ -3306,7 +3303,7 @@ public function getReverseAssociation($className) * @param string|array $limit A limit expression to be inserted into the LIMIT clause. * @param string $containerClass The container class to return the results in. * - * @return DataList The objects matching the filter, in the class specified by $containerClass + * @return DataList The objects matching the filter, in the class specified by $containerClass */ public static function get( $callerClass = null, @@ -3372,7 +3369,7 @@ public static function get( * @param boolean $cache Use caching * @param string|array|null $sort Passed to DataList::sort() so that DataList::first() returns the desired item * - * @return DataObject|null The first item matching the query + * @return static|null The first item matching the query */ public static function get_one($callerClass = null, $filter = "", $cache = true, $sort = "") { @@ -3423,7 +3420,7 @@ public static function get_one($callerClass = null, $filter = "", $cache = true, * * @param boolean $persistent When true will also clear persistent data stored in the Cache system. * When false will just clear session-local cached data - * @return DataObject $this + * @return static $this */ public function flushCache($persistent = true) { @@ -3524,7 +3521,7 @@ public function baseTable() /** * Get the base class for this object * - * @return string + * @return class-string */ public function baseClass() { @@ -4349,7 +4346,7 @@ public function setJoin(DataObject $object, $alias = null) * @param bool $recursive True if recursive * @param ArrayList $list If specified, items will be added to this list. If not, a new * instance of ArrayList will be constructed and returned - * @return ArrayList The list of related objects + * @return ArrayList The list of related objects */ public function findRelatedObjects($source, $recursive = true, $list = null) { @@ -4384,7 +4381,6 @@ public function findRelatedObjects($source, $recursive = true, $list = null) // Recurse if necessary if ($recursive) { foreach ($newItems as $item) { - /** @var DataObject $item */ $item->findRelatedObjects($source, true, $list); } } @@ -4397,8 +4393,8 @@ public function findRelatedObjects($source, $recursive = true, $list = null) * Items already present in the list will be skipped. * * @param ArrayList $list Items to merge into - * @param mixed $items List of new items to merge - * @return ArrayList List of all newly added items that did not already exist in $list + * @param iterable|DataObject|null $items List of new items to merge + * @return ArrayList List of all newly added items that did not already exist in $list */ public function mergeRelatedObjects($list, $items) { @@ -4410,7 +4406,6 @@ public function mergeRelatedObjects($list, $items) $items = [$items]; } - /** @var DataObject $item */ foreach ($items as $item) { $this->mergeRelatedObject($list, $added, $item); } @@ -4432,7 +4427,6 @@ public function mergeRelatedObjects($list, $items) */ public function getUniqueKey(): string { - /** @var UniqueKeyInterface $service */ $service = Injector::inst()->get(UniqueKeyInterface::class); $keyComponents = $this->getUniqueKeyComponents(); diff --git a/src/ORM/DataObjectSchema.php b/src/ORM/DataObjectSchema.php index c6e9cf449f2..ce77dc818a3 100644 --- a/src/ORM/DataObjectSchema.php +++ b/src/ORM/DataObjectSchema.php @@ -144,7 +144,7 @@ public function tableName($class) * * @param string|object $class * - * @return string + * @return class-string * @throws InvalidArgumentException */ public function baseDataClass($class) @@ -261,7 +261,7 @@ public function fieldSpec($classOrInstance, $fieldName, $options = 0) * * @param string $table * - * @return string|null The FQN of the class, or null if not found + * @return class-string|null The FQN of the class, or null if not found */ public function tableClass($table) { @@ -714,7 +714,7 @@ public function tableForField($candidateClass, $fieldName) * @param string $candidateClass * @param string $fieldName * - * @return string + * @return class-string|null */ public function classForField($candidateClass, $fieldName) { diff --git a/src/ORM/DataQuery.php b/src/ORM/DataQuery.php index 05692c3f720..6520c1cbf19 100644 --- a/src/ORM/DataQuery.php +++ b/src/ORM/DataQuery.php @@ -1054,7 +1054,6 @@ protected function joinHasManyRelation( } // Join table with associated has_one - /** @var DataObject $model */ $foreignKey = $schema->getRemoteJoinField($localClass, $localField, $type, $polymorphic); $localIDColumn = $schema->sqlColumnForField($localClass, 'ID', $localPrefix); if ($polymorphic) { diff --git a/src/ORM/EagerLoadedList.php b/src/ORM/EagerLoadedList.php index 6464aea8018..605d542152d 100644 --- a/src/ORM/EagerLoadedList.php +++ b/src/ORM/EagerLoadedList.php @@ -21,6 +21,13 @@ * * Note that when this list represents a relation, adding items to or removing items from this list will NOT * affect the underlying relation in the database. This list is read-only. + * + * @template T of DataObject + * @implements Relation + * @implements SS_List + * @implements Filterable + * @implements Sortable + * @implements Limitable */ class EagerLoadedList extends ViewableData implements Relation, SS_List, Filterable, Sortable, Limitable { @@ -28,11 +35,13 @@ class EagerLoadedList extends ViewableData implements Relation, SS_List, Filtera /** * List responsible for instantiating the actual DataObject objects from eager-loaded data + * @var DataList */ private DataList $dataList; /** * Underlying DataObject class for this list + * @var class-string */ private string $dataClass; @@ -65,6 +74,9 @@ class EagerLoadedList extends ViewableData implements Relation, SS_List, Filtera */ private array $manyManyComponent = []; + /** + * @param class-string $dataClass + */ public function __construct(string $dataClass, string $dataListClass, int|array|null $foreignID = null, array $manyManyComponent = []) { if (!is_a($dataListClass, DataList::class, true)) { @@ -144,6 +156,8 @@ public function addEagerLoadedData(string $relation, int $id, self|DataObject $d /** * Get the dataClass name for this list, ie the DataObject ClassName + * + * @return class-string */ public function dataClass(): string { @@ -179,6 +193,9 @@ public function forForeignID($id): void throw new BadMethodCallException("Can't change the foreign ID for an EagerLoadedList"); } + /** + * @return Traversable + */ public function getIterator(): Traversable { $limitedRows = $this->getFinalisedRows(); @@ -354,6 +371,8 @@ public function offsetExists(mixed $key): bool /** * Returns item stored in list with offset $key + * + * @return T|null */ public function offsetGet(mixed $key): ?DataObject { @@ -493,6 +512,8 @@ public function exclude(...$args): static /** * Return a copy of this list which does not contain any items with any of these params + * + * @return static */ public function excludeAny(...$args): static { @@ -509,6 +530,7 @@ public function excludeAny(...$args): static * Return a new instance of the list with an added filter * * @param array $filterArray + * @return static */ public function addFilter($filterArray): static { @@ -522,6 +544,7 @@ public function addFilter($filterArray): static * * The $list passed needs to contain the same dataclass as $this * + * @return static * @throws InvalidArgumentException */ public function subtract(DataList $list): static @@ -577,7 +600,6 @@ private function getMatches($filters, bool $any = false): array if (is_array($value) && empty($value)) { throw new InvalidArgumentException("Cannot filter $column against an empty set"); } - /** @var SearchFilter $searchFilter */ $searchFilter = $searchFilters[$column]; $extractedValue = $this->extractValue($row, $this->standardiseColumn($searchFilter->getFullName())); $doesMatch = $searchFilter->matches($extractedValue); @@ -612,6 +634,9 @@ private function extractValue(array $row, $key): mixed return null; } + /** + * @return ArrayList + */ public function filterByCallback($callback): ArrayList { if (!is_callable($callback)) { @@ -708,6 +733,8 @@ public function sort(...$args): static /** * Shuffle the items in this list + * + * @return static */ public function shuffle(): static { @@ -862,6 +889,7 @@ public function relation($relationName): ?Relation * At a minimum, $row['ID'] must be set. Unsaved records cannot be eager loaded. * * @param array $row + * @return T */ public function createDataObject($row): DataObject { diff --git a/src/ORM/Filterable.php b/src/ORM/Filterable.php index 55d64479e85..ce5196e4654 100644 --- a/src/ORM/Filterable.php +++ b/src/ORM/Filterable.php @@ -11,6 +11,9 @@ * @see SS_List * @see Sortable * @see Limitable + * + * @template T + * @extends SS_List */ interface Filterable extends SS_List { @@ -26,13 +29,14 @@ public function canFilterBy($by); /** * Return a new instance of this list that only includes items with these characteristics * - * @return Filterable * @example $list = $list->filter('Name', 'bob'); // only bob in the list * @example $list = $list->filter('Name', array('aziz', 'bob'); // aziz and bob in list * @example $list = $list->filter(array('Name'=>'bob, 'Age'=>21)); // bob with the age 21 * @example $list = $list->filter(array('Name'=>'bob, 'Age'=>array(21, 43))); // bob with the Age 21 or 43 * @example $list = $list->filter(array('Name'=>array('aziz','bob'), 'Age'=>array(21, 43))); * // aziz with the age 21 or 43 and bob with the Age 21 or 43 + * + * @return static */ public function filter(); @@ -56,20 +60,21 @@ public function filter(); * // SQL: WHERE (("Name" IN ('bob', 'phil')) OR ("Age" IN ('21', '43')) * * @param string|array See {@link filter()} - * @return static + * @return static */ public function filterAny(); /** * Return a new instance of this list that excludes any items with these characteristics * - * @return Filterable * @example $list = $list->exclude('Name', 'bob'); // exclude bob from list * @example $list = $list->exclude('Name', array('aziz', 'bob'); // exclude aziz and bob from list * @example $list = $list->exclude(array('Name'=>'bob, 'Age'=>21)); // exclude bob that has Age 21 * @example $list = $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // exclude bob with Age 21 or 43 * @example $list = $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43))); * // bob age 21 or 43, phil age 21 or 43 would be excluded + * + * @return static */ public function exclude(); @@ -80,7 +85,7 @@ public function exclude(); * * @example $list = $list->filterByCallback(function($item, $list) { return $item->Age == 9; }) * @param callable $callback - * @return Filterable + * @return SS_List */ public function filterByCallback($callback); @@ -88,7 +93,7 @@ public function filterByCallback($callback); * Return the first item with the given ID * * @param int $id - * @return mixed + * @return T|null */ public function byID($id); @@ -96,7 +101,7 @@ public function byID($id); * Filter this list to only contain the given Primary IDs * * @param array $ids Array of integers - * @return SS_List + * @return static */ public function byIDs($ids); } diff --git a/src/ORM/GroupedList.php b/src/ORM/GroupedList.php index 857637e3d3f..6fdd257d80d 100644 --- a/src/ORM/GroupedList.php +++ b/src/ORM/GroupedList.php @@ -7,6 +7,10 @@ /** * A list decorator that allows a list to be grouped into sub-lists by common * values of a field. + * + * @template TList + * @template T + * @extends ListDecorator */ class GroupedList extends ListDecorator { @@ -40,7 +44,7 @@ public function groupBy($index) * * @param string $index * @param string $children Name of the control under which children can be iterated on - * @return ArrayList + * @return ArrayList */ public function GroupedBy($index, $children = 'Children') { diff --git a/src/ORM/HasManyList.php b/src/ORM/HasManyList.php index a28abfadb79..88a5674d90b 100644 --- a/src/ORM/HasManyList.php +++ b/src/ORM/HasManyList.php @@ -6,6 +6,9 @@ /** * Subclass of {@link DataList} representing a has_many relation. + * + * @template T of DataObject + * @extends RelationList */ class HasManyList extends RelationList { @@ -21,7 +24,7 @@ class HasManyList extends RelationList * {@link DataList} methods. Addition arguments are used to support {@link add()} * and {@link remove()} methods. * - * @param string $dataClass The class of the DataObjects that this will list. + * @param class-string $dataClass The class of the DataObjects that this will list. * @param string $foreignKey The name of the foreign key field to set the ID filter against. */ public function __construct($dataClass, $foreignKey) @@ -43,7 +46,7 @@ public function getForeignKey() /** * @param null|int|array|string $id - * @return array + * @return array|null */ protected function foreignIDFilter($id = null) { diff --git a/src/ORM/Hierarchy/Hierarchy.php b/src/ORM/Hierarchy/Hierarchy.php index e1c4bb42fd5..41d5411fe86 100644 --- a/src/ORM/Hierarchy/Hierarchy.php +++ b/src/ORM/Hierarchy/Hierarchy.php @@ -23,8 +23,8 @@ * obvious example of this is SiteTree. * * @property int $ParentID - * @property DataObject|Hierarchy $owner * @method DataObject Parent() + * @extends DataExtension */ class Hierarchy extends DataExtension { @@ -119,7 +119,6 @@ public static function get_extra_config($class, $extension, $args) public function validate(ValidationResult $validationResult) { // The object is new, won't be looping. - /** @var DataObject|Hierarchy $owner */ $owner = $this->owner; if (!$owner->ID) { return; @@ -190,7 +189,7 @@ protected function loadDescendantIDListInto(&$idList, $node = null) /** * Get the children for this DataObject filtered by canView() * - * @return SS_List + * @return SS_List */ public function Children() { @@ -212,7 +211,7 @@ public function Children() /** * Return all children, including those 'not in menus'. * - * @return DataList + * @return DataList */ public function AllChildren() { @@ -226,7 +225,7 @@ public function AllChildren() * - Modified children will be marked as "ModifiedOnStage" * - Everything else has "SameOnStage" set, as an indicator that this information has been looked up. * - * @return ArrayList + * @return ArrayList */ public function AllChildrenIncludingDeleted() { @@ -252,7 +251,7 @@ public function AllChildrenIncludingDeleted() /** * Return all the children that this page had, including pages that were deleted from both stage & live. * - * @return DataList + * @return DataList * @throws Exception */ public function AllHistoricalChildren() @@ -293,7 +292,6 @@ public function numHistoricalChildren() */ public function numChildren($cache = true) { - $baseClass = $this->owner->baseClass(); $cacheType = 'numChildren'; $id = $this->owner->ID; @@ -355,7 +353,7 @@ public static function prepopulate_numchildren_cache($baseClass, $idList = null) return; } - /** @var Versioned|DataObject $singleton */ + /** @var DataObject&static $dummyObject */ $dummyObject = DataObject::singleton($baseClass); $baseTable = $dummyObject->baseTable(); @@ -431,11 +429,10 @@ private function getHierarchyBaseClass(): string * @param bool $showAll Include all of the elements, even those not shown in the menus. Only applicable when * extension is applied to {@link SiteTree}. * @param bool $skipParentIDFilter Set to true to suppress the ParentID and ID where statements. - * @return DataList + * @return DataList */ public function stageChildren($showAll = false, $skipParentIDFilter = false) { - /** @var DataObject|Hierarchy $owner */ $owner = $this->owner; $hideFromHierarchy = $owner->config()->hide_from_hierarchy; $hideFromCMSTree = $owner->config()->hide_from_cms_tree; @@ -477,7 +474,7 @@ public function stageChildren($showAll = false, $skipParentIDFilter = false) * @param bool $showAll Include all of the elements, even those not shown in the menus. Only * applicable when extension is applied to {@link SiteTree}. * @param bool $onlyDeletedFromStage Only return items that have been deleted from stage - * @return DataList + * @return DataList * @throws Exception */ public function liveChildren($showAll = false, $onlyDeletedFromStage = false) @@ -515,7 +512,7 @@ public function liveChildren($showAll = false, $onlyDeletedFromStage = false) * is returned. * * @param string $filter - * @return DataObject + * @return DataObject&static */ public function getParent($filter = null) { @@ -535,7 +532,7 @@ public function getParent($filter = null) * Return all the parents of this class in a set ordered from the closest to furtherest parent. * * @param bool $includeSelf - * @return ArrayList + * @return ArrayList */ public function getAncestors($includeSelf = false) { diff --git a/src/ORM/Hierarchy/MarkedSet.php b/src/ORM/Hierarchy/MarkedSet.php index 76a7d4e7921..18dc593fabd 100644 --- a/src/ORM/Hierarchy/MarkedSet.php +++ b/src/ORM/Hierarchy/MarkedSet.php @@ -187,7 +187,7 @@ public function getChildrenMethod() * Get children from this node * * @param DataObject $node - * @return SS_List + * @return SS_List */ protected function getChildren(DataObject $node) { @@ -453,7 +453,6 @@ public function markPartialTree() $nodeCountThreshold = $this->getNodeCountThreshold(); // Add root node, not-expanded by default - /** @var DataObject|Hierarchy $rootNode */ $rootNode = $this->rootNode; $this->clearMarks(); $this->markUnexpanded($rootNode); @@ -464,7 +463,6 @@ public function markPartialTree() $children = $this->markChildren($node); if ($nodeCountThreshold && sizeof($this->markedNodes ?? []) > $nodeCountThreshold) { // Undo marking children as opened since they're lazy loaded - /** @var DataObject|Hierarchy $child */ foreach ($children as $child) { $this->markClosed($child); } @@ -542,7 +540,7 @@ protected function markingFilterMatches(DataObject $node) * Mark all children of the given node that match the marking filter. * * @param DataObject $node Parent node - * @return array List of children marked by this operation + * @return array List of children marked by this operation */ protected function markChildren(DataObject $node) { diff --git a/src/ORM/Limitable.php b/src/ORM/Limitable.php index f30083272b1..4a2d37b3ad0 100644 --- a/src/ORM/Limitable.php +++ b/src/ORM/Limitable.php @@ -11,6 +11,9 @@ * @see SS_List * @see Sortable * @see Filterable + * + * @template T + * @implements SS_List */ interface Limitable extends SS_List { @@ -23,6 +26,7 @@ interface Limitable extends SS_List * If `$length` is null, then no limit is applied. If `$length` is 0, then an empty list is returned. * * @throws InvalidArgumentException if $length or offset are negative + * @return static */ public function limit(?int $length, int $offset = 0): Limitable; } diff --git a/src/ORM/ListDecorator.php b/src/ORM/ListDecorator.php index 5a682964a26..c7a465a03ad 100644 --- a/src/ORM/ListDecorator.php +++ b/src/ORM/ListDecorator.php @@ -10,15 +10,24 @@ * A base class for decorators that wrap around a list to provide additional * functionality. It passes through list methods to the underlying list * implementation. + * + * @template TList of SS_List&Sortable&Filterable&Limitable + * @template T + * @implements SS_List + * @implements Sortable + * @implements Filterable + * @implements Limitable */ abstract class ListDecorator extends ViewableData implements SS_List, Sortable, Filterable, Limitable { - /** - * @var SS_List + * @var TList */ protected SS_List&Sortable&Filterable&Limitable $list; + /** + * @param TList $list + */ public function __construct(SS_List&Sortable&Filterable&Limitable $list) { $this->setList($list); @@ -26,6 +35,9 @@ public function __construct(SS_List&Sortable&Filterable&Limitable $list) parent::__construct(); } + /** + * @return TList + */ public function getList(): SS_List&Sortable&Filterable&Limitable { return $this->list; @@ -37,7 +49,10 @@ public function getList(): SS_List&Sortable&Filterable&Limitable * Useful for keeping a decorator/paginated list configuration intact while modifying * the underlying list. * - * @return SS_List + * @template TListA + * @template TA + * @param TListA $list + * @return static */ public function setList(SS_List&Sortable&Filterable&Limitable $list): self { @@ -51,6 +66,9 @@ public function offsetExists(mixed $key): bool return $this->list->offsetExists($key); } + /** + * @return T + */ public function offsetGet(mixed $key): mixed { return $this->list->offsetGet($key); @@ -86,6 +104,9 @@ public function remove($itemObject) $this->list->remove($itemObject); } + /** + * @return Traversable + */ public function getIterator(): Traversable { return $this->list->getIterator(); @@ -106,6 +127,9 @@ public function last() return $this->list->last(); } + /** + * @return int + */ public function TotalItems() { return $this->list->count(); @@ -141,6 +165,9 @@ public function columnUnique($value = "ID") return $this->list->columnUnique($value); } + /** + * @return TList + */ public function each($callback) { return $this->list->each($callback); @@ -164,6 +191,8 @@ public function reverse() * @example $list->sort('Name DESC'); // DESC sorting * @example $list->sort('Name', 'ASC'); * @example $list->sort(array('Name'=>'ASC,'Age'=>'DESC')); + * + * @return TList */ public function sort() { @@ -182,6 +211,8 @@ public function canFilterBy($by) * @example $list->filter('Name', array('aziz', 'bob'); // aziz and bob in list * @example $list->filter(array('Name'=>'bob, 'Age'=>21)); // bob or someone with Age 21 * @example $list->filter(array('Name'=>'bob, 'Age'=>array(21, 43))); // bob or anyone with Age 21 or 43 + * + * @return TList */ public function filter() { @@ -208,7 +239,8 @@ public function filter() * // SQL: WHERE (("Name" IN ('bob', 'phil')) OR ("Age" IN ('21', '43')) * * @param string|array See {@link filter()} - * @return DataList + * + * @return TList */ public function filterAny() { @@ -222,7 +254,7 @@ public function filterAny() * * @example $list = $list->filterByCallback(function($item, $list) { return $item->Age == 9; }) * @param callable $callback - * @return ArrayList (this may change in future implementations) + * @return ArrayList */ public function filterByCallback($callback) { @@ -241,17 +273,14 @@ public function filterByCallback($callback) return $output; } + /** + * @return TList + */ public function limit(?int $length, int $offset = 0): SS_List&Sortable&Filterable&Limitable { return $this->list->limit($length, $offset); } - /** - * Return the first item with the given ID - * - * @param int $id - * @return mixed - */ public function byID($id) { return $this->list->byID($id); @@ -261,7 +290,8 @@ public function byID($id) * Filter this list to only contain the given Primary IDs * * @param array $ids Array of integers - * @return SS_List + * + * @return TList */ public function byIDs($ids) { @@ -275,6 +305,8 @@ public function byIDs($ids) * @example $list->exclude('Name', array('aziz', 'bob'); // exclude aziz and bob from list * @example $list->exclude(array('Name'=>'bob, 'Age'=>21)); // exclude bob or someone with Age 21 * @example $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // exclude bob or anyone with Age 21 or 43 + * + * @return TList */ public function exclude() { diff --git a/src/ORM/ManyManyList.php b/src/ORM/ManyManyList.php index a2aeb4ccf58..52fdfa2c011 100644 --- a/src/ORM/ManyManyList.php +++ b/src/ORM/ManyManyList.php @@ -9,9 +9,13 @@ use SilverStripe\ORM\FieldType\DBComposite; use InvalidArgumentException; use Exception; +use SilverStripe\ORM\FieldType\DBField; /** * Subclass of {@link DataList} representing a many_many relation. + * + * @template T of DataObject + * @extends RelationList */ class ManyManyList extends RelationList { @@ -50,7 +54,7 @@ class ManyManyList extends RelationList * the normal {@link DataList} methods. Addition arguments are used to * support {@link add()} and {@link remove()} methods. * - * @param string $dataClass The class of the DataObjects that this will list. + * @param class-string $dataClass The class of the DataObjects that this will list. * @param string $joinTable The name of the table whose entries define the content of this many_many relation. * @param string $localKey The key in the join table that maps to the dataClass' PK. * @param string $foreignKey The key in the join table that maps to joined class' PK. @@ -120,12 +124,6 @@ protected function appendExtraFieldsToQuery() $this->dataQuery->addSelectFromTable($this->joinTable, $finalized); } - /** - * Create a DataObject from the given SQL row. - * - * @param array $row - * @return DataObject - */ public function createDataObject($row) { // remove any composed fields @@ -165,8 +163,6 @@ public function createDataObject($row) * relationship for some foreign ID * * @param int|null|string|array $id - * - * @return array */ protected function foreignIDFilter($id = null) { @@ -285,7 +281,6 @@ public function add($item, $extraFields = []) ]; } - /** @var DBField[] $fieldObjects */ $fieldObjects = []; if ($extraFields && $this->extraFields) { // Write extra field to manipluation in the same way @@ -293,6 +288,7 @@ public function add($item, $extraFields = []) foreach ($this->extraFields as $fieldName => $fieldSpec) { // Skip fields without an assignment if (array_key_exists($fieldName, $extraFields ?? [])) { + /** @var DBField $fieldObject */ $fieldObject = Injector::inst()->create($fieldSpec, $fieldName); $fieldObject->setValue($extraFields[$fieldName]); $fieldObject->writeToManipulation($manipulation[$this->joinTable]); @@ -462,7 +458,6 @@ public function setExtraData(int $itemID, array $data): void ], ]; - /** @var DBField[] $fieldObjects */ $fieldObjects = []; // Write extra field to manipluation in the same way // that DataObject::prepareManipulationTable writes fields @@ -470,6 +465,7 @@ public function setExtraData(int $itemID, array $data): void if (!array_key_exists($fieldName, $this->extraFields)) { throw new InvalidArgumentException("Field '$fieldName' is not defined in many_many_extraFields for this relationship"); } + /** @var DBField $fieldObject */ $fieldObject = Injector::inst()->create($this->extraFields[$fieldName], $fieldName); // Make sure the field assignment is not an array unless the field allows non-scalar values if (is_array($value) && $fieldObject->scalarValueOnly()) { diff --git a/src/ORM/ManyManyThroughList.php b/src/ORM/ManyManyThroughList.php index a78d317ba73..0553de98c5e 100644 --- a/src/ORM/ManyManyThroughList.php +++ b/src/ORM/ManyManyThroughList.php @@ -9,6 +9,9 @@ /** * ManyManyList backed by a dataobject join table + * + * @template T of DataObject + * @extends RelationList */ class ManyManyThroughList extends RelationList { @@ -21,15 +24,15 @@ class ManyManyThroughList extends RelationList * Create a new ManyManyRelationList object. This relation will utilise an intermediary dataobject * as a join table, unlike ManyManyList which scaffolds a table automatically. * - * @param string $dataClass The class of the DataObjects that this will list. + * @example new ManyManyThroughList('Banner', 'PageBanner', 'BannerID', 'PageID'); + * + * @param class-string $dataClass The class of the DataObjects that this will list. * @param string $joinClass Class name of the joined dataobject record * @param string $localKey The key in the join table that maps to the dataClass' PK. * @param string $foreignKey The key in the join table that maps to joined class' PK. - * * @param array $extraFields Ignored for ManyManyThroughList * @param string $foreignClass 'from' class * @param string $parentClass Parent class (should be subclass of 'from') - * @example new ManyManyThroughList('Banner', 'PageBanner', 'BannerID', 'PageID'); */ public function __construct( $dataClass, @@ -55,10 +58,6 @@ public function __construct( /** * Don't apply foreign ID filter until getFinalisedQuery() - * - * @param array|integer $id (optional) An ID or an array of IDs - if not provided, will use the current ids as - * per getForeignID - * @return array Condition In array(SQL => parameters format) */ protected function foreignIDFilter($id = null) { @@ -134,7 +133,6 @@ public function removeByID($itemID) // Rather than simple un-associating the record (as in has_many list) // Delete the actual mapping row as many_many deletions behave. - /** @var DataObject $record */ foreach ($records as $record) { $record->delete(); } @@ -144,6 +142,9 @@ public function removeByID($itemID) } } + /** + * @return void + */ public function removeAll() { // Get the IDs of records in the current list @@ -216,7 +217,6 @@ public function add($item, $extraFields = []) $foreignKey = $this->manipulator->getForeignIDKey(); $hasManyList = $this->manipulator->getParentRelationship($this->dataQuery()); $records = $hasManyList->filter($localKey, $itemID); - /** @var DataObject $record */ foreach ($records as $record) { if ($extraFields) { foreach ($extraFields as $field => $value) { diff --git a/src/ORM/ManyManyThroughQueryManipulator.php b/src/ORM/ManyManyThroughQueryManipulator.php index 38bb9533274..54539528fd8 100644 --- a/src/ORM/ManyManyThroughQueryManipulator.php +++ b/src/ORM/ManyManyThroughQueryManipulator.php @@ -9,6 +9,8 @@ /** * Injected into DataQuery to augment getFinalisedQuery() with a join table + * + * @template TJoin of DataObject */ class ManyManyThroughQueryManipulator implements DataQueryManipulator { @@ -18,7 +20,7 @@ class ManyManyThroughQueryManipulator implements DataQueryManipulator /** * DataObject that backs the joining table * - * @var string + * @var class-string */ protected $joinClass; @@ -53,6 +55,10 @@ class ManyManyThroughQueryManipulator implements DataQueryManipulator /** * Build query manipulator for a given join table. Additional parameters (foreign key, etc) * will be inferred at evaluation from query parameters set via the ManyManyThroughList + * + * @param class-string $joinClass + * @param string $foreignClass + * @param string $parentClass */ public function __construct(string $joinClass, string $localKey, string $foreignKey, string $foreignClass, string $parentClass) { @@ -68,7 +74,7 @@ public function __construct(string $joinClass, string $localKey, string $foreign } /** - * @return string + * @return class-string */ public function getJoinClass() { @@ -76,7 +82,7 @@ public function getJoinClass() } /** - * @param mixed $joinClass + * @param class-string $joinClass * @return $this */ public function setJoinClass($joinClass) @@ -152,7 +158,7 @@ public function setForeignKey($foreignKey) * Get has_many relationship between parent and join table (for a given DataQuery) * * @param DataQuery $query - * @return HasManyList + * @return HasManyList */ public function getParentRelationship(DataQuery $query) { @@ -307,7 +313,7 @@ public function getParentClass() /** * @param string $parentClass - * @return ManyManyThroughQueryManipulator + * @return $this */ public function setParentClass($parentClass) { diff --git a/src/ORM/PaginatedList.php b/src/ORM/PaginatedList.php index 3da3f3a5756..99e7ebb818a 100644 --- a/src/ORM/PaginatedList.php +++ b/src/ORM/PaginatedList.php @@ -13,10 +13,13 @@ /** * A decorator that wraps around a data list in order to provide pagination. + * + * @template TList of SS_List + * @template T + * @extends ListDecorator */ class PaginatedList extends ListDecorator { - protected $request; protected $getVar = 'start'; @@ -28,7 +31,7 @@ class PaginatedList extends ListDecorator /** * Constructs a new paginated list instance around a list. * - * @param SS_List $list The list to paginate. The getRange method will + * @param TList $list The list to paginate. The getRange method will * be used to get the subset of objects to show. * @param array|ArrayAccess $request Either a map of request parameters or * request object that the pagination offset is read from. diff --git a/src/ORM/PolymorphicHasManyList.php b/src/ORM/PolymorphicHasManyList.php index 36f5b4fe69a..261209f6536 100644 --- a/src/ORM/PolymorphicHasManyList.php +++ b/src/ORM/PolymorphicHasManyList.php @@ -10,6 +10,10 @@ /** * Represents a has_many list linked against a polymorphic relationship. + * + * @template T of DataObject + * @template TForeign of DataObject + * @extends HasManyList */ class PolymorphicHasManyList extends HasManyList { @@ -30,7 +34,7 @@ class PolymorphicHasManyList extends HasManyList /** * Retrieve the name of the class this (has_many) relation is filtered by * - * @return string + * @return class-string */ public function getForeignClass() { @@ -80,10 +84,10 @@ public function getForeignRelationKey(): string /** * Create a new PolymorphicHasManyList relation list. * - * @param string $dataClass The class of the DataObjects that this will list. + * @param class-string $dataClass The class of the DataObjects that this will list. * @param string $foreignField The name of the composite foreign (has_one) relation field. Used * to generate the ID, Class, and Relation foreign keys. - * @param string $foreignClass Name of the class filter this relation is filtered against + * @param class-string $foreignClass Name of the class filter this relation is filtered against */ public function __construct($dataClass, $foreignField, $foreignClass) { @@ -104,13 +108,6 @@ public function __construct($dataClass, $foreignField, $foreignClass) )); } - /** - * Adds the item to this relation. - * - * It does so by setting the relationFilters. - * - * @param DataObject|int $item The DataObject to be added, or its ID - */ public function add($item) { if (is_numeric($item)) { @@ -155,12 +152,6 @@ public function add($item) $item->write(); } - /** - * Remove an item from this relation. - * Doesn't actually remove the item, it just clears the foreign key value. - * - * @param DataObject $item The DataObject to be removed - */ public function remove($item) { if (!($item instanceof $this->dataClass)) { diff --git a/src/ORM/Relation.php b/src/ORM/Relation.php index 47c2ffa4967..59fe4d0c4bd 100644 --- a/src/ORM/Relation.php +++ b/src/ORM/Relation.php @@ -12,6 +12,12 @@ * @method Relation relation($relationName) * @method Relation forForeignID($id) * @method string dataClass() + * + * @template T + * @extends SS_List + * @extends Filterable + * @extends Sortable + * @extends Limitable */ interface Relation extends SS_List, Filterable, Sortable, Limitable { @@ -20,7 +26,7 @@ interface Relation extends SS_List, Filterable, Sortable, Limitable * Sets the ComponentSet to be the given ID list. * Records will be added and deleted as appropriate. * - * @param array $idList List of IDs. + * @param array $idList List of IDs. */ public function setByIDList($idList); @@ -29,7 +35,7 @@ public function setByIDList($idList); * * Does not return the IDs for unsaved DataObjects * - * @return array + * @return array */ public function getIDList(); diff --git a/src/ORM/RelationList.php b/src/ORM/RelationList.php index dfcf8a3ea32..32f5d0fec2d 100644 --- a/src/ORM/RelationList.php +++ b/src/ORM/RelationList.php @@ -10,6 +10,10 @@ * A DataList that represents a relation. * * Adds the notion of a foreign ID that can be optionally set. + * + * @template T of DataObject + * @extends DataList + * @implements Relation */ abstract class RelationList extends DataList implements Relation { @@ -34,8 +38,6 @@ abstract class RelationList extends DataList implements Relation * every time they're called. * * Note that subclasses of RelationList must implement the callback for it to function - * - * @return this */ public function addCallbacks(): CallbackList { @@ -75,8 +77,6 @@ public function addCallbacks(): CallbackList * when adding records to this list. * * Subclasses of RelationList must implement the callback for it to function - * - * @return this */ public function removeCallbacks(): CallbackList { @@ -118,7 +118,7 @@ public function getQueryParams() * * @param int|array $id An ID or an array of IDs. * - * @return static + * @return static */ public function forForeignID($id) { diff --git a/src/ORM/SS_List.php b/src/ORM/SS_List.php index 854210478c3..2aa82783d3f 100644 --- a/src/ORM/SS_List.php +++ b/src/ORM/SS_List.php @@ -8,6 +8,10 @@ /** * An interface that a class can implement to be treated as a list container. + * + * @template T + * @extends ArrayAccess + * @extends IteratorAggregate */ interface SS_List extends ArrayAccess, Countable, IteratorAggregate { @@ -15,7 +19,7 @@ interface SS_List extends ArrayAccess, Countable, IteratorAggregate /** * Returns all the items in the list in an array. * - * @return array + * @return array */ public function toArray(); @@ -44,14 +48,14 @@ public function remove($item); /** * Returns the first item in the list. * - * @return mixed + * @return T|null */ public function first(); /** * Returns the last item in the list. * - * @return mixed + * @return T|null */ public function last(); @@ -71,7 +75,7 @@ public function map($keyfield = 'ID', $titlefield = 'Title'); * * @param string $key * @param mixed $value - * @return mixed + * @return T|null */ public function find($key, $value); @@ -87,7 +91,7 @@ public function column($colName = "ID"); * Walks the list using the specified callback * * @param callable $callback - * @return $this + * @return static */ public function each($callback); } diff --git a/src/ORM/Search/FulltextSearchable.php b/src/ORM/Search/FulltextSearchable.php index f37bf3189a5..1eeff1fd64b 100644 --- a/src/ORM/Search/FulltextSearchable.php +++ b/src/ORM/Search/FulltextSearchable.php @@ -20,7 +20,8 @@ * CAUTION: Will make all files in your /assets folder searchable by file name * unless "File" is excluded from FulltextSearchable::enable(). * - * @see http://doc.silverstripe.org/framework/en/tutorials/4-site-search + * @template T of SiteTree|File + * @extends DataExtension */ class FulltextSearchable extends DataExtension { diff --git a/src/ORM/Search/SearchContext.php b/src/ORM/Search/SearchContext.php index 24984236ca0..7cd78233177 100644 --- a/src/ORM/Search/SearchContext.php +++ b/src/ORM/Search/SearchContext.php @@ -42,6 +42,8 @@ * to include. * * @see http://doc.silverstripe.com/doku.php?id=searchcontext + * + * @template T of object */ class SearchContext { @@ -51,7 +53,7 @@ class SearchContext * DataObject subclass to which search parameters relate to. * Also determines as which object each result is provided. * - * @var string + * @var class-string */ protected $modelClass; @@ -84,7 +86,7 @@ class SearchContext * in the form of a $_REQUEST object. * CAUTION: All values should be treated as insecure client input. * - * @param string $modelClass The base {@link DataObject} class that search properties related to. + * @param class-string $modelClass The base {@link DataObject} class that search properties related to. * Also used to generate a set of result objects based on this class. * @param FieldList $fields Optional. FormFields mapping to {@link DataObject::$db} properties * which are to be searched. Derived from modelclass using @@ -144,7 +146,7 @@ protected function applyBaseTableFields() * Falls back to {@link DataObject::$default_sort} if not provided. * @param int|array|null $limit * @param DataList $existingQuery - * @return DataList + * @return DataList * @throws Exception */ public function getQuery($searchParams, $sort = false, $limit = false, $existingQuery = null) @@ -163,6 +165,7 @@ public function getQuery($searchParams, $sort = false, $limit = false, $existing /** * Perform a search on the passed DataList based on $this->searchParams. + * @return DataList */ private function search(DataList $query): DataList { @@ -185,6 +188,7 @@ private function search(DataList $query): DataList * * @param array|bool|string $sort Database column to sort on. * @param int|array|null $limit + * @return DataList */ private function prepareQuery($sort, $limit, ?DataList $existingQuery): DataList { @@ -248,6 +252,7 @@ private function generalSearchAcrossFields($searchPhrase, DataQuery $subGroup, a * Use the global general search for searching across multiple fields. * * @param string|array $searchPhrase + * @return DataList */ private function generalFieldSearch(DataList $query, array $searchableFields, $searchPhrase): DataList { @@ -293,6 +298,7 @@ private function getGeneralSearchFilter(string $modelClass, string $fieldName): * Search against a single field * * @param string|array $searchPhrase + * @return DataList */ private function individualFieldSearch(DataList $query, array $searchableFields, string $searchField, $searchPhrase): DataList { @@ -338,7 +344,7 @@ private function applyFilter(SearchFilter $filter, DataQuery $dataQuery, array $ * @param array $searchParams * @param array|bool|string $sort * @param array|null|string $limit - * @return DataList + * @return DataList * @throws Exception */ public function getResults($searchParams, $sort = false, $limit = null) @@ -365,7 +371,7 @@ public function clearEmptySearchFields($value) * Accessor for the filter attached to a named field. * * @param string $name - * @return SearchFilter + * @return SearchFilter|null */ public function getFilter($name) { @@ -389,7 +395,7 @@ public function getFilters() /** * Overwrite the current search context filter map. * - * @param array $filters + * @param SearchFilter[] $filters */ public function setFilters($filters) { @@ -486,7 +492,7 @@ public function getSearchParams() * for each field. Returns an ArrayList of ArrayData, suitable for * rendering on a template. * - * @return ArrayList + * @return ArrayList */ public function getSummary() { diff --git a/src/ORM/Sortable.php b/src/ORM/Sortable.php index 0f92a4076dd..07c9e92fc5a 100644 --- a/src/ORM/Sortable.php +++ b/src/ORM/Sortable.php @@ -11,6 +11,9 @@ * @see SS_List * @see Filterable * @see Limitable + * + * @template T + * @implements SS_List */ interface Sortable extends SS_List { @@ -27,11 +30,12 @@ public function canSortBy($by); * Return a new instance of this list that is sorted by one or more fields. You can either pass in a single * field name and direction, or a map of field names to sort directions. * - * @return static * @example $list = $list->sort('Name'); // default ASC sorting * @example $list = $list->sort('Name DESC'); // DESC sorting * @example $list = $list->sort('Name', 'ASC'); * @example $list = $list->sort(array('Name'=>'ASC,'Age'=>'DESC')); + * + * @return static */ public function sort(); @@ -39,8 +43,9 @@ public function sort(); /** * Return a new instance of this list based on reversing the current sort. * - * @return Sortable * @example $list = $list->reverse(); + * + * @return static */ public function reverse(); } diff --git a/src/ORM/UnsavedRelationList.php b/src/ORM/UnsavedRelationList.php index dc7ee697309..76218a5e55b 100644 --- a/src/ORM/UnsavedRelationList.php +++ b/src/ORM/UnsavedRelationList.php @@ -17,6 +17,10 @@ * It can store both saved objects (as IDs) or unsaved objects (as instances * of $dataClass). Unsaved objects are then written when the list is saved * into an instance of {@link RelationList}. + * + * @template T of DataObject + * @extends ArrayList + * @implements Relation */ class UnsavedRelationList extends ArrayList implements Relation { @@ -38,7 +42,7 @@ class UnsavedRelationList extends ArrayList implements Relation /** * The DataObject class name that this relation is querying * - * @var string + * @var class-string */ protected $dataClass; @@ -54,7 +58,7 @@ class UnsavedRelationList extends ArrayList implements Relation * * @param string $baseClass * @param string $relationName - * @param string $dataClass The DataObject class used in the relation + * @param class-string $dataClass The DataObject class used in the relation */ public function __construct($baseClass, $relationName, $dataClass) { @@ -112,7 +116,7 @@ public function push($item, $extraFields = null) /** * Get the dataClass name for this relation, ie the DataObject ClassName * - * @return string + * @return class-string */ public function dataClass() { @@ -130,8 +134,6 @@ public function getIterator(): Traversable /** * Return an array of the actual items that this relation contains at this stage. * This is when the query is actually executed. - * - * @return array */ public function toArray() { @@ -209,8 +211,6 @@ public function setByIDList($idList) * Returns an array with both the keys and values set to the IDs of the records in this list. * Does not respect sort order. Use ->column("ID") to get an ID list with the current sort. * Does not return the IDs for unsaved DataObjects. - * - * @return array */ public function getIDList() { @@ -230,11 +230,6 @@ public function getIDList() return $ids; } - /** - * Returns the first item in the list - * - * @return mixed - */ public function first() { $item = reset($this->items) ?: null; @@ -247,11 +242,6 @@ public function first() return $item; } - /** - * Returns the last item in the list - * - * @return mixed - */ public function last() { $item = end($this->items) ?: null; @@ -291,7 +281,7 @@ public function columnUnique($colName = "ID") /** * Returns a copy of this list with the relationship linked to the given foreign ID. * @param int|array $id An ID or an array of IDs. - * @return Relation + * @return Relation */ public function forForeignID($id) { diff --git a/src/Security/BasicAuth.php b/src/Security/BasicAuth.php index 8dcf688a998..9c47c1f1d6c 100644 --- a/src/Security/BasicAuth.php +++ b/src/Security/BasicAuth.php @@ -96,7 +96,6 @@ public static function requireLogin( try { if ($request->getHeader('PHP_AUTH_USER') && $request->getHeader('PHP_AUTH_PW')) { - /** @var MemberAuthenticator $authenticator */ $authenticators = Security::singleton()->getApplicableAuthenticators(Authenticator::LOGIN); foreach ($authenticators as $name => $authenticator) { diff --git a/src/Security/DefaultAdminService.php b/src/Security/DefaultAdminService.php index 587b88c501d..f7b98d9487c 100644 --- a/src/Security/DefaultAdminService.php +++ b/src/Security/DefaultAdminService.php @@ -152,7 +152,6 @@ public function findOrCreateAdmin($email, $name = null) $this->extend('beforeFindOrCreateAdmin', $email, $name); // Find member - /** @var Member $admin */ $admin = Member::get() ->filter('Email', $email) ->first(); diff --git a/src/Security/Group.php b/src/Security/Group.php index 06b283d395c..cfc5a8098d5 100755 --- a/src/Security/Group.php +++ b/src/Security/Group.php @@ -97,7 +97,6 @@ public function getAllChildren() $doSet = new ArrayList(); $children = Group::get()->filter("ParentID", $this->ID); - /** @var Group $child */ foreach ($children as $child) { $doSet->push($child); $doSet->merge($child->getAllChildren()); @@ -165,12 +164,10 @@ public function getCMSFields() $config->removeComponentsByType(GridFieldDeleteAction::class); $config->addComponent(GridFieldGroupDeleteAction::create($this->ID), GridFieldPageCount::class); - /** @var GridFieldAddExistingAutocompleter $autocompleter */ $autocompleter = $config->getComponentByType(GridFieldAddExistingAutocompleter::class); $autocompleter ->setResultsFormat('$Title ($Email)') ->setSearchFields(['FirstName', 'Surname', 'Email']); - /** @var GridFieldDetailForm $detailForm */ $detailForm = $config->getComponentByType(GridFieldDetailForm::class); $detailForm ->setItemEditFormCallback(function ($form) use ($group) { @@ -307,7 +304,7 @@ public function fieldLabels($includerelations = true) * See {@link DirectMembers()} for retrieving members without any inheritance. * * @param string $filter - * @return ManyManyList + * @return ManyManyList */ public function Members($filter = '') { @@ -338,6 +335,7 @@ public function Members($filter = '') /** * Return only the members directly added to this group + * @return ManyManyList */ public function DirectMembers() { @@ -650,7 +648,7 @@ public function canDelete($member = null) * Returns all of the children for the CMS Tree. * Filters to only those groups that the current user can edit * - * @return ArrayList + * @return ArrayList */ public function AllChildrenIncludingDeleted() { diff --git a/src/Security/InheritedPermissionFlusher.php b/src/Security/InheritedPermissionFlusher.php index cdd3922ffcc..d4aa344e4a4 100644 --- a/src/Security/InheritedPermissionFlusher.php +++ b/src/Security/InheritedPermissionFlusher.php @@ -8,6 +8,9 @@ use SilverStripe\ORM\DataObject; use SilverStripe\Core\Cache\MemberCacheFlusher; +/** + * @extends DataExtension + */ class InheritedPermissionFlusher extends DataExtension implements Flushable { /** diff --git a/src/Security/InheritedPermissions.php b/src/Security/InheritedPermissions.php index 9cd9dfd90e1..bcaa1f6b654 100644 --- a/src/Security/InheritedPermissions.php +++ b/src/Security/InheritedPermissions.php @@ -417,7 +417,6 @@ protected function batchPermissionCheckForStage( ->execute(); foreach ($potentiallyInherited as $item) { - /** @var DataObject|Hierarchy $item */ if ($item['ParentID']) { if (!isset($groupedByParent[$item['ParentID']])) { $groupedByParent[$item['ParentID']] = []; diff --git a/src/Security/InheritedPermissionsExtension.php b/src/Security/InheritedPermissionsExtension.php index 5240246c7f2..2b2432d3d1c 100644 --- a/src/Security/InheritedPermissionsExtension.php +++ b/src/Security/InheritedPermissionsExtension.php @@ -14,6 +14,8 @@ * @method ManyManyList EditorMembers() * @method ManyManyList ViewerGroups() * @method ManyManyList ViewerMembers() + * + * @extends DataExtension */ class InheritedPermissionsExtension extends DataExtension { diff --git a/src/Security/LoginAttempt.php b/src/Security/LoginAttempt.php index 4ffda5c7616..9ff1b31ce4e 100644 --- a/src/Security/LoginAttempt.php +++ b/src/Security/LoginAttempt.php @@ -81,7 +81,7 @@ public function setEmail($email) * Get all login attempts for the given email address * * @param string $email - * @return DataList|LoginAttempt[] + * @return DataList */ public static function getByEmail($email) { diff --git a/src/Security/LoginForm.php b/src/Security/LoginForm.php index 248b80851b9..ddc720df5ec 100644 --- a/src/Security/LoginForm.php +++ b/src/Security/LoginForm.php @@ -34,7 +34,6 @@ public function setAuthenticatorClass($class) { $this->authenticatorClass = $class; - /** @var FieldList|null $fields */ $fields = $this->Fields(); if (!$fields) { return $this; diff --git a/src/Security/Member.php b/src/Security/Member.php index 079bd32eb3e..023b96caa5d 100644 --- a/src/Security/Member.php +++ b/src/Security/Member.php @@ -584,7 +584,6 @@ public function validateAutoLoginToken($autologinToken) */ public static function member_from_autologinhash($hash, $login = false) { - /** @var Member $member */ $member = static::get()->filter([ 'AutoLoginHash' => $hash, 'AutoLoginExpired:GreaterThan' => DBDatetime::now()->getValue(), @@ -610,7 +609,6 @@ public static function member_from_tempid($tempid) // Exclude expired if (static::config()->get('temp_id_lifetime')) { - /** @var DataList|Member[] $members */ $members = $members->filter('TempIDExpired:GreaterThan', DBDatetime::now()->getValue()); } @@ -657,7 +655,6 @@ public function getMemberPasswordField() $label = $editingPassword ? _t(__CLASS__ . '.EDIT_PASSWORD', 'New Password') : $this->fieldLabel('Password'); - /** @var ConfirmedPasswordField $password */ $password = ConfirmedPasswordField::create( 'Password', $label, @@ -1176,7 +1173,7 @@ public function Groups() } /** - * @return ManyManyList|UnsavedRelationList + * @return ManyManyList|UnsavedRelationList */ public function DirectGroups() { @@ -1212,7 +1209,6 @@ public static function map_in_groups($groups = null) $membersList = new ArrayList(); // This is a bit ineffective, but follow the ORM style - /** @var Group $group */ foreach (Group::get()->byIDs($groupIDList) as $group) { $membersList->merge($group->Members()); } @@ -1332,7 +1328,6 @@ public function getCMSFields() $rootTabSet = $fields->fieldByName("Root"); /** @var Tab $mainTab */ $mainTab = $rootTabSet->fieldByName("Main"); - /** @var FieldList $mainFields */ $mainFields = $mainTab->getChildren(); // Build change password field diff --git a/src/Security/MemberAuthenticator/ChangePasswordHandler.php b/src/Security/MemberAuthenticator/ChangePasswordHandler.php index b2330f5b23f..5aefa310e38 100644 --- a/src/Security/MemberAuthenticator/ChangePasswordHandler.php +++ b/src/Security/MemberAuthenticator/ChangePasswordHandler.php @@ -66,7 +66,6 @@ public function changepassword() $request = $this->getRequest(); // Extract the member from the URL. - /** @var Member $member */ $member = null; if ($request->getVar('m') !== null) { $member = Member::get()->filter(['ID' => (int)$request->getVar('m')])->first(); @@ -153,7 +152,6 @@ protected function setSessionToken($member, $token) { // if there is a current member, they should be logged out if ($curMember = Security::getCurrentUser()) { - /** @var LogoutHandler $handler */ Injector::inst()->get(IdentityStore::class)->logOut(); } @@ -275,7 +273,6 @@ public function doChangePassword(array $data, $form) $member->write(); if ($member->canLogin()) { - /** @var IdentityStore $identityStore */ $identityStore = Injector::inst()->get(IdentityStore::class); $identityStore->logIn($member, false, $this->getRequest()); } diff --git a/src/Security/MemberAuthenticator/CookieAuthenticationHandler.php b/src/Security/MemberAuthenticator/CookieAuthenticationHandler.php index 677de47108b..1029e0a4052 100644 --- a/src/Security/MemberAuthenticator/CookieAuthenticationHandler.php +++ b/src/Security/MemberAuthenticator/CookieAuthenticationHandler.php @@ -145,7 +145,6 @@ public function authenticateRequest(HTTPRequest $request) } // check if autologin token matches - /** @var Member $member */ $member = Member::get()->byID($uid); if (!$member) { return null; @@ -153,7 +152,6 @@ public function authenticateRequest(HTTPRequest $request) $hash = $member->encryptWithUserSettings($token); - /** @var RememberLoginHash $rememberLoginHash */ $rememberLoginHash = RememberLoginHash::get() ->filter([ 'MemberID' => $member->ID, diff --git a/src/Security/MemberAuthenticator/LoginHandler.php b/src/Security/MemberAuthenticator/LoginHandler.php index 14b83f3d3eb..db672e11c46 100644 --- a/src/Security/MemberAuthenticator/LoginHandler.php +++ b/src/Security/MemberAuthenticator/LoginHandler.php @@ -115,7 +115,6 @@ public function doLogin($data, MemberLoginForm $form, HTTPRequest $request) $this->extend('beforeLogin'); // Successful login - /** @var ValidationResult $result */ if ($member = $this->checkLogin($data, $request, $result)) { $this->performLogin($member, $data, $request); // Allow operations on the member after successful login @@ -241,7 +240,6 @@ public function performLogin($member, $data, HTTPRequest $request) { /** IdentityStore */ $rememberMe = (isset($data['Remember']) && Security::config()->get('autologin_enabled')); - /** @var IdentityStore $identityStore */ $identityStore = Injector::inst()->get(IdentityStore::class); $identityStore->logIn($member, $rememberMe, $request); diff --git a/src/Security/MemberAuthenticator/LostPasswordHandler.php b/src/Security/MemberAuthenticator/LostPasswordHandler.php index f5cb4538d96..41d3718b210 100644 --- a/src/Security/MemberAuthenticator/LostPasswordHandler.php +++ b/src/Security/MemberAuthenticator/LostPasswordHandler.php @@ -165,7 +165,6 @@ public function forgotPassword(array $data, Form $form): HTTPResponse return $dataValidation; } - /** @var Member $member */ $member = $this->getMemberFromData($data); // Allow vetoing forgot password requests @@ -241,7 +240,6 @@ protected function getMemberFromData(array $data) protected function sendEmail($member, $token) { try { - /** @var Email $email */ $email = Email::create() ->setHTMLTemplate('SilverStripe\\Control\\Email\\ForgotPasswordEmail') ->setData($member) diff --git a/src/Security/MemberAuthenticator/MemberAuthenticator.php b/src/Security/MemberAuthenticator/MemberAuthenticator.php index 6c2d83ecbf5..29ed27a17e8 100644 --- a/src/Security/MemberAuthenticator/MemberAuthenticator.php +++ b/src/Security/MemberAuthenticator/MemberAuthenticator.php @@ -90,7 +90,6 @@ protected function authenticateMember($data, ValidationResult &$result = null, M if (!$member && $email) { // Find user by email $identifierField = Member::config()->get('unique_identifier_field'); - /** @var Member $member */ $member = Member::get() ->filter([$identifierField => $email]) ->first(); diff --git a/src/Security/MemberAuthenticator/SessionAuthenticationHandler.php b/src/Security/MemberAuthenticator/SessionAuthenticationHandler.php index 5dec89702a3..252bb749315 100644 --- a/src/Security/MemberAuthenticator/SessionAuthenticationHandler.php +++ b/src/Security/MemberAuthenticator/SessionAuthenticationHandler.php @@ -62,7 +62,6 @@ public function authenticateRequest(HTTPRequest $request) if (!$id) { return null; } - /** @var Member $member */ $member = DataObject::get_by_id(Member::class, $id); return $member; } @@ -86,7 +85,6 @@ public function logIn(Member $member, $persistent = false, HTTPRequest $request // Activate sudo mode on login so the user doesn't have to reauthenticate for sudo // actions until the sudo mode timeout expires - /** @var SudoModeServiceInterface $service */ $service = Injector::inst()->get(SudoModeServiceInterface::class); $service->activate($session); } diff --git a/src/Security/Member_GroupSet.php b/src/Security/Member_GroupSet.php index 10d134b4aaa..c50afc1bdf6 100644 --- a/src/Security/Member_GroupSet.php +++ b/src/Security/Member_GroupSet.php @@ -11,6 +11,8 @@ /** * Represents a set of Groups attached to a member. * Handles the hierarchy logic. + * + * @extends ManyManyList */ class Member_GroupSet extends ManyManyList { diff --git a/src/Security/PasswordValidator.php b/src/Security/PasswordValidator.php index 776709aaaed..17971187762 100644 --- a/src/Security/PasswordValidator.php +++ b/src/Security/PasswordValidator.php @@ -227,7 +227,6 @@ public function validate($password, $member) ->where(['"MemberPassword"."MemberID"' => $member->ID]) ->sort('"Created" DESC, "ID" DESC') ->limit($historicCount); - /** @var MemberPassword $previousPassword */ foreach ($previousPasswords as $previousPassword) { if ($previousPassword->checkPassword($password)) { $error = _t( diff --git a/src/Security/PermissionCheckboxSetField.php b/src/Security/PermissionCheckboxSetField.php index 8c82e0464eb..252cd9af1cb 100644 --- a/src/Security/PermissionCheckboxSetField.php +++ b/src/Security/PermissionCheckboxSetField.php @@ -127,7 +127,6 @@ public function Field($properties = []) // Get all permissions from roles if ($record->Roles()->count()) { foreach ($record->Roles() as $role) { - /** @var PermissionRole $role */ foreach ($role->Codes() as $code) { if (!isset($inheritedCodes[$code->Code])) { $inheritedCodes[$code->Code] = []; diff --git a/src/Security/RememberLoginHash.php b/src/Security/RememberLoginHash.php index 6733b3190bb..27f9f345bad 100644 --- a/src/Security/RememberLoginHash.php +++ b/src/Security/RememberLoginHash.php @@ -169,7 +169,6 @@ public static function generate(Member $member) if (static::config()->force_single_token) { RememberLoginHash::get()->filter('MemberID', $member->ID)->removeAll(); } - /** @var RememberLoginHash $rememberLoginHash */ $rememberLoginHash = RememberLoginHash::create(); do { $deviceID = $rememberLoginHash->getNewDeviceID(); diff --git a/src/Security/RequestAuthenticationHandler.php b/src/Security/RequestAuthenticationHandler.php index 12994491b33..20db10a4db1 100644 --- a/src/Security/RequestAuthenticationHandler.php +++ b/src/Security/RequestAuthenticationHandler.php @@ -38,7 +38,6 @@ public function setHandlers(array $handlers) public function authenticateRequest(HTTPRequest $request) { - /** @var AuthenticationHandler $handler */ foreach ($this->getHandlers() as $name => $handler) { // in order to add cookies, etc $member = $handler->authenticateRequest($request); diff --git a/src/Security/Security.php b/src/Security/Security.php index 82bfb5bc888..eea203ba479 100644 --- a/src/Security/Security.php +++ b/src/Security/Security.php @@ -253,7 +253,6 @@ public function getApplicableAuthenticators($service = Authenticator::LOGIN) { $authenticators = $this->getAuthenticators(); - /** @var Authenticator $authenticator */ foreach ($authenticators as $name => $authenticator) { if (!($authenticator->supportedServices() & $service)) { unset($authenticators[$name]); @@ -937,7 +936,6 @@ public function lostpassword() { $handlers = []; $authenticators = $this->getApplicableAuthenticators(Authenticator::RESET_PASSWORD); - /** @var Authenticator $authenticator */ foreach ($authenticators as $authenticator) { $handlers[] = $authenticator->getLostPasswordHandler( Controller::join_links($this->Link(), 'lostpassword') @@ -966,7 +964,6 @@ public function lostpassword() */ public function changepassword() { - /** @var array|Authenticator[] $authenticators */ $authenticators = $this->getApplicableAuthenticators(Authenticator::CHANGE_PASSWORD); $handlers = []; foreach ($authenticators as $authenticator) { diff --git a/src/View/GenericTemplateGlobalProvider.php b/src/View/GenericTemplateGlobalProvider.php index 0d126ade948..8971ab0ae6e 100644 --- a/src/View/GenericTemplateGlobalProvider.php +++ b/src/View/GenericTemplateGlobalProvider.php @@ -47,8 +47,9 @@ public static function ModulePath($name) * <% end_cached %> * * - * @param string $className - * @return DataList + * @template T of DataObject + * @param class-string $className + * @return DataList */ public static function getDataList($className) { diff --git a/src/View/Parsers/ShortcodeParser.php b/src/View/Parsers/ShortcodeParser.php index ed1cb858d9c..1032c862af0 100644 --- a/src/View/Parsers/ShortcodeParser.php +++ b/src/View/Parsers/ShortcodeParser.php @@ -619,7 +619,6 @@ protected function replaceMarkerWithContent($node, $tag) $content = $this->getShortcodeReplacementText($tag); if ($content) { - /** @var HTMLValue $parsed */ $parsed = HTMLValue::create($content); $body = $parsed->getBody(); if ($body) { @@ -658,7 +657,6 @@ public function parse($content) // use a proper DOM list($content, $tags) = $this->replaceElementTagsWithMarkers($content); - /** @var HTMLValue $htmlvalue */ $htmlvalue = Injector::inst()->create(HTMLValue::class, $content); // Now parse the result into a DOM @@ -681,7 +679,7 @@ public function parse($content) // Find the parents. Do this before DOM modification, since SPLIT might cause parents to move otherwise $parents = $this->findParentsForMarkers($shortcodes); - /** @var DOMElement $shortcode */ + /** @var DOMElement $shortcode */ foreach ($shortcodes as $shortcode) { $tag = $tags[$shortcode->getAttribute('data-tagid')]; $parent = $parents[$shortcode->getAttribute('data-parentid')]; diff --git a/src/View/Shortcodes/EmbedShortcodeProvider.php b/src/View/Shortcodes/EmbedShortcodeProvider.php index 75c3cdb1369..58aefc2c3b9 100644 --- a/src/View/Shortcodes/EmbedShortcodeProvider.php +++ b/src/View/Shortcodes/EmbedShortcodeProvider.php @@ -242,7 +242,7 @@ protected static function photoEmbed($arguments, $src) * * @param array $arguments List of embed arguments * @param array $exclude List of attribute names to exclude from the resulting list - * @return ArrayList + * @return ArrayList */ private static function buildAttributeListFromArguments(array $arguments, array $exclude = []): ArrayList { diff --git a/src/View/ViewableData.php b/src/View/ViewableData.php index 31f621b5e58..f5f19ec8c0f 100644 --- a/src/View/ViewableData.php +++ b/src/View/ViewableData.php @@ -18,6 +18,7 @@ use SilverStripe\Core\Injector\Injectable; use SilverStripe\Core\Injector\Injector; use SilverStripe\Dev\Debug; +use SilverStripe\Dev\Deprecation; use SilverStripe\ORM\ArrayLib; use SilverStripe\ORM\FieldType\DBField; use SilverStripe\ORM\FieldType\DBHTMLText; @@ -644,10 +645,13 @@ public function getXMLValues($fields) * This is useful so you can use a single record inside a <% control %> block in a template - and then use * to access individual fields on this object. * + * @deprecated 5.2.0 Will be removed without equivalent functionality + * * @return ArrayIterator */ public function getIterator(): Traversable { + Deprecation::notice('5.2.0', 'Will be removed without equivalent functionality'); return new ArrayIterator([$this]); } diff --git a/src/includes/functions.php b/src/includes/functions.php index 8a6d3e6c7db..86c93de0950 100644 --- a/src/includes/functions.php +++ b/src/includes/functions.php @@ -15,8 +15,9 @@ * way to access instance methods which don't rely on instance * data (e.g. the custom SilverStripe static handling). * - * @param string $className - * @return mixed + * @template T of object + * @param class-string $className + * @return T|mixed */ function singleton($className) { diff --git a/tests/php/Dev/SSListContainsOnlyMatchingItemsTest.php b/tests/php/Dev/SSListContainsOnlyMatchingItemsTest.php index 0bdf72821cf..a1824ef7b88 100644 --- a/tests/php/Dev/SSListContainsOnlyMatchingItemsTest.php +++ b/tests/php/Dev/SSListContainsOnlyMatchingItemsTest.php @@ -18,7 +18,7 @@ public function testEvaluateListMatchesCorrectly() } /** - * @return ArrayList|Member[] + * @return ArrayList */ private function getListToMatch() { diff --git a/tests/php/Dev/SSListContainsOnlyTest.php b/tests/php/Dev/SSListContainsOnlyTest.php index e1943c6290d..bd3110f842f 100644 --- a/tests/php/Dev/SSListContainsOnlyTest.php +++ b/tests/php/Dev/SSListContainsOnlyTest.php @@ -62,7 +62,7 @@ public function testEvaluateListMatchesCorrectly($matches) } /** - * @return ArrayList|Member[] + * @return ArrayList */ private function getListToMatch() { diff --git a/tests/php/Dev/SSListContainsTest.php b/tests/php/Dev/SSListContainsTest.php index 6173e9c4855..6d9a28ba1f9 100644 --- a/tests/php/Dev/SSListContainsTest.php +++ b/tests/php/Dev/SSListContainsTest.php @@ -77,7 +77,7 @@ public function testEvaluateListDoesNotMatchWrongMatches($matches) } /** - * @return ArrayList|Member[] + * @return ArrayList */ private function getListToMatch() {