From a1ababbd728428f35218807c4b646541931bec47 Mon Sep 17 00:00:00 2001 From: vgrem Date: Thu, 7 Jul 2022 13:21:24 +0300 Subject: [PATCH] SharePoint API: file/folder addressing enhancements --- .../Files/DownloadFileAsContent.php | 6 +-- examples/SharePoint/Files/DownloadFiles.php | 18 +++++-- src/SharePoint/File.php | 54 +++++++++++++------ src/SharePoint/Folder.php | 2 +- .../Internal/Paths/FileContentPath.php | 20 +++++++ src/SharePoint/Web.php | 21 ++++++++ 6 files changed, 96 insertions(+), 25 deletions(-) create mode 100644 src/SharePoint/Internal/Paths/FileContentPath.php diff --git a/examples/SharePoint/Files/DownloadFileAsContent.php b/examples/SharePoint/Files/DownloadFileAsContent.php index 2bb59e27..a7e90202 100644 --- a/examples/SharePoint/Files/DownloadFileAsContent.php +++ b/examples/SharePoint/Files/DownloadFileAsContent.php @@ -8,13 +8,13 @@ require_once '../../vendor/autoload.php'; $settings = include('../../../tests/Settings.php'); -$sourceFileUrl = "/Shared Documents/SharePoint User Guide.docx"; +$sourceFileUrl = "/sites/team/Shared Documents/sample.txt"; $targetPath = "../data/SharePoint User Guide.docx"; $appCreds = new ClientCredential($settings['ClientId'], $settings['ClientSecret']); -$ctx = (new ClientContext($settings['Url']))->withCredentials($appCreds); +$ctx = (new ClientContext($settings['TeamSiteUrl']))->withCredentials($appCreds); $fileContent = Office365\SharePoint\File::openBinary($ctx, $sourceFileUrl); print "File {$targetPath} has been downloaded successfully\r\n"; -$fileName = join(DIRECTORY_SEPARATOR,[sys_get_temp_dir(),"SharePoint User Guide.docx"]); +$fileName = join(DIRECTORY_SEPARATOR,[sys_get_temp_dir(),basename($sourceFileUrl)]); file_put_contents($fileName,$fileContent); diff --git a/examples/SharePoint/Files/DownloadFiles.php b/examples/SharePoint/Files/DownloadFiles.php index a5cc7e61..000dd60b 100644 --- a/examples/SharePoint/Files/DownloadFiles.php +++ b/examples/SharePoint/Files/DownloadFiles.php @@ -12,20 +12,28 @@ $creds = new ClientCredential($settings['ClientId'], $settings['ClientSecret']); $ctx = (new ClientContext($settings['TeamSiteUrl']))->withCredentials($creds); -$lib_title = "Documents"; +/*$lib_title = "Documents"; $lib = $ctx->getWeb()->getLists()->getByTitle($lib_title); -$folder = $lib->getRootFolder()->expand("Files")->get()->executeQuery(); +$rootFolder = $lib->getRootFolder()->expand("Files")->get()->executeQuery();*/ + +$rootFolder = $ctx + ->getWeb() + ->getFolderByServerRelativeUrl('Shared Documents') + ->expand('Files') + ->get() + ->executeQuery(); + /** @var File $file */ -foreach ($folder->getFiles() as $file) { +foreach ($rootFolder->getFiles() as $file) { try { $localPath = join(DIRECTORY_SEPARATOR, [sys_get_temp_dir(), $file->getName()]); $fh = fopen($localPath, 'w+'); $file->download($fh)->executeQuery(); fclose($fh); print "File: {$file->getServerRedirectedUrl()} has been downloaded into {$localPath}\r\n"; - } catch (\Throwable $th) { - print "Error {$th->getCode()} - File download failed: {$th->getMessage()}"; + } catch (Exception $ex) { + print "Error {$ex->getCode()} - File download failed: {$ex->getMessage()}"; } } diff --git a/src/SharePoint/File.php b/src/SharePoint/File.php index a83b923b..36871671 100644 --- a/src/SharePoint/File.php +++ b/src/SharePoint/File.php @@ -6,7 +6,6 @@ namespace Office365\SharePoint; use Exception; -use Office365\Runtime\Actions\InvokeMethodQuery; use Office365\Runtime\Actions\InvokePostMethodQuery; use Office365\Runtime\ClientResult; use Office365\Runtime\ClientRuntimeContext; @@ -16,6 +15,7 @@ use Office365\Runtime\Paths\ServiceOperationPath; use Office365\Runtime\ResourcePath; use Office365\Runtime\Types\Guid; +use Office365\SharePoint\Internal\Paths\FileContentPath; use Office365\SharePoint\WebParts\LimitedWebPartManager; /** @@ -177,17 +177,25 @@ public function recycle() $this->getContext()->addQuery($qry); return $this; } + + /** * Opens the file - * @param ClientRuntimeContext $ctx - * @param $serverRelativeUrl + * @param ClientContext $ctx + * @param string $serverRelativeUrl + * @param bool $usePath * @return mixed|string * @throws Exception */ - public static function openBinary(ClientRuntimeContext $ctx, $serverRelativeUrl) + public static function openBinary(ClientRuntimeContext $ctx, $serverRelativeUrl, $usePath=true) { - $serverRelativeUrl = rawurlencode($serverRelativeUrl); - $url = $ctx->getServiceRootUrl() . "/web/getfilebyserverrelativeurl('{$serverRelativeUrl}')/\$value"; + $file = new File($ctx); + if($usePath) + $file->setProperty("ServerRelativePath",new SPResourcePath($serverRelativeUrl)); + else + $file->setProperty("ServerRelativeUrl",$serverRelativeUrl); + $contentPath = new FileContentPath($file->getResourcePath()); + $url = $ctx->getServiceRootUrl() . $contentPath->toUrl(); $options = new RequestOptions($url); $options->TransferEncodingChunkedAllowed = true; $response = $ctx->executeQueryDirect($options); @@ -199,15 +207,21 @@ public static function openBinary(ClientRuntimeContext $ctx, $serverRelativeUrl) /** * Saves the file * Note: it is supported to update the existing file only. For adding a new file see FileCollection.add method - * @param ClientRuntimeContext $ctx + * @param ClientContext $ctx * @param string $serverRelativeUrl * @param string $content file content + * @param bool $usePath * @throws Exception */ - public static function saveBinary(ClientRuntimeContext $ctx, $serverRelativeUrl, $content) + public static function saveBinary(ClientRuntimeContext $ctx, $serverRelativeUrl, $content, $usePath=true) { - $serverRelativeUrl = rawurlencode($serverRelativeUrl); - $url = $ctx->getServiceRootUrl() . "/web/getfilebyserverrelativeurl('{$serverRelativeUrl}')/\$value"; + $file = new File($ctx); + if($usePath) + $file->setProperty("ServerRelativePath",new SPResourcePath($serverRelativeUrl)); + else + $file->setProperty("ServerRelativeUrl",$serverRelativeUrl); + $contentPath = new FileContentPath($file->getResourcePath()); + $url = $ctx->getServiceRootUrl() . $contentPath->toUrl(); $request = new RequestOptions($url); $request->Method = HttpMethod::Post; $request->ensureHeader('X-HTTP-Method', 'PUT'); @@ -259,7 +273,8 @@ public function getCheckOutType() */ public function getListItemAllFields() { - return $this->getProperty("ListItemAllFields", new ListItem($this->getContext(), new ResourcePath("ListItemAllFields", $this->getResourcePath()))); + return $this->getProperty("ListItemAllFields", + new ListItem($this->getContext(), new ResourcePath("ListItemAllFields", $this->getResourcePath()))); } /** * Starts a new chunk upload session and uploads the first fragment @@ -298,7 +313,8 @@ public function continueUpload($uploadId, $fileOffset, $content) */ public function finishUpload($uploadId, $fileOffset, $content) { - $qry = new InvokePostMethodQuery($this, "finishupload", array('uploadId' => $uploadId->toString(), 'fileOffset' => $fileOffset), null, $content); + $qry = new InvokePostMethodQuery($this, "finishupload", + array('uploadId' => $uploadId->toString(), 'fileOffset' => $fileOffset), null, $content); $this->getContext()->addQueryAndResultObject($qry, $this); return $this; } @@ -306,10 +322,14 @@ function setProperty($name, $value, $persistChanges = true) { parent::setProperty($name, $value, $persistChanges); if ($name === "UniqueId") { - $this->resourcePath = new ResourcePath("GetFileById(guid'{$value}')", new ResourcePath("Web")); - } else { + $this->resourcePath = $this->getParentWeb()->getFileById($value)->getResourcePath(); + } + if (is_null($this->resourcePath)) { if ($name === "ServerRelativeUrl") { - $this->resourcePath = new ResourcePath("GetFileByServerRelativeUrl('{$value}')", new ResourcePath("Web")); + $this->resourcePath = $this->getParentWeb()->getFileByServerRelativeUrl($value)->getResourcePath(); + } + elseif ($name === "ServerRelativePath") { + $this->resourcePath = $this->getParentWeb()->getFileByServerRelativePath($value)->getResourcePath(); } } return $this; @@ -889,7 +909,9 @@ public function getModifiedBy() */ public function getEffectiveInformationRightsManagementSettings() { - return $this->getProperty("EffectiveInformationRightsManagementSettings", new EffectiveInformationRightsManagementSettings($this->getContext(), new ResourcePath("EffectiveInformationRightsManagementSettings", $this->getResourcePath()))); + return $this->getProperty("EffectiveInformationRightsManagementSettings", + new EffectiveInformationRightsManagementSettings($this->getContext(), + new ResourcePath("EffectiveInformationRightsManagementSettings", $this->getResourcePath()))); } /** * @return Web|null diff --git a/src/SharePoint/Folder.php b/src/SharePoint/Folder.php index 09a53c16..8dfd55ef 100644 --- a/src/SharePoint/Folder.php +++ b/src/SharePoint/Folder.php @@ -143,7 +143,7 @@ public function getListItemAllFields() function setProperty($name, $value, $persistChanges = true) { if ($name == "UniqueId") { - $this->resourcePath = new ResourcePath("GetFolderById(guid'{$value}')", new ResourcePath("Web")); + $this->resourcePath = $this->getContext()->getWeb()->getFolderById($value)->getResourcePath(); } parent::setProperty($name, $value, $persistChanges); return $this; diff --git a/src/SharePoint/Internal/Paths/FileContentPath.php b/src/SharePoint/Internal/Paths/FileContentPath.php new file mode 100644 index 00000000..13823911 --- /dev/null +++ b/src/SharePoint/Internal/Paths/FileContentPath.php @@ -0,0 +1,20 @@ + rawurlencode($serverRelativePath->DecodedUrl)); return new File($this->getContext(), new ServiceOperationPath("getFileByServerRelativePath", $params, $this->getResourcePath())); } + + /** + * Returns the file object with the specified GUID. + * @param string uniqueId A GUID that identifies the file object. + * @return File + */ + public function getFileById($uniqueId) + { + return new File($this->getContext(), + new ServiceOperationPath("GetFileById", array($uniqueId), $this->getResourcePath())); + } /** * Returns the folder object located at the specified server-relative URL. * @param string $serverRelativeUrl The server relative URL of the folder. @@ -210,6 +221,16 @@ public function getFolderByServerRelativePath($serverRelativePath) { return new Folder($this->getContext(), new ServiceOperationPath("getFolderByServerRelativePath", array("decodedUrl" => rawurlencode($serverRelativePath->DecodedUrl)), $this->getResourcePath())); } + /** + * Returns the folder object with the specified GUID. + * @param string uniqueId A GUID that identifies the folder object. + * @return Folder + */ + public function getFolderById($uniqueId) + { + return new Folder($this->getContext(), + new ServiceOperationPath("GetFolderById", array($uniqueId), $this->getResourcePath())); + } /** * @return ContentTypeCollection */