/**
  * Alternative, more OO take on this object's curl method
  * basically a copy-paste-rewrite ;)
  * @param Action $todo
  * @param null $customMethod
  * @return mixed
  * @throws \RuntimeException
  */
 public function doAction(Action $todo, $customMethod = null)
 {
     $method = $customMethod;
     if ($customMethod === null) {
         $method = $todo->getMethod();
     }
     $url = $this->getUrl() . (string) $todo;
     $debug_str1 = array();
     $request = curl_init();
     $debug_str1[] = '$ch = curl_init();';
     if ($this->debug) {
         $this->dbg($url, 1, "pre", "Description: Request URL");
     }
     if ($todo->getVerb() === Action::ACTION_GET && $todo->getData()) {
         $url .= '&' . http_build_query($this->formatDateTimeInstances($todo->getData()));
     }
     curl_setopt($request, \CURLOPT_URL, $url);
     curl_setopt($request, \CURLOPT_HEADER, 0);
     curl_setopt($request, \CURLOPT_RETURNTRANSFER, true);
     $debug_str1[] = 'curl_setopt($ch, \\CURLOPT_URL,"' . $url . '");';
     $debug_str1[] = 'curl_setopt($ch, \\CURLOPT_HEADER,0);';
     $debug_str1[] = 'curl_setopt($ch, \\CURLOPT_RETURNTRANSFER,true);';
     $data = $todo->getData();
     if ($todo->getVerb() !== 'GET' && $data) {
         switch ($todo->getVerb()) {
             case 'PUT':
                 curl_setopt($request, \CURLOPT_CUSTOMREQUEST, 'PUT');
                 $debug_str1[] = 'curl_setopt($request, CURLOPT_CUSTOMREQUEST, "PUT")';
                 break;
             case 'POST':
                 curl_setopt($request, \CURLOPT_POST, 1);
                 $debug_str1[] = 'curl_setopt($ch, CURLOPT_POST, 1);';
                 break;
             default:
                 throw new \RuntimeException(sprintf('Request WITH data implies PUT or POST verb in action, %s given', $todo->getVerb()));
         }
         curl_setopt($request, \CURLOPT_HTTPHEADER, array('Expect:'));
         $debug_str1[] = 'curl_setopt($request, \\CURLOPT_HTTPHEADER, array("Expect:"));';
         if ($this->debug) {
             $this->dbg($todo->getData(true), 1, "pre", "Description: POST data");
         }
         curl_setopt($request, \CURLOPT_POSTFIELDS, http_build_query($this->formatDateTimeInstances($data)));
         $debug_str1[] = 'curl_setopt($request, CURLOPT_POSTFIELDS, $data);';
     }
     curl_setopt($request, \CURLOPT_SSL_VERIFYPEER, false);
     curl_setopt($request, \CURLOPT_SSL_VERIFYHOST, 0);
     curl_setopt($request, \CURLOPT_FOLLOWLOCATION, true);
     $debug_str1[] = 'curl_setopt($ch, \\CURLOPT_SSL_VERIFYPEER, false);';
     $debug_str1[] = 'curl_setopt($ch, \\CURLOPT_SSL_VERIFYHOST, 0);';
     $debug_str1[] = 'curl_setopt($ch, \\CURLOPT_FOLLOWLOCATION, true);';
     $response = curl_exec($request);
     $debug_str1[] = 'curl_exec($ch);';
     if ($this->debug) {
         $this->dbg($response, 1, "pre", "Description: Raw response");
     }
     $httpCode = curl_getinfo($request, \CURLINFO_HTTP_CODE);
     $debug_str1[] = '$httpCode = curl_getinfo($ch, \\CURLINFO_HTTP_CODE);';
     if ($this->debug) {
         $this->dbg($httpCode, 1, "pre", "Description: Response HTTP code");
     }
     curl_close($request);
     $debug_str1[] = 'curl_close($ch);';
     if ($this->debug) {
         $this->dbg($response, 1, "pre", "Description: Response object (" . $this->output . ")");
     }
     // add methods that only return a string
     if (in_array($method, self::$StringOnly)) {
         return $response;
     }
     switch ($this->output) {
         case 'json':
             $object = json_decode($response);
             $jError = json_last_error();
             if ($jError !== \JSON_ERROR_NONE) {
                 throw new \RuntimeException(sprintf('An unexpected problem occurred with the API request. Some causes include: invalid JSON or XML returned.
                         URL request was sent to: %s
                         DATA: %s
                         Here is the actual response from the server: ---- %s%s%s
                         JSON errors: %d - %s', $url, $data ? $todo->getData(true) : 'No data', PHP_EOL . '<br>', $response, PHP_EOL . '<br>', $jError, $this->getJSONError($jError)));
             }
             break;
         case 'serialize':
             $object = unserialize($response);
             if (!$object) {
                 throw new \RuntimeException(sprintf('An unexpected problem occurred with the API request. Some causes include: invalid JSON or XML returned.
                         URL request was sent to: %s
                         DATA: %s
                         Here is the actual response from the server: ---- %s%s%s', $url, $data ? $todo->getData(true) : 'No data', PHP_EOL . '<br>', $response, PHP_EOL));
             }
             //ensure instanceof \stdClass through json_decode
             if (!$object instanceof \stdClass) {
                 $object = json_decode(json_encode((array) $object));
             }
             break;
         case 'xml':
             if (function_exists('simplexml_load_string')) {
                 //simpleXML extension is installed
                 $object = $this->parseSimpleXML(simplexml_load_string($response));
                 break;
             }
             $dom = new \DOMDocument();
             $dom->loadXML($response);
             $object = $this->parseXMLDom($dom);
             break;
     }
     if ($this->debug) {
         $debug_str1 = implode(PHP_EOL, $debug_str1);
         //if needs must, do not echo, we're setting headers below!!
         $this->dbBuffer[] = "<textarea style='height: 300px; width: 600px;'>" . $debug_str1 . "</textarea>";
         $this->getDebugBuffer($httpCode);
     }
     /** @var \stdClass $object */
     $object->http_code = $httpCode;
     if (isset($object->result_code)) {
         $object->success = $object->result_code;
         if (!(int) $object->result_code) {
             $object->error = $object->result_message;
         }
     } elseif (isset($object->succeeded)) {
         // some calls return "succeeded" only
         $object->success = $object->succeeded;
         if (!(int) $object->succeeded) {
             $object->error = $object->message;
         }
     }
     return $object;
 }