class AgreementHandler in Agreement 3.0.x
Same name and namespace in other branches
- 8.2 src/AgreementHandler.php \Drupal\agreement\AgreementHandler
Agreement handler provides methods for looking up agreements.
Hierarchy
- class \Drupal\agreement\AgreementHandler implements AgreementHandlerInterface
Expanded class hierarchy of AgreementHandler
1 file declares its use of AgreementHandler
- AgreementHandlerTest.php in tests/
src/ Unit/ AgreementHandlerTest.php
2 string references to 'AgreementHandler'
- agreement.services.yml in ./
agreement.services.yml - agreement.services.yml
- agreement_types.yml in migrations/
agreement_types.yml - migrations/agreement_types.yml
1 service uses AgreementHandler
File
- src/
AgreementHandler.php, line 20
Namespace
Drupal\agreementView source
class AgreementHandler implements AgreementHandlerInterface {
/**
* Prefix to use for cookie names for anonymous agreements.
*/
const ANON_AGREEMENT_COOKIE_PREFIX = 'agreement_anon_';
/**
* Database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $connection;
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Path matcher.
*
* @var \Drupal\Core\Path\PathMatcherInterface
*/
protected $pathMatcher;
/**
* The datetime.time service.
*
* @var \Drupal\Component\Datetime\TimeInterface
*/
protected $time;
/**
* The request stack.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
/**
* Initialize method.
*
* @param \Drupal\Core\Database\Connection $connection
* The database connection.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\Core\Path\PathMatcherInterface $pathMatcher
* The path matcher service.
* @param \Drupal\Component\Datetime\TimeInterface $time
* The datetime.time service.
* @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
* The request stack.
*/
public function __construct(Connection $connection, EntityTypeManagerInterface $entityTypeManager, PathMatcherInterface $pathMatcher, TimeInterface $time, RequestStack $requestStack) {
$this->connection = $connection;
$this->entityTypeManager = $entityTypeManager;
$this->pathMatcher = $pathMatcher;
$this->time = $time;
$this->requestStack = $requestStack;
}
/**
* {@inheritdoc}
*/
public function agree(Agreement $agreement, AccountProxyInterface $account, $agreed = 1) {
if ($this
->isAnonymousAgreement($agreement, $account)) {
return $this
->agreeAnonymously($account, $agreement, $agreed);
}
return $this
->agreeWhileLoggedIn($account, $agreement, $agreed);
}
/**
* {@inheritdoc}
*/
public function hasAgreed(Agreement $agreement, AccountProxyInterface $account) {
if ($this
->isAnonymousAgreement($agreement, $account)) {
return $this
->hasAnonymousUserAgreed($agreement);
}
return $this
->hasAuthenticatedUserAgreed($agreement, $account);
}
/**
* {@inheritdoc}
*/
public function lastAgreed(Agreement $agreement, UserInterface $account) {
$query = $this->connection
->select('agreement');
$query
->fields('agreement', [
'agreed_date',
])
->condition('uid', $account
->id())
->condition('type', $agreement
->id())
->range(0, 1);
$agreed_date = $query
->execute()
->fetchField();
return $agreed_date === FALSE || $agreed_date === NULL ? -1 : $agreed_date;
}
/**
* {@inheritdoc}
*/
public function canAgree(Agreement $agreement, AccountProxyInterface $account) {
return !$account
->hasPermission('bypass agreement') && $agreement
->accountHasAgreementRole($account);
}
/**
* {@inheritdoc}
*/
public function isAnonymousAgreement(Agreement $agreement, AccountProxyInterface $account) {
if ($account
->isAnonymous() && in_array(RoleInterface::ANONYMOUS_ID, $agreement
->getSettings()['roles'])) {
return TRUE;
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function getAgreementByUserAndPath(AccountProxyInterface $account, $path) {
$agreement_types = $this->entityTypeManager
->getStorage('agreement')
->loadMultiple();
$default_exceptions = [
'/user/password',
'/user/register',
'/user/reset/*',
'/user/login',
'/user/logout',
'/admin/config/people/agreement',
'/admin/config/people/agreement/*',
'/admin/config/people/agreement/manage/*',
];
// Get a list of pages to never display agreements on.
$exceptions = array_reduce($agreement_types, function (&$result, Agreement $item) {
$result[] = $item
->get('path');
return $result;
}, $default_exceptions);
$exception_string = implode("\n", $exceptions);
if ($this->pathMatcher
->matchPath($path, $exception_string)) {
return FALSE;
}
// Reduce the agreement types based on the user role.
$agreements_with_roles = array_reduce($agreement_types, function (&$result, Agreement $item) use ($account) {
if ($item
->accountHasAgreementRole($account)) {
$result[] = $item;
}
return $result;
}, []);
// Try to find an agreement type that matches the path.
$pathMatcher = $this->pathMatcher;
$self = $this;
$info = array_reduce($agreements_with_roles, function (&$result, Agreement $item) use ($account, $path, $pathMatcher, $self) {
if ($result) {
// Always returns the first matched agreement.
return $result;
}
$pattern = $item
->getVisibilityPages();
$has_match = $pathMatcher
->matchPath($path, $pattern);
$has_agreed = $self
->hasAgreed($item, $account);
$visibility = (int) $item
->getVisibilitySetting();
if (0 === $visibility && FALSE === $has_match && !$has_agreed) {
// An agreement exists that matches any page.
$result = $item;
}
elseif (1 === $visibility && $has_match && !$has_agreed) {
// An agreement exists that matches the current path.
$result = $item;
}
return $result;
}, FALSE);
return $info;
}
/**
* {@inheritdoc}
*/
public static function prefixPath($value) {
return $value ? '/' . $value : $value;
}
/**
* Accept agreement for an anonymous user.
*
* @param \Drupal\Core\Session\AccountProxyInterface $account
* The user account to agree.
* @param \Drupal\agreement\Entity\Agreement $agreement
* The agreement that the user is agreeing to.
* @param int $agreed
* An optional integer to set the agreement status to. Defaults to 1.
*
* @return \Symfony\Component\HttpFoundation\Cookie
* A cookie to retain the user's acceptance of the agreement.
*/
protected function agreeAnonymously(AccountProxyInterface $account, Agreement $agreement, $agreed) {
$agreementType = $agreement
->id();
$cookieName = static::ANON_AGREEMENT_COOKIE_PREFIX . $agreementType;
$expire = 0;
if ($agreement
->getSettings()['frequency'] == 365) {
$expire = new \DateTime('+1 year');
}
elseif ($agreement
->agreeOnce()) {
$expire = new \DateTime('+10 years');
}
return new Cookie($cookieName, $agreed, $expire, '/', NULL, NULL, 'lax');
}
/**
* Accept agreement for an authenticated user.
*
* @param \Drupal\Core\Session\AccountProxyInterface $account
* The user account that is agreeing.
* @param \Drupal\agreement\Entity\Agreement $agreement
* The agreement that the user is agreeing to.
* @param int $agreed
* An optional integer to set the agreement status to. Defaults to 1.
*
* @return bool
* TRUE if the operation was successful. Otherwise FALSE.
*/
protected function agreeWhileLoggedIn(AccountProxyInterface $account, Agreement $agreement, $agreed) {
try {
$transaction = $this->connection
->startTransaction();
$this->connection
->delete('agreement')
->condition('uid', $account
->id())
->condition('type', $agreement
->id())
->execute();
$id = $this->connection
->insert('agreement')
->fields([
'uid' => $account
->id(),
'type' => $agreement
->id(),
'agreed' => $agreed,
'sid' => session_id(),
'agreed_date' => $this->time
->getRequestTime(),
])
->execute();
} catch (DatabaseExceptionWrapper $e) {
$transaction
->rollback();
return FALSE;
} catch (\Exception $e) {
$transaction
->rollback();
return FALSE;
}
return isset($id);
}
/**
* Check the status of the anonymous user for a particular agreement.
*
* @param \Drupal\agreement\Entity\Agreement $agreement
* The agreement to check if a user has agreed.
*
* @return bool
* TRUE if the user account has agreed to this agreement.
*/
protected function hasAnonymousUserAgreed(Agreement $agreement) {
$agreementType = $agreement
->id();
return $this->requestStack
->getCurrentRequest()->cookies
->has(static::ANON_AGREEMENT_COOKIE_PREFIX . $agreementType);
}
/**
* Check the status of a user account for a particular agreement.
*
* @param \Drupal\agreement\Entity\Agreement $agreement
* The agreement to check if a user has agreed.
* @param \Drupal\Core\Session\AccountProxyInterface $account
* The user account to check.
*
* @return bool
* TRUE if the user account has agreed to this agreement.
*/
protected function hasAuthenticatedUserAgreed(Agreement $agreement, AccountProxyInterface $account) {
$settings = $agreement
->getSettings();
$frequency = $settings['frequency'];
$query = $this->connection
->select('agreement');
$query
->fields('agreement', [
'agreed',
])
->condition('uid', $account
->id())
->condition('type', $agreement
->id())
->range(0, 1);
if ($frequency == 0) {
// Must agree on every login.
$query
->condition('sid', session_id());
}
else {
// Must agree when frequency is set greater than zero (number of days).
$timestamp = $agreement
->getAgreementFrequencyTimestamp();
if ($timestamp > 0) {
$query
->condition('agreed_date', $agreement
->getAgreementFrequencyTimestamp(), '>=');
}
}
$agreed = $query
->execute()
->fetchField();
return $agreed !== NULL && $agreed > 0;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
AgreementHandler:: |
protected | property | Database connection. | |
AgreementHandler:: |
protected | property | Entity type manager. | |
AgreementHandler:: |
protected | property | Path matcher. | |
AgreementHandler:: |
protected | property | The request stack. | |
AgreementHandler:: |
protected | property | The datetime.time service. | |
AgreementHandler:: |
public | function |
Accept the agreement for an user account. Overrides AgreementHandlerInterface:: |
|
AgreementHandler:: |
protected | function | Accept agreement for an anonymous user. | |
AgreementHandler:: |
protected | function | Accept agreement for an authenticated user. | |
AgreementHandler:: |
constant | Prefix to use for cookie names for anonymous agreements. | ||
AgreementHandler:: |
public | function |
Check if an user can bypass the agreement or if the agreement applies. Overrides AgreementHandlerInterface:: |
|
AgreementHandler:: |
public | function |
Find the agreement by user account and path. Overrides AgreementHandlerInterface:: |
|
AgreementHandler:: |
public | function |
Check the status of an user account for a particular agreement. Overrides AgreementHandlerInterface:: |
|
AgreementHandler:: |
protected | function | Check the status of the anonymous user for a particular agreement. | |
AgreementHandler:: |
protected | function | Check the status of a user account for a particular agreement. | |
AgreementHandler:: |
public | function |
Checks if we're processing an anonymous agreement. Overrides AgreementHandlerInterface:: |
|
AgreementHandler:: |
public | function |
Get the last agreement for the user for the agreement. Overrides AgreementHandlerInterface:: |
|
AgreementHandler:: |
public static | function |
Adds leading slash to a path string. Overrides AgreementHandlerInterface:: |
|
AgreementHandler:: |
public | function | Initialize method. |