vgrem/php-spo
REST/OData client library for Microsoft 365 in PHP. Access SharePoint Online/On-Prem (2013-2019), OneDrive for Business, Teams, and Outlook APIs with supported auth flows (client credentials, certificates, etc.). Install via Composer.
Added
GraphServiceClient::withUserCredentials and GraphServiceClient::withClientSecret methods introducedFixed
16.0.24106.12014 versionGraphServiceClient$siteUrl = "https://contoso.sharepoint.com"; //site or web absolute url
$tenant = "contoso.onmicrosoft.com"; //tenant id or name
$thumbprint = "--thumbprint goes here--";
$clientId = "--client app id goes here--";
$privateKetPath = "-- path to private.key file--"
$privateKey = file_get_contents($privateKetPath);
$ctx = (new ClientContext($siteUrl))->withClientCertificate(
$tenant, $clientId, $privateKey, $thumbprint);
$whoami = $ctx->getWeb()->getCurrentUser()->get()->executeQuery();
print $whoami->getLoginName();
$credentials = new ClientCredential($clientId, $clientSecret);
$client = (new ClientContext($siteUrl))->withCredentials($credentials);
$docSetName = "Orders";
$lib = $client->getWeb()->defaultDocumentLibrary();
$docSet = DocumentSet::create($client, $lib->getRootFolder(), $docSetName)->executeQuery();
print($docSet->getProperty("ServerRelativeUrl"));
CcRecipients property to Message class by @DavidBrogliClientObjectCollection class enhancements, introduced getAll method by @vgremExample: read list items in a large list via getAll method:
$ctx = (new ClientContext($siteUrl))->withCredentials($credentials);
$list = $ctx->getWeb()->getLists()->getByTitle("--large list title--");
$allItems = $list->getItems()->getAll(5000, function ($returnType){
print("{$returnType->getPageInfo()} items loaded...\n");
})->executeQuery();
acquireTokenForPassword method in AADTokenProvider class by @R-Techcomposer.json by @cweiskePHP 8 and drop PHP 5.5 requirement by @cweiskeFieldLookupValue/FieldMultiLookupValue, FieldMultiChoiceValue , refer example 1 below ( related issues: #261)$list = $ctx->getWeb()->getLists()->getByTitle("Tasks");
$taskProps = array(
'Title' => "New task",
'ParentTask' => new FieldLookupValue($taskLookupId),
'PrimaryManager' => new FieldUserValue($userId),
'Managers' => new FieldMultiLookupValue([$userId]),
'TaskCategories' => new FieldMultiChoiceValue(["Event", "Reminder"])
);
$item = $list->addItem($taskProps)->executeQuery();
Reports namespace, refer official documentation for a more detailsOutlook namespace model updates16.0.21729.12001 versionExample: Get details about Microsoft 365 active users
Documentation: reportRoot: getOffice365ActiveUserDetail
use Office365\GraphServiceClient;
use Office365\Runtime\Auth\AADTokenProvider;
use Office365\Runtime\Auth\ClientCredential;
function acquireToken()
{
$resource = "https://graph.microsoft.com";
$provider = new AADTokenProvider($tenantName);
return $provider->acquireTokenForClientCredential($resource,
new ClientCredential($clientId, $clientSecret),["/.default"]);
}
$client = new GraphServiceClient("acquireToken");
$result = $client->getReports()->getOffice365ActivationCounts()->executeQuery();
var_dump($result->getValue());
$result = $client->getReports()->getOffice365ActiveUserDetail("D7")->executeQuery();
var_dump($result->getValue());
16.0.21611.12002 versionExample: Create a modern (communication) site
$credentials = new ClientCredential($ClientId, $ClientSecret);
$ctx = (new ClientContext($Url))->withCredentials($credentials);
$siteManager = new SPSiteManager($ctx);
$result = $siteManager->create("MyCommSite", $ownerEmail, "Low Business Impact");
$siteManager->executeQuery();
print("Site has been created: {$result->getValue()->SiteUrl} \n");
ClientRuntimeContext.executeQueryRetry method to submit queries which supports transparently retrying a failed operation (retry pattern)Example: create a Team
The following is an example of a minimal request to create a Team (via delegated permissions)
use Office365\GraphServiceClient;
use Office365\Runtime\Auth\AADTokenProvider;
use Office365\Runtime\Auth\UserCredentials;
function acquireToken()
{
$tenant = "{tenant}.onmicrosoft.com";
$resource = "https://graph.microsoft.com";
$provider = new AADTokenProvider($tenant);
return $provider->acquireTokenForPassword($resource, "{clientId}",
new UserCredentials("{UserName}", "{Password}"));
}
$client = new GraphServiceClient("acquireToken");
$teamName = "My Sample Team";
$newTeam = $client->getTeams()->add($teamName)->executeQuery();
Example: list all Teams
use Office365\GraphServiceClient;
use Office365\Runtime\Auth\AADTokenProvider;
use Office365\Runtime\Auth\UserCredentials;
function acquireToken()
{
$tenant = "{tenant}.onmicrosoft.com";
$resource = "https://graph.microsoft.com";
$provider = new AADTokenProvider($tenant);
return $provider->acquireTokenForPassword($resource, "{clientId}",
new UserCredentials("{UserName}", "{Password}"));
}
$client = new GraphServiceClient("acquireToken");
$teams = $client->getTeams()->getAll(array("displayName"))->executeQuery();
ClientRuntimeContext.executeQueryRetry method usageOnce Team is created, it might not be immediately available due to replication delay and calling getting team endpoint could fail with a 404 error, the recommended pattern is to retry the get team call three times, with a 10 second delay between calls:
$team = $graphClient->getTeams()->getById($Id)->get()->executeQueryRetry();
#231: introduced support for IPResolve and ForbidReuse options for RequestOptions class by @tommy2d
various bug fixes, including #230
SharePoint API support for Taxonomy namespace, refer example 1 below
SharePoint API model has been updated to 16.0.21221.12006
fluent API improvements, a simplified way to initialize GraphServiceClient and OutlookClient clients by passing acquire token function, AADTokenProvider class which contains built-in support for Client credentials, Username/password flows, refer example 2 below
Example 1: export taxonomy data via SharePoint API
use Office365\Runtime\Auth\ClientCredential;
use Office365\SharePoint\ClientContext;
use Office365\SharePoint\Taxonomy\TaxonomyService;
use Office365\SharePoint\Taxonomy\TermGroup;
$appPrincipal = new ClientCredential($clientId,$clientSecret);
$ctx = (new ClientContext($settings['Url']))->withCredentials($appPrincipal);
$taxSvc = new TaxonomyService($ctx);
$groups = $taxSvc->getTermStore()->getTermGroups()->get()->executeQuery();
$fp = fopen('./SiteTaxonomy.csv', 'w');
/** [@var](https://github.com/var) TermGroup $group */
foreach ($groups as $group){
fputcsv($fp, $group->toJson());
}
fclose($fp);
Example 2: Initialize Graph client
use Office365\Graph\GraphServiceClient;
use Office365\Runtime\Auth\AADTokenProvider;
use Office365\Runtime\Auth\UserCredentials;
function acquireToken()
{
$tenant = "{tenant}.onmicrosoft.com";
$resource = "https://graph.microsoft.com";
$provider = new AADTokenProvider($tenant);
return $provider->acquireTokenForPassword($resource, "{clientId}",
new UserCredentials("{UserName}", "{Password}"));
}
$client = new GraphServiceClient("acquireToken");
OData request headers adjustments (for compatibility with SharePoint 2013 REST Service implementation) #222 by @blizzz
#212: GroupCollection.getByName fix to safely address group by name by @mahmudz
#213: File.finishUpload method fix by @ChangingTerry
SharePoint API model has been updated to 16.0.21103.12002 version
Exclude non-essential files from dist #210 Credit goes to @rvitaliy
SharePoint API model has been updated to 16.0.20628.12006 version
Error handling: validate() method for class Response introduced which throws an exception if the HTTP response was unsuccessful, usage:
$response = Requests::execute($request);
$response->validate();
$file = (new ClientContext($settings['Url']))->withCredentials($credentials)
->getWeb()->getFileByServerRelativePath(new SPResourcePath($fileUrl))->get()->executeQuery();
SharePoint API model has been updated to 16.0.20405.12008 version and introduced a new types and methods:
Web.getFileByServerRelativePath($resourcePath)Web.getFolderByServerRelativePath($resourcePath)Support for addressing Web and File resources by absolute Url
$fileAbsUrl = "https://contoso.sharepoint.com/sites/team/Shared Documents/sample.docx"
$credentials = UserCredential(username, password)
$fh = fopen($fileName, 'w+');
File::fromUrl($fileAbsUrl)->withCredentials($credentials)->download($fh)->executeQuery();
fclose($fh);
Support for simplified ways of authenticating against SharePoint
$credentials = new ClientCredential($clientId, $clientSecret);
$ctx = (new ClientContext($url))->withCredentials($credentials);
SharePoint (for version 16.0.20106.12008) and OutlookServices models have been updated
built-in support to retrieve large collections (or paged data) via lazy loading approach
support for upload "large" file (chunked upload)
5000 items)Due to built-in support, nothing has changed in terms how list items are retrieved to preserve API simplicity, no matter how many items list contains (unless $top query option is provided to restrict the amount of items to load)
Behind the scene, lazy loading approach is utilized to retrieve paged data, which offers optimal performance since the data is getting load only when requested.
$list = $ctx->getWeb()->getLists()->getByTitle("--Large List Title--");
$items = $list->getItems();
$ctx->load($items);
$ctx->executeQuery();
print $items->getCount() . PHP_EOL; //prints the actual amount of items in list/library
//iterate across all list items
foreach ($items as $index => $item){
print($index . ":" . $item->getProperty('Title') . PHP_EOL);
}
Note: Use this solution if you want to upload files that are larger than 2 MB to SharePoint.
$ctx = ClientContext::connectWithClientCredentials($Url, $ClientId, $ClientSecret);
$localPath = "../data/big_buck_bunny.mp4";
$targetLibraryTitle = "Documents";
$targetList = $ctx->getWeb()->getLists()->getByTitle($targetLibraryTitle);
$session = $targetList->getRootFolder()->getFiles()->createUploadSession($localPath, "big_buck_bunny.mp4",
function ($uploadedBytes) {
echo "Progress: $uploadedBytes bytes uploaded .." . PHP_EOL;
});
$ctx->executeQuery();
$targetFileName = $session->getFile()->getName();
echo "File $targetFileName has been uploaded.";
16.0.20008.12009 API versionOffice365\PHP\Client\SharePoint into Office365\SharePointfrom now on instead of
$authCtx = new AuthenticationContext($url); $authCtx->acquireTokenForUser($username,$password); $ctx = new ClientContext($url,$authCtx);
an authenticated client could be instantiated like this:
$ctx = ClientContext::connectWithUserCredentials($url, $username,$password);
and
$authCtx = new AuthenticationContext($url); $authCtx->acquireAppOnlyAccessToken($clientId,$clientSecret); $ctx = new ClientContext($url,$authCtx);
like this:
$ctx = ClientContext::connectWithClientCredentials($url, $clientId,$clientSecret);
introduced a support to generate SharePoint model (complex & entity types) from EDMX metadata
The list of changes:
Types:
RoleType - Specifies the types of roles that are available for users and groups.
RoleDefinitionCreationInformation - Contains properties that are used as parameters to initialize a role definition.
Methods:
RoleAssignmentCollection.addRoleAssignment - Adds a role assignment to the collection of role assignment objects
RoleAssignmentCollection.getByPrincipalId - Gets the role assignment associated with the specified principal ID from the collection
RoleAssignmentCollection.removeRoleAssignment - Removes the role assignment with the specified principal and role definition from the collection.
RoleDefinitionCollection.getById - Gets the role definition with the specified ID from the collect
RoleDefinitionCollection.getByName - Gets the role definition with the specified name.
RoleDefinitionCollection.getByType - Gets the role definition with the specified role type.
Introduced support to set cURL timeout option and bug fixes.
All credit goes to @Deuchnord for those changes.
Introduced support for the resource owner password credential (ROPC) grant, which allows an application to sign in the user by directly handling their password. Could be utilized instead of Basic Authentication which was discontinued in Office 365
The list of changes:
Introduced support for skiptoken operation in query options #118
Added support for managing requests state ( e.g. skipping failed requests)
Updated Travis config file for unit testing against PHP 7.3
The list of resolved issues:
#115 - process error from STS response
JSON formats mapper improvements
Added support for federated STS authentication
The following methods have been introduced:
How can I help you explore Laravel packages today?