foldershare-8.x-1.2/src/Entity/FolderShareTraits/OperationShareTrait.php
src/Entity/FolderShareTraits/OperationShareTrait.php
<?php
namespace Drupal\foldershare\Entity\FolderShareTraits;
use Drupal\user\Entity\User;
use Drupal\foldershare\ManageLog;
use Drupal\foldershare\Entity\Exception\LockException;
/**
* Share FolderShare entities.
*
* This trait includes methods to share FolderShare entities.
*
* <B>Internal trait</B>
* This trait is internal to the FolderShare module and used to define
* features of the FolderShare entity class. It is a mechanism to group
* functionality to improve code management.
*
* @ingroup foldershare
*/
trait OperationShareTrait {
/*---------------------------------------------------------------------
*
* Share FolderShare entity.
*
*---------------------------------------------------------------------*/
/**
* {@inheritdoc}
*/
public function share(array $grants) {
if ($this->isRootItem() === FALSE) {
// Not a root. Only roots have access grants.
return;
}
//
// Lock root folder tree.
// ----------------------
// Lock the folder tree rooted on this item. This prevents other operations
// from modifying this item or its folder tree until grants are updated.
//
// LOCK ROOT FOLDER TREE.
if (self::acquireRootOperationLock($this->id()) === FALSE) {
throw new LockException(
self::getStandardLockExceptionMessage(t('updated'), $this->getName()));
}
//
// Update access grants.
// ---------------------
// Set the grants and save.
$oldGrants = $this->getAccessGrants();
$this->setAccessGrants($grants);
$this->save();
//
// Unlock root folder tree.
// ------------------------
// After access grants are set, we're done.
//
// UNLOCK ROOT FOLDER TREE.
self::releaseRootOperationLock($this->id());
//
// Hook & log.
// -----------
// Announce the change.
$requestingUid = self::getCurrentUserId()[0];
self::postOperationHook(
'share',
[
$this,
$oldGrants,
$grants,
$requestingUid,
]);
ManageLog::activity(
"Changed sharing for top-level @kind '@name' (# @id).\nOld grants: @oldGrants.\nNew grants: @newGrants.",
[
'@id' => $this->id(),
'@kind' => $this->getKind(),
'@name' => $this->getName(),
'@oldGrants' => self::accessGrantsToString($oldGrants),
'@newGrants' => self::accessGrantsToString($grants),
'entity' => $this,
'uid' => $requestingUid,
]);
}
/*---------------------------------------------------------------------
*
* Unshare FolderShare entity.
*
*---------------------------------------------------------------------*/
/**
* {@inheritdoc}
*/
public function unshare(int $uid, string $access = '') {
if ($this->isRootItem() === FALSE) {
// Not a root. Only roots have access grants.
return;
}
//
// Lock root folder tree.
// ----------------------
// Lock the folder tree rooted on this item. This prevents other operations
// from modifying this item or its folder tree until grants are updated.
//
// LOCK ROOT FOLDER TREE.
if (self::acquireRootOperationLock($this->id()) === FALSE) {
throw new LockException(
self::getStandardLockExceptionMessage(t('updated'), $this->getName()));
}
//
// Update access grants.
// ---------------------
// Remove the indicated user from the access grants.
$oldGrants = $this->getAccessGrants();
if (empty($access) === TRUE) {
$this->deleteAccessGrant($uid, 'view');
$this->deleteAccessGrant($uid, 'author');
$access = 'view & author';
}
else {
$this->deleteAccessGrant($uid, $access);
}
$newGrants = $this->getAccessGrants();
$this->save();
//
// Unlock root folder tree.
// ------------------------
// After access grants are set, we're done.
//
// UNLOCK ROOT FOLDER TREE.
self::releaseRootOperationLock($this->id());
//
// Hook & log.
// -----------
// Announce the change.
$requestingUid = self::getCurrentUserId()[0];
self::postOperationHook(
'share',
[
$this,
$oldGrants,
$newGrants,
$requestingUid,
]);
if (ManageLog::isActivityLoggingEnabled() === TRUE) {
$user = User::load($uid);
$userName = ($user === NULL) ? 'Unknown' : $user->getDisplayName();
ManageLog::activity(
"Release sharing for top-level @kind '@name' (# @id) for user %userName (# @uid) to @access.\nOld grants: @oldGrants.\nNew grants: @newGrants.",
[
'@id' => $this->id(),
'@kind' => $this->getKind(),
'@name' => $this->getName(),
'%userName' => $userName,
'@uid' => $uid,
'@access' => $access,
'@oldGrants' => self::accessGrantsToString($oldGrants),
'@newGrants' => self::accessGrantsToString($newGrants),
'entity' => $this,
'uid' => $requestingUid,
]);
}
}
/**
* Unshares multiple items.
*
* Each of the indicated items has its access grants adjusted to remove
* the indicated user for shared access. The $access argument may be
* 'view' or 'author', or left empty to unshare for both.
*
* <B>Process locks</B>
* This method locks each item's root folder tree for the duration of the
* update. This will prevent any other edit operation from being performed
* on the same folder tree until the update is done.
*
* <B>Post-operation hooks</B>
* This method calls the "hook_foldershare_post_operation_share" hook
* after each item is updated.
*
* <B>Activity log</B>
* This method posts a log message after each item has been updated.
*
* @param int[] $ids
* An array of integer FolderShare entity IDs to unshare. Invalid IDs
* are silently skipped.
* @param int $uid
* The user ID of the user to unshare for.
* @param string $access
* The access grant to unshare. One of 'view' or 'author'. An empty
* string unshares for 'view' AND 'author'.
*
* @throws \Drupal\foldershare\Entity\Exception\LockException
* Throws an exception if this item cannot be locked for exclusive use.
*
* @see ::unshare()
*/
public static function unshareMultiple(
array $ids,
int $uid,
string $access = '') {
$nLockExceptions = 0;
foreach ($ids as $id) {
$item = self::load($id);
if ($item !== NULL) {
try {
$item->unshare($uid, $access);
}
catch (LockException $e) {
++$nLockExceptions;
}
}
}
if ($nLockExceptions !== 0) {
throw new LockException(
self::getStandardLockExceptionMessage(t('updated'), NULL));
}
}
}
