foldershare-8.x-1.2/src/Entity/FolderShareTraits/OperationNewFolderTrait.php
src/Entity/FolderShareTraits/OperationNewFolderTrait.php
<?php
namespace Drupal\foldershare\Entity\FolderShareTraits;
use Drupal\foldershare\ManageLog;
use Drupal\foldershare\Entity\Exception\LockException;
use Drupal\foldershare\Entity\Exception\ValidationException;
/**
* Create new FolderShare folders.
*
* This trait includes methods to create root and subfolders.
*
* <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 OperationNewFolderTrait {
/*---------------------------------------------------------------------
*
* Create root folder.
*
*---------------------------------------------------------------------*/
/**
* Creates a new root folder with the given name.
*
* If the name is empty, it is set to a default.
*
* The name is checked for uniqueness among all root items owned by
* the current user. If needed, a sequence number is appended before
* the extension(s) to make the name unique (e.g. 'My new root 12').
*
* <B>Process locks</B>
* This method locks the user's root list for exclusive use during
* creation of the folder. This will prevent any other edit operation from
* modifying the root list until the creation completes.
*
* <B>Post-operation hooks</B>
* This method calls the "hook_foldershare_post_operation_new_folder" hook.
*
* <B>Activity log</B>
* This method posts a log message after the folder is created.
*
* @param string $name
* (optional, default = '') The name for the new folder. If the name is
* empty, it is set to a default name.
* @param bool $allowRename
* (optional, default = TRUE) When TRUE, the entity will be automatically
* renamed, if needed, to insure that it is unique within the folder.
* When FALSE, non-unique names cause an exception to be thrown.
*
* @return \Drupal\foldershare\Entity\FolderShare
* Returns the new folder at the root.
*
* @throws \Drupal\foldershare\Entity\Exception\LockException
* Throws an exception if an access lock could not be acquired.
* @throws \Drupal\foldershare\Entity\Exception\ValidationException
* If the name is already in use or is not legal.
*
* @see ::createFolder()
*/
public static function createRootFolder(
string $name = '',
bool $allowRename = TRUE) {
//
// Validate.
// ---------
// If no name given, use a default. Otherwise insure the name is legal.
if (empty($name) === TRUE) {
$name = t('New folder');
}
elseif (self::isNameLegal($name) === FALSE) {
throw new ValidationException(
self::getStandardIllegalNameExceptionMessage($name));
}
//
// Lock user's root list.
// ----------------------
// Lock the current user's root list while we check if the name is
// unique among other items at the root level.
//
// LOCK USER'S ROOT LIST.
if (self::acquireUserRootListLock() === FALSE) {
throw new LockException(
self::getStandardLockExceptionMessage(t('created'), $name));
}
//
// Check name.
// -----------
// If allowed, adjust the name to make it unique.
$uid = self::getCurrentUserId()[0];
if ($allowRename === TRUE) {
// Insure name doesn't collide with existing root items.
//
// Checking for name uniqueness can only be done safely while
// the root list is locked so that no other process can add or
// change a name.
$name = self::createUniqueName(
self::findAllRootItemNames($uid),
$name,
'');
if ($name === FALSE) {
// This is very very unlikely because creating a unique name
// tries repeatedly to append a number until it gets to
// something unique.
//
// UNLOCK USER'S ROOT LIST.
self::releaseUserRootListLock();
throw new ValidationException(
self::getStandardCannotCreateUniqueNameExceptionMessage('new folder'));
}
}
elseif (self::isRootNameUnique($name) === FALSE) {
// UNLOCK USER'S ROOT LIST.
self::releaseUserRootListLock();
throw new ValidationException(
self::getStandardNameInUseExceptionMessage($name));
}
//
// Create folder.
// --------------
// Use the new name and create a new root folder.
try {
// Give the new root item no parent or root.
// - Empty parent ID.
// - Empty root ID.
// - Automatic id.
// - Automatic uuid.
// - Automatic creation date.
// - Automatic changed date.
// - Automatic langcode.
// - Empty description.
// - Empty size.
// - Empty author grants.
// - Empty view grants.
// - Empty disabled grants.
$folder = self::create([
'name' => $name,
'uid' => $uid,
'kind' => self::FOLDER_KIND,
'mime' => self::FOLDER_MIME,
'size' => 0,
]);
// Add default grants to a root item.
$folder->addDefaultAccessGrants();
$folder->save();
}
catch (\Exception $e) {
// Unknown exception. Creation should not throw an exception.
//
// UNLOCK USER'S ROOT LIST.
self::releaseUserRootListLock();
throw $e;
}
//
// Unlock user's root list.
// ------------------------
// The folder is created with a safe name. We're done with the root list.
//
// UNLOCK USER'S ROOT LIST.
self::releaseUserRootListLock();
//
// Hook & log.
// -----------
// Announce the new folder.
self::postOperationHook(
'new_folder',
[
$folder,
$uid,
]);
ManageLog::activity(
"Created top-level folder '@name' (# @id).",
[
'@id' => (int) $folder->id(),
'@name' => $folder->getName(),
'entity' => $folder,
'uid' => $uid,
]);
return $folder;
}
/*---------------------------------------------------------------------
*
* Create subfolder.
*
*---------------------------------------------------------------------*/
/**
* {@inheritdoc}
*/
public function createFolder(
string $name = '',
bool $allowRename = TRUE) {
//
// Validate
// --------
// If no name given, use a default. Otherwise insure the name is legal.
if (empty($name) === TRUE) {
$name = t('New folder');
}
elseif (self::isNameLegal($name) === FALSE) {
throw new ValidationException(
self::getStandardIllegalNameExceptionMessage($name));
}
//
// Lock root folder tree.
// ----------------------
// Lock the parent root's folder tree to prevent other operations that
// might interfere with the addition of the new folder.
//
// LOCK ROOT FOLDER TREE.
$rootId = $this->getRootItemId();
if (self::acquireRootOperationLock($rootId) === FALSE) {
throw new LockException(
self::getStandardLockExceptionMessage(t('created'), $name));
}
//
// Check name.
// -----------
// If allowed, adjust the name to make it unique.
$uid = self::getCurrentUserId()[0];
if ($allowRename === TRUE) {
// Insure name doesn't collide with existing files or folders.
//
// Checking for name uniqueness can only be done safely while
// the parent folder is locked so that no other process can add or
// change a name.
$name = self::createUniqueName($this->findChildrenNames(), $name, '');
if ($name === FALSE) {
// This is very very unlikely because creating a unique name
// tries repeatedly to append a number until it gets to
// something unique.
//
// UNLOCK ROOT FOLDER TREE.
self::releaseRootOperationLock($rootId);
throw new ValidationException(
self::getStandardCannotCreateUniqueNameExceptionMessage('new folder'));
}
}
elseif ($this->isNameUnique($name) === FALSE) {
// UNLOCK ROOT FOLDER TREE.
self::releaseRootOperationLock($rootId);
throw new ValidationException(
self::getStandardNameInUseExceptionMessage($name));
}
//
// Create the new folder.
// ----------------------
// Use the new name and create a new folder.
try {
// Create and set the parent ID to this folder,
// and the root ID to this folder's root.
// - Automatic id.
// - Automatic uuid.
// - Automatic creation date.
// - Automatic changed date.
// - Automatic langcode.
// - Empty description.
// - Empty size.
// - Empty author grants.
// - Empty view grants.
// - Empty disabled grants.
$folder = self::create([
'name' => $name,
'uid' => $uid,
'kind' => self::FOLDER_KIND,
'mime' => self::FOLDER_MIME,
'size' => 0,
'parentid' => $this->id(),
'rootid' => $this->getRootItemId(),
]);
$folder->save();
}
catch (\Exception $e) {
// Unknown exception. Creation should not throw an exception.
//
// UNLOCK ROOT FOLDER TREE.
self::releaseRootOperationLock($rootId);
throw $e;
}
//
// Unlock root folder tree.
// ------------------------
// The folder is created with a safe name. We're done with the
// folder tree.
//
// UNLOCK ROOT FOLDER TREE.
self::releaseRootOperationLock($rootId);
//
// Hook & log.
// -----------
// Announce the new folder.
self::postOperationHook(
'new_folder',
[
$folder,
$uid,
]);
ManageLog::activity(
"Created folder '@name' (# @id).",
[
'@id' => (int) $folder->id(),
'@name' => $folder->getName(),
'entity' => $folder,
'uid' => $uid,
]);
return $folder;
}
}
