<?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; } } }