| 1: | <?php |
| 2: | /** |
| 3: | * This code is licensed under AGPLv3 license or Afterlogic Software License |
| 4: | * if commercial version of the product was purchased. |
| 5: | * For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files. |
| 6: | */ |
| 7: | |
| 8: | namespace Aurora\Modules\PersonalFiles; |
| 9: | |
| 10: | use Aurora\Api; |
| 11: | use Aurora\Modules\PersonalFiles\Storages\Sabredav\Storage; |
| 12: | use Aurora\System\EventEmitter; |
| 13: | |
| 14: | /** |
| 15: | * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0 |
| 16: | * @license https://afterlogic.com/products/common-licensing Afterlogic Software License |
| 17: | * @copyright Copyright (c) 2023, Afterlogic Corp. |
| 18: | * |
| 19: | * @package Filestorage |
| 20: | * |
| 21: | * @property Module $oModule |
| 22: | */ |
| 23: | class Manager extends \Aurora\System\Managers\AbstractManagerWithStorage |
| 24: | { |
| 25: | /** |
| 26: | * @var \Aurora\Modules\PersonalFiles\Storages\Sabredav\Storage |
| 27: | */ |
| 28: | public $oStorage; |
| 29: | |
| 30: | /** |
| 31: | * @param \Aurora\System\Module\AbstractModule $oModule |
| 32: | */ |
| 33: | public function __construct(\Aurora\System\Module\AbstractModule $oModule = null) |
| 34: | { |
| 35: | parent::__construct($oModule, new Storage($this)); |
| 36: | } |
| 37: | |
| 38: | /** |
| 39: | * Returns Min module decorator. |
| 40: | * |
| 41: | * @return \Aurora\Modules\Min\Module |
| 42: | */ |
| 43: | public function getMinModuleDecorator() |
| 44: | { |
| 45: | static $oMinModuleDecorator = null; |
| 46: | if ($oMinModuleDecorator === null) { |
| 47: | $oMinModuleDecorator = \Aurora\Modules\Min\Module::Decorator(); |
| 48: | } |
| 49: | |
| 50: | return $oMinModuleDecorator; |
| 51: | } |
| 52: | |
| 53: | /** |
| 54: | * Checks if file exists. |
| 55: | * |
| 56: | * @param int $UserId Account object. |
| 57: | * @param int $Type Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 58: | * @param string $Path Path to the folder which contains the file, empty string means the file is in the root folder. |
| 59: | * @param string $Name Filename. |
| 60: | * |
| 61: | * @return bool |
| 62: | */ |
| 63: | public function IsFileExists($UserId, $Type, $Path, $Name) |
| 64: | { |
| 65: | return $this->oStorage->isFileExists($UserId, $Type, $Path, $Name); |
| 66: | } |
| 67: | |
| 68: | /** |
| 69: | * Retrieves array of metadata on the specific file. |
| 70: | * |
| 71: | * @param int $iUserId Account object |
| 72: | * @param string $sType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 73: | * @param string $sPath Path to the folder which contains the file, empty string means the file is in the root folder. |
| 74: | * @param string $sName Filename. |
| 75: | * |
| 76: | * @return \Aurora\Modules\Files\Classes\FileItem |
| 77: | */ |
| 78: | public function getFileInfo($iUserId, $sType, $sPath, $sName) |
| 79: | { |
| 80: | $oResult = null; |
| 81: | |
| 82: | $oItem = \Afterlogic\DAV\Server::getNodeForPath('files/' . $sType . $sPath . '/' . $sName, $iUserId); |
| 83: | |
| 84: | if ($oItem) { |
| 85: | $oResult = $this->oStorage->getFileInfo($iUserId, $sType, $oItem, null, $sPath); |
| 86: | } |
| 87: | return $oResult; |
| 88: | } |
| 89: | |
| 90: | /** |
| 91: | * Retrieves array of metadata on the specific directory. |
| 92: | * |
| 93: | * @param int $iUserId Account object |
| 94: | * @param int $iType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 95: | * @param string $sPath Path to the folder. |
| 96: | * |
| 97: | * @return \Aurora\Modules\Files\Classes\FileItem |
| 98: | */ |
| 99: | public function getDirectoryInfo($iUserId, $iType, $sPath) |
| 100: | { |
| 101: | return $this->oStorage->getDirectoryInfo($iUserId, $iType, $sPath); |
| 102: | } |
| 103: | |
| 104: | /** |
| 105: | * Retrieves object on the specific directory. |
| 106: | * |
| 107: | * @param int $iUserId Account object |
| 108: | * @param int $iType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 109: | * |
| 110: | * @return \Aurora\Modules\Files\Classes\FileItem |
| 111: | */ |
| 112: | public function getDirectory($iUserId, $iType) |
| 113: | { |
| 114: | return $this->oStorage->getDirectory($iUserId, $iType); |
| 115: | } |
| 116: | |
| 117: | /** |
| 118: | * Allows for reading contents of the file. |
| 119: | * |
| 120: | * @param int $iUserId Account object |
| 121: | * @param int $iType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 122: | * @param string $sPath Path to the folder which contains the file, empty string means the file is in the root folder. |
| 123: | * @param string $sName Filename. |
| 124: | * |
| 125: | * @return resource|bool |
| 126: | */ |
| 127: | public function getFile($iUserId, $iType, $sPath, $sName) |
| 128: | { |
| 129: | return $this->oStorage->getFile($iUserId, $iType, $sPath, $sName); |
| 130: | } |
| 131: | |
| 132: | /** |
| 133: | * Creates public link for specific file or folder. |
| 134: | * |
| 135: | * @param int $iUserId |
| 136: | * @param int $iType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 137: | * @param string $sPath Path to the folder. |
| 138: | * @param string $sName Filename. |
| 139: | * @param string $sSize Size information, it will be displayed when recipient opens the link. |
| 140: | * @param string $bIsFolder If **true**, it is assumed the link is created for a folder, **false** otherwise. |
| 141: | * |
| 142: | * @return string|bool |
| 143: | */ |
| 144: | public function createPublicLink($iUserId, $iType, $sPath, $sName, $sSize, $bIsFolder) |
| 145: | { |
| 146: | return $this->oStorage->createPublicLink($iUserId, $iType, $sPath, $sName, $sSize, $bIsFolder); |
| 147: | } |
| 148: | |
| 149: | /** |
| 150: | * Removes public link created for specific file or folder. |
| 151: | * |
| 152: | * @param int $iUserId |
| 153: | * @param int $iType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 154: | * @param string $sPath Path to the folder. |
| 155: | * @param string $sName Filename. |
| 156: | * |
| 157: | * @return bool |
| 158: | */ |
| 159: | public function deletePublicLink($iUserId, $iType, $sPath, $sName) |
| 160: | { |
| 161: | return $this->oStorage->deletePublicLink($iUserId, $iType, $sPath, $sName); |
| 162: | } |
| 163: | |
| 164: | /** |
| 165: | * Performs search for files. |
| 166: | * |
| 167: | * @param int $iUserId |
| 168: | * @param string $sType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 169: | * @param string $sPath Path to the folder. |
| 170: | * @param string $sPattern Search string. |
| 171: | * @param string $sPublicHash Public hash. |
| 172: | * |
| 173: | * @return array|bool array of \Aurora\Modules\Files\Classes\FileItem. |
| 174: | */ |
| 175: | public function getFiles($iUserId, $sType, $sPath, $sPattern = '', $sPublicHash = null, $bIsShared = false) |
| 176: | { |
| 177: | $aFiles = $this->oStorage->getFiles($iUserId, $sType, $sPath, $sPattern, $sPublicHash, $bIsShared); |
| 178: | $aUsers = array(); |
| 179: | foreach ($aFiles as $oFile) { |
| 180: | if (!isset($aUsers[$oFile->Owner])) { |
| 181: | $oUser = \Aurora\Modules\Core\Module::Decorator()->GetUserByPublicId($oFile->Owner); |
| 182: | $aUsers[$oFile->Owner] = $oUser ? $oUser->PublicId : ''; |
| 183: | } |
| 184: | $oFile->Owner = $aUsers[$oFile->Owner]; |
| 185: | } |
| 186: | |
| 187: | return $aFiles; |
| 188: | } |
| 189: | |
| 190: | /** |
| 191: | * Creates a new folder. |
| 192: | * |
| 193: | * @param int $iUserId |
| 194: | * @param int $iType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 195: | * @param string $sPath Path to the parent folder, empty string means top-level folder is created. |
| 196: | * @param string $sFolderName Folder name. |
| 197: | * |
| 198: | * @return bool |
| 199: | */ |
| 200: | public function createFolder($iUserId, $iType, $sPath, $sFolderName) |
| 201: | { |
| 202: | return $this->oStorage->createFolder($iUserId, $iType, $sPath, $sFolderName); |
| 203: | } |
| 204: | |
| 205: | /** |
| 206: | * Creates a new file. |
| 207: | * |
| 208: | * @param int $iUserId Account object |
| 209: | * @param int $iType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 210: | * @param string $sPath Path to the folder which contains the file, empty string means the file is created in the root folder. |
| 211: | * @param string $sFileName Filename. |
| 212: | * @param $mData Data to be stored in the file. |
| 213: | * @param bool $bOverride If **true**, existing file with that name will be overwritten. |
| 214: | * |
| 215: | * @return bool |
| 216: | */ |
| 217: | public function createFile($iUserId, $iType, $sPath, $sFileName, $mData, $bOverride = true, $rangeType = 0, $offset = 0, $extendedProps = []) |
| 218: | { |
| 219: | if (!$bOverride) { |
| 220: | $sFileName = $this->oStorage->getNonExistentFileName($iUserId, $iType, $sPath, $sFileName); |
| 221: | } |
| 222: | // else if (!$rangeType) |
| 223: | // { |
| 224: | // // rangeType 2 means override existing file |
| 225: | // $rangeType = 2; |
| 226: | // } |
| 227: | |
| 228: | return $this->oStorage->createFile($iUserId, $iType, $sPath, $sFileName, $mData, $rangeType, $offset, $extendedProps); |
| 229: | } |
| 230: | |
| 231: | /** |
| 232: | * Creates a link to arbitrary online content. |
| 233: | * |
| 234: | * @param int $iUserId Account object |
| 235: | * @param int $iType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 236: | * @param string $sPath Path to the folder which contains the link. |
| 237: | * @param string $sLink URL of the item to be linked. |
| 238: | * @param string $sName Name of the link. |
| 239: | * |
| 240: | * @return bool |
| 241: | */ |
| 242: | public function createLink($iUserId, $iType, $sPath, $sLink, $sName) |
| 243: | { |
| 244: | return $this->oStorage->createLink($iUserId, $iType, $sPath, $sLink, $sName); |
| 245: | } |
| 246: | |
| 247: | /** |
| 248: | * Removes file or folder. |
| 249: | * |
| 250: | * @param int $iUserId Account object |
| 251: | * @param int $iType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 252: | * @param string $sPath Path to the folder which contains the file, empty string means the file is in the root folder. |
| 253: | * @param string $sName Filename. |
| 254: | * |
| 255: | * @return bool |
| 256: | */ |
| 257: | public function delete($iUserId, $iType, $sPath, $sName) |
| 258: | { |
| 259: | return $this->oStorage->delete($iUserId, $iType, $sPath, $sName); |
| 260: | } |
| 261: | |
| 262: | /** |
| 263: | * Renames file or folder. |
| 264: | * |
| 265: | * @param int $iUserId Account object |
| 266: | * @param int $iType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 267: | * @param string $sPath Path to the folder which contains the file, empty string means the file is in the root folder. |
| 268: | * @param string $sName Name of file or folder. |
| 269: | * @param string $sNewName New name. |
| 270: | * @param bool $bIsLink |
| 271: | * |
| 272: | * @return bool |
| 273: | */ |
| 274: | public function rename($iUserId, $iType, $sPath, $sName, $sNewName, $bIsLink) |
| 275: | { |
| 276: | return $this->oStorage->rename($iUserId, $iType, $sPath, $sName, $sNewName); |
| 277: | } |
| 278: | |
| 279: | /** |
| 280: | * Move file or folder to a different location. In terms of Aurora, item can be moved to a different storage as well. |
| 281: | * |
| 282: | * @param int $iUserId Account object |
| 283: | * @param int $iFromType Source storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 284: | * @param int $iToType Destination storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 285: | * @param string $sFromPath Path to the folder which contains the item. |
| 286: | * @param string $sToPath Destination path of the item. |
| 287: | * @param string $sName Current name of file or folder. |
| 288: | * @param string $sNewName New name of the item. |
| 289: | * |
| 290: | * @return bool |
| 291: | */ |
| 292: | public function move($iUserId, $iFromType, $iToType, $sFromPath, $sToPath, $sName, $sNewName) |
| 293: | { |
| 294: | $GLOBALS['__FILESTORAGE_MOVE_ACTION__'] = true; |
| 295: | $bResult = $this->oStorage->copy($iUserId, $iFromType, $iToType, $sFromPath, $sToPath, $sName, $sNewName, true); |
| 296: | $GLOBALS['__FILESTORAGE_MOVE_ACTION__'] = false; |
| 297: | return $bResult; |
| 298: | } |
| 299: | |
| 300: | /** |
| 301: | * Copies file or folder, optionally renames it. |
| 302: | * |
| 303: | * @param int $iUserId Account object |
| 304: | * @param int $iFromType Source storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 305: | * @param int $iToType Destination storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 306: | * @param string $sFromPath Path to the folder which contains the item. |
| 307: | * @param string $sToPath Destination path of the item. |
| 308: | * @param string $sName Current name of file or folder. |
| 309: | * @param string $sNewName New name of the item. |
| 310: | * |
| 311: | * @return bool |
| 312: | */ |
| 313: | public function copy($iUserId, $iFromType, $iToType, $sFromPath, $sToPath, $sName, $sNewName = null, $bMove = false) |
| 314: | { |
| 315: | return $this->oStorage->copy($iUserId, $iFromType, $iToType, $sFromPath, $sToPath, $sName, $sNewName, $bMove); |
| 316: | } |
| 317: | |
| 318: | /** |
| 319: | * Returns space used by the user in specified storages, in bytes. |
| 320: | * |
| 321: | * @param int $iUserId User identifier. |
| 322: | * @param array $aTypes Storage type list. Accepted values in array: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 323: | * |
| 324: | * @return int; |
| 325: | */ |
| 326: | public function getUserSpaceUsed($iUserId, $aTypes = array(\Aurora\System\Enums\FileStorageType::Personal)) |
| 327: | { |
| 328: | return $this->oStorage->getUserSpaceUsed($iUserId, $aTypes); |
| 329: | } |
| 330: | |
| 331: | /** |
| 332: | * Allows for obtaining filename which doesn't exist in current directory. For example, if you need to store **data.txt** file but it already exists, this method will return **data_1.txt**, or **data_2.txt** if that one already exists, and so on. |
| 333: | * |
| 334: | * @param int $iUserId Account object |
| 335: | * @param int $iType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 336: | * @param string $sPath Path to the folder which contains the file, empty string means the file is in the root folder. |
| 337: | * @param string $sFileName Filename. |
| 338: | * |
| 339: | * @return string |
| 340: | */ |
| 341: | public function getNonExistentFileName($iUserId, $iType, $sPath, $sFileName, $bWithoutGroup = false) |
| 342: | { |
| 343: | return $this->oStorage->getNonExistentFileName($iUserId, $iType, $sPath, $sFileName, $bWithoutGroup); |
| 344: | } |
| 345: | |
| 346: | /** |
| 347: | * |
| 348: | * @param string $sPublicId |
| 349: | */ |
| 350: | public function ClearFiles($sPublicId) |
| 351: | { |
| 352: | $this->oStorage->clearPrivateFiles($sPublicId); |
| 353: | } |
| 354: | |
| 355: | /** |
| 356: | * |
| 357: | * @param string $sUserPublicId |
| 358: | * @param string $sType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 359: | * @param string $sPath Path to the folder which contains the file, empty string means the file is in the root folder. |
| 360: | * @param string $sName Filename. |
| 361: | * @param array $aExtendedProps |
| 362: | * |
| 363: | * @return bool |
| 364: | */ |
| 365: | public function updateExtendedProps($sUserPublicId, $sType, $sPath, $sName, $aExtendedProps) |
| 366: | { |
| 367: | $bResult = false; |
| 368: | |
| 369: | $oItem = \Afterlogic\DAV\Server::getNodeForPath('files/' . $sType . $sPath . '/' . $sName, $sUserPublicId); |
| 370: | if ($oItem instanceof \Afterlogic\DAV\FS\File) { |
| 371: | $aCurrentExtendedProps = $oItem->getProperty('ExtendedProps'); |
| 372: | foreach ($aExtendedProps as $sPropName => $propValue) { |
| 373: | if ($propValue === null) { |
| 374: | unset($aCurrentExtendedProps[$sPropName]); |
| 375: | } else { |
| 376: | $aCurrentExtendedProps[$sPropName] = $propValue; |
| 377: | } |
| 378: | } |
| 379: | $oItem->setProperty('ExtendedProps', $aCurrentExtendedProps); |
| 380: | $bResult = true; |
| 381: | } |
| 382: | |
| 383: | return $bResult; |
| 384: | } |
| 385: | |
| 386: | /** |
| 387: | * |
| 388: | * @param string $sUserPublicId |
| 389: | * @param string $sType Storage type. Accepted values: **\Aurora\System\Enums\FileStorageType::Personal**, **\Aurora\System\Enums\FileStorageType::Corporate**, **\Aurora\System\Enums\FileStorageType::Shared**. |
| 390: | * @param string $sPath Path to the folder which contains the file, empty string means the file is in the root folder. |
| 391: | * @param string $sName Filename. |
| 392: | * |
| 393: | * @return bool |
| 394: | */ |
| 395: | public function getExtendedProps($sUserPublicId, $sType, $sPath, $sName) |
| 396: | { |
| 397: | $aResult = []; |
| 398: | |
| 399: | $oItem = \Afterlogic\DAV\Server::getNodeForPath('files/' . $sType . $sPath . '/' . $sName, $sUserPublicId); |
| 400: | if ($oItem instanceof \Afterlogic\DAV\FS\File) { |
| 401: | $aResult = $oItem->getProperty('ExtendedProps'); |
| 402: | } |
| 403: | |
| 404: | $aArgs = [ |
| 405: | 'UserId' => Api::getUserIdByPublicId($sUserPublicId), |
| 406: | 'Type' => $sType, |
| 407: | 'Path' => $sPath, |
| 408: | 'Name' => $sName, |
| 409: | 'Item' => $oItem |
| 410: | ]; |
| 411: | EventEmitter::getInstance()->emit('Files', 'PopulateExtendedProps', $aArgs, $aResult); |
| 412: | |
| 413: | return $aResult; |
| 414: | } |
| 415: | } |
| 416: |