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