protected function calculateTotalSize(Node $node) { $size = $node['contentProperties']['size'] ?: 0; if ($node->isFolder() || $this->input->getOption('assets')) { foreach ($node->getChildren() as $child) { $size += $this->calculateTotalSize($child); } } return $size; }
protected function main() { $this->init(); $remotePath = $this->input->getArgument('remote_path'); if ($this->input->getOption('id')) { if (!($node = Node::loadById($remotePath))) { throw new \Exception("No node exists with ID '{$remotePath}'."); } } else { if (!($node = Node::loadByPath($remotePath))) { throw new \Exception("No node exists at remote path '{$remotePath}'."); } } $result = $node->trash(); if ($result['success']) { $this->output->writeln("<info>Successfully trashed node at '{$remotePath}'</info>"); if ($this->output->isVerbose()) { $this->output->writeln(json_encode($result['data'])); } } else { $this->output->getErrorOutput()->writeln("<error>Failed to trash node at '{$remotePath}'</error>"); if ($this->output->isVerbose()) { $this->output->getErrorOutput()->writeln(json_encode($result['data'])); } } }
protected function main() { $this->init(); $remotePath = $this->input->getArgument('remote_path'); $savePath = $this->input->getArgument('local_path') ?: getcwd(); if ($this->input->getOption('id')) { if (!($node = Node::loadById($remotePath))) { throw new \Exception("No node exists with ID '{$remotePath}'."); } } else { if (!($node = Node::loadByPath($remotePath))) { throw new \Exception("No node exists at remote path '{$remotePath}'."); } } $node->download($savePath, function ($result, $dest) { if ($result['success']) { $this->output->writeln("<info>Successfully downloaded file to '{$dest}'</info>"); } else { $this->output->getErrorOutput()->writeln("<error>Failed to download node to '{$dest}'</error>"); if ($this->output->isVerbose()) { $this->output->getErrorOutput()->writeln(json_encode($result['data'])); } } }); }
protected function main() { $this->init(); $remotePath = $this->input->getArgument('remote_path') ?: ''; if ($this->input->getOption('id')) { if (!($node = Node::loadById($remotePath))) { throw new \Exception("No node exists with ID '{$remotePath}'."); } } else { if (!($node = Node::loadByPath($remotePath))) { throw new \Exception("No node exists at remote path '{$remotePath}'."); } } if ($node->isFolder()) { throw new \Exception("Links can only be created for files."); } $response = $node->getMetadata(true); if ($response['success']) { if (isset($response['data']['tempLink'])) { $this->output->writeln($response['data']['tempLink']); } else { $this->output->getErrorOutput()->writeln("<error>Failed retrieving temporary link. Make sure you have permission.</error>"); } } else { $this->output->getErrorOutput()->writeln("<error>Failed retrieving metadata for node '{$remotePath}'</error>"); } }
protected function buildMarkdownTree(Node $node, $includeAssets = false, $prefix = '') { static $first; if (is_null($first)) { $first = false; if ($node->isFolder()) { $this->output->writeln("<blue>{$node['name']}</blue>"); } else { $this->output->writeln($node['name']); } } foreach ($node->getChildren() as $node) { $this->output->writeln("{$prefix}- {$node['name']}"); if ($node->isFolder() || $includeAssets === true) { $this->buildMarkdownTree($node, $includeAssets, "{$prefix} "); } } }
protected function main() { $this->init(); $sort = Command::SORT_BY_NAME; if ($this->input->getOption('time')) { $sort = Command::SORT_BY_TIME; } $this->listNodes(Node::filter([['status' => 'PENDING']]), $sort); }
protected function main() { $this->init(); $id = $this->input->getArgument('id'); if (!($node = Node::loadById($id))) { throw new \Exception("No node exists with ID '{$id}'."); } $this->output->writeln($node->getPath()); }
protected function main() { $this->init(); $remotePath = $this->input->getArgument('remote_path'); if ($node = Node::loadByPath($remotePath)) { throw new \Exception("Node already exists at remote path '{$remotePath}'. Make sure it's not in the trash."); } $result = $this->clouddrive->createDirectoryPath($remotePath); if (!$result['success']) { $this->output->writeln("Failed to create remote path '{$remotePath}': " . json_encode($result['data'])); } else { $this->output->writeln("Successfully created remote path '{$remotePath}': " . json_encode($result['data'])); } }
protected function main() { $this->init(); $query = $this->input->getArgument('query'); if ($this->input->getOption('md5')) { $nodes = Node::loadByMd5($query); } else { $nodes = Node::searchNodesByName($query); } $sort = Command::SORT_BY_NAME; if ($this->input->getOption('time')) { $sort = Command::SORT_BY_TIME; } $this->listNodes($nodes, $sort); }
protected function main() { $this->initOnlineCommand(); $remotePath = $this->input->getArgument('remote_path'); if ($this->input->getOption('id')) { if (!($node = Node::loadById($remotePath))) { throw new \Exception("No node exists with ID '{$remotePath}'."); } } else { if (!($node = Node::loadByPath($remotePath))) { throw new \Exception("No node exists at remote path '{$remotePath}'."); } } if ($node->isFolder()) { throw new \Exception("Folder downloads are not currently supported."); } $node->download($this->output->getStream()); }
protected function main() { $this->init(); $path = $this->input->getArgument('path') ?: ''; if ($this->input->getOption('id')) { if (!($node = Node::loadById($path))) { throw new \Exception("No node exists with ID '{$path}'."); } } else { if (!($node = Node::loadByPath($path))) { throw new \Exception("No node exists at remote path '{$path}'."); } } if ($this->config['json.pretty']) { $this->output->writeln(json_encode($node, JSON_PRETTY_PRINT)); } else { $this->output->writeln(json_encode($node)); } }
protected function main() { $this->init(); $remotePath = $this->input->getArgument('remote_path'); if ($this->input->getOption('id')) { if (!($node = Node::loadById($remotePath))) { throw new \Exception("No node exists with ID '{$remotePath}'."); } } else { if (!($node = Node::loadByPath($remotePath))) { throw new \Exception("No node exists at remote path '{$remotePath}'."); } } $result = $node->restore(); if ($result['success']) { $this->output->writeln("Successfully restored node at '{$remotePath}': " . json_encode($result['data'])); } else { $this->output->writeln("Failed to restore node at '{$remotePath}': " . json_encode($result['data'])); } }
protected function main() { $this->init(); $this->clouddrive->getAccount()->authorize(); $remotePath = $this->input->getArgument('remote_path') ?: ''; $sort = Command::SORT_BY_NAME; if ($this->input->getOption('time')) { $sort = Command::SORT_BY_TIME; } if ($this->input->getOption('id')) { if (!($node = Node::loadById($remotePath))) { throw new \Exception("No node exists with ID '{$remotePath}'."); } } else { if (!($node = Node::loadByPath($remotePath))) { throw new \Exception("No node exists at remote path '{$remotePath}'."); } } if ($node->isFolder() || $this->input->getOption('assets')) { $this->listNodes($node->getChildren(), $sort); } else { $this->listNodes([$node], $sort); } }
protected function main() { $this->init(); $nodePath = $this->input->getArgument('node'); $newPath = $this->input->getArgument('new_path'); if (!($node = Node::loadByPath($nodePath))) { throw new \Exception("No node exists at remote path '{$nodePath}'."); } if (!($newParent = Node::loadByPath($newPath))) { throw new \Exception("No node exists at remote path '{$newPath}'."); } $result = $node->move($newParent); if ($result['success']) { $this->output->writeln("<info>Successfully moved node '{$node['name']}' to '{$newPath}'</info>"); if ($this->output->isVerbose()) { $this->output->writeln(json_encode($result['data'])); } } else { $this->output->getErrorOutput()->writeln("<error>Failed to move node '{$node['name']}' to '{$newPath}'</error>"); if ($this->output->isVerbose()) { $this->output->getErrorOutput()->writeln(json_encode($result['data'])); } } }
/** * {@inheritdoc} */ public function findNodesByName($name) { $nodes = ORM::for_table('nodes')->select('raw_data')->where('name', $name)->find_many(); foreach ($nodes as &$node) { $node = new Node(json_decode($node->as_array()['raw_data'], true)); } return $nodes; }
/** * Determine if a node matching the given path exists remotely. If a local * path is given, the MD5 will be compared as well. * * @param string $remotePath The remote path to check * @param null|string $localPath Local path of file to compare MD5 * * @return array * @throws \Exception' */ public function nodeExists($remotePath, $localPath = null) { if (is_null($file = Node::loadByPath($remotePath))) { if (!is_null($localPath)) { if (!empty($nodes = Node::loadByMd5(md5_file($localPath)))) { $ids = []; foreach ($nodes as $node) { $ids[] = $node['id']; } return ['success' => true, 'data' => ['message' => "File(s) with same MD5: " . implode(', ', $ids), 'path_match' => false, 'md5_match' => true, 'nodes' => $nodes]]; } } return ['success' => false, 'data' => ['message' => "File {$remotePath} does not exist.", 'path_match' => false, 'md5_match' => false]]; } $retval = ['success' => true, 'data' => ['message' => "File {$remotePath} exists.", 'path_match' => true, 'md5_match' => false, 'node' => $file]]; if (!is_null($localPath)) { if (!is_null($file['contentProperties']['md5'])) { if (md5_file($localPath) !== $file['contentProperties']['md5']) { $retval['data']['message'] = "File {$remotePath} exists but does not match local checksum."; } else { $retval['data']['message'] = "File {$remotePath} exists and is identical to local copy."; $retval['data']['md5_match'] = true; } } else { $retval['data']['message'] = "File {$remotePath} exists but no checksum is available."; } } return $retval; }
/** * Upload a single file to Amazon Cloud Drive. * * @param resource $resource The local path to the file to upload * @param string $remotePath The remote folder to upload the file to, including the file name * @param bool|false $overwrite Whether to overwrite the file if it already * exists remotely * @param bool $suppressDedup Disables checking for duplicates when uploading * * @return array */ public function uploadStream($resource, $remotePath, $overwrite = false, $suppressDedup = false) { $retval = ['success' => false, 'data' => [], 'response_code' => null]; $info = pathinfo($remotePath); if ($info['dirname'] == '.') { $info['dirname'] = '/'; } $remotePath = $this->getPathString($this->getPathArray($info['dirname'])); if (!($remoteFolder = Node::loadByPath($remotePath))) { $response = $this->createDirectoryPath($remotePath); if ($response['success'] === false) { return $response; } $remoteFolder = $response['data']; } $response = $this->nodeExists("{$remotePath}/{$info['basename']}", $resource); if ($response['success'] === true) { $pathMatch = $response['data']['path_match']; $md5Match = $response['data']['md5_match']; if ($pathMatch === true && $md5Match === true) { // Skip if path and MD5 match $retval['data'] = $response['data']; return $retval; } else { if ($pathMatch === true && $md5Match === false) { // If path is the same and checksum differs, only overwrite if ($overwrite === true) { return $response['data']['node']->overwrite($resource); } $retval['data'] = $response['data']; return $retval; } else { if ($pathMatch === false && $md5Match === true) { // If path differs and checksum is the same, check for dedup if ($suppressDedup === false) { $retval['data'] = $response['data']; return $retval; } } } } } $suppressDedup = $suppressDedup ? '?suppress=deduplication' : ''; $response = $this->httpClient->post("{$this->account->getContentUrl()}nodes{$suppressDedup}", ['headers' => ['Authorization' => "Bearer {$this->account->getToken()['access_token']}"], 'multipart' => [['name' => 'metadata', 'contents' => json_encode(['kind' => 'FILE', 'name' => $info['basename'], 'parents' => [$remoteFolder['id']]])], ['name' => 'file', 'contents' => $resource, 'filename' => $info['basename']]], 'exceptions' => false]); $retval['data'] = json_decode((string) $response->getBody(), true); $retval['response_code'] = $response->getStatusCode(); if (($retval['response_code'] = $response->getStatusCode()) === 201) { $retval['success'] = true; (new Node($retval['data']))->save(); } return $retval; }
/** * Get the timestamp of a file. * * @param string $path * * @return array|false */ public function getTimestamp($path) { if (!($node = Node::loadByPath($path))) { return false; } return ['timestamp' => (new \DateTime($node['modifiedDate']))->getTimestamp()]; }
/** * @throws \Exception */ protected function initOnlineCommand() { if (count($this->config) === 0) { throw new \Exception('Account has not been authorized. Please do so using the `init` command.'); } $this->cacheStore = $this->generateCacheStore(); if ($this->config['email'] && $this->config['client-id'] && $this->config['client-secret']) { $clouddrive = new CloudDrive($this->config['email'], $this->config['client-id'], $this->config['client-secret'], $this->cacheStore); if ($this->output->getVerbosity() === 2) { $this->output->writeln("Authorizing...", OutputInterface::VERBOSITY_VERBOSE); } if ($clouddrive->getAccount()->authorize()['success']) { if ($this->output->getVerbosity() === 2) { $this->output->writeln("Done."); } $this->clouddrive = $clouddrive; Node::init($this->clouddrive->getAccount(), $this->cacheStore); } else { throw new \Exception('Account has not been authorized. Please do so using the `init` command.'); } } }
/** * Sync the local cache with the remote changes. If checkpoint is null, this * will sync all remote node data. * * @throws \Exception */ public function sync() { $params = ['maxNodes' => 5000]; if ($this->checkpoint) { $params['includePurged'] = "true"; } while (true) { if ($this->checkpoint) { $params['checkpoint'] = $this->checkpoint; } $loop = true; $response = $this->httpClient->post("{$this->getMetadataUrl()}changes", ['headers' => ['Authorization' => "Bearer {$this->token['access_token']}"], 'body' => json_encode($params), 'exceptions' => false]); if ($response->getStatusCode() !== 200) { throw new \Exception((string) $response->getBody()); } $data = explode("\n", (string) $response->getBody()); foreach ($data as $part) { $part = json_decode($part, true); if (isset($part['end']) && $part['end'] === true) { break; } if (isset($part['reset']) && $part['reset'] === true) { $this->cache->deleteAllNodes(); } if (isset($part['nodes'])) { if (empty($part['nodes'])) { $loop = false; } else { foreach ($part['nodes'] as $node) { $node = new Node($node); if ($node['status'] === 'PURGED') { $node->delete(); } else { $node->save(); } } } } if (isset($part['checkpoint'])) { $this->checkpoint = $part['checkpoint']; } $this->save(); } if (!$loop) { break; } } }
/** * Move a FILE or FOLDER `Node` to a new remote location. * * @param \CloudDrive\Node $newFolder * * @return array * @throws \Exception */ public function move(Node $newFolder) { if (!$newFolder->isFolder()) { throw new \Exception("New destination node is not a folder."); } if (!$this->isFile() && !$this->isFolder()) { throw new \Exception("Moving a node can only be performed on FILE and FOLDER kinds."); } $retval = ['success' => false, 'data' => []]; $response = self::$httpClient->post(self::$account->getMetadataUrl() . "nodes/{$newFolder['id']}/children", ['headers' => ['Authorization' => 'Bearer ' . self::$account->getToken()['access_token']], 'json' => ['fromParent' => $this['parents'][0], 'childId' => $this['id']], 'exceptions' => false]); $retval['data'] = json_decode((string) $response->getBody(), true); if ($response->getStatusCode() === 200) { $retval['success'] = true; $this->replace($retval['data']); $this->save(); } return $retval; }