diff --git a/README.md b/README.md
index 49dcb6d..ea1b20e 100644
--- a/README.md
+++ b/README.md
@@ -1,204 +1,206 @@
-
-
# PHP Wrapper für PROFFIX REST-API
-Ein effizienter PHP Wrapper für die PROFFIX REST-API
+Ein effizienter PHP Wrapper für die PROFFIX REST-API.

-### Installation
-Der Wrapper kann entweder geklont oder via [Composer](https://getcomposer.org) installiert werden.
+## Installation
+
+Der Wrapper kann via [Composer](https://getcomposer.org) installiert werden.
```php
composer require pitwch/rest-api-wrapper-proffix-php
```
+## Konfiguration
-#### Variante 1: Verwendung mit Composer (empfohlen)
-
+### Initialisierung
-Autoload RestAPIWrapperProffix class:
+Autoload der `RestAPIWrapperProffix` Klasse:
```php
require __DIR__ . '/vendor/autoload.php';
use Pitwch\RestAPIWrapperProffix\Client;
-
```
-
-#### Konfiguration
-
Die Konfiguration wird dem Client mitgegeben:
| Konfiguration | Beispiel | Bemerkung |
|------------------|----------------------------------------------------------------------------------|--------------------------------------------------|
-| url | https://myserver.ch:999 | URL der REST-API **ohne pxapi/v2/** |
-| apiDatabase | DEMO | Name der Datenbank |
-| apiUser | USR | Names des Benutzers |
-| apiPassword | b62cce2fe18f7a156a9c...0f0d7bd18d9e8a40be2e663017 | SHA256-Hash des Benutzerpasswortes |
-| apiModule | ADR,STU | Benötigte Module (mit Komma getrennt) |
-| options | array('key'=>'112a5a90...59028') | Optionen (Details unter Optionen) |
+| url | `https://myserver.ch:999` | URL der REST-API **ohne pxapi/v2/** |
+| apiDatabase | `DEMO` | Name der Datenbank |
+| apiUser | `USR` | Name des Benutzers |
+| apiPassword | `b62cce2fe18f7a156a9c...` | SHA256-Hash des Benutzerpasswortes |
+| apiModule | `ADR,STU` | Benötigte Module (mit Komma getrennt) |
+| options | `array('key'=>'112a5a90...')` | Optionen (Details unter Optionen) |
+### Beispiel für die Initialisierung
-Beispiel:
```php
-
require __DIR__ . '/vendor/autoload.php';
use Pitwch\RestAPIWrapperProffix\Client;
-$pxrest = new Client(
+$pxrest = new Client(
'https://myserver.ch:999',
'DEMO',
'USR',
'b62cce2fe18f7a156a9c719c57bebf0478a3d50f0d7bd18d9e8a40be2e663017',
'ADR,STU',
- array('key'=>'112a5a90fe28b23ed2c776562a7d1043957b5b79fad242b10141254b4de59028','limit'=>2));
-$adressen = $pxrest->get('ADR/Adresse',array('filter'=>'GeaendertAm>d\'2018-05-17 14:54:56\'','depth'=>1,'fields'=>'AdressNr,Name,GeaendertAm'));;
+ ['key'=>'112a5a90fe28b23ed2c776562a7d1043957b5b79fad242b10141254b4de59028','limit'=>2]
+);
+
+$adressen = $pxrest->get('ADR/Adresse', ['filter'=>'GeaendertAm>d\'2018-05-17 14:54:56\'', 'depth'=>1, 'fields'=>'AdressNr,Name,GeaendertAm']);
print_r($adressen);
```
-### Optionen
+
+## Optionen
Optionen sind **fakultativ** und werden in der Regel nicht benötigt:
-| Option | Beispiel | Bemerkung |
-|------------------|------------------------------------------------------------------|----------------------------------------------------------------|
-| key | 112a5a90fe28b...242b10141254b4de59028 | API-Key als SHA256 - Hash (kann auch direkt mitgegeben werden) |
-| version | v2 | API-Version; Standard = v2 |
-| api_prefix | /pxapi/ | Prefix für die API; Standard = /pxapi/ |
-| login_endpoint | PRO/Login | Endpunkt für Login; Standard = PRO/Login |
-| user_agent | php-wrapper-proffix-restapi | User Agent; Standard = php-wrapper-proffix-restapi |
-| timeout | 15 | Timeout für Curl in Sekunden; Standard = 15 |
-| follow_redirects | true | Weiterleitungen der API folgen; Standard = false |
+| Option | Beispiel | Bemerkung |
+|------------------|----------------------------------------|----------------------------------------------------------------|
+| key | `112a5a90fe28b...` | API-Key als SHA256 - Hash (kann auch direkt mitgegeben werden) |
+| version | `v2` | API-Version; Standard = v2 |
+| api_prefix | `/pxapi/` | Prefix für die API; Standard = /pxapi/ |
+| login_endpoint | `PRO/Login` | Endpunkt für Login; Standard = PRO/Login |
+| user_agent | `php-wrapper-proffix-restapi` | User Agent; Standard = php-wrapper-proffix-restapi |
+| timeout | `15` | Timeout für Curl in Sekunden; Standard = 15 |
+| follow_redirects | `true` | Weiterleitungen der API folgen; Standard = false |
-#### Methoden
+## Methoden
+### Allgemeine Methoden (`get`, `put`, `post`, `delete`)
| Parameter | Typ | Bemerkung |
|------------|--------|----------------------------------------------------------------------------------------------------------|
-| endpoint | string | Endpunkt der PROFFIX REST-API; z.B. ADR/Adresse,STU/Rapporte... |
-| data | array | Daten (werden automatisch in JSON konvertiert); z.B: array("Name"=>"Demo AG",...) |
-| parameters | array | Parameter gemäss [PROFFIX REST API Docs](http://www.proffix.net/Portals/0/content/REST%20API/index.html) |
-
+| endpoint | `string` | Endpunkt der PROFFIX REST-API; z.B. `ADR/Adresse`, `STU/Rapporte`... |
+| data | `array` | Daten (werden automatisch in JSON konvertiert); z.B: `["Name"=>"Demo AG",...]` |
+| parameters | `array` | Parameter gemäss [PROFFIX REST API Docs](http://www.proffix.net/Portals/0/content/REST%20API/index.html) |
*Sonderzeichen in den Parametern müssen gegebenfalls mit Escape-Zeichen verwendet werden, z.B:*
```php
-//Escape ' with \'
-array('filter'=>'GeaendertAm>d\'2018-05-17 14:54:56\'','depth'=>1,'fields'=>'AdressNr,Name,GeaendertAm')
+// Escape ' with \'
+$params = ['filter' => 'GeaendertAm>d\'2018-05-17 14:54:56\'', 'depth' => 1, 'fields' => 'AdressNr,Name,GeaendertAm'];
+$pxrest->get('ADR/Adresse', $params);
```
+#### Get / Query
-Folgende unterschiedlichen Methoden sind mit dem Wrapper möglich:
-
+```php
+// Einfache Abfrage
+$adresse = $pxrest->get("ADR/Adresse/1");
+echo $adresse->Name; // DEMO AG
+// Abfrage mit Parametern
+$params = ['filter'=>'GeaendertAm>d\'2018-05-17 14:54:56\'','depth'=>1,'fields'=>'AdressNr,Name,GeaendertAm','limit'=>5];
+$adressen = $pxrest->get("ADR/Adresse", $params);
+```
-##### Get / Query
+#### Put / Update
```php
-//Einfache Abfrage
-$pxrest = new Client(...)
-$adresse = $pxrest->get("ADR/Adresse/1") //Legt Response als Objects in $adresse ab
-$adresse->Name //DEMO AG
-
-/Abfrage mit Parametern
-$pxrest = new Client(...)
-$adresse = $pxrest->get("ADR/Adresse",array('filter'=>'GeaendertAm>d\'2018-05-17 14:54:56\'','depth'=>1,'fields'=>'AdressNr,Name,GeaendertAm','limit'=>5))
-
+$data = ["AdressNr"=>1, "Ort"=>"Zürich", "PLZ"=>8000, "EMail"=>"test@test.com"];
+$adresse = $pxrest->put("ADR/Adresse", $data);
```
-
-##### Put / Update
+#### Post / Create
```php
-$pxrest = new Client(...)
-$data = array("AdressNr"=>1,"Ort"=>"Zürich","PLZ"=>8000,"EMail"=>"test@test.com");
-$adresse = $pxrest->put("ADR/Adresse",$data) //Sendet $data an Endpunkt ADR/Adresse
+$data = ["Ort"=>"Zürich", "PLZ"=>8000, "EMail"=>"test@test.com"];
+$neueAdresse = $pxrest->post("ADR/Adresse", $data);
```
-##### Post / Create
+#### Delete
```php
-$pxrest = new Client(...)
-$data = array("AdressNr"=>1,"Ort"=>"Zürich","PLZ"=>8000,"EMail"=>"test@test.com");
-$adresse = $pxrest->post("ADR/Adresse",$data) //Sendet $data an Endpunkt ADR/Adresse
+$response = $pxrest->delete("ADR/Adresse/42");
```
+### Spezifische Methoden
-##### Response / Antwort
+#### `getList(int $listenr, array $body = [])`
-Alle Methoden geben die Response als Array bzw. NULL (z.B. bei DELETE)
-Bei Fehlern wird `HttpClientException` mit Rückmeldung der PROFFIX REST-API ausgegeben.
+Generiert eine PROFFIX-Liste (z.B. ein PDF) und gibt das Ergebnis als `Response`-Objekt zurück, welches den rohen Dateiinhalt enthält.
-Zudem lassen sich Zusatzinformationen zur Response wie folgt ausgeben:
+| Parameter | Typ | Bemerkung |
+|-----------|----------|------------------------------------------------------------------------------------------------------------------------------------------------|
+| `$listenr`| `int` | Die `ListeNr` der Liste, die generiert werden soll. |
+| `$body` | `array` | (Optional) Ein assoziatives Array mit Parametern für die Listengenerierung. **Wichtig:** Es muss mindestens ein leeres JSON-Objekt (`{}`) gesendet werden. |
-```php
-$pxrest = new Client(...)
-$adresse = $pxrest->get("ADR/Adresse")
-
-//Zusatzinformationen zum letzten Request
-$lastRequest = $pxrest->http->getRequest();
-$lastRequest->getUrl(); // Get requested URL (string).
-$lastRequest->getMethod(); // Get request method (string).
-$lastRequest->getParameters(); // Get request parameters (array).
-$lastRequest->getHeaders(); // Get request headers (array).
-$lastRequest->getBody(); // Get request body (JSON).
+*Beispiel:*
+```php
+$listeNr = 1029; // Beispiel-ID für ADR_Adressliste.repx
+$pdfResponse = $pxrest->getList($listeNr);
-//Zusatzinformationen zur letzten Response
-$lastResponse = $pxrest->http->getResponse();
-$lastResponse->getCode(); // Response code (int).
-$lastResponse->getHeaders(); // Response headers (array).
-$lastResponse->getBody(); // Response body (JSON).
+if ($pdfResponse->getCode() === 200) {
+ file_put_contents('Adressliste.pdf', $pdfResponse->getBody());
+ echo "Liste erfolgreich als Adressliste.pdf gespeichert.";
+}
```
+## Spezielle Endpunkte
-#### Spezielle Endpunkte
-
+### Info
-##### Info
+Ruft Infos vom Endpunkt `PRO/Info` ab.
-Ruft Infos vom Endpunkt **PRO/Info** ab.
-
-*Hinweis: Dieser Endpunkt / Abfrage blockiert keine Lizenz*
+*Hinweis: Dieser Endpunkt / Abfrage blockiert keine Lizenz.*
```php
-$pxrest = new Client(...)
-
-//Variante 1: API - Key direkt mitgeben
+// Variante 1: API-Key direkt mitgeben
$info1 = $pxrest->info('112a5a90fe28b23ed2c776562a7d1043957b5b79fad242b10141254b4de59028');
-//Variante 2: API - Key aus Options verwenden (sofern dort hinterlegt)
+// Variante 2: API-Key aus Options verwenden (sofern dort hinterlegt)
$info2 = $pxrest->info();
```
-##### Datenbank
+### Datenbank
+
+Ruft Infos vom Endpunkt `PRO/Datenbank` ab.
+
+```php
+$dbInfo = $pxrest->database();
+```
+
+## Response / Antwort
-Ruft Infos vom Endpunkt **PRO/Datenbank** ab.
+Alle Methoden geben die Response als Array bzw. `NULL` (z.B. bei `DELETE`) zurück. Bei Fehlern wird eine `HttpClientException` mit der Rückmeldung der PROFFIX REST-API geworfen.
-*Hinweis: Dieser Endpunkt / Abfrage blockiert keine Lizenz*
+Zudem lassen sich Zusatzinformationen zur letzten Response wie folgt ausgeben:
+
+### Letzter Request
```php
-$pxrest = new Client(...);
+$lastRequest = $pxrest->http->getRequest();
+$lastRequest->getUrl(); // Get requested URL (string).
+$lastRequest->getMethod(); // Get request method (string).
+$lastRequest->getParameters(); // Get request parameters (array).
+$lastRequest->getHeaders(); // Get request headers (array).
+$lastRequest->getBody(); // Get request body (JSON).
+```
-//Variante 1: API - Key direkt mitgeben
-$datenbank1 = $pxrest->database('112a5a90fe28b23ed2c776562a7d1043957b5b79fad242b10141254b4de59028');
-
-//Variante 2: API - Key aus Options verwenden (sofern dort hinterlegt)
-$datenbank2 = $pxrest->database();
- ```
-### Ausnahmen / Spezialfälle
+### Letzte Response
+
+```php
+$lastResponse = $pxrest->http->getResponse();
+$lastResponse->getCode(); // Response code (int).
+$lastResponse->getHeaders(); // Response headers (array).
+$lastResponse->getBody(); // Response body (JSON).
+```
-* Endpunkte welche Leerschläge enthalten können (z.B. LAG/Artikel/PC 7/Bestand) müssen mit rawurlencode() genutzt werden
+## Ausnahmen / Spezialfälle
-### Weitere Beispiele
+* Endpunkte, welche Leerschläge enthalten (z.B. `LAG/Artikel/PC 7/Bestand`), müssen mit `rawurlencode()` genutzt werden.
-Im Ordner [/examples](https://github.com/pitwch/php-wrapper-proffix-restapi/tree/master/examples) finden sich weitere,
-auskommentierte Beispiele.
+## Weitere Beispiele
+Im Ordner [/examples](https://github.com/pitwch/php-wrapper-proffix-restapi/tree/master/examples) finden sich weitere auskommentierte Beispiele.
-# Weitere Wrapper für die Proffix Rest-API
+## Weitere Wrapper für die Proffix Rest-API
-- [Golang Wrapper für die Proffix Rest-API](https://github.com/pitwch/go-wrapper-proffix-restapi) :link:
-- [Dart Wrapper für die Proffix Rest-API](https://github.com/pitwch/dart_proffix_rest) :link:
+* [Golang Wrapper für die Proffix Rest-API](https://github.com/pitwch/go-wrapper-proffix-restapi)
+* [Dart Wrapper für die Proffix Rest-API](https://github.com/pitwch/dart_proffix_rest)
diff --git a/composer.json b/composer.json
index 8c2d931..becca14 100644
--- a/composer.json
+++ b/composer.json
@@ -2,7 +2,7 @@
"name": "pitwch/rest-api-wrapper-proffix-php",
"description": "PHP Wrapper for PROFFIX REST API",
"type": "library",
- "version": "1.9.1",
+ "version": "1.9.2",
"homepage": "https://www.pitw.ch",
"license": "MIT",
"authors": [
@@ -28,8 +28,7 @@
},
"autoload-dev": {
"psr-4": {
- "Pitwch\\RestAPIWrapperProffix\\Tests\\": "tests/RestAPIWrapperProffix/",
- "Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\": "tests/Integration/"
+ "Pitwch\\RestAPIWrapperProffix\\Tests\\": "tests/"
}
}
}
\ No newline at end of file
diff --git a/composer.lock b/composer.lock
index eb2eae2..14cc8fb 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "a81d58b9c9ecae9af9c8abe08be6630e",
+ "content-hash": "11e0273ccd566225b44b7b413183f8ae",
"packages": [],
"packages-dev": [
{
@@ -580,16 +580,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "11.5.23",
+ "version": "11.5.24",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "86ebcd8a3dbcd1857d88505109b2a2b376501cde"
+ "reference": "6b07ab1047155cf38f82dd691787a277782271dd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/86ebcd8a3dbcd1857d88505109b2a2b376501cde",
- "reference": "86ebcd8a3dbcd1857d88505109b2a2b376501cde",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6b07ab1047155cf38f82dd691787a277782271dd",
+ "reference": "6b07ab1047155cf38f82dd691787a277782271dd",
"shasum": ""
},
"require": {
@@ -603,7 +603,7 @@
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
"php": ">=8.2",
- "phpunit/php-code-coverage": "^11.0.9",
+ "phpunit/php-code-coverage": "^11.0.10",
"phpunit/php-file-iterator": "^5.1.0",
"phpunit/php-invoker": "^5.0.1",
"phpunit/php-text-template": "^4.0.1",
@@ -661,7 +661,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.23"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.24"
},
"funding": [
{
@@ -685,7 +685,7 @@
"type": "tidelift"
}
],
- "time": "2025-06-13T05:47:49+00:00"
+ "time": "2025-06-20T11:31:02+00:00"
},
{
"name": "sebastian/cli-parser",
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..811a987
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ ./tests/Integration
+
+
+
+
+
+
+
+
+
+
diff --git a/src/RestAPIWrapperProffix/Client.php b/src/RestAPIWrapperProffix/Client.php
index b057190..ff715aa 100644
--- a/src/RestAPIWrapperProffix/Client.php
+++ b/src/RestAPIWrapperProffix/Client.php
@@ -64,9 +64,12 @@ public function database($px_api_key = '')
*/
public function getList(int $listenr, array $body = []): \Pitwch\RestAPIWrapperProffix\HttpClient\Response
{
+ // Per API documentation, a POST to /generieren requires a body, even if empty.
+ // It must be an empty JSON object `{}`.
+ $requestBody = empty($body) ? (object)[] : $body;
+
// First, send a POST request to generate the list file.
- // The `post` method automatically handles JSON decoding and error checking.
- $this->post('PRO/Liste/' . $listenr . '/generieren', $body);
+ $this->post('PRO/Liste/' . $listenr . '/generieren', $requestBody);
// After a successful request, the HttpClient holds the last response.
$postResponse = $this->getHttpClient()->getResponse();
diff --git a/src/RestAPIWrapperProffix/HttpClient/HttpClient.php b/src/RestAPIWrapperProffix/HttpClient/HttpClient.php
index 9bb6855..9a9e50f 100644
--- a/src/RestAPIWrapperProffix/HttpClient/HttpClient.php
+++ b/src/RestAPIWrapperProffix/HttpClient/HttpClient.php
@@ -2,15 +2,11 @@
namespace Pitwch\RestAPIWrapperProffix\HttpClient;
-
-use Pitwch\RestAPIWrapperProffix\Client;
use Pitwch\RestAPIWrapperProffix\HttpClient\HttpClientException;
use Pitwch\RestAPIWrapperProffix\HttpClient\Options;
use Pitwch\RestAPIWrapperProffix\HttpClient\Request;
use Pitwch\RestAPIWrapperProffix\HttpClient\Response;
-
-
/**
* Class HttpClient
*
@@ -18,660 +14,326 @@
*/
class HttpClient
{
- /**
- * @var string The Proffix API URL
- */
protected $url;
-
- /**
- * @var string The Proffix API Database
- */
protected $apiDatabase;
-
- /**
- * @var array The Proffix API Modules
- */
protected $apiModules;
-
- /**
- * @var string The Proffix API User
- */
protected $apiUser;
-
- /**
- * @var string The Proffix API Password
- */
protected $apiPassword;
-
- /**
- * @var Options The options for the client
- */
protected $options;
-
- /**
- * @var Request The request object
- */
public $request;
-
- /**
- * @var Response The response object
- */
public $response;
-
- /**
- * @var string The Proffix Session ID
- */
protected $pxSessionId;
-
- /**
- * @var resource|\CurlHandle The cURL handle
- */
private $ch;
-
- /**
- * @var array The response headers
- */
private $responseHeaders = [];
- /**
- * HttpClient constructor.
- * @param $url
- * @param $apiDatabase
- * @param $apiUser
- * @param $apiPassword
- * @param $apiModules
- * @param $options
- * @throws HttpClientException
- */
- /**
- * HttpClient constructor.
- *
- * @param string $url The Proffix API URL
- * @param string $apiDatabase The Proffix Database
- * @param string $apiUser The Proffix User
- * @param string $apiPassword The Proffix Password
- * @param array $apiModules The required Proffix Modules
- * @param array $options Additional options
- *
- * @throws HttpClientException
- */
- public function __construct($url, $apiDatabase, $apiUser, $apiPassword, $apiModules, $options)
+ public function __construct($url, $apiDatabase, $apiUser, $apiPassword, $apiModules, $options = [])
{
- if (!\function_exists('curl_version')) {
+ if (!function_exists('curl_version')) {
throw new HttpClientException('cURL is not installed on this server', -1, new Request(), new Response());
}
+ if (!is_array($options)) {
+ $options = [];
+ }
+
$this->options = new Options($options);
$this->url = $this->buildApiUrl($url);
$this->apiUser = $apiUser;
$this->apiPassword = $apiPassword;
$this->apiDatabase = $apiDatabase;
$this->apiModules = $apiModules;
-
}
-
- /**
- * Check if the connection is SSL
- *
- * @return bool
- */
- protected function isSsl()
- {
- return 'https://' === \substr($this->url, 0, 8);
- }
-
-
- /**
- * Build the API URL
- *
- * @param string $url
- *
- * @return string
- */
protected function buildApiUrl($url)
{
-
- return \rtrim($url, '/') . $this->options->apiPrefix() . $this->options->getVersion() . '/';
+ return rtrim($url, '/') . $this->options->apiPrefix() . $this->options->getVersion() . '/';
}
-
- /**
- * Build the URL with query parameters
- *
- * @param string $url
- * @param array $parameters
- *
- * @return string
- */
protected function buildUrlQuery($url, $parameters = [])
{
- //Create empty query
- $query = array();
-
if (!empty($parameters)) {
-
- //Check if we need to send ?key Param
- if(array_key_exists('key',$parameters)){
-
- //Check if Param Key is empty -> use from Options
- if(empty($parameters['key'])){
- $parameters['key'] = $this->options->getApiKey();
-
- }
+ if (array_key_exists('key', $parameters) && empty($parameters['key'])) {
+ $parameters['key'] = $this->options->getApiKey();
}
-
- $url .= '?'. \http_build_query($parameters);
-
+ $url .= '?' . http_build_query($parameters);
}
-
return $url;
}
- /**
- * Build the JSON for the login request
- *
- * @return array
- */
- protected function buildLoginJson()
+ protected function login()
{
- $loginJson = [
+ $loginCredentials = [
'Benutzer' => $this->apiUser,
'Passwort' => $this->apiPassword,
'Datenbank' => ['Name' => $this->apiDatabase],
'Module' => is_array($this->apiModules) ? $this->apiModules : explode(',', $this->apiModules)
];
- return $loginJson;
- }
-
- /**
- * Build the login URL
- *
- * @return string
- */
- protected function buildLoginUrl()
- {
-
- return \rtrim($this->url, '/') . '/' . $this->options->getLoginEndpoint();
- }
+ $loginUrl = rtrim($this->url, '/') . '/' . $this->options->getLoginEndpoint();
+ $body = json_encode($loginCredentials);
- /**
- * Login to Proffix
- *
- * @return string The PxSessionId
- *
- * @throws HttpClientException
- */
- protected function login()
- {
- // IMPORTANT: login() now uses the cURL handle initialized by request().
- // It will temporarily set its own options on this handle.
- // Login has specific cURL needs, especially CURLOPT_HEADER = true.
-
- $body = \json_encode($this->buildLoginJson());
- $loginHeaders = [
+ curl_setopt($this->ch, CURLOPT_URL, $loginUrl);
+ curl_setopt($this->ch, CURLOPT_POST, true);
+ curl_setopt($this->ch, CURLOPT_POSTFIELDS, $body);
+ curl_setopt($this->ch, CURLOPT_HEADER, true);
+ curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($this->ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
- 'Content-Length: ' . strlen($body),
- 'Accept: application/json' // Good practice to include Accept for login too
- ];
-
- \curl_setopt($this->ch, CURLOPT_URL, $this->buildLoginUrl());
- \curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'POST');
- \curl_setopt($this->ch, CURLOPT_HTTPHEADER, $loginHeaders);
- \curl_setopt($this->ch, CURLOPT_POSTFIELDS, $body);
- \curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); // Make sure login also returns response
- \curl_setopt($this->ch, CURLOPT_HEADER, true); // Crucial for extracting PxSessionId from login response headers
+ 'Accept: application/json',
+ 'Content-Length: ' . strlen($body)
+ ]);
$response = curl_exec($this->ch);
+ $headerSize = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE);
+ $httpCode = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
+ $header = substr($response, 0, $headerSize);
if (curl_errno($this->ch)) {
- throw new HttpClientException('cURL error: ' . curl_error($this->ch), curl_errno($this->ch), $this->request, $this->response);
+ throw new HttpClientException('cURL error during login: ' . curl_error($this->ch), curl_errno($this->ch), $this->request, null);
}
- $headerSize = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE);
- $header = substr($response, 0, $headerSize);
-
$this->pxSessionId = $this->extractSessionId($header);
-
+
if (empty($this->pxSessionId)) {
$responseBody = substr($response, $headerSize);
$parsedBody = json_decode($responseBody);
- $errorMessage = 'Failed to retrieve PxSessionId from login response.';
- if (isset($parsedBody->Message)) {
- $errorMessage .= ' Proffix API Error: ' . $parsedBody->Message;
- }
- throw new HttpClientException($errorMessage, 401, $this->request, $this->response);
+ $errorMessage = $parsedBody->Message ?? 'Login failed: PxSessionId not found in response headers.';
+ throw new HttpClientException($errorMessage, $httpCode, $this->request, null);
}
-
- return $this->pxSessionId;
}
- /**
- * Logout from Proffix
- *
- * @return bool
- *
- * @throws HttpClientException
- */
protected function logout()
{
if (empty($this->pxSessionId)) {
- return true;
+ return;
}
- $this->initCurl();
-
- $headers = [
- 'PxSessionId: ' . $this->pxSessionId
- ];
-
- curl_setopt($this->ch, CURLOPT_URL, $this->buildLoginUrl());
- curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
- curl_setopt($this->ch, CURLOPT_HTTPHEADER, $headers);
+ $ch = curl_init();
+ $logoutUrl = rtrim($this->url, '/') . '/' . $this->options->getLoginEndpoint();
+ $headers = $this->getRequestHeaders(false);
+ $rawHeaders = [];
+ foreach ($headers as $key => $value) {
+ $rawHeaders[] = $key . ': ' . $value;
+ }
- curl_exec($this->ch);
+ curl_setopt($ch, CURLOPT_URL, $logoutUrl);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $rawHeaders);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 5); // Use a short timeout
- if (curl_errno($this->ch)) {
- throw new HttpClientException('cURL error on logout: ' . curl_error($this->ch), curl_errno($this->ch), $this->request, $this->response);
- }
+ curl_exec($ch);
+ curl_close($ch);
$this->pxSessionId = null;
- return true;
}
- /**
- * Set the HTTP method for the cURL request
- *
- * @param string $method
- */
- protected function setupMethod($method)
- {
- // Reset method-specific options first to ensure a clean state
- \curl_setopt($this->ch, CURLOPT_HTTPGET, false);
- \curl_setopt($this->ch, CURLOPT_POST, false);
- \curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, null); // Reset custom request
-
- if ('GET' == $method) {
- \curl_setopt($this->ch, CURLOPT_HTTPGET, true);
- } elseif ('POST' == $method) {
- \curl_setopt($this->ch, CURLOPT_POST, true);
- } elseif (\in_array($method, ['PUT', 'DELETE', 'OPTIONS'])) {
- \curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $method);
- }
- // For POST, PUT, DELETE with body, CURLOPT_POSTFIELDS will be set later in request()
- }
- /**
- * Get the request headers
- *
- * @param bool $sendData
- *
- * @return array
- *
- * @throws HttpClientException
- */
- protected function getRequestHeaders($sendData = false)
+
+ protected function getRequestHeaders($sendData = false, $body = '')
{
$headers = [
'Accept' => 'application/json',
- 'User-Agent' => $this->options->userAgent() . '/' . Options::VERSION,
+ 'User-Agent' => $this->options->userAgent() . '/' . Options::VERSION,
];
-
if (!empty($this->pxSessionId)) {
$headers['PxSessionId'] = $this->pxSessionId;
}
-
if ($sendData) {
$headers['Content-Type'] = 'application/json;charset=utf-8';
+ $headers['Content-Length'] = strlen($body);
}
-
return $headers;
}
- /**
- * Create the request object
- *
- * @param string $endpoint
- * @param string $method
- * @param array $data
- * @param array $parameters
- *
- * @return Request
- *
- * @throws HttpClientException
- */
protected function createRequest($endpoint, $method, $data = [], $parameters = [])
{
- $body = '';
$url = $this->url . $endpoint;
- $hasData = !empty($data);
-
- if ($hasData) {
- $body = \json_encode($data);
- }
-
+ $body = json_encode($data);
$this->request = new Request(
$this->buildUrlQuery($url, $parameters),
$method,
$parameters,
- $this->getRequestHeaders($hasData),
+ $this->getRequestHeaders(!empty($data), $body),
$body
);
-
- return $this->request;
}
- /**
- * Get the response headers
- *
- * @return array
- */
protected function getResponseHeaders()
{
$headers = [];
- $lines = explode("\n", (string)$this->responseHeaders);
- $lines = \array_filter($lines, 'trim');
-
- foreach ($lines as $index => $line) {
- // Remove HTTP/xxx params.
- if (strpos($line, ': ') === false) {
- continue;
+ $lines = explode("\n", trim((string)$this->responseHeaders));
+ foreach ($lines as $line) {
+ if (strpos($line, ': ') !== false) {
+ list($key, $value) = explode(': ', $line, 2);
+ $headers[trim($key)] = trim($value);
}
-
- list($key, $value) = \explode(': ', $line);
-
- $headers[$key] = isset($headers[$key]) ? $headers[$key] . ', ' . trim($value) : trim($value);
}
-
return $headers;
}
- /**
- * Create the response object
- *
- * @return Response
- *
- * @throws HttpClientException
- */
protected function createResponse()
{
$this->response = new Response();
}
- /**
- * Set the default cURL settings
- */
protected function setDefaultCurlSettings()
{
$verifySsl = $this->options->verifySsl();
- $timeout = $this->options->getTimeout();
- $followRedirects = $this->options->getFollowRedirects();
-
- \curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, $verifySsl);
+ curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, $verifySsl);
if (!$verifySsl) {
- \curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, $verifySsl);
- }
- if ($followRedirects) {
- \curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, $verifySsl);
}
- \curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, $timeout);
- \curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout);
- \curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
- \curl_setopt($this->ch, CURLOPT_HEADER, false); // Default for API calls: no headers in body
- // Note: CURLOPT_HTTPHEADER is NOT set here anymore. It's set in request() method.
- \curl_setopt($this->ch, CURLOPT_URL, $this->request->getUrl());
+ curl_setopt($this->ch, CURLOPT_TIMEOUT, $this->options->getTimeout());
+ curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($this->ch, CURLOPT_HEADER, false);
+ curl_setopt($this->ch, CURLOPT_URL, $this->request->getUrl());
}
- /**
- * Check for errors in the response
- *
- * @param mixed $parsedResponse
- *
- * @throws HttpClientException
- */
protected function lookForErrors($parsedResponse)
{
- // Any non-200/201/202/204 response code indicates an error.
- if (!in_array($this->response->getCode(), ['200', '201', '202', '204'])) {
+ if (!in_array($this->response->getCode(), [200, 201, 202, 204])) {
$errorMessage = 'An unknown error occurred';
-
if (isset($parsedResponse->Message)) {
$errorMessage = $parsedResponse->Message;
- } elseif (is_string($parsedResponse)) {
- $errorMessage = $parsedResponse;
}
-
- if (isset($parsedResponse->Fields) && is_array($parsedResponse->Fields)) {
- $fieldErrors = [];
- foreach ($parsedResponse->Fields as $field) {
- $fieldErrors[] = sprintf(
- 'Field: %s (%s) - %s',
- $field->Name ?? 'N/A',
- $field->Reason ?? 'N/A',
- $field->Message ?? 'N/A'
- );
- }
- if (!empty($fieldErrors)) {
- $errorMessage .= ': ' . implode('; ', $fieldErrors);
- }
- }
-
- throw new HttpClientException(
- sprintf('Error: %s', $errorMessage),
- $this->response->getCode(),
- $this->request,
- $this->response
- );
- }
- }
- /**
- * @param $errors
- * @return array
- */
- protected function parsePxErrorMessage($errors)
- {
- foreach ($errors as $error){
- $clean[] = $error;
+ throw new HttpClientException($errorMessage, $this->response->getCode(), $this->request, $this->response);
}
}
- /**
- * Process the response
- *
- * @return mixed
- *
- * @throws HttpClientException
- */
+
protected function processResponse()
{
$body = $this->response->getBody();
-
- $parsedResponse = \json_decode($body);
-
- // Test if return a valid JSON.
- if (JSON_ERROR_NONE !== json_last_error() && ($this->response->getCode() != 201 && $this->response->getCode() != 204)) {
- $message = function_exists('json_last_error_msg') ? json_last_error_msg() : 'Invalid JSON returned';
- throw new HttpClientException($message, $this->response->getCode(), $this->request, $this->response);
+ $parsedResponse = json_decode($body);
+ if (json_last_error() !== JSON_ERROR_NONE && !in_array($this->response->getCode(), [201, 204])) {
+ throw new HttpClientException(json_last_error_msg(), $this->response->getCode(), $this->request, $this->response);
}
-
$this->lookForErrors($parsedResponse);
-
return $parsedResponse;
}
-
-
public function request($endpoint, $method, $data = [], $parameters = [], $login = true)
{
$this->prepareRequest($endpoint, $method, $data, $parameters, $login);
return $this->executeCurl(true);
}
- /**
- * @param $endpoint
- * @param $method
- * @param array $data
- * @param array $parameters
- * @return Response
- * @throws HttpClientException
- */
public function rawRequest($endpoint, $method, $data = [], $parameters = []): Response
{
- $this->prepareRequest($endpoint, $method, $data, $parameters, true); // Login is always required for raw requests
+ $this->prepareRequest($endpoint, $method, $data, $parameters, true);
return $this->executeCurl(false);
}
- /**
- * @param $endpoint
- * @param $method
- * @param $data
- * @param $parameters
- * @param $login
- * @throws HttpClientException
- */
private function prepareRequest($endpoint, $method, $data, $parameters, $login)
{
$this->initCurl();
+ $body = json_encode($data);
+ $hasData = ($body !== '[]' && $body !== '{}') || !in_array($method, ['GET', 'DELETE']);
- // Create the request object for the main operation.
$this->createRequest($endpoint, $method, $data, $parameters);
- // If login is required, it's performed first.
if ($login && empty($this->pxSessionId)) {
$this->login();
}
- // Apply default cURL settings for the MAIN request.
+ // Always set the default settings for the actual request, AFTER a potential login
$this->setDefaultCurlSettings();
- // Get the final headers for this specific request (which will include PxSessionId if login occurred)
- $finalRequestHeaders = $this->getRequestHeaders(!empty($data));
- $rawFinalRequestHeaders = [];
- foreach ($finalRequestHeaders as $key => $value) {
- $rawFinalRequestHeaders[] = $key . ': ' . $value;
+ // Reset all relevant cURL options to a clean state before every request
+ curl_setopt($this->ch, CURLOPT_HTTPGET, false);
+ curl_setopt($this->ch, CURLOPT_POST, false);
+ curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, null);
+ curl_setopt($this->ch, CURLOPT_POSTFIELDS, null);
+
+ // Explicitly configure the handle for the current request
+ switch ($method) {
+ case 'POST':
+ curl_setopt($this->ch, CURLOPT_POST, true);
+ curl_setopt($this->ch, CURLOPT_POSTFIELDS, $body);
+ break;
+ case 'GET':
+ curl_setopt($this->ch, CURLOPT_HTTPGET, true);
+ break;
+ case 'PUT':
+ curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'PUT');
+ curl_setopt($this->ch, CURLOPT_POSTFIELDS, $body);
+ break;
+ case 'DELETE':
+ curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
+ break;
+ default:
+ curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $method);
+ break;
}
- \curl_setopt($this->ch, CURLOPT_HTTPHEADER, $rawFinalRequestHeaders);
- // Setup method.
- $this->setupMethod($method);
-
- // Include post fields.
- if (!empty($data)) {
- $body = \json_encode($data);
- \curl_setopt($this->ch, CURLOPT_POSTFIELDS, $body);
+ $rawHeaders = [];
+ foreach ($this->getRequestHeaders($hasData, $body) as $key => $value) {
+ $rawHeaders[] = $key . ': ' . $value;
}
-
- $this->createResponse();
+ curl_setopt($this->ch, CURLOPT_HTTPHEADER, $rawHeaders);
}
- /**
- * @param bool $processJson
- * @return mixed|Response
- * @throws HttpClientException
- */
private function executeCurl(bool $processJson = true)
{
- // Set response headers callback
$this->responseHeaders = '';
- \curl_setopt($this->ch, CURLOPT_HEADERFUNCTION, function ($curl, $header) {
+ curl_setopt($this->ch, CURLOPT_HEADERFUNCTION, function ($curl, $header) {
$this->responseHeaders .= $header;
return strlen($header);
});
+ $this->createResponse();
$body = curl_exec($this->ch);
if (curl_errno($this->ch)) {
- throw new HttpClientException('cURL error: ' . curl_error($this->ch), curl_errno($this->ch), $this->request, $this->response);
+ $error_msg = curl_error($this->ch);
+ $error_no = curl_errno($this->ch);
+ curl_close($this->ch);
+ $this->ch = null;
+ throw new HttpClientException('cURL error: ' . $error_msg, $error_no, $this->request, $this->response);
}
$this->response->setBody($body);
$this->response->setCode(curl_getinfo($this->ch, CURLINFO_HTTP_CODE));
$this->response->setHeaders($this->getResponseHeaders());
+ curl_close($this->ch);
+ $this->ch = null;
+
if ($processJson) {
- // processResponse will decode and also call lookForErrors
return $this->processResponse();
}
- // For raw requests, we only check for non-2xx status codes.
- if (!in_array($this->response->getCode(), ['200', '201', '202', '204'])) {
- // Try to parse the body as JSON to get a detailed error message
- $parsedError = \json_decode($this->response->getBody());
- if (JSON_ERROR_NONE === json_last_error()) {
- // It's a JSON error response, pass it to lookForErrors
- $this->lookForErrors($parsedError);
- } else {
- // Not a JSON error, create a generic exception
- throw new HttpClientException(
- 'HTTP Error ' . $this->response->getCode(),
- $this->response->getCode(),
- $this->request,
- $this->response
- );
- }
- }
-
+ $this->lookForErrors(null);
return $this->response;
}
- /**
- * Get the request object
- *
- * @return Request
- */
- public function getRequest()
- {
- return $this->request;
- }
+ public function getRequest() { return $this->request; }
+ public function getResponse() { return $this->response; }
- /**
- * Get the response object
- *
- * @return Response
- */
- public function getResponse()
- {
- return $this->response;
- }
-
- /**
- * Initialize the cURL handle
- */
private function initCurl()
{
- if (!$this->ch) {
- $this->ch = curl_init();
- }
+ // Always create a new cURL handle to ensure a stateless request
+ $this->ch = curl_init();
}
- /**
- * Extract the session ID from the response headers
- *
- * @param string $header
- *
- * @return string|null
- */
- private function extractSessionId($header)
+ private function extractSessionId($headerBlock)
{
- foreach (explode("\r\n", $header) as $line) {
- if (strpos($line, 'PxSessionId:') === 0) {
- return trim(substr($line, strlen('PxSessionId:')));
+ $lines = explode("\n", $headerBlock);
+ foreach ($lines as $line) {
+ if (stripos($line, 'PxSessionId:') === 0) {
+ list(, $value) = explode(':', $line, 2);
+ return trim($value);
}
}
-
return null;
}
- /**
- * Destructor
- */
public function __destruct()
{
- if ($this->ch) {
- if(!empty($this->pxSessionId)){
- $this->logout();
- }
- curl_close($this->ch);
+ // Attempt to log out if a session was active.
+ // The logout method is now self-contained and will handle its own cURL session.
+ if (!empty($this->pxSessionId)) {
+ $this->logout();
}
}
}
diff --git a/tests/.phpunit.result.cache b/tests/.phpunit.result.cache
deleted file mode 100644
index 7306b06..0000000
--- a/tests/.phpunit.result.cache
+++ /dev/null
@@ -1 +0,0 @@
-{"version":1,"defects":{"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testCanGetAddressList":8,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testCanGetArticleStock":7,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testCanCreateAddress":8,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testCanUpdateNewlyCreatedAddress":8,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testCanGetCountryDetailsCH":8,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testCanDeleteAddress":8},"times":{"Pitwch\\RestAPIWrapperProffix\\Tests\\HttpClientTest::testHttpClientCanBeInstantiated":0.003,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testClientCanBeInstantiated":0,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testCanGetAddressList":0.011,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testCanGetArticleStock":2.475,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\MinimalIntegrationTest::testMinimalAssertion":0.001,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\AppleTest::testRedDelicious":0.003,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testCanGetCountryDetailsCH":0.001,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testCanCreateAddress":0.001,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testCanUpdateNewlyCreatedAddress":0.001,"Pitwch\\RestAPIWrapperProffix\\Tests\\Integration\\ClientIntegrationTest::testCanDeleteAddress":0.001}}
\ No newline at end of file
diff --git a/tests/Integration/ClientIntegrationTest.php b/tests/Integration/ClientIntegrationTest.php
index fc7eab2..13f7d25 100644
--- a/tests/Integration/ClientIntegrationTest.php
+++ b/tests/Integration/ClientIntegrationTest.php
@@ -19,12 +19,14 @@ protected function setUp(): void
$this->client = new Client(
$_ENV['PROFFIX_API_URL'],
$_ENV['PROFFIX_API_DATABASE'],
- $_ENV['PROFFIX_API_USER'],
+ $_ENV['PROFFIX_API_USERNAME'],
$_ENV['PROFFIX_API_PASSWORD'],
- $_ENV['PROFFIX_API_MODULES']
+ $_ENV['PROFFIX_API_MODULES'],
+ []
);
}
+
public function testCanGetAddressList(): void
{
$addresses = $this->client->get('ADR/Adresse');
@@ -158,8 +160,22 @@ public function testCanDeleteAddress(): void
public function testCanGetList(): void
{
+ // 1. Find the list number dynamically
+ $listName = 'ADR_Adressliste.repx';
+ $listInfo = $this->client->get('PRO/Liste', [
+ 'Filter' => "Name=='{$listName}'",
+ 'limit' => 1,
+ 'fields' => 'ListeNr'
+ ]);
+
+ if (empty($listInfo) || !isset($listInfo[0]->ListeNr)) {
+ $this->markTestSkipped("List '{$listName}' not found. Skipping getList test.");
+ }
+ $listeNr = $listInfo[0]->ListeNr;
+
try {
- $response = $this->client->getList(1029); // Using a known list ID from Go tests
+ // 2. Get the list using the found ID
+ $response = $this->client->getList($listeNr);
$this->assertEquals(200, $response->getCode());
$this->assertNotEmpty($response->getBody());
@@ -171,7 +187,7 @@ public function testCanGetList(): void
// The list might not exist in all test environments. If so, skip the test.
// A 404 on the final GET will be caught here.
if ($e->getCode() === 404) {
- $this->markTestSkipped('List with ID 1029 not found or failed to generate. Skipping getList test.');
+ $this->markTestSkipped("List with ID {$listeNr} not found or failed to generate. Skipping getList test.");
} else {
// Re-throw other exceptions
throw $e;
diff --git a/tests/RestAPIWrapperProffix/HttpClientTest.php b/tests/RestAPIWrapperProffix/HttpClientTest.php
deleted file mode 100644
index d66faaa..0000000
--- a/tests/RestAPIWrapperProffix/HttpClientTest.php
+++ /dev/null
@@ -1,44 +0,0 @@
-defaultOptions = [
- 'url' => 'http://fake-api.proffix.com',
- 'apiDatabase' => 'FAKEDB',
- 'apiUser' => 'testuser',
- 'apiPassword' => 'password',
- 'apiModules' => ['CRM', 'ADR'],
- 'options' => [] // Default HttpClient Options
- ];
-
- $this->httpClient = new HttpClient(
- $this->defaultOptions['url'],
- $this->defaultOptions['apiDatabase'],
- $this->defaultOptions['apiUser'],
- $this->defaultOptions['apiPassword'],
- $this->defaultOptions['apiModules'],
- $this->defaultOptions['options']
- );
- }
-
- public function testHttpClientCanBeInstantiated(): void
- {
- $this->assertInstanceOf(HttpClient::class, $this->httpClient);
- }
-
- // More tests will be added here, e.g., for login, request methods, error handling.
- // These will likely require mocking cURL functions or HTTP responses.
-
-}
diff --git a/tests/phpunit.xml b/tests/phpunit.xml
deleted file mode 100644
index b07d758..0000000
--- a/tests/phpunit.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ./Integration
-
-
-
-