foldershare-8.x-1.2/src/Entity/FolderShareTraits/GetSetRootTrait.php
src/Entity/FolderShareTraits/GetSetRootTrait.php
<?php
namespace Drupal\foldershare\Entity\FolderShareTraits;
use Drupal\Core\Database\Database;
use Drupal\foldershare\FolderShareInterface;
/**
* Get/set FolderShare entity root fields.
*
* This trait includes get and set methods for FolderShare entity
* root fields.
*
* <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 GetSetRootTrait {
/*---------------------------------------------------------------------
*
* Root field.
*
*---------------------------------------------------------------------*/
/**
* Clears the root ID.
*
* <B>This method is internal and strictly for use by the FolderShare
* module itself.</B>
*
* The caller must call save() for the change to take effect.
*
* <B>Process locks</B>
* This method does not lock access. The caller should lock around changes
* to the entity.
*
* @see ::setRootItemId()
*/
private function clearRootItemId() {
$this->rootid->setValue(['target_id' => NULL]);
}
/**
* {@inheritdoc}
*/
public function getRootItem() {
$id = $this->getRootItemId();
if ($id === (int) $this->id()) {
return $this;
}
return self::load($id);
}
/**
* {@inheritdoc}
*/
public function getRootItemId() {
$rootField = $this->rootid->getValue();
if ((empty($rootField) === TRUE) ||
(isset($rootField[0]) === FALSE) ||
(empty($rootField[0]) === TRUE) ||
(isset($rootField[0]['target_id']) === FALSE) ||
(empty($rootField[0]['target_id']) === TRUE)) {
// Empty. No root.
//
// Freshly loaded entities tend to have empty root fields for root
// items. But entities during construction or after having a root
// ID cleared have non-empty root fields with empty target IDs.
// We need to check all of the possibilities to be sure this is a
// root item.
return (int) $this->id();
}
return (int) $rootField[0]['target_id'];
}
/**
* {@inheritdoc}
*/
public function isRootItem() {
// Root items have empty parent and root IDs.
$rootField = $this->rootid->getValue();
return (empty($rootField) === TRUE) ||
(isset($rootField[0]) === FALSE) ||
(empty($rootField[0]) === TRUE) ||
(isset($rootField[0]['target_id']) === FALSE) ||
(empty($rootField[0]['target_id']) === TRUE);
}
/**
* Sets the root ID.
*
* <B>This method is internal and strictly for use by the FolderShare
* module itself.</B>
*
* The caller must call save() for the change to take effect.
*
* <B>Process locks</B>
* This method does not lock access. The caller should lock around changes
* to the entity.
*
* @param int $rootId
* The root ID for the new root ancestor of this item. The value is
* not validated and is expected to be a valid entity ID. If the value
* is FolderShareInterface::USER_ROOT_LIST, negative, or the ID of this
* item, the root ID is cleared to NULL, indicating the item is in the
* root list.
*
* @see ::clearRootItemId()
* @see ::setRootItemIdRecursively()
*/
private function setRootItemId(int $rootId) {
if ($rootId < 0 || (int) $this->id() === $rootId) {
$this->rootid->setValue(['target_id' => NULL]);
}
else {
$this->rootid->setValue(['target_id' => $rootId]);
}
}
/**
* Sets the root Id on all descendants.
*
* <B>This method is internal and strictly for use by the FolderShare
* module itself.</B>
*
* This method is intended for use by fsck() to fix a corrupted file
* system by correcting root IDs.
*
* This method recurses through a folder tree, starting with the given
* parent item. All descendants are given the new root ID via database
* updates.
*
* During recursion, this method skips subfolder trees that already have
* the correct root ID. It is assumed that if a parent folder has the right
* root ID, the children have already been updated. This is a necessary
* assumption so that repeated calls to this method during a scheduled
* task will eventually find nothing more to do.
*
* The caller must flush all entity-dependent caches (e.g. the entity
* type's storage manager caches and the render cache, at least) in
* order for the changed entities to be recognized.
*
* @param int $parentId
* The FolderShare entity ID of a parent. The parent is presumed to
* already have been given the correct root ID.
* @param int $rootId
* The root ID to set all descendants to use.
*
* @see ::setRootItemId()
* @see ::fsck()
*/
private static function setDescendantsRootItemId(int $parentId, int $rootId) {
$connection = Database::getConnection();
// Find folder children in need of updates.
$query = $connection->select(self::BASE_TABLE, 'fs');
$query->addField('fs', 'id', 'id');
$query->condition('parentid', $parentId, '=');
$query->condition('kind', FolderShareInterface::FOLDER_KIND, '=');
$query->condition('rootid', $rootId, '<>');
$childIds = $query->execute()->fetchCol(0);
// Recurse through all folder children.
foreach ($childIds as $childId) {
self::setDescendantsRootItemId($childId, $rootId);
}
// Update all children to the new root ID.
$query = $connection->update(self::BASE_TABLE);
$query->condition('parentid', $parentId, '=');
$query->fields([
'rootid' => $rootId,
]);
$query->execute();
}
}
