# php-owsclient
Composer installable wrappers for owsclient for PHP

The clients in thus library are intended to be used by all PHP apps for interacting with OWS microservices.

## Requirements
* PHP 8.2+

## GrassClient
The GrassClient is intended to be used to make calls to microservices via ows-grass.  This replaces Common\Proxy class.

It's encouraged to create an extended class in your app for one specific microservice so that the ows-grass service name is set in one place. 

### Usage
Example for making a request to microservice via ows-grass:
```
use GuzzleHttp\Client as GuzzleClient;
use Orchard\OwsClient\Grass\Config as GrassConfig;
use Orchard\OwsClient\GrassClient;

class MyClient extends GrassClient
{
    /**
     * @param array  $grassConfig   Config read from grass.yml
     * @param array  $sessionData   OA/ALW session data
     * @param string $moduleName    OA or ALW
     * @param int    $oauthClientId VAPI Oauth config key
     */
    public function __construct(array $grassConfig, array $sessionData, $moduleName, $oauthClientId)
    {
        parent::__construct(
            new GuzzleClient(),
            new GrassConfig($grassConfig),
            '/my/service', // This is the service route ows-grass knows by.
            $sessionData,
            $moduleName,
            $oauthClientId
        );

        // In most cases, you may only need to have one URI.  This shows an example for multiple endpoints.
        $this->setUris(
            array(
                'endpoint1' => '/endpoint/one',
                'endpoint2' => '/endpoint/two',
                'endpoint3' => '/endpoint3',
            )
        );
    }
    
    /**
     * This function makes a call to /endpoint/one
     *
     * @return array
     */
    public function useEndpoint1()
    {
        // Note: you can also use the `makeRequest` function if you want to have a GuzzleHttp\Psr7\Response
        // object returned.  The `callGrass` function returns an associative array with status and message
        // keys.  e.g. array('status' => 200, 'message' => 'success')
        $response = $this->callGrass(
            'GET',
            $this->getServiceUri() . $this->getUris()['endpoint1'] . '/' . $param
        );
        
        return json_decode($response, true);
    }
    
    /**
     * This function makes a call to /endpoint3
     *
     * @return array
     */
    public function useEndpoint3()
    {
        $response = $this->makeRequest(
            'GET',
            $this->getServiceUri() . $this->getUris()['endpoint3']
        );
        
        // get HTTP status code
        $status = $response->getStatusCode();
        
        // Note: the `getBody` method returns a `StreamInferface` object.  You are required to call `getContents`
        // in order to get the real body of the message.
        $body = $reponse->getBody()->getConents();
        
        return json_decode($body, true);
    }
}
```

## ServiceClient
The ServiceClient is intended to be used to make direct calls to other microservices from a microservice or a service or a cron job, etc. that has no front-end user interaction.

This class utilizes [php-owsrequest](https://github.com/theorchard/php-owsrequest) library.  You can use this client directly w/o the need to extend it.

### Usage
Example for making a request to microservice directly:
```
use Orchard\OwsClient\ServiceClient;
use GuzzleHttp\Client as GuzzleClient;
use Orchard\OwsRequest\Cache\ApcuCache; // Or your own CacheInterface implementation
use Orchard\OwsRequest\SecretsManager;
use Orchard\OwsRequest\M2MTokenManager;

// Set up AWS config
$awsConfig = [
    'key'    => 'your-aws-access-key',
    'secret' => 'your-aws-secret-key',
    'region' => 'your-region'
];

// Set up cache
$cache = new ApcuCache();

// Set up m2mTokenManager
$secretsManagerClient = new SecretsManager($awsConfig['region'] ?? 'us-east-1');
$m2mTokenManager = new M2MTokenManager($secretsManagerClient, $environment, $sender, $cache, $logger);

$client = new ServiceClient(
    new GuzzleClient(),  // HTTP client
    'sender-service',    // Microservice name making the request
    'recipient-service', // Microservice name receiving the request
    $cache,              // Cache implementation
    $m2mTokenManager,    // Inject to enable dedicated M2M JWTs
    'qa',                // Environment (e.g. 'qa', 'prod')
    true,                // (Optional) Use HTTPS (true) or HTTP (false)
    $logger,             // (Optional) Logger
    false                // (Optional) Use legacy urls (eg: webservice)
);

// Make a request
$response = $client->makeRequest('GET', '/my/endpoint');
```

🔐 Dedicated M2M JWTs
Dedicated machine-to-machine (M2M) JWT authentication is supported via the M2MTokenManager.

✅ How It Works
If a M2MTokenManager instance is passed to the ServiceClient constructor:
    - The client will attempt to retrieve a dedicated JWT for secure, authenticated service-to-service communication.
    - The JWT will be added to the Authorization header of the outgoing request.

🔄 Precedence Order
Before falling back to the dedicated M2M JWT, the client will first check for existing tokens in the following order:
    - Frontend JWT from OA/WS session
    - JWT provided in the incoming request headers
    - (If both missing) → Fetch and use the dedicated M2M JWT

Note: M2MTokenManager is a required parameter, If you do not want to use dedicated M2M JWTs, you must explicitly pass null to m2mTokenManager constructor argument

🧠 Caching Support
The ServiceClient accepts any implementation of Orchard\OwsRequest\Cache\CacheInterface.

* Used to cache M2M JWTs(shared/dedicated), reducing redundant token fetches.
* Improves performance and reduces load on your Secrets Manager.

## Installation
```bash
composer require orchard/owsclient
```

## Setup
Ensure composer.phar is installed and available on your path.

```bash
git clone git@github.com:theorchard/php-owsclient.git php-owsclient
cd php-owsclient/
composer install
```

## Testing
Ensure ant is installed and available on your path.

```bash
cd build/
ant phpunit
```

or

```bash
cd tests/
../vendor/bin/phpunit tests/unit/
```

## Linting
Ensure ant is installed and available on your path.

```bash
cd build
ant phpcs
```

or

```bash
vendor/bin/phpcs -p --standard=PSR2 src/
vendor/bin/phpcs -p --standard=PSR2 tests/
```

## Releasing Versions

To release a new version of OwsClient library, create an atomic PR, consisting of one change to the composer.json file:

```json
"version": "NEW_VERSION_HERE"
```

Then, run a comparison between the last stable tag to master using this URL - `https://github.com/theorchard/php-owsclient/compare/{source_tag}...master`. All you need to change is the `{source_tag}`.

Please copy all commit messages from the comparison result and convert that into the release notes for the new version. Please use bullet points for each note.

Once you have the release notes, put them in the description field of the PR and send it for review. Upon approval and merge, create a new tag using Github.
