544962b8e061c133467e4bd3312cf247559eefda
[shpub.git] / src / shpub / Request.php
1 <?php
2 namespace shpub;
3
4 class Request
5 {
6     public $req;
7     public $cfg;
8
9     protected $sendAsJson = false;
10     protected $uploadsInfo = [];
11     protected $dedicatedBody = false;
12
13     protected $properties = [];
14     protected $type = null;
15     protected $action = null;
16     protected $url = null;
17
18     public function __construct($host, $cfg)
19     {
20         $this->cfg = $cfg;
21         $this->req = new MyHttpRequest2($host->endpoints->micropub, 'POST');
22         $this->req->setHeader('User-Agent: shpub');
23         if (version_compare(PHP_VERSION, '5.6.0', '<')) {
24             //correct ssl validation on php 5.5 is a pain, so disable
25             $this->req->setConfig('ssl_verify_host', false);
26             $this->req->setConfig('ssl_verify_peer', false);
27         }
28         $this->req->setHeader('Content-type', 'application/x-www-form-urlencoded');
29         $this->req->setHeader('authorization', 'Bearer ' . $host->token);
30     }
31
32     public function send($body = null)
33     {
34         if ($this->sendAsJson) {
35             //application/json
36             if ($body !== null) {
37                 throw new \Exception('body already defined');
38             }
39             $this->req->setHeader('Content-Type: application/json');
40             $data = [];
41             if ($this->action !== null) {
42                 $data['action'] = $this->action;
43             }
44             if ($this->url !== null) {
45                 $data['url'] = $this->url;
46             }
47             if ($this->type !== null) {
48                 $data['type'] = 'h-' . $this->type;
49             }
50             if (count($this->properties)) {
51                 $data['properties'] = $this->properties;
52             }
53             $body = json_encode($data);
54         } else {
55             //form-encoded
56             if ($this->type !== null) {
57                 $this->req->addPostParameter('h', $this->type);
58             }
59             if ($this->action !== null) {
60                 $this->req->addPostParameter('action', $this->action);
61             }
62             if ($this->url !== null) {
63                 $this->req->addPostParameter('url', $this->url);
64             }
65             foreach ($this->properties as $propkey => $propval) {
66                 if (isset($propval['html'])) {
67                     //workaround for content[html]
68                     $propkey = $propkey . '[html]';
69                     $propval = $propval['html'];
70                 } else if (count($propval) == 1) {
71                     $propval = reset($propval);
72                 }
73                 $this->req->addPostParameter($propkey, $propval);
74             }
75         }
76
77         if ($body !== null) {
78             $this->dedicatedBody = true;
79             $this->req->setBody($body);
80         }
81         if ($this->cfg->debug) {
82             $this->printCurl();
83         }
84         $res = $this->req->send();
85
86         if (intval($res->getStatus() / 100) != 2) {
87             Log::err(
88                 'Server returned an error status code ' . $res->getStatus()
89             );
90             Log::err($res->getBody());
91             exit(11);
92         }
93         return $res;
94     }
95
96     public function setAction($action)
97     {
98         $this->action = $action;
99     }
100
101     public function setType($type)
102     {
103         $this->type = $type;
104     }
105
106     public function setUrl($url)
107     {
108         $this->url = $url;
109     }
110
111     /**
112      * @param string                $fieldName name of file-upload field
113      * @param string|resource|array $filename  full name of local file,
114      *               pointer to open file or an array of files
115      */
116     public function addUpload($fieldName, $filename)
117     {
118         if ($this->sendAsJson) {
119             throw new \Exception('File uploads do not work with JSON');
120         }
121         $this->uploadsInfo[$fieldName] = $filename;
122         return $this->req->addUpload($fieldName, $filename);
123     }
124
125     public function addContent($text, $isHtml)
126     {
127         if ($isHtml) {
128             $this->addProperty(
129                 'content', ['html' => $text]
130             );
131         } else {
132             $this->addProperty('content', $text);
133         }
134
135     }
136
137     /**
138      * Adds a micropub property to the request.
139      *
140      * @param string       $key    Parameter name
141      * @param string|array $values One or multiple values
142      */
143     public function addProperty($key, $values)
144     {
145         $this->properties[$key] = (array) $values;
146     }
147
148     protected function printCurl()
149     {
150         $command = 'curl';
151         if ($this->req->getMethod() != 'GET') {
152             $command .= ' -X ' . $this->req->getMethod();
153         }
154         foreach ($this->req->getHeaders() as $key => $val) {
155             $caseKey = implode('-', array_map('ucfirst', explode('-', $key)));
156             $command .= ' -H ' . escapeshellarg($caseKey . ': ' . $val);
157         }
158
159         $postParams = $this->req->getPostParams();
160
161         if (count($this->uploadsInfo) == 0) {
162             foreach ($postParams as $k => $v) {
163                 if (!is_array($v)) {
164                     $command .= ' -d ' . escapeshellarg($k . '=' . $v);
165                 } else {
166                     foreach ($v as $ak => $av) {
167                         $command .= ' -d ' . escapeshellarg(
168                             $k . '[' . $ak . ']=' . $av
169                         );
170                     }
171                 }
172             }
173         } else {
174             foreach ($postParams as $k => $v) {
175                 $command .= ' -F ' . escapeshellarg($k . '=' . $v);
176             }
177             foreach ($this->uploadsInfo as $fieldName => $filename) {
178                 if (!is_array($filename)) {
179                     $command .= ' -F ' . escapeshellarg(
180                         $fieldName . '=@' . $filename
181                     );
182                 } else {
183                     foreach ($filename as $k => $realFilename) {
184                         $command .= ' -F ' . escapeshellarg(
185                             $fieldName . '[' . $k . ']=@' . $realFilename
186                         );
187                     }
188                 }
189             }
190         }
191
192         if ($this->dedicatedBody) {
193             $command .= ' --data ' . escapeshellarg($this->req->getBody());
194         }
195
196         $command .= ' ' . escapeshellarg((string) $this->req->getUrl());
197
198         Log::msg($command);
199     }
200
201     public function setSendAsJson($json)
202     {
203         $this->sendAsJson = $json;
204     }
205 }