diff --git a/CHANGELOG.md b/CHANGELOG.md index b50d2ec..132d2e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## [2.2.3] - 2026-06-08 +- Fixed [#64](https://github.com/zammad/zammad-api-client-php/issues/64) - Use `From` header instead of deprecated `X-On-Behalf-Of`. + ## [2.2.2] - 2026-04-27 - Fix PHP deprecation warnings. diff --git a/README.md b/README.md index ba300f1..b385b67 100644 --- a/README.md +++ b/README.md @@ -296,7 +296,7 @@ If you want Zammad to execute an API call on behalf of another user than the one ```php $client->setOnBehalfOfUser('myuser'); ``` -Any API call after above code will use this setting. If you want to return to using the user you used for authentication, call: +This sets the `From` HTTP header. Any API call after above code will use this setting. If you want to return to using the user you used for authentication, call: ```php $client->unsetOnBehalfOfUser(); ``` diff --git a/src/Client.php b/src/Client.php index 9361112..835195a 100644 --- a/src/Client.php +++ b/src/Client.php @@ -73,9 +73,9 @@ private function request ( $method, $url, array $url_parameters = [], array $opt $options['headers']['Accept'] = 'application/json'; $options['headers']['Content-Type'] = 'application/json; charset=utf-8'; - // Set "on behalf of user" header + // Set "on behalf of user" header (X-On-Behalf-Of was deprecated in Zammad 6.5 in favor of From) if ( !empty($this->on_behalf_of_user) ) { - $options['headers']['X-On-Behalf-Of'] = $this->on_behalf_of_user; + $options['headers']['From'] = $this->on_behalf_of_user; } $http_client_response = $this->http_client->request( $method, $url, $options ); diff --git a/test/ZammadAPIClient/ClientTest.php b/test/ZammadAPIClient/ClientTest.php index a38bba6..01db0cb 100644 --- a/test/ZammadAPIClient/ClientTest.php +++ b/test/ZammadAPIClient/ClientTest.php @@ -5,10 +5,15 @@ use PHPUnit\Framework\TestCase; use ZammadAPIClient\Client; +use ZammadAPIClient\EnvConfigTrait; +use ZammadAPIClient\HTTPClientInterface; use GuzzleHttp\Exception\ConnectException; +use Psr\Http\Message\ResponseInterface; class ClientTest extends TestCase { + use EnvConfigTrait; + public function testNetworkError() { // When providing a wrong URL, there must be a proper exception thrown. @@ -21,4 +26,80 @@ public function testNetworkError() ]); $client->get('/nonexisting'); } + + public function testSetsFromHeaderWhenOnBehalfOfUserIsSet() + { + $client = $this->createClientWithMockHttpClient(); + $client->setOnBehalfOfUser('testuser'); + $client->get('tickets'); + + $this->assertArrayHasKey('From', $this->capturedOptions['headers']); + $this->assertSame('testuser', $this->capturedOptions['headers']['From']); + } + + public function testDoesNotSetFromHeaderByDefault() + { + $client = $this->createClientWithMockHttpClient(); + $client->get('tickets'); + + $this->assertArrayNotHasKey('From', $this->capturedOptions['headers']); + } + + public function testRemovesFromHeaderAfterUnsetOnBehalfOfUser() + { + $client = $this->createClientWithMockHttpClient(); + $client->setOnBehalfOfUser('testuser'); + $client->unsetOnBehalfOfUser(); + $client->get('tickets'); + + $this->assertArrayNotHasKey('From', $this->capturedOptions['headers']); + } + + public function testFromHeaderAgainstZammad() + { + $client = self::createZammadClient(); + if (!$client) { + $this->markTestSkipped( + 'Zammad environment variables not set. ' + . 'Set ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_URL, ' + . 'ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_USERNAME, ' + . 'ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_PASSWORD.' + ); + } + + $client->setOnBehalfOfUser(getenv('ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_USERNAME')); + $response = $client->get('users'); + + $this->assertSame(200, $response->getStatusCode()); + $this->assertFalse($response->hasError()); + + $client->unsetOnBehalfOfUser(); + $response = $client->get('users'); + + $this->assertSame(200, $response->getStatusCode()); + $this->assertFalse($response->hasError()); + } + + private $capturedOptions = []; + + private function createClientWithMockHttpClient() + { + $this->capturedOptions = []; + + $mockResponse = $this->createMock(ResponseInterface::class); + + $mockHttpClient = $this->createMock(HTTPClientInterface::class); + $mockHttpClient + ->method('request') + ->will($this->returnCallback(function ($method, $uri, $options) use ($mockResponse) { + $this->capturedOptions = $options; + return $mockResponse; + })); + + return new Client([ + 'url' => 'https://example.com/', + 'username' => 'test', + 'password' => 'test', + ], $mockHttpClient); + } } diff --git a/test/ZammadAPIClient/EnvConfigTrait.php b/test/ZammadAPIClient/EnvConfigTrait.php new file mode 100644 index 0000000..08ea826 --- /dev/null +++ b/test/ZammadAPIClient/EnvConfigTrait.php @@ -0,0 +1,39 @@ + 'ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_URL', + 'username' => 'ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_USERNAME', + 'password' => 'ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_PASSWORD', + ]; + + foreach ($env_keys as $config_key => $env_key) { + $value = getenv($env_key); + if (empty($value)) { + throw new \RuntimeException("Missing environment variable $env_key"); + } + $config[$config_key] = $value; + } + + return $config; + } + + private static function createZammadClient(array $extra_config = []): ?Client + { + try { + $config = self::getZammadConfig($extra_config); + } + catch (\RuntimeException $e) { + return null; + } + + return new Client($config); + } +} diff --git a/test/ZammadAPIClient/Resource/AbstractBaseTest.php b/test/ZammadAPIClient/Resource/AbstractBaseTest.php index 7f1d554..7750b66 100644 --- a/test/ZammadAPIClient/Resource/AbstractBaseTest.php +++ b/test/ZammadAPIClient/Resource/AbstractBaseTest.php @@ -5,10 +5,13 @@ use PHPUnit\Framework\TestCase; use ZammadAPIClient\Client; +use ZammadAPIClient\EnvConfigTrait; use ZammadAPIClient\Exception\AlreadyFetchedObjectException; abstract class AbstractBaseTest extends TestCase { + use EnvConfigTrait; + private static $client; protected $resource_type; protected static $created_objects = []; @@ -17,25 +20,10 @@ abstract class AbstractBaseTest extends TestCase public static function setUpBeforeClass(): void { - $client_config = [ - # Set a high timeout for tests to work with slow CI. + $client_config = self::getZammadConfig([ 'timeout' => 30, - 'debug' => getenv('ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_DEBUG'), - ]; - - $env_keys = [ - 'url' => 'ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_URL', - 'username' => 'ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_USERNAME', - 'password' => 'ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_PASSWORD', - ]; - foreach ( $env_keys as $config_key => $env_key ) { - $value = getenv($env_key); - if ( empty($value) ) { - throw new \RuntimeException("Missing environment variable $env_key"); - } - - $client_config[$config_key] = $value; - } + 'debug' => getenv('ZAMMAD_PHP_API_CLIENT_UNIT_TESTS_DEBUG'), + ]); self::$client = new Client($client_config); }