/** * Store a restore request in database * @param int $uid User identifier * @param string $path path to the file (or directory) to restore, relative to user's home dir (in owncloud) * @param int $version The resource's version taken (if possible) nb of days before today (should be 1, 6 or 15 days) * @param string $filetype File type ('file' or 'dir') * @param string $userdate User browser's date * @param int $limit * @param int $offset * @return OCA\User_Files_Restore\Db\request The created request * @throws \Exception */ public function saveRequest($uid, $path, $version, $filetype, $userdate, $dateCreate = null, $limit = null, $offset = null) { if ($filetype !== 'file' and $filetype !== 'dir' and $filetype !== 'custom') { throw new \Exception($this->l->t('Server error: filetype not allowed.')); return false; } $sql = "SELECT * FROM *PREFIX*user_files_restore WHERE uid = ? AND path = ? AND status = " . self::STATUS_TODO; try { $request = $this->findEntity($sql, array($uid, $path), $limit, $offset); $this->delete($request); } catch (\OCP\AppFramework\Db\DoesNotExistException $e) { } catch (\OCP\AppFramework\Db\MultipleObjectsReturnedException $e) { throw new \Exception($this->l->t('Server error: more than one request with same requester/path pair.')); return false; } $request = new Request(); $request->setUid($uid); if (!empty($dateCreate)) { $request->setDateRequest(date('Y-m-d H:i:s', $dateCreate)); } else { $request->setDateRequest(date('Y-m-d H:i:s')); } $request->setUserDateRequest($userdate); $request->setPath($path); $request->setFiletype($filetype); $request->setVersion((int) $version); $request->setStatus(self::STATUS_TODO); $this->insert($request); return $request; }
/** * Create a request * @NoAdminRequired * @param string $file File path * @param int $version Allowed values are stored in appconfig "versions" * @param string $filetype */ public function create($file, $version, $filetype, $userdate) { $currentRequest = new Request(); $currentRequest->setUid($this->userId); $currentRequest->setPath($file); $currentRequest->setVersion($version); $currentRequest->setFiletype($filetype); $currentRequest->setUserDateRequest($userdate); $collision = false; // test if there is(are) collision(s) between requests (one is contained into another) $existingRequests = $this->requestMapper->getRequests($this->userId, RequestMapper::STATUS_TODO); $toSortRequests = array(); $toCancelRequests = array(); foreach ($existingRequests as $existingRequest) { // if versions are identical if ($existingRequest->getVersion() === $currentRequest->getVersion()) { // if current request contains existing request if (strpos($existingRequest->getPath(), $currentRequest->getPath()) === 0) { array_push($toCancelRequests, $existingRequest); array_push($toSortRequests, $currentRequest); $collision = true; } elseif ($currentRequest->getPath() == $existingRequest->getPath()) { // nothing to do, exiting foreach $collision = true; break; } elseif (strpos($currentRequest->getPath(), $existingRequest->getPath()) === 0) { array_push($toSortRequests, $existingRequest); } } else { // if current request contains existing request if (strpos($existingRequest->getPath(), $currentRequest->getPath()) === 0) { array_push($toSortRequests, $currentRequest); array_push($toSortRequests, $existingRequest); $collision = true; } elseif ($currentRequest->getPath() == $existingRequest->getPath()) { array_push($toCancelRequests, $existingRequest); array_push($toSortRequests, $currentRequest); $collision = true; } elseif (strpos($currentRequest->getPath(), $existingRequest->getPath()) === 0) { array_push($toSortRequests, $existingRequest); array_push($toSortRequests, $currentRequest); $collision = true; } } } // collision // process toCancelRequest and toSortRequests if ($collision) { if (!empty($toSortRequests)) { $response = new JSONResponse(); // sort on path length, shortest first usort($toSortRequests, function ($a, $b) { if (strlen($a->getPath()) == strlen($b->getPath())) { return 0; } if (strlen($a->getPath()) < strlen($b->getPath())) { return -1; } return 1; }); // update the dateRequest field (creation date) accordingly // Obviously, current request will be created, not updated $currentDate = time(); $inc = 1; foreach ($toSortRequests as $request) { $requestId = $request->getId(); if (!empty($requestId)) { $request->setDateRequest(date('Y-m-d H:i:s', $currentDate + $inc)); try { $this->requestMapper->update($request); } catch (\Exception $e) { $response = new JSONResponse(); return array('status' => 'error', 'data' => array('msg' => $e->getMessage())); } } else { try { $this->requestMapper->saveRequest($this->userId, $request->getPath(), $request->getVersion(), $request->getFiletype(), $request->getUserDateRequest(), $currentDate + $inc); } catch (\Exception $e) { $response = new JSONResponse(); return array('status' => 'error', 'data' => array('msg' => $e->getMessage())); } } $inc++; } // get only paths (to display to user) $toSortRequestsPath = array_map(function ($elt) { return $elt->getPath(); }, $toSortRequests); $toCancelRequestsPath = array_map(function ($elt) { return $elt->getPath(); }, $toCancelRequests); // cancel useless requests foreach ($toCancelRequests as $request) { $this->requestMapper->delete($request); } // Probably do not want to display what we keep... if (count($toCancelRequestsPath) > 0) { return array('status' => 'collision_error', 'data' => array('toKeep' => json_encode($toSortRequestsPath), 'toCancel' => json_encode($toCancelRequestsPath))); } else { return array('status' => 'success', 'data' => array('msg' => $this->l->t('Request successfully created'), 'id' => $currentRequest->getId(), 'file' => $currentRequest->getPath(), 'version' => (int) $currentRequest->getVersion())); } } return array('status' => 'error', 'data' => array('msg' => $this->l->t('Your request is already taken in account by an older one.'))); } // no collision // TODO: optimization: extract chars before first / on ER and CR, then compare // insert current request if (!$collision) { try { $request = $this->requestMapper->saveRequest($this->userId, $file, (int) $version, $filetype, $userdate); } catch (\Exception $e) { $response = new JSONResponse(); return array('status' => 'error', 'data' => array('msg' => $e->getMessage())); } return array('status' => 'success', 'data' => array('msg' => $this->l->t('Request successfully created'), 'id' => $request->getId(), 'file' => $request->getPath(), 'version' => (int) $request->getVersion())); } }