Skip to content
Snippets Groups Projects
AscCoursesApi.php 9.88 KiB
Newer Older
<?php
namespace Drupal\asc_courses;

// use Consolidation\OutputFormatters\StructuredData\RowsOfFields;
// use Drush\Commands\DrushCommands;
use \Drupal\Core\Database\Database;
use \Drupal\Core\Config;

class AscCoursesApi {
  protected $debug = 0;
  protected $consumer_key;
  protected $consumer_secret;
  public $config;
  public $soip_constant_name;
  public $environment;
  public $base_url;
  public $access_token;
  public $access_token_data;
  public $resolve_host;


  /**
   * {@inheritdoc}
   */
  public function __construct($config = null, $environment = '') {
    // Get settings
    if (!empty($config)) {
      $this->config = $config;
    }
    else {
      $this->config = $config = \Drupal::service('config.factory')->get('asc_courses.settings');
    }
    
    if ($this->debug) echo "\nAPI connector class instantiated\n";

    // Get environment if not overridden
    if(empty($environment)) {
      if ($this->debug) echo "Environment argument was empty. Reading it from configuration.\n";
      $environment = $this->config->get('asc_courses.eip_environment');
    }
    if ($this->debug) echo "Environment: " . $environment . "\n";

    // HARD CODED VALUES
    if ($environment == 'prod') {
      $this->environment = $environment;
      $this->base_url = "https://apig.eip.osu.edu/";
      $this->consumer_key = $config->get('asc_courses.prod_consumer_key');
      $this->consumer_secret = $config->get('asc_courses.prod_consumer_secret');
      $this->soip_constant_name = "PANTHEON_SOIP_EIP_PROD";
    }
    else {
      $this->environment = $environment;
      $this->base_url = "https://apig-qa.eip.osu.edu/";
      $this->consumer_key = $config->get('asc_courses.qa_consumer_key');
      $this->consumer_secret = $config->get('asc_courses.qa_consumer_secret');
      $this->soip_constant_name = "PANTHEON_SOIP_EIP";  
    }

    if(isset($_ENV['PANTHEON_ENVIRONMENT']) && $_ENV['PANTHEON_ENVIRONMENT'] != "lando") {
      if ($this->debug) echo "Pantheon environment: " . $_ENV['PANTHEON_ENVIRONMENT'] . "\n";
      $host = parse_url($this->base_url, PHP_URL_HOST);
      if ($this->debug) echo "host: $host\n";
      $localhost = "127.0.0.1";
      $this->resolve_host = array(sprintf("%s:%d:%s", $host, constant($this->soip_constant_name), $localhost));
      if ($this->debug) echo "\n resolve_host : " . implode($this->resolve_host) . "\n";
      // error_log("resolve_host : " . implode($this->resolve_host));
    }

    if ($this->debug) echo "\n\n";
  }

  /**
   * Return an access token if possible
   */
  public function getAccessToken() {
    if($this->debug) echo "============ getAccessToken =============\n";
    $now = time();
    if($this->debug) echo "Current time: " . date("Y-m-d h:i:s", $now) . "\n";

    // First check object variables
    if(!empty($this->access_token_data) 
       && (($this->access_token_data->expiration - $now) > 30)) 
    {
      if($this->debug) echo "Object variables were set and not stale\n";
      $this->access_token = $this->access_token_data->access_token;        
    }
    else {
      // fetch configuration
      $env_access_token_setting = 'asc_courses.' . $this->environment . '_access_token';
      if($this->debug) echo "env_access_token_setting: $env_access_token_setting\n";
      $access_token_data = unserialize($this->config->get($env_access_token_setting));
      if($this->debug) echo "Config access token: " . print_r($access_token_data, true) . "\n";

      if(!empty($access_token_data)
         && (($access_token_data->expiration - $now) > 30)) 
      {
        if($this->debug) echo "Config token was available and not stale.\n";
        $this->access_token_data = $access_token_data;
        $this->access_token = $access_token_data->access_token;
      }
      else {
        if($this->debug) echo "Config token was unset or stale.\n";
        $access_token_data = $this->fetchAccessToken();

        if(!empty($access_token_data->access_token)) {
          $this->access_token_data = $access_token_data;
          $this->access_token = $access_token_data->access_token;
        }
      }
    }

    if (!empty($this->access_token_data)) {
      $expirey = $this->access_token_data->expiration;
      if($this->debug) {
        echo "Token expiration: " . date("Y-m-d h:i:s", $expirey) . "\n";
        echo "Expires in " . ($expirey - $now) . " seconds..\n";
        echo "\n\n";  
      }
      return $this->access_token;    
    }
    else {
      die("\ngetAccessToken() - failed to retrieve access token! X_X\n\n");
    }
  }

  /**
   * Fetch a new access token via the API and return it
   */
  protected function fetchAccessToken() {
    // get an access token
    $bearer_auth_plain = $this->consumer_key . ":" . $this->consumer_secret;
    if ($this->debug) echo "fetchAccessToken() - Tokens: " . $bearer_auth_plain . "\n";
    $bearer_auth = base64_encode($bearer_auth_plain);
    if ($this->debug) echo "fetchAccessToken() - Bearer auth: $bearer_auth\n";

    $access_token_url = $this->base_url . "token?grant_type=client_credentials";
    if ($this->debug) echo "fetchAccessToken() - Access token URL: $access_token_url\n";
    $access_token_headers = [
      "Accept: application/json",
      "Authorization: Basic $bearer_auth",
    ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $access_token_url);

    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    curl_setopt($ch, CURLOPT_POST, true);
    // curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $access_token_headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

    if(isset($this->resolve_host)) {
      if ($this->debug) echo "fetchAccessToken() - Resolve host set: " . print_r($this->resolve_host, true) . "\n";
      curl_setopt($ch, CURLOPT_RESOLVE, $this->resolve_host);
      curl_setopt($ch, CURLOPT_PORT, constant($this->soip_constant_name));  
    }

    if($this->debug > 1) {
      curl_setopt($ch, CURLOPT_VERBOSE, true);
    }

    $access_token_start = microtime(true);
    $access_token_result = curl_exec($ch);
    $access_token_error = curl_error($ch);
    curl_close($ch);
    $access_token_finish = microtime(true);
    $access_token_seconds = $access_token_finish - $access_token_start;
    if ($this->debug) echo "fetchAccessToken() - CURL error: " . print_r($access_token_error, true) . "\n";

    if(!empty($access_token_error) || empty($access_token_result)) {
      echo "\n$access_token_error\n";
      die("fetchAccessToken() - Failed to fetch access token from the API!!  X_X\n\n");
    }
    else {
      $now = time();
      $access_token_data = json_decode($access_token_result);
      $access_token_data->expiration = (time() + $access_token_data->expires_in);
      $access_token_data->fetched = $now;
  
      if ($this->debug) {
        echo "fetchAccessToken() - Access token result: \n";
        print_r($access_token_result);
        echo "\n";
        echo "fetchAccessToken() - Access token in $access_token_seconds seconds\n";  
        echo "fetchAccessToken() - Now: " . $now . " - " . date("Y-m-d h:i:s", $now) . "\n";
        print_r($access_token_data);
      }
  
      // Save access token data to config
      $env_access_token_setting = 'asc_courses.' . $this->environment . '_access_token';
      if($this->debug) echo "fetchAccessToken() - env_access_token_setting: $env_access_token_setting\n";
      $config = \Drupal::service('config.factory')->getEditable('asc_courses.settings');
      $config->set("asc_courses." . $this->environment . "_access_token", serialize($access_token_data));
      $config->save();
  
      return $access_token_data;
    }
  }

  /**
   * Fetch and store courses for a single D-Org
   */
  public function fetchSubjectCourses($dorg) {
    $access_token = $this->getAccessToken();
    $course_data_url = $this->base_url . "crseinfo/1.0.0/getCatalogInfo?campus=COL&acad_org=$dorg";

    if($this->debug) echo "course data url: $course_data_url\n";
    $course_data_headers = [
      "Accept: application/json",
      "Authorization: Bearer $access_token"
    ];



    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $course_data_url);

    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    // curl_setopt($ch, CURLOPT_POST, true);
    // curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $course_data_headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

    if(isset($this->resolve_host)) {
      if ($this->debug) echo "fetchAccessToken() - Resolve host set: " . $this->resolve_host . "\n";
      // error_log("fetchAccessToken() - Resolve host set: " . $this->resolve_host);
      curl_setopt($ch, CURLOPT_RESOLVE, $this->resolve_host);
      curl_setopt($ch, CURLOPT_PORT, constant($this->soip_constant_name));  
    }

    if($this->debug > 1) {
      curl_setopt($ch, CURLOPT_VERBOSE, true);
    }

    $curl_start = microtime(true);
    $course_data_result = curl_exec($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);
    $curl_finish = microtime(true);
    $curl_seconds = $curl_finish - $curl_start;
    if ($this->debug) echo "fetchSubjectCourses() - CURL error: " . print_r($curl_error, true) . "\n";

    if(!empty($curl_error) || empty($course_data_result)) {
      echo "\n$curl_error\n";
      die("fetchSubjectCourses() - Failed to fetch [$dorg] course information from the API!!  X_X\n\n");
    }
    else {
      if ($this->debug) echo "Course data length:" . strlen($course_data_result) . "\n";
      if ($this->debug) echo "Course data in $curl_seconds seconds\n\n";
  
  
      $connection = \Drupal::database();
      $row = [
        'date' => time(),
        'dept_org' => $dorg,
        'raw_json' => $course_data_result
      ];
      $connection->insert('asc_course_data')->fields($row)->execute();
  
      $course_data = json_decode($course_data_result);      
      return $course_data;
    }


  }

}