Git Product home page Git Product logo

msgraph-sdk-php's Introduction

Get started with the Microsoft Graph SDK for PHP

Build Status Latest Stable Version Total Downloads PHP Version Require

Install the SDK

You can install the PHP SDK with Composer by editing your composer.json file:

{
    "require": {
        // x-release-please-start-version
        "microsoft/microsoft-graph": "^2.12.0"
        // x-release-please-end
    }
}

Get started with Microsoft Graph

Register your application

Register your application to use the Microsoft Graph API using Microsoft Azure Active Directory in your tenant's Active Directory to support work or school users for your tenant, or multiple tenants.

Create a Token Request Context

A Token Request Context contains the credentials used to authenticate requests. The SDK supports various contexts that align with OAuth 2.0 flows: client_credentials, authorization_code and on_behalf_of with support for secret-based and certificate-based client authentication.

Under the hood, the Token Request Context is passed to an authentication provider which fetches, caches and refreshes access tokens ensuring all requests are authenticated against the Microsoft Identity platform.

The following sample creates a TokenRequestContext that gets access without a user:

<?php
use Microsoft\Kiota\Authentication\Oauth\ClientCredentialContext;
use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;

$tokenRequestContext = new ClientCredentialContext(
    'tenantId',
    'clientId',
    'clientSecret'
);

To gets access on behalf of a user:

<?php
use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;
use Microsoft\Graph\Core\Authentication\GraphPhpLeagueAuthenticationProvider;

$tokenRequestContext = new AuthorizationCodeContext(
    'tenantId',
    'clientId',
    'clientSecret',
    'authCode',
    'redirectUri'
);

Note that your application will need to handle redirecting the user to the Microsoft Identity login page to get the authorization_code that's passed into the AuthorizationCodeContext. See for more on the authorization_code grant flow. To keep your user signed in across multiple requests within a session, see section on access token management

Initialize a GraphServiceClient

Using the Token Request Context and optional scopes, a GraphServiceClient can be initialised:

use Microsoft\Graph\GraphServiceClient;

// Defaults to using https://graph.microsoft.com/.default scopes
$graphServiceClient = new GraphServiceClient($tokenRequestContext);

// With specific scopes
$scopes = ['User.Read', 'Mail.ReadWrite'];
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);

To initialize the GraphServiceClient with an already acquired access token or to retrieve the access token that the SDK fetches on your behalf, see section on access token management.

For more on Graph client configuration, see more examples

Call Microsoft Graph using the v1.0 endpoint and models

The following is an example that shows how to fetch a user from Microsoft Graph

<?php
use Microsoft\Graph\GraphServiceClient;
use Microsoft\Kiota\Abstractions\ApiException;
use Microsoft\Kiota\Authentication\Oauth\ClientCredentialContext;

$tokenRequestContext = new ClientCredentialContext(
    'tenantId',
    'clientId',
    'clientSecret'
);
$graphServiceClient = new GraphServiceClient($tokenRequestContext);

try {
    $user = $graphServiceClient->users()->byUserId('[userPrincipalName]')->get()->wait();
    echo "Hello, I am {$user->getGivenName()}";

} catch (ApiException $ex) {
    echo $ex->getError()->getMessage();
}

Note: The SDK is designed to make async requests by default. Operations (get(), post()...) return a Promise. To get the result, call wait() after the operation. Example: ->get()->wait();

Note that to calling me() requires a signed-in user and therefore delegated permissions (obtained using the authorization_code flow):

<?php
use Microsoft\Graph\GraphServiceClient;
use Microsoft\Kiota\Abstractions\ApiException;
use Microsoft\Kiota\Authentication\Oauth\AuthorizationCodeContext;

$tokenRequestContext = new AuthorizationCodeContext(
    'tenantId',
    'clientId',
    'clientSecret',
    'authCode',
    'redirectUri'
);
$scopes = ['User.Read'];
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);

try {
    $user = $graphServiceClient->me()->get()->wait();
    echo "Hello, I am {$user->getGivenName()}";
} catch (ApiException $ex) {
    echo $ex->getError()->getMessage();
}

Documentation and resources

Upgrading

For detailed information on breaking changes, bug fixes and new functionality introduced during major upgrades, check out our Upgrade Guide

Develop

Run Tests

Run

vendor/bin/phpunit

from the base directory.

Issues

View or log issues on the Issues tab in the repo.

Contribute

Please read our Contributing guidelines carefully for advice on how to contribute to this repo.

Copyright and license

Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT license.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

msgraph-sdk-php's People

Contributors

2miroslav avatar andrii-boiko avatar andrueastman avatar anvanza avatar baywet avatar curry684 avatar dan-silver avatar dbristow-otc avatar dependabot[bot] avatar dragosdanielboia avatar fey101 avatar github-actions[bot] avatar guilliamxavier avatar isvargasmsft avatar jasverix avatar jelle-s avatar landall avatar levure avatar michaelmainer avatar microsoft-github-policy-service[bot] avatar ndiritu avatar noahheck avatar nokafor avatar osalabs avatar release-please[bot] avatar ronnyjss avatar silaskenneth avatar tolbon avatar zengin avatar zombaya avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

msgraph-sdk-php's Issues

File download throws exception on fclose

Hello,

I have an issue where this line throws an exception :

Warning: fclose(): supplied argument is not a valid stream resource

This seems to be fixed in the dev branch with that is_resource check.

Problem being, that I have installed this package with composer and i have the 1.1.1 version. When is the dev branch getting pushed to composer ? Or what would be a good way to workaround this for the time being ?

Open Extensions on mail Message

Hello,

I'm trying to add Open Extension to a mail message.

After reading Microsoft Graph documentation about OpenExtensions, I understand that I have to add this to my json when creating/sending my message :

{
// Message body here
"extensions": 
    {
        "@odata.type":"microsoft.graph.openTypeExtension",
        "extensionName": "com.mydomain.myextensioname",
        "mydatakey": "mydata"
    }
}

However since I'm using this SDK, I'm not sure if this can be done with the SDK. For instance I see that there is a setExtension() method on the Message model, and there is an OpenTypeExtension class, but it only takes an extensionName.

So if adding custom data with Open Extensions is possible with this SDK, where do I add my custom data ?

Thanks.

Downloading the contents of a DriveItem

As per the documentation we can download the file using ->download('C:/item.pdf'); but I want the public url or contents or the file like blob.
Can I get any suggestion?
Thanks

Get profile photo contents

Any time I request the /me/photo/$value resource, the client returns an empty array []. Am I doing something wrong?

Issues installing in Laravel via composer

When I try to install in my project I get this. I have try everything but nothing works. Thanks,

Can you please explain this:

Your requirements could not be resolved to an installable set of packages.

Problem 1
- The requested package tangent-solutions/powerbi-sdk could not be found in any version, there may be a typo in the package name.

Potential causes:

Model/RecurrencePattern:getDaysOfWeek() results in a ErrorException

When trying to execute getDaysOfWeek() on a Model/RecurrencePattern you will receive a ErrorException: Array to string conversion.

This is produced because the code is trying to cast it to a single DayOfWeek instead of an array of DayOfWeek-objects.

Unit test

I created a unit test for this in a new branch.

Example value of DaysOfWeek

$this->_propDict['daysOfWeek'] = array('monday','wednesday');

Location of the bug

// src/Model/RecurrencePattern.php:L146-L163

/**
* Gets the daysOfWeek
* A collection of the days of the week on which the event occurs. Possible values are: sunday, monday, tuesday, wednesday, thursday, friday, saturday.
* If type is relativeMonthly or relativeYearly, and daysOfWeek specifies more than one day, the event falls on the first day that satisfies the pattern.
* Required if type is weekly, relativeMonthly, or relativeYearly.
*
* @return DayOfWeek The daysOfWeek
*/
public function getDaysOfWeek()
{
    if (array_key_exists("daysOfWeek", $this->_propDict)) {
        if (is_a($this->_propDict["daysOfWeek"], "Microsoft\Graph\Model\DayOfWeek")) {
            return $this->_propDict["daysOfWeek"];
        } else {
            $this->_propDict["daysOfWeek"] = new DayOfWeek($this->_propDict["daysOfWeek"]);
            return $this->_propDict["daysOfWeek"];
        }
    }
    return null;
}

AB#7577

Can't download files

From StackOverflow:

I have a service app and I'm willing to download a file from an user's Drive.

I am able to upload a file using

$graph->createRequest("PUT", "/users/".$userId."/drive/items/root:/".$folderName."/".$fileName.":/content")
                ->upload($filePath);

But I am not able to download it. Here is the code I am using:

$graph = new Graph();
$graph->setAccessToken($accessToken);
$graph->createRequest("GET", "/users/".$userId."/drive/items/".$docId."/content")
                    ->download($filePath);

The error is: PHP Warning: fclose(): 16 is not a valid stream resource in microsoft-graph/src/Http/GraphRequest.php on line 344

I could note that making a request to the URL https://graph.microsoft.com/v1.0/users/{USER_ID}/drive/items/{DOC_ID}/content using Postman and passing Authorization Bearer {ACCESS_TOKEN}, the response is the file's content, which is the expected behavior, but for some reason, calling it via PHP is not working.

Decoding a GraphResponse

After uploading a file,I am trying to decode the GraphResponse object,

I use the line $resp = new GraphResponse($response);

Its throwing an error

Class 'Microsoft\Graph\GraphResponse' not found

Is there something I can do to fix this?

otherMails

Is there access to otherMails field while creating a user?
I can't seem to find this

Requesting an empty collection returns an object of the return type

When requesting a collection that returns an empty result the result is actually parsed to an object that was given in the ReturnType.

Example:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.plannerPlan)",
    "@odata.count": 0,
    "value": []
}

Results in

object(Microsoft\Graph\Model\PlannerPlan)[400]
  protected '_propDict' => 
    array (size=3)
      '@odata.context' => string 'https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.plannerPlan)' (length=82)
      '@odata.count' => int 0
      'value' => 
        array (size=0)
          empty

I think the system should handle this as an empty array. The problem can be found in the class \Microsoft\Graph\Http\GraphResponse - method getResponseAsObject - line 152 where the system checks if the variable '$values' is available. When given an empty array the system returns false and continues to parse the collection as an object, returning false results.

Inconsistency between camel case and snake case in getters and setters

In some of the models the getters use camel case for the property array but the setters use snake case. One of the examples would be the DateTimeTimeZone Model. This does not create any issues when fetching data but leads to problems when trying to create these objects to attach them to requests.

Batch request

How does one execute a batch request with the currently provided library?
The docs don't give any example.

Wrong phpdoc if using inherit class

link: https://github.com/microsoftgraph/msgraph-sdk-php/blob/dev/src/Http/GraphRequest.php#L141

What should be:

    /**
    * Sets the return type of the response object
    *
    * @param mixed $returnClass The object class to use
    *
    * @return static object
    */
    public function setReturnType($returnClass)
    {
        $this->returnType = $returnClass;
        if ($this->returnType == "GuzzleHttp\Psr7\Stream") {
            $this->returnsStream  = true;
        } else {
            $this->returnsStream = false;
        }
        return $this;
    }

what is:

    /**
    * Sets the return type of the response object
    *
    * @param mixed $returnClass The object class to use
    *
    * @return GraphRequest object
    */
    public function setReturnType($returnClass)
    {
        $this->returnType = $returnClass;
        if ($this->returnType == "GuzzleHttp\Psr7\Stream") {
            $this->returnsStream  = true;
        } else {
            $this->returnsStream = false;
        }
        return $this;
    }

When I'm using GraphCollectionRequest object class and try to chain setReturnType method, phpstorm don't hint the GraphCollectionRequest methods, because treat that like GraphRequest object.
AB#7570

sync mails delta same message ids

Hi,

I ran into a problem when I was trying to sync messages.
The ids of the messages in the first 2 pages are exactly the same.
In all the other pages the the ids are unique.

But the id of the first message of the first page == the id of the first message of the second page
the id of the second message of the first page == the id of the second message of the second page
...

Could this be a bug in the library ?
Here's the code I use to sync the messages:

try{
            $graph = new Graph();
            $graph->setAccessToken($token);
            if($deltaLink == false){
                $deltaPageRequest = $graph->createCollectionRequest("GET", "/me/mailFolders/$folder_id/messages/delta")
                    ->setReturnType(Model\Message::class);
            }else{
                $deltaPageRequest = $graph->createCollectionRequest("GET", $deltaLink)
                ->setReturnType(Model\Message::class);
            }  
        }catch(\Exception $e){
            error_log($e->getMessage());
            return array();
        }  

        while (!$deltaPageRequest->isEnd()) {
            $items = $deltaPageRequest->getPage();
            foreach ($items as $item) {
                //here the ids of the messages in the first 2 pages are exactly the same
                $mails[$item->getId()] = $this->parseMail($item);
            }
        }

Hash (#) in filename

Hi

I'm attempting to send a file to OneDrive using the following code:

    $uri = "/me/drive/items/$folderId/children('{$fileName}')/content";

    $graph = $this->graph->create($user);
    $client = $this->graph->createClient();

    $item = $graph->createRequest("PUT", $uri)
        ->attachBody($fileContent)
        ->setReturnType(Model\DriveItem::class)
        ->execute($client);

This works great if $fileName is something like Test.doc

But for some reason, when the filename has a hash (#) in the filename, then I get an error:

object(Microsoft\Graph\Model\DriveItem)#1509 (1) {
  ["_propDict":protected]=>
  array(1) {
    ["error"]=>
    array(3) {
      ["code"]=>
      string(10) "BadRequest"
      ["message"]=>
      string(36) "Bad Request - Error in query syntax."
      ["innerError"]=>
      array(2) {
        ["request-id"]=>
        string(36) "ff3fe15f-b1ee-4e92-8abd-2400b1c1b5cf"
        ["date"]=>
        string(19) "2018-10-04T14:30:51"
      }
    }
  }

Can someone possibly clarify if this is a bug or actual behaviour (i.e. you cannot have a # in a filename)

Thanks

EDIT:

StackOverflow question: https://stackoverflow.com/questions/40914114/how-to-install-a-specific-version-of-package-using-composer

Requests fail when the endpoint string contains case-insensitive "http"

I was receiving GuzzleHttp\Exception\ClientException "BadRequest" exceptions for a large amount of the requests I was sending.

Client error: `GET https://graph.microsoft.com/me/calendarview/delta?$deltatoken={{{redacted_deltatoken}}}` resulted in a `400 Bad Request` response:
{
  "error": {
    "code": "BadRequest",
    "message": "Invalid version",
    "innerError": {
      "request-id":  (truncated...)

The request logged in the exception log was clearly wrong:

GET https://graph.microsoft.com/me/calendarview/delta?$deltatoken={{{redacted_deltatoken}}}

The problem here is that it's missing the api version parameter. But that was definitely set, why is it missing?

After two days of searching, it finally occurred to me that this part of the code is why this request is failing so bad.

Deltatokens are base-64 encoded strings. A delta token can contain the characters h, t and p. After taking a careful look at the actual deltatoken logged by my logger, I found the sequence htTP somewhere in the token.

Unfortunately, this isn't an extremely rare or one-off exception, I had several hundred instances of this exact exception.

TL;DR

stripos (found here) checks the endpoint for the (case-insensitive) string 'http', some endpoints or endpoint parameters can randomly contain the string http (or case-insensitive, like HtTP ...), and will be treated as an opaque URL, which results in a BadRequest exception.

Proposed solution?

I think the whole _getRequestUrl function is defective as a whole, I think the intention was that as you pass a full url like http://blablabla.com/bla that it would use that url instead, but it is only the endpoint, calling new GraphRequest('GET', 'http://blablabla.com/bla, ...) would result in a request sent to https://graph.microsoft.com/http://blablabla.com/bla, which doesn't make any sense to me.

I think the stripos check can just be removed.

Instead, if there is a reason for that check, check if http is found in the beginning of the string instead! i.e. stripos($this->endpoint, "http") === 0

Remove docs and tests from composer

The docs and tests combined bring the composer package to 33.9MB. 33.2MB alone is just docs.

Being in the vendor folder, this generally isn't read. It's also extremely unnecessary when packaged and distributed.

97% of the msgraph-sdk-php package is docs, which aren't read as a composer package.

The specified object was not found in the store when updating photo

Hello.

I'm trying to update a signed user profile photo with the Laravel PHP Microsoft package, but im getting this error again and again:

`Client error: `PUT https://graph.microsoft.com/v1.0/me/photo/$value` resulted in a `404 Not Found` response:\n
{\r\n
  "error": {\r\n
    "code": "ErrorItemNotFound",\r\n
    "message": "The specified object was not found in the store., No  (truncated...)\n`

This is my code:

public function updatePhoto($photo){
        $image = Image::make($photo);
        $image->encode('png');
        $tokenCache = new \App\TokenStore\TokenCache;
        $graph = new Graph();
        $graph->setAccessToken($tokenCache->getAccessToken());
        $update = $graph->createRequest("PUT", "/me/photo/\$value")
             ->addHeaders(array("Content-Type" => "image/png"))
             ->attachBody($image)
             ->execute();
    }

The documentation is very general and I don't know what I'm doing wrong.

POST request sample missing

Here's a working sample of a code that creates a calendar event. Make sure you add the oauth scope "calendars.readwrite"

use Microsoft\Graph\Graph;
use Microsoft\Graph\Model\Event;

// create event - https://msdn.microsoft.com/office/office365/APi/calendar-rest-operations#create-events
$data = [
    'Subject' => 'Discuss the Calendar REST API',
    'Body' => [
        'ContentType' => 'HTML',
        'Content' => 'I think it will meet our requirements!',
    ],
    'Start' => [
        'DateTime' => '2017-04-03T10:00:00',
        'TimeZone' => 'Pacific Standard Time',
    ],
    'End' => [
        'DateTime' => '2017-04-03T11:00:00',
        'TimeZone' => 'Pacific Standard Time',
    ],
];
$baseId = 'AAMkAGIwN2UwM2RjLTk5MGUtNGIyNy1iOWFhLTAwNGVkMjdkMjRmZABGAAAAAACJt9sn3f6GR6qxavhjhQC1BwAt21bHzu1ZRIju7agcz-kiAAAAAAEGAAAt21bHzu1ZRIju7agcz-';
$calendarId = $baseId . 'kiAAAd2sS_AAA=';
$url = "/me/calendars/$calendarId/events";
$response = $graph->createRequest("POST", $url)
    ->attachBody($data)
    ->setReturnType(Event::class)
    ->execute();
echo '<pre>';print_r($response);exit;

Improvement: expanded relations to objects

When we query the graph and expand the a relationship, for example /sites/root?$expand=sites the return value type of getSites will be an array and not an array of Site objects.

This is just an example, the same counts for other expanded relationships (/drive/root?$exapend=children, ...). I'm aware that this is a breaking change.
AB#7584

in the phpdoc for Contact, the types of array valued fields are specified as singletons

ex,

   /** 
    * Sets the emailAddresses
    * The contact's email addresses.
    *
    * @param EmailAddress $val The emailAddresses
    *
    * @return Contact
    */
    public function setEmailAddresses($val)
    {
	$this->_propDict["emailAddresses"] = $val;
        return $this;
    }

should have
* @param EmailAddress[] $val The emailAddresses
so the ide knows its an array. Currently the API fails if you pass it a single EmailAddress (expected), and then the IDE yells at you when you correctly pass it an array (annoying), not just annoying but also I'm relying on the phpdoc to tell me the correct format of the parameter to this method, and its telling me the wrong thing, which is a problem. Also applies to setImAddresses, setHomePhones, setBusinessPhones, setChildren,

AB#7590

OneDrive functional tests require pre-existing files

The following functional tests fail when the requested file does not exist:

  • testSearchFile
  • testCreateSharingLink
  • testInvite

The setup for this test should make one or more files to be used in testing. testSearchFile() should also search for a minimum of one file, instead of requiring a certain number of files to be found.
AB#7591

API returns same response some time.

Hi run cronjob which fetch workspace and dump into mysql database. I also set log for all the workspace i got from response.

sometimes api response are the same( i mean it will not get updated workspace) until i open file and re upload it on server its start working.

I check file permission but that was not issued. I check log but updated workspace are not in response, but when i echo the response it display and reupload to server its display.

I dont find issue either this issue is cause by cache or something else

@odata.nextLink question - How to get list of all users (not only the first 100)

Hi Caitlin,

Firstly, my name is Milan and I work for a company called TimeTac. I am working on synchronization service between Microsoft Azure (using Graph API) and our TimeTac system. At one point, I found out about your project 'Microsoft Graph SDK PHP' and I decided to test it out.

Most importantly, thank you for your effort! This library works very well and I managed to accomplish most of what I needed, but I believe I find an issue (or bug), so I wanted to ask you about this. Let me describe it shortly:

When I use /users to fetch all the users I get first 100 of users (because endpoint returns paginated results. Also in that response, there is a field called @odata.nextLink, where I should be able to read a link to get next 100 of users, etc.

I use this part of the code to get a list of the users:
$users = $graph->createRequest("GET", "/users")
->setReturnType(Model\User::class)
->execute();
This code will return first 100 of users, but I see no way to get @odata.nextLink in order to read all of them. My questions are:

  1. Should the SDK API be aware of nextLink field and return all data to me?
  2. If not, what can I do to get @odata.nextLink at the same time when I executeRequest and get a list of the users?

To clarify, my final goal is to get array $users which have all users (not only the first 100, as it currently does). What would be the best approach to accomplish this with your SDK?

p.s. If I was using Guzzle alone (without your SDK) I would get whole response and find @odata.nextLink field, then create some kind of while(@odata.nextLink) structure to iterate through all the users, but I'm not sure how to do it here, because I'm not getting $response, but a $users array.

I was reading through documentation and comments inside your code, but I haven't found a suitable solution. Any help would be appreciated.

Kind regards,

Support for AD Graph API (graph.windows.net)

Hi there,

we want to use this package for the AD Graph API => graph.windows.net (not the normal Graph API => graph.microsoft.com).

The main problem I currently see, is how the version is passed in the URL (URL-Path vs GET-Param).

Is there another PHP Package which supports the AD Graph API?
Do you plan to support the AD Graph API in future?

Best regards

Alex
AB#7574

Missing getters in Location model (beta API)

A typical resource/room contains the following (beta API):

Location {#381 ▼
  #_propDict: array:7 [▼
    "displayName" => "Room Name"
    "locationUri" => "[email protected]"
    "locationType" => "conferenceRoom"
    "uniqueId" => "[email protected]"
    "uniqueIdType" => "directory"
    "address" => array:6 [▶]
    "coordinates" => []
  ]
}

However, the Location model only contains getters for

  • displayName
  • locationEmailAddress (returns empty)
  • address

big delta sync

Hi,

Consider the following example:

$deltaPageRequest = $graph->createCollectionRequest('GET', '/me/mailFolders/[id]/messages/delta')
                                ->setPageSize(50)
                                ->setReturnType(Model\Message::class);
while (!$deltaPageRequest->isEnd()) {
                $items = $deltaPageRequest->getPage();
                 foreach ($items as $item) {
                              //do stuff
                 }
}

Here we sync the messages in a specific folder in the user's mailbox. This works fine but if there are a lot of messages in the folder some problems can occur. (I'm trying to sync 40000 messages)

If the access token expires while we are syncing this huge amount of messages we get a "InvalidAuthenticationToken" exception.

It's possible to catch this exception and set a new token for the graph object:

$graph->setAccessToken()

But you can't change the access token for the $deltaPageRequest.
So you can only create a new CollectionRequest and start again. But you also can't specify a start page for the CollectionRequest. So if we were syncing page 50 and we received the "InvalidAuthenticationToken" exception we can't recreate the $deltaPageRequest en start from page 50 and proceed. We have to start from page 1 again.

So what would be the best solution for this problem ? Change the GraphRequest class and make it possible to change the access token or change the GraphCollectionRequest class to specify the page for the first request ? Or is there a better solution ?

AB#7576

Version 1.3.1 prohibits successing delta-requests

Version 1.3.1 removed a test to see if a request started with http. This makes it harder to do successing deltapage requests.

I wrote a failing unittest, although I suspect there should allready be one, namely Functional\DeltaQueryTest::testDeltaQuery(). I do not have access to groups, so I'm not able to test that one.

Unittest

I added a patch for this test as an attachment.

// File: tests\Functional\MailTest.php
public function testMailGetFoldersWithDelta()
{
        $folderIterator = $this->_client
            ->createCollectionRequest('GET', '/me/mailFolders/delta')
            ->setReturnType(Model\MailFolder::class);

        while (!$folderIterator->isEnd())
        {
            $folders = $folderIterator->getPage();
        }

        $deltaLink = $folderIterator->getDeltaLink();

        $this->assertNotEmpty($deltaLink);

        $folderIterator = $this->_client
            ->createCollectionRequest('GET', $deltaLink)
            ->setReturnType(Model\MailFolder::class);

        while (!$folderIterator->isEnd()) {
            $folders = $folderIterator->getPage();
        }

        $deltaLink2 = $folderIterator->getDeltalink();
        $this->assertNotEquals($deltaLink,$deltaLink2);
}

Test Result

E                                                                   1 / 1 (100%)

Time: 3.73 seconds, Memory: 6.00MB

There was 1 error:

1) MailTest::testMailGetFoldersWithDelta
GuzzleHttp\Exception\RequestException: cURL error 1: Protocol "v1.0https" not supported or disabled in libcurl (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:187
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:150
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:103
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php:43
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php:28
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php:51
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php:37
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/Middleware.php:30
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php:70
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/Middleware.php:59
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/HandlerStack.php:67
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/Client.php:277
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/Client.php:125
/home/int8/msgraph-sdk-php/vendor/guzzlehttp/guzzle/src/Client.php:131
/home/int8/msgraph-sdk-php/src/Http/GraphRequest.php:257
/home/int8/msgraph-sdk-php/src/Http/GraphCollectionRequest.php:150
/home/int8/msgraph-sdk-php/tests/Functional/MailTest.php:146
/home/int8/msgraph-sdk-php/vendor/phpunit/phpunit/phpunit:52

ERRORS!
Tests: 1, Assertions: 1, Errors: 1.

Process finished with exit code 2

Reason

$folderIterator->getDeltaLink() will result in a string like https://graph.microsoft.com/v1.0/me/mailFolders/delta?$deltatoken={redactedDeltaToken}.

Since there is no longer a check to see if an endpoint starts with http, the version will be prepended to the string, resulting in a faulty url like v1.0https://graph.microsoft.com/v1.0/me/mailFolders/delta?$deltatoken={redactedDeltaToken}.

API version

This api sdk library uses https://graph.microsoft.com/ with v1.0, but if you have a look at the calendar api here https://msdn.microsoft.com/office/office365/APi/calendar-rest-operations and check the v2.0 checkbox at the top, you will see that this sdk actually uses https://outlook.office.com/api/ with v2.0

I know this is true because I tried the POST body parameters of the version 1.0 and it gave me an error.

Can someone explain the different names and versions of these apis?
I tried going to https://developer.microsoft.com/en-us/graph/ but there's no information about the api versions.

Thank you.

Facilitate expected failures, specifically 404

For endpoint /me/manager the expected result is a 404 page not found if you are the "top of the food chain". Currently this is treated as a hard error and thus causing an exception to be thrown, whilst it's expected program flow. I'd expect (in this case) a 404 to be internally handled to a null return value.

$graph variable undefined

Hi,

I just installed msgraph using:
composer require 'microsoft/microsoft-graph'

I am now trying to see if the installation was successful by returning the $graph variable after I run autoload.php.

include('../../vendor/autoload.php');
var_dump($graph);

It returns NULL.

Is there something that I have missed?

UploadSession example

Hello,

I'm trying to upload files to OneDrive, but I don't see any example of UploadSession in this repo even tho the UploadSession model exists.

Could you provide an example please ?

Thanks

Model Constructor Design

Many (All ?) classes within the Microsoft\Graph\Model namespace extend Microsoft\Graph\Model\Entity. Each has the following private property and constructor:

private $_propDict;

public function __construct($propDict = array())
{
    parent::__construct($propDict);
    $this->_propDict = $propDict;
    return $this;
}

At the same time, the Microsoft\Graph\Model\Entity also contains the private $_propDict property and a similar constructor:

private $_propDict;

public function __construct($propDict = array())
{
    $this->_propDict = $propDict
    return $this;
}

The return statement from the constructor does nothing, as the purpose of the constructor is to instantiate the object, the return value is essentially ignored. Therefore, all return statements from can be removed.


I haven't had a chance to look at all Models, but the current management of the $_propDict property and the __construct functions is a bit confusing. If a Model subclass doesn't declare it's own constructor, the parent's constructor will be invoked:

class BaseClass
{
	protected $values;

	public function __construct($values)
	{
		$this->values = $values;
	}
}

class ChildClass extends BaseClass
{
	public function getValues()
	{
		return $this->values;
	}
}

$object = new ChildClass(['stuff', 'stuff2']);

print_r($object->getValues()); // Array('stuff', 'stuff2')

The current behavior of the Models though will create 2 full copies of the $propDict property whose values will change independent of each other:

class BaseClass
{
	private $values;

	public function __construct($values)
	{
		$this->values = $values;
	}

	public function getParentValues()
	{
		return $this->values;
	}
}

class ChildClass extends BaseClass
{
	private $values;

	public function __construct($values)
	{
		parent::__construct($values);

		$this->values = array_merge($values, ['stuff3']);
	}

	public function getChildValues()
	{
		return $this->values;
	}
}

$object = new ChildClass(['stuff', 'stuff2']);

print_r($object->getParentValues()); // Array('stuff', 'stuff2')
print_r($object->getChildValues());  // Array('stuff', 'stuff2', 'stuff3')

If there isn't a specific design reason for the current behavior, we change the visibility of the $_propDict property of the Entity class to protected then remove that property and the constructor of each of the sub-classes.

Problem with calling getStart repeatedly

Calling getStart() on the Event Model repeatedly will lead to nested DateTimeTimeZone Objects

Calling print_r($event->getStart()) three times in a row will lead to this result:
screenshot_032417_012748_am

Changing
if (is_a($this->_propDict["start"], "DateTimeTimeZone")) {

Into

if (is_a($this->_propDict["start"], "Microsoft\Graph\Model\DateTimeTimeZone")) {

solved this problem for me.

(It is likely that the same issue occures for other methods returning objects, e.g. getLocation(), getBody() etc.)

Paginating messages

When getting messages only 10 messages are returned the data does not contain @odata:nextLink

$me = $graph->createRequest("get", "/me/messages")
            ->setReturnType(Model\Message::class)
            ->execute();
return $me;

[Disregard] - Quick question regarding Contact ids

Should they be unique each time I create a Contact? I've just created 3 different contacts and when listing them back they have the same id. Have I missed something or am I misunderstanding?

$data = new Model\Contact([
    'givenName'      => 'Joe',
    'surname'        => date('YmdHis'),
    'emailAddresses' => [
        [
            'address' => date('YmdHis') . '@xyz.com',
            'name'    => 'Joe ' . date('YmdHis'),
        ],
    ],

]);

$url = '/me/contacts';
$result = $graph->createRequest('POST', $url)
                ->attachBody($data)
                ->setReturnType(Model\Contact::class)
                ->execute();
echo $contact->getId(); // all the same?

Installing SDK Issue

Hi, I have this problem installing the SDK using composer:

[InvalidArgumentException]
Could not find a version of package tangent-solutions/powerbi-sdk matching your minimum-stability (stable). Require
it with an explicit version constraint allowing its desired stability.

What can I do to resolve this?

Thank you!

Get User ID upon Create

Hi,

Which function do I use to retrieve user ID upon creation since getId() is not defined?

Get the conversationI/ID of sent mail

Hello,

I'm actually sending a mail using the /me/sendmail endpoint, but in the graph documentation, it says server doesn't send back any response. So is there a way to get the ID or ConversationID of the sent mail ? Or do i have to create the message first as a draft then send it ?

Thanks in advance.

Big file upload

Hi, while we have UploadSession class, getUploadUrl, setUploadUrl methods for uploading big files, but because of newbie I can't understand whole procedure, so tried normal uploading method, but returns Maximum request length exceeded. can anyone will explain/write the procedure/code.

Clarify editable components of the library

As I'm actively using the library (you may have noticed 😉 ) I'm happy to suggest improvements where I see fit, however it's not quite clear which changes would be persistent. Most of the library, at least the Models namespace, is obviously generated, so changes would likely be lost when API v1.1 or v2 arrives.

I would appreciate either some guidance on this subject (CONTRIBUTING.md file?), or some kind of insight in how the library is generated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.