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: