Skip to content

Commit

Permalink
#5885 added context checking first if available to resolve context pa…
Browse files Browse the repository at this point in the history
…th before resolving from request
  • Loading branch information
touhidurabir committed Jun 13, 2024
1 parent c23a9b1 commit 0883111
Showing 1 changed file with 255 additions and 0 deletions.
255 changes: 255 additions & 0 deletions classes/invitation/invitations/BaseInvitation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
<?php

/**
* @file classes/invitation/invitations/BaseInvitation.php
*
* Copyright (c) 2023 Simon Fraser University
* Copyright (c) 2023 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class BaseInvitation
*
* @brief Abstract class for all Invitations
*/

namespace PKP\invitation\invitations;

use APP\core\Application;
use Carbon\Carbon;
use DateTime;
use Exception;
use Illuminate\Mail\Mailable;
use Illuminate\Support\Facades\Mail;
use PKP\config\Config;
use PKP\context\Context;
use PKP\facades\Repo;
use PKP\invitation\invitations\enums\InvitationStatus;
use PKP\invitation\models\Invitation;
use PKP\pages\invitation\PKPInvitationHandler;
use PKP\security\Validation;
use ReflectionClass;
use Symfony\Component\Mailer\Exception\TransportException;

abstract class BaseInvitation
{
public const DEFAULT_EXPIRY_DAYS = 3;

/**
* The name of the class name of the specific invitation
*/
public string $className;
private string $keyHash;
public string $key;
public DateTime $expirationDate;

private int $id;

protected ?Mailable $mailable = null;
protected ?Context $context = null;

public function __construct(
public ?int $userId,
public ?string $email,
public ?int $contextId,
public ?int $assocId,
?int $expiryDays = null
) {
$expiryDays ??= Config::getVar('invitations', 'expiration_days', self::DEFAULT_EXPIRY_DAYS);
$this->expirationDate = Carbon::now()->addDays($expiryDays);
$this->className = $this::class;
}

public function getPayload(): array
{
$values = [];

$reflection = new ReflectionClass($this->className);
$constructor = $reflection->getConstructor();

if ($constructor) {
// If the constructor exists, get its parameters
$parameters = $constructor->getParameters();

// Loop through the parameters and get their values from the object
foreach ($parameters as $parameter) {
$propertyName = $parameter->getName();
$propertyValue = $reflection->getProperty($propertyName)->getValue($this);
$values[$propertyName] = $propertyValue;
}
}

return $values;
}

public function markStatus(InvitationStatus $status): void
{
$invitation = Repo::invitation()
->getByKeyHash($this->keyHash);

if (is_null($invitation)) {
throw new Exception('This invitation was not found');
}

$invitation->markAs($status);
}

public function acceptHandle(): void
{
$this->markStatus(InvitationStatus::ACCEPTED);
}
public function declineHandle(): void
{
$this->markStatus(InvitationStatus::DECLINED);
}

abstract public function getMailable(): ?Mailable;
abstract public function preDispatchActions(): bool;

public function getAcceptUrl(): string
{
$request = Application::get()->getRequest();
return $request->getDispatcher()
->url(
$request,
Application::ROUTE_PAGE,
$this->context?->getPath() ?? $request->getContext()->getPath(),
PKPInvitationHandler::REPLY_PAGE,
PKPInvitationHandler::REPLY_OP_ACCEPT,
null,
[
'id' => $this->getId(),
'key' => $this->key,
]
);
}
public function getDeclineUrl(): string
{
$request = Application::get()->getRequest();
return $request->getDispatcher()
->url(
$request,
Application::ROUTE_PAGE,
$this->context?->getPath() ?? $request->getContext()->getPath(),
PKPInvitationHandler::REPLY_PAGE,
PKPInvitationHandler::REPLY_OP_DECLINE,
null,
[
'id' => $this->getId(),
'key' => $this->key,
]
);
}

public function dispatch(bool $sendEmail = false): bool
{
// Need to return error messages also?
if (!$this->preDispatchActions()) {
return false;
}

if (!isset($this->keyHash)) {
if (!isset($this->key)) {
$this->key = Validation::generatePassword();
}

$this->keyHash = self::makeKeyHash($this->key);
}

$invitationId = Repo::invitation()->addInvitation($this);

$this->setId($invitationId);

$mailable = $this->getMailable();

if ($sendEmail && isset($mailable)) {
try {
Mail::to($this->email)
->send($mailable);

} catch (TransportException $e) {
trigger_error('Failed to send email invitation: ' . $e->getMessage(), E_USER_ERROR);
}
}

return true;
}

public function isKeyValid(string $key): bool
{
$keyHash = self::makeKeyHash($key);

return $keyHash == $this->keyHash;
}

public function getExcludedPayloadVariables(): array
{
return [
'mailable',
'context',
'userId',
'assocId',
'key',
'keyHash',
'expirationDate',
'className',
'email',
'contextId',
];
}

public function setMailable(Mailable $mailable): void
{
$this->mailable = $mailable;
}

public function setKeyHash(string $keyHash): void
{
$this->keyHash = $keyHash;
}

public function getKeyHash(): string
{
return $this->keyHash;
}

public function setExpirationDate(Carbon $expirationDate): void
{
$this->expirationDate = $expirationDate;
}

public function setInvitationModel(Invitation $invitationModel)
{
$this->keyHash = $invitationModel->keyHash;
$this->expirationDate = $invitationModel->expiryDate;
$this->id = $invitationModel->id;
}

/**
* Check if invitation is expired
*/
public function isExpired(): bool
{
$currentDateTime = Carbon::now();

if ($this->expirationDate > $currentDateTime) {
return false;
}

return false;
}

public static function makeKeyHash($key): string
{
return password_hash($key, PASSWORD_BCRYPT);
}

public function setId($id): void
{
$this->id = $id;
}

public function getId(): int
{
return $this->id;
}
}

0 comments on commit 0883111

Please sign in to comment.