Skip to content

Commit

Permalink
Fix merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
Ndiritu committed May 25, 2022
2 parents 0cd4e03 + 4d158ec commit 7ef92a5
Show file tree
Hide file tree
Showing 21 changed files with 422 additions and 55 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- Added missing mappings in PHP for uint8 and int8. [#1473](https://github.com/microsoft/kiota/pull/1473)

### Changed

## [0.2.0] - 2022-05-24

### Added

- Added support for enum options descriptions (C#/Go/Java/TypeScript). [#90](https://github.com/microsoft/kiota/issues/90)
Expand All @@ -17,7 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added support for multiple collections indexing under the same parent.
- Added code exclusions placeholder in the generation. (oneOf)
- Added support for continuous access evaluation in Java. [#1179](https://github.com/microsoft/kiota/issues/1179)
- Added missing mappings in PHP for uint8 and int8. [#1473](https://github.com/microsoft/kiota/pull/1473)
- Added support for special characters in URL query parameter names. [#1584](https://github.com/microsoft/kiota/pull/1584)

### Changed

Expand All @@ -39,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed the lookup of model namespaces to only look in the target namespace to avoid reference collisions.
- Fixed a bug for the generated send method for paths returning Enums in dotnet.
- Breaking: renamed the --loglevel parameter to --log-level.
- Fixed a bug where some path parameter objects would have empty key values [#1586](https://github.com/microsoft/kiota/issues/1586)

## [0.1.3] - 2022-05-06

Expand Down
5 changes: 3 additions & 2 deletions abstractions/php/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@
}
},
"require": {
"ramsey/uuid": "^3 || ^4",
"php": "^7.4 || ^8.0",
"php-http/promise": "^1.1.0",
"php-http/message-factory": "^1.0.2",
"rize/uri-template": "^0.3.4"
"league/uri": "^6.5",
"doctrine/annotations": "^1.13",
"ramsey/uuid": "^3 || ^4"
},
"require-dev": {
"phpstan/phpstan": "^1.2.0",
Expand Down
34 changes: 34 additions & 0 deletions abstractions/php/src/QueryParameter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/**
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* Licensed under the MIT License. See License in the project root
* for license information.
*/


namespace Microsoft\Kiota\Abstractions;

/**
* Class QueryParameter
*
* Attribute/annotation for query parameter class properties
*
* @Annotation
* @Target("PROPERTY")
* @NamedArgumentConstructor
* @package Microsoft\Kiota\Abstractions
* @copyright 2022 Microsoft Corporation
* @license https://opensource.org/licenses/MIT MIT License
*/
class QueryParameter
{
/**
* @var string
*/
public string $name = "";

public function __construct(string $name)
{
$this->name = $name;
}
}
29 changes: 0 additions & 29 deletions abstractions/php/src/QueryParameterBase.php

This file was deleted.

36 changes: 30 additions & 6 deletions abstractions/php/src/RequestInformation.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<?php
namespace Microsoft\Kiota\Abstractions;

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;
use Exception;
use InvalidArgumentException;
use League\Uri\Contracts\UriException;
use League\Uri\UriTemplate;
use Microsoft\Kiota\Abstractions\Serialization\Parsable;
use Psr\Http\Message\StreamInterface;
use Rize\UriTemplate;
use RuntimeException;

class RequestInformation {
Expand Down Expand Up @@ -37,9 +40,18 @@ class RequestInformation {
private static string $binaryContentType = 'application/octet-stream';
/** @var string $contentTypeHeader */
public static string $contentTypeHeader = 'Content-Type';
private static AnnotationReader $annotationReader;

public function __construct()
{
// Init annotation utils
AnnotationRegistry::registerLoader('class_exists');
self::$annotationReader = new AnnotationReader();
}

/** Gets the URI of the request.
* @return string
* @throws UriException
*/
public function getUri(): string {
if (!empty($this->uri)) {
Expand All @@ -49,9 +61,9 @@ public function getUri(): string {
&& is_string($this->pathParameters[self::$RAW_URL_KEY])) {
$this->setUri($this->pathParameters[self::$RAW_URL_KEY]);
} else {
$template = (new UriTemplate());
$template = new UriTemplate($this->urlTemplate);
$params = array_merge($this->pathParameters, $this->queryParameters);
return $template->expand($this->urlTemplate, $params);
return $template->expand($params);
}
return $this->uri;
}
Expand Down Expand Up @@ -136,10 +148,22 @@ public function setContentFromParsable(RequestAdapter $requestAdapter, string $c

/**
* Set the query parameters.
* @param array<string,mixed> $queryParameters
* @param object|null $queryParameters
*/
public function setQueryParameters(array $queryParameters): void {
$this->queryParameters = $queryParameters;
public function setQueryParameters(?object $queryParameters): void {
if (!$queryParameters) return;
$reflectionClass = new \ReflectionClass($queryParameters);
foreach ($reflectionClass->getProperties() as $classProperty) {
$propertyValue = $classProperty->getValue($queryParameters);
$propertyAnnotation = self::$annotationReader->getPropertyAnnotation($classProperty, QueryParameter::class);
if ($propertyValue) {
if ($propertyAnnotation) {
$this->queryParameters[$propertyAnnotation->name] = $propertyValue;
continue;
}
$this->queryParameters[$classProperty->name] = $propertyValue;
}
}
}

/**
Expand Down
35 changes: 30 additions & 5 deletions abstractions/php/tests/RequestInformationTest.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<?php

namespace Microsoft\Kiota\Abstractions\Tests;
use DateTime;
use Microsoft\Kiota\Abstractions\RequestInformation;
use PHPUnit\Framework\TestCase;
use Microsoft\Kiota\Abstractions\QueryParameter;
use Rize\UriTemplate;

class RequestInformationTest extends TestCase {
private RequestInformation $requestInformation;
Expand All @@ -15,12 +16,36 @@ protected function setUp(): void {
public function testSetUri(): void{
$pathParameters = [
'baseUrl' => 'https://google.com',
'user' => 'silas',
'user%2Did' => 'silas',
];
$queryParameters = ['startDate' => (new DateTime('2022-01-17'))->format('Y-m-d')];
$this->requestInformation->urlTemplate = '{+baseUrl}/{user}/mails/?startDate=\'{startDate}\'';
$queryParameters = ['%24select' => ['subject', 'importance']];
$this->requestInformation->urlTemplate = '{+baseUrl}/{user%2Did}/mails{?%24select}';
$this->requestInformation->pathParameters = $pathParameters;
$this->requestInformation->queryParameters = $queryParameters;
$this->assertEquals("https://google.com/silas/mails/?startDate='2022-01-17'", $this->requestInformation->getUri());
$this->assertEquals("https://google.com/silas/mails?%24select=subject,importance", $this->requestInformation->getUri());
}

public function testSetQueryParameters(): void {
$this->requestInformation->urlTemplate = '{?%24select,top}';

$queryParam = new TestQueryParameter();
$this->requestInformation->setQueryParameters($queryParam);
$this->assertEquals('?top=10', $this->requestInformation->getUri());
$this->assertTrue(sizeof($this->requestInformation->queryParameters) == 1);
$queryParam->select = ['displayName', 'age'];
$this->requestInformation->setQueryParameters($queryParam);
$this->assertTrue(sizeof($this->requestInformation->queryParameters) == 2);
$this->assertArrayHasKey('%24select', $this->requestInformation->queryParameters);
$this->assertEquals(['displayName', 'age'], $this->requestInformation->queryParameters['%24select']);
$this->assertArrayHasKey('top', $this->requestInformation->queryParameters);
$this->assertEquals('?%24select=displayName,age&top=10', $this->requestInformation->getUri());
}
}

class TestQueryParameter {
/**
* @QueryParameter("%24select")
*/
public ?array $select = null;
public int $top = 10; // no annotation
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public function getAuthorizationTokenAsync(string $url): Promise
return new FulfilledPromise(null);
}
try {
$params = array_merge($this->tokenRequestContext->getParams(), ['scope' => implode(',', $this->scopes)]);
$params = array_merge($this->tokenRequestContext->getParams(), ['scope' => implode(' ', $this->scopes)]);
if ($this->cachedToken) {
if ($this->cachedToken->getExpires() && $this->cachedToken->hasExpired()) {
if ($this->cachedToken->getRefreshToken()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Microsoft\Kiota\Authentication\Oauth\OnBehalfOfContext;
use Microsoft\Kiota\Authentication\PhpLeagueAccessTokenProvider;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\RequestInterface;

class PhpLeagueAccessTokenProviderTest extends TestCase
{
Expand All @@ -33,6 +34,23 @@ public function testPassingEmptyScopesThrowsException(): void
$tokenProvider = new PhpLeagueAccessTokenProvider(new ClientCredentialContext('', '', ''), []);
}

public function testPassingMultipleScopes(): void
{
$tokenProvider = new PhpLeagueAccessTokenProvider(new ClientCredentialContext(
'tenantId', 'clientId', 'secret'
), ['User.Read', 'Calendar.ReadWrite']);
$mockResponses = [
function (RequestInterface $request) {
parse_str($request->getBody()->getContents(), $requestBodyMap);
$this->assertArrayHasKey('scope', $requestBodyMap);
$this->assertEquals('User.Read Calendar.ReadWrite', $requestBodyMap['scope']);
return new Response(200);
}
];
$tokenProvider->getOauthProvider()->setHttpClient($this->getMockHttpClient($mockResponses));
$tokenProvider->getAuthorizationTokenAsync('https://example.com');
}

public function testGetAuthorizationTokenWithSuccessfulTokenResponse(): void
{
$oauthContexts = $this->getOauthContexts();
Expand Down
1 change: 1 addition & 0 deletions http/php/guzzle/src/KiotaClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public static function createWithConfig(array $guzzleConfig): Client
public static function getDefaultHandlerStack(): HandlerStack
{
$handlerStack = new HandlerStack(Utils::chooseHandler());
$handlerStack->push(KiotaMiddleware::parameterNamesDecoding());
$handlerStack->push(KiotaMiddleware::retry());
$handlerStack->push(GuzzleMiddleware::redirect());
return $handlerStack;
Expand Down
15 changes: 15 additions & 0 deletions http/php/guzzle/src/Middleware/KiotaMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use Microsoft\Kiota\Http\Middleware\Options\ChaosOption;
use Microsoft\Kiota\Http\Middleware\Options\CompressionOption;
use Microsoft\Kiota\Http\Middleware\Options\ParametersDecodingOption;
use Microsoft\Kiota\Http\Middleware\Options\RetryOption;
use Microsoft\Kiota\Http\Middleware\Options\TelemetryOption;

Expand Down Expand Up @@ -78,4 +79,18 @@ public static function chaos(?ChaosOption $chaosOption = null): callable
return new ChaosHandler($handler, $chaosOption);
};
}

/**
* Middleware that decodes special characters in the request query parameter names that had to be encoded due to RFC 6570
* restrictions before executing the request. Configured by the $decodingOption
*
* @param ParametersDecodingOption|null $decodingOption
* @return callable
*/
public static function parameterNamesDecoding(?ParametersDecodingOption $decodingOption = null): callable
{
return static function (callable $handler) use ($decodingOption): ParametersNameDecodingHandler {
return new ParametersNameDecodingHandler($handler, $decodingOption);
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php
/**
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* Licensed under the MIT License. See License in the project root
* for license information.
*/


namespace Microsoft\Kiota\Http\Middleware\Options;

use Microsoft\Kiota\Abstractions\RequestOption;
use Microsoft\Kiota\Http\Middleware\ParametersNameDecodingHandler;

/**
* Class ParametersDecodingOption
*
* Config options for the {@link ParametersNameDecodingHandler}
*
* @package Microsoft\Kiota\Http\Middleware\Options
* @copyright 2022 Microsoft Corporation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://developer.microsoft.com/graph
*/
class ParametersDecodingOption implements RequestOption
{
/**
* @var bool Whether to decode characters in the request query parameter names
*/
private bool $enabled;
/**
* @var array|string[] list of characters to decode in the request query parameter names before executing request
*/
private array $parametersToDecode;

/**
* @param array|string[] $parametersToDecode {@link $parameterstoDecode}
* @param bool $enabled {@link $enabled}
*/
public function __construct(array $parametersToDecode = ['.', '-', '~', '$'], bool $enabled = true)
{
$this->parametersToDecode = $parametersToDecode;
$this->enabled = $enabled;
}

/**
* @return bool
*/
public function isEnabled(): bool
{
return $this->enabled;
}

/**
* @param bool $enabled
*/
public function setEnabled(bool $enabled): void
{
$this->enabled = $enabled;
}

/**
* @return array|string[]
*/
public function getParametersToDecode(): array
{
return $this->parametersToDecode;
}

/**
* @param array|string[] $parametersToDecode
*/
public function setParametersToDecode(array $parametersToDecode): void
{
$this->parametersToDecode = $parametersToDecode;
}
}
Loading

0 comments on commit 7ef92a5

Please sign in to comment.