<commit_before><?php

namespace Serwisant\SerwisantApi;

use GuzzleHttp;

class AccessTokenOauth implements AccessToken
{
  protected $client_id;
  protected $client_secret;
  protected $scope;
  protected $container;

  private $ip;
  private $lang;

  protected $access_token;

  public function __construct(string $client_id, string $client_secret, string $scope = '', AccessTokenContainer $container = null)
  {
    $this->client_id = $client_id;
    $this->client_secret = $client_secret;
    $this->scope = $scope;
    $this->container = $container;
  }

  public function setIp($ip)
  {
    $this->ip = $ip;
    return $this;
  }

  public function setLang($lang)
  {
    $this->lang = $lang;
    return $this;
  }

  public function get()
  {
    if ($this->access_token === null) {
      $this->fetch();
    }
    return $this->access_token;
  }

  public function refresh()
  {
    $params = [
      'grant_type' => 'client_credentials',
      'client_id' => $this->client_id,
      'client_secret' => $this->client_secret,
      'scope' => $this->scope
    ];

    $token_data = $this->http($params);

    if ($token_data !== null) {
      $this->access_token = $token_data['access_token'];

      if ($this->container !== null) {
        $this->container->store($token_data['access_token'], $token_data['expiry'], $token_data['refresh_token']);
      }
    }
  }

  public function revoke($access_token = null): bool
  {
    $params = [
      'client_id' => $this->client_id,
      'client_secret' => $this->client_secret,
      'token' => $access_token
    ];

    try {
      $client = new GuzzleHttp\Client();
      $client->request('POST', $this->revokeUrl(), $this->clientOptions($this->revokeUrl(), $params));
      return true;
    } catch (GuzzleHttp\Exception\ClientException $ex) {
      return false;
    }
  }

  protected function fetch()
  {
    if ($this->container instanceof AccessTokenContainer && $this->container->getExpiryTimestamp() - 10 > time()) {
      $this->access_token = $this->container->getAccessToken();
    }

    if ($this->access_token === null) {
      $this->refresh();
    }
  }

  protected function url(): string
  {
    if (trim(getenv('OAUTH_URL'))) {
      return getenv('OAUTH_URL');
    }
    return self::URL;
  }

  protected function revokeUrl(): string
  {
    if (trim(getenv('OAUTH_REVOKE_URL'))) {
      return getenv('OAUTH_REVOKE_URL');
    }
    return self::REVOKE_URL;
  }

  protected function http($params): array
  {
    try {
      $client = new GuzzleHttp\Client();
      $res = $client->request('POST', $this->url(), $this->clientOptions($this->url(), $params));
      $contents = $res->getBody()->getContents();
      $data = json_decode($contents, true);

      if (true === array_key_exists('refresh_token', $data)) {
        $refresh_token = $data['refresh_token'];
      } else {
        $refresh_token = null;
      }

      return [
        'access_token' => $data['access_token'],
        'refresh_token' => $refresh_token,
        'expiry' => ($data['created_at'] + $data['expires_in'])
      ];

    } catch (GuzzleHttp\Exception\ClientException $ex) {
      $http_code = $ex->getResponse()->getStatusCode();

      switch ($http_code) {
        case 400:
        case 401:
          $error = json_decode($ex->getResponse()->getBody()->getContents(), true);
          if ($error['error'] === 'invalid_grant') {
            # niepoprawne login, hasło
            throw new ExceptionUnauthorized($error['error_description'], $error['error']);
          } else {
            # inne sytuacje, niepoprawny key/secret
            throw new ExceptionAccessDenied($error['error_description'], $error['error']);
          }
        default:
          throw new Exception("Unable to fetch an access token, HTTP code was '{$http_code}'");
      }
    }
  }

  private function clientOptions($url, $params)
  {
    $headers = [];

    if (trim((string)$this->ip) !== '') {
      $headers['X-Real-IP'] = $this->ip;
      $headers['CF-Connecting-IP'] = $this->ip;
    }
    if (trim((string)$this->lang) !== '') {
      $headers['Accept-Language'] = $this->lang;
    }

    $timeout = intval(getenv('HTTP_TIMEOUT'));
    if ($timeout <= 0) {
      $timeout = 30;
    }

    $options =  [
      'connect_timeout' => ceil($timeout / 5),
      'timeout' => $timeout,
      'form_params' => $params,
      'headers' => $headers,
      'verify' => parse_url($url, PHP_URL_HOST) == self::HOST // for custom API URL skip SSL verification
    ];

    error_log(print_r($options, 1));

    return $options;
  }
}<commit_msg>Removing debug<commit_after><?php

namespace Serwisant\SerwisantApi;

use GuzzleHttp;

class AccessTokenOauth implements AccessToken
{
  protected $client_id;
  protected $client_secret;
  protected $scope;
  protected $container;

  private $ip;
  private $lang;

  protected $access_token;

  public function __construct(string $client_id, string $client_secret, string $scope = '', AccessTokenContainer $container = null)
  {
    $this->client_id = $client_id;
    $this->client_secret = $client_secret;
    $this->scope = $scope;
    $this->container = $container;
  }

  public function setIp($ip)
  {
    $this->ip = $ip;
    return $this;
  }

  public function setLang($lang)
  {
    $this->lang = $lang;
    return $this;
  }

  public function get()
  {
    if ($this->access_token === null) {
      $this->fetch();
    }
    return $this->access_token;
  }

  public function refresh()
  {
    $params = [
      'grant_type' => 'client_credentials',
      'client_id' => $this->client_id,
      'client_secret' => $this->client_secret,
      'scope' => $this->scope
    ];

    $token_data = $this->http($params);

    if ($token_data !== null) {
      $this->access_token = $token_data['access_token'];

      if ($this->container !== null) {
        $this->container->store($token_data['access_token'], $token_data['expiry'], $token_data['refresh_token']);
      }
    }
  }

  public function revoke($access_token = null): bool
  {
    $params = [
      'client_id' => $this->client_id,
      'client_secret' => $this->client_secret,
      'token' => $access_token
    ];

    try {
      $client = new GuzzleHttp\Client();
      $client->request('POST', $this->revokeUrl(), $this->clientOptions($this->revokeUrl(), $params));
      return true;
    } catch (GuzzleHttp\Exception\ClientException $ex) {
      return false;
    }
  }

  protected function fetch()
  {
    if ($this->container instanceof AccessTokenContainer && $this->container->getExpiryTimestamp() - 10 > time()) {
      $this->access_token = $this->container->getAccessToken();
    }

    if ($this->access_token === null) {
      $this->refresh();
    }
  }

  protected function url(): string
  {
    if (trim(getenv('OAUTH_URL'))) {
      return getenv('OAUTH_URL');
    }
    return self::URL;
  }

  protected function revokeUrl(): string
  {
    if (trim(getenv('OAUTH_REVOKE_URL'))) {
      return getenv('OAUTH_REVOKE_URL');
    }
    return self::REVOKE_URL;
  }

  protected function http($params): array
  {
    try {
      $client = new GuzzleHttp\Client();
      $res = $client->request('POST', $this->url(), $this->clientOptions($this->url(), $params));
      $contents = $res->getBody()->getContents();
      $data = json_decode($contents, true);

      if (true === array_key_exists('refresh_token', $data)) {
        $refresh_token = $data['refresh_token'];
      } else {
        $refresh_token = null;
      }

      return [
        'access_token' => $data['access_token'],
        'refresh_token' => $refresh_token,
        'expiry' => ($data['created_at'] + $data['expires_in'])
      ];

    } catch (GuzzleHttp\Exception\ClientException $ex) {
      $http_code = $ex->getResponse()->getStatusCode();

      switch ($http_code) {
        case 400:
        case 401:
          $error = json_decode($ex->getResponse()->getBody()->getContents(), true);
          if ($error['error'] === 'invalid_grant') {
            # niepoprawne login, hasło
            throw new ExceptionUnauthorized($error['error_description'], $error['error']);
          } else {
            # inne sytuacje, niepoprawny key/secret
            throw new ExceptionAccessDenied($error['error_description'], $error['error']);
          }
        default:
          throw new Exception("Unable to fetch an access token, HTTP code was '{$http_code}'");
      }
    }
  }

  private function clientOptions($url, $params)
  {
    $headers = [];

    if (trim((string)$this->ip) !== '') {
      $headers['X-Real-IP'] = $this->ip;
      $headers['CF-Connecting-IP'] = $this->ip;
    }
    if (trim((string)$this->lang) !== '') {
      $headers['Accept-Language'] = $this->lang;
    }

    $timeout = intval(getenv('HTTP_TIMEOUT'));
    if ($timeout <= 0) {
      $timeout = 30;
    }

    $options =  [
      'connect_timeout' => ceil($timeout / 5),
      'timeout' => $timeout,
      'form_params' => $params,
      'headers' => $headers,
      'verify' => parse_url($url, PHP_URL_HOST) == self::HOST // for custom API URL skip SSL verification
    ];
    
    return $options;
  }
}
{'fraction_non_alphanumeric': 0.16818032607506292, 'fraction_numerical': 0.002735529051318525, 'mean_word_length': 2.854913538591312, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 129, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5317752', 'n_tokens_mistral': 2970, 'n_tokens_neox': 2883, 'n_words': 561}