X-Git-Url: https://git.cweiske.de/shpub.git/blobdiff_plain/6f748120fbb71c4a7b3d9fd762f40933b8cb4e95..b2351eea120bb8f6293aae113e77a3e3edd46687:/src/shpub/Request.php diff --git a/src/shpub/Request.php b/src/shpub/Request.php index cbcc57e..3d7221d 100644 --- a/src/shpub/Request.php +++ b/src/shpub/Request.php @@ -5,121 +5,254 @@ class Request { public $req; public $cfg; + public $host; + protected $sendAsJson = false; + protected $directUpload = false; protected $uploadsInfo = []; protected $dedicatedBody = false; + protected $properties = []; + protected $type = null; + protected $action = null; + protected $url = null; + public function __construct($host, $cfg) { - $this->cfg = $cfg; - $this->req = new MyHttpRequest2($host->endpoints->micropub, 'POST'); - $this->req->setHeader('User-Agent: shpub'); + $this->cfg = $cfg; + $this->host = $host; + $this->req = $this->getHttpRequest( + $this->host->endpoints->micropub, $this->host->token + ); + } + + protected function getHttpRequest($url, $accessToken) + { + $req = new MyHttpRequest2($url, 'POST'); + $req->setHeader('User-Agent: shpub'); if (version_compare(PHP_VERSION, '5.6.0', '<')) { //correct ssl validation on php 5.5 is a pain, so disable - $this->req->setConfig('ssl_verify_host', false); - $this->req->setConfig('ssl_verify_peer', false); + $req->setConfig('ssl_verify_host', false); + $req->setConfig('ssl_verify_peer', false); } - $this->req->setHeader('Content-type', 'application/x-www-form-urlencoded'); - $this->req->setHeader('authorization', 'Bearer ' . $host->token); + $req->setHeader('Content-type', 'application/x-www-form-urlencoded'); + $req->setHeader('authorization', 'Bearer ' . $accessToken); + return $req; } public function send($body = null) { + if ($this->sendAsJson) { + //application/json + if ($body !== null) { + throw new \Exception('body already defined'); + } + $this->req->setHeader('Content-Type: application/json'); + $data = []; + if ($this->action !== null) { + $data['action'] = $this->action; + } + if ($this->url !== null) { + $data['url'] = $this->url; + } + if ($this->type !== null) { + $data['type'] = array('h-' . $this->type); + } + if (count($this->properties)) { + $data['properties'] = $this->properties; + } + $body = json_encode($data); + } else { + //form-encoded + if ($this->type !== null) { + $this->req->addPostParameter('h', $this->type); + } + if ($this->action !== null) { + $this->req->addPostParameter('action', $this->action); + } + if ($this->url !== null) { + $this->req->addPostParameter('url', $this->url); + } + foreach ($this->properties as $propkey => $propval) { + if (isset($propval['html'])) { + //workaround for content[html] + $propkey = $propkey . '[html]'; + $propval = $propval['html']; + } else if (count($propval) == 1) { + $propval = reset($propval); + } + $this->req->addPostParameter($propkey, $propval); + } + } + if ($body !== null) { $this->dedicatedBody = true; $this->req->setBody($body); } if ($this->cfg->debug) { - $this->printCurl(); + $cp = new CurlPrinter(); + $cp->show($this->req, $this->uploadsInfo, $this->dedicatedBody); } $res = $this->req->send(); if (intval($res->getStatus() / 100) != 2) { - Log::err( - 'Server returned an error status code ' . $res->getStatus() - ); - Log::err($res->getBody()); - exit(11); + $this->displayErrorResponse($res); } return $res; } - /** - * @param string $fieldName name of file-upload field - * @param string|resource|array $filename full name of local file, - * pointer to open file or an array of files - */ - public function addUpload($fieldName, $filename) + protected function displayErrorResponse($res) { - $this->uploadsInfo[$fieldName] = $filename; - return $this->req->addUpload($fieldName, $filename); + Log::err( + 'Server returned an error status code ' . $res->getStatus() + ); + + $shown = false; + if ($res->getHeader('content-type') == 'application/json') { + $errData = json_decode($res->getBody()); + if (!isset($errData->error)) { + Log::err('Error response does not contain "error" property'); + } else if (isset($errData->error_description)) { + Log::err($errData->error . ': ' . $errData->error_description); + $shown = true; + } else { + Log::err($errData->error); + $shown = true; + } + } + + if (!$shown) { + Log::err($res->getBody()); + } + exit(11); + } + + public function setAction($action) + { + $this->action = $action; + } + + public function setType($type) + { + $this->type = $type; + } + + public function setUrl($url) + { + $this->url = $url; } /** - * Add one or multiple POST parameters. - * Automatically adds them as array or as string. + * Add file upload * - * @param string $key Parameter name - * @param string|array $values One or multiple values + * @param string $fieldName name of file-upload field + * @param array $fileNames list of local file paths + * + * @return void */ - public function addPostParameter($key, $values) + public function addUpload($fieldName, $fileNames) { - if (count($values) == 1) { - $values = reset($values); + if ($this->directUpload && $this->sendAsJson) { + throw new \Exception( + 'Cannot do direct upload with JSON requests' + ); + } + + if ($this->host->endpoints->media === null + || $this->directUpload + ) { + if ($this->sendAsJson) { + throw new \Exception( + 'No media endpoint available, which is required for JSON' + ); + } + if (count($fileNames) == 1) { + $fileNames = reset($fileNames); + } + $this->uploadsInfo[$fieldName] = $fileNames; + return $this->req->addUpload($fieldName, $fileNames); + } + + $urls = []; + foreach ($fileNames as $fileName) { + $urls[] = $this->uploadToMediaEndpoint($fileName); + } + if (count($urls) == 1) { + $urls = reset($urls); } - $this->req->addPostParameter($key, $values); + $this->addProperty($fieldName, $urls); } - protected function printCurl() + /** + * Execute the file upload + * + * @param string $fileName File path + * + * @return string URL at media endpoint + */ + public function uploadToMediaEndpoint($fileName) { - $command = 'curl'; - if ($this->req->getMethod() != 'GET') { - $command .= ' -X ' . $this->req->getMethod(); + $httpReq = $this->getHttpRequest( + $this->host->endpoints->media, $this->host->token + ); + $httpReq->addUpload('file', $fileName); + + if ($this->cfg->debug) { + $cp = new CurlPrinter(); + $cp->show($httpReq, ['file' => $fileName]); } - foreach ($this->req->getHeaders() as $key => $val) { - $caseKey = implode('-', array_map('ucfirst', explode('-', $key))); - $command .= ' -H ' . escapeshellarg($caseKey . ': ' . $val); + $res = $httpReq->send(); + if (intval($res->getStatus() / 100) != 2) { + Log::err( + 'Media endpoint returned an error status code ' + . $res->getStatus() + ); + Log::err($res->getBody()); + exit(11); } - $postParams = $this->req->getPostParams(); - - if (count($this->uploadsInfo) == 0) { - foreach ($postParams as $k => $v) { - if (!is_array($v)) { - $command .= ' -d ' . escapeshellarg($k . '=' . $v); - } else { - foreach ($v as $ak => $av) { - $command .= ' -d ' . escapeshellarg( - $k . '[' . $ak . ']=' . $av - ); - } - } - } - } else { - foreach ($postParams as $k => $v) { - $command .= ' -F ' . escapeshellarg($k . '=' . $v); - } - foreach ($this->uploadsInfo as $fieldName => $filename) { - if (!is_array($filename)) { - $command .= ' -F ' . escapeshellarg( - $fieldName . '=@' . $filename - ); - } else { - foreach ($filename as $k => $realFilename) { - $command .= ' -F ' . escapeshellarg( - $fieldName . '[' . $k . ']=@' . $realFilename - ); - } - } - } + $location = $res->getHeader('location'); + if ($location === null) { + Log::err('Media endpoint did not return a URL'); + exit(11); } - if ($this->dedicatedBody) { - $command .= ' --data ' . escapeshellarg($this->req->getBody()); + $base = new \Net_URL2($this->host->endpoints->media); + return (string) $base->resolve($location); + } + + public function addContent($text, $isHtml) + { + if ($isHtml) { + $this->addProperty( + 'content', [['html' => $text]] + ); + } else { + $this->addProperty('content', $text); } - $command .= ' ' . escapeshellarg((string) $this->req->getUrl()); + } - Log::msg($command); + /** + * Adds a micropub property to the request. + * + * @param string $key Parameter name + * @param string|array $values One or multiple values + * + * @return void + */ + public function addProperty($key, $values) + { + $this->properties[$key] = (array) $values; + } + + public function setSendAsJson($json) + { + $this->sendAsJson = $json; + } + + public function setDirectUpload($directUpload) + { + $this->directUpload = $directUpload; } } \ No newline at end of file