9 namespace Fossology\Lib\Dao;
19 const FOLDER_KEY =
"folder";
20 const DEPTH_KEY =
"depth";
21 const REUSE_KEY =
'reuse';
24 const MODE_FOLDER = 1;
25 const MODE_UPLOAD = 2;
40 $this->logger =
new Logger(self::class);
41 $this->uploadDao = $uploadDao;
42 $this->userDao = $userDao;
50 $folderInfo = $this->
dbManager->getSingleRow(
"SELECT count(*) cnt FROM folder WHERE folder_pk=$1", array(self::TOP_LEVEL), __METHOD__);
51 $hasFolder = $folderInfo[
'cnt'] > 0;
55 public function insertFolder($folderName, $folderDescription, $parentFolderId = self::TOP_LEVEL)
58 $statementName = __METHOD__;
61 "INSERT INTO folder (folder_name, folder_desc) VALUES ($1, $2) returning folder_pk");
62 $res = $this->
dbManager->execute($statementName, array($folderName, $folderDescription));
63 $folderRow = $this->
dbManager->fetchArray($res);
64 $folderId = $folderRow[
"folder_pk"];
66 $this->insertFolderContents($parentFolderId, self::MODE_FOLDER, $folderId);
71 public function getFolderId($folderName, $parentFolderId = self::TOP_LEVEL)
73 $statementName = __METHOD__;
75 "SELECT folder_pk FROM folder, foldercontents fc"
76 .
" WHERE LOWER(folder_name)=LOWER($1) AND fc.parent_fk=$2 AND fc.foldercontents_mode=$3 AND folder_pk=child_id");
77 $res = $this->
dbManager->execute($statementName, array( $folderName, $parentFolderId, self::MODE_FOLDER));
80 $rootFolder = !empty($rows) ? intval($rows[0][
'folder_pk']) : null;
86 public function insertFolderContents($parentId, $foldercontentsMode, $childId)
88 $statementName = __METHOD__;
90 "INSERT INTO foldercontents (parent_fk, foldercontents_mode, child_id) VALUES ($1, $2, $3)");
91 $res = $this->
dbManager->execute($statementName, array($parentId, $foldercontentsMode, $childId));
95 protected function fixFolderSequence()
97 $statementName = __METHOD__;
99 "SELECT setval('folder_folder_pk_seq', (SELECT max(folder_pk) + 1 FROM folder LIMIT 1))");
100 $res = $this->
dbManager->execute($statementName);
110 $statementName = __METHOD__;
111 $this->
dbManager->prepare($statementName,
112 "SELECT f.* FROM folder f INNER JOIN users u ON f.folder_pk = u.root_folder_fk WHERE u.user_pk = $1");
113 $res = $this->
dbManager->execute($statementName, array($userId));
114 $row = $this->
dbManager->fetchArray($res);
115 $rootFolder = $row ?
new Folder(intval($row[
'folder_pk']), $row[
'folder_name'], $row[
'folder_desc'], intval($row[
'folder_perm'])) :
null;
126 $statementName = __METHOD__;
127 $this->
dbManager->prepare($statementName,
128 "SELECT f.* FROM folder f INNER JOIN users u ON f.folder_pk = u.default_folder_fk WHERE u.user_pk = $1");
129 $res = $this->
dbManager->execute($statementName, array($userId));
130 $row = $this->
dbManager->fetchArray($res);
131 $rootFolder = $row ?
new Folder(intval($row[
'folder_pk']), $row[
'folder_name'], $row[
'folder_desc'], intval($row[
'folder_perm'])) :
null;
136 public function getFolderTreeCte($parentId =
null)
138 $parentCondition = $parentId ?
'folder_pk=$1' :
'folder_pk=' . self::TOP_LEVEL;
140 return "WITH RECURSIVE folder_tree(folder_pk, parent_fk, folder_name, folder_desc, folder_perm, id_path, name_path, depth, cycle_detected) AS (
142 f.folder_pk, fc.parent_fk, f.folder_name, f.folder_desc, f.folder_perm,
143 ARRAY [f.folder_pk] AS id_path,
144 ARRAY [f.folder_name] AS name_path,
146 FALSE AS cycle_detected
147 FROM folder f LEFT JOIN foldercontents fc ON fc.foldercontents_mode=" . self::MODE_FOLDER .
" AND f.folder_pk=fc.child_id
148 WHERE $parentCondition
151 f.folder_pk, fc.parent_fk, f.folder_name, f.folder_desc, f.folder_perm,
152 id_path || f.folder_pk,
153 name_path || f.folder_name,
154 array_length(id_path, 1),
155 f.folder_pk = ANY (id_path)
156 FROM folder f, foldercontents fc, folder_tree ft
157 WHERE f.folder_pk=fc.child_id AND foldercontents_mode=" . self::MODE_FOLDER .
" AND fc.parent_fk = ft.folder_pk AND NOT cycle_detected
161 public function getFolderStructure($parentId =
null)
163 $statementName = __METHOD__ . ($parentId ?
'.relativeToParent' :
'');
164 $parameters = $parentId ? array($parentId) : array();
165 $this->
dbManager->prepare($statementName, $this->getFolderTreeCte($parentId)
166 .
" SELECT folder_pk, parent_fk, folder_name, folder_desc, folder_perm, depth FROM folder_tree ORDER BY name_path");
167 $res = $this->
dbManager->execute($statementName, $parameters);
173 while ($row = $this->
dbManager->fetchArray($res)) {
179 foreach ($rows as $r) {
180 $folderIds[] = intval($r[
'folder_pk']);
186 foreach ($rows as $row) {
187 $folderId = intval($row[
'folder_pk']);
188 $countUploads = isset($allCounts[$folderId]) ? $allCounts[$folderId] : array();
191 self::FOLDER_KEY =>
new Folder(
192 $folderId, $row[
'folder_name'], $row[
'folder_desc'], intval($row[
'folder_perm'])),
193 self::DEPTH_KEY => $row[
'depth'],
194 self::REUSE_KEY => $countUploads
207 if (empty($folderIds)) {
211 $trustGroupIds = array_keys($userGroupMap);
212 $trustedGroups =
'{' . implode(
',', $trustGroupIds) .
'}';
213 $folderIdList =
'{' . implode(
',', array_map(
'intval', $folderIds)) .
'}';
215 $statementName = __METHOD__;
216 $this->
dbManager->prepare($statementName,
"
217 SELECT fc.parent_fk AS folder_pk, uc.group_fk AS group_id, count(*) AS cnt
218 FROM foldercontents fc
219 INNER JOIN upload u ON u.upload_pk = fc.child_id
220 INNER JOIN upload_clearing uc ON u.upload_pk = uc.upload_fk AND uc.group_fk = ANY($1)
221 WHERE fc.parent_fk = ANY($2)
222 AND fc.foldercontents_mode = " . self::MODE_UPLOAD .
"
223 AND (u.upload_mode = 100 OR u.upload_mode = 104)
224 GROUP BY fc.parent_fk, uc.group_fk
226 $res = $this->
dbManager->execute($statementName, array($trustedGroups, $folderIdList));
229 while ($row = $this->
dbManager->fetchArray($res)) {
230 $folderId = intval($row[
'folder_pk']);
231 $groupName = $userGroupMap[$row[
'group_id']];
232 if (!isset($results[$folderId])) {
233 $results[$folderId] = array();
235 $results[$folderId][$groupName] = array(
236 'group_id' => $row[
'group_id'],
237 'count' => $row[
'cnt'],
238 'group_name' => $groupName
252 $trustGroupIds = array_keys($userGroupMap);
253 $statementName = __METHOD__;
254 $trustedGroups =
'{' . implode(
',', $trustGroupIds) .
'}';
255 $parameters = array($parentId, $trustedGroups);
257 $this->
dbManager->prepare($statementName,
"
258 SELECT group_fk group_id,count(*) FROM foldercontents fc
259 INNER JOIN upload u ON u.upload_pk = fc.child_id
260 INNER JOIN upload_clearing uc ON u.upload_pk=uc.upload_fk AND uc.group_fk=ANY($2)
261 WHERE fc.parent_fk = $1 AND fc.foldercontents_mode = " . self::MODE_UPLOAD .
" AND (u.upload_mode = 100 OR u.upload_mode = 104)
264 $res = $this->
dbManager->execute($statementName, $parameters);
266 while ($row = $this->
dbManager->fetchArray($res)) {
267 $row[
'group_name'] = $userGroupMap[$row[
'group_id']];
268 $results[$row[
'group_name']] = $row;
274 public function getAllFolderIds()
276 $statementName = __METHOD__;
277 $this->
dbManager->prepare($statementName,
"SELECT folder_pk FROM folder");
278 $res = $this->
dbManager->execute($statementName);
279 $results = $this->
dbManager->fetchAll($res);
282 return array_map(
'intval', array_column($results,
'folder_pk'));
285 public function getFolderChildUploads($parentId, $trustGroupId)
287 $statementName = __METHOD__;
288 $parameters = array($parentId, $trustGroupId);
290 $this->
dbManager->prepare($statementName, $sql =
"
291 SELECT u.*, uc.*, fc.foldercontents_pk FROM foldercontents fc
292 INNER JOIN upload u ON u.upload_pk = fc.child_id AND u.upload_mode IN (100, 104)
293 INNER JOIN upload_clearing uc ON uc.upload_fk = u.upload_pk AND uc.group_fk = $2
294 WHERE fc.parent_fk = $1 AND fc.foldercontents_mode = " . self::MODE_UPLOAD .
";");
295 $res = $this->
dbManager->execute($statementName, $parameters);
296 $results = $this->
dbManager->fetchAll($res);
308 if (empty($trustGroupId)) {
312 foreach ($this->getFolderChildUploads($parentId, $trustGroupId) as $row) {
325 $statementName = __METHOD__;
326 $this->
dbManager->prepare($statementName,
"
327 SELECT u.upload_pk, u.upload_filename, u.upload_desc,
328 u.uploadtree_tablename, u.upload_ts,
329 uc.group_fk, uc.assignee, uc.status_fk, uc.status_comment
331 INNER JOIN upload_clearing uc ON uc.upload_fk = u.upload_pk AND uc.group_fk = $1
332 WHERE u.upload_mode IN (100, 104)
333 AND u.pfile_fk IS NOT NULL
334 ORDER BY u.upload_filename
336 $res = $this->
dbManager->execute($statementName, array($trustGroupId));
338 while ($row = $this->
dbManager->fetchArray($res)) {
345 public function createFolder($folderName, $folderDescription, $parentId)
347 $folderId = $this->
dbManager->insertTableRow(
"folder", array(
"folder_name" => $folderName,
"user_fk" =>
Auth::getUserId(),
"folder_desc" => $folderDescription),
null,
'folder_pk');
348 $this->insertFolderContents($parentId, self::MODE_FOLDER, $folderId);
353 public function ensureTopLevelFolder()
356 $this->
dbManager->insertTableRow(
"folder", array(
"folder_pk" => self::TOP_LEVEL,
"folder_name" =>
"Software Repository",
"folder_desc" =>
"Top Folder"));
357 $this->insertFolderContents(1, 0, 0);
358 $this->fixFolderSequence();
362 public function isWithoutReusableFolders($folderStructure)
364 foreach ($folderStructure as $folder) {
365 $posibilities = array_reduce($folder[self::REUSE_KEY],
function($sum,$groupInfo)
367 return $sum+$groupInfo[
'count'];
369 if ($posibilities > 0) {
376 protected function isInFolderTree($parentId, $folderId)
379 $this->getFolderTreeCte($parentId) .
" SELECT depth FROM folder_tree WHERE folder_pk=$2 LIMIT 1",
380 array($parentId, $folderId),
382 return !empty($cycle);
385 public function getContent($folderContentId)
387 $content = $this->
dbManager->getSingleRow(
'SELECT * FROM foldercontents WHERE foldercontents_pk=$1',
388 array($folderContentId),
389 __METHOD__ .
'.getContent');
390 if (empty($content)) {
391 throw new \Exception(
'invalid FolderContentId');
396 protected function isContentMovable($content, $newParentId)
398 if ($content[
'parent_fk'] == $newParentId) {
401 $newParent = $this->
dbManager->getSingleRow(
'SELECT * FROM folder WHERE folder_pk=$1',
403 __METHOD__ .
'.getParent');
404 if (empty($newParent)) {
405 throw new \Exception(
'invalid parent folder');
408 if ($content[
'foldercontents_mode'] == self::MODE_FOLDER) {
409 if ($this->isInFolderTree($content[
'child_id'], $newParentId)) {
410 throw new \Exception(
"action would cause a cycle");
412 } elseif ($content[
'foldercontents_mode'] == self::MODE_UPLOAD) {
413 $uploadId = $content[
'child_id'];
415 throw new \Exception(
'permission to upload denied');
422 public function moveContent($folderContentId, $newParentId)
424 $content = $this->getContent($folderContentId);
425 if (!$this->isContentMovable($content, $newParentId)) {
429 $this->
dbManager->getSingleRow(
'UPDATE foldercontents SET parent_fk=$2 WHERE foldercontents_pk=$1',
430 array($folderContentId, $newParentId), __METHOD__ .
'.updateFolderParent');
433 public function copyContent($folderContentId, $newParentId)
435 $content = $this->getContent($folderContentId);
436 if (!$this->isContentMovable($content, $newParentId)) {
440 $this->insertFolderContents($newParentId, $content[
'foldercontents_mode'], $content[
'child_id']);
443 public function getRemovableContents($folderId)
445 $sqlChildren =
"SELECT child_id,foldercontents_mode
446 FROM foldercontents GROUP BY child_id,foldercontents_mode
447 HAVING count(*)>1 AND bool_or(parent_fk=$1)";
448 $sql =
"SELECT fc.* FROM foldercontents fc,($sqlChildren) chi "
449 .
"WHERE fc.child_id=chi.child_id AND fc.foldercontents_mode=chi.foldercontents_mode and fc.parent_fk=$1";
450 $this->
dbManager->prepare($stmt = __METHOD__, $sql);
451 $res = $this->
dbManager->execute($stmt, array($folderId));
453 while ($row = $this->
dbManager->fetchArray($res)) {
454 $contents[] = $row[
'foldercontents_pk'];
460 public function isRemovableContent($childId, $mode)
462 $sql =
"SELECT count(parent_fk) FROM foldercontents WHERE child_id=$1 AND foldercontents_mode=$2";
463 $parentCounter = $this->
dbManager->getSingleRow($sql, array($childId, $mode), __METHOD__);
464 return $parentCounter[
'count'] > 1;
467 public function removeContent($folderContentId)
469 $content = $this->getContent($folderContentId);
470 if ($this->isRemovableContent($content[
'child_id'], $content[
'foldercontents_mode'])) {
471 $sql =
"DELETE FROM foldercontents WHERE foldercontents_pk=$1";
472 $this->
dbManager->getSingleRow($sql, array($folderContentId), __METHOD__);
478 public function removeContentById($uploadpk, $folderId)
480 $sql =
"DELETE FROM foldercontents WHERE child_id=$1 AND parent_fk=$2 AND foldercontents_mode=$3";
481 $this->
dbManager->getSingleRow($sql,array($uploadpk, $folderId,2),__METHOD__);
484 public function getFolderChildFolders($folderId)
487 $stmtFolder = __METHOD__;
488 $sqlFolder =
"SELECT foldercontents_pk,foldercontents_mode, folder_name FROM foldercontents JOIN folder"
489 .
" ON foldercontents.child_id=folder.folder_pk WHERE foldercontents.parent_fk=$1"
490 .
" AND foldercontents_mode=" . self::MODE_FOLDER;
491 $this->
dbManager->prepare($stmtFolder, $sqlFolder);
492 $res = $this->
dbManager->execute($stmtFolder, array($folderId));
493 while ($row = $this->
dbManager->fetchArray($res)) {
494 $results[$row[
'foldercontents_pk']] = $row;
506 $folderRow = $this->
dbManager->getSingleRow(
'SELECT * FROM folder WHERE folder_pk = $1', array($folderId));
510 return new Folder($folderRow[
'folder_pk'], $folderRow[
'folder_name'], $folderRow[
'folder_desc'], $folderRow[
'folder_perm']);
520 if ($userId ==
null) {
524 return $this->isInFolderTree($rootFolder, $folderId);
535 $folderContentsRow = $this->
dbManager->getSingleRow(
536 'SELECT foldercontents_pk FROM foldercontents '.
537 'WHERE child_id = $1 AND foldercontents_mode = $2', [$childId, $mode]);
538 if (!$folderContentsRow) {
541 return intval($folderContentsRow[
'foldercontents_pk']);
551 $sql =
"SELECT parent_fk FROM foldercontents " .
552 "WHERE foldercontents_mode = " . self::MODE_FOLDER .
553 " AND child_id = $1;";
554 $statement = __METHOD__ .
".getParentId";
555 $row = $this->
dbManager->getSingleRow($sql, [$folderPk], $statement);
556 return (empty($row)) ? null : $row[
'parent_fk'];
Contains the constants and helpers for authentication of user.
static getUserId()
Get the current user's id.
static getGroupId()
Get the current user's group id.
isFolderAccessible($folderId, $userId=null)
getFolderUploads($parentId, $trustGroupId=null)
getAllUploadsForGroup($trustGroupId)
Get all uploads accessible to a group in a single query.
getFolderParentId($folderPk)
getFolderContentsId($childId, $mode)
countFolderUploads($parentId, $userGroupMap)
countFolderUploadsBatch($folderIds, $userGroupMap)
getDefaultFolder($userId)
static createFromTable($row)
fo_dbManager * dbManager
fo_dbManager object