/**
  * Run the request
  * 
  * @param \Raml\SecurityScheme $securityscheme_obj The security scheme to process the call data for
  * @param \V1\APICall $apicall_obj					The APICall object
  * 
  * @return mixed The object we just completed or an array describing the next step in the security process
  */
 public function run(\Raml\SecurityScheme $securityscheme_obj, \V1\APICall $apicall_obj)
 {
     $settings = $securityscheme_obj->getSettings();
     $credentials = $apicall_obj->get_credentials();
     // Save the credentials
     \V1\Keyring::set_credentials($credentials);
     /**
      * By default we'll return the response from the authentication request so that it's meaningful.
      * However, in doing so, we'll need to block the main request, so developers may set this flag
      * to ignore the authentication, signifying that they've already got the information they needed
      * from it.
      * 
      * NOTE: This security method is meant as a basic way to catch security methods we otherwise
      * haven't implemented in our system. Take it for what it's worth. 
      * 
      * @TODO When using this security method, skip processing the APICall object for a speedup.
      */
     if (!empty($credentials['CUSTOM_IGNORE_AUTH'])) {
         return true;
     }
     // Remove unused credentials so as not to replace bad variables in the template.
     foreach ($credentials as $variable => $entry) {
         if (strpos($variable, 'CUSTOM_') !== 0) {
             unset($credentials[$variable]);
         }
     }
     // We need the method or we'll fail the call.
     if (empty($settings['method'])) {
         $this->error = true;
         return $this;
     }
     // Normalize the data into arrays.
     $described_by = $securityscheme_obj->getDescribedBy();
     $headers = $this->get_param_array($described_by->getHeaders());
     $query_params = $this->get_param_array($described_by->getQueryParameters());
     $bodies = $described_by->getBodies();
     $method = \Str::upper($settings['method']);
     $url = $settings['url'];
     // Grab the body if we have one, and the method supports one.
     $body = null;
     $body_type = null;
     if (count($bodies) > 0 && !in_array($method, array('GET', 'HEAD'))) {
         reset($bodies);
         $body_type = key($bodies);
         $body = $bodies[$body_type]->getExamples()[0];
     }
     /**
      * NOTE: These replacements may ruin the formatting or allow for people to inject data into them.
      * API Providers should be aware of that possibility.
      * 
      * @TODO In the future, we can consider implementing checking to verify that people aren't sending
      * crap data through the system.
      */
     $headers = $this->remove_cr_and_lf($this->replace_variables($headers, $credentials));
     $query_params = $this->remove_cr_and_lf($this->replace_variables($query_params, $credentials));
     $body = $this->replace_variables($body, $credentials);
     if (!empty($query_params)) {
         $query_string = http_build_query($query_params, null, '&');
         if (strpos($url, '?') === false) {
             $url .= '?' . $query_string;
         } else {
             $url .= '&' . $query_string;
         }
     }
     /**
      * RUNCLE RICK'S RAD RUN CALLS (The second coming!)
      */
     $curl = \Remote::forge($url, 'curl', $method);
     // Set the headers
     $headers = \V1\RunCall::get_headers($headers);
     foreach ($headers as $header_name => $header_value) {
         $curl->set_header($header_name, $header_value);
     }
     // Return the headers
     $curl->set_option(CURLOPT_HEADER, true);
     // If we need a body, set that.
     if (!empty($body) && !in_array($method, array('GET', 'HEAD'))) {
         $curl->set_header('Content-Type', $body_type);
         $curl->set_params($body);
     }
     // Run the request
     try {
         $response = $curl->execute()->response();
     } catch (\RequestStatusException $e) {
         $response = \Remote::get_response($curl);
     } catch (\RequestException $e) {
         $this->error = true;
         return $this;
     }
     // Set the usage stats, and format the response
     return \V1\Socket::prepare_response(array('status' => $response->status, 'headers' => $response->headers, 'body' => $response->body));
 }
 /**
  * Call the remote API server
  * 
  * @param \V1\APICall $apicall_obj The APICall object we're using to make calls
  * @return array The array of data ready for display (Response array or error array)
  */
 public function make_the_call(\V1\APICall $apicall_obj)
 {
     /**
      * RUNCLE RICK'S RAD RUN CALL :)
      */
     $api = \V1\Model\APIs::get_api();
     $account = \V1\Model\Account::get_account();
     /*
      * When we make a call from the local server, we'll get the localhost IP. If that's the case,
      * we'll set our public IP. DO NOT use X-Forwarded-For in the request headers to us. It's unreliable.
      * We'll still set our X-Forwarded-For in case the API provider wishes to use it.
      */
     $forwarded_for = \Input::real_ip('0.0.0.0', true);
     if ($internal_call = \Utility::is_internal_call()) {
         $forwarded_for = \Config::get('engine.call_test_ip');
     }
     /*
      * Add our own headers to allow for authenticating our server and customers. We overwrite any
      * of these headers that were specified by the API Provider through RAML, or by the developer
      * through thier configuration.
      */
     $headers = static::get_headers($apicall_obj->get_headers());
     $call = array('url' => $apicall_obj->get_url(), 'method' => $apicall_obj->get_method(), 'headers' => $headers, 'body' => $apicall_obj->get_method_params(), 'body-type' => $apicall_obj->get_body_type());
     if (\Fuel::$env !== 'production' && \Config::get('engine.dev_disable_live_calls', false) === true) {
         /**
          * In dev mode we can disable calls to the remote server. Feel free to change the
          * dummy response to whatever you'd like to.
          */
         $response = array('status' => 200, 'headers' => array('X-Dev-Mode' => 'Dummy header'), 'body' => array('dummy_key' => 'dummy_val'));
         return \Utility::format_response(200, $response);
     } else {
         /*
          * We'll see if anyone got a cached entry into our system while we were configuring stuff.
          * That way we'll save time.
          */
         if (\V1\APIRequest::is_static() && is_array($cached_data = \V1\Call\StaticCall::get_call_cache())) {
             // Return the response-formatted data from the cached entry.
             return $cached_data;
         }
         $queued = \V1\Socket::forge()->queue_call(\V1\APIRequest::get('api'), $call, $apicall_obj);
     }
     // Non-Data Calls grab the request right away.
     if (\Session::get('data_call', false) === false) {
         if ($queued === false) {
             // Server unavailable
             return \Utility::format_error(503, \Err::SERVER_ERROR, \Lang::get('v1::errors.remote_unavailable'));
         }
         // Pull the results.
         $result = \V1\Socket::forge()->get_results();
         if (is_array($result)) {
             // We only have one call.
             return $result[\V1\APIRequest::get('api')][0];
         } else {
             // If the request failed with false, it means that all streams timed out.
             return \Utility::format_error(500);
         }
     }
     $dc_response = array('status' => 200, 'headers' => array(), 'body' => \V1\Constant::QUEUED_CALL);
     // In Data Call mode we just signify that we've queued the call.
     return \Utility::format_response(200, $dc_response);
 }
 /**
  * Run the Data Call
  * 
  * @return mixed The array of responses and template data, or the HTML template if the format is "html"
  */
 public static function run()
 {
     if (\Session::get('public', true) === true) {
         return \Utility::format_error(400, \V1\Err::NO_JS_CALLS, \Lang::get('v1::errors.no_js_calls'));
     }
     // Make sure the Data Call exists, and is part of their account.
     if (empty($data_call_data = \V1\Model\DataCalls::get_data_call())) {
         return \Utility::format_error(404, \V1\Err::BAD_DATA_CALL, \Lang::get('v1::errors.bad_data_call'));
     }
     $account_data = \V1\Model\Account::get_account();
     // Make sure they are allowed to access it.
     if ($account_data['access_level'] < $data_call_data['min_access_level']) {
         return \Utility::format_error(402, \V1\Err::UPGRADE_REQUIRED, \Lang::get('v1::errors.upgrade_required'));
     }
     // Make sure that the Data Call is enabled or callable.
     if ($data_call_data['active_level'] === 0 && ($account_data['can_run_inactive'] === 0 && $account_data['id'] !== $data_call_data['account_id'])) {
         return \Utility::format_error(403, \V1\Err::DISABLED_DATA_CALL, \Lang::get('v1::errors.disabled_data_call'));
     }
     // Custom Data Calls allow the user to send us their workload (call script) and we'll process it for them.
     if (\V1\APIRequest::get('data-call', false) === 'custom') {
         $call_script = \V1\APIRequest::get('call-script', false);
     } else {
         $call_script = json_decode($data_call_data['call_script'], true);
     }
     // Make sure we have a call script.
     if (empty($call_script) || !is_array($call_script)) {
         return \Utility::format_error(503, \V1\Err::DATA_CALL_MISCONFIG, \Lang::get('v1::errors.data_call_misconfig'));
     }
     // Free accounts may not change their Data Calls, as they may only use public data calls.
     if ($account_data['access_level'] > 1 && is_array($call_options = \V1\APIRequest::data_call('call-options', false))) {
         $call_script = array_replace_recursive($call_script, $call_options);
     }
     /*
      * Set the Data Call flag to bypass things that no longer pertain to further calls, such as
      * authentication to Bit API Hub.
      */
     \Session::set('data_call', true);
     $response = array();
     $template_data = null;
     foreach ($call_script as $key => $call) {
         // If we have template data for widgets, gadgets, graphs, and charts, oh my, then we'll use it later.
         if ($key === 'template') {
             $template_data = $call;
             continue;
         }
         // We need a name. Even custom calls use the "custom" API.
         if (empty($call['api'])) {
             continue;
         }
         // Set the post data as defined in our script.
         \Session::set('posted_data', $call);
         // Make the call.
         $api_call = \Request::forge('v1/index', false)->execute()->response->body;
         // Bad decode
         if (empty($api_call)) {
             $response[$call['api']][] = \Utility::format_error(500);
         }
         // The response cometh forth, not stuck in zein queue.
         if (!empty($api_call[0]['response']['body']) && $api_call[0]['response']['body'] === \V1\Constant::QUEUED_CALL) {
             // Keep the order of calls right proper. :P
             $response[$call['api']][] = \V1\Constant::QUEUED_CALL;
         } else {
             // We have our response, so we set that now.
             $response[$call['api']][] = $api_call[0];
         }
     }
     // If the customer doesn't need any response data, then we don't make them wait while we retrieve the results.
     if (\V1\APIRequest::data_call('no-response', false) === true) {
         $response = array('status' => 200, 'headers' => array(), 'body' => \Lang::get('v1::response.done'));
         return \Utility::format_response(200, $response);
     }
     // Check for responses.
     $call_queue = \V1\Socket::forge()->get_results();
     // If we have queued responses, and possibly place holders, then we'll loop.
     if (!empty($call_queue) && !empty($response)) {
         // Let's loop. :)
         foreach ($call_queue as $api_name => $call_number_data) {
             /*
              * Somehow we don't need the response. Odd... I don't know why they bother giving me this stuff
              * if they don't want me to use it.
              */
             if (empty($response[$api_name])) {
                 continue;
             }
             // Find the next queued placeholder.
             $queued_placeholder = array_search(\V1\Constant::QUEUED_CALL, $response[$api_name]);
             // If we have a placeholder, then put it's value in place.
             if ($queued_placeholder !== false) {
                 $response[$api_name][$queued_placeholder] = $call_number_data[(int) key($call_number_data)];
             }
         }
     }
     // If we have template data to display, then format that now.
     if (!empty($template_data)) {
         // We only want the template we just compiled, so return that.
         if (\Session::get('response_format') === 'html') {
             return static::process_template($template_data, $response, true);
         }
         // Set the template to the array of template data.
         $response['template'] = static::process_template($template_data, $response);
         return \Utility::format_response(200, $response);
     } else {
         // No template data, so just return the responses.
         return \Utility::format_response(200, $response);
     }
 }