30 const FOLDER_KEY =
"folder";
31 const DEPTH_KEY =
"depth";
32 const REUSE_KEY =
'reuse';
35 const MODE_FOLDER = 1;
36 const MODE_UPLOAD = 2;
51 $this->logger =
new Logger(self::class);
52 $this->uploadDao = $uploadDao;
53 $this->userDao = $userDao;
61 $folderInfo = $this->
dbManager->getSingleRow(
"SELECT count(*) cnt FROM folder WHERE folder_pk=$1", array(self::TOP_LEVEL), __METHOD__);
62 $hasFolder = $folderInfo[
'cnt'] > 0;
66 public function insertFolder($folderName, $folderDescription, $parentFolderId = self::TOP_LEVEL)
69 $statementName = __METHOD__;
72 "INSERT INTO folder (folder_name, folder_desc) VALUES ($1, $2) returning folder_pk");
73 $res = $this->
dbManager->execute($statementName, array($folderName, $folderDescription));
74 $folderRow = $this->
dbManager->fetchArray($res);
75 $folderId = $folderRow[
"folder_pk"];
77 $this->insertFolderContents($parentFolderId, self::MODE_FOLDER, $folderId);
82 public function getFolderId($folderName, $parentFolderId = self::TOP_LEVEL)
84 $statementName = __METHOD__;
86 "SELECT folder_pk FROM folder, foldercontents fc" 87 .
" WHERE LOWER(folder_name)=LOWER($1) AND fc.parent_fk=$2 AND fc.foldercontents_mode=$3 AND folder_pk=child_id");
88 $res = $this->
dbManager->execute($statementName, array( $folderName, $parentFolderId, self::MODE_FOLDER));
91 $rootFolder = !empty($rows) ? intval($rows[0][
'folder_pk']) : null;
97 public function insertFolderContents($parentId, $foldercontentsMode, $childId)
99 $statementName = __METHOD__;
100 $this->
dbManager->prepare($statementName,
101 "INSERT INTO foldercontents (parent_fk, foldercontents_mode, child_id) VALUES ($1, $2, $3)");
102 $res = $this->
dbManager->execute($statementName, array($parentId, $foldercontentsMode, $childId));
106 protected function fixFolderSequence()
108 $statementName = __METHOD__;
109 $this->
dbManager->prepare($statementName,
110 "SELECT setval('folder_folder_pk_seq', (SELECT max(folder_pk) + 1 FROM folder LIMIT 1))");
111 $res = $this->
dbManager->execute($statementName);
121 $statementName = __METHOD__;
122 $this->
dbManager->prepare($statementName,
123 "SELECT f.* FROM folder f INNER JOIN users u ON f.folder_pk = u.root_folder_fk WHERE u.user_pk = $1");
124 $res = $this->
dbManager->execute($statementName, array($userId));
125 $row = $this->
dbManager->fetchArray($res);
126 $rootFolder = $row ?
new Folder(intval($row[
'folder_pk']), $row[
'folder_name'], $row[
'folder_desc'], intval($row[
'folder_perm'])) : null;
131 public function getFolderTreeCte($parentId = null)
133 $parentCondition = $parentId ?
'folder_pk=$1' :
'folder_pk=' . self::TOP_LEVEL;
135 return "WITH RECURSIVE folder_tree(folder_pk, parent_fk, folder_name, folder_desc, folder_perm, id_path, name_path, depth, cycle_detected) AS ( 137 f.folder_pk, fc.parent_fk, f.folder_name, f.folder_desc, f.folder_perm, 138 ARRAY [f.folder_pk] AS id_path, 139 ARRAY [f.folder_name] AS name_path, 141 FALSE AS cycle_detected 142 FROM folder f LEFT JOIN foldercontents fc ON fc.foldercontents_mode=" . self::MODE_FOLDER .
" AND f.folder_pk=fc.child_id 143 WHERE $parentCondition 146 f.folder_pk, fc.parent_fk, f.folder_name, f.folder_desc, f.folder_perm, 147 id_path || f.folder_pk, 148 name_path || f.folder_name, 149 array_length(id_path, 1), 150 f.folder_pk = ANY (id_path) 151 FROM folder f, foldercontents fc, folder_tree ft 152 WHERE f.folder_pk=fc.child_id AND foldercontents_mode=" . self::MODE_FOLDER .
" AND fc.parent_fk = ft.folder_pk AND NOT cycle_detected 156 public function getFolderStructure($parentId = null)
158 $statementName = __METHOD__ . ($parentId ?
'.relativeToParent' :
'');
159 $parameters = $parentId ? array($parentId) : array();
160 $this->
dbManager->prepare($statementName, $this->getFolderTreeCte($parentId)
161 .
" SELECT folder_pk, parent_fk, folder_name, folder_desc, folder_perm, depth FROM folder_tree ORDER BY name_path");
162 $res = $this->
dbManager->execute($statementName, $parameters);
167 while ($row = $this->
dbManager->fetchArray($res)) {
171 self::FOLDER_KEY =>
new Folder(
172 intval($row[
'folder_pk']), $row[
'folder_name'], $row[
'folder_desc'], intval($row[
'folder_perm'])),
173 self::DEPTH_KEY => $row[
'depth'],
174 self::REUSE_KEY => $countUploads
188 $trustGroupIds = array_keys($userGroupMap);
189 $statementName = __METHOD__;
190 $trustedGroups =
'{' . implode(
',', $trustGroupIds) .
'}';
191 $parameters = array($parentId, $trustedGroups);
193 $this->
dbManager->prepare($statementName,
" 194 SELECT group_fk group_id,count(*) FROM foldercontents fc 195 INNER JOIN upload u ON u.upload_pk = fc.child_id 196 INNER JOIN upload_clearing uc ON u.upload_pk=uc.upload_fk AND uc.group_fk=ANY($2) 197 WHERE fc.parent_fk = $1 AND fc.foldercontents_mode = " . self::MODE_UPLOAD .
" AND (u.upload_mode = 100 OR u.upload_mode = 104) 200 $res = $this->
dbManager->execute($statementName, $parameters);
202 while ($row = $this->
dbManager->fetchArray($res)) {
203 $row[
'group_name'] = $userGroupMap[$row[
'group_id']];
204 $results[$row[
'group_name']] = $row;
210 public function getAllFolderIds()
212 $statementName = __METHOD__;
213 $this->
dbManager->prepare($statementName,
"SELECT DISTINCT folder_pk FROM folder");
214 $res = $this->
dbManager->execute($statementName);
215 $results = $this->
dbManager->fetchAll($res);
219 for ($i=0; $i <
sizeof($results); $i++) {
220 array_push($allIds, intval($results[$i][
'folder_pk']));
226 public function getFolderChildUploads($parentId, $trustGroupId)
228 $statementName = __METHOD__;
229 $parameters = array($parentId, $trustGroupId);
231 $this->
dbManager->prepare($statementName, $sql =
" 232 SELECT u.*,uc.*,fc.foldercontents_pk FROM foldercontents fc 233 INNER JOIN upload u ON u.upload_pk = fc.child_id 234 INNER JOIN upload_clearing uc ON u.upload_pk=uc.upload_fk AND uc.group_fk=$2 235 WHERE fc.parent_fk = $1 AND fc.foldercontents_mode = " . self::MODE_UPLOAD .
" AND (u.upload_mode = 100 OR u.upload_mode = 104);");
236 $res = $this->
dbManager->execute($statementName, $parameters);
237 $results = $this->
dbManager->fetchAll($res);
249 if (empty($trustGroupId)) {
253 foreach ($this->getFolderChildUploads($parentId, $trustGroupId) as $row) {
259 public function createFolder($folderName, $folderDescription, $parentId)
261 $folderId = $this->
dbManager->insertTableRow(
"folder", array(
"folder_name" => $folderName,
"user_fk" =>
Auth::getUserId(),
"folder_desc" => $folderDescription), null,
'folder_pk');
262 $this->insertFolderContents($parentId, self::MODE_FOLDER, $folderId);
267 public function ensureTopLevelFolder()
270 $this->
dbManager->insertTableRow(
"folder", array(
"folder_pk" => self::TOP_LEVEL,
"folder_name" =>
"Software Repository",
"folder_desc" =>
"Top Folder"));
271 $this->insertFolderContents(1, 0, 0);
272 $this->fixFolderSequence();
276 public function isWithoutReusableFolders($folderStructure)
278 foreach ($folderStructure as $folder) {
279 $posibilities = array_reduce($folder[self::REUSE_KEY],
function($sum,$groupInfo)
281 return $sum+$groupInfo[
'count'];
283 if ($posibilities > 0) {
290 protected function isInFolderTree($parentId, $folderId)
293 $this->getFolderTreeCte($parentId) .
" SELECT depth FROM folder_tree WHERE folder_pk=$2 LIMIT 1",
294 array($parentId, $folderId),
296 return !empty($cycle);
299 protected function getContent($folderContentId)
301 $content = $this->
dbManager->getSingleRow(
'SELECT * FROM foldercontents WHERE foldercontents_pk=$1',
302 array($folderContentId),
303 __METHOD__ .
'.getContent');
304 if (empty($content)) {
305 throw new \Exception(
'invalid FolderContentId');
310 protected function isContentMovable($content, $newParentId)
312 if ($content[
'parent_fk'] == $newParentId) {
315 $newParent = $this->
dbManager->getSingleRow(
'SELECT * FROM folder WHERE folder_pk=$1',
317 __METHOD__ .
'.getParent');
318 if (empty($newParent)) {
319 throw new \Exception(
'invalid parent folder');
322 if ($content[
'foldercontents_mode'] == self::MODE_FOLDER) {
323 if ($this->isInFolderTree($content[
'child_id'], $newParentId)) {
324 throw new \Exception(
"action would cause a cycle");
326 } elseif ($content[
'foldercontents_mode'] == self::MODE_UPLOAD) {
327 $uploadId = $content[
'child_id'];
329 throw new \Exception(
'permission to upload denied');
336 public function moveContent($folderContentId, $newParentId)
338 $content = $this->getContent($folderContentId);
339 if (!$this->isContentMovable($content, $newParentId)) {
343 $this->
dbManager->getSingleRow(
'UPDATE foldercontents SET parent_fk=$2 WHERE foldercontents_pk=$1',
344 array($folderContentId, $newParentId), __METHOD__ .
'.updateFolderParent');
347 public function copyContent($folderContentId, $newParentId)
349 $content = $this->getContent($folderContentId);
350 if (!$this->isContentMovable($content, $newParentId)) {
354 $this->insertFolderContents($newParentId, $content[
'foldercontents_mode'], $content[
'child_id']);
357 public function getRemovableContents($folderId)
359 $sqlChildren =
"SELECT child_id,foldercontents_mode 360 FROM foldercontents GROUP BY child_id,foldercontents_mode 361 HAVING count(*)>1 AND bool_or(parent_fk=$1)";
362 $sql =
"SELECT fc.* FROM foldercontents fc,($sqlChildren) chi " 363 .
"WHERE fc.child_id=chi.child_id AND fc.foldercontents_mode=chi.foldercontents_mode and fc.parent_fk=$1";
364 $this->
dbManager->prepare($stmt = __METHOD__, $sql);
365 $res = $this->
dbManager->execute($stmt, array($folderId));
367 while ($row = $this->
dbManager->fetchArray($res)) {
368 $contents[] = $row[
'foldercontents_pk'];
374 public function isRemovableContent($childId, $mode)
376 $sql =
"SELECT count(parent_fk) FROM foldercontents WHERE child_id=$1 AND foldercontents_mode=$2";
377 $parentCounter = $this->
dbManager->getSingleRow($sql, array($childId, $mode), __METHOD__);
378 return $parentCounter[
'count'] > 1;
381 public function removeContent($folderContentId)
383 $content = $this->getContent($folderContentId);
384 if ($this->isRemovableContent($content[
'child_id'], $content[
'foldercontents_mode'])) {
385 $sql =
"DELETE FROM foldercontents WHERE foldercontents_pk=$1";
386 $this->
dbManager->getSingleRow($sql, array($folderContentId), __METHOD__);
390 public function removeContentById($uploadpk, $folderId)
392 $sql =
"DELETE FROM foldercontents WHERE child_id=$1 AND parent_fk=$2 AND foldercontents_mode=$3";
393 $this->
dbManager->getSingleRow($sql,array($uploadpk, $folderId,2),__METHOD__);
396 public function getFolderChildFolders($folderId)
399 $stmtFolder = __METHOD__;
400 $sqlFolder =
"SELECT foldercontents_pk,foldercontents_mode, folder_name FROM foldercontents,folder " 401 .
"WHERE foldercontents.parent_fk=$1 AND foldercontents.child_id=folder.folder_pk" 402 .
" AND foldercontents_mode=" . self::MODE_FOLDER;
403 $this->
dbManager->prepare($stmtFolder, $sqlFolder);
404 $res = $this->
dbManager->execute($stmtFolder, array($folderId));
405 while ($row = $this->
dbManager->fetchArray($res)) {
406 $results[$row[
'foldercontents_pk']] = $row;
418 $folderRow = $this->
dbManager->getSingleRow(
'SELECT * FROM folder WHERE folder_pk = $1', array($folderId));
422 return new Folder($folderRow[
'folder_pk'], $folderRow[
'folder_name'], $folderRow[
'folder_desc'], $folderRow[
'folder_perm']);
432 $allUserFolders = array();
433 if ($userId == null) {
438 if (in_array($folderId, array_keys($allUserFolders))) {
451 $folderContentsRow = $this->
dbManager->getSingleRow(
452 'SELECT foldercontents_pk FROM foldercontents '.
453 'WHERE child_id = $1', [$childId]);
454 if (!$folderContentsRow) {
457 return intval($folderContentsRow[
'foldercontents_pk']);
467 $sql =
"SELECT parent_fk FROM foldercontents " .
468 "WHERE foldercontents_mode = " . self::MODE_FOLDER .
469 " AND child_id = $1;";
470 $statement = __METHOD__ .
".getParentId";
471 $row = $this->
dbManager->getSingleRow($sql, [$folderPk], $statement);
472 return (empty($row)) ? null : $row[
'parent_fk'];
static getUserId()
Get the current user's id.
isFolderAccessible($folderId, $userId=null)
GetFolderArray($RootFolder, &$FolderArray)
Get an array of all the folders from a $RootFolder on down.
getFolderParentId($folderPk)
static createFromTable($row)
fo_dbManager * dbManager
fo_dbManager object
countFolderUploads($parentId, $userGroupMap)
static getGroupId()
Get the current user's group id.
getFolderContentsId($childId)
getFolderUploads($parentId, $trustGroupId=null)