From 787c36201072efeab07dff480c9329d4f0e98e73 Mon Sep 17 00:00:00 2001 From: Demian Katz Date: Thu, 5 Sep 2024 15:19:56 -0400 Subject: [PATCH 1/5] Use local password hash service instead of laminas-crypt. (#3888) --- module/VuFind/config/module.config.php | 1 + module/VuFind/src/VuFind/Auth/Database.php | 25 ++++-- .../src/VuFind/Auth/DatabaseFactory.php | 73 +++++++++++++++ .../VuFind/src/VuFind/Auth/PluginManager.php | 4 +- .../VuFind/Controller/InstallController.php | 11 +-- .../src/VuFind/Crypt/PasswordHasher.php | 90 +++++++++++++++++++ 6 files changed, 191 insertions(+), 13 deletions(-) create mode 100644 module/VuFind/src/VuFind/Auth/DatabaseFactory.php create mode 100644 module/VuFind/src/VuFind/Crypt/PasswordHasher.php diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php index 9a74716244e..69508443e7f 100644 --- a/module/VuFind/config/module.config.php +++ b/module/VuFind/config/module.config.php @@ -436,6 +436,7 @@ 'VuFind\Cover\Loader' => 'VuFind\Cover\LoaderFactory', 'VuFind\Cover\Router' => 'VuFind\Cover\RouterFactory', 'VuFind\Crypt\HMAC' => 'VuFind\Crypt\HMACFactory', + 'VuFind\Crypt\PasswordHasher' => 'Laminas\ServiceManager\Factory\InvokableFactory', 'VuFind\Crypt\SecretCalculator' => 'VuFind\Crypt\SecretCalculatorFactory', 'VuFind\Date\Converter' => 'VuFind\Service\DateConverterFactory', 'VuFind\Db\AdapterFactory' => 'VuFind\Service\ServiceWithConfigIniFactory', diff --git a/module/VuFind/src/VuFind/Auth/Database.php b/module/VuFind/src/VuFind/Auth/Database.php index aba9bb09854..e342afe4f7b 100644 --- a/module/VuFind/src/VuFind/Auth/Database.php +++ b/module/VuFind/src/VuFind/Auth/Database.php @@ -31,8 +31,8 @@ namespace VuFind\Auth; -use Laminas\Crypt\Password\Bcrypt; use Laminas\Http\PhpEnvironment\Request; +use VuFind\Crypt\PasswordHasher; use VuFind\Db\Entity\UserEntityInterface; use VuFind\Db\Service\UserServiceInterface; use VuFind\Exception\Auth as AuthException; @@ -54,6 +54,13 @@ */ class Database extends AbstractBase { + /** + * Password hasher + * + * @var PasswordHasher + */ + protected $hasher; + /** * Username * @@ -68,6 +75,16 @@ class Database extends AbstractBase */ protected $password; + /** + * Constructor + * + * @param ?PasswordHasher $hasher Password hash service (null to create one) + */ + public function __construct(?PasswordHasher $hasher = null) + { + $this->hasher = $hasher ?? new PasswordHasher(); + } + /** * Attempt to authenticate the current user. Throws exception if login fails. * @@ -121,8 +138,7 @@ protected function passwordHashingEnabled() protected function setUserPassword(UserEntityInterface $user, string $pass): void { if ($this->passwordHashingEnabled()) { - $bcrypt = new Bcrypt(); - $user->setPasswordHash($bcrypt->create($pass)); + $user->setPasswordHash($this->hasher->create($pass)); } else { $user->setRawPassword($pass); } @@ -300,8 +316,7 @@ protected function checkPassword($password, $userRow) ); } - $bcrypt = new Bcrypt(); - return $bcrypt->verify($password, $userRow->getPasswordHash() ?? ''); + return $this->hasher->verify($password, $userRow->getPasswordHash() ?? ''); } // Default case: unencrypted passwords: diff --git a/module/VuFind/src/VuFind/Auth/DatabaseFactory.php b/module/VuFind/src/VuFind/Auth/DatabaseFactory.php new file mode 100644 index 00000000000..a8e0d0af016 --- /dev/null +++ b/module/VuFind/src/VuFind/Auth/DatabaseFactory.php @@ -0,0 +1,73 @@ + + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ + +namespace VuFind\Auth; + +use Laminas\ServiceManager\Exception\ServiceNotCreatedException; +use Laminas\ServiceManager\Exception\ServiceNotFoundException; +use Psr\Container\ContainerExceptionInterface as ContainerException; +use Psr\Container\ContainerInterface; +use VuFind\Crypt\PasswordHasher; + +/** + * Factory for Database authentication module. + * + * @category VuFind + * @package Authentication + * @author Demian Katz + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class DatabaseFactory implements \Laminas\ServiceManager\Factory\FactoryInterface +{ + /** + * Create an object + * + * @param ContainerInterface $container Service manager + * @param string $requestedName Service being created + * @param null|array $options Extra options (optional) + * + * @return object + * + * @throws ServiceNotFoundException if unable to resolve the service. + * @throws ServiceNotCreatedException if an exception is raised when + * creating a service. + * @throws ContainerException&\Throwable if any other error occurs + */ + public function __invoke( + ContainerInterface $container, + $requestedName, + array $options = null + ) { + if (!empty($options)) { + throw new \Exception('Unexpected options sent to factory.'); + } + return new $requestedName($container->get(PasswordHasher::class)); + } +} diff --git a/module/VuFind/src/VuFind/Auth/PluginManager.php b/module/VuFind/src/VuFind/Auth/PluginManager.php index c7f480b75c9..6772f100d06 100644 --- a/module/VuFind/src/VuFind/Auth/PluginManager.php +++ b/module/VuFind/src/VuFind/Auth/PluginManager.php @@ -29,8 +29,6 @@ namespace VuFind\Auth; -use Laminas\ServiceManager\Factory\InvokableFactory; - /** * Auth handler plugin manager * @@ -75,7 +73,7 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager AlmaDatabase::class => ILSFactory::class, CAS::class => CASFactory::class, ChoiceAuth::class => ChoiceAuthFactory::class, - Database::class => InvokableFactory::class, + Database::class => DatabaseFactory::class, Email::class => EmailFactory::class, Facebook::class => FacebookFactory::class, ILS::class => ILSFactory::class, diff --git a/module/VuFind/src/VuFind/Controller/InstallController.php b/module/VuFind/src/VuFind/Controller/InstallController.php index 897cb57a57c..129a6546bc1 100644 --- a/module/VuFind/src/VuFind/Controller/InstallController.php +++ b/module/VuFind/src/VuFind/Controller/InstallController.php @@ -29,9 +29,9 @@ namespace VuFind\Controller; -use Laminas\Crypt\Password\Bcrypt; use Laminas\Mvc\MvcEvent; use VuFind\Config\Writer as ConfigWriter; +use VuFind\Crypt\PasswordHasher; use VuFind\Db\Service\TagServiceInterface; use VuFind\Db\Service\UserCardServiceInterface; use VuFind\Db\Service\UserServiceInterface; @@ -811,18 +811,19 @@ public function performsecurityfixAction() // Now we want to loop through the database and update passwords (if // necessary). $ilsAuthenticator = $this->getService(\VuFind\Auth\ILSAuthenticator::class); - $userRows = $this->getDbService(UserServiceInterface::class)->getInsecureRows(); + $userService = $this->getDbService(UserServiceInterface::class); + $userRows = $userService->getInsecureRows(); if (count($userRows) > 0) { - $bcrypt = new Bcrypt(); + $hasher = $this->getService(PasswordHasher::class); foreach ($userRows as $row) { if ($row->getRawPassword() != '') { - $row->setPasswordHash($bcrypt->create($row->getRawPassword())); + $row->setPasswordHash($hasher->create($row->getRawPassword())); $row->setRawPassword(''); } if ($rawPassword = $row->getRawCatPassword()) { $ilsAuthenticator->saveUserCatalogCredentials($row, $row->getCatUsername(), $rawPassword); } else { - $row->save(); + $userService->persistEntity($row); } } $msg = count($userRows) . ' user row(s) encrypted.'; diff --git a/module/VuFind/src/VuFind/Crypt/PasswordHasher.php b/module/VuFind/src/VuFind/Crypt/PasswordHasher.php new file mode 100644 index 00000000000..65b7481a551 --- /dev/null +++ b/module/VuFind/src/VuFind/Crypt/PasswordHasher.php @@ -0,0 +1,90 @@ + + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ + +namespace VuFind\Crypt; + +use function password_hash; +use function password_verify; + +use const PASSWORD_BCRYPT; + +/** + * Password hasher + * + * @category VuFind + * @package Crypt + * @author Demian Katz + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org/wiki/development Wiki + */ +class PasswordHasher +{ + /** + * Algorithm to use for hashing + * + * @var string + */ + protected string $algorithm = PASSWORD_BCRYPT; + + /** + * Cost of hashing + * + * @var int + */ + protected int $cost = 10; + + /** + * Create a hash from a password + * + * @param string $password Password to hash + * + * @return string + */ + public function create(string $password): string + { + $options = ['cost' => $this->cost]; + return password_hash($password, $this->algorithm, $options); + } + + /** + * Does the provided password match the provided hash value? + * + * @param string $password Password to check + * @param string $hash Hash to compare against + * + * @return bool + */ + public function verify(string $password, string $hash): bool + { + return password_verify($password, $hash); + } +} From 4580d427883dbdbbce0b03ec8775229f25e6b26b Mon Sep 17 00:00:00 2001 From: Ere Maijala Date: Thu, 5 Sep 2024 22:22:32 +0300 Subject: [PATCH 2/5] Make it possible to retrieve user's saved searches only (#3905) --- .../VuFind/src/VuFind/Db/Service/SearchService.php | 13 ++++++++++--- .../VuFind/Db/Service/SearchServiceInterface.php | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/module/VuFind/src/VuFind/Db/Service/SearchService.php b/module/VuFind/src/VuFind/Db/Service/SearchService.php index d4a64545a55..96391c87ef2 100644 --- a/module/VuFind/src/VuFind/Db/Service/SearchService.php +++ b/module/VuFind/src/VuFind/Db/Service/SearchService.php @@ -154,17 +154,24 @@ public function getSearchByIdAndOwner( /** * Get an array of rows for the specified user. * - * @param string $sessionId Session ID of current user. + * @param ?string $sessionId Session ID of current user or null to ignore searches in session. * @param UserEntityInterface|int|null $userOrId User entity or ID of current user (optional). * * @return SearchEntityInterface[] */ - public function getSearches(string $sessionId, UserEntityInterface|int|null $userOrId = null): array + public function getSearches(?string $sessionId, UserEntityInterface|int|null $userOrId = null): array { + // If we don't get a session id or user id, don't return anything: + if (null === $sessionId && null === $userOrId) { + return []; + } $uid = $userOrId instanceof UserEntityInterface ? $userOrId->getId() : $userOrId; $callback = function ($select) use ($sessionId, $uid) { - $select->where->equalTo('session_id', $sessionId)->and->equalTo('saved', 0); + if (null !== $sessionId) { + $select->where->equalTo('session_id', $sessionId)->and->equalTo('saved', 0); + } if ($uid !== null) { + // Note: It doesn't hurt to use OR here even if there are no other terms $select->where->OR->equalTo('user_id', $uid); } $select->order('created'); diff --git a/module/VuFind/src/VuFind/Db/Service/SearchServiceInterface.php b/module/VuFind/src/VuFind/Db/Service/SearchServiceInterface.php index 098c70a1cae..52683b5d009 100644 --- a/module/VuFind/src/VuFind/Db/Service/SearchServiceInterface.php +++ b/module/VuFind/src/VuFind/Db/Service/SearchServiceInterface.php @@ -99,7 +99,7 @@ public function getSearchByIdAndOwner( /** * Get an array of rows for the specified user. * - * @param string $sessionId Session ID of current user. + * @param ?string $sessionId Session ID of current user or null to ignore searches in session. * @param UserEntityInterface|int|null $userOrId User entity or ID of current user (optional). * * @return SearchEntityInterface[] From 366b057c57f987418cdb5d7f97c89a39b41f03a2 Mon Sep 17 00:00:00 2001 From: Ere Maijala Date: Thu, 5 Sep 2024 22:24:33 +0300 Subject: [PATCH 3/5] Use static as return type in db entity interfaces (#3902) --- .../Db/Entity/AccessTokenEntityInterface.php | 12 +-- .../Db/Entity/AuthHashEntityInterface.php | 20 ++--- .../Entity/ChangeTrackerEntityInterface.php | 24 +++--- .../Db/Entity/CommentsEntityInterface.php | 16 ++-- .../Entity/ExternalSessionEntityInterface.php | 12 +-- .../Db/Entity/FeedbackEntityInterface.php | 36 ++++---- .../Db/Entity/LoginTokenEntityInterface.php | 32 +++---- .../Entity/OaiResumptionEntityInterface.php | 8 +- .../Db/Entity/RatingsEntityInterface.php | 16 ++-- .../Db/Entity/RecordEntityInterface.php | 20 ++--- .../Db/Entity/ResourceEntityInterface.php | 24 +++--- .../Db/Entity/ResourceTagsEntityInterface.php | 20 ++--- .../Db/Entity/SearchEntityInterface.php | 40 ++++----- .../Db/Entity/SessionEntityInterface.php | 16 ++-- .../Db/Entity/ShortlinksEntityInterface.php | 12 +-- .../VuFind/Db/Entity/TagsEntityInterface.php | 4 +- .../Db/Entity/UserCardEntityInterface.php | 32 +++---- .../VuFind/Db/Entity/UserEntityInterface.php | 84 +++++++++---------- .../Db/Entity/UserListEntityInterface.php | 20 ++--- .../Db/Entity/UserResourceEntityInterface.php | 20 ++--- .../VuFind/src/VuFind/Db/Row/AccessToken.php | 12 +-- module/VuFind/src/VuFind/Db/Row/AuthHash.php | 20 ++--- .../src/VuFind/Db/Row/ChangeTracker.php | 24 +++--- module/VuFind/src/VuFind/Db/Row/Comments.php | 16 ++-- .../src/VuFind/Db/Row/ExternalSession.php | 14 ++-- module/VuFind/src/VuFind/Db/Row/Feedback.php | 36 ++++---- .../VuFind/src/VuFind/Db/Row/LoginToken.php | 32 +++---- .../src/VuFind/Db/Row/OaiResumption.php | 8 +- module/VuFind/src/VuFind/Db/Row/Ratings.php | 18 ++-- module/VuFind/src/VuFind/Db/Row/Record.php | 20 ++--- module/VuFind/src/VuFind/Db/Row/Resource.php | 24 +++--- .../VuFind/src/VuFind/Db/Row/ResourceTags.php | 22 ++--- module/VuFind/src/VuFind/Db/Row/Search.php | 42 +++++----- module/VuFind/src/VuFind/Db/Row/Session.php | 16 ++-- .../VuFind/src/VuFind/Db/Row/Shortlinks.php | 14 ++-- module/VuFind/src/VuFind/Db/Row/Tags.php | 4 +- module/VuFind/src/VuFind/Db/Row/User.php | 84 +++++++++---------- module/VuFind/src/VuFind/Db/Row/UserCard.php | 32 +++---- module/VuFind/src/VuFind/Db/Row/UserList.php | 20 ++--- .../VuFind/src/VuFind/Db/Row/UserResource.php | 22 ++--- 40 files changed, 474 insertions(+), 474 deletions(-) diff --git a/module/VuFind/src/VuFind/Db/Entity/AccessTokenEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/AccessTokenEntityInterface.php index 01468cfe62e..baa8bd89cfb 100644 --- a/module/VuFind/src/VuFind/Db/Entity/AccessTokenEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/AccessTokenEntityInterface.php @@ -45,18 +45,18 @@ interface AccessTokenEntityInterface extends EntityInterface * * @param ?UserEntityInterface $user User owning token * - * @return AccessTokenEntityInterface + * @return static */ - public function setUser(?UserEntityInterface $user): AccessTokenEntityInterface; + public function setUser(?UserEntityInterface $user): static; /** * Set data. * * @param string $data Data * - * @return AccessTokenEntityInterface + * @return static */ - public function setData(string $data): AccessTokenEntityInterface; + public function setData(string $data): static; /** * Is the access token revoked? @@ -70,7 +70,7 @@ public function isRevoked(): bool; * * @param bool $revoked Revoked * - * @return AccessTokenEntityInterface + * @return static */ - public function setRevoked(bool $revoked): AccessTokenEntityInterface; + public function setRevoked(bool $revoked): static; } diff --git a/module/VuFind/src/VuFind/Db/Entity/AuthHashEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/AuthHashEntityInterface.php index 36b8cea943e..4d9ed61751d 100644 --- a/module/VuFind/src/VuFind/Db/Entity/AuthHashEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/AuthHashEntityInterface.php @@ -61,9 +61,9 @@ public function getSessionId(): ?string; * * @param ?string $sessionId PHP Session id string * - * @return AuthHashEntityInterface + * @return static */ - public function setSessionId(?string $sessionId): AuthHashEntityInterface; + public function setSessionId(?string $sessionId): static; /** * Get hash value. @@ -77,9 +77,9 @@ public function getHash(): string; * * @param string $hash Hash Value * - * @return AuthHashEntityInterface + * @return static */ - public function setHash(string $hash): AuthHashEntityInterface; + public function setHash(string $hash): static; /** * Get type of hash. @@ -93,9 +93,9 @@ public function getHashType(): ?string; * * @param ?string $type Hash Type * - * @return AuthHashEntityInterface + * @return static */ - public function setHashType(?string $type): AuthHashEntityInterface; + public function setHashType(?string $type): static; /** * Get data. @@ -109,9 +109,9 @@ public function getData(): ?string; * * @param ?string $data Data * - * @return AuthHashEntityInterface + * @return static */ - public function setData(?string $data): AuthHashEntityInterface; + public function setData(?string $data): static; /** * Get created date. @@ -125,7 +125,7 @@ public function getCreated(): DateTime; * * @param DateTime $dateTime Created date * - * @return AuthHashEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): AuthHashEntityInterface; + public function setCreated(DateTime $dateTime): static; } diff --git a/module/VuFind/src/VuFind/Db/Entity/ChangeTrackerEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/ChangeTrackerEntityInterface.php index 9dc5559c092..90afc00a5d2 100644 --- a/module/VuFind/src/VuFind/Db/Entity/ChangeTrackerEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/ChangeTrackerEntityInterface.php @@ -47,9 +47,9 @@ interface ChangeTrackerEntityInterface extends EntityInterface * * @param string $id Id * - * @return ChangeTrackerEntityInterface + * @return static */ - public function setId(string $id): ChangeTrackerEntityInterface; + public function setId(string $id): static; /** * Getter for identifier. @@ -63,9 +63,9 @@ public function getId(): string; * * @param string $name Index name * - * @return ChangeTrackerEntityInterface + * @return static */ - public function setIndexName(string $name): ChangeTrackerEntityInterface; + public function setIndexName(string $name): static; /** * Getter for index name (formerly core). @@ -79,9 +79,9 @@ public function getIndexName(): string; * * @param ?DateTime $dateTime Time first added to index. * - * @return ChangeTrackerEntityInterface + * @return static */ - public function setFirstIndexed(?DateTime $dateTime): ChangeTrackerEntityInterface; + public function setFirstIndexed(?DateTime $dateTime): static; /** * FirstIndexed getter. @@ -95,9 +95,9 @@ public function getFirstIndexed(): ?DateTime; * * @param ?DateTime $dateTime Last time changed in index. * - * @return ChangeTrackerEntityInterface + * @return static */ - public function setLastIndexed(?DateTime $dateTime): ChangeTrackerEntityInterface; + public function setLastIndexed(?DateTime $dateTime): static; /** * LastIndexed getter. @@ -111,9 +111,9 @@ public function getLastIndexed(): ?DateTime; * * @param ?DateTime $dateTime Last time original record was edited * - * @return ChangeTrackerEntityInterface + * @return static */ - public function setLastRecordChange(?DateTime $dateTime): ChangeTrackerEntityInterface; + public function setLastRecordChange(?DateTime $dateTime): static; /** * LastRecordChange getter. @@ -127,9 +127,9 @@ public function getLastRecordChange(): ?DateTime; * * @param ?DateTime $dateTime Time record was removed from index * - * @return ChangeTrackerEntityInterface + * @return static */ - public function setDeleted(?DateTime $dateTime): ChangeTrackerEntityInterface; + public function setDeleted(?DateTime $dateTime): static; /** * Deleted getter. diff --git a/module/VuFind/src/VuFind/Db/Entity/CommentsEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/CommentsEntityInterface.php index aaaf17680b8..892c68632a7 100644 --- a/module/VuFind/src/VuFind/Db/Entity/CommentsEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/CommentsEntityInterface.php @@ -54,9 +54,9 @@ public function getId(): int; * * @param string $comment Comment * - * @return Comments + * @return static */ - public function setComment(string $comment): CommentsEntityInterface; + public function setComment(string $comment): static; /** * Comment getter @@ -70,9 +70,9 @@ public function getComment(): string; * * @param DateTime $dateTime Created date * - * @return Comments + * @return static */ - public function setCreated(DateTime $dateTime): CommentsEntityInterface; + public function setCreated(DateTime $dateTime): static; /** * Created getter @@ -86,9 +86,9 @@ public function getCreated(): DateTime; * * @param ?UserEntityInterface $user User that created comment * - * @return Comments + * @return static */ - public function setUser(?UserEntityInterface $user): CommentsEntityInterface; + public function setUser(?UserEntityInterface $user): static; /** * User getter @@ -102,7 +102,7 @@ public function getUser(): ?UserEntityInterface; * * @param ResourceEntityInterface $resource Resource id. * - * @return Comments + * @return static */ - public function setResource(ResourceEntityInterface $resource): CommentsEntityInterface; + public function setResource(ResourceEntityInterface $resource): static; } diff --git a/module/VuFind/src/VuFind/Db/Entity/ExternalSessionEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/ExternalSessionEntityInterface.php index b71efd39945..5ef2136f25d 100644 --- a/module/VuFind/src/VuFind/Db/Entity/ExternalSessionEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/ExternalSessionEntityInterface.php @@ -61,9 +61,9 @@ public function getSessionId(): string; * * @param string $sessionId PHP session id string * - * @return ExternalSessionEntityInterface + * @return static */ - public function setSessionId(string $sessionId): ExternalSessionEntityInterface; + public function setSessionId(string $sessionId): static; /** * Get external session id string. @@ -77,9 +77,9 @@ public function getExternalSessionId(): string; * * @param string $externalSessionId External session id string * - * @return ExternalSessionEntityInterface + * @return static */ - public function setExternalSessionId(string $externalSessionId): ExternalSessionEntityInterface; + public function setExternalSessionId(string $externalSessionId): static; /** * Get created date. @@ -93,7 +93,7 @@ public function getCreated(): DateTime; * * @param DateTime $dateTime Created date * - * @return ExternalSessionEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): ExternalSessionEntityInterface; + public function setCreated(DateTime $dateTime): static; } diff --git a/module/VuFind/src/VuFind/Db/Entity/FeedbackEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/FeedbackEntityInterface.php index b7f91118c4b..4f75f29fa77 100644 --- a/module/VuFind/src/VuFind/Db/Entity/FeedbackEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/FeedbackEntityInterface.php @@ -54,9 +54,9 @@ public function getId(): int; * * @param string $message Message * - * @return FeedbackEntityInterface + * @return static */ - public function setMessage(string $message): FeedbackEntityInterface; + public function setMessage(string $message): static; /** * Message getter @@ -70,9 +70,9 @@ public function getMessage(): string; * * @param array $data Form data * - * @return FeedbackEntityInterface + * @return static */ - public function setFormData(array $data): FeedbackEntityInterface; + public function setFormData(array $data): static; /** * Form data getter @@ -86,9 +86,9 @@ public function getFormData(): array; * * @param string $name Form name * - * @return FeedbackEntityInterface + * @return static */ - public function setFormName(string $name): FeedbackEntityInterface; + public function setFormName(string $name): static; /** * Form name getter @@ -102,9 +102,9 @@ public function getFormName(): string; * * @param DateTime $dateTime Created date * - * @return FeedbackEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): FeedbackEntityInterface; + public function setCreated(DateTime $dateTime): static; /** * Created getter @@ -118,9 +118,9 @@ public function getCreated(): DateTime; * * @param DateTime $dateTime Last update date * - * @return FeedbackEntityInterface + * @return static */ - public function setUpdated(DateTime $dateTime): FeedbackEntityInterface; + public function setUpdated(DateTime $dateTime): static; /** * Updated getter @@ -134,9 +134,9 @@ public function getUpdated(): DateTime; * * @param string $status Status * - * @return FeedbackEntityInterface + * @return static */ - public function setStatus(string $status): FeedbackEntityInterface; + public function setStatus(string $status): static; /** * Status getter @@ -150,9 +150,9 @@ public function getStatus(): string; * * @param string $url Site URL * - * @return FeedbackEntityInterface + * @return static */ - public function setSiteUrl(string $url): FeedbackEntityInterface; + public function setSiteUrl(string $url): static; /** * Site URL getter @@ -166,9 +166,9 @@ public function getSiteUrl(): string; * * @param ?UserEntityInterface $user User that created request * - * @return FeedbackEntityInterface + * @return static */ - public function setUser(?UserEntityInterface $user): FeedbackEntityInterface; + public function setUser(?UserEntityInterface $user): static; /** * User getter @@ -182,9 +182,9 @@ public function getUser(): ?UserEntityInterface; * * @param ?UserEntityInterface $user User that updated request * - * @return FeedbackEntityInterface + * @return static */ - public function setUpdatedBy(?UserEntityInterface $user): FeedbackEntityInterface; + public function setUpdatedBy(?UserEntityInterface $user): static; /** * Updatedby getter diff --git a/module/VuFind/src/VuFind/Db/Entity/LoginTokenEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/LoginTokenEntityInterface.php index 23809fb3c42..b6be0b860aa 100644 --- a/module/VuFind/src/VuFind/Db/Entity/LoginTokenEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/LoginTokenEntityInterface.php @@ -54,9 +54,9 @@ public function getId(): int; * * @param UserEntityInterface $user User to set * - * @return LoginTokenEntityInterface + * @return static */ - public function setUser(UserEntityInterface $user): LoginTokenEntityInterface; + public function setUser(UserEntityInterface $user): static; /** * User getter (only null if entity has not been populated yet). @@ -70,9 +70,9 @@ public function getUser(): ?UserEntityInterface; * * @param string $token Token * - * @return LoginTokenEntityInterface + * @return static */ - public function setToken(string $token): LoginTokenEntityInterface; + public function setToken(string $token): static; /** * Get token string. @@ -86,9 +86,9 @@ public function getToken(): string; * * @param string $series Series * - * @return LoginTokenEntityInterface + * @return static */ - public function setSeries(string $series): LoginTokenEntityInterface; + public function setSeries(string $series): static; /** * Get series string. @@ -102,9 +102,9 @@ public function getSeries(): string; * * @param DateTime $dateTime Last login date/time * - * @return LoginTokenEntityInterface + * @return static */ - public function setLastLogin(DateTime $dateTime): LoginTokenEntityInterface; + public function setLastLogin(DateTime $dateTime): static; /** * Get last login date/time. @@ -118,9 +118,9 @@ public function getLastLogin(): DateTime; * * @param ?string $browser Browser details (or null for none) * - * @return LoginTokenEntityInterface + * @return static */ - public function setBrowser(?string $browser): LoginTokenEntityInterface; + public function setBrowser(?string $browser): static; /** * Get browser details (or null for none). @@ -134,9 +134,9 @@ public function getBrowser(): ?string; * * @param ?string $platform Platform details (or null for none) * - * @return LoginTokenEntityInterface + * @return static */ - public function setPlatform(?string $platform): LoginTokenEntityInterface; + public function setPlatform(?string $platform): static; /** * Get platform details (or null for none). @@ -150,9 +150,9 @@ public function getPlatform(): ?string; * * @param int $expires Expiration timestamp * - * @return LoginTokenEntityInterface + * @return static */ - public function setExpires(int $expires): LoginTokenEntityInterface; + public function setExpires(int $expires): static; /** * Get expiration timestamp. @@ -166,9 +166,9 @@ public function getExpires(): int; * * @param ?string $sid Last session ID (or null for none) * - * @return LoginTokenEntityInterface + * @return static */ - public function setLastSessionId(?string $sid): LoginTokenEntityInterface; + public function setLastSessionId(?string $sid): static; /** * Get last session ID (or null for none). diff --git a/module/VuFind/src/VuFind/Db/Entity/OaiResumptionEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/OaiResumptionEntityInterface.php index 5da2323329a..84287e68e3f 100644 --- a/module/VuFind/src/VuFind/Db/Entity/OaiResumptionEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/OaiResumptionEntityInterface.php @@ -54,9 +54,9 @@ public function getId(): int; * * @param ?string $params Resumption parameters. * - * @return OaiResumptionEntityInterface + * @return static */ - public function setResumptionParameters(?string $params): OaiResumptionEntityInterface; + public function setResumptionParameters(?string $params): static; /** * Get resumption parameters. @@ -70,9 +70,9 @@ public function getResumptionParameters(): ?string; * * @param DateTime $dateTime Expiration date * - * @return OaiResumptionEntityInterface + * @return static */ - public function setExpiry(DateTime $dateTime): OaiResumptionEntityInterface; + public function setExpiry(DateTime $dateTime): static; /** * Get expiry date. diff --git a/module/VuFind/src/VuFind/Db/Entity/RatingsEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/RatingsEntityInterface.php index b23317960c0..0e520febcd5 100644 --- a/module/VuFind/src/VuFind/Db/Entity/RatingsEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/RatingsEntityInterface.php @@ -61,9 +61,9 @@ public function getUser(): ?UserEntityInterface; * * @param ?UserEntityInterface $user User * - * @return RatingsEntityInterface + * @return static */ - public function setUser(?UserEntityInterface $user): RatingsEntityInterface; + public function setUser(?UserEntityInterface $user): static; /** * Get resource. @@ -77,9 +77,9 @@ public function getResource(): ResourceEntityInterface; * * @param ResourceEntityInterface $resource Resource * - * @return RatingsEntityInterface + * @return static */ - public function setResource(ResourceEntityInterface $resource): RatingsEntityInterface; + public function setResource(ResourceEntityInterface $resource): static; /** * Get rating. @@ -93,9 +93,9 @@ public function getRating(): int; * * @param int $rating Rating * - * @return RatingsEntityInterface + * @return static */ - public function setRating(int $rating): RatingsEntityInterface; + public function setRating(int $rating): static; /** * Get created date. @@ -109,7 +109,7 @@ public function getCreated(): DateTime; * * @param DateTime $dateTime Created date * - * @return RatingsEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): RatingsEntityInterface; + public function setCreated(DateTime $dateTime): static; } diff --git a/module/VuFind/src/VuFind/Db/Entity/RecordEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/RecordEntityInterface.php index 63f2cd4d793..ee4ff96aefc 100644 --- a/module/VuFind/src/VuFind/Db/Entity/RecordEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/RecordEntityInterface.php @@ -61,9 +61,9 @@ public function getRecordId(): ?string; * * @param ?string $recordId Record id * - * @return RecordEntityInterface + * @return static */ - public function setRecordId(?string $recordId): RecordEntityInterface; + public function setRecordId(?string $recordId): static; /** * Get record source. @@ -77,9 +77,9 @@ public function getSource(): ?string; * * @param ?string $recordSource Record source * - * @return RecordEntityInterface + * @return static */ - public function setSource(?string $recordSource): RecordEntityInterface; + public function setSource(?string $recordSource): static; /** * Get record version. @@ -93,9 +93,9 @@ public function getVersion(): string; * * @param string $recordVersion Record version * - * @return RecordEntityInterface + * @return static */ - public function setVersion(string $recordVersion): RecordEntityInterface; + public function setVersion(string $recordVersion): static; /** * Get record data. @@ -109,9 +109,9 @@ public function getData(): ?string; * * @param ?string $recordData Record data * - * @return RecordEntityInterface + * @return static */ - public function setData(?string $recordData): RecordEntityInterface; + public function setData(?string $recordData): static; /** * Get updated date. @@ -125,7 +125,7 @@ public function getUpdated(): DateTime; * * @param DateTime $dateTime Updated date * - * @return RecordEntityInterface + * @return static */ - public function setUpdated(DateTime $dateTime): RecordEntityInterface; + public function setUpdated(DateTime $dateTime): static; } diff --git a/module/VuFind/src/VuFind/Db/Entity/ResourceEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/ResourceEntityInterface.php index 0a948ee7ba7..bf7dbae1e85 100644 --- a/module/VuFind/src/VuFind/Db/Entity/ResourceEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/ResourceEntityInterface.php @@ -52,9 +52,9 @@ public function getId(): int; * * @param string $recordId recordId * - * @return ResourceEntityInterface + * @return static */ - public function setRecordId(string $recordId): ResourceEntityInterface; + public function setRecordId(string $recordId): static; /** * Record Id getter @@ -68,9 +68,9 @@ public function getRecordId(): string; * * @param string $title Title of the record. * - * @return ResourceEntityInterface + * @return static */ - public function setTitle(string $title): ResourceEntityInterface; + public function setTitle(string $title): static; /** * Title getter @@ -84,27 +84,27 @@ public function getTitle(): string; * * @param ?string $author Author of the title. * - * @return ResourceEntityInterface + * @return static */ - public function setAuthor(?string $author): ResourceEntityInterface; + public function setAuthor(?string $author): static; /** * Year setter * * @param ?int $year Year title is published. * - * @return ResourceEntityInterface + * @return static */ - public function setYear(?int $year): ResourceEntityInterface; + public function setYear(?int $year): static; /** * Source setter * * @param string $source Source (a search backend ID). * - * @return ResourceEntityInterface + * @return static */ - public function setSource(string $source): ResourceEntityInterface; + public function setSource(string $source): static; /** * Source getter @@ -118,9 +118,9 @@ public function getSource(): string; * * @param ?string $extraMetadata ExtraMetadata. * - * @return ResourceEntityInterface + * @return static */ - public function setExtraMetadata(?string $extraMetadata): ResourceEntityInterface; + public function setExtraMetadata(?string $extraMetadata): static; /** * Extra Metadata getter diff --git a/module/VuFind/src/VuFind/Db/Entity/ResourceTagsEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/ResourceTagsEntityInterface.php index dae2e9efa7a..cf307fac330 100644 --- a/module/VuFind/src/VuFind/Db/Entity/ResourceTagsEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/ResourceTagsEntityInterface.php @@ -61,9 +61,9 @@ public function getResource(): ?ResourceEntityInterface; * * @param ?ResourceEntityInterface $resource Resource * - * @return ResourceTagsEntityInterface + * @return static */ - public function setResource(?ResourceEntityInterface $resource): ResourceTagsEntityInterface; + public function setResource(?ResourceEntityInterface $resource): static; /** * Get tag. @@ -77,9 +77,9 @@ public function getTag(): TagsEntityInterface; * * @param TagsEntityInterface $tag Tag * - * @return ResourceTagsEntityInterface + * @return static */ - public function setTag(TagsEntityInterface $tag): ResourceTagsEntityInterface; + public function setTag(TagsEntityInterface $tag): static; /** * Get user list. @@ -93,9 +93,9 @@ public function getUserList(): ?UserListEntityInterface; * * @param ?UserListEntityInterface $list User list * - * @return ResourceTagsEntityInterface + * @return static */ - public function setUserList(?UserListEntityInterface $list): ResourceTagsEntityInterface; + public function setUserList(?UserListEntityInterface $list): static; /** * Get user. @@ -109,9 +109,9 @@ public function getUser(): ?UserEntityInterface; * * @param ?UserEntityInterface $user User * - * @return ResourceTagsEntityInterface + * @return static */ - public function setUser(?UserEntityInterface $user): ResourceTagsEntityInterface; + public function setUser(?UserEntityInterface $user): static; /** * Get created date. @@ -125,7 +125,7 @@ public function getPosted(): DateTime; * * @param DateTime $dateTime Created date * - * @return ResourceTagsEntityInterface + * @return static */ - public function setPosted(DateTime $dateTime): ResourceTagsEntityInterface; + public function setPosted(DateTime $dateTime): static; } diff --git a/module/VuFind/src/VuFind/Db/Entity/SearchEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/SearchEntityInterface.php index ca6bf3a8cec..70e45ac46b8 100644 --- a/module/VuFind/src/VuFind/Db/Entity/SearchEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/SearchEntityInterface.php @@ -61,9 +61,9 @@ public function getUser(): ?UserEntityInterface; * * @param ?UserEntityInterface $user User * - * @return SearchEntityInterface + * @return static */ - public function setUser(?UserEntityInterface $user): SearchEntityInterface; + public function setUser(?UserEntityInterface $user): static; /** * Get session identifier. @@ -77,9 +77,9 @@ public function getSessionId(): ?string; * * @param ?string $sessionId Session id * - * @return SearchEntityInterface + * @return static */ - public function setSessionId(?string $sessionId): SearchEntityInterface; + public function setSessionId(?string $sessionId): static; /** * Get created date. @@ -93,9 +93,9 @@ public function getCreated(): DateTime; * * @param DateTime $dateTime Created date * - * @return SearchEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): SearchEntityInterface; + public function setCreated(DateTime $dateTime): static; /** * Get title. @@ -109,9 +109,9 @@ public function getTitle(): ?string; * * @param ?string $title Title * - * @return SearchEntityInterface + * @return static */ - public function setTitle(?string $title): SearchEntityInterface; + public function setTitle(?string $title): static; /** * Get saved. @@ -125,9 +125,9 @@ public function getSaved(): bool; * * @param bool $saved Saved * - * @return SearchEntityInterface + * @return static */ - public function setSaved(bool $saved): SearchEntityInterface; + public function setSaved(bool $saved): static; /** * Get the search object from the row. @@ -141,9 +141,9 @@ public function getSearchObject(): ?\VuFind\Search\Minified; * * @param ?\VuFind\Search\Minified $searchObject Search object * - * @return SearchEntityInterface + * @return static */ - public function setSearchObject(?\VuFind\Search\Minified $searchObject): SearchEntityInterface; + public function setSearchObject(?\VuFind\Search\Minified $searchObject): static; /** * Get checksum. @@ -157,9 +157,9 @@ public function getChecksum(): ?int; * * @param ?int $checksum Checksum * - * @return SearchEntityInterface + * @return static */ - public function setChecksum(?int $checksum): SearchEntityInterface; + public function setChecksum(?int $checksum): static; /** * Get notification frequency. @@ -173,9 +173,9 @@ public function getNotificationFrequency(): int; * * @param int $notificationFrequency Notification frequency * - * @return SearchEntityInterface + * @return static */ - public function setNotificationFrequency(int $notificationFrequency): SearchEntityInterface; + public function setNotificationFrequency(int $notificationFrequency): static; /** * When was the last notification sent? @@ -189,9 +189,9 @@ public function getLastNotificationSent(): DateTime; * * @param DateTime $lastNotificationSent Time when last notification was sent * - * @return SearchEntityInterface + * @return static */ - public function setLastNotificationSent(Datetime $lastNotificationSent): SearchEntityInterface; + public function setLastNotificationSent(Datetime $lastNotificationSent): static; /** * Get notification base URL. @@ -205,7 +205,7 @@ public function getNotificationBaseUrl(): string; * * @param string $notificationBaseUrl Notification base URL * - * @return SearchEntityInterface + * @return static */ - public function setNotificationBaseUrl(string $notificationBaseUrl): SearchEntityInterface; + public function setNotificationBaseUrl(string $notificationBaseUrl): static; } diff --git a/module/VuFind/src/VuFind/Db/Entity/SessionEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/SessionEntityInterface.php index 368d2784731..d5065709c4d 100644 --- a/module/VuFind/src/VuFind/Db/Entity/SessionEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/SessionEntityInterface.php @@ -54,27 +54,27 @@ public function getId(): int; * * @param ?string $sid Session Id. * - * @return SessionEntityInterface + * @return static */ - public function setSessionId(?string $sid): SessionEntityInterface; + public function setSessionId(?string $sid): static; /** * Created setter. * * @param DateTime $dateTime Created date * - * @return SessionEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): SessionEntityInterface; + public function setCreated(DateTime $dateTime): static; /** * Set time the session is last used. * * @param int $lastUsed Time last used * - * @return SessionEntityInterface + * @return static */ - public function setLastUsed(int $lastUsed): SessionEntityInterface; + public function setLastUsed(int $lastUsed): static; /** * Get time when the session was last used. @@ -88,9 +88,9 @@ public function getLastUsed(): int; * * @param ?string $data Session data. * - * @return SessionEntityInterface + * @return static */ - public function setData(?string $data): SessionEntityInterface; + public function setData(?string $data): static; /** * Get session data. diff --git a/module/VuFind/src/VuFind/Db/Entity/ShortlinksEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/ShortlinksEntityInterface.php index e9992fd0e21..a0ad4947a5d 100644 --- a/module/VuFind/src/VuFind/Db/Entity/ShortlinksEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/ShortlinksEntityInterface.php @@ -62,9 +62,9 @@ public function getPath(): string; * * @param string $path Path * - * @return ShortlinksEntityInterface + * @return static */ - public function setPath(string $path): ShortlinksEntityInterface; + public function setPath(string $path): static; /** * Get shortlinks hash. @@ -78,9 +78,9 @@ public function getHash(): ?string; * * @param ?string $hash Shortlinks hash * - * @return ShortlinksEntityInterface + * @return static */ - public function setHash(?string $hash): ShortlinksEntityInterface; + public function setHash(?string $hash): static; /** * Get creation timestamp. @@ -94,7 +94,7 @@ public function getCreated(): DateTime; * * @param DateTime $dateTime Creation timestamp * - * @return ShortlinksEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): ShortlinksEntityInterface; + public function setCreated(DateTime $dateTime): static; } diff --git a/module/VuFind/src/VuFind/Db/Entity/TagsEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/TagsEntityInterface.php index 5166d8aa1c0..430096035d5 100644 --- a/module/VuFind/src/VuFind/Db/Entity/TagsEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/TagsEntityInterface.php @@ -52,9 +52,9 @@ public function getId(): int; * * @param string $tag Tag * - * @return TagsEntityInterface + * @return static */ - public function setTag(string $tag): TagsEntityInterface; + public function setTag(string $tag): static; /** * Tag getter diff --git a/module/VuFind/src/VuFind/Db/Entity/UserCardEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/UserCardEntityInterface.php index 08b965f5bd3..48f7a389dbb 100644 --- a/module/VuFind/src/VuFind/Db/Entity/UserCardEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/UserCardEntityInterface.php @@ -54,9 +54,9 @@ public function getId(): ?int; * * @param string $cardName User card name. * - * @return UserCardEntityInterface + * @return static */ - public function setCardName(string $cardName): UserCardEntityInterface; + public function setCardName(string $cardName): static; /** * Get user card name. @@ -70,9 +70,9 @@ public function getCardName(): string; * * @param string $catUsername Catalog username * - * @return UserCardEntityInterface + * @return static */ - public function setCatUsername(string $catUsername): UserCardEntityInterface; + public function setCatUsername(string $catUsername): static; /** * Get catalog username. @@ -86,9 +86,9 @@ public function getCatUsername(): string; * * @param ?string $catPassword Cat password * - * @return UserCardEntityInterface + * @return static */ - public function setRawCatPassword(?string $catPassword): UserCardEntityInterface; + public function setRawCatPassword(?string $catPassword): static; /** * Get raw catalog password. @@ -102,9 +102,9 @@ public function getRawCatPassword(): ?string; * * @param ?string $passEnc Encrypted password * - * @return UserCardEntityInterface + * @return static */ - public function setCatPassEnc(?string $passEnc): UserCardEntityInterface; + public function setCatPassEnc(?string $passEnc): static; /** * Get encrypted catalog password. @@ -118,9 +118,9 @@ public function getCatPassEnc(): ?string; * * @param ?string $homeLibrary Home library * - * @return UserCardEntityInterface + * @return static */ - public function setHomeLibrary(?string $homeLibrary): UserCardEntityInterface; + public function setHomeLibrary(?string $homeLibrary): static; /** * Get home library. @@ -134,9 +134,9 @@ public function getHomeLibrary(): ?string; * * @param DateTime $dateTime Created date * - * @return UserCardEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): UserCardEntityInterface; + public function setCreated(DateTime $dateTime): static; /** * Get created date. @@ -150,9 +150,9 @@ public function getCreated(): DateTime; * * @param DateTime $dateTime Saved date and time * - * @return UserCardEntityInterface + * @return static */ - public function setSaved(DateTime $dateTime): UserCardEntityInterface; + public function setSaved(DateTime $dateTime): static; /** * Get saved time. @@ -166,9 +166,9 @@ public function getSaved(): DateTime; * * @param UserEntityInterface $user User that owns card * - * @return UserCardEntityInterface + * @return static */ - public function setUser(UserEntityInterface $user): UserCardEntityInterface; + public function setUser(UserEntityInterface $user): static; /** * User getter diff --git a/module/VuFind/src/VuFind/Db/Entity/UserEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/UserEntityInterface.php index 8a0752a8fb4..c7d1759c829 100644 --- a/module/VuFind/src/VuFind/Db/Entity/UserEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/UserEntityInterface.php @@ -54,9 +54,9 @@ public function getId(): ?int; * * @param string $username Username * - * @return UserEntityInterface + * @return static */ - public function setUsername(string $username): UserEntityInterface; + public function setUsername(string $username): static; /** * Get username. @@ -70,9 +70,9 @@ public function getUsername(): string; * * @param string $password Password * - * @return UserEntityInterface + * @return static */ - public function setRawPassword(string $password): UserEntityInterface; + public function setRawPassword(string $password): static; /** * Get raw (unhashed) password (if available). This should only be used when hashing is disabled. @@ -86,9 +86,9 @@ public function getRawPassword(): string; * * @param ?string $hash Password hash * - * @return UserEntityInterface + * @return static */ - public function setPasswordHash(?string $hash): UserEntityInterface; + public function setPasswordHash(?string $hash): static; /** * Get hashed password. This should only be used when hashing is enabled. @@ -102,9 +102,9 @@ public function getPasswordHash(): ?string; * * @param string $firstName New first name * - * @return UserEntityInterface + * @return static */ - public function setFirstname(string $firstName): UserEntityInterface; + public function setFirstname(string $firstName): static; /** * Get firstname. @@ -118,9 +118,9 @@ public function getFirstname(): string; * * @param string $lastName New last name * - * @return UserEntityInterface + * @return static */ - public function setLastname(string $lastName): UserEntityInterface; + public function setLastname(string $lastName): static; /** * Get lastname. @@ -134,9 +134,9 @@ public function getLastname(): string; * * @param string $email Email address * - * @return UserEntityInterface + * @return static */ - public function setEmail(string $email): UserEntityInterface; + public function setEmail(string $email): static; /** * Get email. @@ -150,9 +150,9 @@ public function getEmail(): string; * * @param string $email New pending email * - * @return UserEntityInterface + * @return static */ - public function setPendingEmail(string $email): UserEntityInterface; + public function setPendingEmail(string $email): static; /** * Get pending email. @@ -166,9 +166,9 @@ public function getPendingEmail(): string; * * @param ?string $catId Catalog id * - * @return UserEntityInterface + * @return static */ - public function setCatId(?string $catId): UserEntityInterface; + public function setCatId(?string $catId): static; /** * Get catalog id. @@ -182,9 +182,9 @@ public function getCatId(): ?string; * * @param ?string $catUsername Catalog username * - * @return UserEntityInterface + * @return static */ - public function setCatUsername(?string $catUsername): UserEntityInterface; + public function setCatUsername(?string $catUsername): static; /** * Get catalog username. @@ -198,9 +198,9 @@ public function getCatUsername(): ?string; * * @param ?string $homeLibrary Home library * - * @return UserEntityInterface + * @return static */ - public function setHomeLibrary(?string $homeLibrary): UserEntityInterface; + public function setHomeLibrary(?string $homeLibrary): static; /** * Get home library. @@ -214,9 +214,9 @@ public function getHomeLibrary(): ?string; * * @param ?string $catPassword Cat password * - * @return UserEntityInterface + * @return static */ - public function setRawCatPassword(?string $catPassword): UserEntityInterface; + public function setRawCatPassword(?string $catPassword): static; /** * Get raw catalog password. @@ -230,9 +230,9 @@ public function getRawCatPassword(): ?string; * * @param ?string $passEnc Encrypted password * - * @return UserEntityInterface + * @return static */ - public function setCatPassEnc(?string $passEnc): UserEntityInterface; + public function setCatPassEnc(?string $passEnc): static; /** * Get encrypted catalog password. @@ -246,9 +246,9 @@ public function getCatPassEnc(): ?string; * * @param string $college College * - * @return UserEntityInterface + * @return static */ - public function setCollege(string $college): UserEntityInterface; + public function setCollege(string $college): static; /** * Get college. @@ -262,9 +262,9 @@ public function getCollege(): string; * * @param string $major Major * - * @return UserEntityInterface + * @return static */ - public function setMajor(string $major): UserEntityInterface; + public function setMajor(string $major): static; /** * Get major. @@ -278,9 +278,9 @@ public function getMajor(): string; * * @param string $hash Hash value to save * - * @return UserEntityInterface + * @return static */ - public function setVerifyHash(string $hash): UserEntityInterface; + public function setVerifyHash(string $hash): static; /** * Get verification hash for recovery. @@ -294,9 +294,9 @@ public function getVerifyHash(): string; * * @param ?string $authMethod New value (null for none) * - * @return UserEntityInterface + * @return static */ - public function setAuthMethod(?string $authMethod): UserEntityInterface; + public function setAuthMethod(?string $authMethod): static; /** * Get active authentication method (if any). @@ -310,9 +310,9 @@ public function getAuthMethod(): ?string; * * @param string $lang Last language * - * @return UserEntityInterface + * @return static */ - public function setLastLanguage(string $lang): UserEntityInterface; + public function setLastLanguage(string $lang): static; /** * Get last language. @@ -333,18 +333,18 @@ public function hasUserProvidedEmail(): bool; * * @param bool $userProvided New value * - * @return UserEntityInterface + * @return static */ - public function setHasUserProvidedEmail(bool $userProvided): UserEntityInterface; + public function setHasUserProvidedEmail(bool $userProvided): static; /** * Last login setter. * * @param DateTime $dateTime Last login date * - * @return UserEntityInterface + * @return static */ - public function setLastLogin(DateTime $dateTime): UserEntityInterface; + public function setLastLogin(DateTime $dateTime): static; /** * Last login getter @@ -358,9 +358,9 @@ public function getLastLogin(): DateTime; * * @param DateTime $dateTime Last login date * - * @return UserEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): UserEntityInterface; + public function setCreated(DateTime $dateTime): static; /** * Created getter @@ -374,9 +374,9 @@ public function getCreated(): Datetime; * * @param ?DateTime $dateTime Verification date (or null) * - * @return UserEntityInterface + * @return static */ - public function setEmailVerified(?DateTime $dateTime): UserEntityInterface; + public function setEmailVerified(?DateTime $dateTime): static; /** * Get email verification date (or null for unverified). diff --git a/module/VuFind/src/VuFind/Db/Entity/UserListEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/UserListEntityInterface.php index 6dd9ce2d692..a78c5179677 100644 --- a/module/VuFind/src/VuFind/Db/Entity/UserListEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/UserListEntityInterface.php @@ -54,9 +54,9 @@ public function getId(): ?int; * * @param string $title Title * - * @return UserListEntityInterface + * @return static */ - public function setTitle(string $title): UserListEntityInterface; + public function setTitle(string $title): static; /** * Get title. @@ -70,9 +70,9 @@ public function getTitle(): string; * * @param ?string $description Description * - * @return UserListEntityInterface + * @return static */ - public function setDescription(?string $description): UserListEntityInterface; + public function setDescription(?string $description): static; /** * Get description. @@ -86,9 +86,9 @@ public function getDescription(): ?string; * * @param DateTime $dateTime Created date * - * @return UserListEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): UserListEntityInterface; + public function setCreated(DateTime $dateTime): static; /** * Get created date. @@ -102,9 +102,9 @@ public function getCreated(): DateTime; * * @param bool $public Is the list public? * - * @return UserListEntityInterface + * @return static */ - public function setPublic(bool $public): UserListEntityInterface; + public function setPublic(bool $public): static; /** * Is this a public list? @@ -118,9 +118,9 @@ public function isPublic(): bool; * * @param ?UserEntityInterface $user User owning the list. * - * @return UserListEntityInterface + * @return static */ - public function setUser(?UserEntityInterface $user): UserListEntityInterface; + public function setUser(?UserEntityInterface $user): static; /** * Get user. diff --git a/module/VuFind/src/VuFind/Db/Entity/UserResourceEntityInterface.php b/module/VuFind/src/VuFind/Db/Entity/UserResourceEntityInterface.php index 6a787b3601e..b9bdcf4f2ff 100644 --- a/module/VuFind/src/VuFind/Db/Entity/UserResourceEntityInterface.php +++ b/module/VuFind/src/VuFind/Db/Entity/UserResourceEntityInterface.php @@ -61,9 +61,9 @@ public function getUser(): UserEntityInterface; * * @param UserEntityInterface $user User * - * @return UserResourceEntityInterface + * @return static */ - public function setUser(UserEntityInterface $user): UserResourceEntityInterface; + public function setUser(UserEntityInterface $user): static; /** * Get resource. @@ -77,9 +77,9 @@ public function getResource(): ResourceEntityInterface; * * @param ResourceEntityInterface $resource Resource * - * @return UserResourceEntityInterface + * @return static */ - public function setResource(ResourceEntityInterface $resource): UserResourceEntityInterface; + public function setResource(ResourceEntityInterface $resource): static; /** * Get user list. @@ -93,9 +93,9 @@ public function getUserList(): ?UserListEntityInterface; * * @param ?UserListEntityInterface $list User list * - * @return UserResourceEntityInterface + * @return static */ - public function setUserList(?UserListEntityInterface $list): UserResourceEntityInterface; + public function setUserList(?UserListEntityInterface $list): static; /** * Get notes. @@ -109,9 +109,9 @@ public function getNotes(): ?string; * * @param ?string $notes Notes associated with the resource * - * @return UserResourceEntityInterface + * @return static */ - public function setNotes(?string $notes): UserResourceEntityInterface; + public function setNotes(?string $notes): static; /** * Get saved date. @@ -125,7 +125,7 @@ public function getSaved(): DateTime; * * @param DateTime $dateTime Created date * - * @return UserResourceEntityInterface + * @return static */ - public function setSaved(DateTime $dateTime): UserResourceEntityInterface; + public function setSaved(DateTime $dateTime): static; } diff --git a/module/VuFind/src/VuFind/Db/Row/AccessToken.php b/module/VuFind/src/VuFind/Db/Row/AccessToken.php index 08136871d61..f771064f8ba 100644 --- a/module/VuFind/src/VuFind/Db/Row/AccessToken.php +++ b/module/VuFind/src/VuFind/Db/Row/AccessToken.php @@ -59,9 +59,9 @@ public function __construct($adapter) * * @param ?UserEntityInterface $user User owning token * - * @return AccessTokenEntityInterface + * @return static */ - public function setUser(?UserEntityInterface $user): AccessTokenEntityInterface + public function setUser(?UserEntityInterface $user): static { $this->__set('user_id', $user?->getId()); return $this; @@ -72,9 +72,9 @@ public function setUser(?UserEntityInterface $user): AccessTokenEntityInterface * * @param string $data Data * - * @return AccessTokenEntityInterface + * @return static */ - public function setData(string $data): AccessTokenEntityInterface + public function setData(string $data): static { $this->__set('data', $data); return $this; @@ -95,9 +95,9 @@ public function isRevoked(): bool * * @param bool $revoked Revoked * - * @return AccessTokenEntityInterface + * @return static */ - public function setRevoked(bool $revoked): AccessTokenEntityInterface + public function setRevoked(bool $revoked): static { $this->__set('revoked', $revoked); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/AuthHash.php b/module/VuFind/src/VuFind/Db/Row/AuthHash.php index 5f340b829e4..de5a60da0ac 100644 --- a/module/VuFind/src/VuFind/Db/Row/AuthHash.php +++ b/module/VuFind/src/VuFind/Db/Row/AuthHash.php @@ -93,9 +93,9 @@ public function getSessionId(): ?string * * @param ?string $sessionId PHP Session id string * - * @return AuthHashEntityInterface + * @return static */ - public function setSessionId(?string $sessionId): AuthHashEntityInterface + public function setSessionId(?string $sessionId): static { $this->session_id = $sessionId; return $this; @@ -116,9 +116,9 @@ public function getHash(): string * * @param string $hash Hash Value * - * @return AuthHashEntityInterface + * @return static */ - public function setHash(string $hash): AuthHashEntityInterface + public function setHash(string $hash): static { $this->hash = $hash; return $this; @@ -139,9 +139,9 @@ public function getHashType(): ?string * * @param ?string $type Hash Type * - * @return AuthHashEntityInterface + * @return static */ - public function setHashType(?string $type): AuthHashEntityInterface + public function setHashType(?string $type): static { $this->type = $type; return $this; @@ -162,9 +162,9 @@ public function getData(): ?string * * @param ?string $data Data * - * @return AuthHashEntityInterface + * @return static */ - public function setData(?string $data): AuthHashEntityInterface + public function setData(?string $data): static { $this->__set('data', $data); return $this; @@ -185,9 +185,9 @@ public function getCreated(): DateTime * * @param DateTime $dateTime Created date * - * @return AuthHashEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): AuthHashEntityInterface + public function setCreated(DateTime $dateTime): static { $this->created = $dateTime->format('Y-m-d H:i:s'); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/ChangeTracker.php b/module/VuFind/src/VuFind/Db/Row/ChangeTracker.php index d5dfd6621dd..e3f15904e1c 100644 --- a/module/VuFind/src/VuFind/Db/Row/ChangeTracker.php +++ b/module/VuFind/src/VuFind/Db/Row/ChangeTracker.php @@ -65,9 +65,9 @@ public function __construct($adapter) * * @param string $id Id * - * @return ChangeTrackerEntityInterface + * @return static */ - public function setId(string $id): ChangeTrackerEntityInterface + public function setId(string $id): static { $this->id = $id; return $this; @@ -88,9 +88,9 @@ public function getId(): string * * @param string $name Index name * - * @return ChangeTrackerEntityInterface + * @return static */ - public function setIndexName(string $name): ChangeTrackerEntityInterface + public function setIndexName(string $name): static { $this->core = $name; return $this; @@ -111,9 +111,9 @@ public function getIndexName(): string * * @param ?DateTime $dateTime Time first added to index. * - * @return ChangeTrackerEntityInterface + * @return static */ - public function setFirstIndexed(?DateTime $dateTime): ChangeTrackerEntityInterface + public function setFirstIndexed(?DateTime $dateTime): static { $this->first_indexed = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -134,9 +134,9 @@ public function getFirstIndexed(): ?DateTime * * @param ?DateTime $dateTime Last time changed in index. * - * @return ChangeTrackerEntityInterface + * @return static */ - public function setLastIndexed(?DateTime $dateTime): ChangeTrackerEntityInterface + public function setLastIndexed(?DateTime $dateTime): static { $this->last_indexed = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -157,9 +157,9 @@ public function getLastIndexed(): ?DateTime * * @param ?DateTime $dateTime Last time original record was edited * - * @return ChangeTrackerEntityInterface + * @return static */ - public function setLastRecordChange(?DateTime $dateTime): ChangeTrackerEntityInterface + public function setLastRecordChange(?DateTime $dateTime): static { $this->last_record_change = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -180,9 +180,9 @@ public function getLastRecordChange(): ?DateTime * * @param ?DateTime $dateTime Time record was removed from index * - * @return ChangeTrackerEntityInterface + * @return static */ - public function setDeleted(?DateTime $dateTime): ChangeTrackerEntityInterface + public function setDeleted(?DateTime $dateTime): static { $this->deleted = $dateTime->format('Y-m-d H:i:s'); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/Comments.php b/module/VuFind/src/VuFind/Db/Row/Comments.php index 66387f37f05..dbe7d52ad50 100644 --- a/module/VuFind/src/VuFind/Db/Row/Comments.php +++ b/module/VuFind/src/VuFind/Db/Row/Comments.php @@ -80,9 +80,9 @@ public function getId(): int * * @param string $comment Comment * - * @return Comments + * @return static */ - public function setComment(string $comment): CommentsEntityInterface + public function setComment(string $comment): static { $this->comment = $comment; return $this; @@ -103,9 +103,9 @@ public function getComment(): string * * @param DateTime $dateTime Created date * - * @return Comments + * @return static */ - public function setCreated(DateTime $dateTime): CommentsEntityInterface + public function setCreated(DateTime $dateTime): static { $this->created = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -126,9 +126,9 @@ public function getCreated(): DateTime * * @param ?UserEntityInterface $user User that created comment * - * @return Comments + * @return static */ - public function setUser(?UserEntityInterface $user): CommentsEntityInterface + public function setUser(?UserEntityInterface $user): static { $this->user_id = $user ? $user->getId() : null; return $this; @@ -151,9 +151,9 @@ public function getUser(): ?UserEntityInterface * * @param ResourceEntityInterface $resource Resource id. * - * @return Comments + * @return static */ - public function setResource(ResourceEntityInterface $resource): CommentsEntityInterface + public function setResource(ResourceEntityInterface $resource): static { $this->resource_id = $resource->getId(); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/ExternalSession.php b/module/VuFind/src/VuFind/Db/Row/ExternalSession.php index 7dea047ffb6..ad46955a5fa 100644 --- a/module/VuFind/src/VuFind/Db/Row/ExternalSession.php +++ b/module/VuFind/src/VuFind/Db/Row/ExternalSession.php @@ -49,7 +49,7 @@ * @property string $external_session_id * @property string $created */ -class ExternalSession extends RowGateway implements \VuFind\Db\Entity\ExternalSessionEntityInterface +class ExternalSession extends RowGateway implements ExternalSessionEntityInterface { /** * Constructor @@ -86,9 +86,9 @@ public function getSessionId(): string * * @param string $sessionId PHP session id string * - * @return ExternalSessionEntityInterface + * @return static */ - public function setSessionId(string $sessionId): ExternalSessionEntityInterface + public function setSessionId(string $sessionId): static { $this->session_id = $sessionId; return $this; @@ -109,9 +109,9 @@ public function getExternalSessionId(): string * * @param string $externalSessionId External session id string * - * @return ExternalSessionEntityInterface + * @return static */ - public function setExternalSessionId(string $externalSessionId): ExternalSessionEntityInterface + public function setExternalSessionId(string $externalSessionId): static { $this->external_session_id = $externalSessionId; return $this; @@ -132,9 +132,9 @@ public function getCreated(): DateTime * * @param DateTime $dateTime Created date * - * @return ExternalSessionEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): ExternalSessionEntityInterface + public function setCreated(DateTime $dateTime): static { $this->created = $dateTime->format('Y-m-d H:i:s'); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/Feedback.php b/module/VuFind/src/VuFind/Db/Row/Feedback.php index ee39ffc0f36..960cbc621e9 100644 --- a/module/VuFind/src/VuFind/Db/Row/Feedback.php +++ b/module/VuFind/src/VuFind/Db/Row/Feedback.php @@ -87,9 +87,9 @@ public function getId(): int * * @param string $message Message * - * @return FeedbackEntityInterface + * @return static */ - public function setMessage(string $message): FeedbackEntityInterface + public function setMessage(string $message): static { $this->message = $message; return $this; @@ -110,9 +110,9 @@ public function getMessage(): string * * @param array $data Form data * - * @return FeedbackEntityInterface + * @return static */ - public function setFormData(array $data): FeedbackEntityInterface + public function setFormData(array $data): static { $this->form_data = json_encode($data); return $this; @@ -133,9 +133,9 @@ public function getFormData(): array * * @param string $name Form name * - * @return FeedbackEntityInterface + * @return static */ - public function setFormName(string $name): FeedbackEntityInterface + public function setFormName(string $name): static { $this->form_name = $name; return $this; @@ -156,9 +156,9 @@ public function getFormName(): string * * @param DateTime $dateTime Created date * - * @return FeedbackEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): FeedbackEntityInterface + public function setCreated(DateTime $dateTime): static { $this->created = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -179,9 +179,9 @@ public function getCreated(): DateTime * * @param DateTime $dateTime Last update date * - * @return FeedbackEntityInterface + * @return static */ - public function setUpdated(DateTime $dateTime): FeedbackEntityInterface + public function setUpdated(DateTime $dateTime): static { $this->updated = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -202,9 +202,9 @@ public function getUpdated(): DateTime * * @param string $status Status * - * @return FeedbackEntityInterface + * @return static */ - public function setStatus(string $status): FeedbackEntityInterface + public function setStatus(string $status): static { $this->status = $status; return $this; @@ -225,9 +225,9 @@ public function getStatus(): string * * @param string $url Site URL * - * @return FeedbackEntityInterface + * @return static */ - public function setSiteUrl(string $url): FeedbackEntityInterface + public function setSiteUrl(string $url): static { $this->site_url = $url; return $this; @@ -248,9 +248,9 @@ public function getSiteUrl(): string * * @param ?UserEntityInterface $user User that created request * - * @return FeedbackEntityInterface + * @return static */ - public function setUser(?UserEntityInterface $user): FeedbackEntityInterface + public function setUser(?UserEntityInterface $user): static { $this->user_id = $user?->getId(); return $this; @@ -273,9 +273,9 @@ public function getUser(): ?UserEntityInterface * * @param ?UserEntityInterface $user User that updated request * - * @return FeedbackEntityInterface + * @return static */ - public function setUpdatedBy(?UserEntityInterface $user): FeedbackEntityInterface + public function setUpdatedBy(?UserEntityInterface $user): static { $this->updated_by = $user ? $user->getId() : null; return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/LoginToken.php b/module/VuFind/src/VuFind/Db/Row/LoginToken.php index 5995dcb41ed..645b8ea027d 100644 --- a/module/VuFind/src/VuFind/Db/Row/LoginToken.php +++ b/module/VuFind/src/VuFind/Db/Row/LoginToken.php @@ -84,9 +84,9 @@ public function getId(): int * * @param UserEntityInterface $user User to set * - * @return LoginTokenEntityInterface + * @return static */ - public function setUser(UserEntityInterface $user): LoginTokenEntityInterface + public function setUser(UserEntityInterface $user): static { $this->user_id = $user->getId(); return $this; @@ -109,9 +109,9 @@ public function getUser(): ?UserEntityInterface * * @param string $token Token * - * @return LoginTokenEntityInterface + * @return static */ - public function setToken(string $token): LoginTokenEntityInterface + public function setToken(string $token): static { $this->token = $token; return $this; @@ -132,9 +132,9 @@ public function getToken(): string * * @param string $series Series * - * @return LoginTokenEntityInterface + * @return static */ - public function setSeries(string $series): LoginTokenEntityInterface + public function setSeries(string $series): static { $this->series = $series; return $this; @@ -155,9 +155,9 @@ public function getSeries(): string * * @param DateTime $dateTime Last login date/time * - * @return LoginTokenEntityInterface + * @return static */ - public function setLastLogin(DateTime $dateTime): LoginTokenEntityInterface + public function setLastLogin(DateTime $dateTime): static { $this->last_login = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -178,9 +178,9 @@ public function getLastLogin(): DateTime * * @param ?string $browser Browser details (or null for none) * - * @return LoginTokenEntityInterface + * @return static */ - public function setBrowser(?string $browser): LoginTokenEntityInterface + public function setBrowser(?string $browser): static { $this->browser = $browser; return $this; @@ -201,9 +201,9 @@ public function getBrowser(): ?string * * @param ?string $platform Platform details (or null for none) * - * @return LoginTokenEntityInterface + * @return static */ - public function setPlatform(?string $platform): LoginTokenEntityInterface + public function setPlatform(?string $platform): static { $this->platform = $platform; return $this; @@ -224,9 +224,9 @@ public function getPlatform(): ?string * * @param int $expires Expiration timestamp * - * @return LoginTokenEntityInterface + * @return static */ - public function setExpires(int $expires): LoginTokenEntityInterface + public function setExpires(int $expires): static { $this->expires = $expires; return $this; @@ -247,9 +247,9 @@ public function getExpires(): int * * @param ?string $sid Last session ID (or null for none) * - * @return LoginTokenEntityInterface + * @return static */ - public function setLastSessionId(?string $sid): LoginTokenEntityInterface + public function setLastSessionId(?string $sid): static { $this->last_session_id = $sid; return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/OaiResumption.php b/module/VuFind/src/VuFind/Db/Row/OaiResumption.php index ced137c1682..fbd3e97a4f5 100644 --- a/module/VuFind/src/VuFind/Db/Row/OaiResumption.php +++ b/module/VuFind/src/VuFind/Db/Row/OaiResumption.php @@ -111,9 +111,9 @@ public function getId(): int * * @param ?string $params Resumption parameters. * - * @return OaiResumptionEntityInterface + * @return static */ - public function setResumptionParameters(?string $params): OaiResumptionEntityInterface + public function setResumptionParameters(?string $params): static { $this->params = $params; return $this; @@ -134,9 +134,9 @@ public function getResumptionParameters(): ?string * * @param DateTime $dateTime Expiration date * - * @return OaiResumptionEntityInterface + * @return static */ - public function setExpiry(DateTime $dateTime): OaiResumptionEntityInterface + public function setExpiry(DateTime $dateTime): static { $this->expires = $dateTime->format('Y-m-d H:i:s'); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/Ratings.php b/module/VuFind/src/VuFind/Db/Row/Ratings.php index c077dd22ec8..a4ded638a5d 100644 --- a/module/VuFind/src/VuFind/Db/Row/Ratings.php +++ b/module/VuFind/src/VuFind/Db/Row/Ratings.php @@ -54,7 +54,7 @@ * @property string $created */ class Ratings extends RowGateway implements - \VuFind\Db\Entity\RatingsEntityInterface, + RatingsEntityInterface, \VuFind\Db\Table\DbTableAwareInterface, DbServiceAwareInterface { @@ -98,9 +98,9 @@ public function getUser(): ?UserEntityInterface * * @param ?UserEntityInterface $user User * - * @return RatingsEntityInterface + * @return static */ - public function setUser(?UserEntityInterface $user): RatingsEntityInterface + public function setUser(?UserEntityInterface $user): static { $this->user_id = $user?->getId(); return $this; @@ -123,9 +123,9 @@ public function getResource(): ResourceEntityInterface * * @param ResourceEntityInterface $resource Resource * - * @return RatingsEntityInterface + * @return static */ - public function setResource(ResourceEntityInterface $resource): RatingsEntityInterface + public function setResource(ResourceEntityInterface $resource): static { $this->resource_id = $resource->getId(); return $this; @@ -146,9 +146,9 @@ public function getRating(): int * * @param int $rating Rating * - * @return RatingsEntityInterface + * @return static */ - public function setRating(int $rating): RatingsEntityInterface + public function setRating(int $rating): static { $this->rating = $rating; return $this; @@ -169,9 +169,9 @@ public function getCreated(): DateTime * * @param DateTime $dateTime Created date * - * @return RatingsEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): RatingsEntityInterface + public function setCreated(DateTime $dateTime): static { $this->created = $dateTime->format('Y-m-d H:i:s'); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/Record.php b/module/VuFind/src/VuFind/Db/Row/Record.php index c023ca93952..1e3b897d0ae 100644 --- a/module/VuFind/src/VuFind/Db/Row/Record.php +++ b/module/VuFind/src/VuFind/Db/Row/Record.php @@ -85,9 +85,9 @@ public function getRecordId(): ?string * * @param ?string $recordId Record id * - * @return RecordEntityInterface + * @return static */ - public function setRecordId(?string $recordId): RecordEntityInterface + public function setRecordId(?string $recordId): static { $this->record_id = $recordId; return $this; @@ -108,9 +108,9 @@ public function getSource(): ?string * * @param ?string $recordSource Record source * - * @return RecordEntityInterface + * @return static */ - public function setSource(?string $recordSource): RecordEntityInterface + public function setSource(?string $recordSource): static { $this->source = $recordSource; return $this; @@ -131,9 +131,9 @@ public function getVersion(): string * * @param string $recordVersion Record version * - * @return RecordEntityInterface + * @return static */ - public function setVersion(string $recordVersion): RecordEntityInterface + public function setVersion(string $recordVersion): static { $this->version = $recordVersion; return $this; @@ -158,9 +158,9 @@ public function getData(): ?string * * @param ?string $recordData Record data * - * @return RecordEntityInterface + * @return static */ - public function setData(?string $recordData): RecordEntityInterface + public function setData(?string $recordData): static { $this->__set('data', $recordData); return $this; @@ -181,9 +181,9 @@ public function getUpdated(): DateTime * * @param DateTime $dateTime Updated date * - * @return RecordEntityInterface + * @return static */ - public function setUpdated(DateTime $dateTime): RecordEntityInterface + public function setUpdated(DateTime $dateTime): static { $this->updated = $dateTime->format('Y-m-d H:i:s'); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/Resource.php b/module/VuFind/src/VuFind/Db/Row/Resource.php index a3ad7ad5594..e369c47f80c 100644 --- a/module/VuFind/src/VuFind/Db/Row/Resource.php +++ b/module/VuFind/src/VuFind/Db/Row/Resource.php @@ -294,9 +294,9 @@ public function getId(): int * * @param string $recordId recordId * - * @return ResourceEntityInterface + * @return static */ - public function setRecordId(string $recordId): ResourceEntityInterface + public function setRecordId(string $recordId): static { $this->record_id = $recordId; return $this; @@ -317,9 +317,9 @@ public function getRecordId(): string * * @param string $title Title of the record. * - * @return ResourceEntityInterface + * @return static */ - public function setTitle(string $title): ResourceEntityInterface + public function setTitle(string $title): static { $this->title = $title; return $this; @@ -340,9 +340,9 @@ public function getTitle(): string * * @param ?string $author Author of the title. * - * @return ResourceEntityInterface + * @return static */ - public function setAuthor(?string $author): ResourceEntityInterface + public function setAuthor(?string $author): static { $this->author = $author; return $this; @@ -353,9 +353,9 @@ public function setAuthor(?string $author): ResourceEntityInterface * * @param ?int $year Year title is published. * - * @return ResourceEntityInterface + * @return static */ - public function setYear(?int $year): ResourceEntityInterface + public function setYear(?int $year): static { $this->year = $year; return $this; @@ -366,9 +366,9 @@ public function setYear(?int $year): ResourceEntityInterface * * @param string $source Source (a search backend ID). * - * @return ResourceEntityInterface + * @return static */ - public function setSource(string $source): ResourceEntityInterface + public function setSource(string $source): static { $this->source = $source; return $this; @@ -389,9 +389,9 @@ public function getSource(): string * * @param ?string $extraMetadata ExtraMetadata. * - * @return ResourceEntityInterface + * @return static */ - public function setExtraMetadata(?string $extraMetadata): ResourceEntityInterface + public function setExtraMetadata(?string $extraMetadata): static { $this->extra_metadata = $extraMetadata; return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/ResourceTags.php b/module/VuFind/src/VuFind/Db/Row/ResourceTags.php index 976a862cdad..783a212f8a7 100644 --- a/module/VuFind/src/VuFind/Db/Row/ResourceTags.php +++ b/module/VuFind/src/VuFind/Db/Row/ResourceTags.php @@ -59,7 +59,7 @@ * @property string $posted */ class ResourceTags extends RowGateway implements - \VuFind\Db\Entity\ResourceTagsEntityInterface, + ResourceTagsEntityInterface, \VuFind\Db\Table\DbTableAwareInterface, DbServiceAwareInterface { @@ -103,9 +103,9 @@ public function getResource(): ?ResourceEntityInterface * * @param ?ResourceEntityInterface $resource Resource * - * @return ResourceTagsEntityInterface + * @return static */ - public function setResource(?ResourceEntityInterface $resource): ResourceTagsEntityInterface + public function setResource(?ResourceEntityInterface $resource): static { $this->resource_id = $resource?->getId(); return $this; @@ -128,9 +128,9 @@ public function getTag(): TagsEntityInterface * * @param TagsEntityInterface $tag Tag * - * @return ResourceTagsEntityInterface + * @return static */ - public function setTag(TagsEntityInterface $tag): ResourceTagsEntityInterface + public function setTag(TagsEntityInterface $tag): static { $this->tag_id = $tag->getId(); return $this; @@ -153,9 +153,9 @@ public function getUserList(): ?UserListEntityInterface * * @param ?UserListEntityInterface $list User list * - * @return ResourceTagsEntityInterface + * @return static */ - public function setUserList(?UserListEntityInterface $list): ResourceTagsEntityInterface + public function setUserList(?UserListEntityInterface $list): static { $this->list_id = $list?->getId(); return $this; @@ -178,9 +178,9 @@ public function getUser(): ?UserEntityInterface * * @param ?UserEntityInterface $user User * - * @return ResourceTagsEntityInterface + * @return static */ - public function setUser(?UserEntityInterface $user): ResourceTagsEntityInterface + public function setUser(?UserEntityInterface $user): static { $this->user_id = $user?->getId(); return $this; @@ -201,9 +201,9 @@ public function getPosted(): DateTime * * @param DateTime $dateTime Created date * - * @return ResourceTagsEntityInterface + * @return static */ - public function setPosted(DateTime $dateTime): ResourceTagsEntityInterface + public function setPosted(DateTime $dateTime): static { $this->posted = $dateTime->format('Y-m-d H:i:s'); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/Search.php b/module/VuFind/src/VuFind/Db/Row/Search.php index bdaeb354a50..0f5bac540d1 100644 --- a/module/VuFind/src/VuFind/Db/Row/Search.php +++ b/module/VuFind/src/VuFind/Db/Row/Search.php @@ -61,7 +61,7 @@ * @property string $notification_base_url */ class Search extends RowGateway implements - \VuFind\Db\Entity\SearchEntityInterface, + SearchEntityInterface, \VuFind\Db\Table\DbTableAwareInterface, DbServiceAwareInterface { @@ -217,9 +217,9 @@ public function getUser(): ?UserEntityInterface * * @param ?UserEntityInterface $user User * - * @return SearchEntityInterface + * @return static */ - public function setUser(?UserEntityInterface $user): SearchEntityInterface + public function setUser(?UserEntityInterface $user): static { $this->user_id = $user?->getId(); return $this; @@ -240,9 +240,9 @@ public function getSessionId(): ?string * * @param ?string $sessionId Session id * - * @return SearchEntityInterface + * @return static */ - public function setSessionId(?string $sessionId): SearchEntityInterface + public function setSessionId(?string $sessionId): static { $this->session_id = $sessionId; return $this; @@ -263,9 +263,9 @@ public function getCreated(): DateTime * * @param DateTime $dateTime Created date * - * @return SearchEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): SearchEntityInterface + public function setCreated(DateTime $dateTime): static { $this->created = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -286,9 +286,9 @@ public function getTitle(): ?string * * @param ?string $title Title * - * @return SearchEntityInterface + * @return static */ - public function setTitle(?string $title): SearchEntityInterface + public function setTitle(?string $title): static { $this->title = $title; return $this; @@ -309,9 +309,9 @@ public function getSaved(): bool * * @param bool $saved Saved * - * @return SearchEntityInterface + * @return static */ - public function setSaved(bool $saved): SearchEntityInterface + public function setSaved(bool $saved): static { $this->saved = $saved ? 1 : 0; return $this; @@ -322,9 +322,9 @@ public function setSaved(bool $saved): SearchEntityInterface * * @param ?\VuFind\Search\Minified $searchObject Search object * - * @return SearchEntityInterface + * @return static */ - public function setSearchObject(?\VuFind\Search\Minified $searchObject): SearchEntityInterface + public function setSearchObject(?\VuFind\Search\Minified $searchObject): static { $this->search_object = $searchObject ? serialize($searchObject) : null; return $this; @@ -345,9 +345,9 @@ public function getChecksum(): ?int * * @param ?int $checksum Checksum * - * @return SearchEntityInterface + * @return static */ - public function setChecksum(?int $checksum): SearchEntityInterface + public function setChecksum(?int $checksum): static { $this->checksum = $checksum; return $this; @@ -368,9 +368,9 @@ public function getNotificationFrequency(): int * * @param int $notificationFrequency Notification frequency * - * @return SearchEntityInterface + * @return static */ - public function setNotificationFrequency(int $notificationFrequency): SearchEntityInterface + public function setNotificationFrequency(int $notificationFrequency): static { $this->notification_frequency = $notificationFrequency; return $this; @@ -391,9 +391,9 @@ public function getLastNotificationSent(): DateTime * * @param DateTime $lastNotificationSent Time when last notification was sent * - * @return SearchEntityInterface + * @return static */ - public function setLastNotificationSent(Datetime $lastNotificationSent): SearchEntityInterface + public function setLastNotificationSent(Datetime $lastNotificationSent): static { $this->last_notification_sent = $lastNotificationSent->format('Y-m-d H:i:s'); return $this; @@ -414,9 +414,9 @@ public function getNotificationBaseUrl(): string * * @param string $notificationBaseUrl Notification base URL * - * @return SearchEntityInterface + * @return static */ - public function setNotificationBaseUrl(string $notificationBaseUrl): SearchEntityInterface + public function setNotificationBaseUrl(string $notificationBaseUrl): static { $this->notification_base_url = $notificationBaseUrl; return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/Session.php b/module/VuFind/src/VuFind/Db/Row/Session.php index f3ede294dad..7db832b828a 100644 --- a/module/VuFind/src/VuFind/Db/Row/Session.php +++ b/module/VuFind/src/VuFind/Db/Row/Session.php @@ -74,9 +74,9 @@ public function getId(): int * * @param ?string $sid Session Id. * - * @return SessionEntityInterface + * @return static */ - public function setSessionId(?string $sid): SessionEntityInterface + public function setSessionId(?string $sid): static { $this->session_id = $sid; return $this; @@ -87,9 +87,9 @@ public function setSessionId(?string $sid): SessionEntityInterface * * @param DateTime $dateTime Created date * - * @return SessionEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): SessionEntityInterface + public function setCreated(DateTime $dateTime): static { $this->created = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -100,9 +100,9 @@ public function setCreated(DateTime $dateTime): SessionEntityInterface * * @param int $lastUsed Time last used * - * @return SessionEntityInterface + * @return static */ - public function setLastUsed(int $lastUsed): SessionEntityInterface + public function setLastUsed(int $lastUsed): static { $this->last_used = $lastUsed; return $this; @@ -123,9 +123,9 @@ public function getLastUsed(): int * * @param ?string $data Session data. * - * @return SessionEntityInterface + * @return static */ - public function setData(?string $data): SessionEntityInterface + public function setData(?string $data): static { $this->data = $data; return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/Shortlinks.php b/module/VuFind/src/VuFind/Db/Row/Shortlinks.php index b116ba0374f..13d1a716a24 100644 --- a/module/VuFind/src/VuFind/Db/Row/Shortlinks.php +++ b/module/VuFind/src/VuFind/Db/Row/Shortlinks.php @@ -46,7 +46,7 @@ * @property string $hash * @property string $created */ -class Shortlinks extends RowGateway implements \VuFind\Db\Entity\ShortlinksEntityInterface +class Shortlinks extends RowGateway implements ShortlinksEntityInterface { /** * Constructor @@ -84,9 +84,9 @@ public function getPath(): string * * @param string $path Path * - * @return ShortlinksEntityInterface + * @return static */ - public function setPath(string $path): ShortlinksEntityInterface + public function setPath(string $path): static { $this->path = $path; return $this; @@ -107,9 +107,9 @@ public function getHash(): ?string * * @param ?string $hash Shortlinks hash * - * @return ShortlinksEntityInterface + * @return static */ - public function setHash(?string $hash): ShortlinksEntityInterface + public function setHash(?string $hash): static { $this->hash = $hash; return $this; @@ -130,9 +130,9 @@ public function getCreated(): DateTime * * @param DateTime $dateTime Creation timestamp * - * @return ShortlinksEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): ShortlinksEntityInterface + public function setCreated(DateTime $dateTime): static { $this->created = $dateTime->format('Y-m-d H:i:s'); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/Tags.php b/module/VuFind/src/VuFind/Db/Row/Tags.php index 32a6e245cee..b36457a3c06 100644 --- a/module/VuFind/src/VuFind/Db/Row/Tags.php +++ b/module/VuFind/src/VuFind/Db/Row/Tags.php @@ -129,9 +129,9 @@ public function getId(): int * * @param string $tag Tag * - * @return TagsEntityInterface + * @return static */ - public function setTag(string $tag): TagsEntityInterface + public function setTag(string $tag): static { $this->tag = $tag; return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/User.php b/module/VuFind/src/VuFind/Db/Row/User.php index 3347dc9ade2..97569a84497 100644 --- a/module/VuFind/src/VuFind/Db/Row/User.php +++ b/module/VuFind/src/VuFind/Db/Row/User.php @@ -716,9 +716,9 @@ public function getId(): ?int * * @param string $username Username * - * @return UserEntityInterface + * @return static */ - public function setUsername(string $username): UserEntityInterface + public function setUsername(string $username): static { $this->username = $username; return $this; @@ -739,9 +739,9 @@ public function getUsername(): string * * @param string $password Password * - * @return UserEntityInterface + * @return static */ - public function setRawPassword(string $password): UserEntityInterface + public function setRawPassword(string $password): static { $this->password = $password; return $this; @@ -762,9 +762,9 @@ public function getRawPassword(): string * * @param ?string $hash Password hash * - * @return UserEntityInterface + * @return static */ - public function setPasswordHash(?string $hash): UserEntityInterface + public function setPasswordHash(?string $hash): static { $this->pass_hash = $hash; return $this; @@ -785,9 +785,9 @@ public function getPasswordHash(): ?string * * @param string $firstName New first name * - * @return UserEntityInterface + * @return static */ - public function setFirstname(string $firstName): UserEntityInterface + public function setFirstname(string $firstName): static { $this->firstname = $firstName; return $this; @@ -808,9 +808,9 @@ public function getFirstname(): string * * @param string $lastName New last name * - * @return UserEntityInterface + * @return static */ - public function setLastname(string $lastName): UserEntityInterface + public function setLastname(string $lastName): static { $this->lastname = $lastName; return $this; @@ -831,9 +831,9 @@ public function getLastname(): string * * @param string $email Email address * - * @return UserEntityInterface + * @return static */ - public function setEmail(string $email): UserEntityInterface + public function setEmail(string $email): static { $this->email = $email; return $this; @@ -854,9 +854,9 @@ public function getEmail(): string * * @param string $email New pending email * - * @return UserEntityInterface + * @return static */ - public function setPendingEmail(string $email): UserEntityInterface + public function setPendingEmail(string $email): static { $this->pending_email = $email; return $this; @@ -877,9 +877,9 @@ public function getPendingEmail(): string * * @param ?string $catId Catalog id * - * @return UserEntityInterface + * @return static */ - public function setCatId(?string $catId): UserEntityInterface + public function setCatId(?string $catId): static { $this->cat_id = $catId; return $this; @@ -900,9 +900,9 @@ public function getCatId(): ?string * * @param ?string $catUsername Catalog username * - * @return UserEntityInterface + * @return static */ - public function setCatUsername(?string $catUsername): UserEntityInterface + public function setCatUsername(?string $catUsername): static { $this->cat_username = $catUsername; return $this; @@ -923,9 +923,9 @@ public function getCatUsername(): ?string * * @param ?string $homeLibrary Home library * - * @return UserEntityInterface + * @return static */ - public function setHomeLibrary(?string $homeLibrary): UserEntityInterface + public function setHomeLibrary(?string $homeLibrary): static { $this->home_library = $homeLibrary; return $this; @@ -946,9 +946,9 @@ public function getHomeLibrary(): ?string * * @param ?string $catPassword Cat password * - * @return UserEntityInterface + * @return static */ - public function setRawCatPassword(?string $catPassword): UserEntityInterface + public function setRawCatPassword(?string $catPassword): static { $this->cat_password = $catPassword; return $this; @@ -969,9 +969,9 @@ public function getRawCatPassword(): ?string * * @param ?string $passEnc Encrypted password * - * @return UserEntityInterface + * @return static */ - public function setCatPassEnc(?string $passEnc): UserEntityInterface + public function setCatPassEnc(?string $passEnc): static { $this->cat_pass_enc = $passEnc; return $this; @@ -992,9 +992,9 @@ public function getCatPassEnc(): ?string * * @param string $college College * - * @return UserEntityInterface + * @return static */ - public function setCollege(string $college): UserEntityInterface + public function setCollege(string $college): static { $this->college = $college; return $this; @@ -1015,9 +1015,9 @@ public function getCollege(): string * * @param string $major Major * - * @return UserEntityInterface + * @return static */ - public function setMajor(string $major): UserEntityInterface + public function setMajor(string $major): static { $this->major = $major; return $this; @@ -1038,9 +1038,9 @@ public function getMajor(): string * * @param string $hash Hash value to save * - * @return UserEntityInterface + * @return static */ - public function setVerifyHash(string $hash): UserEntityInterface + public function setVerifyHash(string $hash): static { $this->verify_hash = $hash; return $this; @@ -1061,9 +1061,9 @@ public function getVerifyHash(): string * * @param ?string $authMethod New value (null for none) * - * @return UserEntityInterface + * @return static */ - public function setAuthMethod(?string $authMethod): UserEntityInterface + public function setAuthMethod(?string $authMethod): static { $this->auth_method = $authMethod; return $this; @@ -1084,9 +1084,9 @@ public function getAuthMethod(): ?string * * @param string $lang Last language * - * @return UserEntityInterface + * @return static */ - public function setLastLanguage(string $lang): UserEntityInterface + public function setLastLanguage(string $lang): static { $this->last_language = $lang; return $this; @@ -1117,9 +1117,9 @@ public function hasUserProvidedEmail(): bool * * @param bool $userProvided New value * - * @return UserEntityInterface + * @return static */ - public function setHasUserProvidedEmail(bool $userProvided): UserEntityInterface + public function setHasUserProvidedEmail(bool $userProvided): static { $this->user_provided_email = $userProvided ? 1 : 0; return $this; @@ -1130,9 +1130,9 @@ public function setHasUserProvidedEmail(bool $userProvided): UserEntityInterface * * @param DateTime $dateTime Last login date * - * @return UserEntityInterface + * @return static */ - public function setLastLogin(DateTime $dateTime): UserEntityInterface + public function setLastLogin(DateTime $dateTime): static { $this->last_login = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -1153,9 +1153,9 @@ public function getLastLogin(): DateTime * * @param DateTime $dateTime Creation date * - * @return UserEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): UserEntityInterface + public function setCreated(DateTime $dateTime): static { $this->created = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -1176,9 +1176,9 @@ public function getCreated(): DateTime * * @param ?DateTime $dateTime Verification date (or null) * - * @return UserEntityInterface + * @return static */ - public function setEmailVerified(?DateTime $dateTime): UserEntityInterface + public function setEmailVerified(?DateTime $dateTime): static { $this->email_verified = $dateTime?->format('Y-m-d H:i:s'); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/UserCard.php b/module/VuFind/src/VuFind/Db/Row/UserCard.php index 0811386aff5..0b9b14f8f72 100644 --- a/module/VuFind/src/VuFind/Db/Row/UserCard.php +++ b/module/VuFind/src/VuFind/Db/Row/UserCard.php @@ -82,9 +82,9 @@ public function getId(): ?int * * @param string $cardName User card name. * - * @return UserCardEntityInterface + * @return static */ - public function setCardName(string $cardName): UserCardEntityInterface + public function setCardName(string $cardName): static { $this->card_name = $cardName; return $this; @@ -105,9 +105,9 @@ public function getCardName(): string * * @param string $catUsername Catalog username * - * @return UserCardEntityInterface + * @return static */ - public function setCatUsername(string $catUsername): UserCardEntityInterface + public function setCatUsername(string $catUsername): static { $this->cat_username = $catUsername; return $this; @@ -128,9 +128,9 @@ public function getCatUsername(): string * * @param ?string $catPassword Cat password * - * @return UserCardEntityInterface + * @return static */ - public function setRawCatPassword(?string $catPassword): UserCardEntityInterface + public function setRawCatPassword(?string $catPassword): static { $this->cat_password = $catPassword; return $this; @@ -151,9 +151,9 @@ public function getRawCatPassword(): ?string * * @param ?string $passEnc Encrypted password * - * @return UserCardEntityInterface + * @return static */ - public function setCatPassEnc(?string $passEnc): UserCardEntityInterface + public function setCatPassEnc(?string $passEnc): static { $this->cat_pass_enc = $passEnc; return $this; @@ -174,9 +174,9 @@ public function getCatPassEnc(): ?string * * @param ?string $homeLibrary Home library * - * @return UserCardEntityInterface + * @return static */ - public function setHomeLibrary(?string $homeLibrary): UserCardEntityInterface + public function setHomeLibrary(?string $homeLibrary): static { $this->home_library = $homeLibrary; return $this; @@ -197,9 +197,9 @@ public function getHomeLibrary(): ?string * * @param DateTime $dateTime Created date * - * @return UserCardEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): UserCardEntityInterface + public function setCreated(DateTime $dateTime): static { $this->created = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -220,9 +220,9 @@ public function getCreated(): DateTime * * @param DateTime $dateTime Saved date and time * - * @return UserCardEntityInterface + * @return static */ - public function setSaved(DateTime $dateTime): UserCardEntityInterface + public function setSaved(DateTime $dateTime): static { $this->saved = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -243,9 +243,9 @@ public function getSaved(): DateTime * * @param UserEntityInterface $user User that owns card * - * @return UserCardEntityInterface + * @return static */ - public function setUser(UserEntityInterface $user): UserCardEntityInterface + public function setUser(UserEntityInterface $user): static { $this->user_id = $user->getId(); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/UserList.php b/module/VuFind/src/VuFind/Db/Row/UserList.php index c546221339c..a6c9471ef30 100644 --- a/module/VuFind/src/VuFind/Db/Row/UserList.php +++ b/module/VuFind/src/VuFind/Db/Row/UserList.php @@ -263,9 +263,9 @@ public function getId(): ?int * * @param string $title Title * - * @return UserListEntityInterface + * @return static */ - public function setTitle(string $title): UserListEntityInterface + public function setTitle(string $title): static { $this->title = $title; return $this; @@ -286,9 +286,9 @@ public function getTitle(): string * * @param ?string $description Description * - * @return UserListEntityInterface + * @return static */ - public function setDescription(?string $description): UserListEntityInterface + public function setDescription(?string $description): static { $this->description = $description; return $this; @@ -309,9 +309,9 @@ public function getDescription(): ?string * * @param DateTime $dateTime Created date * - * @return UserListEntityInterface + * @return static */ - public function setCreated(DateTime $dateTime): UserListEntityInterface + public function setCreated(DateTime $dateTime): static { $this->created = $dateTime->format('Y-m-d H:i:s'); return $this; @@ -332,9 +332,9 @@ public function getCreated(): DateTime * * @param bool $public Is the list public? * - * @return UserListEntityInterface + * @return static */ - public function setPublic(bool $public): UserListEntityInterface + public function setPublic(bool $public): static { $this->public = $public ? '1' : '0'; return $this; @@ -345,9 +345,9 @@ public function setPublic(bool $public): UserListEntityInterface * * @param ?UserEntityInterface $user User owning the list. * - * @return UserListEntityInterface + * @return static */ - public function setUser(?UserEntityInterface $user): UserListEntityInterface + public function setUser(?UserEntityInterface $user): static { $this->user_id = $user?->getId(); return $this; diff --git a/module/VuFind/src/VuFind/Db/Row/UserResource.php b/module/VuFind/src/VuFind/Db/Row/UserResource.php index d8a5e110ab3..85b9dd2d274 100644 --- a/module/VuFind/src/VuFind/Db/Row/UserResource.php +++ b/module/VuFind/src/VuFind/Db/Row/UserResource.php @@ -57,7 +57,7 @@ * @property string $saved */ class UserResource extends RowGateway implements - \VuFind\Db\Entity\UserResourceEntityInterface, + UserResourceEntityInterface, \VuFind\Db\Table\DbTableAwareInterface, DbServiceAwareInterface { @@ -100,9 +100,9 @@ public function getUser(): UserEntityInterface * * @param UserEntityInterface $user User * - * @return UserResourceEntityInterface + * @return static */ - public function setUser(UserEntityInterface $user): UserResourceEntityInterface + public function setUser(UserEntityInterface $user): static { $this->user_id = $user->getId(); return $this; @@ -124,9 +124,9 @@ public function getResource(): ResourceEntityInterface * * @param ResourceEntityInterface $resource Resource * - * @return UserResourceEntityInterface + * @return static */ - public function setResource(ResourceEntityInterface $resource): UserResourceEntityInterface + public function setResource(ResourceEntityInterface $resource): static { $this->resource_id = $resource->getId(); return $this; @@ -149,9 +149,9 @@ public function getUserList(): ?UserListEntityInterface * * @param ?UserListEntityInterface $list User list * - * @return UserResourceEntityInterface + * @return static */ - public function setUserList(?UserListEntityInterface $list): UserResourceEntityInterface + public function setUserList(?UserListEntityInterface $list): static { $this->list_id = $list?->getId(); return $this; @@ -172,9 +172,9 @@ public function getNotes(): ?string * * @param ?string $notes Notes associated with the resource * - * @return UserResourceEntityInterface + * @return static */ - public function setNotes(?string $notes): UserResourceEntityInterface + public function setNotes(?string $notes): static { $this->notes = $notes; return $this; @@ -195,9 +195,9 @@ public function getSaved(): DateTime * * @param DateTime $dateTime Created date * - * @return UserResourceEntityInterface + * @return static */ - public function setSaved(DateTime $dateTime): UserResourceEntityInterface + public function setSaved(DateTime $dateTime): static { $this->saved = $dateTime->format('Y-m-d H:i:s'); return $this; From e72625da021099c610d1ee663ece7a4b4d8da62b Mon Sep 17 00:00:00 2001 From: Thomas Wagener Date: Thu, 12 Sep 2024 14:13:49 +0200 Subject: [PATCH 4/5] Signature fix of Solr's backend terms method (#3885) --- .../src/VuFindSearch/Backend/Solr/Backend.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php index afa5966086f..a104d0e7da5 100644 --- a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php +++ b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php @@ -334,18 +334,18 @@ public function similar($id, ParamBag $params = null) /** * Return terms from SOLR index. * - * @param string $field Index field - * @param string $start Starting term (blank for beginning of list) - * @param int $limit Maximum number of terms - * @param ParamBag $params Additional parameters + * @param string|ParamBag|null $field Index field + * @param ?string $start Starting term (blank for beginning of list) + * @param ?int $limit Maximum number of terms + * @param ?ParamBag $params Additional parameters * * @return Terms */ public function terms( - $field = null, - $start = null, - $limit = null, - ParamBag $params = null + string|ParamBag|null $field = null, + ?string $start = null, + ?int $limit = null, + ?ParamBag $params = null ) { // Support alternate syntax with ParamBag as first parameter: if ($field instanceof ParamBag && $params === null) { From 5c208337771644d595baf7526d04f88ee4a49385 Mon Sep 17 00:00:00 2001 From: Ere Maijala Date: Thu, 3 Oct 2024 21:53:17 +0300 Subject: [PATCH 5/5] [dev-11.0] Replace Laminas Mail with Symfony Mailer. (#3975) --- composer.json | 2 +- composer.lock | 806 +++++++++++------- config/vufind/config.ini | 28 +- .../VuFind/src/VuFind/Form/Handler/Email.php | 22 +- .../VuFind/src/VuFind/Log/LoggerFactory.php | 14 +- module/VuFind/src/VuFind/Log/Writer/Mail.php | 116 ++- module/VuFind/src/VuFind/Mailer/Bcc.php | 44 - module/VuFind/src/VuFind/Mailer/Cc.php | 44 - module/VuFind/src/VuFind/Mailer/Factory.php | 89 +- module/VuFind/src/VuFind/Mailer/From.php | 44 - .../VuFind/Mailer/GetFieldValueFixTrait.php | 101 --- module/VuFind/src/VuFind/Mailer/Mailer.php | 370 ++++---- module/VuFind/src/VuFind/Mailer/Message.php | 96 --- module/VuFind/src/VuFind/Mailer/ReplyTo.php | 44 - module/VuFind/src/VuFind/Mailer/To.php | 44 - .../src/VuFindTest/Feature/EmailTrait.php | 32 + .../VuFindTest/Mink/AccountActionsTest.php | 5 +- .../src/VuFindTest/Mink/ChoiceAuthTest.php | 5 +- .../VuFindTest/Mink/EmailVerificationTest.php | 28 +- .../src/VuFindTest/Mink/UrlShortenerTest.php | 5 +- .../src/VuFindTest/Mailer/MailerTest.php | 231 +++-- 21 files changed, 1010 insertions(+), 1160 deletions(-) delete mode 100644 module/VuFind/src/VuFind/Mailer/Bcc.php delete mode 100644 module/VuFind/src/VuFind/Mailer/Cc.php delete mode 100644 module/VuFind/src/VuFind/Mailer/From.php delete mode 100644 module/VuFind/src/VuFind/Mailer/GetFieldValueFixTrait.php delete mode 100644 module/VuFind/src/VuFind/Mailer/Message.php delete mode 100644 module/VuFind/src/VuFind/Mailer/ReplyTo.php delete mode 100644 module/VuFind/src/VuFind/Mailer/To.php diff --git a/composer.json b/composer.json index be5ef65e29b..f399ac8a8e0 100644 --- a/composer.json +++ b/composer.json @@ -57,7 +57,6 @@ "laminas/laminas-i18n": "2.28.0", "laminas/laminas-loader": "2.10.0", "laminas/laminas-log": "2.17.0", - "laminas/laminas-mail": "2.25.1", "laminas/laminas-modulemanager": "2.16.0", "laminas/laminas-mvc": "3.7.0", "laminas/laminas-mvc-i18n": "1.8.0", @@ -87,6 +86,7 @@ "steverhoades/oauth2-openid-connect-server": "2.6.1", "swagger-api/swagger-ui": "5.17.14", "symfony/console": "6.4.11", + "symfony/mailer": "6.4.12", "symfony/rate-limiter": "^6.4", "symfony/var-dumper": "6.4.11", "symfony/yaml": "6.4.11", diff --git a/composer.lock b/composer.lock index 24e67857a60..f227e348fb1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d8e2980eedae649fe224b7e49018beeb", + "content-hash": "a3b3369d5130dc83c7a9a6616ebbce7a", "packages": [ { "name": "ahand/mobileesp", @@ -842,6 +842,83 @@ ], "time": "2024-05-22T20:47:39+00:00" }, + { + "name": "doctrine/lexer", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.21" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2024-02-05T11:56:58+00:00" + }, { "name": "doctrine/persistence", "version": "3.3.3", @@ -939,6 +1016,73 @@ ], "time": "2024-06-20T10:14:30+00:00" }, + { + "name": "egulias/email-validator", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2023-10-06T06:47:41+00:00" + }, { "name": "endroid/qr-code", "version": "5.0.9", @@ -3207,82 +3351,6 @@ ], "time": "2023-12-05T18:27:50+00:00" }, - { - "name": "laminas/laminas-mail", - "version": "2.25.1", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-mail.git", - "reference": "110e04497395123998220e244cceecb167cc6dda" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-mail/zipball/110e04497395123998220e244cceecb167cc6dda", - "reference": "110e04497395123998220e244cceecb167cc6dda", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "laminas/laminas-loader": "^2.9.0", - "laminas/laminas-mime": "^2.11.0", - "laminas/laminas-stdlib": "^3.17.0", - "laminas/laminas-validator": "^2.31.0", - "php": "~8.1.0 || ~8.2.0 || ~8.3.0", - "symfony/polyfill-intl-idn": "^1.27.0", - "symfony/polyfill-mbstring": "^1.27.0", - "webmozart/assert": "^1.11.0" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.5.0", - "laminas/laminas-db": "^2.18", - "laminas/laminas-servicemanager": "^3.22.1", - "phpunit/phpunit": "^10.4.2", - "psalm/plugin-phpunit": "^0.18.4", - "symfony/process": "^6.3.4", - "vimeo/psalm": "^5.15" - }, - "suggest": { - "laminas/laminas-servicemanager": "^3.21 when using SMTP to deliver messages" - }, - "type": "library", - "extra": { - "laminas": { - "component": "Laminas\\Mail", - "config-provider": "Laminas\\Mail\\ConfigProvider" - } - }, - "autoload": { - "psr-4": { - "Laminas\\Mail\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "mail" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-mail/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-mail/issues", - "rss": "https://github.com/laminas/laminas-mail/releases.atom", - "source": "https://github.com/laminas/laminas-mail" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "abandoned": "symfony/mailer", - "time": "2023-11-02T10:32:34+00:00" - }, { "name": "laminas/laminas-math", "version": "3.7.0", @@ -3350,67 +3418,6 @@ ], "time": "2023-10-18T09:53:37+00:00" }, - { - "name": "laminas/laminas-mime", - "version": "2.12.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-mime.git", - "reference": "08cc544778829b7d68d27a097885bd6e7130135e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-mime/zipball/08cc544778829b7d68d27a097885bd6e7130135e", - "reference": "08cc544778829b7d68d27a097885bd6e7130135e", - "shasum": "" - }, - "require": { - "laminas/laminas-stdlib": "^2.7 || ^3.0", - "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" - }, - "conflict": { - "zendframework/zend-mime": "*" - }, - "require-dev": { - "laminas/laminas-coding-standard": "~2.4.0", - "laminas/laminas-mail": "^2.19.0", - "phpunit/phpunit": "~9.5.25" - }, - "suggest": { - "laminas/laminas-mail": "Laminas\\Mail component" - }, - "type": "library", - "autoload": { - "psr-4": { - "Laminas\\Mime\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "Create and parse MIME messages and parts", - "homepage": "https://laminas.dev", - "keywords": [ - "laminas", - "mime" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-mime/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-mime/issues", - "rss": "https://github.com/laminas/laminas-mime/releases.atom", - "source": "https://github.com/laminas/laminas-mime" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2023-11-02T16:47:19+00:00" - }, { "name": "laminas/laminas-modulemanager", "version": "2.16.0", @@ -8249,31 +8256,45 @@ "time": "2024-04-18T09:32:20+00:00" }, { - "name": "symfony/filesystem", - "version": "v6.4.9", + "name": "symfony/event-dispatcher", + "version": "v6.4.8", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "b51ef8059159330b74a4d52f68e671033c0fe463" + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b51ef8059159330b74a4d52f68e671033c0fe463", - "reference": "b51ef8059159330b74a4d52f68e671033c0fe463", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8d7507f02b06e06815e56bb39aa0128e3806208b", + "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" }, "require-dev": { - "symfony/process": "^5.4|^6.4|^7.0" + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Filesystem\\": "" + "Symfony\\Component\\EventDispatcher\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -8293,10 +8314,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides basic utilities for the filesystem", + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.9" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.8" }, "funding": [ { @@ -8312,29 +8333,336 @@ "type": "tidelift" } ], - "time": "2024-06-28T09:49:33+00:00" + "time": "2024-05-31T14:49:08+00:00" }, { - "name": "symfony/options-resolver", - "version": "v6.4.8", + "name": "symfony/event-dispatcher-contracts", + "version": "v3.5.0", "source": { "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "22ab9e9101ab18de37839074f8a1197f55590c1b" + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/22ab9e9101ab18de37839074f8a1197f55590c1b", - "reference": "22ab9e9101ab18de37839074f8a1197f55590c1b", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3" + "psr/event-dispatcher": "^1" }, "type": "library", - "autoload": { - "psr-4": { + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v6.4.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "b51ef8059159330b74a4d52f68e671033c0fe463" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b51ef8059159330b74a4d52f68e671033c0fe463", + "reference": "b51ef8059159330b74a4d52f68e671033c0fe463", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^5.4|^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v6.4.9" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-28T09:49:33+00:00" + }, + { + "name": "symfony/mailer", + "version": "v6.4.12", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "b6a25408c569ae2366b3f663a4edad19420a9c26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/b6a25408c569ae2366b3f663a4edad19420a9c26", + "reference": "b6a25408c569ae2366b3f663a4edad19420a9c26", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.1", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/mime": "^6.2|^7.0", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", + "symfony/twig-bridge": "<6.2.1" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/messenger": "^6.2|^7.0", + "symfony/twig-bridge": "^6.2|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v6.4.12" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-08T12:30:05+00:00" + }, + { + "name": "symfony/mime", + "version": "v6.4.12", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "abe16ee7790b16aa525877419deb0f113953f0e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/abe16ee7790b16aa525877419deb0f113953f0e1", + "reference": "abe16ee7790b16aa525877419deb0f113953f0e1", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<5.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.4|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v6.4.12" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-20T08:18:25+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v6.4.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "22ab9e9101ab18de37839074f8a1197f55590c1b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/22ab9e9101ab18de37839074f8a1197f55590c1b", + "reference": "22ab9e9101ab18de37839074f8a1197f55590c1b", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { "Symfony\\Component\\OptionsResolver\\": "" }, "exclude-from-classmap": [ @@ -13558,162 +13886,6 @@ ], "time": "2024-08-29T08:15:38+00:00" }, - { - "name": "symfony/event-dispatcher", - "version": "v6.4.8", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8d7507f02b06e06815e56bb39aa0128e3806208b", - "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/event-dispatcher-contracts": "^2.5|^3" - }, - "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/service-contracts": "<2.5" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.8" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-05-31T14:49:08+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/event-dispatcher": "^1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-04-18T09:32:20+00:00" - }, { "name": "symfony/finder", "version": "v6.4.11", @@ -14119,5 +14291,5 @@ "platform-overrides": { "php": "8.1" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.6.0" } diff --git a/config/vufind/config.ini b/config/vufind/config.ini index cfac1e0e703..07ca203d472 100644 --- a/config/vufind/config.ini +++ b/config/vufind/config.ini @@ -695,27 +695,45 @@ search_enabled = false ; This section requires no changes for most installations; if your SMTP server ; requires authentication, you can fill in a username and password below. [Mail] +; For normal SMTP you can use the following settings: host = localhost port = 25 ;username = user ;password = pass -; The server name to report to the upstream mail server when sending mail. -;name = vufind.myuniversity.edu +; Use password_file to load the secret from another file instead of including it +; directly in this configuration. +;password_file = /path/to/secret ; If a login is required you can define which protocol to use for securing the ; connection. If no explicit protocol ('tls' or 'ssl') is configured, a protocol ; based on the configured port is chosen (587 -> tls, 487 -> ssl). ;secure = tls ; This setting enforces a limit (in seconds) on the lifetime of an SMTP -; connection, which can be useful when sending batches of emails, since it can -; help avoid errors caused by server timeouts. Comment out the setting to disable -; the limit. +; connection before the connection is checked, which can be useful when sending +; batches of emails, since it can help avoid errors caused by server timeouts. +; This is mapped to the ping_threshold option in Symfony Mailer. +; Comment out the setting to use the default ping threshold. +; See https://symfony.com/doc/current/mailer.html#other-options for more +; information. connection_time_limit = 60 +; The server name to report to the upstream mail server when sending mail. +;name = vufind.myuniversity.edu + +; To use any other transport than SMTP, you can use the dsn setting to define +; the connection string. +; See https://symfony.com/doc/current/mailer.html#transport-setup for more +; information on the DSN configuration. Also note that VuFind does not include the +; third-party transports out of box, but you can add them to composer.local.json. +;dsn = "native://default" + ; Uncomment this setting to disable outbound mail but simulate success; this ; is useful for interface testing but should never be used in production! ;testOnly = true ; Set to a file path writable by VuFind to log email messages into that file; ; primarily intended for testing/debugging purposes. ;message_log = /tmp/emails.log +; Message log format. Valid options are 'plain' for plain text (default) and +; 'serialized' for serialized Email objects. +;message_log_format = plain ; The action to email records and searches may be "enabled", "disabled" or "require_login" ; (default = "require_login") ; If set to "enabled", users can send anonymous emails; If set to "require_login", diff --git a/module/VuFind/src/VuFind/Form/Handler/Email.php b/module/VuFind/src/VuFind/Form/Handler/Email.php index 3d7b61efe46..b06316921c2 100644 --- a/module/VuFind/src/VuFind/Form/Handler/Email.php +++ b/module/VuFind/src/VuFind/Form/Handler/Email.php @@ -33,8 +33,8 @@ use Laminas\Config\Config; use Laminas\Log\LoggerAwareInterface; -use Laminas\Mail\Address; use Laminas\View\Renderer\RendererInterface; +use Symfony\Component\Mime\Address; use VuFind\Db\Entity\UserEntityInterface; use VuFind\Exception\Mail as MailException; use VuFind\Form\Form; @@ -127,7 +127,7 @@ public function handle( foreach ($recipients as $recipient) { if ($recipient['email']) { $success = $this->sendEmail( - $recipient['name'], + $recipient['name'] ?? '', $recipient['email'], $senderName, $senderEmail, @@ -167,14 +167,14 @@ protected function getSender(Form $form) /** * Send form data as email. * - * @param string $recipientName Recipient name - * @param string $recipientEmail Recipient email - * @param string $senderName Sender name - * @param string $senderEmail Sender email - * @param string $replyToName Reply-to name - * @param string $replyToEmail Reply-to email - * @param string $emailSubject Email subject - * @param string $emailMessage Email message + * @param ?string $recipientName Recipient name + * @param string $recipientEmail Recipient email + * @param string $senderName Sender name + * @param string $senderEmail Sender email + * @param string $replyToName Reply-to name + * @param string $replyToEmail Reply-to email + * @param string $emailSubject Email subject + * @param string $emailMessage Email message * * @return bool */ @@ -190,7 +190,7 @@ protected function sendEmail( ): bool { try { $this->mailer->send( - new Address($recipientEmail, $recipientName), + new Address($recipientEmail, $recipientName ?? ''), new Address($senderEmail, $senderName), $emailSubject, $emailMessage, diff --git a/module/VuFind/src/VuFind/Log/LoggerFactory.php b/module/VuFind/src/VuFind/Log/LoggerFactory.php index 49fb7715ad1..128a6a41a40 100644 --- a/module/VuFind/src/VuFind/Log/LoggerFactory.php +++ b/module/VuFind/src/VuFind/Log/LoggerFactory.php @@ -109,16 +109,14 @@ protected function addEmailWriters( $email = $parts[0]; $error_types = $parts[1] ?? ''; - // use smtp - $mailer = $container->get(\VuFind\Mailer\Mailer::class); - $msg = $mailer->getNewMessage() - ->addFrom($config->Site->email) - ->addTo($email) - ->setSubject('VuFind Log Message'); - // Make Writers $filters = explode(',', $error_types); - $writer = new Writer\Mail($msg, $mailer->getTransport()); + $writer = new Writer\Mail( + $container->get(\VuFind\Mailer\Mailer::class), + $config->Site->email, + $email, + 'VuFind Log Message' + ); $this->addWriters($logger, $writer, $filters); } diff --git a/module/VuFind/src/VuFind/Log/Writer/Mail.php b/module/VuFind/src/VuFind/Log/Writer/Mail.php index 822c27b01fe..7953183dfe6 100644 --- a/module/VuFind/src/VuFind/Log/Writer/Mail.php +++ b/module/VuFind/src/VuFind/Log/Writer/Mail.php @@ -3,9 +3,11 @@ /** * Mail log writer * + * Inspired by Laminas Mail log writer + * * PHP version 8 * - * Copyright (C) Villanova University 2010. + * Copyright (C) The National Library of Finland 2024. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -22,26 +24,70 @@ * * @category VuFind * @package Error_Logging - * @author Chris Hallberg + * @author Ere Maijala * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org Main Site */ namespace VuFind\Log\Writer; +use Laminas\Log\Formatter\FormatterInterface; +use Laminas\Log\Formatter\Simple as SimpleFormatter; +use Laminas\Log\Writer\AbstractWriter; +use Symfony\Component\Mime\Email; +use VuFind\Exception\Mail as MailException; +use VuFind\Mailer\Mailer; + /** - * This class extends the Laminas Logging towards Mail systems + * This class implements the Laminas Logging interface for Mail systems + * + * Inspired by Laminas Mail log writer * * @category VuFind * @package Error_Logging - * @author Chris Hallberg + * @author Ere Maijala * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org Main Site */ -class Mail extends \Laminas\Log\Writer\Mail +class Mail extends AbstractWriter { use VerbosityTrait; + /** + * Array of formatted events to include in message body. + * + * @var array + */ + protected $eventsToMail = []; + + /** + * Array keeping track of the number of entries per priority level. + * + * @var array + */ + protected $numEntriesPerPriority = []; + + /** + * Constructor + * + * @param Mailer $mailer Mailer + * @param string $from Sender address + * @param string $to Recipient address + * @param string $subject Email subject + * @param ?FormatterInterface $formatter Log entry formatter + * + * @throws Exception\InvalidArgumentException + */ + public function __construct( + protected Mailer $mailer, + protected string $from, + protected string $to, + protected string $subject, + ?FormatterInterface $formatter = null + ) { + $this->setFormatter($formatter ?? new SimpleFormatter()); + } + /** * Write a message to the log. * @@ -52,7 +98,63 @@ class Mail extends \Laminas\Log\Writer\Mail */ protected function doWrite(array $event) { - // Apply verbosity, Call parent method: - parent::doWrite($this->applyVerbosity($event)); + $event = $this->applyVerbosity($event); + // Track the number of entries per priority level. + if (!isset($this->numEntriesPerPriority[$event['priorityName']])) { + $this->numEntriesPerPriority[$event['priorityName']] = 1; + } else { + $this->numEntriesPerPriority[$event['priorityName']]++; + } + + // All plaintext events are to use the standard formatter. + $this->eventsToMail[] = $this->formatter->format($event); + } + + /** + * Sends mail to recipient(s) if log entries are present. Note that both + * plaintext and HTML portions of email are handled here. + * + * @return void + */ + public function shutdown() + { + if (!$this->eventsToMail) { + return; + } + + // Merge all messages into a single text: + $message = implode(PHP_EOL, $this->eventsToMail); + + // Finally, send the mail. If an exception occurs, convert it into a + // warning-level message so we can avoid an exception thrown without a + // stack frame. + // N.B. Logger cannot be used when reporting errors with Logger! + try { + $this->mailer->send( + $this->to, + $this->from, + $this->subject, + $message + ); + } catch (MailException $e) { + trigger_error('Unable to send log entries via email: ' . (string)$e, E_USER_WARNING); + } + } + + /** + * Gets a string of number of entries per-priority level that occurred, or + * an empty string if none occurred. + * + * @return string + */ + protected function getFormattedNumEntriesPerPriority() + { + $strings = []; + + foreach ($this->numEntriesPerPriority as $priority => $numEntries) { + $strings[] = "{$priority}={$numEntries}"; + } + + return implode(', ', $strings); } } diff --git a/module/VuFind/src/VuFind/Mailer/Bcc.php b/module/VuFind/src/VuFind/Mailer/Bcc.php deleted file mode 100644 index 9eb625c6bb0..00000000000 --- a/module/VuFind/src/VuFind/Mailer/Bcc.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ - -namespace VuFind\Mailer; - -/** - * Tweaked Laminas "Bcc" header class - * - * @category VuFind - * @package Mailer - * @author Ere Maijala - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ -class Bcc extends \Laminas\Mail\Header\Bcc -{ - use GetFieldValueFixTrait; -} diff --git a/module/VuFind/src/VuFind/Mailer/Cc.php b/module/VuFind/src/VuFind/Mailer/Cc.php deleted file mode 100644 index bb91280afc0..00000000000 --- a/module/VuFind/src/VuFind/Mailer/Cc.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ - -namespace VuFind\Mailer; - -/** - * Tweaked Laminas "Cc" header class - * - * @category VuFind - * @package Mailer - * @author Ere Maijala - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ -class Cc extends \Laminas\Mail\Header\Cc -{ - use GetFieldValueFixTrait; -} diff --git a/module/VuFind/src/VuFind/Mailer/Factory.php b/module/VuFind/src/VuFind/Mailer/Factory.php index f05f4568a8e..43a393f17d1 100644 --- a/module/VuFind/src/VuFind/Mailer/Factory.php +++ b/module/VuFind/src/VuFind/Mailer/Factory.php @@ -6,6 +6,7 @@ * PHP version 8 * * Copyright (C) Villanova University 2009. + * Copyright (C) The National Library of Finland 2024. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -23,20 +24,19 @@ * @category VuFind * @package Mailer * @author Demian Katz + * @author Ere Maijala * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development Wiki */ namespace VuFind\Mailer; -use Laminas\Mail\Transport\InMemory; -use Laminas\Mail\Transport\Smtp; -use Laminas\Mail\Transport\SmtpOptions; use Laminas\ServiceManager\Exception\ServiceNotCreatedException; use Laminas\ServiceManager\Exception\ServiceNotFoundException; use Laminas\ServiceManager\Factory\FactoryInterface; use Psr\Container\ContainerExceptionInterface as ContainerException; use Psr\Container\ContainerInterface; +use VuFind\Config\Feature\SecretTrait; /** * Factory for instantiating Mailer objects @@ -44,6 +44,7 @@ * @category VuFind * @package Mailer * @author Demian Katz + * @author Ere Maijala * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development Wiki * @@ -51,48 +52,52 @@ */ class Factory implements FactoryInterface { + use SecretTrait; + /** - * Build the mail transport object. + * Return DSN from the configuration * - * @param \Laminas\Config\Config $config Configuration + * @param array $config Configuration * - * @return InMemory|Smtp + * @return string */ - protected function getTransport($config) + protected function getDSN(array $config): string { - // In test mode? Return fake object: - if (isset($config->Mail->testOnly) && $config->Mail->testOnly) { - return new InMemory(); + // In test mode? Use null transport: + if ($config['Mail']['testOnly'] ?? false) { + return 'null://null'; + } + + if ($dsn = $config['Mail']['dsn'] ?? null) { + return $dsn; } - // Create mail transport: - $settings = [ - 'host' => $config->Mail->host, 'port' => $config->Mail->port, - ]; - if (isset($config->Mail->name)) { - $settings['name'] = $config->Mail->name; + // Create DSN from settings: + $protocol = ($config['Mail']['secure'] ?? false) ? 'smtps' : 'smtp'; + $dsn = "$protocol://"; + if ( + ($username = $config['Mail']['username'] ?? null) + && ($password = $this->getSecretFromConfig($config['Mail'], 'password')) + ) { + $dsn .= "$username:$password@"; } - if (isset($config->Mail->username) && isset($config->Mail->password)) { - $settings['connection_class'] = 'login'; - $settings['connection_config'] = [ - 'username' => $config->Mail->username, - 'password' => $config->Mail->password, - ]; - // Set user defined secure connection if provided; otherwise set default - // secure connection based on configured port number. - if (isset($config->Mail->secure)) { - $settings['connection_config']['ssl'] = $config->Mail->secure; - } elseif ($settings['port'] == '587') { - $settings['connection_config']['ssl'] = 'tls'; - } elseif ($settings['port'] == '487') { - $settings['connection_config']['ssl'] = 'ssl'; - } + $dsn .= $config['Mail']['host']; + if ($port = $config['Mail']['port'] ?? null) { + $dsn .= ":$port"; } - if (isset($config->Mail->connection_time_limit)) { - $settings['connection_time_limit'] - = $config->Mail->connection_time_limit; + + $dsnParams = []; + if ($name = $config['Mail']['name'] ?? null) { + $dsnParams['local_domain'] = $name; } - return new Smtp(new SmtpOptions($settings)); + if (null !== ($limit = $config['Mail']['connection_time_limit'] ?? null)) { + $dsnParams['ping_threshold'] = $limit; + } + if ($dsnParams) { + $dsn .= '?' . http_build_query($dsnParams); + } + + return $dsn; } /** @@ -119,16 +124,20 @@ public function __invoke( } // Load configurations: - $config = $container->get(\VuFind\Config\PluginManager::class) - ->get('config'); + $config = $container->get(\VuFind\Config\PluginManager::class)->get('config')->toArray(); // Create service: $class = new $requestedName( - $this->getTransport($config), - $config->Mail->message_log + new \Symfony\Component\Mailer\Mailer( + \Symfony\Component\Mailer\Transport::fromDsn($this->getDSN($config)) + ), + [ + 'message_log' => $config['Mail']['message_log'] ?? null, + 'message_log_format' => $config['Mail']['message_log_format'] ?? null, + ] ); if (!empty($config->Mail->override_from)) { - $class->setFromAddressOverride($config->Mail->override_from); + $class->setFromAddressOverride($config['Mail']['override_from'] ?? null); } return $class; } diff --git a/module/VuFind/src/VuFind/Mailer/From.php b/module/VuFind/src/VuFind/Mailer/From.php deleted file mode 100644 index 1ac5fea05fe..00000000000 --- a/module/VuFind/src/VuFind/Mailer/From.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ - -namespace VuFind\Mailer; - -/** - * Tweaked Laminas "From" header class - * - * @category VuFind - * @package Mailer - * @author Ere Maijala - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ -class From extends \Laminas\Mail\Header\From -{ - use GetFieldValueFixTrait; -} diff --git a/module/VuFind/src/VuFind/Mailer/GetFieldValueFixTrait.php b/module/VuFind/src/VuFind/Mailer/GetFieldValueFixTrait.php deleted file mode 100644 index 1390c21bddb..00000000000 --- a/module/VuFind/src/VuFind/Mailer/GetFieldValueFixTrait.php +++ /dev/null @@ -1,101 +0,0 @@ - - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ - -namespace VuFind\Mailer; - -use Laminas\Mail\Header\HeaderInterface; -use Laminas\Mail\Header\HeaderValue; -use Laminas\Mail\Header\HeaderWrap; -use Laminas\Mail\Headers; - -use function sprintf; - -/** - * Trait that provides an improved version of the getFieldValue method. - * - * @category VuFind - * @package Mailer - * @author Ere Maijala - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ -trait GetFieldValueFixTrait -{ - /** - * Retrieve header value - * - * Overrides the original implementation to always enclose name in quotes. - * - * @param bool $format Return the value in Mime::Encoded (HeaderInterface::FORMAT_ENCODED) or - * in Raw format (HeaderInterface::FORMAT_RAW). Using a constant from HeaderInterface is - * recommended instead of a raw boolean value. - * - * @return string - */ - public function getFieldValue($format = HeaderInterface::FORMAT_RAW) - { - $emails = []; - $encoding = $this->getEncoding(); - - foreach ($this->getAddressList() as $address) { - $email = $address->getEmail(); - $name = $address->getName(); - - if ( - $format === HeaderInterface::FORMAT_ENCODED - && 'ASCII' !== $encoding - ) { - if (! empty($name)) { - $name = HeaderWrap::mimeEncodeValue($name, $encoding); - } - - if (preg_match('/^(.+)@([^@]+)$/', $email, $matches)) { - $localPart = $matches[1]; - $hostname = $this->idnToAscii($matches[2]); - $email = sprintf('%s@%s', $localPart, $hostname); - } - } - - if (empty($name)) { - $emails[] = $email; - } else { - $emails[] = sprintf('"%s" <%s>', $name, $email); - } - } - - // Ensure the values are valid before sending them. - if ($format !== HeaderInterface::FORMAT_RAW) { - foreach ($emails as $email) { - HeaderValue::assertValid($email); - } - } - - return implode(',' . Headers::FOLDING, $emails); - } -} diff --git a/module/VuFind/src/VuFind/Mailer/Mailer.php b/module/VuFind/src/VuFind/Mailer/Mailer.php index 5d28ab88056..446e8acc2e7 100644 --- a/module/VuFind/src/VuFind/Mailer/Mailer.php +++ b/module/VuFind/src/VuFind/Mailer/Mailer.php @@ -6,6 +6,7 @@ * PHP version 8 * * Copyright (C) Villanova University 2009. + * Copyright (C) The National Library of Finland 2024. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -23,23 +24,23 @@ * @category VuFind * @package Mailer * @author Demian Katz + * @author Ere Maijala * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development Wiki */ namespace VuFind\Mailer; -use Laminas\Mail\Address; -use Laminas\Mail\AddressList; -use Laminas\Mail\Header\ContentType; -use Laminas\Mail\Transport\TransportInterface; -use Laminas\Mime\Message as MimeMessage; -use Laminas\Mime\Mime; -use Laminas\Mime\Part as MimePart; +use Laminas\View\Renderer\PhpRenderer; +use Symfony\Component\Mailer\MailerInterface; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Exception\RfcComplianceException; use VuFind\Exception\Mail as MailException; +use VuFind\RecordDriver\AbstractBase; use function count; -use function is_callable; +use function is_array; /** * VuFind Mailer Class @@ -47,6 +48,7 @@ * @category VuFind * @package Mailer * @author Demian Katz + * @author Ere Maijala * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development Wiki */ @@ -60,17 +62,14 @@ class Mailer implements /** * Mail transport * - * @var TransportInterface + * @var MailerInterface */ protected $transport; /** - * A clone of $transport above. This can be used to reset the connection state - * in case transport doesn't support the disconnect method or it throws an - * exception (this can happen if the connection is stale and the connector tries - * to issue a QUIT message for clean disconnect). + * A clone of $transport above. This can be used to reset the connection state. * - * @var TransportInterface + * @var MailerInterface */ protected $initialTransport; @@ -91,10 +90,10 @@ class Mailer implements /** * Constructor * - * @param TransportInterface $transport Mail transport - * @param ?string $messageLog File to log messages into (null for no logging) + * @param MailerInterface $transport Mail transport + * @param array $options Message log options */ - public function __construct(TransportInterface $transport, protected ?string $messageLog = null) + public function __construct(MailerInterface $transport, protected array $options = []) { $this->setTransport($transport); } @@ -102,27 +101,21 @@ public function __construct(TransportInterface $transport, protected ?string $me /** * Get the mail transport object. * - * @return TransportInterface + * @return MailerInterface */ - public function getTransport() + public function getTransport(): MailerInterface { return $this->transport; } /** - * Get a text email message object. + * Get an email message object. * - * @return Message + * @return Email */ - public function getNewMessage() + public function getNewMessage(): Email { - $message = $this->getNewBlankMessage(); - $headers = $message->getHeaders(); - $ctype = new ContentType(); - $ctype->setType(Mime::TYPE_TEXT); - $ctype->addParameter('charset', 'UTF-8'); - $headers->addHeader($ctype); - return $message; + return new Email(); } /** @@ -132,46 +125,33 @@ public function getNewMessage() */ public function resetConnection() { - // If the transport has a disconnect method, call it. Otherwise, and in case - // disconnect fails, revert to the transport instance clone made before a - // connection was made. - $transport = $this->getTransport(); - if (is_callable([$transport, 'disconnect'])) { - try { - $transport->disconnect(); - } catch (\Exception $e) { - $this->setTransport($this->initialTransport); - } - } else { - $this->setTransport($this->initialTransport); - } + $this->setTransport($this->initialTransport); return $this; } /** * Get a blank email message object. * - * @return Message + * @return Email + * + * @deprecated Use getNewMessage */ - public function getNewBlankMessage() + public function getNewBlankMessage(): Email { - $message = new Message(); - $message->setEncoding('UTF-8'); - return $message; + return $this->getNewMessage(); } /** * Set the mail transport object. * - * @param TransportInterface $transport Mail transport object + * @param MailerInterface $transport Mail transport object * * @return void */ - public function setTransport($transport) + public function setTransport(MailerInterface $transport): void { $this->transport = $transport; - // Store a clone of the given transport so that we can reset the connection - // as necessary. + // Store a clone of the given transport so that we can reset the connection as necessary: $this->initialTransport = clone $this->transport; } @@ -180,83 +160,91 @@ public function setTransport($transport) * * @param string $input String to convert * - * @return AddressList + * @return array */ - public function stringToAddressList($input) + public function stringToAddressList($input): array { // Create recipient list - $list = new AddressList(); + $list = []; foreach (preg_split('/[\s,;]/', $input) as $current) { $current = trim($current); if (!empty($current)) { - $list->add($current); + $list[] = $current; } } return $list; } /** - * Constructs a {@see MimeMessage} body from given text and html content. + * Constructs an {@see Email} body from given text and html content. * * @param string|null $text Mail content used for plain text part * @param string|null $html Mail content used for html part * - * @return MimeMessage + * @return Email */ public function buildMultipartBody( string $text = null, string $html = null - ): MimeMessage { - $parts = new MimeMessage(); - - if ($text) { - $textPart = new MimePart($text); - $textPart->setType(Mime::TYPE_TEXT); - $textPart->setCharset('utf-8'); - $textPart->setEncoding(Mime::ENCODING_QUOTEDPRINTABLE); - $parts->addPart($textPart); + ): Email { + $email = $this->getNewMessage(); + if (null !== $text) { + $email->text($text); } - - if ($html) { - $htmlPart = new MimePart($html); - $htmlPart->setType(Mime::TYPE_HTML); - $htmlPart->setCharset('utf-8'); - $htmlPart->setEncoding(Mime::ENCODING_QUOTEDPRINTABLE); - $parts->addPart($htmlPart); + if (null !== $html) { + $email->html($html); } - - $alternativePart = new MimePart($parts->generateMessage()); - $alternativePart->setType('multipart/alternative'); - $alternativePart->setBoundary($parts->getMime()->boundary()); - $alternativePart->setCharset('utf-8'); - - $body = new MimeMessage(); - $body->setParts([$alternativePart]); - - return $body; + return $email; } /** * Send an email message. * - * @param string|Address|AddressList $to Recipient email address (or - * delimited list) - * @param string|Address $from Sender name and email address - * @param string $subject Subject line for message - * @param string|MimeMessage $body Message body - * @param string $cc CC recipient (null for none) - * @param string|Address|AddressList $replyTo Reply-To address (or delimited - * list, null for none) + * @param string|string[]|Address|Address[] $to Recipient email address(es) (or delimited list) + * @param string|Address $from Sender name and email address + * @param string $subject Subject line for message + * @param string|Email $body Message body + * @param string|string[]|Address|Address[]|null $cc CC recipient(s) (null for none) + * @param string|string[]|Address|Address[]|null $replyTo Reply-To address(es) (or delimited list, null for none) * * @throws MailException * @return void */ - public function send($to, $from, $subject, $body, $cc = null, $replyTo = null) - { - $recipients = $this->convertToAddressList($to); - $replyTo = $this->convertToAddressList($replyTo); + public function send( + string|Address|array $to, + string|Address $from, + string $subject, + string|Email $body, + string|Address|array|null $cc = null, + string|Address|array|null $replyTo = null + ) { + try { + if (!($from instanceof Address)) { + $from = new Address($from); + } + } catch (RfcComplianceException $e) { + throw new MailException('Invalid Sender Email Address', MailException::ERROR_INVALID_SENDER, $e); + } + try { + $recipients = $this->convertToAddressList($to); + } catch (RfcComplianceException $e) { + throw new MailException('Invalid Recipient Email Address', MailException::ERROR_INVALID_RECIPIENT, $e); + } + try { + $replyTo = $this->convertToAddressList($replyTo); + } catch (RfcComplianceException $e) { + throw new MailException('Invalid Reply-To Email Address', MailException::ERROR_INVALID_REPLY_TO, $e); + } + try { + $cc = $this->convertToAddressList($cc); + } catch (RfcComplianceException $e) { + throw new MailException('Invalid CC Email Address', MailException::ERROR_INVALID_RECIPIENT, $e); + } - // Validate email addresses: + // Validate recipient email address count: + if (count($recipients) == 0) { + throw new MailException('Invalid Recipient Email Address', MailException::ERROR_INVALID_RECIPIENT); + } if ($this->maxRecipients > 0) { if ($this->maxRecipients < count($recipients)) { throw new MailException( @@ -265,53 +253,19 @@ public function send($to, $from, $subject, $body, $cc = null, $replyTo = null) ); } } - $validator = new \Laminas\Validator\EmailAddress(); - if (count($recipients) == 0) { - throw new MailException( - 'Invalid Recipient Email Address', - MailException::ERROR_INVALID_RECIPIENT - ); - } - foreach ($recipients as $current) { - if (!$validator->isValid($current->getEmail())) { - throw new MailException( - 'Invalid Recipient Email Address', - MailException::ERROR_INVALID_RECIPIENT - ); - } - } - foreach ($replyTo as $current) { - if (!$validator->isValid($current->getEmail())) { - throw new MailException( - 'Invalid Reply-To Email Address', - MailException::ERROR_INVALID_REPLY_TO - ); - } - } - $fromEmail = ($from instanceof Address) - ? $from->getEmail() : $from; - if (!$validator->isValid($fromEmail)) { - throw new MailException( - 'Invalid Sender Email Address', - MailException::ERROR_INVALID_SENDER - ); - } if ( !empty($this->fromAddressOverride) - && $this->fromAddressOverride != $fromEmail + && $this->fromAddressOverride != $from->getAddress() ) { // Add the original from address as the reply-to address unless // a reply-to address has been specified - if (count($replyTo) === 0) { - $replyTo->add($fromEmail); - } - if (!($from instanceof Address)) { - $from = new Address($from); + if (!$replyTo) { + $replyTo[] = $from->getAddress(); } $name = $from->getName(); if (!$name) { - [$fromPre] = explode('@', $from->getEmail()); + [$fromPre] = explode('@', $from->getAddress()); $name = $fromPre ? $fromPre : null; } $from = new Address($this->fromAddressOverride, $name); @@ -320,59 +274,64 @@ public function send($to, $from, $subject, $body, $cc = null, $replyTo = null) // Convert all exceptions thrown by mailer into MailException objects: try { // Send message - $message = $body instanceof MimeMessage - ? $this->getNewBlankMessage() - : $this->getNewMessage(); - $message->addFrom($from) - ->addTo($recipients) - ->setBody($body) - ->setSubject($subject); - if ($cc !== null) { - $message->addCc($cc); + if ($body instanceof Email) { + $email = $body; + if (null === $email->getSubject()) { + $email->subject($subject); + } + } else { + $email = $this->getNewMessage(); + $email->text($body); + $email->subject($subject); } - if ($replyTo) { - $message->addReplyTo($replyTo); + $email->addFrom($from); + foreach ($recipients as $current) { + $email->addTo($current); } - $this->getTransport()->send($message); - if ($this->messageLog) { - file_put_contents($this->messageLog, $message->toString() . "\n", FILE_APPEND); + foreach ($cc as $current) { + $email->addCc($current); + } + foreach ($replyTo as $current) { + $email->addReplyTo($current); + } + $this->getTransport()->send($email); + if ($logFile = $this->options['message_log'] ?? null) { + $format = $this->options['message_log_format'] ?? 'plain'; + $data = 'serialized' === $format + ? serialize($email) . "\x1E" // use Record Separator to separate messages + : $email->toString() . "\n\n"; + file_put_contents($logFile, $data, FILE_APPEND); } } catch (\Exception $e) { $this->logError($e->getMessage()); - throw new MailException($e->getMessage(), MailException::ERROR_UNKNOWN); + throw new MailException($e->getMessage(), MailException::ERROR_UNKNOWN, $e); } } /** * Send an email message representing a link. * - * @param string $to Recipient email address - * @param string|\Laminas\Mail\Address $from Sender name and email - * address - * @param string $msg User notes to include in - * message - * @param string $url URL to share - * @param \Laminas\View\Renderer\PhpRenderer $view View object (used to render - * email templates) - * @param string $subject Subject for email - * (optional) - * @param string $cc CC recipient (null for - * none) - * @param string|Address|AddressList $replyTo Reply-To address (or - * delimited list, null for none) + * @param string|string[]|Address|Address[] $to Recipient email address(es) (or delimited list) + * @param string|Address $from Sender name and email address + * @param string $msg User notes to include in message + * @param string $url URL to share + * @param PhpRenderer $view View object (used to render email templates) + * @param ?string $subject Subject for email (optional) + * @param string|string[]|Address|Address[]|null $cc CC recipient(s) (null for none) + * @param string|string[]|Address|Address[]|null $replyTo Reply-To address(es) (or delimited list, null for none) * * @throws MailException * @return void */ public function sendLink( - $to, - $from, - $msg, - $url, - $view, - $subject = null, - $cc = null, - $replyTo = null + string|Address|array $to, + string|Address $from, + string $msg, + string $url, + PhpRenderer $view, + ?string $subject = null, + string|Address|array|null $cc = null, + string|Address|array|null $replyTo = null ) { if (null === $subject) { $subject = $this->getDefaultLinkSubject(); @@ -399,33 +358,27 @@ public function getDefaultLinkSubject() /** * Send an email message representing a record. * - * @param string $to Recipient email address - * @param string|\Laminas\Mail\Address $from Sender name and email - * address - * @param string $msg User notes to include in - * message - * @param \VuFind\RecordDriver\AbstractBase $record Record being emailed - * @param \Laminas\View\Renderer\PhpRenderer $view View object (used to render - * email templates) - * @param string $subject Subject for email - * (optional) - * @param string $cc CC recipient (null for - * none) - * @param string|Address|AddressList $replyTo Reply-To address (or - * delimited list, null for none) + * @param string|Address|Address[] $to Recipient email address(es) (or delimited list) + * @param string|Address $from Sender name and email address + * @param string $msg User notes to include in message + * @param AbstractBase $record Record being emailed + * @param PhpRenderer $view View object (used to render email templates) + * @param ?string $subject Subject for email (optional) + * @param string|Address|Address[]|null $cc CC recipient(s) (null for none) + * @param string|Address|Address[]|null $replyTo Reply-To address(es) (or delimited list, null for none) * * @throws MailException * @return void */ public function sendRecord( - $to, - $from, - $msg, - $record, - $view, - $subject = null, - $cc = null, - $replyTo = null + string|Address|array $to, + string|Address $from, + string $msg, + AbstractBase $record, + PhpRenderer $view, + ?string $subject = null, + string|Address|array|null $cc = null, + string|Address|array|null $replyTo = null ) { if (null === $subject) { $subject = $this->getDefaultRecordSubject($record); @@ -460,8 +413,7 @@ public function setMaxRecipients($max) */ public function getDefaultRecordSubject($record) { - return $this->translate('Library Catalog Record') . ': ' - . $record->getBreadcrumb(); + return $this->translate('Library Catalog Record') . ': ' . $record->getBreadcrumb(); } /** @@ -487,21 +439,27 @@ public function setFromAddressOverride($address) } /** - * Convert the given addresses to an AddressList object + * Convert the given addresses to an array * - * @param string|Address|AddressList $addresses Addresses + * @param string|Address|Address[]|null $addresses Addresses * - * @return AddressList + * @return array */ - protected function convertToAddressList($addresses) + protected function convertToAddressList(string|Address|array|null $addresses): array { - if ($addresses instanceof AddressList) { - $result = $addresses; - } elseif ($addresses instanceof Address) { - $result = new AddressList(); - $result->add($addresses); - } else { - $result = $this->stringToAddressList($addresses ? $addresses : ''); + if (empty($addresses)) { + return []; + } + if ($addresses instanceof Address) { + return [$addresses]; + } + if (is_array($addresses)) { + // Address::createArray takes an array of strings or Address objects, so this handles both cases: + return Address::createArray($addresses); + } + $result = []; + foreach (explode(';', $addresses) as $current) { + $result[] = Address::create($current); } return $result; } diff --git a/module/VuFind/src/VuFind/Mailer/Message.php b/module/VuFind/src/VuFind/Mailer/Message.php deleted file mode 100644 index 2d291b1e301..00000000000 --- a/module/VuFind/src/VuFind/Mailer/Message.php +++ /dev/null @@ -1,96 +0,0 @@ - - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ - -namespace VuFind\Mailer; - -use Laminas\Mail\AddressList; - -/** - * Tweaked Laminas Message class - * - * @category VuFind - * @package Mailer - * @author Ere Maijala - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ -class Message extends \Laminas\Mail\Message -{ - /** - * Retrieve list of From senders - * - * Returns our local "From" class - * - * @return AddressList - */ - public function getFrom() - { - return $this->getAddressListFromHeader('from', From::class); - } - - /** - * Access the address list of the To header - * - * @return AddressList - */ - public function getTo() - { - return $this->getAddressListFromHeader('to', To::class); - } - - /** - * Retrieve list of CC recipients - * - * @return AddressList - */ - public function getCc() - { - return $this->getAddressListFromHeader('cc', Cc::class); - } - - /** - * Retrieve list of BCC recipients - * - * @return AddressList - */ - public function getBcc() - { - return $this->getAddressListFromHeader('bcc', Bcc::class); - } - - /** - * Access the address list of the Reply-To header - * - * @return AddressList - */ - public function getReplyTo() - { - return $this->getAddressListFromHeader('reply-to', ReplyTo::class); - } -} diff --git a/module/VuFind/src/VuFind/Mailer/ReplyTo.php b/module/VuFind/src/VuFind/Mailer/ReplyTo.php deleted file mode 100644 index a022782aaf2..00000000000 --- a/module/VuFind/src/VuFind/Mailer/ReplyTo.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ - -namespace VuFind\Mailer; - -/** - * Tweaked Laminas "ReplyTo" header class - * - * @category VuFind - * @package Mailer - * @author Ere Maijala - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ -class ReplyTo extends \Laminas\Mail\Header\ReplyTo -{ - use GetFieldValueFixTrait; -} diff --git a/module/VuFind/src/VuFind/Mailer/To.php b/module/VuFind/src/VuFind/Mailer/To.php deleted file mode 100644 index 44390d2f968..00000000000 --- a/module/VuFind/src/VuFind/Mailer/To.php +++ /dev/null @@ -1,44 +0,0 @@ - - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ - -namespace VuFind\Mailer; - -/** - * Tweaked Laminas "To" header class - * - * @category VuFind - * @package Mailer - * @author Ere Maijala - * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License - * @link https://vufind.org/wiki/development Wiki - */ -class To extends \Laminas\Mail\Header\To -{ - use GetFieldValueFixTrait; -} diff --git a/module/VuFind/src/VuFindTest/Feature/EmailTrait.php b/module/VuFind/src/VuFindTest/Feature/EmailTrait.php index 77da4e60e67..61ac8b3802f 100644 --- a/module/VuFind/src/VuFindTest/Feature/EmailTrait.php +++ b/module/VuFind/src/VuFindTest/Feature/EmailTrait.php @@ -29,6 +29,8 @@ namespace VuFindTest\Feature; +use Symfony\Component\Mime\Email; + /** * Trait adding the ability to inspect sent emails. * @@ -50,6 +52,16 @@ protected function getEmailLogPath(): string return APPLICATION_PATH . '/vufind-mail.log'; } + /** + * Get the format to use for email message log. + * + * @return string + */ + protected function getEmailLogFormat(): string + { + return 'serialized'; + } + /** * Clear out the email log to eliminate any past contents. * @@ -59,4 +71,24 @@ protected function resetEmailLog(): void { file_put_contents($this->getEmailLogPath(), ''); } + + /** + * Get a logged email from the log file. + * + * @param int $index Index of the message to get (0-based) + * + * @return Email + */ + protected function getLoggedEmail(int $index = 0): Email + { + $data = file_get_contents($this->getEmailLogPath()); + if (!$data) { + throw new \Exception('No serialized email message data found'); + } + $records = explode("\x1E", $data); + if (null === ($record = $records[$index] ?? null)) { + throw new \Exception("Message with index $index not found"); + } + return unserialize($record); + } } diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/AccountActionsTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/AccountActionsTest.php index 75ee44791b1..b0b71ebd103 100644 --- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/AccountActionsTest.php +++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/AccountActionsTest.php @@ -474,6 +474,7 @@ public function testRecoverPasswordByUsername(): void 'Mail' => [ 'testOnly' => true, 'message_log' => $this->getEmailLogPath(), + 'message_log_format' => $this->getEmailLogFormat(), ], ], ] @@ -498,8 +499,8 @@ public function testRecoverPasswordByUsername(): void ); // Extract URL from email: - $email = file_get_contents($this->getEmailLogPath()); - preg_match('/You can reset your password at this URL: (http.*)/', $email, $matches); + $email = $this->getLoggedEmail(); + preg_match('/You can reset your password at this URL: (http.*)/', $email->getBody()->getBody(), $matches); $link = $matches[1]; // Reset the password: diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/ChoiceAuthTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/ChoiceAuthTest.php index ccba4bc5b0e..c4988cad62d 100644 --- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/ChoiceAuthTest.php +++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/ChoiceAuthTest.php @@ -104,6 +104,7 @@ protected function getConfigIniEmailOverrides(): array 'Mail' => [ 'testOnly' => true, 'message_log' => $this->getEmailLogPath(), + 'message_log_format' => $this->getEmailLogFormat(), ], ]; } @@ -286,8 +287,8 @@ public function testEmailAuthentication(): void ); // Extract the link from the provided message: - $email = file_get_contents($this->getEmailLogPath()); - preg_match('/Link to login: <(http.*)>/', $email, $matches); + $email = $this->getLoggedEmail(); + preg_match('/Link to login: <(http.*)>/', $email->getBody()->getBody(), $matches); $session->visit($matches[1]); // Log out diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/EmailVerificationTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/EmailVerificationTest.php index b224bfa19cd..74382855c19 100644 --- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/EmailVerificationTest.php +++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/EmailVerificationTest.php @@ -73,6 +73,7 @@ public function testEmailVerification(): void 'Mail' => [ 'testOnly' => true, 'message_log' => $this->getEmailLogPath(), + 'message_log_format' => $this->getEmailLogFormat(), ], ], ] @@ -94,8 +95,12 @@ public function testEmailVerification(): void ); // Extract the link from the provided message: - $email = file_get_contents($this->getEmailLogPath()); - preg_match('/You can verify your email address with this link: <(http.*)>/', $email, $matches); + $email = $this->getLoggedEmail(); + preg_match( + '/You can verify your email address with this link: <(http.*)>/', + $email->getBody()->getBody(), + $matches + ); $verifyLink = $matches[1]; // Follow the verification link: @@ -136,6 +141,7 @@ public function testEmailAddressChange(): void 'Mail' => [ 'testOnly' => true, 'message_log' => $this->getEmailLogPath(), + 'message_log_format' => $this->getEmailLogFormat(), ], ], ] @@ -170,15 +176,21 @@ public function testEmailAddressChange(): void ); // Confirm that messages went to both new and old email addresses, and extract the verify link: - $email = file_get_contents($this->getEmailLogPath()); - $this->assertStringContainsString('To: changed@example.com', $email); - $this->assertStringContainsString('To: username1@ignore.com', $email); + $email = $this->getLoggedEmail(0); + $this->assertEquals('To: changed@example.com', $email->getHeaders()->get('to')->toString()); + preg_match( + '/You can verify your email address with this link: <(http.*)>/', + $email->getBody()->getBody(), + $matches + ); + $verifyLink = $matches[1]; + + $notifyEmail = $this->getLoggedEmail(1); + $this->assertEquals('To: username1@ignore.com', $notifyEmail->getHeaders()->get('to')->toString()); $this->assertStringContainsString( 'A request was just made to change your email address at Library Catalog.', - $email + $notifyEmail->getBody()->getBody() ); - preg_match('/You can verify your email address with this link: <(http.*)>/', $email, $matches); - $verifyLink = $matches[1]; // Follow the verification link: $session->visit($verifyLink); diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/UrlShortenerTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/UrlShortenerTest.php index 84f7897161b..5c2355eea91 100644 --- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/UrlShortenerTest.php +++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/UrlShortenerTest.php @@ -57,6 +57,7 @@ public function testDatabaseDrivenShortening(): void 'email_action' => 'enabled', 'testOnly' => true, 'message_log' => $this->getEmailLogPath(), + 'message_log_format' => $this->getEmailLogFormat(), 'url_shortener' => 'database', ], ], @@ -76,8 +77,8 @@ public function testDatabaseDrivenShortening(): void $this->assertEquals('Message Sent', $this->findCssAndGetText($page, '.modal .alert-success')); // Extract the link from the provided message: - $email = file_get_contents($this->getEmailLogPath()); - preg_match('/Link: <(http.*)>/', $email, $matches); + $email = $this->getLoggedEmail(); + preg_match('/Link: <(http.*)>/', $email->getBody()->getBody(), $matches); $shortLink = $matches[1]; $this->assertNotEquals($searchUrl, $shortLink); $this->assertStringContainsString('/short', $shortLink); diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Mailer/MailerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Mailer/MailerTest.php index 1906d9ff29e..b1b9bef9fe8 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/Mailer/MailerTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Mailer/MailerTest.php @@ -29,8 +29,8 @@ namespace VuFindTest\Mailer; -use Laminas\Mail\Address; -use Laminas\Mail\AddressList; +use Symfony\Component\Mailer\MailerInterface; +use Symfony\Component\Mime\Address; use VuFind\Mailer\Factory as MailerFactory; use VuFind\Mailer\Mailer; use VuFindTest\Container\MockContainer; @@ -49,6 +49,7 @@ class MailerTest extends \PHPUnit\Framework\TestCase { use \VuFindTest\Feature\ConfigPluginManagerTrait; + use \VuFindTest\Feature\ReflectionTrait; /** * Test that the factory configures the object correctly. @@ -61,26 +62,30 @@ public function testFactoryConfiguration() 'Mail' => [ 'host' => 'vufindtest.localhost', 'port' => 123, - 'connection_time_limit' => 600, - 'name' => 'foo', + 'name' => 'foo?bar', 'username' => 'vufinduser', 'password' => 'vufindpass', + 'connection_time_limit' => 60, + ], + ]; + $configDsn = [ + 'Mail' => [ + 'dsn' => 'esmtp://foo@bar/', ], ]; $cm = $this->getMockConfigPluginManager(compact('config')); $sm = new MockContainer($this); $sm->set(\VuFind\Config\PluginManager::class, $cm); $factory = new MailerFactory(); - $mailer = $factory($sm, Mailer::class); - $options = $mailer->getTransport()->getOptions(); - $this->assertEquals('vufindtest.localhost', $options->getHost()); - $this->assertEquals('foo', $options->getName()); - $this->assertEquals(123, $options->getPort()); - $this->assertEquals(600, $options->getConnectionTimeLimit()); - $this->assertEquals('login', $options->getConnectionClass()); + + $this->assertEquals( + 'smtp://vufinduser:vufindpass@vufindtest.localhost:123?local_domain=foo%3Fbar&ping_threshold=60', + $this->callMethod($factory, 'getDSN', [$config]) + ); + $this->assertEquals( - ['username' => 'vufinduser', 'password' => 'vufindpass'], - $options->getConnectionConfig() + 'esmtp://foo@bar/', + $this->callMethod($factory, 'getDSN', [$configDsn]) ); } @@ -92,14 +97,12 @@ public function testFactoryConfiguration() public function testSend() { $callback = function ($message): bool { - return '' == $message->getTo()->current()->toString() - && '' == $message->getFrom()->current()->toString() - && 'body' == $message->getBody() + return 'to@example.com' == $message->getTo()[0]->toString() + && 'from@example.com' == $message->getFrom()[0]->toString() + && 'body' == $message->getBody()->getBody() && 'subject' == $message->getSubject(); }; - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $transport->expects($this->once())->method('send')->with($this->callback($callback)); - $mailer = new Mailer($transport); + $mailer = $this->getMailer($callback); $mailer->send('to@example.com', 'from@example.com', 'subject', 'body'); } @@ -111,16 +114,13 @@ public function testSend() public function testSendWithAddressObjectInSender() { $callback = function ($message): bool { - $fromString = $message->getFrom()->current()->toString(); - return '' == $message->getTo()->current()->toString() - && 'Sender TextName ' == $fromString - && 'body' == $message->getBody() + return 'to@example.com' == $message->getTo()[0]->toString() + && '"Sender TextName" ' == $message->getFrom()[0]->toString() + && 'body' == $message->getBody()->getBody() && 'subject' == $message->getSubject(); }; - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $transport->expects($this->once())->method('send')->with($this->callback($callback)); + $mailer = $this->getMailer($callback); $address = new Address('from@example.com', 'Sender TextName'); - $mailer = new Mailer($transport); $mailer->send('to@example.com', $address, 'subject', 'body'); } @@ -132,36 +132,33 @@ public function testSendWithAddressObjectInSender() public function testSendWithAddressObjectInRecipient() { $callback = function ($message): bool { - return 'Recipient TextName ' == $message->getTo()->current()->toString() - && '' == $message->getFrom()->current()->toString() - && 'body' == $message->getBody() + return '"Recipient TextName" ' == $message->getTo()[0]->toString() + && 'from@example.com' == $message->getFrom()[0]->toString() + && 'body' == $message->getBody()->getBody() && 'subject' == $message->getSubject(); }; - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $transport->expects($this->once())->method('send')->with($this->callback($callback)); + $mailer = $this->getMailer($callback); $address = new Address('to@example.com', 'Recipient TextName'); - $mailer = new Mailer($transport); $mailer->send($address, 'from@example.com', 'subject', 'body'); } /** - * Test sending an email using an address list object for the To field. + * Test sending an email using an address list for the To field. * * @return void */ - public function testSendWithAddressListObjectInRecipient() + public function testSendWithAddressListInRecipient() { $callback = function ($message): bool { - return 'Recipient TextName ' == $message->getTo()->current()->toString() - && '' == $message->getFrom()->current()->toString() - && 'body' == $message->getBody() + return '"Recipient TextName" ' == $message->getTo()[0]->toString() + && 'from@example.com' == $message->getFrom()[0]->toString() + && 'body' == $message->getBody()->getBody() && 'subject' == $message->getSubject(); }; - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $transport->expects($this->once())->method('send')->with($this->callback($callback)); - $list = new AddressList(); - $list->add(new Address('to@example.com', 'Recipient TextName')); - $mailer = new Mailer($transport); + $mailer = $this->getMailer($callback); + $list = [ + new Address('to@example.com', 'Recipient TextName'), + ]; $mailer->send($list, 'from@example.com', 'subject', 'body'); } @@ -173,18 +170,15 @@ public function testSendWithAddressListObjectInRecipient() public function testSendWithFromOverride() { $callback = function ($message): bool { - $fromString = $message->getFrom()->current()->toString(); - return '' == $message->getTo()->current()->toString() - && '' == $message->getReplyTo()->current()->toString() - && 'me ' == $fromString - && 'body' == $message->getBody() + return 'to@example.com' == $message->getTo()[0]->toString() + && 'me@example.com' == $message->getReplyTo()[0]->toString() + && '"me" ' == $message->getFrom()[0]->toString() + && 'body' == $message->getBody()->getBody() && 'subject' == $message->getSubject(); }; - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $transport->expects($this->once())->method('send')->with($this->callback($callback)); - $address = new Address('me@example.com'); - $mailer = new Mailer($transport); + $mailer = $this->getMailer($callback); $mailer->setFromAddressOverride('no-reply@example.com'); + $address = new Address('me@example.com'); $mailer->send('to@example.com', $address, 'subject', 'body'); } @@ -196,17 +190,14 @@ public function testSendWithFromOverride() public function testSendWithReplyTo() { $callback = function ($message): bool { - $fromString = $message->getFrom()->current()->toString(); - return '' == $message->getTo()->current()->toString() - && '' == $message->getReplyTo()->current()->toString() - && '' == $fromString - && 'body' == $message->getBody() + return 'to@example.com' == $message->getTo()[0]->toString() + && 'reply-to@example.com' == $message->getReplyTo()[0]->toString() + && 'me@example.com' == $message->getFrom()[0]->toString() + && 'body' == $message->getBody()->getBody() && 'subject' == $message->getSubject(); }; - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $transport->expects($this->once())->method('send')->with($this->callback($callback)); + $mailer = $this->getMailer($callback); $address = new Address('me@example.com'); - $mailer = new Mailer($transport); $mailer->send('to@example.com', $address, 'subject', 'body', null, 'reply-to@example.com'); } @@ -219,18 +210,16 @@ public function testSendWithReplyTo() public function testSendWithFromOverrideAndReplyTo() { $callback = function ($message): bool { - $fromString = $message->getFrom()->current()->toString(); - return '' == $message->getTo()->current()->toString() - && '' == $message->getReplyTo()->current()->toString() - && 'me ' == $fromString - && 'body' == $message->getBody() + $fromString = $message->getFrom()[0]->toString(); + return 'to@example.com' == $message->getTo()[0]->toString() + && 'reply-to@example.com' == $message->getReplyTo()[0]->toString() + && '"me" ' == $fromString + && 'body' == $message->getBody()->getBody() && 'subject' == $message->getSubject(); }; - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $transport->expects($this->once())->method('send')->with($this->callback($callback)); - $address = new Address('me@example.com'); - $mailer = new Mailer($transport); + $mailer = $this->getMailer($callback); $mailer->setFromAddressOverride('no-reply@example.com'); + $address = new Address('me@example.com'); $mailer->send('to@example.com', $address, 'subject', 'body', null, 'reply-to@example.com'); } @@ -245,9 +234,8 @@ public function testBadTo() $this->expectExceptionMessage('Invalid Recipient Email Address'); $this->expectExceptionCode(\VuFind\Exception\Mail::ERROR_INVALID_RECIPIENT); - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $mailer = new Mailer($transport); - $mailer->send('bad@bad', 'from@example.com', 'subject', 'body'); + $mailer = $this->getMailer(); + $mailer->send('bad@.bad', 'from@example.com', 'subject', 'body'); } /** @@ -261,15 +249,14 @@ public function testBadReplyTo() $this->expectExceptionMessage('Invalid Reply-To Email Address'); $this->expectExceptionCode(\VuFind\Exception\Mail::ERROR_INVALID_REPLY_TO); - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $mailer = new Mailer($transport); + $mailer = $this->getMailer(); $mailer->send( 'good@good.com', 'from@example.com', 'subject', 'body', null, - 'bad@bad' + 'bad@.bad' ); } @@ -284,8 +271,7 @@ public function testEmptyTo() $this->expectExceptionMessage('Invalid Recipient Email Address'); $this->expectExceptionCode(\VuFind\Exception\Mail::ERROR_INVALID_RECIPIENT); - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $mailer = new Mailer($transport); + $mailer = $this->getMailer(); $mailer->send('', 'from@example.com', 'subject', 'body'); } @@ -300,8 +286,7 @@ public function testTooManyRecipients() $this->expectExceptionMessage('Too Many Email Recipients'); $this->expectExceptionCode(\VuFind\Exception\Mail::ERROR_TOO_MANY_RECIPIENTS); - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $mailer = new Mailer($transport); + $mailer = $this->getMailer(); $mailer->send('one@test.com;two@test.com', 'from@example.com', 'subject', 'body'); } @@ -316,25 +301,8 @@ public function testBadFrom() $this->expectExceptionMessage('Invalid Sender Email Address'); $this->expectExceptionCode(\VuFind\Exception\Mail::ERROR_INVALID_SENDER); - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $mailer = new Mailer($transport); - $mailer->send('to@example.com', 'bad@bad', 'subject', 'body'); - } - - /** - * Test bad from address in Address object. - * - * @return void - */ - public function testBadFromInAddressObject() - { - $this->expectException(\VuFind\Exception\Mail::class); - $this->expectExceptionMessage('Invalid Sender Email Address'); - $this->expectExceptionCode(\VuFind\Exception\Mail::ERROR_INVALID_SENDER); - - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $mailer = new Mailer($transport); - $mailer->send('to@example.com', new Address('bad@bad'), 'subject', 'body'); + $mailer = $this->getMailer(); + $mailer->send('to@example.com', 'bad@.bad', 'subject', 'body'); } /** @@ -347,7 +315,7 @@ public function testTransportException() $this->expectException(\VuFind\Exception\Mail::class); $this->expectExceptionMessage('Boom'); - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); + $transport = $this->createMock(MailerInterface::class); $transport->expects($this->once())->method('send')->will($this->throwException(new \Exception('Boom'))); $mailer = new Mailer($transport); $mailer->send('to@example.com', 'from@example.com', 'subject', 'body'); @@ -397,17 +365,15 @@ public function testSendLink() $callback = function ($message): bool { $to = $message->getTo(); - return $to->has('to@example.com') - && $to->has('to2@example.com') + return 'to@example.com' === $to[0]->toString() + && 'to2@example.com' === $to[1]->toString() && 2 == count($to) - && '' == $message->getFrom()->current()->toString() - && '' == $message->getCc()->current()->toString() - && 'body' == $message->getBody() + && 'from@example.com' == $message->getFrom()[0]->toString() + && 'cc@example.com' == $message->getCc()[0]->toString() + && 'body' == $message->getBody()->getBody() && 'Library Catalog Search Result' == $message->getSubject(); }; - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $transport->expects($this->once())->method('send')->with($this->callback($callback)); - $mailer = new Mailer($transport); + $mailer = $this->getMailer($callback); $mailer->setMaxRecipients(2); $mailer->sendLink( 'to@example.com;to2@example.com', @@ -443,30 +409,15 @@ public function testSendRecord() ->will($this->returnValue('body')); $callback = function ($message): bool { - return '' == $message->getTo()->current()->toString() - && '' == $message->getFrom()->current()->toString() - && 'body' == $message->getBody() + return 'to@example.com' == $message->getTo()[0]->toString() + && 'from@example.com' == $message->getFrom()[0]->toString() + && 'body' == $message->getBody()->getBody() && 'Library Catalog Record: breadcrumb' == $message->getSubject(); }; - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $transport->expects($this->once())->method('send')->with($this->callback($callback)); - $mailer = new Mailer($transport); + $mailer = $this->getMailer($callback); $mailer->sendRecord('to@example.com', 'from@example.com', 'message', $driver, $view); } - /** - * Test connection reset - * - * @return void - */ - public function testResetConnection() - { - $transport = $this->createMock(\Laminas\Mail\Transport\Smtp::class); - $transport->expects($this->once())->method('disconnect'); - $mailer = new Mailer($transport); - $mailer->resetConnection(); - } - /** * Test sending an email using with text part and html part and multipart content type. * @@ -478,19 +429,31 @@ public function testSendMimeMessageWithMultipartAlternativeContentType() $html = 'htmlhtml body part'; $text = 'this is the text part'; $callback = function ($message) use ($html, $text): bool { - $fromString = $message->getFrom()->current()->toString(); - return '' == $message->getTo()->current()->toString() - && 'Sender TextName ' == $fromString + return 'to@example.com' == $message->getTo()[0]->toString() + && '"Sender TextName" ' == $message->getFrom()[0]->toString() && 'subject' == $message->getSubject() - && 0 <= strpos($message->getBody()->getParts()[0]->getContent(), $html) - && 0 <= strpos($message->getBody()->getParts()[0]->getContent(), $text) - && 'multipart/alternative' == $message->getHeaders()->get('Content-Type')->getType(); + && str_contains($message->getBody()->getParts()[0]->getBody(), $text) + && str_contains($message->getBody()->getParts()[1]->getBody(), $html); }; - $transport = $this->createMock(\Laminas\Mail\Transport\TransportInterface::class); - $transport->expects($this->once())->method('send')->with($this->callback($callback)); $address = new Address('from@example.com', 'Sender TextName'); - $mailer = new Mailer($transport); + $mailer = $this->getMailer($callback); $body = $mailer->buildMultipartBody($text, $html); $mailer->send('to@example.com', $address, 'subject', $body); } + + /** + * Create mailer with a mock transport + * + * @param ?callable $callback Mock send method result callback + * + * @return Mailer + */ + protected function getMailer($callback = null) + { + $transport = $this->createMock(MailerInterface::class); + if ($callback) { + $transport->expects($this->once())->method('send')->with($this->callback($callback)); + } + return new Mailer($transport); + } }