diff --git a/src/lib/php/Dao/FolderDao.php b/src/lib/php/Dao/FolderDao.php index b27e7e99..cfcfc0ba 100644 --- a/src/lib/php/Dao/FolderDao.php +++ b/src/lib/php/Dao/FolderDao.php @@ -1,406 +1,406 @@ dbManager = $dbManager; $this->logger = new Logger(self::className()); $this->uploadDao = $uploadDao; $this->userDao = $userDao; } /** * @return boolean */ public function hasTopLevelFolder() { $folderInfo = $this->dbManager->getSingleRow("SELECT count(*) cnt FROM folder WHERE folder_pk=$1",array(self::TOP_LEVEL),__METHOD__); $hasFolder = $folderInfo['cnt']>0; return $hasFolder; } public function insertFolder($folderName, $folderDescription, $parentFolderId=self::TOP_LEVEL) { $statementName = __METHOD__; $this->dbManager->prepare($statementName, "INSERT INTO folder (folder_name, folder_desc) VALUES ($1, $2) returning folder_pk"); $res = $this->dbManager->execute($statementName, array($folderName, $folderDescription)); $folderRow=$this->dbManager->fetchArray($res); $folderId=$folderRow["folder_pk"]; $this->dbManager->freeResult($res); $this->insertFolderContents($parentFolderId, self::MODE_FOLDER, $folderId); return $folderId; } public function getFolderId($folderName, $parentFolderId=self::TOP_LEVEL) { $statementName = __METHOD__; $this->dbManager->prepare($statementName, "SELECT folder_pk FROM folder, foldercontents fc" ." WHERE folder_name=$1 AND fc.parent_fk=$2 AND fc.foldercontents_mode=$3 AND folder_pk=child_id"); $res = $this->dbManager->execute($statementName, array( $folderName, $parentFolderId, self::MODE_FOLDER)); $rows= $this->dbManager->fetchAll($res); $rootFolder = !empty($rows) ? intval($rows[0]['folder_pk']) : null; $this->dbManager->freeResult($res); return $rootFolder; } public function insertFolderContents($parentId, $foldercontentsMode, $childId) { $statementName = __METHOD__; $this->dbManager->prepare($statementName, "INSERT INTO foldercontents (parent_fk, foldercontents_mode, child_id) VALUES ($1, $2, $3)"); $res = $this->dbManager->execute($statementName, array($parentId, $foldercontentsMode, $childId)); $this->dbManager->freeResult($res); } protected function fixFolderSequence() { $statementName = __METHOD__; $this->dbManager->prepare($statementName, "SELECT setval('folder_folder_pk_seq', (SELECT max(folder_pk) + 1 FROM folder LIMIT 1))"); $res = $this->dbManager->execute($statementName); $this->dbManager->freeResult($res); } /** * @param int $userId * @return Folder|null */ public function getRootFolder($userId) { $statementName = __METHOD__; $this->dbManager->prepare($statementName, "SELECT f.* FROM folder f INNER JOIN users u ON f.folder_pk = u.root_folder_fk WHERE u.user_pk = $1"); $res = $this->dbManager->execute($statementName, array($userId)); $row = $this->dbManager->fetchArray($res); $rootFolder = $row ? new Folder(intval($row['folder_pk']), $row['folder_name'], $row['folder_desc'], intval($row['folder_perm'])) : null; $this->dbManager->freeResult($res); return $rootFolder; } public function getFolderTreeCte($parentId=null) { $parentCondition = $parentId ? 'folder_pk=$1' : 'folder_pk='.self::TOP_LEVEL; return "WITH RECURSIVE folder_tree(folder_pk, parent_fk, folder_name, folder_desc, folder_perm, id_path, name_path, depth, cycle_detected) AS ( SELECT f.folder_pk, fc.parent_fk, f.folder_name, f.folder_desc, f.folder_perm, ARRAY [f.folder_pk] AS id_path, ARRAY [f.folder_name] AS name_path, 0 AS depth, FALSE AS cycle_detected FROM folder f LEFT JOIN foldercontents fc ON fc.foldercontents_mode=".self::MODE_FOLDER." AND f.folder_pk=fc.child_id WHERE $parentCondition UNION ALL SELECT f.folder_pk, fc.parent_fk, f.folder_name, f.folder_desc, f.folder_perm, id_path || f.folder_pk, name_path || f.folder_name, array_length(id_path, 1), f.folder_pk = ANY (id_path) FROM folder f, foldercontents fc, folder_tree ft WHERE f.folder_pk=fc.child_id AND foldercontents_mode=".self::MODE_FOLDER." AND fc.parent_fk = ft.folder_pk AND NOT cycle_detected )"; } public function getFolderStructure($parentId=null) { $statementName = __METHOD__ . ($parentId ? '.relativeToParent' : ''); $parameters = $parentId ? array($parentId) : array(); $this->dbManager->prepare($statementName, $this->getFolderTreeCte($parentId) . " SELECT folder_pk, parent_fk, folder_name, folder_desc, folder_perm, depth FROM folder_tree ORDER BY name_path"); $res = $this->dbManager->execute($statementName, $parameters); $userGroupMap = $this->userDao->getUserGroupMap(Auth::getUserId()); $results = array(); while ($row = $this->dbManager->fetchArray($res)) { $countUploads = $this->countFolderUploads(intval($row['folder_pk']), $userGroupMap); $results[] = array( self::FOLDER_KEY => new Folder( intval($row['folder_pk']), $row['folder_name'], $row['folder_desc'], intval($row['folder_perm'])), self::DEPTH_KEY => $row['depth'], self::REUSE_KEY => $countUploads ); } $this->dbManager->freeResult($res); return $results; } /** * @param int $parentId * @param string[] $userGroupMap map groupId=>groupName * @return array of array(group_id,count,group_name) */ public function countFolderUploads($parentId, $userGroupMap) { $trustGroupIds = array_keys($userGroupMap); $statementName = __METHOD__; $trustedGroups = '{'. implode(',', $trustGroupIds) .'}'; $parameters = array($parentId, $trustedGroups); $this->dbManager->prepare($statementName, " SELECT group_fk group_id,count(*) FROM foldercontents fc INNER JOIN upload u ON u.upload_pk = fc.child_id INNER JOIN upload_clearing uc ON u.upload_pk=uc.upload_fk AND uc.group_fk=ANY($2) WHERE fc.parent_fk = $1 AND fc.foldercontents_mode = ". self::MODE_UPLOAD ." AND u.upload_mode = 104 GROUP BY group_fk "); $res = $this->dbManager->execute($statementName, $parameters); $results = array(); while ($row = $this->dbManager->fetchArray($res)) { $row['group_name'] = $userGroupMap[$row['group_id']]; $results[$row['group_name']] = $row; } $this->dbManager->freeResult($res); return $results; } public function getFolderChildUploads($parentId, $trustGroupId) { $statementName = __METHOD__; $parameters = array($parentId, $trustGroupId); $this->dbManager->prepare($statementName, $sql=" SELECT u.*,uc.*,fc.foldercontents_pk FROM foldercontents fc INNER JOIN upload u ON u.upload_pk = fc.child_id INNER JOIN upload_clearing uc ON u.upload_pk=uc.upload_fk AND uc.group_fk=$2 WHERE fc.parent_fk = $1 AND fc.foldercontents_mode = " .self::MODE_UPLOAD. " AND u.upload_mode = 104 "); $res = $this->dbManager->execute($statementName, $parameters); $results = $this->dbManager->fetchAll($res); $this->dbManager->freeResult($res); return $results; } /** * @param int $parentId * @param int $trustGroupId * @return UploadProgress[] */ public function getFolderUploads($parentId, $trustGroupId=null) { if (empty($trustGroupId)) { $trustGroupId = Auth::getGroupId(); } $results = array(); foreach($this->getFolderChildUploads($parentId, $trustGroupId) as $row) { $results[] = UploadProgress::createFromTable($row); } return $results; } public function createFolder($folderName, $folderDescription, $parentId) { - $folderId = $this->dbManager->insertTableRow("folder", array("folder_name"=>$folderName, "folder_desc"=>$folderDescription), null, 'folder_pk'); + $folderId = $this->dbManager->insertTableRow("folder", array("folder_name"=>$folderName, "user_fk"=>Auth::getUserId(), "folder_desc"=>$folderDescription), null, 'folder_pk'); $this->insertFolderContents($parentId, self::MODE_FOLDER, $folderId); return $folderId; } public function ensureTopLevelFolder() { if (!$this->hasTopLevelFolder()) { $this->dbManager->insertTableRow("folder", array("folder_pk"=>self::TOP_LEVEL, "folder_name"=>"Software Repository", "folder_desc"=>"Top Folder")); $this->insertFolderContents(1,0,0); $this->fixFolderSequence(); } } public function isWithoutReusableFolders($folderStructure) { foreach($folderStructure as $folder) { $posibilities = array_reduce($folder[self::REUSE_KEY], function($sum,$groupInfo){ return $sum+$groupInfo['count'];}, 0); if($posibilities > 0) { return false; } } return true; } protected function isInFolderTree($parentId,$folderId) { $cycle = $this->dbManager->getSingleRow( $this->getFolderTreeCte($parentId) . " SELECT depth FROM folder_tree WHERE folder_pk=$2 LIMIT 1", array($parentId,$folderId), __METHOD__); return !empty($cycle); } protected function getContent($folderContentId) { $content = $this->dbManager->getSingleRow('SELECT * FROM foldercontents WHERE foldercontents_pk=$1', array($folderContentId), __METHOD__.'.getContent' ); if (empty($content)) { throw new \Exception('invalid FolderContentId'); } return $content; } protected function isContentMovable($content, $newParentId) { if ($content['parent_fk'] == $newParentId) { return false; } $newParent = $this->dbManager->getSingleRow('SELECT * FROM folder WHERE folder_pk=$1', array($newParentId), __METHOD__.'.getParent'); if (empty($newParent)) { throw new \Exception('invalid parent folder'); } if($content['foldercontents_mode']==self::MODE_FOLDER) { if ($this->isInFolderTree($content['child_id'],$newParentId)) { throw new \Exception("action would cause a cycle"); } } elseif($content['foldercontents_mode']==self::MODE_UPLOAD) { $uploadId = $content['child_id']; if (!$this->uploadDao->isEditable($uploadId, Auth::getGroupId())) { throw new \Exception('permission to upload denied'); } } return true; } public function moveContent($folderContentId, $newParentId) { $content = $this->getContent($folderContentId); if (!$this->isContentMovable($content, $newParentId)) { return; } $this->dbManager->getSingleRow('UPDATE foldercontents SET parent_fk=$2 WHERE foldercontents_pk=$1', array($folderContentId,$newParentId),__METHOD__.'.updateFolderParent'); } public function copyContent($folderContentId, $newParentId) { $content = $this->getContent($folderContentId); if (!$this->isContentMovable($content, $newParentId)) { return; } $this->insertFolderContents($newParentId, $content['foldercontents_mode'], $content['child_id']); } public function getRemovableContents($folderId) { $sqlChildren = "SELECT child_id,foldercontents_mode FROM foldercontents GROUP BY child_id,foldercontents_mode HAVING count(*)>1 AND bool_or(parent_fk=$1)"; $sql = "SELECT fc.* FROM foldercontents fc,($sqlChildren) chi " . "WHERE fc.child_id=chi.child_id AND fc.foldercontents_mode=chi.foldercontents_mode and fc.parent_fk=$1"; $this->dbManager->prepare($stmt=__METHOD__,$sql); $res = $this->dbManager->execute($stmt,array($folderId)); $contents = array(); while($row=$this->dbManager->fetchArray($res)) { $contents[] = $row['foldercontents_pk']; } $this->dbManager->freeResult($res); return $contents; } protected function isRemovableContent($childId,$mode) { $sql = "SELECT count(parent_fk) FROM foldercontents WHERE child_id=$1 AND foldercontents_mode=$2"; $parentCounter = $this->dbManager->getSingleRow($sql,array($childId,$mode),__METHOD__); return $parentCounter['count']>1; } public function removeContent($folderContentId) { $content = $this->getContent($folderContentId); if($this->isRemovableContent($content['child_id'],$content['foldercontents_mode'])) { $sql = "DELETE FROM foldercontents WHERE foldercontents_pk=$1"; $this->dbManager->getSingleRow($sql,array($folderContentId),__METHOD__); } } public function getFolderChildFolders($folderId) { $results = array(); $stmtFolder = __METHOD__; $sqlFolder = "SELECT foldercontents_pk,foldercontents_mode, folder_name FROM foldercontents,folder " . "WHERE foldercontents.parent_fk=$1 AND foldercontents.child_id=folder.folder_pk" . " AND foldercontents_mode=".self::MODE_FOLDER; $this->dbManager->prepare($stmtFolder, $sqlFolder); $res = $this->dbManager->execute($stmtFolder,array($folderId)); while($row=$this->dbManager->fetchArray($res)) { $results[$row['foldercontents_pk']] = $row; } $this->dbManager->freeResult($res); return $results; } /** * @param int $folderId * @return Folder|null */ public function getFolder($folderId) { $folderRow = $this->dbManager->getSingleRow('SELECT * FROM folder WHERE folder_pk = $1', array($folderId)); if (!$folderRow) { return null; } return new Folder($folderRow['folder_pk'],$folderRow['folder_name'],$folderRow['folder_desc'],$folderRow['folder_perm']); } -} \ No newline at end of file +} diff --git a/src/www/ui/admin-folder-delete.php b/src/www/ui/admin-folder-delete.php index ac527a5c..29338359 100644 --- a/src/www/ui/admin-folder-delete.php +++ b/src/www/ui/admin-folder-delete.php @@ -1,131 +1,135 @@ Name = "admin_folder_delete"; $this->Title = TITLE_admin_folder_delete; $this->MenuList = "Organize::Folders::Delete Folder"; $this->Dependency = array(); $this->DBaccess = PLUGIN_DB_WRITE; parent::__construct(); $this->dbManager = $GLOBALS['container']->get('db.manager'); } /** * \brief Delete * Creates a job to detele the folder * * \param $folderpk - the folder_pk to remove * \return NULL on success, string on failure. */ - function Delete($folderpk, $Depends = NULL) + function Delete($folderpk, $userId) { /* Can't remove top folder */ if ($folderpk == FolderGetTop()) { $text = _("Can Not Delete Root Folder"); return ($text); } /* Get the folder's name */ $FolderName = FolderGetName($folderpk); /* Prepare the job: job "Delete" */ - $userId = Auth::getUserId(); $groupId = Auth::getGroupId(); $jobpk = JobAddJob($userId, $groupId, "Delete Folder: $FolderName"); if (empty($jobpk) || ($jobpk < 0)) { $text = _("Failed to create job record"); return ($text); } /* Add job: job "Delete" has jobqueue item "delagent" */ $jqargs = "DELETE FOLDER $folderpk"; $jobqueuepk = JobQueueAdd($jobpk, "delagent", $jqargs, NULL, NULL); if (empty($jobqueuepk)) { $text = _("Failed to place delete in job queue"); return ($text); } /* Tell the scheduler to check the queue. */ $success = fo_communicate_with_scheduler("database", $output, $error_msg); if (!$success) return $error_msg . "\n" . $output; return (NULL); } // Delete() /** * \brief Generate the text for this plugin. */ public function Output() { /* If this is a POST, then process the request. */ $folder = GetParm('folder', PARM_INTEGER); if (!empty($folder)) { - $rc = $this->Delete($folder); - $sql = "SELECT * FROM folder where folder_pk = $1;"; - $Folder = $this->dbManager->getSingleRow($sql,array($folder),__METHOD__."GetRowWithFolderName"); - if (empty($rc)) { - /* Need to refresh the screen */ - $text = _("Deletion of folder "); - $text1 = _(" added to job queue"); - $this->vars['message'] = $text . $Folder['folder_name'] . $text1; - } - else { - $text = _("Deletion of "); - $text1 = _(" failed: "); - $this->vars['message'] = $text . $Folder['folder_name'] . $text1 . $rc; + $userId = Auth::getUserId(); + $sql = "SELECT folder_name FROM folder join users on (users.user_pk = folder.user_fk or users.user_perm = 10) where folder_pk = '$1' and users.user_pk = $2;"; + $Folder = $this->dbManager->getSingleRow($sql,array($folder,$userId),__METHOD__."GetRowWithFolderName"); + if(!empty($Folder['folder_name'])){ + $rc = $this->Delete($folder, $userId); + if (empty($rc)) { + /* Need to refresh the screen */ + $text = _("Deletion of folder "); + $text1 = _(" added to job queue"); + $this->vars['message'] = $text . $Folder['folder_name'] . $text1; + }else{ + $text = _("Deletion of "); + $text1 = _(" failed: "); + $this->vars['message'] = $text . $Folder['folder_name'] . $text1 . $rc; + } + }else{ + $text = _("Cannot delete this folder :: Permission denied"); + $this->vars['message'] = $text; } } $V= "
\n"; // no url = this url $text = _("Select the folder to"); $text1 = _("delete"); $V.= "$text $text1.\n"; $V.= "\n"; $text = _("Select the folder to delete: "); $V.= "

$text\n"; $V.= "

\n"; $text = _("Delete"); $V.= "\n"; $V.= "

\n"; return $V; } } $NewPlugin = new admin_folder_delete; diff --git a/src/www/ui/core-schema.dat b/src/www/ui/core-schema.dat index f4cb263a..7b49b9fb 100644 --- a/src/www/ui/core-schema.dat +++ b/src/www/ui/core-schema.dat @@ -1,1845 +1,1849 @@